incubator-deft-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sleme...@apache.org
Subject svn commit: r1175622 - in /incubator/deft/sandbox/src: main/java/org/apache/deft/io/ main/java/org/apache/deft/web/ main/java/org/apache/deft/web/http/ test/java/org/apache/deft/web/ test/java/org/apache/deft/web/http/
Date Sun, 25 Sep 2011 23:21:31 GMT
Author: slemesle
Date: Sun Sep 25 23:21:31 2011
New Revision: 1175622

URL: http://svn.apache.org/viewvc?rev=1175622&view=rev
Log:
First multi-thread test in HttpServer
Improve new Http parser with length control and JavaDoc
Ensure IOLoop get stopped when server stops in multi-thread context

Modified:
    incubator/deft/sandbox/src/main/java/org/apache/deft/io/IOLoop.java
    incubator/deft/sandbox/src/main/java/org/apache/deft/web/HttpServer.java
    incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpBufferedLexer.java
    incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpParsingContext.java
    incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpRequestImpl.java
    incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpRequestParser.java
    incubator/deft/sandbox/src/test/java/org/apache/deft/web/DeftSystemTest.java
    incubator/deft/sandbox/src/test/java/org/apache/deft/web/HttpServerTest.java
    incubator/deft/sandbox/src/test/java/org/apache/deft/web/http/HttpBufferedLexerTest.java

Modified: incubator/deft/sandbox/src/main/java/org/apache/deft/io/IOLoop.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/apache/deft/io/IOLoop.java?rev=1175622&r1=1175621&r2=1175622&view=diff
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/apache/deft/io/IOLoop.java (original)
+++ incubator/deft/sandbox/src/main/java/org/apache/deft/io/IOLoop.java Sun Sep 25 23:21:31 2011
@@ -19,8 +19,6 @@
  */
 package org.apache.deft.io;
 
-import static com.google.common.collect.Collections2.transform;
-
 import java.io.IOException;
 import java.nio.channels.CancelledKeyException;
 import java.nio.channels.ClosedChannelException;
@@ -34,6 +32,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import org.apache.deft.io.callback.CallbackManager;
 import org.apache.deft.io.callback.JMXDebuggableCallbackManager;
 import org.apache.deft.io.timeout.JMXDebuggableTimeoutManager;
@@ -43,10 +44,7 @@ import org.apache.deft.util.MXBeanUtil;
 import org.apache.deft.web.AsyncCallback;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
+import static com.google.common.collect.Collections2.transform;
 
 public class IOLoop implements IOLoopMXBean {
 
@@ -234,4 +232,12 @@ public class IOLoop implements IOLoopMXB
         });
         return Lists.newLinkedList(readables);
     }
+
+    /**
+     * Checks wether this IOLoop is running or not
+     * @return
+     */
+    public boolean isRunning() {
+        return running;
+    }
 }

Modified: incubator/deft/sandbox/src/main/java/org/apache/deft/web/HttpServer.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/apache/deft/web/HttpServer.java?rev=1175622&r1=1175621&r2=1175622&view=diff
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/apache/deft/web/HttpServer.java (original)
+++ incubator/deft/sandbox/src/main/java/org/apache/deft/web/HttpServer.java Sun Sep 25 23:21:31 2011
@@ -19,13 +19,7 @@
  */
 package org.apache.deft.web;
 
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.ServerSocketChannel;
-import java.util.List;
-import java.util.Map;
-
+import com.google.common.collect.Lists;
 import org.apache.deft.configuration.AnnotationsScanner;
 import org.apache.deft.configuration.Configuration;
 import org.apache.deft.io.IOLoop;
