package com.limegroup.gnutella.handshaking; import java.util.Arrays; import java.util.Collections; import java.util.Properties; import junit.framework.Test; import com.limegroup.gnutella.ManagedConnection; import com.limegroup.gnutella.ManagedConnectionStub; import com.limegroup.gnutella.RouterService; import com.limegroup.gnutella.settings.ConnectionSettings; import com.limegroup.gnutella.settings.UltrapeerSettings; import com.limegroup.gnutella.util.BaseTestCase; import com.limegroup.gnutella.util.PrivilegedAccessor; /** * Tests the functionality of the <tt>UltrapeerHandshakeResponderTest</tt> * class.<p> * * For the Ultrapeer specifications, see:<p> * * http://groups.yahoo.com/group/the_gdf/files/Proposals/Ultrapeer/Ultrapeers_1.0_clean.html */ public final class UltrapeerHandshakeResponderTest extends BaseTestCase { public UltrapeerHandshakeResponderTest(String name) { super(name); } public static Test suite() { return buildTestSuite(UltrapeerHandshakeResponderTest.class); } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Always assume we're encoding & accept it. This simplifies the testing. * For further tests on whether how handshaking works in response to these * settings, see HandshakeResponseTest. */ public void setUp() { ConnectionSettings.ACCEPT_DEFLATE.setValue(true); ConnectionSettings.ENCODE_DEFLATE.setValue(true); } /** * Free all slots */ protected void tearDown() throws Exception { freeSlots(); } /** * Fills all available slots of ConnectionManager so that * checks for x < UltrapeerSettings.MAX_LEAVES will always * fail */ private void fillSlots() throws Exception { int maxLeaves = UltrapeerSettings.MAX_LEAVES.getValue(); ManagedConnection[] mc = new ManagedConnection[maxLeaves]; for(int i = 0; i < mc.length; i++) { mc[i] = new ManagedConnectionStub(); } PrivilegedAccessor.setValue(RouterService.getConnectionManager(), "_initializedClientConnections", Arrays.asList(mc)); } /** * Restores the ConnectionManager._initializedClientConnections List */ private void freeSlots() throws Exception { PrivilegedAccessor.setValue(RouterService.getConnectionManager(), "_initializedClientConnections", Collections.EMPTY_LIST); } /** * Tests the method for responding to outgoing connection attempts. * The response we send is the final response of the handshake -- * the third header exchange overall. */ public void testRespondToOutgoingUltrapeer() throws Exception { UltrapeerSettings.FORCE_ULTRAPEER_MODE.setValue(false); ConnectionSettings.ALLOW_WHILE_DISCONNECTED.setValue(true); // test the 3 Ultrapeer cases -- // create the Ultrapeer responder to test off of UltrapeerHandshakeResponder responder = new UltrapeerHandshakeResponder("23.3.4.5"); // 1) Ultrapeer-Ultrapeer::No X-Ultrapeer-Needed Properties props = new UltrapeerHeaders("40.0.9.8"); HandshakeResponse headers = HandshakeResponse.createResponse(props); HandshakeResponse hr = responder.respond(headers, true); // we shouldn't send any response header in this case -- it's // just assumed that we're becoming an Ultrapeer assertTrue("should be accepted", hr.isAccepted()); assertEquals("should only have deflate header", 1, hr.props().size()); assertTrue("should be deflated", hr.isDeflateEnabled()); // 2) Ultrapeer-Ultrapeer::X-Ultrapeer-Needed: true props = new UltrapeerHeaders("40.0.9.8"); // this should be redundant, but make sure it's handled the way // we want props.put(HeaderNames.X_ULTRAPEER_NEEDED, "true"); headers = HandshakeResponse.createResponse(props); hr = responder.respond(headers, true); // we shouldn't send any response header in this case -- it's // just assumed that we're becoming an Ultrapeer assertTrue("should be accepted", hr.isAccepted()); assertEquals("should only have deflate header", 1, hr.props().size()); assertTrue("should be deflated", hr.isDeflateEnabled()); // 3) Ultrapeer-Ultrapeer::X-Ultrapeer-Needed: false props = new UltrapeerHeaders("78.9.3.0"); props.put(HeaderNames.X_ULTRAPEER_NEEDED, "false"); headers = HandshakeResponse.createResponse(props); hr = responder.respond(headers, true); assertTrue("should not be an Ultrapeer", !hr.isUltrapeer()); assertTrue("should be becoming an leaf", hr.isLeaf()); assertTrue("should be accepted", hr.isAccepted()); assertEquals("should have two headers", 2, hr.props().size()); assertTrue("should be deflating", hr.isDeflateEnabled()); ConnectionSettings.ALLOW_WHILE_DISCONNECTED.setValue(false); } /** * Tests to make sure that outgoing connection responses are handled * correctly when the host we're responding to is a leaf. */ public void testRespondToOutgoingLeaf() throws Exception { ConnectionSettings.ALLOW_WHILE_DISCONNECTED.setValue(true); ConnectionSettings.EVER_ACCEPTED_INCOMING.setValue(true); UltrapeerSettings.EVER_ULTRAPEER_CAPABLE.setValue(true); ConnectionSettings.LOCAL_IS_PRIVATE.setValue(false); assertTrue(RouterService.isSupernode()); UltrapeerHandshakeResponder responder = new UltrapeerHandshakeResponder("23.3.4.5"); // Leaf-Ultrapeer --> leaf slots available Properties props = new LeafHeaders("78.9.3.0"); HandshakeResponse headers = HandshakeResponse.createResponse(props); HandshakeResponse hr = responder.respond(headers, true); assertTrue("should have returned that we accepted the connection", hr.isAccepted()); assertEquals("should only have one header", 1, hr.props().size()); assertTrue("should deflate to leaf (may change)", hr.isDeflateEnabled()); fillSlots(); hr = responder.respond(headers, true); assertTrue("should not have accepted the connection", !hr.isAccepted()); assertEquals("should not have any headers", 0, hr.props().size()); // clean up settings ConnectionSettings.ALLOW_WHILE_DISCONNECTED.setValue(false); } /** * Tests the method for responding to incoming connection attempts. */ public void testRespondToIncomingUltrapeer() throws Exception { UltrapeerSettings.FORCE_ULTRAPEER_MODE.setValue(false); ConnectionSettings.PREFERENCING_ACTIVE.setValue(true); ConnectionSettings.ALLOW_WHILE_DISCONNECTED.setValue(true); UltrapeerHandshakeResponder responder = new UltrapeerHandshakeResponder("23.3.4.5"); // 1) check the Ultrapeer case -- leaf guidance should be used // here because the Ultrapeer definitely does not have the // maximum number of leaves HandshakeResponse up = HandshakeResponse.createResponse(new UltrapeerHeaders("80.45.0.1")); HandshakeResponse hr = responder.respond(up, false); assertTrue("should report Ultrapeer true", hr.isUltrapeer()); assertTrue("should tell the connecting Ultrapeer to become a leaf", hr.hasLeafGuidance()); assertTrue("should be deflated (may change)", hr.isDeflateEnabled()); // 2) check to make sure that Ultrapeers are accepted as // Ultrapeer connections when we have enough leaves -- create this // artifially by setting the MAX_LEAVES to zero ConnectionSettings.ALLOW_WHILE_DISCONNECTED.setValue(true); fillSlots(); hr = responder.respond(up, false); assertTrue("should tell the Ultrapeer to stay an Ultrapeer", !hr.hasLeafGuidance()); assertTrue("should still be accepted as an Ultrapeer", hr.isAccepted()); assertTrue("should be deflating to leaf", hr.isDeflateEnabled()); UltrapeerSettings.MAX_LEAVES.revertToDefault(); ConnectionSettings.ALLOW_WHILE_DISCONNECTED.setValue(false); } /** * Test to make sure that incoming leaf connections are handled correctly. */ public void testRespondToIncomingLeaf() throws Exception { ConnectionSettings.PREFERENCING_ACTIVE.setValue(true); ConnectionSettings.ALLOW_WHILE_DISCONNECTED.setValue(true); ConnectionSettings.EVER_ACCEPTED_INCOMING.setValue(true); UltrapeerSettings.EVER_ULTRAPEER_CAPABLE.setValue(true); ConnectionSettings.LOCAL_IS_PRIVATE.setValue(false); assertTrue(RouterService.isSupernode()); // the ultrapeer we'll be testing against UltrapeerHandshakeResponder responder = new UltrapeerHandshakeResponder("23.3.4.5"); // 1) check to make sure that leaves are properly accepted as // leaves HandshakeResponse leaf = HandshakeResponse.createResponse(new LeafHeaders("80.45.0.1")); HandshakeResponse hr = responder.respond(leaf, false); assertTrue("should report Ultrapeer true", hr.isUltrapeer()); assertTrue("should be high degree connection", hr.isHighDegreeConnection()); assertTrue("should be an Ultrapeer query routing connection", hr.isUltrapeerQueryRoutingConnection()); assertTrue("should be deflating to leaf", hr.isDeflateEnabled()); // 2) check to make sure that leaves are rejected with X-Try-Ultrapeer // headers when we alread have enough leaves -- create this // situation artificially by setting the MAX_LEAVES to zero fillSlots(); hr = responder.respond(leaf, false); assertTrue("should have rejected the leaf: status code was: "+ hr.getStatusLine(), !hr.isAccepted()); assertTrue("should have X-Try-Ultrapeer hosts", hr.hasXTryUltrapeers()); UltrapeerSettings.MAX_LEAVES.revertToDefault(); ConnectionSettings.ALLOW_WHILE_DISCONNECTED.setValue(false); } }