public void testDiskRepairMessage() throws Exception { int len = 100 * 1024; byte[] repairData = ByteArray.makeRandomBytes(len); V3LcapMessage src = makeRepairMessage(repairData); assertEquals(len, src.getRepairDataLength()); assertEquals(V3LcapMessage.EST_ENCODED_HEADER_LENGTH + len, src.getEstimatedEncodedLength()); InputStream srcStream = src.getInputStream(); V3LcapMessage copy = new V3LcapMessage(srcStream, tempDir, theDaemon); assertEqualMessages(src, copy); assertEquals(len, copy.getRepairDataLength()); assertEquals(V3LcapMessage.EST_ENCODED_HEADER_LENGTH + len, src.getEstimatedEncodedLength()); InputStream in = copy.getRepairDataInputStream(); assertTrue(in + "", in instanceof FileInputStream); ByteArrayOutputStream out = new ByteArrayOutputStream(); StreamUtil.copy(in, out); byte[] repairCopy = out.toByteArray(); assertEquals(repairData, repairCopy); // ensure that repeated delete doesn't cause error copy.delete(); copy.delete(); }
private byte[] fromHex(String hex) { return ByteArray.fromHexString(hex); }
/** JUnitTest case for class: org.lockss.protocol.Message */ public class TestV3LcapMessage extends LockssTestCase { private String m_url = "http://www.example.com"; private String m_archivalID = "TestAU_1.0"; private PeerIdentity m_testID; private V3LcapMessage m_testMsg; private List m_testVoteBlocks; private MockPollManager mPollMgr; private MockLockssDaemon theDaemon; private File tempDir; private byte[] m_testBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; private byte[] m_repairData = ByteArray.makeRandomBytes(1000); private CIProperties m_repairProps = null; public void setUp() throws Exception { super.setUp(); theDaemon = getMockLockssDaemon(); tempDir = getTempDir(); String tempDirPath = tempDir.getAbsolutePath(); System.setProperty("java.io.tmpdir", tempDirPath); Properties p = new Properties(); p.setProperty(IdentityManager.PARAM_IDDB_DIR, tempDirPath + "iddb"); p.setProperty(ConfigManager.PARAM_PLATFORM_DISK_SPACE_LIST, tempDirPath); p.setProperty(IdentityManager.PARAM_LOCAL_IP, "127.0.0.1"); p.setProperty(V3LcapMessage.PARAM_REPAIR_DATA_THRESHOLD, "4096"); ConfigurationUtil.setCurrentConfigFromProps(p); IdentityManager idmgr = theDaemon.getIdentityManager(); idmgr.startService(); mPollMgr = new MockPollManager(); theDaemon.setPollManager(mPollMgr); try { m_testID = idmgr.stringToPeerIdentity("127.0.0.1"); } catch (IOException ex) { fail("can't open test host 127.0.0.1: " + ex); } m_repairProps = new CIProperties(); m_repairProps.setProperty("key1", "val1"); m_repairProps.setProperty("key2", "val2"); m_repairProps.setProperty("key3", "val3"); m_testVoteBlocks = V3TestUtils.makeVoteBlockList(10); m_testMsg = this.makeTestVoteMessage(m_testVoteBlocks); } public void testNoOpMessageCreation() throws Exception { // Without voterNonce2 V3LcapMessage noopMsg = V3LcapMessage.makeNoOpMsg(m_testID, m_testBytes, m_testBytes, theDaemon); // With voterNonce2 V3LcapMessage noopMsg2 = V3LcapMessage.makeNoOpMsg(m_testID, m_testBytes, m_testBytes, m_testBytes, theDaemon); // now check the fields we expect to be valid assertEquals(V3LcapMessage.MSG_NO_OP, noopMsg.getOpcode()); assertTrue(m_testID == noopMsg.getOriginatorId()); assertEquals(m_testBytes, noopMsg.getPollerNonce()); assertEquals(m_testBytes, noopMsg.getVoterNonce()); assertEquals(null, noopMsg.getVoterNonce2()); assertEquals(null, noopMsg.getVoteBlocks()); assertEquals(V3LcapMessage.EST_ENCODED_HEADER_LENGTH, noopMsg.getEstimatedEncodedLength()); // Same for msg with voterNonce2 assertEquals(V3LcapMessage.MSG_NO_OP, noopMsg2.getOpcode()); assertTrue(m_testID == noopMsg2.getOriginatorId()); assertEquals(m_testBytes, noopMsg2.getPollerNonce()); assertEquals(m_testBytes, noopMsg2.getVoterNonce()); assertEquals(m_testBytes, noopMsg2.getVoterNonce2()); assertEquals(null, noopMsg2.getVoteBlocks()); assertEquals(V3LcapMessage.EST_ENCODED_HEADER_LENGTH, noopMsg2.getEstimatedEncodedLength()); } public void testRandomNoOpMessageCreation() throws Exception { V3LcapMessage noopMsg1 = V3LcapMessage.makeNoOpMsg(m_testID, theDaemon); V3LcapMessage noopMsg2 = V3LcapMessage.makeNoOpMsg(m_testID, theDaemon); // now check the fields we expect to be valid assertEquals(V3LcapMessage.MSG_NO_OP, noopMsg1.getOpcode()); assertEquals(V3LcapMessage.MSG_NO_OP, noopMsg2.getOpcode()); assertTrue(noopMsg1.getOriginatorId() == m_testID); assertTrue(noopMsg1.getOriginatorId() == noopMsg2.getOriginatorId()); assertFalse(noopMsg1.getPollerNonce() == noopMsg2.getPollerNonce()); assertFalse(noopMsg1.getVoterNonce() == noopMsg2.getVoterNonce()); assertEquals(null, noopMsg1.getVoterNonce2()); assertEquals(null, noopMsg2.getVoterNonce2()); assertEquals(null, noopMsg1.getVoteBlocks()); assertEquals(null, noopMsg2.getVoteBlocks()); } public void testNoOpMessageToString() throws IOException { V3LcapMessage noopMsg = V3LcapMessage.makeNoOpMsg(m_testID, m_testBytes, m_testBytes, theDaemon); String expectedResult = "[V3LcapMessage: from " + m_testID.toString() + ", NoOp]"; assertEquals(expectedResult, noopMsg.toString()); } public void testTestMessageToString() throws IOException { String expectedResult = "[V3LcapMessage: from " + m_testID.toString() + ", Vote AUID: TestAU_1.0 " + "Key:key " + "PN:AQIDBAUGBwgJAAECAwQFBgcICQA= " + "VN:AQIDBAUGBwgJAAECAwQFBgcICQA= " + "B:10 ver 3 rev 5]"; assertEquals(expectedResult, m_testMsg.toString()); } public void getGroup() throws Exception { m_testMsg.setGroups(null); assertNull(m_testMsg.getGroups()); assertNull(m_testMsg.getGroupList()); m_testMsg.setGroups("foo"); assertEquals("foo", m_testMsg.getGroups()); assertEquals(ListUtil.list("foo"), m_testMsg.getGroupList()); m_testMsg.setGroups("foo;bar"); assertEquals("foo;bar", m_testMsg.getGroups()); assertEquals(ListUtil.list("foo", "bar"), m_testMsg.getGroupList()); m_testMsg.setGroups("foo;bar;baz"); assertEquals("foo;bar;baz", m_testMsg.getGroups()); assertEquals(ListUtil.list("foo", "bar", "baz"), m_testMsg.getGroupList()); } public void testNoOpEncoding() throws Exception { V3LcapMessage noopMsg = V3LcapMessage.makeNoOpMsg(m_testID, m_testBytes, m_testBytes, theDaemon); InputStream fromMsg = noopMsg.getInputStream(); V3LcapMessage msg = new V3LcapMessage(fromMsg, tempDir, theDaemon); // now test to see if we got back what we started with assertTrue(m_testID == msg.getOriginatorId()); assertEquals(V3LcapMessage.MSG_NO_OP, msg.getOpcode()); assertEquals(m_testBytes, msg.getPollerNonce()); assertEquals(m_testBytes, msg.getVoterNonce()); assertEquals(null, msg.getVoterNonce2()); } public void testMemoryRepairMessage() throws Exception { int len = 1024; byte[] repairData = ByteArray.makeRandomBytes(len); V3LcapMessage src = makeRepairMessage(repairData); assertEquals(len, src.getRepairDataLength()); assertEquals(V3LcapMessage.EST_ENCODED_HEADER_LENGTH + len, src.getEstimatedEncodedLength()); InputStream srcStream = src.getInputStream(); V3LcapMessage copy = new V3LcapMessage(srcStream, tempDir, theDaemon); assertEqualMessages(src, copy); assertEquals(len, copy.getRepairDataLength()); assertEquals(V3LcapMessage.EST_ENCODED_HEADER_LENGTH + len, src.getEstimatedEncodedLength()); InputStream in = copy.getRepairDataInputStream(); assertTrue(in + "", in instanceof ByteArrayInputStream); ByteArrayOutputStream out = new ByteArrayOutputStream(); StreamUtil.copy(in, out); byte[] repairCopy = out.toByteArray(); assertEquals(repairData, repairCopy); // ensure that repeated delete doesn't cause error copy.delete(); copy.delete(); } public void testDiskRepairMessage() throws Exception { int len = 100 * 1024; byte[] repairData = ByteArray.makeRandomBytes(len); V3LcapMessage src = makeRepairMessage(repairData); assertEquals(len, src.getRepairDataLength()); assertEquals(V3LcapMessage.EST_ENCODED_HEADER_LENGTH + len, src.getEstimatedEncodedLength()); InputStream srcStream = src.getInputStream(); V3LcapMessage copy = new V3LcapMessage(srcStream, tempDir, theDaemon); assertEqualMessages(src, copy); assertEquals(len, copy.getRepairDataLength()); assertEquals(V3LcapMessage.EST_ENCODED_HEADER_LENGTH + len, src.getEstimatedEncodedLength()); InputStream in = copy.getRepairDataInputStream(); assertTrue(in + "", in instanceof FileInputStream); ByteArrayOutputStream out = new ByteArrayOutputStream(); StreamUtil.copy(in, out); byte[] repairCopy = out.toByteArray(); assertEquals(repairData, repairCopy); // ensure that repeated delete doesn't cause error copy.delete(); copy.delete(); } public void testPollDuration() throws Exception { TimeBase.setSimulated(TimeBase.nowMs()); V3LcapMessage src = this.makePollMessage(6 * Constants.WEEK); InputStream srcStream = src.getInputStream(); V3LcapMessage copy = new V3LcapMessage(srcStream, tempDir, theDaemon); assertEqualMessages(src, copy); assertEquals(6 * Constants.WEEK, copy.getDuration()); } public void testNullPollNak() throws Exception { V3LcapMessage src = this.makePollAckMessage(null); InputStream srcStream = src.getInputStream(); V3LcapMessage copy = new V3LcapMessage(srcStream, tempDir, theDaemon); assertEqualMessages(src, copy); assertNull(src.getNak()); assertNull(copy.getNak()); } public void testNonNullPollNak1() throws Exception { V3LcapMessage src = this.makePollAckMessage(V3LcapMessage.PollNak.NAK_GROUP_MISMATCH); InputStream srcStream = src.getInputStream(); V3LcapMessage copy = new V3LcapMessage(srcStream, tempDir, theDaemon); assertEqualMessages(src, copy); assertNotNull(src.getNak()); assertNotNull(copy.getNak()); assertEquals(V3LcapMessage.PollNak.NAK_GROUP_MISMATCH, src.getNak()); assertEquals(V3LcapMessage.PollNak.NAK_GROUP_MISMATCH, copy.getNak()); } public void testNonNullPollNak2() throws Exception { V3LcapMessage src = this.makePollAckMessage(V3LcapMessage.PollNak.NAK_NO_TIME); InputStream srcStream = src.getInputStream(); V3LcapMessage copy = new V3LcapMessage(srcStream, tempDir, theDaemon); assertEqualMessages(src, copy); assertNotNull(src.getNak()); assertNotNull(copy.getNak()); assertEquals(V3LcapMessage.PollNak.NAK_NO_TIME, src.getNak()); assertEquals(V3LcapMessage.PollNak.NAK_NO_TIME, copy.getNak()); } public void testUnknownPollNak() throws Exception { MyV3LcapMessage src = makePollAckMessage(V3LcapMessage.PollNak.NAK_NO_TIME); src.setTestNak("KNACKERED"); InputStream srcStream = src.getInputStream(); V3LcapMessage copy = new V3LcapMessage(srcStream, tempDir, theDaemon); assertEqualMessages(src, copy); assertNotNull(src.getNak()); assertNotNull(copy.getNak()); assertEquals(V3LcapMessage.PollNak.NAK_NO_TIME, src.getNak()); assertEquals(V3LcapMessage.PollNak.NAK_UNKNOWN, copy.getNak()); } public void testRequestMessageCreation() throws Exception { V3LcapMessage reqMsg = new V3LcapMessage( "ArchivalID_2", "key", "Plug42", m_testBytes, m_testBytes, V3LcapMessage.MSG_REPAIR_REQ, 987654321, m_testID, tempDir, theDaemon); reqMsg.setTargetUrl("http://foo.com/"); for (Iterator ix = m_testVoteBlocks.iterator(); ix.hasNext(); ) { reqMsg.addVoteBlock((VoteBlock) ix.next()); } assertEquals(3, reqMsg.getProtocolVersion()); assertEquals("Plug42", reqMsg.getPluginVersion()); assertTrue(m_testID == reqMsg.getOriginatorId()); assertEquals(V3LcapMessage.MSG_REPAIR_REQ, reqMsg.getOpcode()); assertEquals("ArchivalID_2", reqMsg.getArchivalId()); assertEquals("http://foo.com/", reqMsg.getTargetUrl()); assertEquals(m_testBytes, reqMsg.getPollerNonce()); assertEquals(m_testBytes, reqMsg.getVoterNonce()); assertEquals(null, reqMsg.getVoterNonce2()); List aBlocks = new ArrayList(); List bBlocks = new ArrayList(); for (VoteBlocksIterator iter = m_testMsg.getVoteBlockIterator(); iter.hasNext(); ) { aBlocks.add(iter.next()); } for (VoteBlocksIterator iter = reqMsg.getVoteBlockIterator(); iter.hasNext(); ) { bBlocks.add(iter.next()); } assertEquals(aBlocks, bBlocks); // Actual size of test vote blocks is unpredictable assertTrue(reqMsg.getEstimatedEncodedLength() > V3LcapMessage.EST_ENCODED_HEADER_LENGTH); } public void testDiskBasedStreamEncodingTest() throws Exception { // Make a list of vote blocks large enough to trigger on-disk // vote message creation. List testVoteBlocks = V3TestUtils.makeVoteBlockList(21); V3LcapMessage testMsg = makeTestVoteMessage(testVoteBlocks); assertTrue(testMsg.m_voteBlocks instanceof DiskVoteBlocks); // Encode the test message. InputStream is = testMsg.getInputStream(); V3LcapMessage decodedMsg = new V3LcapMessage(is, tempDir, theDaemon); // Ensure that the decoded message matches the test message. assertEqualMessages(testMsg, decodedMsg); } private void assertEqualMessages(V3LcapMessage a, V3LcapMessage b) throws Exception { assertTrue(a.getOriginatorId() == b.getOriginatorId()); assertEquals(a.getOpcode(), b.getOpcode()); assertEquals(a.getTargetUrl(), b.getTargetUrl()); assertEquals(a.getArchivalId(), b.getArchivalId()); assertEquals(a.getProtocolVersion(), b.getProtocolVersion()); assertEquals(a.getPollerNonce(), b.getPollerNonce()); assertEquals(a.getVoterNonce(), b.getVoterNonce()); assertEquals(a.getVoterNonce2(), b.getVoterNonce2()); assertEquals(a.getPluginVersion(), b.getPluginVersion()); assertEquals(a.getHashAlgorithm(), b.getHashAlgorithm()); assertEquals(a.isVoteComplete(), b.isVoteComplete()); assertEquals(a.getRepairDataLength(), b.getRepairDataLength()); assertEquals(a.getLastVoteBlockURL(), b.getLastVoteBlockURL()); assertIsomorphic(a.getNominees(), b.getNominees()); List aBlocks = new ArrayList(); List bBlocks = new ArrayList(); for (VoteBlocksIterator iter = a.getVoteBlockIterator(); iter.hasNext(); ) { aBlocks.add(iter.next()); } for (VoteBlocksIterator iter = b.getVoteBlockIterator(); iter.hasNext(); ) { bBlocks.add(iter.next()); } assertTrue(aBlocks.equals(bBlocks)); // TODO: Figure out how to test time. } private V3LcapMessage makePollMessage(long duration) { V3LcapMessage msg = new V3LcapMessage( "ArchivalID_2", "key", "Plug42", m_testBytes, m_testBytes, V3LcapMessage.MSG_POLL, TimeBase.nowMs() + duration, m_testID, tempDir, theDaemon); return msg; } private MyV3LcapMessage makePollAckMessage(V3LcapMessage.PollNak nak) { MyV3LcapMessage msg = new MyV3LcapMessage( "ArchivalID_2", "key", "Plug42", m_testBytes, m_testBytes, V3LcapMessage.MSG_POLL_ACK, 987654321, m_testID, tempDir, theDaemon); if (nak != null) { msg.setNak(nak); } return msg; } private V3LcapMessage makeRepairMessage(byte[] repairData) { V3LcapMessage msg = new V3LcapMessage( "ArchivalID_2", "key", "Plug42", m_testBytes, m_testBytes, V3LcapMessage.MSG_REPAIR_REP, 987654321, m_testID, tempDir, theDaemon); msg.setHashAlgorithm(LcapMessage.getDefaultHashAlgorithm()); msg.setTargetUrl(m_url); msg.setArchivalId(m_archivalID); msg.setPluginVersion("PlugVer42"); msg.setRepairDataLength(repairData.length); msg.setRepairProps(m_repairProps); msg.setInputStream(new ByteArrayInputStream(repairData)); return msg; } private V3LcapMessage makeTestVoteMessage(Collection voteBlocks) throws IOException { mPollMgr.setStateDir("key", tempDir); V3LcapMessage msg = new V3LcapMessage( "ArchivalID_2", "key", "Plug42", m_testBytes, m_testBytes, V3LcapMessage.MSG_VOTE, 987654321, m_testID, tempDir, theDaemon); // Set msg vote blocks. for (Iterator ix = voteBlocks.iterator(); ix.hasNext(); ) { msg.addVoteBlock((VoteBlock) ix.next()); } msg.setHashAlgorithm(LcapMessage.getDefaultHashAlgorithm()); msg.setArchivalId(m_archivalID); msg.setPluginVersion("PlugVer42"); return msg; } static class MyV3LcapMessage extends V3LcapMessage { String testNak; public MyV3LcapMessage(File messageDir, LockssApp daemon) { super(messageDir, daemon); } public MyV3LcapMessage( String auId, String pollKey, String pluginVersion, byte[] pollerNonce, byte[] voterNonce, int opcode, long deadline, PeerIdentity origin, File messageDir, LockssApp daemon) { super( auId, pollKey, pluginVersion, pollerNonce, voterNonce, opcode, deadline, origin, messageDir, daemon); } public MyV3LcapMessage( String auId, String pollKey, String pluginVersion, byte[] pollerNonce, byte[] voterNonce, byte[] voterNonce2, int opcode, long deadline, PeerIdentity origin, File messageDir, LockssApp daemon) { super( auId, pollKey, pluginVersion, pollerNonce, voterNonce, voterNonce2, opcode, deadline, origin, messageDir, daemon); } public MyV3LcapMessage(byte[] encodedBytes, File messageDir, LockssApp daemon) throws IOException { super(encodedBytes, messageDir, daemon); } public MyV3LcapMessage(InputStream inputStream, File messageDir, LockssApp daemon) throws IOException { super(inputStream, messageDir, daemon); } void setTestNak(String nakName) { testNak = nakName; } public void storeProps() throws IOException { super.storeProps(); if (testNak != null) { m_props.setProperty("nak", testNak); } } } }