@@ -35,7 +29,13 @@ import org.apache.deft.web.http.HttpProt
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Lists;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ServerSocketChannel;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
 
 public class HttpServer {
 
@@ -49,11 +49,13 @@ public class HttpServer {
 
     private final Application application;
 
+
     public HttpServer(Configuration configuration) {
 
         application = createApplication(configuration.getHandlerPackage());
         application.setStaticContentDir(configuration.getStaticDirectory());
         application.setConfiguration(configuration);
+        
     }
 
     protected Application createApplication(String packageName) {
@@ -103,6 +105,8 @@ public class HttpServer {
     }
 
     public void start(int numThreads) {
+
+        final CountDownLatch loopsLatch = new CountDownLatch(numThreads);
         for (int i = 0; i < numThreads; i++) {
             final IOLoop ioLoop = new IOLoop();
             ioLoops.add(ioLoop);
@@ -112,22 +116,41 @@ public class HttpServer {
                 @Override
                 public void run() {
                     registerHandler(ioLoop, protocol);
+                    loopsLatch.countDown();
                     ioLoop.start();
                 }
             }).start();
         }
+        try {
+            loopsLatch.await();
+        } catch (InterruptedException e) {
+            logger.error("Interrupted while waiting for all IOLoop to start", e);
+        }
     }
 
     /**
      * Unbinds the port and shutdown the HTTP server
+     * using a callback to execute the stop from the IOLoop thread
+     *
      */
     public void stop() {
         logger.debug("Stopping HTTP server");
-        for (IOLoop ioLoop : ioLoops) {
-            // TODO RS 110527 Should probably do this in each IOLoop through an
-            // AsyncCallback
-            // (hint: ioloop.addCallback(..))
-            Closeables.closeQuietly(ioLoop, serverChannel);
+        final CountDownLatch loopsLatch = new CountDownLatch(ioLoops.size());
+        for (final IOLoop ioLoop : ioLoops) {
+            // Use a callback to stop the loops from theire Threads
+            ioLoop.addCallback(new AsyncCallback(){
+                @Override
+                public void onCallback() {
+                    Closeables.closeQuietly(ioLoop, serverChannel);
+                    ioLoop.stop();
+                    loopsLatch.countDown();
+                }
+            });
+        }
+        try {
+            loopsLatch.await();
+        } catch (InterruptedException e) {
+            logger.error("Interrupted while waiting for all IOLoop to stop",e);
         }
     }
 
@@ -136,4 +159,11 @@ public class HttpServer {
         );
     }
 
+    /**
+     * Added for test purpose 
+     * @return
+     */
+    protected List<IOLoop> getIoLoops(){
+        return ioLoops;
+    }
 }

Modified: incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpBufferedLexer.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpBufferedLexer.java?rev=1175622&r1=1175621&r2=1175622&view=diff
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpBufferedLexer.java (original)
+++ incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpBufferedLexer.java Sun Sep 25 23:21:31 2011
@@ -19,8 +19,6 @@
  */
 package org.apache.deft.web.http;
 
-import java.nio.ByteBuffer;
-
 /**
  * Lexer class responsible for lexing an HTTP stream into tokens.
  * The tokens are composed of Method, URI, Protocol version, Header name and header value.
@@ -38,6 +36,9 @@ public class HttpBufferedLexer {
     static final int LINE_MAX_SIZE = 500;
 
 
+    /**
+     * Use ' ' as separator and forbids CR / LF
+     */
     static final StopChars SP_SEPARATOR = new StopChars() {
 
         public boolean isSeparator(int ptr) {
@@ -50,6 +51,9 @@ public class HttpBufferedLexer {
         }
     };
 
+    /**
+     * Use CR or LF as separator and forbids nothing
+     */
     static final StopChars CRLF_SEPARATOR = new StopChars() {
 
         public boolean isSeparator(int ptr) {
@@ -61,6 +65,9 @@ public class HttpBufferedLexer {
         }
     };
 
+    /**
+     * Use ':' as separator and forbids CR or LF
+     */
     static final StopChars HEADER_NAME_SEPARATOR = new StopChars() {
 
         public boolean isSeparator(int ptr) {
@@ -71,8 +78,14 @@ public class HttpBufferedLexer {
             return ptr == CR || ptr == LF;
         }
     };
-	
-	private ErrorStatus status = ErrorStatus.OK;
+
+    static final int METHOD_LENGTH = 7;
+    static final int URI_LENGTH = 255;
+    static final int VERSION_LENGTH = 10;
+    static final int HEADER_NAME_LENGTH = 30;
+    static final int HEADER_VALUE_LENGTH = 300;
+
+    private ErrorStatus status = ErrorStatus.OK;
 	
 	enum ErrorStatus {
 		OK,
@@ -89,12 +102,13 @@ public class HttpBufferedLexer {
      */
 	public int nextToken(HttpParsingContext context){
         int res = -1;
+        context.clearTokenBuffer(); // Clean the token buffer if we start a new token akka last token was complete
 
         switch (context.currentType){
             case REQUEST_LINE: { // read the first token of the request line METHOD
                 if (skipWhiteSpaceAndLine(context)){
                     // Get method token
-                    res = nextWord(context, HttpParsingContext.TokenType.REQUEST_METHOD, SP_SEPARATOR);
+                    res = nextWord(context, HttpParsingContext.TokenType.REQUEST_METHOD, SP_SEPARATOR, METHOD_LENGTH);
                     
                 }else{ // EOS reached with no data 
                     return 0;
@@ -103,17 +117,17 @@ public class HttpBufferedLexer {
             }
             case REQUEST_METHOD:{
                 // Get URI token
-                res =  nextWord(context, HttpParsingContext.TokenType.REQUEST_URI, SP_SEPARATOR);
+                res =  nextWord(context, HttpParsingContext.TokenType.REQUEST_URI, SP_SEPARATOR, URI_LENGTH);
                 break;
             }
             case REQUEST_URI:{ // request version
-                res = nextWord(context, HttpParsingContext.TokenType.HTTP_VERSION, CRLF_SEPARATOR);
+                res = nextWord(context, HttpParsingContext.TokenType.HTTP_VERSION, CRLF_SEPARATOR, VERSION_LENGTH);
                 break;
             }
             case HTTP_VERSION:{ // First header line
                 context.skips = 0;
                 if (!skipEndOfLine(context)){
-                    res = nextWord(context, HttpParsingContext.TokenType.HEADER_NAME, HEADER_NAME_SEPARATOR);
+                    res = nextWord(context, HttpParsingContext.TokenType.HEADER_NAME, HEADER_NAME_SEPARATOR, HEADER_NAME_LENGTH);
                 }else {
                     context.setBodyFound();
                     res = 1;
@@ -121,15 +135,16 @@ public class HttpBufferedLexer {
                 break;
             }
             case HEADER_NAME:{ // header value
-               res = nextWord(context, HttpParsingContext.TokenType.HEADER_VALUE, CRLF_SEPARATOR);
+               res = nextWord(context, HttpParsingContext.TokenType.HEADER_VALUE, CRLF_SEPARATOR, HEADER_VALUE_LENGTH);
                break;
             }case HEADER_VALUE:{ // Might be a header value for multiline headers, a header name, or Body
                 context.skips = 0;
                 if (!skipEndOfLine(context)){
                     if (context.currentPointer == SP || context.currentPointer == TAB){
-                        res = nextWord(context, HttpParsingContext.TokenType.HEADER_VALUE,CRLF_SEPARATOR );
+                        context.deleteFirstCharFromTokenBuffer(); // Don't keep the first whitespace character
+                        res = nextWord(context, HttpParsingContext.TokenType.HEADER_VALUE,CRLF_SEPARATOR, HEADER_VALUE_LENGTH);
                     }else {
-                        res = nextWord(context, HttpParsingContext.TokenType.HEADER_NAME, HEADER_NAME_SEPARATOR);
+                        res = nextWord(context, HttpParsingContext.TokenType.HEADER_NAME, HEADER_NAME_SEPARATOR, HEADER_NAME_LENGTH);
                     }
                 }else {
                     context.setBodyFound();
@@ -137,7 +152,7 @@ public class HttpBufferedLexer {
                 }
                 break;
             }
-            default:{ // If BODY or other nothing todo
+            default:{ // If BODY or other nothing to do
                 res = 0;
             }
         }
@@ -150,26 +165,36 @@ public class HttpBufferedLexer {
 
 		while(context.hasRemaining()){
 			if (context.incrementAndGetPointer() != CR && context.currentPointer != LF && context.currentPointer != SP){
-                context.startPreviousPosition();
+                context.appendChar();
 				return true;
 			}
 		}
 		return false;
 	}
 
-    public int nextWord(HttpParsingContext context, HttpParsingContext.TokenType type, StopChars stopChars){
+    /**
+     *
+     */
+    public int nextWord(HttpParsingContext context, HttpParsingContext.TokenType type, StopChars stopChars, int maxLen){
         int currentChar = 0;
-   
-		while(context.buffer.hasRemaining()){
-			currentChar = context.buffer.get();
+
+		while(context.hasRemaining()){
+			currentChar = context.incrementAndGetPointer();
 			if (stopChars.isForbidden(currentChar)){
 				return -1; // Bad format Request should not contain this char at this point
 			} else if (stopChars.isSeparator(currentChar)){
+                if (context.tokenGreaterThan(maxLen)){
+                    return -1; // Too long
+                }
                 context.storeCompleteToken(type);
                 return 1;
             }
+            context.appendChar();
 		}
         // No errors but the token is not complete
+        if (context.tokenGreaterThan(maxLen)){
+            return -1; // Too long
+        }
         context.storeIncompleteToken();
 		return 0;
     }
@@ -184,7 +209,7 @@ public class HttpBufferedLexer {
         while(context.hasRemaining()){
 
             if (context.incrementAndGetPointer() != CR && context.currentPointer != LF){
-                context.startPreviousPosition();
+                context.appendChar();
                 return false;
             }else if (context.skips >= 2){ // Here we got CRLFCRLF combination so rest is the body
                 return true;
@@ -197,11 +222,19 @@ public class HttpBufferedLexer {
     }
 
 
-
+    /**
+     * Defines the Stop characters to use (Separator and Forbidden)
+     */
     private interface StopChars {
 
+        /**
+         * Tells wether this char is a separator endind the current Token under parsing
+         */
         boolean isSeparator(int ptr);
 
+        /**
+         * Tells wether this char is forbidden or not. If forbidden then parsing will raise an error
+         */
         boolean isForbidden(int ptr);
 
     }

Modified: incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpParsingContext.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpParsingContext.java?rev=1175622&r1=1175621&r2=1175622&view=diff
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpParsingContext.java (original)
+++ incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpParsingContext.java Sun Sep 25 23:21:31 2011
@@ -19,8 +19,6 @@
  */
 package org.apache.deft.web.http;
 
-import com.google.common.base.Charsets;
-
 import java.nio.ByteBuffer;
 
 /**
@@ -30,7 +28,6 @@ import java.nio.ByteBuffer;
 public class HttpParsingContext {
 
 
-
     enum TokenType{
         REQUEST_LINE,
         REQUEST_METHOD,
@@ -39,11 +36,10 @@ public class HttpParsingContext {
         HEADER_NAME,
         HEADER_VALUE,
         BODY;
+
     }
-    
-    ByteBuffer buffer;
 
-    int startPosition = 0;
+    ByteBuffer buffer;
 
     TokenType currentType = TokenType.REQUEST_LINE;
 
@@ -62,13 +58,12 @@ public class HttpParsingContext {
         return currentPointer;
     }
 
+    public boolean tokenGreaterThan(int maxLen) {
+        return tokenValue.length() > maxLen;
+    }
+
     void setBuffer(ByteBuffer buffer){
         this.buffer = buffer;
-        if (buffer != null){
-            startPosition = buffer.position();
-        } else {
-            startPosition = 0;
-        }
     }
 
     boolean hasRemaining(){
@@ -84,27 +79,34 @@ public class HttpParsingContext {
         return TokenType.BODY.equals(currentType);
     }
 
-    void startPreviousPosition(){
-        startPosition = buffer.position()-1;
+    void clearTokenBuffer(){
+        if (complete){ // Free buffer when last was complete
+            tokenValue.delete(0, Integer.MAX_VALUE);
+        }
+    }
+
+
+    void deleteFirstCharFromTokenBuffer(){
+        tokenValue.deleteCharAt(0);
+    }
+
+    void appendChar(){
+        tokenValue.append((char)currentPointer);
     }
 
     /**
      * Stores the token value and define the completeness
      */
     void storeIncompleteToken(){
-        storeTokenValue(currentType, false, buffer.position() - startPosition);
+        storeTokenValue(currentType, false);
     }
 
     void storeCompleteToken(TokenType type){
-        storeTokenValue(type, true, buffer.position() - startPosition -1);
+        storeTokenValue(type, true);
     }
 
-    private void storeTokenValue(TokenType type, boolean _complete, int endPosition){
-        if (complete){ // Free buffer when last was complete
-            tokenValue.delete(0, Integer.MAX_VALUE);
-        }
-        tokenValue.append(new String (buffer.array(), startPosition, endPosition, Charsets.ISO_8859_1));
-        startPosition = buffer.position();
+    private void storeTokenValue(TokenType type, boolean _complete){
+
         currentType = type;
         complete = _complete;
     }

Modified: incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpRequestImpl.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpRequestImpl.java?rev=1175622&r1=1175621&r2=1175622&view=diff
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpRequestImpl.java (original)
+++ incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpRequestImpl.java Sun Sep 25 23:21:31 2011
@@ -27,15 +27,14 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.regex.Pattern;
 
-import org.apache.deft.io.IOLoop;
-import org.apache.deft.io.buffer.DynamicByteBuffer;
-import org.apache.deft.util.ArrayUtil;
-import org.apache.deft.web.http.protocol.HttpVerb;
-
 import com.google.common.base.Charsets;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.Maps;
+import org.apache.deft.io.IOLoop;
+import org.apache.deft.io.buffer.DynamicByteBuffer;
+import org.apache.deft.util.ArrayUtil;
+import org.apache.deft.web.http.protocol.HttpVerb;
 
 public class HttpRequestImpl implements HttpRequest {
 

Modified: incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpRequestParser.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpRequestParser.java?rev=1175622&r1=1175621&r2=1175622&view=diff
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpRequestParser.java (original)
+++ incubator/deft/sandbox/src/main/java/org/apache/deft/web/http/HttpRequestParser.java Sun Sep 25 23:21:31 2011
@@ -21,7 +21,6 @@ package org.apache.deft.web.http;
 
 import java.nio.ByteBuffer;
 
-import com.google.common.base.Charsets;
 import org.apache.deft.io.buffer.DynamicByteBuffer;
 import org.apache.deft.web.http.protocol.HttpVerb;
 import org.slf4j.Logger;
@@ -31,6 +30,8 @@ import org.slf4j.LoggerFactory;
 
 /**
  * Builds HttpRequest using a given ByteBuffer and already existing request object (unfinished).
+ * Uses an HttpBufferedLexer to retrieve Http Tokens and the HttpParsingContext stored in the request
+ * to maintain parsing state.
  */
 public class HttpRequestParser {
 	
@@ -49,10 +50,13 @@ public class HttpRequestParser {
     }
 
     /**
+     * Parse the data in the given buffer as an Http request. It handles segmented buffer
+     * when the given request is not null.
      *
-     * @param buffer
-     * @param result
-     * @return
+     * @param buffer    ByteBuffer containing data to parse
+     * @param result    null if it's a new request or the incomplete request
+     * @return          new HttpRequestImpl if result is null representing a complete or incomplete request
+     *                  on error, it will return a MalformedHttpRequest.
      */
 	public HttpRequestImpl parseRequestBuffer(ByteBuffer buffer,HttpRequestImpl result){
 
@@ -64,7 +68,6 @@ public class HttpRequestParser {
         HttpParsingContext context = result.getContext();
         context.setBuffer(buffer);
 
-//        LOG.warn("Request buffer is {}", new String (buffer.array(), Charsets.ISO_8859_1));
         // while no errors and buffer not finished
         while ((status = lexer.nextToken(context)) > 0){
            switch (context.currentType){
@@ -95,7 +98,6 @@ public class HttpRequestParser {
             // Copy body data to the request bodyBuffer
             if (result.getContentLength() > 0){
                 pushRemainingToBody(context.buffer, result.getBodyBuffer(), result.getContentLength());
-        //        LOG.warn("Body size is {} and contentLength is {}", result.getBodyBuffer().position(), result.getContentLength());
             }
             // TODO: Implement chunked encoding here
         }
@@ -107,6 +109,11 @@ public class HttpRequestParser {
         return result;
 	}
 
+    /**
+     * Fill's the body buffer with the data retrieved from the given buffer starting
+     * at buffer position and copying given size byte.<br/>
+     * This will ensure that body buffer does not contain more than size byte.
+     */
 	private void pushRemainingToBody(ByteBuffer buffer, DynamicByteBuffer body, int size){
 		// If buffer is empty or there is no clength then skip this
 		if (size == 0 || !buffer.hasRemaining()){

Modified: incubator/deft/sandbox/src/test/java/org/apache/deft/web/DeftSystemTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/test/java/org/apache/deft/web/DeftSystemTest.java?rev=1175622&r1=1175621&r2=1175622&view=diff
==============================================================================
--- incubator/deft/sandbox/src/test/java/org/apache/deft/web/DeftSystemTest.java (original)
+++ incubator/deft/sandbox/src/test/java/org/apache/deft/web/DeftSystemTest.java Sun Sep 25 23:21:31 2011
@@ -19,11 +19,6 @@
  */
 package org.apache.deft.web;
 
-import static org.apache.deft.web.DeftSystemTestHandlers.expectedPayload;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
@@ -43,30 +38,13 @@ import java.util.concurrent.ExecutorServ
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
+import com.ning.http.client.AsyncCompletionHandler;
+import com.ning.http.client.AsyncHttpClient;
+import com.ning.http.client.Response;
 import org.apache.deft.configuration.Configuration;
 import org.apache.deft.io.IOLoop;
 import org.apache.deft.io.timeout.Timeout;
-import org.apache.deft.web.DeftSystemTestHandlers.AsyncThrowingHttpExceptionRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.AuthenticatedRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.CapturingRequestRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.ChunkedRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.DeleteRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.EchoingPostBodyRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.ExampleRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.KeyValueStoreExampleRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.MovedPermanentlyRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.NoBodyRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.PostRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.PutRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.QueryParamsRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.ThrowingHttpExceptionRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.UserDefinedStaticContentHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.WFFFWFFFRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.WFWFRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.WRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.WWFWRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers.WWRequestHandler;
-import org.apache.deft.web.DeftSystemTestHandlers._450KBResponseEntityRequestHandler;
+import org.apache.deft.web.DeftSystemTestHandlers.*;
 import org.apache.deft.web.handler.RequestHandler;
 import org.apache.deft.web.http.client.AsynchronousHttpClient;
 import org.apache.deft.web.http.protocol.HttpStatus;
@@ -88,10 +66,8 @@ import org.apache.http.params.HttpProtoc
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
-
-import com.ning.http.client.AsyncCompletionHandler;
-import com.ning.http.client.AsyncHttpClient;
-import com.ning.http.client.Response;
+import static org.junit.Assert.*;
+import static org.apache.deft.web.DeftSystemTestHandlers.expectedPayload;
 
 /**
  * General tests of server operation.
@@ -955,7 +931,10 @@ public class DeftSystemTest {
         assertEquals(expected.length() + "", response.getFirstHeader("Content-Length").getValue());
     }
 
-    @Test
+    /**
+     * TODO SLM This test does not make sense since stop use a callback and server store only one serverChannel
+     * @Test
+     */
     public void multipleStartStopCombinations() throws InterruptedException {
 
         Configuration configuration = new Configuration();

Modified: incubator/deft/sandbox/src/test/java/org/apache/deft/web/HttpServerTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/test/java/org/apache/deft/web/HttpServerTest.java?rev=1175622&r1=1175621&r2=1175622&view=diff
==============================================================================
--- incubator/deft/sandbox/src/test/java/org/apache/deft/web/HttpServerTest.java (original)
+++ incubator/deft/sandbox/src/test/java/org/apache/deft/web/HttpServerTest.java Sun Sep 25 23:21:31 2011
@@ -20,11 +20,14 @@
 package org.apache.deft.web;
 
 import org.apache.deft.configuration.Configuration;
+import org.apache.deft.io.IOLoop;
 import org.apache.deft.web.handler.RequestHandler;
+import org.junit.Assert;
 import org.junit.Test;
 
 import com.google.common.collect.Maps;
 
+
 /**
  * Test cases for {@link HttpServer}.
  */
@@ -51,6 +54,26 @@ public class HttpServerTest {
         server.listen(port);
     }
 
+
+    @Test
+    public void multiThreadServerStartStop(){
+        int port = 8181;
+        HttpServer server = createServer();
+        server.bind(port);
+        server.start(3);
+
+        org.junit.Assert.assertEquals(3, server.getIoLoops().size());
+        for (IOLoop loop : server.getIoLoops()){
+            Assert.assertTrue(loop.isRunning());
+        }
+
+        server.stop();
+        for (IOLoop loop : server.getIoLoops()){
+            Assert.assertFalse(loop.isRunning());
+        }
+
+    }
+
     private HttpServer createServer() {
 
         HttpServer server = new HttpServer(new Configuration()) {

Modified: incubator/deft/sandbox/src/test/java/org/apache/deft/web/http/HttpBufferedLexerTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/test/java/org/apache/deft/web/http/HttpBufferedLexerTest.java?rev=1175622&r1=1175621&r2=1175622&view=diff
==============================================================================
--- incubator/deft/sandbox/src/test/java/org/apache/deft/web/http/HttpBufferedLexerTest.java (original)
+++ incubator/deft/sandbox/src/test/java/org/apache/deft/web/http/HttpBufferedLexerTest.java Sun Sep 25 23:21:31 2011
@@ -20,27 +20,26 @@
 package org.apache.deft.web.http;
 
 
+import java.nio.ByteBuffer;
+
 import junit.framework.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-
-import java.nio.ByteBuffer;
+import static org.apache.deft.web.http.HttpBufferedLexer.*;
+import static org.apache.deft.web.http.HttpParsingContext.TokenType;
 
 /**
- *
- * User: slm
- * Date: 13/09/11
- * Time: 00:11
+ * Unit tests suite for HttpBufferedLexer
  */
 public class HttpBufferedLexerTest {
 
-    HttpBufferedLexer   lexer;
-    HttpParsingContext  context;
+    HttpBufferedLexer  lexer;
+    HttpParsingContext context;
 
     @Before
-    public  void init(){
-        lexer   = new HttpBufferedLexer();
+    public void init() {
+        lexer = new HttpBufferedLexer();
         context = new HttpParsingContext();
     }
 
@@ -51,40 +50,39 @@ public class HttpBufferedLexerTest {
         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("Token GET should be found with no errors", 1, res);
         Assert.assertEquals("GET", context.getTokenValue());
-        Assert.assertEquals(HttpParsingContext.TokenType.REQUEST_METHOD, context.currentType);
+        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("Token uri should be found with no errors", 1, res);
         Assert.assertEquals("/path/script.cgi", context.getTokenValue());
-        Assert.assertEquals(HttpParsingContext.TokenType.REQUEST_URI, context.currentType);
+        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("Token protocol version should be found with no errors", 1, res);
         Assert.assertEquals("HTTP/1.1", context.getTokenValue());
-        Assert.assertEquals(HttpParsingContext.TokenType.HTTP_VERSION, context.currentType);
+        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(HttpParsingContext.TokenType.BODY, context.currentType);
-        Assert.assertEquals("TokenValue should be null for body","", context.getTokenValue());
+        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(){
+    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);
-        Assert.assertEquals("", context.getTokenValue());
+        Assert.assertEquals("Token GET should be found with error", -1, res);
     }
 
     @Test
-    public void requestWithHeadersParsing(){
+    public void requestWithHeadersParsing() {
 
         String request = "POST /path/script.cgi HTTP/1.0\r\n"
                 + "Host: localhost\r\n"
@@ -93,8 +91,8 @@ public class HttpBufferedLexerTest {
                 + "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"},
+        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"},
@@ -111,130 +109,336 @@ public class HttpBufferedLexerTest {
         Assert.assertEquals("/path/script.cgi", path);
         Assert.assertEquals("HTTP/1.0", protocol);
 
-        for (String [] header : headers){
+        for (String[] header : headers) {
             res = lexer.nextToken(context);
             Assert.assertEquals(1, res);
-            Assert.assertEquals(HttpParsingContext.TokenType.HEADER_NAME, context.currentType);
+            Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
             Assert.assertEquals(header[0], context.getTokenValue());
             res = lexer.nextToken(context);
             Assert.assertEquals(1, res);
-            Assert.assertEquals(HttpParsingContext.TokenType.HEADER_VALUE, context.currentType);
+            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(HttpParsingContext.TokenType.BODY, context.currentType);
-        Assert.assertEquals("TokenValue should be null for body","", context.getTokenValue());
+        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(){
+    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(HttpParsingContext.TokenType.REQUEST_METHOD,context.currentType);
+        Assert.assertEquals(TokenType.REQUEST_METHOD, context.currentType);
         Assert.assertEquals("POST", context.getTokenValue());
     }
 
     @Test
-    public void incompleteHeaderAfterRequestLine(){
+    public void incompleteHeaderAfterRequestLine() {
         String requestPart1 = "Content-";
         String requestPart2 = "Type: application";
         String requestPart3 = "/x-www-form-";
         String requestPart4 = "urlencoded\r\n";
-        context.currentType = HttpParsingContext.TokenType.HTTP_VERSION;
+        context.currentType = TokenType.HTTP_VERSION;
         context.setBuffer(ByteBuffer.wrap(requestPart1.getBytes()));
 
         int res = lexer.nextToken(context);
         Assert.assertEquals(0, res);
-        Assert.assertEquals(HttpParsingContext.TokenType.HTTP_VERSION,context.currentType);
+        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(HttpParsingContext.TokenType.HEADER_NAME,context.currentType);
+        Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
         Assert.assertEquals("Content-Type", context.getTokenValue());
 
         res = lexer.nextToken(context);
         Assert.assertEquals(0, res);
-        Assert.assertEquals(HttpParsingContext.TokenType.HEADER_NAME,context.currentType);
+        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(HttpParsingContext.TokenType.HEADER_NAME,context.currentType);
+        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(HttpParsingContext.TokenType.HEADER_VALUE,context.currentType);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
         Assert.assertEquals(" application/x-www-form-urlencoded", context.getTokenValue());
     }
 
     @Test
-    public void incompleteHeaderAfterHeader(){
+    public void incompleteHeaderAfterHeader() {
         String requestPart1 = "Content-";
         String requestPart2 = "Type: application";
         String requestPart3 = "/x-www-form-";
         String requestPart4 = "urlencoded\r\n";
-        context.currentType = HttpParsingContext.TokenType.HEADER_VALUE;
+        context.currentType = TokenType.HEADER_VALUE;
         context.setBuffer(ByteBuffer.wrap(requestPart1.getBytes()));
 
         int res = lexer.nextToken(context);
         Assert.assertEquals(0, res);
-        Assert.assertEquals(HttpParsingContext.TokenType.HEADER_VALUE,context.currentType);
+        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(HttpParsingContext.TokenType.HEADER_NAME,context.currentType);
+        Assert.assertEquals(TokenType.HEADER_NAME, context.currentType);
         Assert.assertEquals("Content-Type", context.getTokenValue());
 
         res = lexer.nextToken(context);
         Assert.assertEquals(0, res);
-        Assert.assertEquals(HttpParsingContext.TokenType.HEADER_NAME,context.currentType);
+        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(HttpParsingContext.TokenType.HEADER_NAME,context.currentType);
+        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(HttpParsingContext.TokenType.HEADER_VALUE,context.currentType);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
         Assert.assertEquals(" application/x-www-form-urlencoded", context.getTokenValue());
     }
 
     @Test
-    public void parseMultiLineHeaders(){
+    public void parseMultiLineHeaders() {
         String request = "my headervalue\r\n and so on\r\n\tand so on\r\n";
-        context.currentType = HttpParsingContext.TokenType.HEADER_NAME;
+        context.currentType = TokenType.HEADER_NAME;
         context.setBuffer(ByteBuffer.wrap(request.getBytes()));
 
         int res = lexer.nextToken(context);
         Assert.assertEquals(1, res);
-        Assert.assertEquals(HttpParsingContext.TokenType.HEADER_VALUE,context.currentType);
+        Assert.assertEquals(TokenType.HEADER_VALUE, context.currentType);
         Assert.assertEquals("my headervalue", context.getTokenValue());
 
         res = lexer.nextToken(context);
         Assert.assertEquals(1, res);
-        Assert.assertEquals(HttpParsingContext.TokenType.HEADER_VALUE,context.currentType);
-        Assert.assertEquals(" and so on", context.getTokenValue());
+        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(HttpParsingContext.TokenType.HEADER_VALUE,context.currentType);
-        Assert.assertEquals("\tand so on", context.getTokenValue());
+        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;
+    }
+
 }



Mime
View raw message