package com.limegroup.gnutella; import java.io.InterruptedIOException; import java.util.Arrays; import java.util.Iterator; import junit.framework.Test; import com.limegroup.gnutella.messages.QueryReply; import com.limegroup.gnutella.messages.QueryRequest; import com.limegroup.gnutella.routing.QueryRouteTable; import com.limegroup.gnutella.routing.RouteTableMessage; import com.limegroup.gnutella.stubs.ActivityCallbackStub; /** * Tests that an Ultrapeer correctly handle Probe queries. Essentially tests * the following methods of MessageRouter: handleQueryRequestPossibleDuplicate * and handleQueryRequest * * ULTRAPEER[0] ---- CENTRAL TEST ULTRAPEER ---- ULTRAPEER_2 * | * | * | * LEAF[0] */ public final class ServerSideDynamicQueryTest extends ServerSideTestCase { protected static int TIMEOUT = 2000; public ServerSideDynamicQueryTest(String name) { super(name); } public static Test suite() { return buildTestSuite(ServerSideDynamicQueryTest.class); } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } public static Integer numUPs() { return new Integer(2); } public static Integer numLeaves() { return new Integer(1); } public static ActivityCallback getActivityCallback() { return new ActivityCallbackStub(); } public static void setUpQRPTables() throws Exception { //3. routed leaf, with route table for "test" QueryRouteTable qrt = new QueryRouteTable(); qrt.add("berkeley"); qrt.add("susheel"); qrt.addIndivisible(HugeTestUtils.UNIQUE_SHA1.toString()); for (Iterator iter=qrt.encode(null).iterator(); iter.hasNext(); ) { LEAF[0].send((RouteTableMessage)iter.next()); LEAF[0].flush(); } // for Ultrapeer 1 qrt = new QueryRouteTable(); qrt.add("leehsus"); qrt.add("berkeley"); for (Iterator iter=qrt.encode(null).iterator(); iter.hasNext(); ) { ULTRAPEER[0].send((RouteTableMessage)iter.next()); ULTRAPEER[0].flush(); } } // BEGIN TESTS // ------------------------------------------------------ public void testBasicProbeMechanicsFromUltrapeer() throws Exception { drainAll(); QueryRequest request = QueryRequest.createQuery("berkeley"); request.setTTL((byte)1); ULTRAPEER[1].send(request); ULTRAPEER[1].flush(); QueryRequest reqRecvd = (QueryRequest) LEAF[0].receive(TIMEOUT); assertEquals("berkeley", reqRecvd.getQuery()); assertTrue(Arrays.equals(request.getGUID(), reqRecvd.getGUID())); // should NOT be forwarded to other Ultrapeer assertTrue(noUnexpectedMessages(ULTRAPEER[0])); // make sure probes are routed back correctly.... Response response1=new Response(0L, 0L, "berkeley rocks"); byte[] guid1=GUID.makeGuid(); QueryReply reply1=new QueryReply(request.getGUID(), (byte)2, 6346, IP, 56, new Response[] {response1}, guid1, false); drain(ULTRAPEER[1]); LEAF[0].send(reply1); LEAF[0].flush(); QueryReply qRep = getFirstQueryReply(ULTRAPEER[1]); assertNotNull(qRep); assertEquals(new GUID(guid1), new GUID(qRep.getClientGUID())); Thread.sleep(2*1000); // extend the probe.... request.setTTL((byte)2); ULTRAPEER[1].send(request); ULTRAPEER[1].flush(); // leaves don't get any unexpected messages, no use using // noUnenexpectedMessages reqRecvd = getFirstQueryRequest(LEAF[0], TIMEOUT); assertNull("Did not expected a QueryRequest", reqRecvd); reqRecvd = getFirstQueryRequest(ULTRAPEER[0]); assertNotNull(reqRecvd); assertEquals("berkeley", reqRecvd.getQuery()); assertTrue(Arrays.equals(request.getGUID(), reqRecvd.getGUID())); assertEquals((byte)1, reqRecvd.getHops()); } public void testBasicProbeMechanicsFromLeaf() throws Exception { drainAll(); QueryRequest request = QueryRequest.createQuery("berkeley"); request.hop(); request.setTTL((byte)1); assertEquals(1, request.getHops()); ULTRAPEER[1].send(request); ULTRAPEER[1].flush(); QueryRequest reqRecvd = (QueryRequest) LEAF[0].receive(TIMEOUT); assertEquals("berkeley", reqRecvd.getQuery()); assertTrue(Arrays.equals(request.getGUID(), reqRecvd.getGUID())); // should NOT be forwarded to other Ultrapeer assertTrue(noUnexpectedMessages(ULTRAPEER[0])); // make sure probes are routed back correctly.... Response response1=new Response(0L, 0L, "berkeley rocks"); byte[] guid1=GUID.makeGuid(); QueryReply reply1=new QueryReply(request.getGUID(), (byte)2, 6346, IP, 56, new Response[] {response1}, guid1, false); drain(ULTRAPEER[1]); LEAF[0].send(reply1); LEAF[0].flush(); QueryReply qRep = getFirstQueryReply(ULTRAPEER[1]); assertNotNull(qRep); assertEquals(new GUID(guid1), new GUID(qRep.getClientGUID())); Thread.sleep(2*1000); // extend the probe.... request.setTTL((byte)2); ULTRAPEER[1].send(request); ULTRAPEER[1].flush(); // leaves don't get any unexpected messages, no use using // noUnenexpectedMessages reqRecvd = getFirstQueryRequest(LEAF[0], TIMEOUT); assertNull("Did not expected a QueryRequest", reqRecvd); reqRecvd = getFirstQueryRequest(ULTRAPEER[0]); assertNotNull(reqRecvd); assertEquals("berkeley", reqRecvd.getQuery()); assertTrue(Arrays.equals(request.getGUID(), reqRecvd.getGUID())); assertEquals((byte)2, reqRecvd.getHops()); } public void testDuplicateProbes() throws Exception { drainAll(); QueryRequest request = QueryRequest.createQuery("berkeley"); request.setTTL((byte)1); ULTRAPEER[1].send(request); ULTRAPEER[1].flush(); QueryRequest reqRecvd = (QueryRequest) LEAF[0].receive(TIMEOUT); assertEquals("berkeley", reqRecvd.getQuery()); assertTrue(Arrays.equals(request.getGUID(), reqRecvd.getGUID())); // should NOT be forwarded to other Ultrapeer assertTrue(noUnexpectedMessages(ULTRAPEER[0])); Thread.sleep(2*1000); // test that the duplicate probe doesn't go anywhere it isn't supposed ULTRAPEER[1].send(request); ULTRAPEER[1].flush(); // should NOT be forwarded to leaf again.... // leaves don't get any unexpected messages, no use using // noUnenexpectedMessages reqRecvd = getFirstQueryRequest(LEAF[0], TIMEOUT); assertNull("Did not expected a QueryRequest", reqRecvd); // should NOT be forwarded to other Ultrapeer.... assertTrue(noUnexpectedMessages(ULTRAPEER[0])); } // makes sure a probe can't be extended twice.... public void testProbeIsLimited() throws Exception { drainAll(); QueryRequest request = QueryRequest.createQuery("berkeley"); request.setTTL((byte)1); ULTRAPEER[1].send(request); ULTRAPEER[1].flush(); QueryRequest reqRecvd = (QueryRequest) LEAF[0].receive(TIMEOUT); assertEquals("berkeley", reqRecvd.getQuery()); assertTrue(Arrays.equals(request.getGUID(), reqRecvd.getGUID())); // should NOT be forwarded to other Ultrapeer assertTrue(noUnexpectedMessages(ULTRAPEER[0])); Thread.sleep(2*1000); // extend the probe.... request.setTTL((byte)3); ULTRAPEER[1].send(request); ULTRAPEER[1].flush(); // leaves don't get any unexpected messages, no use using // noUnenexpectedMessages try { LEAF[0].receive(TIMEOUT); fail("expected InterruptedIOException"); } catch (InterruptedIOException expected) {} reqRecvd = getFirstQueryRequest(ULTRAPEER[0]); assertNotNull(reqRecvd); assertEquals("berkeley", reqRecvd.getQuery()); assertTrue(Arrays.equals(request.getGUID(), reqRecvd.getGUID())); assertEquals((byte)1, reqRecvd.getHops()); Thread.sleep(2*1000); // extend it again but make sure it doesn't get through... request.setTTL((byte)4); ULTRAPEER[1].send(request); ULTRAPEER[1].flush(); // should NOT be forwarded to leaf again.... // leaves don't get any unexpected messages, no use using // noUnenexpectedMessages reqRecvd = getFirstQueryRequest(LEAF[0], TIMEOUT); assertNull("Did not expected a QueryRequest", reqRecvd); // should NOT be forwarded to other Ultrapeer.... assertTrue(noUnexpectedMessages(ULTRAPEER[0])); } // tries to extend queries with original TTL > 1, should fail... public void testProbeIsTTL1Only() throws Exception { for (int i = 2; i < 5; i++) { drainAll(); QueryRequest request = QueryRequest.createQuery("berkeley"); request.setTTL((byte)i); ULTRAPEER[1].send(request); ULTRAPEER[1].flush(); QueryRequest reqRecvd = (QueryRequest) LEAF[0].receive(TIMEOUT); assertEquals("berkeley", reqRecvd.getQuery()); assertTrue(Arrays.equals(request.getGUID(), reqRecvd.getGUID())); // should be forwarded to other Ultrapeer reqRecvd = getFirstQueryRequest(ULTRAPEER[0]); assertNotNull(reqRecvd); assertEquals("berkeley", reqRecvd.getQuery()); assertTrue(Arrays.equals(request.getGUID(), reqRecvd.getGUID())); assertEquals((byte)1, reqRecvd.getHops()); Thread.sleep(2*1000); // extend the probe.... request.setTTL((byte)(i+1)); ULTRAPEER[1].send(request); ULTRAPEER[1].flush(); // should be counted as a duplicate and not forwarded anywhere... // leaves don't get any unexpected messages, no use using // noUnenexpectedMessages reqRecvd = getFirstQueryRequest(LEAF[0], TIMEOUT); assertNull("Did not expected a QueryRequest", reqRecvd); assertTrue(noUnexpectedMessages(ULTRAPEER[0])); } } }