package edu.washington.cs.oneswarm.f2f.servicesharing; import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.logging.Logger; import org.gudy.azureus2.core3.util.DirectByteBuffer; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; import com.aelitis.azureus.core.networkmanager.NetworkConnection; import com.aelitis.azureus.core.networkmanager.NetworkManager; import com.aelitis.azureus.core.networkmanager.impl.tcp.ProtocolEndpointTCP; import com.aelitis.azureus.ui.UIFunctionsManager; import edu.washington.cs.oneswarm.f2f.Friend; import edu.washington.cs.oneswarm.f2f.messaging.OSF2FHashSearch; import edu.washington.cs.oneswarm.f2f.messaging.OSF2FHashSearchResp; import edu.washington.cs.oneswarm.f2f.messaging.OSF2FMessage; import edu.washington.cs.oneswarm.f2f.messaging.OSF2FMessageEncoder; import edu.washington.cs.oneswarm.f2f.network.FriendConnection; import edu.washington.cs.oneswarm.f2f.network.QueueManager; import edu.washington.cs.oneswarm.f2f.network.SearchManager; import edu.washington.cs.oneswarm.test.integration.ServiceSharingClientTest; import edu.washington.cs.oneswarm.test.util.MessageStreamDecoderTestImpl; import edu.washington.cs.oneswarm.test.util.OneSwarmTestBase; import edu.washington.cs.oneswarm.test.util.TestUtils; /** * Tests ServiceConnections, verifying that data put into its NetworkConnection * makes its way to at least one of the connection endpoints. * * @author Krysta * */ public class ClientServiceConnectionTest extends OneSwarmTestBase { private static Logger logger = Logger.getLogger(ServiceSharingClientTest.class.getName()); private final static Random random = new Random(12345); /* The number of friend connections to create. */ private final static int NUM_FRIENDS = 2; /* The various layers of data-handling */ private static ServiceConnection clientConn; private static NetworkConnection netConn; private static List<FriendConnection> friends; private static MessageStreamDecoderTestImpl decoder; @Before public void setupLogging() { logFinest(logger); logFinest(ServiceSharingLoopback.logger); logFinest(ServiceSharingManager.logger); logFinest(ServiceChannelEndpoint.logger); logFinest(SearchManager.logger); } @Test public void testClientService() throws Exception { /* * Verify that data put into the network connection from ClientServiceConnection * makes its way to exactly one of its friend channels * * Test plan: * * Create a ClientServiceConnection with NUM_FRIEND FriendConnections * * Have the service connection's network connection retrieve a message * * Verify that exactly one friend added the message to its outgoing queue */ try { setupConnections(); // Send a single byte sendData(new byte[] {'a'}); // Send random bytes byte[] randomData = new byte[100]; random.nextBytes(randomData); sendData(randomData); } catch (Exception e) { e.printStackTrace(); logger.severe(e.toString()); fail(); } finally { logger.info("End testClientService()"); } } // Construct all the objects involved in handling data - NetworkConnection, // ClientServiceConnection, FriendConnections, etc. private static void setupConnections() { decoder = new MessageStreamDecoderTestImpl(); ProtocolEndpointTCP tcpEndpoint = new ProtocolEndpointTCP(null); netConn = NetworkManager.getSingleton().createConnection( tcpEndpoint.getConnectionEndpoint(), new OSF2FMessageEncoder(), decoder, false, false, null); clientConn = new ServiceConnection(true, (short) 0, netConn); friends = new ArrayList<FriendConnection>(); QueueManager qMgr = new QueueManager(); for (int i = 0; i < NUM_FRIENDS; i++) { Friend remoteFriend = new Friend("", "Remote " + i, null, false); FriendConnection friend = FriendConnection.createStubForTests(qMgr, netConn, remoteFriend); friends.add(friend); ServiceChannelEndpoint ep = new ServiceChannelEndpoint(friend, new OSF2FHashSearch( (byte) 0, 0, 0), new OSF2FHashSearchResp((byte) 0, 0, 0, 0), true); clientConn.addChannel(ep); } } private static void sendData(byte[] origData) throws IOException { // Put some data into the network // This is simulated by passing data to our mock decoder and telling // the network connection to receive incoming data decoder.setData(origData); int amt = netConn.getIncomingMessageQueue().receiveFromTransport(10); // Verify that the network connection received the correct number of // bytes (mainly this is a sanity check of our mock decoder)\ assertEquals(origData.length, amt, "Decoder returned incorrect number of bytes"); // Verify that exactly the original data went to exactly one friend int channelsEntered = 0; for (FriendConnection friend : friends) { OSF2FMessage msg = friend.getLastMessageQueued(); if (msg == null || msg.getData().length < 2) continue; DirectByteBuffer finalData = msg.getData()[1]; if (origData.length == finalData.remaining((byte) 0)) { boolean match = true; for (int i = 0; i < origData.length; i++) match = match && (origData[i] == finalData.get((byte) 0)); if (match) channelsEntered++; } } assertEquals(1, channelsEntered, "Data not put into any channel or put into too many channels"); } @AfterClass public static void tearDownClass() throws Exception { // Quit OneSwarm if (UIFunctionsManager.getUIFunctions() != null) { UIFunctionsManager.getUIFunctions().requestShutdown(); } } /** Boilerplate code for running as executable. */ public static void main(String[] args) throws Exception { TestUtils.swtCompatibleTestRunner(ClientServiceConnectionTest.class); } }