You are viewing a plain text version of this content. The canonical link for it is here.
Posted to awf-commits@incubator.apache.org by jm...@apache.org on 2012/02/12 20:24:36 UTC

svn commit: r1243316 [7/8] - in /incubator/deft/sandbox/jmeehan: ./ awf-core/ awf-core/.settings/ awf-core/src/ awf-core/src/main/ awf-core/src/main/assembly/ awf-core/src/main/java/ awf-core/src/main/java/org/ awf-core/src/main/java/org/apache/ awf-co...

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpBufferedLexerTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpBufferedLexerTest.java?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpBufferedLexerTest.java (added)
+++ incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpBufferedLexerTest.java Sun Feb 12 20:24:30 2012
@@ -0,0 +1,447 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.awf.web.http;
+
+
+import java.nio.ByteBuffer;
+
+import junit.framework.Assert;
+
+import org.apache.awf.web.http.HttpBufferedLexer;
+import org.apache.awf.web.http.HttpParsingContext;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.apache.awf.web.http.HttpBufferedLexer.*;
+import static org.apache.awf.web.http.HttpParsingContext.TokenType;
+
+/**
+ * Unit tests suite for HttpBufferedLexer
+ */
+public class HttpBufferedLexerTest {
+
+    HttpBufferedLexer  lexer;
+    HttpParsingContext context;
+
+    @Before
+    public void init() {
+        lexer = new HttpBufferedLexer();
+        context = new HttpParsingContext();
+    }
+
+    @Test
+    public void testNextTokenSimpleGet() throws Exception {
+        String request = "GET /path/script.cgi HTTP/1.1\r\n\r\n";
+
+        context.setBuffer(ByteBuffer.wrap(request.getBytes()));
+
+        int res = lexer.nextToken(context);
+        Assert.assertEquals("Token GET should be found with no errors", 1, res);
+        Assert.assertEquals("GET", context.getTokenValue());
+        Assert.assertEquals(TokenType.REQUEST_METHOD, context.currentType);
+
+        res = lexer.nextToken(context);
+        Assert.assertEquals("Token uri should be found with no errors", 1, res);
+        Assert.assertEquals("/path/script.cgi", context.getTokenValue());
+        Assert.assertEquals(TokenType.REQUEST_URI, context.currentType);
+
+        res = lexer.nextToken(context);
+        Assert.assertEquals("Token protocol version should be found with no errors", 1, res);
+        Assert.assertEquals("HTTP/1.1", context.getTokenValue());
+        Assert.assertEquals(TokenType.HTTP_VERSION, context.currentType);
+
+        res = lexer.nextToken(context);
+        Assert.assertEquals("Token body should be found with no errors", 1, res);
+        Assert.assertEquals(TokenType.BODY, context.currentType);
+        Assert.assertEquals("TokenValue should be null for body", "", context.getTokenValue());
+
+    }
+
+    @Test
+    public void requestLineContainingCRLF() {
+        String request = "GET\r\n /path/script.cgi HTTP/1.1\r\n\r\n";
+
+        context.setBuffer(ByteBuffer.wrap(request.getBytes()));
+
+        int res = lexer.nextToken(context);
+        Assert.assertEquals("Token GET should be found with error", -1, res);
+    }
+
+    @Test
+    public void requestWithHeadersParsing() {
+
+        String request = "POST /path/script.cgi HTTP/1.0\r\n"
+                + "Host: localhost\r\n"
+                + "From: frog@jmarshall.com\r\n"
+                + "User-Agent: HTTPTool/1.0\r\n"
+                + "Content-Type: application/x-www-form-urlencoded\r\n"
+                + "Content-Length: 32\r\n\r\n";
+
+        context.setBuffer(ByteBuffer.wrap(request.getBytes()));
+        String[][] headers = new String[][]{{"Host", " localhost"},
+                {"From", " frog@jmarshall.com"},
+                {"User-Agent", " HTTPTool/1.0"},
+                {"Content-Type", " application/x-www-form-urlencoded"},
+                {"Content-Length", " 32"}};
+
+        int res = lexer.nextToken(context);
+        String method = context.getTokenValue();
+        res = lexer.nextToken(context);
+        String path = context.getTokenValue();
+        res = lexer.nextToken(context);
+        String protocol = context.getTokenValue();
+
+        Assert.assertEquals("POST", method);
+        Assert.assertEquals("/path/script.cgi", path);
+        Assert.assertEquals("HTTP/1.0", protocol);
+
+        for (String[] header : headers) {
+            res = lexer.nextToken(context);
+            Assert.assertEquals(1, res);
+            Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
+            Assert.assertEquals(header[0], context.getTokenValue());
+            res = lexer.nextToken(context);
+            Assert.assertEquals(1, res);
+            Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
+            Assert.assertEquals(header[1], context.getTokenValue());
+        }
+
+        res = lexer.nextToken(context);
+        Assert.assertEquals("Token body should be found with no errors", 1, res);
+        Assert.assertEquals(TokenType.BODY, context.currentType);
+        Assert.assertEquals("TokenValue should be null for body", "", context.getTokenValue());
+
+    }
+
+    @Test
+    public void requestLineWithTrailingHeaders() {
+        String request = " \r\n \r\nPOST ";
+        context.setBuffer(ByteBuffer.wrap(request.getBytes()));
+
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.REQUEST_METHOD, context.currentType);
+        Assert.assertEquals("POST", context.getTokenValue());
+    }
+
+    @Test
+    public void incompleteHeaderAfterRequestLine() {
+        String requestPart1 = "Content-";
+        String requestPart2 = "Type: application";
+        String requestPart3 = "/x-www-form-";
+        String requestPart4 = "urlencoded\r\n";
+        context.currentType = TokenType.HTTP_VERSION;
+        context.setBuffer(ByteBuffer.wrap(requestPart1.getBytes()));
+
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(0, res);
+        Assert.assertEquals(TokenType.HTTP_VERSION, context.currentType);
+        Assert.assertEquals("Content-", context.getTokenValue());
+
+        context.setBuffer(ByteBuffer.wrap(requestPart2.getBytes()));
+        res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
+        Assert.assertEquals("Content-Type", context.getTokenValue());
+
+        res = lexer.nextToken(context);
+        Assert.assertEquals(0, res);
+        Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
+        Assert.assertEquals(" application", context.getTokenValue());
+
+        context.setBuffer(ByteBuffer.wrap(requestPart3.getBytes()));
+        res = lexer.nextToken(context);
+        Assert.assertEquals(0, res);
+        Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
+        Assert.assertEquals(" application/x-www-form-", context.getTokenValue());
+
+        context.setBuffer(ByteBuffer.wrap(requestPart4.getBytes()));
+        res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
+        Assert.assertEquals(" application/x-www-form-urlencoded", context.getTokenValue());
+    }
+
+    @Test
+    public void incompleteHeaderAfterHeader() {
+        String requestPart1 = "Content-";
+        String requestPart2 = "Type: application";
+        String requestPart3 = "/x-www-form-";
+        String requestPart4 = "urlencoded\r\n";
+        context.currentType = TokenType.HEADER_VALUE;
+        context.setBuffer(ByteBuffer.wrap(requestPart1.getBytes()));
+
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(0, res);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
+        Assert.assertEquals("Content-", context.getTokenValue());
+
+        context.setBuffer(ByteBuffer.wrap(requestPart2.getBytes()));
+        res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
+        Assert.assertEquals("Content-Type", context.getTokenValue());
+
+        res = lexer.nextToken(context);
+        Assert.assertEquals(0, res);
+        Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
+        Assert.assertEquals(" application", context.getTokenValue());
+
+        context.setBuffer(ByteBuffer.wrap(requestPart3.getBytes()));
+        res = lexer.nextToken(context);
+        Assert.assertEquals(0, res);
+        Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
+        Assert.assertEquals(" application/x-www-form-", context.getTokenValue());
+
+        context.setBuffer(ByteBuffer.wrap(requestPart4.getBytes()));
+        res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
+        Assert.assertEquals(" application/x-www-form-urlencoded", context.getTokenValue());
+    }
+
+    @Test
+    public void parseMultiLineHeaders() {
+        String request = "my headervalue\r\n and so on\r\n\tand so on\r\n";
+        context.currentType = TokenType.HEADER_NAME;
+        context.setBuffer(ByteBuffer.wrap(request.getBytes()));
+
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
+        Assert.assertEquals("my headervalue", context.getTokenValue());
+
+        res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
+        Assert.assertEquals("and so on", context.getTokenValue());
+
+        res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
+        Assert.assertEquals("and so on", context.getTokenValue());
+    }
+
+    @Test
+    public void failOnMethodAboveMaxSize() {
+        StringBuilder request = getRandomString(METHOD_LENGTH + 1).append(' ');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.REQUEST_LINE, context.currentType);
+
+        request = getRandomString(METHOD_LENGTH + 1);
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.REQUEST_LINE, context.currentType);
+
+    }
+
+
+    @Test
+    public void successOnMethodAtMaxSize() {
+        StringBuilder request = getRandomString(METHOD_LENGTH).append(' ');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.REQUEST_METHOD, context.currentType);
+        Assert.assertEquals(request.deleteCharAt(METHOD_LENGTH).toString(), context.getTokenValue());
+    }
+
+    @Test
+    public void successOnUriAtMaxSize() {
+        StringBuilder request = getRandomString(URI_LENGTH).append(' ');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        context.currentType = TokenType.REQUEST_METHOD;
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.REQUEST_URI, context.currentType);
+        Assert.assertEquals(request.deleteCharAt(URI_LENGTH).toString(), context.getTokenValue());
+    }
+
+    @Test
+    public void failOnUriAboveMaxSize() {
+        StringBuilder request = getRandomString(URI_LENGTH + 1).append(' ');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        context.currentType = TokenType.REQUEST_METHOD;
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.REQUEST_METHOD, context.currentType);
+
+        request = getRandomString(URI_LENGTH + 1);
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.REQUEST_METHOD, context.currentType);
+    }
+
+    @Test
+    public void successOnVersionAtMaxSize() {
+        StringBuilder request = getRandomString(VERSION_LENGTH).append('\r');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        context.currentType = TokenType.REQUEST_URI;
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.HTTP_VERSION, context.currentType);
+        Assert.assertEquals(request.deleteCharAt(VERSION_LENGTH).toString(),
+                context.getTokenValue());
+    }
+
+    @Test
+    public void failOnVersionAboveMaxSize() {
+        StringBuilder request = getRandomString(VERSION_LENGTH + 1).append(' ');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        context.currentType = TokenType.REQUEST_URI;
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.REQUEST_URI, context.currentType);
+
+        request = getRandomString(VERSION_LENGTH + 1);
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.REQUEST_URI, context.currentType);
+    }
+
+    @Test
+    public void successOnHeaderNameAtMaxSizeFromRequestLine() {
+        StringBuilder request = getRandomString(HEADER_NAME_LENGTH).append(':');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        context.currentType = TokenType.HTTP_VERSION;
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
+        Assert.assertEquals(request.deleteCharAt(HEADER_NAME_LENGTH).toString(), context.getTokenValue());
+    }
+
+    @Test
+    public void failOnHeaderNameAboveMaxSizeFromRequestLine() {
+        StringBuilder request = getRandomString(HEADER_NAME_LENGTH + 1).append(' ');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        context.currentType = TokenType.HTTP_VERSION;
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.HTTP_VERSION, context.currentType);
+
+        request = getRandomString(HEADER_NAME_LENGTH + 1);
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.HTTP_VERSION, context.currentType);
+    }
+
+    @Test
+    public void successOnHeaderNameAtMaxSizeFromHeaderValue() {
+        StringBuilder request = getRandomString(HEADER_NAME_LENGTH).append(':');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        context.currentType = TokenType.HEADER_VALUE;
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
+        Assert.assertEquals(request.deleteCharAt(HEADER_NAME_LENGTH).toString(), context.getTokenValue());
+    }
+
+    @Test
+    public void failOnHeaderNameAboveMaxSizeFromHeaderValue() {
+        StringBuilder request = getRandomString(HEADER_NAME_LENGTH + 1).append(' ');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        context.currentType = TokenType.HEADER_VALUE;
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
+
+        request = getRandomString(HEADER_NAME_LENGTH + 1);
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
+    }
+
+    @Test
+    public void successOnHeaderValueAtMaxSize() {
+        StringBuilder request = getRandomString(HEADER_VALUE_LENGTH).append('\r');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        context.currentType = TokenType.HEADER_NAME;
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
+        Assert.assertEquals(request.deleteCharAt(HEADER_VALUE_LENGTH).toString(), context.getTokenValue());
+    }
+
+    @Test
+    public void failOnHeaderValueAboveMaxSize() {
+        StringBuilder request = getRandomString(HEADER_VALUE_LENGTH + 1).append('\r');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        context.currentType = TokenType.HEADER_NAME;
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
+
+        request = getRandomString(HEADER_NAME_LENGTH + 1);
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
+    }
+
+    @Test
+    public void successOnHeaderValueAtMaxSizeOnMultiLine() {
+        StringBuilder request = getRandomString(HEADER_VALUE_LENGTH).insert(0, '\t').append('\r');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        context.currentType = TokenType.HEADER_VALUE;
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(1, res);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
+        Assert.assertEquals(request.deleteCharAt(0).deleteCharAt(HEADER_VALUE_LENGTH).toString(), context.getTokenValue());
+    }
+
+    @Test
+    public void failOnHeaderValueAboveMaxSizeOnMultiLine() {
+        StringBuilder request = getRandomString(HEADER_VALUE_LENGTH + 1).insert(0, ' ').append('\r');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        context.currentType = TokenType.HEADER_VALUE;
+        int res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
+
+        request = getRandomString(HEADER_VALUE_LENGTH + 1).insert(0, '\t');
+        context.setBuffer(ByteBuffer.wrap(request.toString().getBytes()));
+        res = lexer.nextToken(context);
+        Assert.assertEquals(-1, res);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
+    }
+
+    /**
+     * Generate
+     *
+     * @param length
+     * @return
+     */
+    private StringBuilder getRandomString(int length) {
+
+        StringBuilder stringBuilder = new StringBuilder(length);
+        for (int i = 0; i < length; i++) {
+            stringBuilder.append('A');
+        }
+        return stringBuilder;
+    }
+
+}

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpExceptionTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpExceptionTest.java?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpExceptionTest.java (added)
+++ incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpExceptionTest.java Sun Feb 12 20:24:30 2012
@@ -0,0 +1,51 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.awf.web.http;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.awf.web.http.HttpException;
+import org.apache.awf.web.http.protocol.HttpStatus;
+import org.junit.Test;
+
+/**
+ * Test cases for {@link HttpException}.
+ */
+public class HttpExceptionTest {
+
+    @Test
+    public void testHttpException() {
+
+        HttpException exception = new HttpException(HttpStatus.SERVER_ERROR_INTERNAL_SERVER_ERROR);
+
+        assertEquals(HttpStatus.SERVER_ERROR_INTERNAL_SERVER_ERROR, exception.getStatus());
+        assertTrue(exception.getMessage().isEmpty());
+    }
+
+    @Test
+    public void testHttpExceptionWithMessage() {
+
+        HttpException exception = new HttpException(HttpStatus.CLIENT_ERROR_NOT_FOUND, "testMessage");
+
+        assertEquals(HttpStatus.CLIENT_ERROR_NOT_FOUND, exception.getStatus());
+        assertEquals("testMessage", exception.getMessage());
+    }
+}

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpProtocolTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpProtocolTest.java?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpProtocolTest.java (added)
+++ incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpProtocolTest.java Sun Feb 12 20:24:30 2012
@@ -0,0 +1,138 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.awf.web.http;
+
+import com.google.common.collect.Maps;
+
+import org.apache.awf.io.IOLoop;
+import org.apache.awf.util.Closeables;
+import org.apache.awf.web.Application;
+import org.apache.awf.web.handler.RequestHandler;
+import org.apache.awf.web.http.HttpProtocol;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+
+/**
+ *
+ * User: slemesle
+ * Date: 11/09/11
+ * Time: 12:35
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(value = {Closeables.class})
+@PowerMockIgnore("javax.management.*")
+public class HttpProtocolTest {
+
+    private IOLoop ioLoop;
+    private HttpProtocol protocol;
+    private SelectionKey key;
+    private SocketChannel socketChannel;
+
+
+    @Before
+    public void beforeTests(){
+
+        ioLoop = Mockito.mock(IOLoop.class);
+        socketChannel = Mockito.mock(SocketChannel.class);
+        key = new MySelectionKey(socketChannel);
+        PowerMockito.mockStatic(Closeables.class);
+        protocol = new HttpProtocol(ioLoop, new Application(Maps.<String, RequestHandler>newHashMap()));
+    }
+
+    @Test
+    public void testHandleReadReachEOF() throws Exception {
+
+        ByteBuffer byteBuffer = ByteBuffer.allocate(10);
+        key.attach(byteBuffer);
+
+        // See what happens when read returns -1
+        Mockito.when(socketChannel.read(byteBuffer)).thenReturn(-1);
+
+        protocol.handleRead(key);
+
+        Mockito.verify(socketChannel).read(byteBuffer);
+
+        // CloseQuietly should have been called for this channel EOF
+        PowerMockito.verifyStatic(Mockito.times(1));
+        Closeables.closeQuietly(ioLoop, socketChannel);
+    }
+
+
+    /**
+     * Since did not succeed in mocking final fields
+     * here is a short mock for the SelectionKey
+     */
+    class MySelectionKey extends SelectionKey {
+
+        SelectableChannel channel;
+
+        MySelectionKey(SelectableChannel channel) {
+            super();
+            this.channel = channel;
+        }
+
+        @Override
+        public SelectableChannel channel() {
+            return channel;
+        }
+
+        @Override
+        public Selector selector() {
+            return null;
+        }
+
+        @Override
+        public boolean isValid() {
+            return false;
+        }
+
+        @Override
+        public void cancel() {
+            // Nothing Todo
+        }
+
+        @Override
+        public int interestOps() {
+            return 0;  
+        }
+
+        @Override
+        public SelectionKey interestOps(int i) {
+            return this;
+        }
+
+        @Override
+        public int readyOps() {
+            return 0;
+        }
+    }
+}

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpRequestDispatcherTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpRequestDispatcherTest.java?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpRequestDispatcherTest.java (added)
+++ incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpRequestDispatcherTest.java Sun Feb 12 20:24:30 2012
@@ -0,0 +1,196 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.awf.web.http;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.apache.awf.annotation.Asynchronous;
+import org.apache.awf.web.handler.RequestHandler;
+import org.apache.awf.web.http.HttpException;
+import org.apache.awf.web.http.HttpRequest;
+import org.apache.awf.web.http.HttpRequestDispatcher;
+import org.apache.awf.web.http.HttpResponse;
+import org.apache.awf.web.http.protocol.HttpStatus;
+import org.apache.awf.web.http.protocol.HttpVerb;
+import org.junit.Test;
+
+/**
+ * Test cases for {@link HttpRequestDispatcher}.
+ */
+public class HttpRequestDispatcherTest {
+
+    private class TestRequestHandler extends RequestHandler {
+
+        @Override
+        public void get(HttpRequest request, HttpResponse response) {
+            response.write("get");
+        }
+
+        @Override
+        public void post(HttpRequest request, HttpResponse response) {
+            response.write("post");
+        }
+
+        @Override
+        public void head(HttpRequest request, HttpResponse response) {
+            response.write("head");
+        }
+
+        @Override
+        public void put(HttpRequest request, HttpResponse response) {
+            response.write("put");
+        }
+
+        @Override
+        public void delete(HttpRequest request, HttpResponse response) {
+            response.write("delete");
+        }
+    }
+
+    @Test
+    public void testDispatchForGet() {
+
+        RequestHandler handler = new TestRequestHandler();
+        HttpRequest request = mock(HttpRequest.class);
+        HttpResponse response = mock(HttpResponse.class);
+
+        when(request.getMethod()).thenReturn(HttpVerb.GET);
+
+        HttpRequestDispatcher.dispatch(handler, request, response);
+        verify(response, times(1)).write("get");
+    }
+
+    @Test
+    public void testDispatchForPost() {
+
+        RequestHandler handler = new TestRequestHandler();
+        HttpRequest request = mock(HttpRequest.class);
+        HttpResponse response = mock(HttpResponse.class);
+
+        when(request.getMethod()).thenReturn(HttpVerb.POST);
+
+        HttpRequestDispatcher.dispatch(handler, request, response);
+        verify(response, times(1)).write("post");
+    }
+
+    @Test
+    public void testDispatchForHead() {
+
+        RequestHandler handler = new TestRequestHandler();
+        HttpRequest request = mock(HttpRequest.class);
+        HttpResponse response = mock(HttpResponse.class);
+
+        when(request.getMethod()).thenReturn(HttpVerb.HEAD);
+
+        HttpRequestDispatcher.dispatch(handler, request, response);
+        verify(response, times(1)).write("head");
+    }
+
+    @Test
+    public void testDispatchForPut() {
+
+        RequestHandler handler = new TestRequestHandler();
+        HttpRequest request = mock(HttpRequest.class);
+        HttpResponse response = mock(HttpResponse.class);
+
+        when(request.getMethod()).thenReturn(HttpVerb.PUT);
+
+        HttpRequestDispatcher.dispatch(handler, request, response);
+        verify(response, times(1)).write("put");
+    }
+
+    @Test
+    public void testDispatchForDelete() {
+
+        RequestHandler handler = new TestRequestHandler();
+        HttpRequest request = mock(HttpRequest.class);
+        HttpResponse response = mock(HttpResponse.class);
+
+        when(request.getMethod()).thenReturn(HttpVerb.DELETE);
+
+        HttpRequestDispatcher.dispatch(handler, request, response);
+        verify(response, times(1)).write("delete");
+    }
+
+    @Test
+    public void testDispatchForOptions() {
+
+        RequestHandler handler = new TestRequestHandler();
+        HttpRequest request = mock(HttpRequest.class);
+        HttpResponse response = mock(HttpResponse.class);
+
+        when(request.getMethod()).thenReturn(HttpVerb.OPTIONS);
+
+        HttpRequestDispatcher.dispatch(handler, request, response);
+        verify(response, times(0)).write(anyString());
+    }
+
+    @Test
+    public void testDispatchForTrace() {
+
+        RequestHandler handler = new TestRequestHandler();
+        HttpRequest request = mock(HttpRequest.class);
+        HttpResponse response = mock(HttpResponse.class);
+
+        when(request.getMethod()).thenReturn(HttpVerb.TRACE);
+
+        HttpRequestDispatcher.dispatch(handler, request, response);
+        verify(response, times(0)).write(anyString());
+    }
+
+    @Test
+    public void testDispatchForConnect() {
+
+        RequestHandler handler = new TestRequestHandler();
+        HttpRequest request = mock(HttpRequest.class);
+        HttpResponse response = mock(HttpResponse.class);
+
+        when(request.getMethod()).thenReturn(HttpVerb.CONNECT);
+
+        HttpRequestDispatcher.dispatch(handler, request, response);
+        verify(response, times(0)).write(anyString());
+    }
+
+    @Test
+    public void testDispatchForHttpException() {
+
+        RequestHandler handler = new TestRequestHandler() {
+            @Override
+            @Asynchronous
+            public void get(HttpRequest request, HttpResponse response) {
+                throw new HttpException(HttpStatus.CLIENT_ERROR_BAD_REQUEST, "testMessage");
+            }
+        };
+
+        HttpRequest request = mock(HttpRequest.class);
+        HttpResponse response = mock(HttpResponse.class);
+
+        when(request.getMethod()).thenReturn(HttpVerb.GET);
+
+        HttpRequestDispatcher.dispatch(handler, request, response);
+        verify(response, times(1)).setStatus(HttpStatus.CLIENT_ERROR_BAD_REQUEST);
+        verify(response, times(1)).write("testMessage");
+        verify(response, times(1)).finish();
+    }
+}

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpRequestImplTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpRequestImplTest.java?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpRequestImplTest.java (added)
+++ incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpRequestImplTest.java Sun Feb 12 20:24:30 2012
@@ -0,0 +1,77 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.awf.web.http;
+
+import java.util.HashMap;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class HttpRequestImplTest {
+
+    @Test
+    public void testHttpRequestNoQueryString() {
+        String requestLine = "GET /foobar HTTP/1.1 ";
+        HttpRequest request = new HttpRequestImpl(requestLine, new HashMap<String, String> ());
+        Assert.assertEquals("/foobar", request.getRequestedPath());
+    }
+
+    @Test
+    public void testHttpRequestNullQueryString() {
+        String requestLine = "GET /foobar? HTTP/1.1 ";
+        HttpRequest request = new HttpRequestImpl(requestLine, new HashMap<String, String>());
+        Assert.assertEquals("/foobar", request.getRequestedPath());
+    }
+
+    @Test
+    public void testHttpRequestNullQueryStringTrailingSlash() {
+        String requestLine = "GET /foobar/? HTTP/1.1 ";
+        HttpRequest request = new HttpRequestImpl(requestLine, new HashMap<String, String>());
+        Assert.assertEquals("/foobar/", request.getRequestedPath());
+    }
+
+    @Test
+    public void doNotExpectContinueWhenBodyNotEmptyWithExpectHeader(){
+        HttpRequestImpl request = new HttpRequestImpl();
+        request.pushToHeaders("content-length", "12");
+        request.pushToHeaders("expect", "niniin");
+        request.getContentLength();
+        request.getBodyBuffer().put("12345".getBytes());
+        Assert.assertFalse("Expect continue should be false when body is submitted", request.expectContinue());
+
+    }
+
+    @Test
+    public void expectContinueWhenBodyNotNullButEmptyWithExpectHeader(){
+        HttpRequestImpl request = new HttpRequestImpl();
+        request.pushToHeaders("content-length", "12");
+        request.pushToHeaders("expect", "niniin");
+        request.getContentLength();
+        Assert.assertTrue("Expect continue should be false when body bot submitted", request.expectContinue());
+    }
+
+    @Test
+    public void expectContinueWhenBodyNullWithExpectHeader(){
+        HttpRequestImpl request = new HttpRequestImpl();
+        request.pushToHeaders("expect", "niniin");
+        request.getContentLength();
+        Assert.assertTrue("Expect continue should be false when body is submitted", request.expectContinue());
+    }
+}

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpRequestParserTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpRequestParserTest.java?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpRequestParserTest.java (added)
+++ incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/HttpRequestParserTest.java Sun Feb 12 20:24:30 2012
@@ -0,0 +1,419 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.awf.web.http;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.awf.util.HttpRequestHelper;
+import org.apache.awf.util.HttpUtil;
+import org.apache.awf.web.http.HttpRequest;
+import org.apache.awf.web.http.HttpRequestImpl;
+import org.apache.awf.web.http.HttpRequestParser;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class HttpRequestParserTest {
+
+    
+    private HttpRequestParser parser;
+
+    @Before
+    public void init(){
+        parser = new HttpRequestParser();
+    }
+
+    @Test
+    public void testDeserializeHttpGetRequest() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addHeader("Host", "127.0.0.1:8080");
+        helper.addHeader("User-Agent", "curl/7.19.5 (i386-apple-darwin10.0.0) libcurl/7.19.5 zlib/1.2.3");
+        helper.addHeader("Accept", "*/*");
+        ByteBuffer bb1 = helper.getRequestAsByteBuffer();
+
+        helper = new HttpRequestHelper();
+        helper.addHeader("Host", "127.0.0.1:8080");
+        helper.addHeader("User-Agent",
+                "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; sv-SE; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2");
+        helper.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+        helper.addHeader("Accept-Language", "sv-se,sv;q=0.8,en-us;q=0.5,en;q=0.3");
+        helper.addHeader("Accept-Encoding", "gzip,deflate");
+        helper.addHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
+        helper.addHeader("Keep-Alive", "115");
+        helper.addHeader("Connection", "keep-alve");
+        ByteBuffer bb2 = helper.getRequestAsByteBuffer();
+
+        HttpRequest request1 = parser.parseRequestBuffer(bb1);
+        HttpRequest request2 = parser.parseRequestBuffer(bb2);
+
+        assertEquals("GET / HTTP/1.1", request1.getRequestLine());
+        assertEquals("GET / HTTP/1.1", request2.getRequestLine());
+
+        assertEquals(4, request1.getHeaders().size());
+        assertEquals(9, request2.getHeaders().size());
+
+        List<String> expectedHeaderNamesInRequest1 = Arrays.asList(new String[] { "User-Agent", "Host", "Accept",
+                "From" });
+        for (String expectedHeaderName : expectedHeaderNamesInRequest1) {
+            assertTrue(request1.getHeaders().containsKey(expectedHeaderName.toLowerCase()));
+        }
+
+        List<String> expectedHeaderNamesInRequest2 = Arrays.asList(new String[] { "Host", "User-Agent", "Accept",
+                "From", "Accept-Language", "Accept-Encoding", "Accept-Charset", "Keep-Alive", "Connection" });
+        for (String expectedHeaderName : expectedHeaderNamesInRequest2) {
+            assertTrue(request2.getHeaders().containsKey(expectedHeaderName.toLowerCase()));
+        }
+
+        // TODO RS 100920 verify that the headers exist
+    }
+
+
+    @Test
+    public void testSingleGetParameter() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addGetParameter("firstname", "jim");
+
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+
+        assertEquals(1, request.getParameters().size());
+        assertEquals("jim", request.getParameter("firstname"));
+    }
+
+    @Test
+    public void testMultipleGetParameter() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addGetParameter("firstname", "jim");
+        helper.addGetParameter("lastname", "petersson");
+        helper.addGetParameter("city", "stockholm");
+
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        Map<String, Collection<String>> params = request.getParameters();
+
+        assertEquals(3, getSize(params));
+        assertEquals("jim", request.getParameter("firstname"));
+        assertEquals("petersson", request.getParameter("lastname"));
+        assertEquals("stockholm", request.getParameter("city"));
+    }
+
+    private int getSize(Map<String, Collection<String>> mmap) {
+        int size = 0;
+        for (Collection<String> values : mmap.values()) {
+            size += values.size();
+        }
+        return size;
+    }
+
+    @Test
+    public void testSingleParameterWithoutValue() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addGetParameter("firstname", null);
+
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        Map<String, Collection<String>> params = request.getParameters();
+        assertEquals(0, getSize(params));
+        assertEquals(null, request.getParameter("firstname"));
+    }
+
+    @Test
+    public void testMultipleParametersWithoutValue() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addGetParameter("firstname", null);
+        helper.addGetParameter("lastName", "");
+
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        Map<String, Collection<String>> params = request.getParameters();
+
+        assertEquals(0, getSize(params));
+        assertEquals(null, request.getParameter("firstname"));
+        assertEquals(null, request.getParameter("lastName"));
+    }
+    
+    @Test
+    public void testEncodedParametersValue() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addGetParameter("email", "name%40server");
+
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        Map<String, Collection<String>> params = request.getParameters();
+
+        assertEquals(1, getSize(params));
+        assertEquals("name@server", request.getParameter("email"));
+    }
+
+    @Test
+    public void testMultipleParametersWithAndWithoutValue() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addGetParameter("firstname", null);
+        helper.addGetParameter("lastName", "petersson");
+        helper.addGetParameter("city", "");
+        helper.addGetParameter("phoneno", "12345");
+        helper.addGetParameter("age", "30");
+
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        Map<String, Collection<String>> params = request.getParameters();
+
+        assertEquals(3, getSize(params));
+        assertEquals(null, request.getParameter("firstname"));
+        assertEquals("petersson", request.getParameter("lastName"));
+        assertEquals(null, request.getParameter("city"));
+        assertEquals("12345", request.getParameter("phoneno"));
+        assertEquals("30", request.getParameter("age"));
+    }
+
+    @Test
+    public void testSingleGetParameterMultipleValues() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addGetParameter("letters", "x");
+        helper.addGetParameter("letters", "y");
+        helper.addGetParameter("letters", "z");
+
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        Map<String, Collection<String>> params = request.getParameters();
+
+        assertEquals(3, getSize(params));
+        Collection<String> values = params.get("letters");
+        assertEquals(3, values.size());
+        assertTrue(values.contains("x"));
+        assertTrue(values.contains("y"));
+        assertTrue(values.contains("z"));
+    }
+
+    @Test
+    public void testMultipleGetParametersMultipleValues() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addGetParameter("letters", "x");
+        helper.addGetParameter("letters", "y");
+        helper.addGetParameter("letters", "z");
+        helper.addGetParameter("numbers", "23");
+        helper.addGetParameter("numbers", "54");
+        helper.addGetParameter("country", "swe");
+
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        Map<String, Collection<String>> params = request.getParameters();
+
+        assertEquals(6, getSize(params));
+        Collection<String> letters = params.get("letters");
+        Collection<String> numbers = params.get("numbers");
+        Collection<String> country = params.get("country");
+
+        assertEquals(3, letters.size());
+        assertEquals(2, numbers.size());
+        assertEquals(1, country.size());
+
+        assertTrue(letters.contains("x"));
+        assertTrue(letters.contains("y"));
+        assertTrue(letters.contains("z"));
+
+        assertTrue(numbers.contains("23"));
+        assertTrue(numbers.contains("54"));
+
+        assertTrue(country.contains("swe"));
+    }
+
+    @Test
+    public void testSingleGetParameterMultipleValuesIncludingNull() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addGetParameter("letters", "x");
+        helper.addGetParameter("letters", "y");
+        helper.addGetParameter("letters", null);
+        helper.addGetParameter("letters", "z");
+
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        Map<String, Collection<String>> params = request.getParameters();
+
+        assertEquals(3, getSize(params));
+        Collection<String> values = params.get("letters");
+        assertEquals(3, values.size());
+        assertTrue(values.contains("x"));
+        assertTrue(values.contains("y"));
+        assertTrue(values.contains("z"));
+    }
+
+    @Test
+    public void testEmptyParameters() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        Map<String, Collection<String>> params = request.getParameters();
+        assertNotNull(params);
+        assertEquals(0, getSize(params));
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testImmutableParameters() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addGetParameter("letter", "x");
+
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        Map<String, Collection<String>> params = request.getParameters();
+        params.put("not", new ArrayList<String>());
+    }
+
+    @Test
+    public void testHostVerification_exists_HTTP_1_0() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.setVersion("1.0");
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        boolean requestOk = HttpUtil.verifyRequest(request);
+        assertTrue(requestOk);
+    }
+
+    @Test
+    public void testHostVerification_nonExisting_HTTP_1_0() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.setVersion("1.0");
+        helper.removeHeader("Host");
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        boolean requestOk = HttpUtil.verifyRequest(request);
+        assertTrue(requestOk);
+    }
+
+    @Test
+    public void testHostVerification_exists_HTTP_1_1() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        boolean requestOk = HttpUtil.verifyRequest(request);
+        assertTrue(requestOk);
+    }
+
+    @Test
+    public void testHostVerification_nonExisting_HTTP_1_1() {
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.removeHeader("Host");
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+        boolean requestOk = HttpUtil.verifyRequest(request);
+        assertFalse(requestOk);
+    }
+
+    @Test
+    public void testGarbageRequest() {
+        HttpRequest request =  parser.parseRequestBuffer(ByteBuffer.wrap(new byte[] { 1, 1, 1, 1 } // garbage
+                ));
+    }
+
+    /**
+     * Ensure that header keys are converted to lower case, to facilitate
+     * case-insensitive retrieval through
+     * {@link org.apache.awf.web.http.HttpRequestImpl#getHeader(String)}.
+     */
+    @Test
+    public void testOfConvertsHeaderKeysToLowerCase() {
+
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addHeader("TESTKEY", "unimportant");
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+
+        assertFalse(request.getHeaders().containsKey("TESTKEY"));
+        assertTrue(request.getHeaders().containsKey("testkey"));
+    }
+
+    /**
+     * Ensure that the case of any header values is correctly maintained.
+     */
+    @Test
+    public void testOfMaintainsHeaderValueCase() {
+
+        String expected = "vAlUe";
+
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addHeader("TESTKEY", expected);
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+
+        String actual = request.getHeader("TESTKEY");
+        assertEquals(expected, actual);
+    }
+
+    /**
+     * Ensure that case for any key passed to the method is unimportant for its
+     * retrieval.
+     */
+    @Test
+    public void testGetHeader() {
+
+        String expected = "value";
+
+        HttpRequestHelper helper = new HttpRequestHelper();
+        helper.addHeader("TESTKEY", expected);
+        HttpRequest request = parser.parseRequestBuffer(helper.getRequestAsByteBuffer());
+
+        assertEquals(expected, request.getHeader("TESTKEY"));
+        assertEquals(expected, request.getHeader("testkey"));
+    }
+
+    @Test
+    public void testHttpRequestNoQueryString() {
+        String requestLine = "GET /foobar HTTP/1.1 ";
+        HttpRequest request = new HttpRequestImpl(requestLine, new HashMap<String, String>());
+        Assert.assertEquals("/foobar", request.getRequestedPath());
+    }
+
+    @Test
+    public void testHttpRequestNullQueryString() {
+        String requestLine = "GET /foobar? HTTP/1.1 ";
+        HttpRequest request = new HttpRequestImpl(requestLine, new HashMap<String, String>());
+        Assert.assertEquals("/foobar", request.getRequestedPath());
+    }
+
+    @Test
+    public void testHttpRequestNullQueryStringTrailingSlash() {
+        String requestLine = "GET /foobar/? HTTP/1.1 ";
+        HttpRequest request = new HttpRequestImpl(requestLine, new HashMap<String, String>());
+        Assert.assertEquals("/foobar/", request.getRequestedPath());
+    }
+
+    @Test
+    public void testNoCookies() {
+        HttpRequestHelper hrh = new HttpRequestHelper();
+        HttpRequest hr = parser.parseRequestBuffer(hrh.getRequestAsByteBuffer());
+        Assert.assertEquals(0, hr.getCookies().size());
+    }
+
+    @Test
+    public void testOneCookie() {
+        HttpRequestHelper hrh = new HttpRequestHelper();
+        hrh.addHeader("Cookie", "one=value");
+        HttpRequest hr = parser.parseRequestBuffer(hrh.getRequestAsByteBuffer());
+        Assert.assertEquals("value", hr.getCookie("one"));
+    }
+
+    @Test
+    public void testOneCookieWithoutValue() {
+        HttpRequestHelper hrh = new HttpRequestHelper();
+        hrh.addHeader("Cookie", "one=");
+        HttpRequest hr = parser.parseRequestBuffer(hrh.getRequestAsByteBuffer());
+        Assert.assertEquals("", hr.getCookie("one"));
+    }
+
+    @Test
+    public void testMultipleCookies() {
+        HttpRequestHelper hrh = new HttpRequestHelper();
+        hrh.addHeader("Cookie", "one=value;two=value2");
+        HttpRequest hr = parser.parseRequestBuffer(hrh.getRequestAsByteBuffer());
+        Assert.assertEquals("value", hr.getCookie("one"));
+        Assert.assertEquals("value2", hr.getCookie("two"));
+    }
+
+}

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/client/AsynchronousHttpClientTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/client/AsynchronousHttpClientTest.java?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/client/AsynchronousHttpClientTest.java (added)
+++ incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/client/AsynchronousHttpClientTest.java Sun Feb 12 20:24:30 2012
@@ -0,0 +1,107 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.awf.web.http.client;
+
+import static org.apache.awf.web.http.client.AsynchronousHttpClient.HTTP_VERSION;
+import static org.apache.awf.web.http.client.AsynchronousHttpClient.NEWLINE;
+import static org.apache.awf.web.http.client.AsynchronousHttpClient.USER_AGENT_HEADER;
+import static org.junit.Assert.assertEquals;
+
+import org.apache.awf.web.AsyncResult;
+import org.apache.awf.web.http.client.AsynchronousHttpClient;
+import org.apache.awf.web.http.client.Response;
+import org.apache.awf.web.http.protocol.HttpVerb;
+import org.junit.Test;
+
+/**
+ * Test cases for {@link AsynchronousHttpClient}.
+ */
+public class AsynchronousHttpClientTest {
+
+    @Test
+    public void testMakeRequestLineAndHeaders() {
+
+        AsynchronousHttpClient client = new AsynchronousHttpClient() {
+            @Override
+            protected void doFetch(AsyncResult<Response> callback, long requestStarted) {
+                // Do nothing.
+            }
+        };
+
+        client.get("http://testurl.com/path/", null);
+
+        String expected = HttpVerb.GET + " /path/ " + HTTP_VERSION;
+        expected += "Host: testurl.com" + NEWLINE + USER_AGENT_HEADER;
+        expected += NEWLINE;
+
+        String actual = client.makeRequestLineAndHeaders();
+
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testMakeRequestLineAndHeadersWithBody() {
+
+        AsynchronousHttpClient client = new AsynchronousHttpClient() {
+            @Override
+            protected void doFetch(AsyncResult<Response> callback, long requestStarted) {
+                // Do nothing.
+            }
+        };
+
+        client.post("http://testurl.com/path/", "name=value", null);
+
+        String expected = HttpVerb.POST + " /path/ " + HTTP_VERSION;
+        expected += "Host: testurl.com" + NEWLINE + USER_AGENT_HEADER;
+        expected += "Content-Type: application/x-www-form-urlencoded" + NEWLINE;
+        expected += "Content-Length: 10";
+        expected += NEWLINE + NEWLINE;
+        expected += "name=value";
+        expected += NEWLINE;
+
+        String actual = client.makeRequestLineAndHeaders();
+
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testMakeRequestLineAndHeadersWithZeroLengthBody() {
+
+        AsynchronousHttpClient client = new AsynchronousHttpClient() {
+            @Override
+            protected void doFetch(AsyncResult<Response> callback, long requestStarted) {
+                // Do nothing.
+            }
+        };
+
+        client.post("http://testurl.com/path/", "", null);
+
+        String expected = HttpVerb.POST + " /path/ " + HTTP_VERSION;
+        expected += "Host: testurl.com" + NEWLINE + USER_AGENT_HEADER;
+        expected += "Content-Type: application/x-www-form-urlencoded" + NEWLINE;
+        expected += "Content-Length: 0";
+        expected += NEWLINE + NEWLINE;
+        expected += NEWLINE;
+
+        String actual = client.makeRequestLineAndHeaders();
+
+        assertEquals(expected, actual);
+    }
+}

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/client/RequestTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/client/RequestTest.java?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/client/RequestTest.java (added)
+++ incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/client/RequestTest.java Sun Feb 12 20:24:30 2012
@@ -0,0 +1,81 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.awf.web.http.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.apache.awf.web.http.client.Request;
+import org.apache.awf.web.http.protocol.ContentType;
+import org.apache.awf.web.http.protocol.HttpVerb;
+import org.junit.Test;
+
+import com.google.common.base.Charsets;
+
+/**
+ * Test cases for {@link Request}.
+ */
+public class RequestTest {
+
+    @Test
+    public void testRequest() {
+
+        final Request request = new Request("http://testurl.com:8080", HttpVerb.POST, false, 99);
+
+        assertEquals(request.getVerb(), HttpVerb.POST);
+
+        assertEquals("http", request.getURL().getProtocol());
+        assertEquals("testurl.com", request.getURL().getHost());
+        assertEquals(8080, request.getURL().getPort());
+
+        assertEquals(false, request.isFollowingRedirects());
+        assertEquals(99, request.getMaxRedirects());
+    }
+
+    @Test(expected = RuntimeException.class)
+    public void testRequestForMalformedUrl() {
+
+        new Request("malformed", HttpVerb.POST);
+    }
+
+    @Test
+    public void testSetGetBody() {
+
+        final Request request = new Request("http://unimportant-value.com", HttpVerb.POST);
+
+        request.setBody("testContent1");
+        assertTrue(Arrays.equals("testContent1".getBytes(), request.getBody()));
+
+        request.setBody("testContent2".getBytes());
+        assertEquals("testContent2", new String(request.getBody(), Charsets.ISO_8859_1));
+    }
+
+    @Test
+    public void testSetGetContentType() {
+
+        final Request request = new Request("http://unimportant-value.com", HttpVerb.POST);
+        assertEquals(ContentType.APPLICATION_FORM_URLENCODED, request.getContentType());
+
+        request.setContentType(ContentType.MULTIPART_FORM_DATA);
+        assertEquals(ContentType.MULTIPART_FORM_DATA, request.getContentType());
+    }
+}

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/protocol/ContentTypeTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/protocol/ContentTypeTest.java?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/protocol/ContentTypeTest.java (added)
+++ incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/protocol/ContentTypeTest.java Sun Feb 12 20:24:30 2012
@@ -0,0 +1,36 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.awf.web.http.protocol;
+
+import static org.junit.Assert.assertTrue;
+
+import org.apache.awf.web.http.protocol.ContentType;
+import org.junit.Test;
+
+/**
+ * Test cases for {@link ContentType}.
+ */
+public class ContentTypeTest {
+
+    @Test
+    public void test() throws Exception {
+        assertTrue("No functionality in class to test.", true);
+    }
+}

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/protocol/HttpStatusTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/protocol/HttpStatusTest.java?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/protocol/HttpStatusTest.java (added)
+++ incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/protocol/HttpStatusTest.java Sun Feb 12 20:24:30 2012
@@ -0,0 +1,64 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.awf.web.http.protocol;
+
+import org.apache.awf.web.http.protocol.HttpStatus;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ * Test cases for {@link HttpStatus}.
+ */
+public class HttpStatusTest {
+
+    private static int STATUS_CODE_COUNT = 38;
+
+    @Test
+    public void testCount() {
+        assertEquals(STATUS_CODE_COUNT, HttpStatus.values().length);
+    }
+
+    @Test
+    public void testCode() {
+
+        for (final HttpStatus status : HttpStatus.values()) {
+            if (status.name().startsWith("SUCCESS")) {
+                assertTrue("Incorrect: " + status.name(), status.code() >= 100 && status.code() < 300);
+            } else if (status.name().startsWith("REDIRECTION")) {
+                assertTrue("Incorrect: " + status.name(), status.code() >= 300 && status.code() < 400);
+            } else if (status.name().startsWith("CLIENT_ERROR")) {
+                assertTrue("Incorrect: " + status.name(), status.code() >= 400 && status.code() < 500);
+            } else if (status.name().startsWith("SERVER_ERROR")) {
+                assertTrue("Incorrect: " + status.name(), status.code() >= 500 && status.code() < 600);
+            } else {
+                assertTrue("Unknown: " + status.name(), false);
+            }
+        }
+    }
+
+    @Test
+    public void testLine() {
+
+        for (final HttpStatus status : HttpStatus.values()) {
+            assertNotNull(status.line());
+            assertTrue("Incorrect: " + status.name(), status.line().startsWith("HTTP/1.1 " + status.code()));
+        }
+    }
+}

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/protocol/HttpVerbTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/protocol/HttpVerbTest.java?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/protocol/HttpVerbTest.java (added)
+++ incubator/deft/sandbox/jmeehan/awf-core/src/test/java/org/apache/awf/web/http/protocol/HttpVerbTest.java Sun Feb 12 20:24:30 2012
@@ -0,0 +1,37 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.awf.web.http.protocol;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.awf.web.http.protocol.HttpVerb;
+import org.junit.Test;
+
+/**
+ * Test cases for {@link HttpVerb}.
+ */
+public class HttpVerbTest {
+
+    @Test
+    public void testHttpVerb() {
+
+        assertEquals(8, HttpVerb.values().length);
+    }
+}

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/resources/f4_impact_1_original.jpg
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/resources/f4_impact_1_original.jpg?rev=1243316&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/deft/sandbox/jmeehan/awf-core/src/test/resources/f4_impact_1_original.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/resources/n792205362_2067.jpg
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/resources/n792205362_2067.jpg?rev=1243316&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/deft/sandbox/jmeehan/awf-core/src/test/resources/n792205362_2067.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/deft/sandbox/jmeehan/awf-core/src/test/resources/test.txt
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-core/src/test/resources/test.txt?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-core/src/test/resources/test.txt (added)
+++ incubator/deft/sandbox/jmeehan/awf-core/src/test/resources/test.txt Sun Feb 12 20:24:30 2012
@@ -0,0 +1 @@
+test.txt
\ No newline at end of file

Added: incubator/deft/sandbox/jmeehan/awf-example-gossip/.classpath
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-example-gossip/.classpath?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-example-gossip/.classpath (added)
+++ incubator/deft/sandbox/jmeehan/awf-example-gossip/.classpath Sun Feb 12 20:24:30 2012
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

Added: incubator/deft/sandbox/jmeehan/awf-example-gossip/.project
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-example-gossip/.project?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-example-gossip/.project (added)
+++ incubator/deft/sandbox/jmeehan/awf-example-gossip/.project Sun Feb 12 20:24:30 2012
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>awf-example-gossip</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+	</natures>
+</projectDescription>

Added: incubator/deft/sandbox/jmeehan/awf-example-gossip/.settings/org.eclipse.jdt.core.prefs
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-example-gossip/.settings/org.eclipse.jdt.core.prefs?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-example-gossip/.settings/org.eclipse.jdt.core.prefs (added)
+++ incubator/deft/sandbox/jmeehan/awf-example-gossip/.settings/org.eclipse.jdt.core.prefs Sun Feb 12 20:24:30 2012
@@ -0,0 +1,6 @@
+#Sun Feb 12 15:46:01 GMT 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5

Added: incubator/deft/sandbox/jmeehan/awf-example-gossip/.settings/org.eclipse.m2e.core.prefs
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-example-gossip/.settings/org.eclipse.m2e.core.prefs?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-example-gossip/.settings/org.eclipse.m2e.core.prefs (added)
+++ incubator/deft/sandbox/jmeehan/awf-example-gossip/.settings/org.eclipse.m2e.core.prefs Sun Feb 12 20:24:30 2012
@@ -0,0 +1,5 @@
+#Sun Feb 12 15:42:01 GMT 2012
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1

Added: incubator/deft/sandbox/jmeehan/awf-example-gossip/README
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-example-gossip/README?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-example-gossip/README (added)
+++ incubator/deft/sandbox/jmeehan/awf-example-gossip/README Sun Feb 12 20:24:30 2012
@@ -0,0 +1,27 @@
+A "demo framework" for building a decentralized gossip based distributed system with accrual failure 
+detection. It's also an implementation of: The Phi Accrual Failure Detector[1] and Amazon's paper on Gossip[2].
+
+[1] http://ddg.jaist.ac.jp/pub/HDY+04.pdf
+[2] http://www.cs.cornell.edu/home/rvr/papers/flowgossip.pdf
+
+External Dependencies needed for this example, not included in the AWF distribution:
+json-simple ("A simple Java toolkit for JSON") http://code.google.com/p/json-simple/ (Apache License 2.0)
+
+Usage:
+
+There are two configuration points (per node), 'seed' and 'address' you need to change before you are ready to start 
+your cluster.
+They are located in the MessagingService class. The seed should be a stable node that new nodes will use for bootstrapping 
+into the existing cluster. The address is you local ip and port that other nodes in the cluster will connect to.
+Your seed will have seed == address (that is how a seed is defined). 
+
+Example 1.
+A two node cluster, running on the same machine
+Node A (seed node). seed = 127.0.0.1:14922, address = 127.0.0.1:14922 
+Node B. seed = 127.0.0.1:14922, address = 127.0.0.1:14923
+
+Example 2
+A three node cluster, running on three different machines
+Node A (seed node). seed = 192.168.0.1:14922, address = 192.168.0.1:14922 
+Node B. seed = 192.168.0.1:14922, address = 192.168.0.2:14923
+Node C. seed = 192.168.0.1:14922, address = 192.168.0.3:14924

Added: incubator/deft/sandbox/jmeehan/awf-example-gossip/pom.xml
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-example-gossip/pom.xml?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-example-gossip/pom.xml (added)
+++ incubator/deft/sandbox/jmeehan/awf-example-gossip/pom.xml Sun Feb 12 20:24:30 2012
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+	<!--
+	     		Licensed to the Apache Software Foundation (ASF) under one or more
+		contributor license agreements. See the NOTICE file distributed with
+		this work for additional information regarding copyright ownership.
+		The ASF licenses this file to You under the Apache License, Version
+		2.0 (the "License"); you may not use this file except in compliance
+		with the License. You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0 Unless required by
+		applicable law or agreed to in writing, software distributed under the
+		License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+		CONDITIONS OF ANY KIND, either express or implied. See the License for
+		the specific language governing permissions and limitations under the
+		License.
+	-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>org.apache.awf</groupId>
+		<artifactId>awf-parent</artifactId>
+		<version>0.4.0-SNAPSHOT</version>
+		<relativePath>../awf-parent</relativePath>
+	</parent>
+	<artifactId>awf-example-gossip</artifactId>
+
+	<name>Apache AWF Gossip Server Example</name>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.awf</groupId>
+			<artifactId>awf-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.googlecode.json-simple</groupId>
+			<artifactId>json-simple</artifactId>
+			<scope>compile</scope>
+		</dependency>
+	</dependencies>
+</project>
+

Added: incubator/deft/sandbox/jmeehan/awf-example-gossip/src/main/java/org/apache/awf/example/gossip/FailureDetector.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/jmeehan/awf-example-gossip/src/main/java/org/apache/awf/example/gossip/FailureDetector.java?rev=1243316&view=auto
==============================================================================
--- incubator/deft/sandbox/jmeehan/awf-example-gossip/src/main/java/org/apache/awf/example/gossip/FailureDetector.java (added)
+++ incubator/deft/sandbox/jmeehan/awf-example-gossip/src/main/java/org/apache/awf/example/gossip/FailureDetector.java Sun Feb 12 20:24:30 2012
@@ -0,0 +1,111 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.awf.example.gossip;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+/**
+ *  Java implementation of 'The Phi Accrual Failure Detector' by Hayashibara et al.
+ * 
+ *  Failure detection is the process of determining which nodes in a distributed fault-tolerant system have failed.
+ *  Original Phi Accrual Failure Detection paper: http://ddg.jaist.ac.jp/pub/HDY+04.pdf
+ *
+ *  A low threshold is prone to generate many wrong suspicions but ensures a quick detection in the event of a real crash.
+ *  Conversely, a high threshold generates fewer mistakes but needs more time to detect actual crashes""" 
+ *
+ *  (Original (python) version by Brandon Williams (github.com/driftx), modified by Roger Schildmeijer 
+ *  (github.com/rchildmeijer))
+ */
+
+public class FailureDetector {
+	
+	private static final int MAX_SAMPLE_SIZE = 1000;
+	
+	/**
+	 * 1 = 10% error rate, 2 = 1%, 3 = 0.1%.., (eg threshold=3. no heartbeat for >6s => node marked as dead
+	 */
+	private static final int THRESHOLD = 3; 
+	
+	private final Map<String, List<Long>> intervals = Maps.newHashMap();
+	private final Map<String, Map<String, Long>> hosts = Maps.newHashMap();
+	private final Map<String, Long> timestamps = Maps.newHashMap();
+
+	/**
+	 * Called when host has indicated being alive (aka heartbeat) 
+	 * @param host format = "ip:port", eg. "192.168.0.1:14922"
+	 */
+	public void heartbeat(String host) {
+		if (!timestamps.containsKey(host)) {
+			timestamps.put(host, System.currentTimeMillis());
+			intervals.put(host, new LinkedList<Long>());
+			hosts.put(host, new HashMap<String, Long>());
+		} else {
+			long now = System.currentTimeMillis();
+			long interval = now - timestamps.get(host);
+			timestamps.put(host, now);
+			intervals.get(host).add(interval);
+			if (intervals.get(host).size() > MAX_SAMPLE_SIZE) {
+				int size = intervals.get(host).size(); 
+				intervals.get(host).remove(size - 1);
+			}
+			if (intervals.get(host).size() > 1) {
+				long numerator = sum(intervals.get(host));
+				double denominator = intervals.get(host).size();
+				hosts.get(host).put("mean", (long) (numerator / denominator));
+			}
+			
+		}
+	}
+	
+	private double probability(String host, long timestamp) {
+		double exponent = -1.0 * timestamp / hosts.get(host).get("mean");
+		return 1 - (1.0 - Math.pow(Math.E, exponent));
+	}
+	
+	public double phi(String host) {
+		Map<String, Long> means = hosts.get(host);
+		if (/*means == null || */means.isEmpty()) {
+			return 0.0;
+		}
+		long timestamp = System.currentTimeMillis();
+		long diff = timestamp - timestamps.get(host);
+		double prob = probability(host, diff);
+		if (Double.isNaN(prob)) {	// is isNaN correct? is isZero would be more correct
+			return Math.pow(1, -128);
+		}
+		return -1 * Math.log10(prob);
+	}
+	
+	public boolean isAlive(String host) { return phi(host) < THRESHOLD; }
+	
+	public boolean isDead(String host) { return !isAlive(host); }
+	
+	private Long sum(List<Long> values) {
+		long sum = 0;
+		for (Long value : values) sum += value;
+		return sum;
+	}
+	
+}