You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by rd...@apache.org on 2008/02/27 21:57:40 UTC

svn commit: r631723 - in /james/server/trunk: imap-api/src/main/java/org/apache/james/api/imap/message/request/ imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/base/ imap-codec-library/src/main/java/org/apache/james/imapserver...

Author: rdonkin
Date: Wed Feb 27 12:57:38 2008
New Revision: 631723

URL: http://svn.apache.org/viewvc?rev=631723&view=rev
Log:
More search parsing

Modified:
    james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/message/request/SearchKey.java
    james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/base/AbstractImapCommandParser.java
    james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParser.java
    james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeyTest.java

Modified: james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/message/request/SearchKey.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/message/request/SearchKey.java?rev=631723&r1=631722&r2=631723&view=diff
==============================================================================
--- james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/message/request/SearchKey.java (original)
+++ james/server/trunk/imap-api/src/main/java/org/apache/james/api/imap/message/request/SearchKey.java Wed Feb 27 12:57:38 2008
@@ -185,7 +185,7 @@
                 null);
     }
 
-    public static SearchKey buildLKeyword(String value) {
+    public static SearchKey buildKeyword(String value) {
         return new SearchKey(TYPE_KEYWORD, null, null, null, 0, null,
                 value, null);
     }

Modified: james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/base/AbstractImapCommandParser.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/base/AbstractImapCommandParser.java?rev=631723&r1=631722&r2=631723&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/base/AbstractImapCommandParser.java (original)
+++ james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/base/AbstractImapCommandParser.java Wed Feb 27 12:57:38 2008
@@ -193,11 +193,16 @@
      */
     public DayMonthYear date(ImapRequestLineReader request) throws ProtocolException {
         
-        final char dayHigh = request.consume();
-        final char dayLow = request.consume();
-        final int day = DecoderUtils.decodeFixedDay(dayHigh, dayLow);
+        final char one = request.consume();
+        final char two = request.consume();
+        final int day;
+        if (two == '-') {
+            day = DecoderUtils.decodeFixedDay(' ', one);
+        } else {
+            day = DecoderUtils.decodeFixedDay(one, two);
+            nextIsDash(request);
+        }
         
-        nextIsDash(request);
         final char monthFirstChar = request.consume();
         final char monthSecondChar = request.consume();
         final char monthThirdChar = request.consume();

Modified: james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParser.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParser.java?rev=631723&r1=631722&r2=631723&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParser.java (original)
+++ james/server/trunk/imap-codec-library/src/main/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParser.java Wed Feb 27 12:57:38 2008
@@ -18,6 +18,9 @@
  ****************************************************************/
 package org.apache.james.imapserver.codec.decode.imap4rev1;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
 import org.apache.james.api.imap.ImapCommand;
 import org.apache.james.api.imap.ImapMessage;
 import org.apache.james.api.imap.ProtocolException;
@@ -29,6 +32,44 @@
 
 class SearchCommandParser extends AbstractUidCommandParser implements InitialisableCommandFactory
 {
+    public static final void main(String[] args) throws Exception {
+        final byte[] mixed = "BEforE 1-Jan-2000".getBytes("US-ASCII");
+        final byte[] allSmalls = "before 1-Jan-2000".getBytes("US-ASCII");
+        final byte[] allCaps = "BEFORE 1-Jan-2000".getBytes("US-ASCII");
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        SearchCommandParser parser = new SearchCommandParser();
+        long start  = System.currentTimeMillis();
+        long i = 0;
+        ByteArrayInputStream bais = new ByteArrayInputStream(allCaps);
+        while (i++ < 1000000) {
+                bais.reset();
+                ImapRequestLineReader request = new ImapRequestLineReader(
+                        bais, 
+                        baos);
+                parser.searchKey(request);
+        }
+        i = 0;
+        bais = new ByteArrayInputStream(allSmalls);
+        while (i++ < 1000000) {
+            bais.reset();
+            ImapRequestLineReader request = new ImapRequestLineReader(
+                    bais, 
+                    baos);
+            parser.searchKey(request);
+        }
+        i = 0;
+        bais = new ByteArrayInputStream(mixed);
+        while (i++ < 1000000) {
+            bais.reset();
+            ImapRequestLineReader request = new ImapRequestLineReader(
+                    bais, 
+                    baos);
+            parser.searchKey(request);
+        }
+        long end = System.currentTimeMillis();
+        System.out.println(end - start);
+    }
+    
     public SearchCommandParser() {
     }
 
@@ -45,80 +86,299 @@
      * Parses the request argument into a valid search term.
      */
     public SearchKey searchKey( ImapRequestLineReader request ) throws ProtocolException {
+        final int cap = consumeAndCap(request);
+        switch (cap) {
+            case 'A': return a(request);
+            case 'B': return b(request);
+            case 'C': return cc(request);
+            case 'D': return d(request);
+            case 'E': throw new ProtocolException("Unknown search key");
+            case 'F': return f(request);
+            case 'G': throw new ProtocolException("Unknown search key");
+            case 'H': return header(request);
+            case 'I': throw new ProtocolException("Unknown search key");
+            case 'J': throw new ProtocolException("Unknown search key");
+            case 'K': return keyword(request);
+            case 'L': return larger(request);
+            case 'M': throw new ProtocolException("Unknown search key");
+            case 'N': return n(request);
+            case 'O': return o(request);
+            default:
+                throw new ProtocolException("Unknown search key");
+        }
+    }
+
+    private int consumeAndCap(ImapRequestLineReader request) throws ProtocolException {
+        final char next = request.consume();
+        final int cap = next > 'Z' ? next ^ 32 : next;
+        return cap;
+    }
+
+    private SearchKey cc(ImapRequestLineReader request) throws ProtocolException {
         final SearchKey result;
-        final char next = request.nextWordChar();
-        request.consume();
+        nextIsC(request);
+        nextIsSpace(request);
+        final String value = astring(request);
+        result = SearchKey.buildCc(value);
+        return result;
+    }
+    
+    private SearchKey o(ImapRequestLineReader request) throws ProtocolException {
+        final int next = consumeAndCap(request);
         switch (next) {
-            case 'a':
-            case 'A':
-                result = a(request);
-                break;
-            case 'b':
-            case 'B':
-                result = b(request);
-                break;
+            case 'L': return old(request);
+            case 'N': return on(request);
+            default:
+                throw new ProtocolException("Unknown search key");
+        }
+    }
+    
+    private SearchKey n(ImapRequestLineReader request) throws ProtocolException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'E': return _new(request);
+            default:
+                throw new ProtocolException("Unknown search key");
+        }
+    }
+    
+    private SearchKey f(ImapRequestLineReader request) throws ProtocolException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'L': return flagged(request);
+            case 'R': return from(request);
+            default:
+                throw new ProtocolException("Unknown search key");
+        }
+    }
+    
+    private SearchKey d(ImapRequestLineReader request) throws ProtocolException {
+        final int next = consumeAndCap(request);
+        switch (next) {
+            case 'E': return deleted(request);
+            case 'R': return draft(request);
             default:
                 throw new ProtocolException("Unknown search key");
         }
-        return result;
     }
 
