/** * Licensed to the Apache Software Foundation (ASF) 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 org.apache.zookeeper.server.quorum; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.File; import java.io.IOException; import java.net.Socket; import java.util.ArrayList; import org.apache.jute.BinaryInputArchive; import org.apache.jute.BinaryOutputArchive; import org.apache.jute.Index; import org.apache.jute.InputArchive; import org.apache.jute.Record; import org.apache.zookeeper.ZKTestCase; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.ACL; import org.apache.zookeeper.server.ZKDatabase; import org.apache.zookeeper.server.ZooKeeperServer; import org.apache.zookeeper.server.persistence.FileTxnSnapLog; import org.apache.zookeeper.server.quorum.Learner; import org.apache.zookeeper.server.quorum.QuorumPeer; import org.apache.zookeeper.txn.CreateTxn; import org.apache.zookeeper.txn.TxnHeader; import org.junit.Assert; import org.junit.Test; public class LearnerTest extends ZKTestCase { class SimpleLearnerZooKeeperServer extends LearnerZooKeeperServer { boolean startupCalled; public SimpleLearnerZooKeeperServer(FileTxnSnapLog ftsl) throws IOException { super(ftsl, 2000, 2000, 2000, null, new ZKDatabase(ftsl), null); } Learner learner; @Override public Learner getLearner() { return learner; } @Override public void startup() { startupCalled = true; } } class SimpleLearner extends Learner { SimpleLearner(FileTxnSnapLog ftsl) throws IOException { self = new QuorumPeer(); zk = new SimpleLearnerZooKeeperServer(ftsl); ((SimpleLearnerZooKeeperServer)zk).learner = this; } } static private void recursiveDelete(File dir) { if (dir == null || !dir.exists()) { return; } if (!dir.isDirectory()) { dir.delete(); } for(File child: dir.listFiles()) { recursiveDelete(child); } } @Test public void syncTest() throws Exception { File tmpFile = File.createTempFile("test", ".dir"); tmpFile.delete(); try { FileTxnSnapLog ftsl = new FileTxnSnapLog(tmpFile, tmpFile); SimpleLearner sl = new SimpleLearner(ftsl); long startZxid = sl.zk.getLastProcessedZxid(); // Set up bogus streams ByteArrayOutputStream baos = new ByteArrayOutputStream(); BinaryOutputArchive oa = BinaryOutputArchive.getArchive(baos); sl.leaderOs = BinaryOutputArchive.getArchive(new ByteArrayOutputStream()); // make streams and socket do something innocuous sl.bufferedOutput = new BufferedOutputStream(System.out); sl.sock = new Socket(); // fake messages from the server QuorumPacket qp = new QuorumPacket(Leader.SNAP, 0, null, null); oa.writeRecord(qp, null); sl.zk.getZKDatabase().serializeSnapshot(oa); oa.writeString("BenWasHere", "signature"); TxnHeader hdr = new TxnHeader(0, 0, 0, 0, ZooDefs.OpCode.create); CreateTxn txn = new CreateTxn("/foo", new byte[0], new ArrayList<ACL>(), false, sl.zk.getZKDatabase().getNode("/").stat.getCversion()); ByteArrayOutputStream tbaos = new ByteArrayOutputStream(); BinaryOutputArchive boa = BinaryOutputArchive.getArchive(tbaos); hdr.serialize(boa, "hdr"); txn.serialize(boa, "txn"); tbaos.close(); qp = new QuorumPacket(Leader.PROPOSAL, 1, tbaos.toByteArray(), null); oa.writeRecord(qp, null); // setup the messages to be streamed to follower sl.leaderIs = BinaryInputArchive.getArchive(new ByteArrayInputStream(baos.toByteArray())); try { sl.syncWithLeader(3); } catch(EOFException e) {} sl.zk.shutdown(); sl = new SimpleLearner(ftsl); Assert.assertEquals(startZxid, sl.zk.getLastProcessedZxid()); } finally { recursiveDelete(tmpFile); } } }