package com.limegroup.gnutella.handshaking; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Properties; import junit.framework.Test; import com.limegroup.gnutella.connection.ReadBufferChannel; import com.limegroup.gnutella.util.BaseTestCase; public class ReadHandshakeStateTest extends BaseTestCase { public ReadHandshakeStateTest(String name) { super(name); } public static Test suite() { return buildTestSuite(ReadHandshakeStateTest.class); } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } public void testSimpleProcess() throws Exception { String testString = "FIRST LINE\r\n" + "Header1: Value1\r\n" + "Header2: Value2\r\n" + "\r\n"; ByteBuffer buffer = ByteBuffer.wrap(testString.getBytes()); ReadBufferChannel channel = new ReadBufferChannel(buffer); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); ReadHandshakeTester tester = new ReadHandshakeTester(support); assertFalse(tester.process(channel, scratch)); assertTrue(tester.isProcessedConnectLine()); assertTrue(tester.isProcessedHeaders()); assertEquals("FIRST LINE", tester.getConnectLine()); assertEquals("", tester.getCurrentHeader()); assertTrue(tester.isDoneConnect()); Properties props = support.getReadHandshakeResponse().props(); assertEquals(2, props.size()); assertEquals("Value1", props.get("Header1")); assertEquals("Value2", props.get("Header2")); assertFalse(tester.isWriting()); assertTrue(tester.isReading()); } public void testComplexProcess() throws Exception { String testString = "FIRST LINE\r\n" + "Header1: Value1\r\n" + "Header2: Value2\r\n" + "UnknownData\r\n" + "\r\n" + "Extra Data Leftover"; ByteBuffer buffer = ByteBuffer.wrap(testString.getBytes()); ReadBufferChannel channel = new ReadBufferChannel(buffer); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); ReadHandshakeTester tester = new ReadHandshakeTester(support); buffer.limit("FIRS".length()); assertTrue(tester.process(channel, scratch)); assertFalse(tester.isProcessedConnectLine()); assertFalse(tester.isProcessedHeaders()); assertEquals("FIRS", tester.getCurrentHeader()); assertFalse(tester.isDoneConnect()); buffer.limit("FIRST LINE\r\n".length()); assertTrue(tester.process(channel, scratch)); assertTrue(tester.isProcessedConnectLine()); assertFalse(tester.isProcessedHeaders()); assertEquals("", tester.getCurrentHeader()); assertEquals("FIRST LINE", tester.getConnectLine()); assertTrue(tester.isDoneConnect()); buffer.limit("FIRST LINE\r\nHeader1: Value1".length()); assertTrue(tester.process(channel, scratch)); assertFalse(tester.isProcessedHeaders()); assertEquals("Header1: Value1", tester.getCurrentHeader()); assertEquals(0, support.getReadHandshakeResponse().props().size()); buffer.limit("FIRST LINE\r\nHeader1: Value1\r\n".length()); assertTrue(tester.process(channel, scratch)); assertFalse(tester.isProcessedHeaders()); assertEquals("", tester.getCurrentHeader()); assertEquals(1, support.getReadHandshakeResponse().props().size()); assertEquals("Value1", support.getReadHandshakeResponse().props().get("Header1")); buffer.limit("FIRST LINE\r\nHeader1: Value1\r\nHeader2: Value2\r\nUnknownData\r\n".length()); assertTrue(tester.process(channel, scratch)); assertFalse(tester.isProcessedHeaders()); assertEquals("", tester.getCurrentHeader()); assertEquals(2, support.getReadHandshakeResponse().props().size()); assertEquals("Value1", support.getReadHandshakeResponse().props().get("Header1")); assertEquals("Value2", support.getReadHandshakeResponse().props().get("Header2")); buffer.limit(testString.length()); assertFalse(tester.process(channel, scratch)); assertTrue(tester.isProcessedHeaders()); assertEquals("", tester.getCurrentHeader()); assertEquals(2, support.getReadHandshakeResponse().props().size()); assertEquals("Value1", support.getReadHandshakeResponse().props().get("Header1")); assertEquals("Value2", support.getReadHandshakeResponse().props().get("Header2")); assertEquals("Extra Data Leftover".length(), scratch.position()); scratch.flip(); assertEquals("Extra Data Leftover", new String(scratch.array(), 0, scratch.limit())); } public void testEOF() throws Exception { String testString = "FIRST LINE\r\n" + "Header1: Value1\r\n" + "Header2: Value2\r\n"; ByteBuffer buffer = ByteBuffer.wrap(testString.getBytes()); ReadBufferChannel channel = new ReadBufferChannel(buffer, true); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); ReadHandshakeTester tester = new ReadHandshakeTester(support); try { tester.process(channel, scratch); fail("should have IOXd"); } catch(IOException iox) { assertEquals("EOF", iox.getMessage()); } assertTrue(tester.isProcessedConnectLine()); assertFalse(tester.isProcessedHeaders()); Properties props = support.getReadHandshakeResponse().props(); assertEquals(2, props.size()); assertEquals("Value1", props.get("Header1")); assertEquals("Value2", props.get("Header2")); } public void testReadRequestStateProcessConnectLineSucceeds() throws Exception { ReadBufferChannel channel = new ReadBufferChannel("GNUTELLA CONNECT/0.6\r\n".getBytes()); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); HandshakeState state = new ReadHandshakeState.ReadRequestState(support); assertTrue(state.process(channel, scratch)); } public void testReadRequestStateProcessConnectLineFails() throws Exception { ReadBufferChannel channel = new ReadBufferChannel("GNUTELLA CONNECT/0.5\r\n".getBytes()); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); HandshakeState state = new ReadHandshakeState.ReadRequestState(support); try { state.process(channel, scratch); fail("should have IOXd"); } catch(IOException iox) { assertEquals("not a valid connect string!", iox.getMessage()); } } public void testReadRequestStateProcessAbsurdConnectLine() throws Exception { ReadBufferChannel channel = new ReadBufferChannel("HTTP/1.1 GET\r\n".getBytes()); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); HandshakeState state = new ReadHandshakeState.ReadRequestState(support); try { state.process(channel, scratch); fail("should have IOXd"); } catch(IOException iox) { assertEquals("not a valid connect string!", iox.getMessage()); } } public void testReadRequestStateProcessNewerConnectLine() throws Exception { ReadBufferChannel channel = new ReadBufferChannel("GNUTELLA CONNECT/0.7\r\n".getBytes()); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); HandshakeState state = new ReadHandshakeState.ReadRequestState(support); assertTrue(state.process(channel, scratch)); } public void testReadResponseStateProcessConnectLineSucceeds() throws Exception { ReadBufferChannel channel = new ReadBufferChannel("GNUTELLA/0.6 200 OK\r\n".getBytes()); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); HandshakeState state = new ReadHandshakeState.ReadResponseState(support); assertTrue(state.process(channel, scratch)); } public void testReadResponseStateProcessConnectLineSucceedsEvenWhenBadCode() throws Exception { ReadBufferChannel channel = new ReadBufferChannel("GNUTELLA/0.6 400 Failed\r\n".getBytes()); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); HandshakeState state = new ReadHandshakeState.ReadResponseState(support); assertTrue(state.process(channel, scratch)); } public void testReadResponseStateProcessConnectLineFailsBadVersion() throws Exception { ReadBufferChannel channel = new ReadBufferChannel("GNUTELLA/0.5\r\n".getBytes()); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); HandshakeState state = new ReadHandshakeState.ReadResponseState(support); try { state.process(channel, scratch); fail("should have IOXd"); } catch(IOException iox) { assertEquals("Bad connect string", iox.getMessage()); } } public void testReadResponseStateProcessAbsurdConnectLine() throws Exception { ReadBufferChannel channel = new ReadBufferChannel("HTTP/1.1 200 OK\r\n".getBytes()); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); HandshakeState state = new ReadHandshakeState.ReadResponseState(support); try { state.process(channel, scratch); fail("should have IOXd"); } catch(IOException iox) { assertEquals("Bad connect string", iox.getMessage()); } } public void testReadResponseStateProcessHeadersSucceeds() throws Exception { ReadBufferChannel channel = new ReadBufferChannel("GNUTELLA/0.6 200 OK\r\n\r\n".getBytes()); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); HandshakeState state = new ReadHandshakeState.ReadResponseState(support); assertFalse(state.process(channel, scratch)); } public void testReadResponseStateProcessHeadersBadCodeFails() throws Exception { ReadBufferChannel channel = new ReadBufferChannel("GNUTELLA/0.6 303 Failed\r\n\r\n".getBytes()); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); HandshakeState state = new ReadHandshakeState.ReadResponseState(support); try { state.process(channel, scratch); fail("should have failed!"); } catch(NoGnutellaOkException ngok) { assertEquals(303, ngok.getCode()); } } public void testReadResponseStateProcessConnectLineCrawler() throws Exception { ReadBufferChannel channel = new ReadBufferChannel("GNUTELLA/0.6\r\n".getBytes()); ByteBuffer scratch = ByteBuffer.allocate(2048); HandshakeSupport support = new HandshakeSupport("127.0.0.1"); support.processReadHeader("Crawler: 0.1"); HandshakeState state = new ReadHandshakeState.ReadResponseState(support); try { state.process(channel, scratch); fail("should have IOXd"); } catch(IOException iox) { assertEquals("crawler", iox.getMessage()); } } private static class ReadHandshakeTester extends ReadHandshakeState { private boolean processedConnectLine; private boolean processedHeaders; ReadHandshakeTester(HandshakeSupport support) { super(support); } protected void processConnectLine() throws IOException { this.processedConnectLine = true; } protected void processHeaders() throws IOException { this.processedHeaders = true; } public boolean isProcessedConnectLine() { return processedConnectLine; } public boolean isProcessedHeaders() { return processedHeaders; } public String getConnectLine() { return connectLine; } public String getCurrentHeader() { return currentHeader.toString(); } public boolean isDoneConnect() { return doneConnect; } } }