-    private SearchKey b(ImapRequestLineReader request) throws ProtocolException {
+    private SearchKey keyword(ImapRequestLineReader request) throws ProtocolException {
         final SearchKey result;
-        final char next = request.consume();
+        nextIsE(request);
+        nextIsY(request);
+        nextIsW(request);
+        nextIsO(request);
+        nextIsR(request);
+        nextIsD(request);
+        nextIsSpace(request);
+        final String value = atom(request);
+        result = SearchKey.buildKeyword(value);
+        return result;
+    }
+    
+    private SearchKey header(ImapRequestLineReader request) throws ProtocolException {
+        final SearchKey result;
+        nextIsE(request);
+        nextIsA(request);
+        nextIsD(request);
+        nextIsE(request);
+        nextIsR(request);
+        nextIsSpace(request);
+        final String field = astring(request);
+        nextIsSpace(request);
+        final String value = astring(request);
+        result = SearchKey.buildHeader(field, value);
+        return result;
+    }
+    
+    private SearchKey larger(ImapRequestLineReader request) throws ProtocolException {
+        final SearchKey result;
+        nextIsA(request);
+        nextIsR(request);
+        nextIsG(request);
+        nextIsE(request);
+        nextIsR(request);
+        nextIsSpace(request);
+        final long value = number(request);
+        result = SearchKey.buildLarger(value);
+        return result;
+    }
+    
+    private SearchKey from(ImapRequestLineReader request) throws ProtocolException {
+        final SearchKey result;
+        nextIsO(request);
+        nextIsM(request);
+        nextIsSpace(request);
+        final String value = astring(request);
+        result = SearchKey.buildFrom(value);
+        return result;
+    }
+    
+    private SearchKey flagged(ImapRequestLineReader request) throws ProtocolException {
+        final SearchKey result;
+        nextIsA(request);
+        nextIsG(request);
+        nextIsG(request);
+        nextIsE(request);
+        nextIsD(request);
+        result = SearchKey.buildFlagged();
+        return result;
+    }
+    
+    private SearchKey old(ImapRequestLineReader request) throws ProtocolException {
+        final SearchKey result;
+        nextIsD(request);
+        result = SearchKey.buildOld();
+        return result;
+    }
+    
+    private SearchKey _new(ImapRequestLineReader request) throws ProtocolException {
+        final SearchKey result;
+        nextIsW(request);
+        result = SearchKey.buildNew();
+        return result;
+    }
+    
+    private SearchKey draft(ImapRequestLineReader request) throws ProtocolException {
+        final SearchKey result;
+        nextIsA(request);
+        nextIsF(request);
+        nextIsT(request);
+        result = SearchKey.buildDraft();
+        return result;
+    }
+    
+    private SearchKey deleted(ImapRequestLineReader request) throws ProtocolException {
+        final SearchKey result;
+        nextIsL(request);
+        nextIsE(request);
+        nextIsT(request);
+        nextIsE(request);
+        nextIsD(request);
+        result = SearchKey.buildDeleted();
+        return result;
+    }
+    
+    private SearchKey b(ImapRequestLineReader request) throws ProtocolException {
+        final int next = consumeAndCap(request);
         switch (next) {
-            case 'c':
-            case 'C':
-                result = bcc(request);
-                break;
-            case 'E':
-            case 'e':
-                nextIsF(request);
-                nextIsO(request);
-                nextIsR(request);
-                nextIsE(request);
-                final DayMonthYear value = date(request);
-                result = SearchKey.buildBefore(value);
-                break;
+            case 'C': return bcc(request);
+            case 'E': return before(request);
+            case 'O': return body(request);
             default:
                 throw new ProtocolException("Unknown search key");
         }
+    }
+
+    private SearchKey body(ImapRequestLineReader request) throws ProtocolException {
+        final SearchKey result;
+        nextIsD(request);
+        nextIsY(request);
+        nextIsSpace(request);
+        final String value = astring(request);
+        result = SearchKey.buildBody(value);
+        return result;
+    }
 
+    private SearchKey on(ImapRequestLineReader request) throws ProtocolException {
+        final SearchKey result;
+        nextIsSpace(request);
+        final DayMonthYear value = date(request);
+        result = SearchKey.buildOn(value);
+        return result;
+    }
+    
+    private SearchKey before(ImapRequestLineReader request) throws ProtocolException {
+        final SearchKey result;
+        nextIsF(request);
+        nextIsO(request);
+        nextIsR(request);
+        nextIsE(request);
+        nextIsSpace(request);
+        final DayMonthYear value = date(request);
+        result = SearchKey.buildBefore(value);
         return result;
     }
 
     private SearchKey bcc(ImapRequestLineReader request) throws ProtocolException {
         final SearchKey result;
         nextIsC(request);
+        nextIsSpace(request);
         final String value = astring(request);
         result = SearchKey.buildBcc(value);
         return result;
     }
 
     private SearchKey a(ImapRequestLineReader request) throws ProtocolException {
-        final SearchKey result;
-        final char next = request.consume();
+        final int next = consumeAndCap(request);
         switch (next) {
-            case 'l':
-            case 'L':
-                nextIsL(request);
-                result = SearchKey.buildAll();
-                break;
-            case 'n':
-            case 'N':
-                nextIsS(request);
-                nextIsW(request);
-                nextIsE(request);
-                nextIsR(request);
-                nextIsE(request);
-                nextIsD(request);
-                result = SearchKey.buildAnswered();
-                break;
+            case 'L': return all(request);
+            case 'N': return answered(request);
             default:
                 throw new ProtocolException("Unknown search key");
         }
+    }
+
+    private SearchKey answered(ImapRequestLineReader request) throws ProtocolException {
+        final SearchKey result;
+        nextIsS(request);
+        nextIsW(request);
+        nextIsE(request);
+        nextIsR(request);
+        nextIsE(request);
+        nextIsD(request);
+        result = SearchKey.buildAnswered();
         return result;
     }
+
+    private SearchKey all(ImapRequestLineReader request) throws ProtocolException {
+        final SearchKey result;
+        nextIsL(request);
+        result = SearchKey.buildAll();
+        return result;
+    }
+    
+    private void nextIsSpace(ImapRequestLineReader request ) throws ProtocolException {
+        final char next = request.consume();
+        if (next != ' ') {
+            throw new ProtocolException("Unknown search key");
+        }
+    }
+    
+    private void nextIsG( ImapRequestLineReader request ) throws ProtocolException {
+        final char next = request.consume();
+        if (next != 'G' && next != 'g') {
+            throw new ProtocolException("Unknown search key");
+        }
+    }
+    
+    private void nextIsM( ImapRequestLineReader request ) throws ProtocolException {
+        final char next = request.consume();
+        if (next != 'M' && next != 'm') {
+            throw new ProtocolException("Unknown search key");
+        }
+    }
+    
+    private void nextIsA( ImapRequestLineReader request ) throws ProtocolException {
+        final char next = request.consume();
+        if (next != 'A' && next != 'a') {
+            throw new ProtocolException("Unknown search key");
+        }
+    }
+    
+    private void nextIsT( ImapRequestLineReader request ) throws ProtocolException {
+        final char next = request.consume();
+        if (next != 'T' && next != 't') {
+            throw new ProtocolException("Unknown search key");
+        }
+    }
+    
+    private void nextIsY( ImapRequestLineReader request ) throws ProtocolException {
+        final char next = request.consume();
+        if (next != 'Y' && next != 'y') {
+            throw new ProtocolException("Unknown search key");
+        }
+    }
     
     private void nextIsO( ImapRequestLineReader request ) throws ProtocolException {
         final char next = request.consume();
@@ -185,6 +445,7 @@
 
     protected ImapMessage decode(ImapCommand command, ImapRequestLineReader request, String tag, boolean useUids) throws ProtocolException {
         // Parse the search term from the request
+        request.nextWordChar();
         final SearchKey key = searchKey( request );
         endLine( request );
         final ImapMessage result = getMessageFactory().createSearchMessage(command, key, useUids, tag);

Modified: james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeyTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeyTest.java?rev=631723&r1=631722&r2=631723&view=diff
==============================================================================
--- james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeyTest.java (original)
+++ james/server/trunk/imap-codec-library/src/test/java/org/apache/james/imapserver/codec/decode/imap4rev1/SearchCommandParserSearchKeyTest.java Wed Feb 27 12:57:38 2008
@@ -21,22 +21,17 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
-import java.util.Date;
-
-import javax.mail.Flags;
 
 import org.apache.james.api.imap.ImapCommand;
 import org.apache.james.api.imap.ImapMessage;
 import org.apache.james.api.imap.ProtocolException;
 import org.apache.james.api.imap.imap4rev1.Imap4Rev1CommandFactory;
 import org.apache.james.api.imap.imap4rev1.Imap4Rev1MessageFactory;
-import org.apache.james.api.imap.message.IdRange;
-import org.apache.james.api.imap.message.request.SearchKey;
 import org.apache.james.api.imap.message.request.DayMonthYear;
+import org.apache.james.api.imap.message.request.SearchKey;
 import org.apache.james.imapserver.codec.decode.ImapRequestLineReader;
 import org.jmock.Mock;
 import org.jmock.MockObjectTestCase;
-import org.jmock.core.Constraint;
 
 public class SearchCommandParserSearchKeyTest extends MockObjectTestCase {
 
@@ -102,6 +97,24 @@
         checkInvalid("b\r\n", key);
         checkInvalid("bc\r\n", key);
         checkInvalid("bg\r\n", key);
+        checkInvalid("bccc\r\n", key);
+    }
+    
+    public void testShouldParseOn() throws Exception {
+        SearchKey key = SearchKey.buildOn(DATE);
+        checkValid("ON 1-Jan-2000\r\n", key);
+        checkValid("on 1-Jan-2000\r\n", key);
+        checkValid("oN 1-Jan-2000\r\n", key);
+        checkInvalid("o\r\n", key);
+        checkInvalid("om\r\n", key);
+        checkInvalid("oni\r\n", key);
+        checkInvalid("on \r\n", key);
+        checkInvalid("on 1\r\n", key);
+        checkInvalid("on 1-\r\n", key);
+        checkInvalid("on 1-J\r\n", key);
+        checkInvalid("on 1-Ja\r\n", key);
+        checkInvalid("on 1-Jan\r\n", key);
+        checkInvalid("on 1-Jan-\r\n", key);
     }
     
     public void testShouldParseBefore() throws Exception {
@@ -116,6 +129,7 @@
         checkInvalid("BEfo\r\n", key);
         checkInvalid("BEfor\r\n", key);
         checkInvalid("BEforE\r\n", key);
+        checkInvalid("BEforEi\r\n", key);
         checkInvalid("BEforE \r\n", key);
         checkInvalid("BEforE 1\r\n", key);
         checkInvalid("BEforE 1-\r\n", key);
@@ -124,7 +138,87 @@
         checkInvalid("BEforE 1-Jan\r\n", key);
         checkInvalid("BEforE 1-Jan-\r\n", key);
     }
+    
+    public void testShouldParseBody() throws Exception {
+        SearchKey key = SearchKey.buildBody("Text");
+        checkValid("BODY Text\r\n", key);
+        checkValid("BODY \"Text\"\r\n", key);
+        checkValid("body Text\r\n", key);
+        checkValid("body \"Text\"\r\n", key);
+        checkValid("BodY Text\r\n", key);
+        checkValid("BodY \"Text\"\r\n", key);
+        checkInvalid("b\r\n", key);
+        checkInvalid("Bo\r\n", key);
+        checkInvalid("Bod\r\n", key);
+        checkInvalid("Bodd\r\n", key);
+        checkInvalid("Bodym\r\n", key);   
+    }
+    
+    
+    public void testShouldParseCc() throws Exception {
+        SearchKey key = SearchKey.buildCc("SomeText");
+        checkValid("CC SomeText\r\n", key);
+        checkValid("CC \"SomeText\"\r\n", key);
+        checkValid("cc SomeText\r\n", key);
+        checkValid("cc \"SomeText\"\r\n", key);
+        checkValid("Cc SomeText\r\n", key);
+        checkValid("Cc \"SomeText\"\r\n", key);
+        checkInvalid("c\r\n", key);
+        checkInvalid("cd\r\n", key);
+        checkInvalid("ccc\r\n", key);
+    }
+
+    public void testShouldParseFrom() throws Exception {
+        SearchKey key = SearchKey.buildFrom("Someone");
+        checkValid("FROM Someone\r\n", key);
+        checkValid("FROM \"Someone\"\r\n", key);
+        checkValid("from Someone\r\n", key);
+        checkValid("from \"Someone\"\r\n", key);
+        checkValid("FRom Someone\r\n", key);
+        checkValid("FRom \"Someone\"\r\n", key);
+        checkInvalid("f\r\n", key);
+        checkInvalid("fr\r\n", key);
+        checkInvalid("ftom\r\n", key);
+        checkInvalid("froml\r\n", key);
+    }
+    
+    public void testShouldParseKeyword() throws Exception {
+        SearchKey key = SearchKey.buildKeyword("AFlag");
+        checkValid("KEYWORD AFlag\r\n", key);
+        checkInvalid("KEYWORD \"AFlag\"\r\n", key);
+        checkValid("keyword AFlag\r\n", key);
+        checkInvalid("keyword \"AFlag\"\r\n", key);
+        checkValid("KEYword AFlag\r\n", key);
+        checkInvalid("KEYword \"AFlag\"\r\n", key);
+        checkInvalid("k\r\n", key);
+        checkInvalid("ke\r\n", key);
+        checkInvalid("key\r\n", key);
+        checkInvalid("keyw\r\n", key);
+        checkInvalid("keywo\r\n", key);
+        checkInvalid("keywor\r\n", key);
+        checkInvalid("keywordi\r\n", key);
+        checkInvalid("keyword \r\n", key);
+    }
+    
 
+    public void testShouldParseHeader() throws Exception {
+        SearchKey key = SearchKey.buildHeader("Field", "Value");
+        checkValid("HEADER Field Value\r\n", key);
+        checkValid("HEADER \"Field\" \"Value\"\r\n", key);
+        checkValid("header Field Value\r\n", key);
+        checkValid("header \"Field\" \"Value\"\r\n", key);
+        checkValid("HEAder Field Value\r\n", key);
+        checkValid("HEAder \"Field\" \"Value\"\r\n", key);
+        checkInvalid("h\r\n", key);
+        checkInvalid("he\r\n", key);
+        checkInvalid("hea\r\n", key);
+        checkInvalid("head\r\n", key);
+        checkInvalid("heade\r\n", key);
+        checkInvalid("header\r\n", key);
+        checkInvalid("header field\r\n", key);
+        checkInvalid("header field \r\n", key);
+    }
+    
     private void checkValid(String input, final SearchKey key) throws Exception {
         ImapRequestLineReader reader = new ImapRequestLineReader(new ByteArrayInputStream(input.getBytes("US-ASCII")), 
                 new ByteArrayOutputStream());
@@ -132,7 +226,86 @@
         assertEquals(key, parser.searchKey(reader));
     }
 
+    public void testShouldParseDeleted() throws Exception {
+        SearchKey key = SearchKey.buildDeleted();
+        checkValid("DELETED\r\n", key);
+        checkValid("deleted\r\n", key);
+        checkValid("deLEteD\r\n", key);
+        checkInvalid("d\r\n", key);
+        checkInvalid("de\r\n", key);
+        checkInvalid("del\r\n", key);
+        checkInvalid("dele\r\n", key);
+        checkInvalid("delet\r\n", key);
+        checkInvalid("delete\r\n", key);
+    }
 
+    public void testEShouldBeInvalid() throws Exception {
+        SearchKey key = SearchKey.buildDeleted();
+        checkInvalid("e\r\n", key);
+        checkInvalid("ee\r\n", key);
+    }
+    
+    public void testShouldParseDraft() throws Exception {
+        SearchKey key = SearchKey.buildDraft();
+        checkValid("DRAFT\r\n", key);
+        checkValid("draft\r\n", key);
+        checkValid("DRaft\r\n", key);
+        checkInvalid("D\r\n", key);
+        checkInvalid("DR\r\n", key);
+        checkInvalid("DRA\r\n", key);
+        checkInvalid("DRAF\r\n", key);
+    }
+    
+    public void testShouldParseNew() throws Exception {
+        SearchKey key = SearchKey.buildNew();
+        checkValid("NEW\r\n", key);
+        checkValid("new\r\n", key);
+        checkValid("NeW\r\n", key);
+        checkInvalid("n\r\n", key);
+        checkInvalid("ne\r\n", key);
+        checkInvalid("nwe\r\n", key);
+    }
+    
+    public void testShouldParseOld() throws Exception {
+        SearchKey key = SearchKey.buildOld();
+        checkValid("OLD\r\n", key);
+        checkValid("old\r\n", key);
+        checkValid("oLd\r\n", key);
+        checkInvalid("o\r\n", key);
+        checkInvalid("ol\r\n", key);
+        checkInvalid("olr\r\n", key);
+    }
+    
+    public void testShouldParseFlagged() throws Exception {
+        SearchKey key = SearchKey.buildFlagged();
+        checkValid("FLAGGED\r\n", key);
+        checkValid("flagged\r\n", key);
+        checkValid("FLAGged\r\n", key);
+        checkInvalid("F\r\n", key);
+        checkInvalid("FL\r\n", key);
+        checkInvalid("FLA\r\n", key);
+        checkInvalid("FLAG\r\n", key);
+        checkInvalid("FLAGG\r\n", key);
+        checkInvalid("FLAGGE\r\n", key);
+        checkInvalid("FLoas\r\n", key);
+    }
+    
+
+    public void testShouldParseLarger() throws Exception {
+        SearchKey key = SearchKey.buildLarger(1234);
+        checkValid("LARGER 1234\r\n", key);
+        checkValid("larger 1234\r\n", key);
+        checkValid("larger 1234\r\n", key);
+        checkInvalid("l\r\n", key);
+        checkInvalid("la\r\n", key);
+        checkInvalid("lar\r\n", key);
+        checkInvalid("larg\r\n", key);
+        checkInvalid("large\r\n", key);
+        checkInvalid("larger\r\n", key);
+        checkInvalid("larger \r\n", key);
+        checkInvalid("larger peach\r\n", key);
+     }
+    
     private void checkInvalid(String input, final SearchKey key) throws Exception {
         ImapRequestLineReader reader = new ImapRequestLineReader(new ByteArrayInputStream(input.getBytes("US-ASCII")), 
                 new ByteArrayOutputStream());



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org