@Test
public void testLeaderOutOfView() throws Exception {

    ClientBase.setupTestEnv();
    int numServers = 3;
    // used for assertions later
    boolean foundLeading = false;
    boolean foundFollowing = false;
    // capture QuorumPeer logging
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    WriterAppender appender = getConsoleAppender(os, Level.DEBUG);
    Logger qlogger = Logger.getLogger("org.apache.zookeeper.server.quorum");
    qlogger.addAppender(appender);
    try {
        Servers svrs = new Servers();
        svrs.clientPorts = new int[numServers];
        for (int i = 0; i < numServers; i++) {
            svrs.clientPorts[i] = PortAssignment.unique();
        }
        String quorumCfgIncomplete = getUniquePortCfgForId(1) + "\n" + getUniquePortCfgForId(2);
        String quorumCfgComplete = quorumCfgIncomplete + "\n" + getUniquePortCfgForId(3);
        svrs.mt = new MainThread[3];
        // Node 1 is started without the leader (3) in its config view
        svrs.mt[0] = new MainThread(1, svrs.clientPorts[0], quorumCfgIncomplete);
        for (int i = 1; i < numServers; i++) {
            svrs.mt[i] = new MainThread(i + 1, svrs.clientPorts[i], quorumCfgComplete);
        }
        // Node 1 must be started first, before quorum is formed, to trigger the attempted invalid connection to 3
        svrs.mt[0].start();
        QuorumPeer quorumPeer1 = waitForQuorumPeer(svrs.mt[0], CONNECTION_TIMEOUT);
        Assert.assertTrue(quorumPeer1.getPeerState() == QuorumPeer.ServerState.LOOKING);
        // Node 3 started second to avoid 1 and 2 forming a quorum before 3 starts up
        int highestServerIndex = numServers - 1;
        svrs.mt[highestServerIndex].start();
        QuorumPeer quorumPeer3 = waitForQuorumPeer(svrs.mt[highestServerIndex], CONNECTION_TIMEOUT);
        Assert.assertTrue(quorumPeer3.getPeerState() == QuorumPeer.ServerState.LOOKING);
        // Node 2 started last, kicks off leader election
        for (int i = 1; i < highestServerIndex; i++) {
            svrs.mt[i].start();
        }
        // Nodes 2 and 3 now form quorum and fully start. 1 attempts to vote for 3, fails, returns to LOOKING state
        for (int i = 1; i < numServers; i++) {
            Assert.assertTrue("waiting for server to start",
                    ClientBase.waitForServerUp("127.0.0.1:" + svrs.clientPorts[i], CONNECTION_TIMEOUT));
        }
        Assert.assertTrue(svrs.mt[0].getQuorumPeer().getPeerState() == QuorumPeer.ServerState.LOOKING);
        Assert.assertTrue(svrs.mt[highestServerIndex].getQuorumPeer().getPeerState() == QuorumPeer.ServerState.LEADING);
        for (int i = 1; i < highestServerIndex; i++) {
            Assert.assertTrue(svrs.mt[i].getQuorumPeer().getPeerState() == QuorumPeer.ServerState.FOLLOWING);
        }
        // Look through the logs for output that indicates Node 1 is LEADING or FOLLOWING
        LineNumberReader r = new LineNumberReader(new StringReader(os.toString()));
        Pattern leading = Pattern.compile(".*myid=1.*QuorumPeer.*LEADING.*");
        Pattern following = Pattern.compile(".*myid=1.*QuorumPeer.*FOLLOWING.*");
        String line;
        while ((line = r.readLine()) != null && !foundLeading && !foundFollowing) {
            foundLeading = leading.matcher(line).matches();
            foundFollowing = following.matcher(line).matches();
        }
    } finally {
        qlogger.removeAppender(appender);
    }
    Assert.assertFalse("Corrupt peer should never become leader", foundLeading);
    Assert.assertFalse("Corrupt peer should not attempt connection to out of view leader", foundFollowing);
}