1 /*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. 5 * 6 */ 7 8 package com.sleepycat.je.rep.elections; 9 10 import static org.junit.Assert.assertEquals; 11 import static org.junit.Assert.assertTrue; 12 13 import java.util.Arrays; 14 import java.util.HashSet; 15 16 import org.junit.After; 17 import org.junit.Before; 18 import org.junit.Test; 19 20 import com.sleepycat.je.rep.elections.Proposer.Proposal; 21 import com.sleepycat.je.rep.elections.Protocol.Accept; 22 import com.sleepycat.je.rep.elections.Protocol.Propose; 23 import com.sleepycat.je.rep.elections.Protocol.StringValue; 24 import com.sleepycat.je.rep.elections.Protocol.Value; 25 import com.sleepycat.je.rep.impl.TextProtocol.ResponseMessage; 26 import com.sleepycat.je.rep.impl.node.NameIdPair; 27 import com.sleepycat.je.rep.impl.node.RepNode; 28 import com.sleepycat.je.rep.net.DataChannelFactory; 29 import com.sleepycat.je.rep.utilint.RepTestUtils; 30 import com.sleepycat.je.rep.utilint.net.DataChannelFactoryBuilder; 31 import com.sleepycat.util.test.TestBase; 32 33 /** 34 * Tests the Acceptor Protocol for the correct responses to Propose and Accept 35 * messages, based on the Paxos protocol. 36 */ 37 public class AcceptorTest extends TestBase { 38 39 Protocol protocol; 40 Acceptor acceptor; 41 DataChannelFactory channelFactory; 42 43 TimebasedProposalGenerator proposalGenerator = 44 new TimebasedProposalGenerator(); 45 46 @Before setUp()47 public void setUp() { 48 channelFactory = 49 DataChannelFactoryBuilder.construct( 50 RepTestUtils.readRepNetConfig()); 51 52 Acceptor.SuggestionGenerator suggestionGenerator = 53 new Acceptor.SuggestionGenerator() { 54 55 @SuppressWarnings("unused") 56 public Value get(Proposal proposal) { 57 return new StringValue("VALUE"); 58 } 59 60 @SuppressWarnings("unused") 61 public long getRanking(Proposal proposal) { 62 return 100; 63 } 64 }; 65 protocol = new Protocol 66 (TimebasedProposalGenerator.getParser(), 67 MasterValue.getParser(), 68 "TestGroup", 69 new NameIdPair("n1", 1), 70 null, 71 channelFactory); 72 protocol.updateNodeIds(new HashSet<Integer> 73 (Arrays.asList(Integer.valueOf(1)))); 74 acceptor = new Acceptor 75 (protocol, 76 new RepNode(new NameIdPair("n0", 0)) { 77 @Override 78 public int getElectionPriority() { 79 return 1; 80 } 81 }, 82 suggestionGenerator); 83 } 84 85 @After tearDown()86 public void tearDown() { 87 acceptor = null; 88 } 89 checkPropose(Proposal pn, Protocol.MessageOp checkOp)90 void checkPropose(Proposal pn, Protocol.MessageOp checkOp) { 91 Propose prop = protocol.new Propose(pn); 92 ResponseMessage prom1 = acceptor.process(prop); 93 94 assertEquals(checkOp, prom1.getOp()); 95 } 96 checkAccept(Proposal pn, Value v, Protocol.MessageOp checkOp)97 void checkAccept(Proposal pn, Value v, Protocol.MessageOp checkOp) { 98 Accept a = protocol.new Accept(pn, v); 99 ResponseMessage ad = acceptor.process(a); 100 assertEquals(checkOp, ad.getOp()); 101 } 102 103 @Test testAcceptor()104 public void testAcceptor() { 105 Proposal pn0 = proposalGenerator.nextProposal(); 106 Proposal pn1 = proposalGenerator.nextProposal(); 107 108 /* Proposal numbers should be in ascending order. */ 109 assertTrue(pn1.compareTo(pn0)> 0); 110 111 checkPropose(pn1, protocol.PROMISE); 112 113 /* Lower numbered proposal should be rejected. */ 114 checkPropose(pn0, protocol.REJECT); 115 116 Value v = new StringValue("VALUE"); 117 checkAccept(pn1, v, protocol.ACCEPTED); 118 119 /* .. and continue to be rejected after the acceptance. */ 120 checkPropose(pn0, protocol.REJECT); 121 122 /* .. higher proposals should still be accepted. */ 123 Proposal pn2 = proposalGenerator.nextProposal(); 124 assertTrue(pn2.compareTo(pn1)> 0); 125 checkPropose(pn2, protocol.PROMISE); 126 checkAccept(pn2, v, protocol.ACCEPTED); 127 128 /* .. and ones lower than the promised proposal are rejected. */ 129 checkAccept(pn0, v, protocol.REJECT); 130 checkAccept(pn1, v, protocol.REJECT); 131 } 132 } 133