package com.limegroup.gnutella.connection; import junit.framework.Test; import com.limegroup.gnutella.Response; import com.limegroup.gnutella.messages.*; import com.limegroup.gnutella.routing.PatchTableMessage; import com.limegroup.gnutella.routing.ResetTableMessage; import com.limegroup.gnutella.util.BaseTestCase; import com.limegroup.gnutella.util.PrivilegedAccessor; /** * Tests that the composite queue correctly expires messages & prioritizes * things correctly. */ public class CompositeQueueTest extends BaseTestCase { private CompositeQueue QUEUE = new CompositeQueue(3000, 100, 1000, 1); private static final byte[] IP = new byte[] { 1, 1, 1, 1 }; public CompositeQueueTest(String name) { super(name); } public static Test suite() { return buildTestSuite(CompositeQueueTest.class); } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * This checks to make sure that messages in the outgoing queue are ordered * and prioritized correctly. * NOTE: It is important to remember that the queues the messages are stored * in are BucketQueues -- that means that even if the capacity of the queue is * 1, then EACH BUCKET will have 1 item. So two PingReply's with different * hops will BOTH be stored in the queue, because each hop is a different * priority, and each priority is a different bucket. */ public void testReorderBuffer() throws Exception { Message m=null; // send QueryRequest QUEUE.add(QueryRequest.createQuery("test", (byte)5)); // send PingRequest with one hop m=new PingRequest((byte)5); m.hop(); QUEUE.add(m); // send QueryReply with priority 1 m=new QueryReply(new byte[16], (byte)5, 6340, IP, 0, new Response[0], new byte[16], false); m.setPriority(30000); QUEUE.add(m); // send 3 push requests QUEUE.add(new PushRequest(new byte[16], (byte)5, new byte[16], 0, IP, 6340)); QUEUE.add(new PushRequest(new byte[16], (byte)5, new byte[16], 0, IP, 6341)); QUEUE.add(new PushRequest(new byte[16], (byte)5, new byte[16], 0, IP, 6342)); // send QueryReply with priority 1 m=new QueryReply(new byte[16], (byte)5, 6343, IP, 0, new Response[0], new byte[16], false); m.setPriority(30000); QUEUE.add(m); // send 4 push requests QUEUE.add(new PushRequest(new byte[16], (byte)5, new byte[16], 0, IP, 6343)); QUEUE.add(new PushRequest(new byte[16], (byte)5, new byte[16], 0, IP, 6344)); QUEUE.add(new PushRequest(new byte[16], (byte)5, new byte[16], 0, IP, 6345)); QUEUE.add(new PushRequest(new byte[16], (byte)5, new byte[16], 0, IP, 6346)); // send QueryReply with priority 7 m=new QueryReply(new byte[16], (byte)5, 6341, IP, 0, new Response[0], new byte[16], false); QUEUE.add(m); // send PingReply with 3 hops m=PingReply.create(new byte[16], (byte)5, 6343, IP); m.hop(); m.hop(); m.hop(); QUEUE.add(m); // send PingReply with 3 hops m=PingReply.create(new byte[16], (byte)5, 6344, IP); m.hop(); m.hop(); m.hop(); QUEUE.add(m); // send QueryReply with priority 2 m=new QueryReply(new byte[16], (byte)5, 6344, IP, 0, new Response[0], new byte[16], false); m.setPriority(20000); QUEUE.add(m); // send QueryReply with priority 0 m=new QueryReply(new byte[16], (byte)5, 6345, IP, 0, new Response[0], new byte[16], false); m.setPriority(50000); QUEUE.add(m); // send Reset message QUEUE.add(new ResetTableMessage(1024, (byte)2)); // send a watchdog pong QUEUE.add(PingReply.create(new byte[16], (byte)1, 6342, IP)); // send PingReply with 2 hops m = PingReply.create(new byte[16], (byte)3, 6340, IP); m.hop(); m.hop(); QUEUE.add(m); // send QueryReply with priority 4 m=new QueryReply(new byte[16], (byte)5, 6346, IP, 0, new Response[0], new byte[16], false); m.setPriority(5000); QUEUE.add(m); // send QueryReply with priority 5 m=new QueryReply(new byte[16], (byte)5, 6342, IP, 0, new Response[0], new byte[16], false); m.setPriority(1000); QUEUE.add(m); // send Patch message QUEUE.add(new PatchTableMessage((short)1, (short)2, PatchTableMessage.COMPRESSOR_NONE, (byte)8, new byte[10], 0, 5)); // send a watchdog ping QUEUE.add(new PingRequest((byte)1)); // send Patch message QUEUE.add(new PatchTableMessage((short)2, (short)2, PatchTableMessage.COMPRESSOR_NONE, (byte)8, new byte[10], 5, 9)); // send QueryRequest QUEUE.add(QueryRequest.createQuery("test2", (byte)5)); // send QueryRequest with 1 hop m = QueryRequest.createQuery("test far", (byte)5); m.hop(); QUEUE.add(m); // send QueryRequest with 2 hop m = QueryRequest.createQuery("test farther", (byte)5); m.hop(); m.hop(); QUEUE.add(m); //2. Buffers should look this before emptying: // Except for QRP messages, all queues are LIFO when priorities match // WATCHDOG: pong/6342 ping // PUSH: x/6340 x/6341 x/6342 x/6343 x/6344 x/6345 x/6346 // QUERY_REPLY: 6345/50k 6340/30k 6343/30k // 6344/20k 6346/5k 6342/1k 6341/0 // QUERY: "test farther"/2 "test far"/1, "test"/0, "test2"/0 // PING_REPLY: x/6340/2 x/6344/3 // PING: x // OTHER: reset patch1 patch2 // cheat 'cause it's easy. PrivilegedAccessor.setValue(QUEUE, "_cycled", Boolean.FALSE); //3. Read them...now in different order! m=QUEUE.removeNext(); assertInstanceof("Unexpected message: "+m, PingRequest.class, m); assertEquals("Unexpected # of hops"+m, 0, m.getHops()); m=QUEUE.removeNext(); //push assertInstanceof("Unexpected message: "+m, PushRequest.class, m); assertEquals("unexpected push request port", 6346, ((PushRequest)m).getPort()); m=QUEUE.removeNext(); //push assertInstanceof("Unexpected message: "+m, PushRequest.class, m); assertEquals("unexpected push request port", 6345, ((PushRequest)m).getPort()); m=QUEUE.removeNext(); //push assertInstanceof("Unexpected message: "+m, PushRequest.class, m); assertEquals("unexpected push request port", 6344, ((PushRequest)m).getPort()); m=QUEUE.removeNext(); //push assertInstanceof("Unexpected message: "+m, PushRequest.class, m); assertEquals("unexpected push request port", 6343, ((PushRequest)m).getPort()); m=QUEUE.removeNext(); //push assertInstanceof("Unexpected message: "+m, PushRequest.class, m); assertEquals("unexpected push request port", 6342, ((PushRequest)m).getPort()); m=QUEUE.removeNext(); //push assertInstanceof("Unexpected message: "+m, PushRequest.class, m); assertEquals("unexpected push request port", 6341, ((PushRequest)m).getPort()); m=QUEUE.removeNext(); //reply/6341 (high priority) assertInstanceof("m not a queryreply", QueryReply.class, m); assertEquals("unexpected queryreply port. priority: " + m.getPriority(), 6341, ((QueryReply)m).getPort()); m=QUEUE.removeNext(); //reply/6342 (medium priority) assertInstanceof("m not a queryreply", QueryReply.class, m); assertEquals("unexpected query reply port", 6342, ((QueryReply)m).getPort()); m=QUEUE.removeNext(); //reply/6346 assertInstanceof("m not a queryreply", QueryReply.class, m); assertEquals("unexpected queryreply port", 6346, ((QueryReply)m).getPort()); m=QUEUE.removeNext(); //reply/6344 assertInstanceof("m not a queryreply", QueryReply.class, m); assertEquals("unexpected queryreply port", 6344, ((QueryReply)m).getPort()); m=QUEUE.removeNext(); //reply/6343 assertInstanceof("m not a queryreply", QueryReply.class, m); assertEquals("unexpected queryreply port", 6343, ((QueryReply)m).getPort()); m=QUEUE.removeNext(); //reply/6340 assertInstanceof("m not a queryreply", QueryReply.class, m); assertEquals("unexpected queryreply port", 6340, ((QueryReply)m).getPort()); m=QUEUE.removeNext(); //query "test2"/0 assertInstanceof("m not a queryrequest", QueryRequest.class, m); assertEquals("unexpected query", "test2", ((QueryRequest)m).getQuery()); m=QUEUE.removeNext(); //query "test"/0 assertInstanceof("m not a queryrequest", QueryRequest.class, m); assertEquals("unexpected query", "test", ((QueryRequest)m).getQuery()); m=QUEUE.removeNext(); //query "test far"/1 assertInstanceof("m not a queryrequest", QueryRequest.class, m); assertEquals("unexpected query", "test far", ((QueryRequest)m).getQuery()); m=QUEUE.removeNext(); //reply 6343 assertInstanceof("m not a pingreply", PingReply.class, m); assertEquals("unexpected pingreply port", 6344, ((PingReply)m).getPort()); m=QUEUE.removeNext(); //ping 6340 assertInstanceof("m not a pingrequest", PingRequest.class, m); assertGreaterThan("unexpected number of hops (>0)", 0, m.getHops()); m=QUEUE.removeNext(); //QRP reset assertInstanceof("m not a resettablemessage", ResetTableMessage.class, m); m=QUEUE.removeNext(); //watchdog pong/6342 assertInstanceof("m not a pingreply", PingReply.class, m); assertEquals("unexpected pingreply port", 6342, ((PingReply)m).getPort()); assertEquals("unexpected number of hops", 0, m.getHops()); //watchdog response pong m=QUEUE.removeNext(); //push assertInstanceof("Unexpected message: "+m, PushRequest.class, m); assertEquals("unexpected push request port", 6340, ((PushRequest)m).getPort()); m=QUEUE.removeNext(); //reply/6341 (high priority) assertInstanceof("m not a queryreply", QueryReply.class, m); assertEquals("unexpected queryreply port. priority: " + m.getPriority(), 6345, ((QueryReply)m).getPort()); m=QUEUE.removeNext(); //query "test farther"/2 assertInstanceof("m not a queryrequest", QueryRequest.class, m); assertEquals("unexpected query", "test farther", ((QueryRequest)m).getQuery()); m=QUEUE.removeNext(); //reply 6340 assertInstanceof("m not a pingreply", PingReply.class, m); assertEquals("unexpected pingreply port", 6340, ((PingReply)m).getPort()); m=QUEUE.removeNext(); //QRP patch1 assertInstanceof("m not a patchtablemessage", PatchTableMessage.class, m); assertEquals("unexpected patchtablemessage sequencenumber", 1, ((PatchTableMessage)m).getSequenceNumber()); m=QUEUE.removeNext(); //QRP patch2 assertInstanceof("m not a patchtable message", PatchTableMessage.class, m); assertEquals("unexpected patchtablemessage sequencenumber", 2, ((PatchTableMessage)m).getSequenceNumber()); } /** * Test to make sure that messages properly timeout in the message * queues and are dropped. */ public void testBufferTimeout() throws Exception { //Drop one message QUEUE.add(QueryRequest.createQuery("0", (byte)3)); sleep(1200); QUEUE.add(QueryRequest.createQuery("1200", (byte)3)); Message m = QUEUE.removeNext(); assertInstanceof("m not a queryrequest", QueryRequest.class, m); assertEquals("unexpected query", "1200", ((QueryRequest)m).getQuery()); assertNull(QUEUE.removeNext()); assertEquals(1, QUEUE.resetDropped()); //Drop many messages QUEUE.add(QueryRequest.createQuery("0", (byte)3)); sleep(300); QUEUE.add(QueryRequest.createQuery("300", (byte)3)); sleep(300); QUEUE.add(QueryRequest.createQuery("600", (byte)3)); sleep(500); QUEUE.add(QueryRequest.createQuery("1100", (byte)3)); sleep(900); QUEUE.add(QueryRequest.createQuery("2000", (byte)3)); m=QUEUE.removeNext(); assertInstanceof("m not a queryrequest", QueryRequest.class, m); assertEquals("unexpected query", "2000", ((QueryRequest)m).getQuery()); m=QUEUE.removeNext(); assertInstanceof("m not a queryrequest", QueryRequest.class, m); assertEquals("unexpected query", ((QueryRequest)m).getQuery(), "1100"); assertNull(QUEUE.removeNext()); assertEquals("unexpected # of dropped sent messages", 3, QUEUE.resetDropped()); } public void testPriorityHint() throws Exception { //Tests wrap-around loop of sendQueuedMessages Message m=null; // head...tail QUEUE.add(hopped(new PingRequest((byte)4))); QUEUE.add(QueryRequest.createQuery("a", (byte)3)); assertInstanceof("didn't recieve queryrequest", QueryRequest.class, QUEUE.removeNext()); assertInstanceof("didn't recieve pingrequest", PingRequest.class, QUEUE.removeNext()); assertNull(QUEUE.removeNext()); // force it to reset the current cycle. //tail...<wrap>...head QUEUE.add(QueryRequest.createQuery("a", (byte)3)); QUEUE.add(hopped(new PingRequest((byte)5))); assertInstanceof("didn't recieve pingrequest", PingRequest.class, QUEUE.removeNext()); assertInstanceof("didn't recieve queryrequest", QueryRequest.class, QUEUE.removeNext()); assertNull(QUEUE.removeNext()); // force it to reset the current cycle. //tail...<wrap>...head // WATCHDOG: ping // PUSH: // QUERY_REPLY: reply // QUERY: query // PING_REPLY: // PING: // OTHER: reset QUEUE.add(new PingRequest((byte)1)); QUEUE.add(new QueryReply(new byte[16], (byte)5, 6341, IP, 0, new Response[0], new byte[16], false)); QUEUE.add(new ResetTableMessage(1024, (byte)2)); QUEUE.add(QueryRequest.createQuery("a", (byte)3)); m=QUEUE.removeNext(); assertInstanceof("Got: "+m, QueryRequest.class, m); m=QUEUE.removeNext(); assertInstanceof("GOt: " +m, ResetTableMessage.class, m); m=QUEUE.removeNext(); assertInstanceof("Got: " + m, PingRequest.class, m); m=QUEUE.removeNext(); assertInstanceof("Got: " + m, QueryReply.class, m); } private static Message hopped(Message m) { m.hop(); return m; } private static void sleep(long msecs) { try { Thread.sleep(msecs); } catch (InterruptedException ignored) { } } }