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