/**
* Licensed to the zk1931 under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the
* License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.zk1931.jzab;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashSet;
import java.util.Set;
/**
* Tests for FastLeaderElection.
*/
public class FastLeaderElectionTest extends TestBase {
private static final Logger LOG =
LoggerFactory.getLogger(FastLeaderElectionTest.class);
@Test(timeout=5000)
public void testSelectLeaderWithHigherId() throws Exception {
// Starts 2 servers from a 3-server cluster, they have the same
// ackEpoch and lastZxid, we will pick the one with larger server id,
// which is server2.
QuorumTestCallback cb1 = new QuorumTestCallback();
QuorumTestCallback cb2 = new QuorumTestCallback();
TestStateMachine st = new TestStateMachine();
String server1 = getUniqueHostPort();
String server2 = getUniqueHostPort();
String server3 = getUniqueHostPort();
Set<String> peers = new HashSet<>();
peers.add(server1);
peers.add(server2);
peers.add(server3);
PersistentState state1 = makeInitialState(server1, 1);
state1.setAckEpoch(0);
PersistentState state2 = makeInitialState(server2, 1);
state2.setAckEpoch(0);
ZabConfig config1 = new ZabConfig();
ZabConfig config2 = new ZabConfig();
Zab zab1 = new Zab(st, config1, server1, peers, state1, cb1, null);
Zab zab2 = new Zab(st, config2, server2, peers, state2, cb2, null);
cb1.waitDiscovering();
cb2.waitDiscovering();
// Verify we have selected the server with higher server id.
Assert.assertEquals(server2, cb1.electedLeader);
Assert.assertEquals(server2, cb2.electedLeader);
zab1.shutdown();
zab2.shutdown();
}
@Test(timeout=5000)
public void testSelectLeaderWithHigherAckEpoch() throws Exception {
// Starts 2 servers from a 3-server cluster, server1 has the same zxid
// as server2 but with a higher ackEpoch, we will pick the server1 as the
// leader.
QuorumTestCallback cb1 = new QuorumTestCallback();
QuorumTestCallback cb2 = new QuorumTestCallback();
TestStateMachine st = new TestStateMachine();
String server1 = getUniqueHostPort();
String server2 = getUniqueHostPort();
String server3 = getUniqueHostPort();
Set<String> peers = new HashSet<>();
peers.add(server1);
peers.add(server2);
peers.add(server3);
PersistentState state1 = makeInitialState(server1, 1);
state1.setProposedEpoch(1);
state1.setAckEpoch(1);
PersistentState state2 = makeInitialState(server2, 1);
state2.setAckEpoch(0);
ZabConfig config1 = new ZabConfig();
ZabConfig config2 = new ZabConfig();
Zab zab1 = new Zab(st, config1, server1, peers, state1, cb1, null);
Zab zab2 = new Zab(st, config2, server2, peers, state2, cb2, null);
cb1.waitDiscovering();
cb2.waitDiscovering();
// Verify we have selected the server with higher server id.
Assert.assertEquals(server1, cb1.electedLeader);
Assert.assertEquals(server1, cb2.electedLeader);
zab1.shutdown();
zab2.shutdown();
}
@Test(timeout=5000)
public void testSelectLeaderWithHigherZxid() throws Exception {
// Starts 2 servers from a 3-server cluster, server1 has the same ackEpoch
// as server2 but with a higher lastZxid, we will pick the server1 as the
// leader.
QuorumTestCallback cb1 = new QuorumTestCallback();
QuorumTestCallback cb2 = new QuorumTestCallback();
TestStateMachine st = new TestStateMachine();
String server1 = getUniqueHostPort();
String server2 = getUniqueHostPort();
String server3 = getUniqueHostPort();
Set<String> peers = new HashSet<>();
peers.add(server1);
peers.add(server2);
peers.add(server3);
PersistentState state1 = makeInitialState(server1, 1);
PersistentState state2 = makeInitialState(server2, 0);
ZabConfig config1 = new ZabConfig();
ZabConfig config2 = new ZabConfig();
Zab zab1 = new Zab(st, config1, server1, peers, state1, cb1, null);
Zab zab2 = new Zab(st, config2, server2, peers, state2, cb2, null);
cb1.waitDiscovering();
cb2.waitDiscovering();
// Verify we have selected the server with higher server id.
Assert.assertEquals(server1, cb1.electedLeader);
Assert.assertEquals(server1, cb2.electedLeader);
zab1.shutdown();
zab2.shutdown();
}
@Test(timeout=5000)
public void testSelectLeaderFromThreeServers() throws Exception {
// Starts 3 servers from a 3-server cluster:
// server1 : ackEpoch : 2, lastZxid (0, 0)
// server2 : ackEpoch : 1, lastZxid (0, 0)
// server3 : ackEpoch : 0, lastZxid (0, 0)
// The best case we'll select server1 as the leader, the worst case
// (If server2 and server3 form a quorum first) we'll select server2 as
// the leader.
QuorumTestCallback cb1 = new QuorumTestCallback();
QuorumTestCallback cb2 = new QuorumTestCallback();
QuorumTestCallback cb3 = new QuorumTestCallback();
TestStateMachine st = new TestStateMachine();
String server1 = getUniqueHostPort();
String server2 = getUniqueHostPort();
String server3 = getUniqueHostPort();
Set<String> peers = new HashSet<>();
peers.add(server1);
peers.add(server2);
peers.add(server3);
PersistentState state1 = makeInitialState(server1, 0);
state1.setAckEpoch(2);
state1.setProposedEpoch(2);
PersistentState state2 = makeInitialState(server2, 0);
state2.setAckEpoch(1);
state2.setProposedEpoch(1);
PersistentState state3 = makeInitialState(server3, 0);
state2.setAckEpoch(0);
state2.setProposedEpoch(0);
ZabConfig config1 = new ZabConfig();
ZabConfig config2 = new ZabConfig();
ZabConfig config3 = new ZabConfig();
Zab zab1 = new Zab(st, config1, server1, peers, state1, cb1, null);
Zab zab2 = new Zab(st, config2, server2, peers, state2, cb2, null);
Zab zab3 = new Zab(st, config3, server3, peers, state3, cb3, null);
cb1.waitBroadcasting();
cb2.waitBroadcasting();
cb3.waitBroadcasting();
// Verify they have selected the same leader.
Assert.assertEquals(cb2.electedLeader , cb1.electedLeader);
Assert.assertEquals(cb2.electedLeader , cb3.electedLeader);
// The leader should be either server1 or server2.
Assert.assertTrue(server1.equals(cb1.electedLeader) ||
server3.equals(cb1.electedLeader));
zab1.shutdown();
zab2.shutdown();
zab3.shutdown();
}
}