Blob Blame History Raw
From: Peter Lemenkov <lemenkov@gmail.com>
Date: Sun, 24 Mar 2013 18:44:54 +0400
Subject: [PATCH] Move tests to the canonical directory

Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>

diff --git a/apps/lucene_parser/src/lucene_parse_test.erl b/apps/lucene_parser/src/lucene_parse_test.erl
deleted file mode 100644
index fa58775..0000000
--- a/apps/lucene_parser/src/lucene_parse_test.erl
+++ /dev/null
@@ -1,558 +0,0 @@
-%% -------------------------------------------------------------------
-%%
-%% Copyright (c) 2007-2010 Basho Technologies, Inc.  All Rights Reserved.
-%%
-%% -------------------------------------------------------------------
-
--module(lucene_parse_test).
--include_lib("eunit/include/eunit.hrl").
--include("lucene_parser.hrl").
-
-%% Simple string parsing.
-string1_test() ->
-    Expect = [
-        #string { s="test" }
-    ],
-    test_helper("test", Expect).
-
-%% Two terms.
-string2_test() ->
-    Expect = [
-        #string { s="test1"},
-        #string { s="test2"}
-    ],
-    test_helper("test1 test2", Expect).
-
-%% Combinations of quoted and unquoted strings. 
-string3_test() ->
-    Expect = [
-        #string { s="test1"}, 
-        #string { s="test2"}
-    ],
-    test_helper("\"test1\" test2", Expect),
-    test_helper("'test1' test2", Expect),
-    test_helper("test1 \"test2\"", Expect),
-    test_helper("test1 'test2'", Expect),
-    test_helper("'test1' 'test2'", Expect),
-    test_helper("\"test1\" \"test2\"", Expect).
-
-%% Some special characters.
-string4_test() ->
-    Expect = [
-        #string { s="test1!+-:'\"" },
-        #string { s="!+-:'\"test2"}
-    ],
-    test_helper("'test1!+-:\\'\\\"' '!+-:\\'\\\"test2'", Expect),
-    test_helper("\"test1!+-:'\\\"\" \"!+-:'\\\"test2\"", Expect),
-    test_helper("test1\\!\\+\\-\\:\\'\\\" \\!\\+\\-\\:\\'\\\"test2", Expect).
-
-%% All special characters.
-string5_test() ->
-    Expect = [
-        #string { s="test\"' +-!():^[]{}~*?^|\\test"}
-    ],
-    test_helper("test\\\"\\'\\ \\+\\-\\!\\(\\)\\:\\^\\[\\]\\{\\}\\~*?\\^\\|\\\\test", Expect),
-    test_helper("'test\"\\' +-!():^[]{}~*?^|\\\\test'", Expect),
-    test_helper("\"test\\\"' +-!():^[]{}~*?^|\\\\test\"", Expect).
-
-%% Spaces and tabs.
-string6_test() ->
-    Expect = [
-        #string { s="This is a\ttab."}
-    ],
-    test_helper("'This is a\ttab.'", Expect),
-    test_helper("\"This is a\ttab.\"", Expect).
-
-%% Fields.
-field_test() ->
-    Expect = [
-        #scope {
-            field="field",
-            ops=[#string { s="test" }]
-        }
-    ],
-    test_helper("field:test", Expect),
-    test_helper("field:\"test\"", Expect),
-    test_helper("field:'test'", Expect).
-
-%% Required term, single word.
-required1_test() ->
-    Expect = [
-        #string { s="test", flags=[required] }
-    ],
-    test_helper("+test", Expect),
-    test_helper("+'test'", Expect),
-    test_helper("+\"test\"", Expect).
-
-%% Required term, multiple words.
-required2_test() ->
-    Expect = [
-        #string { s="test1" },
-        #string { s="test2", flags=[required] }
-    ],
-    test_helper("test1 +test2", Expect),
-    test_helper("test1 +'test2'", Expect),
-    test_helper("test1 +\"test2\"", Expect).
-
-%% Prohibited term, single word.
-prohibited1_test() ->
-    Expect = [
-        #negation { op=#string { s="test" } }
-    ],
-    test_helper("-test", Expect),
-    test_helper("-'test'", Expect),
-    test_helper("-\"test\"", Expect).
-
-%% Prohibited term, multiple words.
-prohibited2_test() ->
-    Expect = [
-        #string { s="test1"},
-        #negation { op=#string { s="test2" } }
-    ],
-    test_helper("test1 -test2", Expect),
-    test_helper("test1 -'test2'", Expect),
-    test_helper("test1 -\"test2\"", Expect).
-
-required_and_prohibited1_test() ->
-    Expect = [
-        #intersection { ops=[
-            #scope { field="acc", ops=[#string { s="aab", flags=[required] }] },
-            #negation { op=#scope { field="acc", ops=[#string { s="aac" }] } }
-        ]}
-    ],
-    test_helper("+acc:aab AND -acc:aac", Expect).
-    
-
-%% Intersection.
-intersection1_test() ->
-    Expect = [
-        #intersection { ops=[
-              #string { s="test1"},
-              #string { s="test2"}
-        ]}
-    ],
-    test_helper("test1 AND test2", Expect).
-
-%% Intersection style 2.
-intersection2_test() ->
-    Expect = [
-        #intersection { ops=[
-              #string { s="test1"},
-              #string { s="test2"}
-        ]}
-    ],
-    test_helper("test1 && test2", Expect).
-
-%% Union.
-union1_test() ->
-    Expect = [
-        #union { ops=[
-              #string { s="test1"},
-              #string { s="test2"}
-        ]}
-    ],
-    test_helper("test1 OR test2", Expect).
-
-%% Union style 2.
-union2_test() ->
-    Expect = [
-        #union { ops=[
-              #string { s="test1"},
-              #string { s="test2"}
-        ]}
-    ],
-    test_helper("test1 || test2", Expect).
-
-%% Negation.
-negate1_test() ->
-    Expect = [
-        #string { s="test1" },
-        #negation { op=#string { s="test2" } }
-    ],
-    test_helper("test1 NOT test2", Expect).
-
-%% Negation style 2.
-negate2_test() ->
-    Expect = [
-        #string { s="test1" },
-        #negation { op=#string { s="test2" } }
-    ],
-    test_helper("test1 !test2", Expect).
-
-%% Negate a phrase.
-negate3_test() ->
-    Expect = [
-        #negation { op=#string { s="test1 test2" } }
-    ],
-    test_helper("NOT 'test1 test2'", Expect).
-
-%% Fuzzy without a value.
-fuzzy1_test() ->
-    Expect = [
-        #string { s="test", flags=[{fuzzy, 0.5}]}
-    ],
-    test_helper("test~", Expect).
-
-%% Fuzzy with a value.
-fuzzy2_test() ->
-    Expect = [
-        #string { s="test", flags=[{fuzzy, 0.8}]}
-    ],
-    test_helper("test~0.8", Expect).
-
-%% Multiple fuzzy values.
-fuzzy3_test() ->
-    Expect = [
-        #string { s="test1", flags=[{fuzzy, 0.1}]},
-        #string { s="test2", flags=[{fuzzy, 0.2}]},
-        #string { s="test3", flags=[{fuzzy, 0.3}]}
-    ],
-    test_helper("test1~0.1 test2~0.2 test3~0.3", Expect).
-
-%% Proximity on a single phrase.
-proximity1_test() ->
-    Expect = [
-        #string { s="test", flags=[{proximity, 5}]}
-    ],
-    test_helper("test~5", Expect).
-
-proximity2_test() ->
-    Expect = [
-        #string { s="test1 test2", flags=[{proximity, 5}]}
-    ],
-    test_helper("'test1 test2'~5", Expect),
-    test_helper("\"test1 test2\"~5", Expect).
-
-group1_test() ->
-    Expect = [
-        #string { s="test1"},
-        #group { ops=[
-            #string { s="test2"},
-            #string { s="test3"}
-        ]}
-    ],
-    test_helper("test1 (test2 test3)", Expect),
-    test_helper("'test1' ('test2' \"test3\")", Expect).
-
-group2_test() ->
-    Expect = [
-        #group { ops=[
-            #string { s="test1"},
-            #group { ops=[
-                #string { s="test2"},
-                #string { s="test3"}
-            ]}
-        ]}
-    ],
-    test_helper("(test1 (test2 test3))", Expect),
-    test_helper("('test1' ('test2' \"test3\"))", Expect).
-
-group3_test() ->
-    Expect = [
-        #scope { index="index", field="field", ops=[
-            #group { ops=[
-              #string { s="test1", flags=[required] },
-              #string { s="test2 test3", flags=[required] }
-            ]}
-        ]}
-    ],
-    test_helper("index.field:(+test1 +\"test2 test3\")", Expect).
-
-range1_test() ->
-    Expect = [
-        #range {
-            from=#inclusive { s="begin" },
-            to=#inclusive { s="end" }
-        }
-    ],
-    test_helper("[begin TO end]", Expect).
-
-range2_test() ->
-    Expect = [
-        #scope { field="field", ops=[
-            #range {
-                from=#inclusive { s="begin" },
-                to=#inclusive { s="end" }
-            }
-        ]}
-    ],
-    test_helper("field:[begin TO end]", Expect).
-
-range3_test() ->
-    Expect = [
-        #range {
-            from=#exclusive { s="begin" },
-            to=#exclusive { s="end" }
-        }
-    ],
-    test_helper("{begin TO end}", Expect).
-
-range4_test() ->
-    Expect = [
-        #scope { field="field", ops=[
-            #range {
-                from=#exclusive { s="begin" },
-                to=#exclusive { s="end" }
-            }
-        ]}
-    ],
-    test_helper("field:{begin TO end}", Expect).
-
-boost1_test() ->
-    Expect = [
-        #string { s="test", flags=[{boost, 1.0}] }
-    ],
-    test_helper("test^", Expect).
-
-boost2_test() ->
-    Expect = [
-        #string { s="test0", flags=[{boost, 0.5}] },
-        #string { s="test1", flags=[{boost, 1.0}] },
-        #string { s="test2", flags=[{boost, 2.0}] },
-        #string { s="test 3", flags=[{boost, 3.0}] }
-    ],
-    test_helper("test0^0.5 test1^1 test2^2.0 \"test 3\"^3.0", Expect),
-    test_helper("test0^0.5 test1^ test2^2.0 'test 3'^3.0", Expect).
-
-wildcard1_test() ->
-    Expect = [
-        #string { s="test", flags=[{wildcard,char}] }
-    ],
-    test_helper("test?", Expect).
-
-wildcard2_test() ->
-    Expect = [
-        #string { s="test", flags=[{wildcard,glob}] }
-    ],
-    test_helper("test*", Expect).
-
-integer1_test() ->
-    Expect = [
-        #scope { field="field", ops=[
-            #string { s="123456789"}
-        ]}
-    ],
-    test_helper("field:123456789", Expect).
-
-integer2_test() ->
-    Expect = [
-        #scope { field="field", ops=[
-            #string { s="-123456789"}
-        ]}
-    ],
-    test_helper("field:\\-123456789", Expect),
-    test_helper("field:'-123456789'", Expect),
-    test_helper("field:\"-123456789\"", Expect).
-
-date1_test() ->
-    Expect = [
-        #string { s="2007-04-05T14:30"}
-    ],
-    test_helper("2007\\-04\\-05T14\\:30", Expect),
-    test_helper("'2007-04-05T14:30'", Expect),
-    test_helper("\"2007-04-05T14:30\"", Expect).
-
-date2_test() ->
-    Expect = [
-        #scope { field="field", ops=[
-            #string { s="2007-04-05T14:30"}
-        ]}
-    ],
-    test_helper("field:2007\\-04\\-05T14\\:30", Expect),
-    test_helper("field:'2007-04-05T14:30'", Expect),
-    test_helper("field:\"2007-04-05T14:30\"", Expect).
-
-
-complex1_test() ->
-    Expect = [
-        #scope { field="color", ops=[
-            #group { ops=[
-                #string { s="red" },
-                #string { s="blue" }
-            ]}
-        ]}
-    ],
-    test_helper("color:(red blue)", Expect).
-
-complex2_test() ->
-    Expect = [
-        #intersection { ops=[
-            #scope { field="acc", ops=[#string { s="afa" }]},
-            #scope { field="color", ops=[#string { s="red" }]},
-            #scope { field="parity", ops=[#string { s="even" }]}
-        ]}
-    ],
-    test_helper("acc:afa AND color:red AND parity:even", Expect).
-
-complex3_test() ->
-    Expect = [
-        #scope { field="color", ops=[
-            #union { ops=[
-                #string { s="red" },
-                #string { s="blue" }
-            ]}
-        ]}
-    ],
-    test_helper("color:(red OR blue)", Expect).
-
-complex4_test() ->
-    Expect = [
-        #union { ops=[
-            #scope { field="color", ops=[#string { s="red" }] },
-            #scope { field="parity", ops=[#string { s="odd" }] },
-            #scope { field="key", ops=[#string { s="AAB" }] }
-        ]}
-    ],
-    test_helper("color:red OR parity:odd OR key:AAB", Expect).
-
-complex5_test() ->
-    Expect = [
-        #scope { field="acc", ops=[
-            #intersection { ops=[
-                #string { s="aab" },
-                #negation { op=#string { s="aac" } }
-            ]}
-        ]}
-    ],
-    test_helper( "acc:(aab AND NOT aac)", Expect).
-
-complex7_test() ->
-    Expect = [
-        #scope { field="acc", ops=[
-            #intersection { ops=[
-                #string { s="aab" },
-                #negation { op=#string { s="aac" } }
-            ]}
-        ]}
-    ],
-    test_helper( "acc:(aab AND (NOT aac))", Expect).
-
-complex9_test() ->
-    Expect = [
-        #negation { op=#scope { field="acc", ops=[#string { s="AEB" }] } },
-        #negation { op=#scope { field="parity", ops=[#string { s="even" }] } },
-        #negation { op=#scope { field="color", ops=[#string { s="red" }] } },
-        #negation { op=#scope { field="color", ops=[#string { s="orange" }] } },
-        #negation { op=#scope { field="color", ops=[#string { s="yellow" }] } }
-    ],
-    test_helper( "-acc:AEB -parity:even -color:red -color:orange -color:yellow", Expect).
-
-complex10_test() ->
-    Expect = [
-        #union { ops=[
-            #intersection { ops=[
-                #scope { field="color", ops=[#string { s="red" }] },
-                #union { ops=[
-                    #scope { field="parity", ops=[#string { s="even" }] },
-                    #scope { field="key", ops=[#string { s="ABE" }] }
-                ]}
-            ]},
-            #intersection { ops=[
-                #union { ops=[
-                    #scope { field="color", ops=[#string { s="blue" }] },
-                    #scope { field="key", ops=[#string { s="ABC" }] }
-                ]},
-                #scope { field="parity", ops=[#string { s="odd" }] }
-            ]}
-        ]}
-    ],
-    test_helper( "(color:red AND (parity:even OR key:ABE)) OR ((color:blue OR key:ABC) AND parity:odd)", Expect).
-
-complex11_test() ->
-    Expect = [
-        #intersection { ops=[
-            #union { ops=[
-                #scope { field="color", ops=[#string { s="re", flags=[{wildcard,glob}] }] },
-                #scope { field="color", ops=[#string { s="blub", flags=[{fuzzy, 0.5}] }]}
-            ]},
-            #scope { field="parity", ops=[
-                #range { from={exclusive, "d"}, to={exclusive, "f"} }
-            ]}
-        ]}
-    ],
-    test_helper( "(color:re* OR color:blub~) AND (parity:{d TO f})", Expect).
-
-complex12_test() ->
-    Expect = [
-        #intersection { ops=[
-            #scope { field="acc", ops=[#string { s="afa" }] },
-            #negation { op=#scope { field="acc", ops=[#string { s="aga" }] } },
-            #negation { op=#scope { field="color",
-                                    ops=[#string { s="oran",
-                                                   flags=[{wildcard,glob}] }] }}
-        ]}
-    ],
-    test_helper( "(acc:afa AND -acc:aga) AND -color:oran*", Expect).
-
-complex13_test() ->
-    Expect = [
-        #intersection { ops=[
-            #scope { field="acc", ops=[#string { s="afa" }] },
-            #negation { op=#scope { field="acc", ops=[#string { s="aga" }] } },
-            #negation { op=#scope { field="color",
-                                    ops=[#string { s="oran",
-                                                   flags=[{wildcard,glob}] }] }}
-        ]}
-    ],
-    test_helper( "(acc:afa AND (NOT acc:aga)) AND (NOT color:oran*)", Expect).
-
-complex14_test() ->
-    Expect = [
-        #intersection { ops=[
-            #scope { field="acc", ops=[
-                #group { ops=[
-                    #string { s="afa" },
-                    #negation { op=#string { s="aga" } }
-                ]}
-            ]},
-            #negation { op=#scope { field="color",
-                                    ops=[#string { s="oran",
-                                                   flags=[{wildcard,glob}] }] }}
-        ]}
-    ],
-    test_helper( "acc:(afa NOT aga) AND -color:oran*", Expect).
-
-complex15_test() ->
-    Expect = [
-        #intersection { ops=[
-            #scope { field="acc", ops=[
-                #intersection { ops=[
-                    #string { s="afa" },
-                    #negation { op=#string { s="aga" } }
-                ]}
-            ]},
-            #negation { op=#scope { field="color",
-                                    ops=[#string { s="oran",
-                                                   flags=[{wildcard,glob}] }] }}
-        ]}
-    ],
-    test_helper( "acc:(afa AND (NOT aga)) AND (NOT color:oran*)", Expect).
-
-
-%% Scan and parse a query, compare to what we expect.
-test_helper(String, Expect) ->
-    {ok, Tokens, _} = lucene_scan:string(String),
-    {ok, Actual} = lucene_parse:parse(Tokens),
-    is_equal(Actual, Expect) orelse begin
-        Msg = 
-        "Query   : ~p~n"
-        "Expected: ~p~n"
-        "Actual  : ~p",
-        error_logger:error_msg(Msg, [String, Expect, Actual]),
-        throw({error_parsing_query, String})
-    end.
-
-%% Compare two query trees, ignoring the autogenerated ID.
-is_equal(R1, R2) when is_reference(R1) andalso is_reference(R2) ->
-    true;
-is_equal(L1, L2) 
-  when is_list(L1) andalso length(L1) > 0 andalso is_list(L2) andalso length(L2) > 0 -> 
-    is_equal(hd(L1), hd(L2)) andalso is_equal(tl(L1), tl(L2));
-is_equal(T1, T2) when is_tuple(T1) andalso is_tuple(T2) ->
-    is_equal(tuple_to_list(T1), tuple_to_list(T2));
-is_equal(Other, Other) -> 
-    true;
-is_equal(Other1, Other2) ->
-    error_logger:error_msg("Mismatch: ~p /= ~p", [Other1, Other2]),
-    false.
-
diff --git a/apps/lucene_parser/src/lucene_scan_test.erl b/apps/lucene_parser/src/lucene_scan_test.erl
deleted file mode 100644
index 951bc27..0000000
--- a/apps/lucene_parser/src/lucene_scan_test.erl
+++ /dev/null
@@ -1,382 +0,0 @@
-%% -------------------------------------------------------------------
-%%
-%% Copyright (c) 2007-2010 Basho Technologies, Inc.  All Rights Reserved.
-%%
-%% -------------------------------------------------------------------
-
--module(lucene_scan_test).
--include_lib("eunit/include/eunit.hrl").
-
-%% Simple string parsing.
-string1_test() ->
-    Expect = [
-              {string, 1, "test"}
-             ],
-    test_helper("test", Expect).
-
-%% Two terms.
-string2_test() ->
-    Expect = [
-              {string, 1, "test1"},
-              {string, 1, "test2"}
-             ],
-    test_helper("test1 test2", Expect).
-
-%% Combinations of quoted and unquoted strings. 
-string3_test() ->
-    Expect = [
-              {string, 1, "test1"},
-              {string, 1, "test2"}
-             ],
-    test_helper("\"test1\" test2", Expect),
-    test_helper("'test1' test2", Expect),
-    test_helper("test1 \"test2\"", Expect),
-    test_helper("test1 'test2'", Expect),
-    test_helper("'test1' 'test2'", Expect),
-    test_helper("\"test1\" \"test2\"", Expect).
-
-%% Some special characters.
-string4_test() ->
-    Expect = [
-              {string, 1, "test1!+-:'\""},
-              {string, 1, "!+-:'\"test2"}
-             ],
-    test_helper("'test1!+-:\\'\\\"' '!+-:\\'\\\"test2'", Expect),
-    test_helper("\"test1!+-:'\\\"\" \"!+-:'\\\"test2\"", Expect),
-    test_helper("test1\\!\\+\\-\\:\\'\\\" \\!\\+\\-\\:\\'\\\"test2", Expect).
-
-%% All special characters.
-string5_test() ->
-    Expect = [
-              {string, 1, "test\"' +-!():^[]{}~*?^|\\test"}
-             ],
-    test_helper("test\\\"\\'\\ \\+\\-\\!\\(\\)\\:\\^\\[\\]\\{\\}\\~*?\\^\\|\\\\test", Expect),
-    test_helper("'test\"\\' +-!():^[]{}~*?^|\\\\test'", Expect),
-    test_helper("\"test\\\"' +-!():^[]{}~*?^|\\\\test\"", Expect).
-
-%% Spaces and tabs.
-string6_test() ->
-    Expect = [
-              {string, 1, "This is a\ttab."}
-             ],
-    test_helper("'This is a\ttab.'", Expect),
-    test_helper("\"This is a\ttab.\"", Expect).
-
-%% Scopes.
-scope_test() ->
-    Expect = [
-              {string, 1, "scope"},
-              {scope, 1, ":"},
-              {string, 1, "test"}
-             ],
-    test_helper("scope:test", Expect),
-    test_helper("scope:\"test\"", Expect),
-    test_helper("scope:'test'", Expect).
-
-%% Required term, single word.
-required1_test() ->
-    Expect = [
-              {required, 1, "+"},
-              {string, 1, "test"}
-             ],
-    test_helper("+test", Expect),
-    test_helper("+'test'", Expect),
-    test_helper("+\"test\"", Expect).
-
-%% Required term, multiple words.
-required2_test() ->
-    Expect = [
-              {string, 1, "test1"},
-              {required, 1, "+"},
-              {string, 1, "test2"}
-             ],
-    test_helper("test1 +test2", Expect),
-    test_helper("test1 +'test2'", Expect),
-    test_helper("test1 +\"test2\"", Expect).
-
-%% Prohibited term, single word.
-prohibited1_test() ->
-    Expect = [
-              {prohibited, 1, "-"},
-              {string, 1, "test"}
-             ],
-    test_helper("-test", Expect),
-    test_helper("-'test'", Expect),
-    test_helper("-\"test\"", Expect).
-
-%% Prohibited term, multiple words.
-prohibited2_test() ->
-    Expect = [
-              {string, 1, "test1"},
-              {prohibited, 1, "-"},
-              {string, 1, "test2"}
-             ],
-    test_helper("test1 -test2", Expect),
-    test_helper("test1 -'test2'", Expect),
-    test_helper("test1 -\"test2\"", Expect).
-
-%% Intersection.
-intersection1_test() ->
-    Expect = [
-              {string, 1, "test1"},
-              {intersection, 1, "AND"},
-              {string, 1, "test2"}
-             ],
-    test_helper("test1 AND test2", Expect).
-
-%% Intersection style 2.
-intersection2_test() ->
-    Expect = [
-              {string, 1, "test1"},
-              {intersection, 1, "&&"},
-              {string, 1, "test2"}
-             ],
-    test_helper("test1 && test2", Expect).
-
-%% Union.
-union1_test() ->
-    Expect = [
-              {string, 1, "test1"},
-              {union, 1, "OR"},
-              {string, 1, "test2"}
-             ],
-    test_helper("test1 OR test2", Expect).
-
-%% Union style 2.
-union2_test() ->
-    Expect = [
-              {string, 1, "test1"},
-              {union, 1, "||"},
-              {string, 1, "test2"}
-             ],
-    test_helper("test1 || test2", Expect).
-    
-%% Negation.
-negate1_test() ->
-    Expect = [
-              {string, 1, "test1"},
-              {negation, 1, "NOT"},
-              {string, 1, "test2"}
-             ],
-    test_helper("test1 NOT test2", Expect).
-
-%% Negation style 2.
-negation2_test() ->
-    Expect = [
-              {string, 1, "test1"},
-              {negation, 1, "!"},
-              {string, 1, "test2"}
-             ],
-    test_helper("test1 !test2", Expect).
-
-%% Negation a phrase.
-negation3_test() ->
-    Expect = [
-              {negation, 1, "NOT"},
-              {string, 1, "test1 test2"}
-             ],
-    test_helper("NOT 'test1 test2'", Expect).
-
-%% Fuzzy without a value.
-fuzzy1_test() ->
-    Expect = [
-              {string, 1, "test"},
-              {fuzzy, 1, 0.5}
-             ],
-    test_helper("test~", Expect).
-
-%% Fuzzy with a value.
-fuzzy2_test() ->
-    Expect = [
-              {string, 1, "test"},
-              {fuzzy, 1, 0.8}
-             ],
-    test_helper("test~0.8", Expect).
-
-%% Multiple fuzzy values.
-fuzzy3_test() ->
-    Expect = [
-              {string, 1, "test1"},
-              {fuzzy, 1, 0.1},
-              {string, 1, "test2"},
-              {fuzzy, 1, 0.2},
-              {string, 1, "test3"},
-              {fuzzy, 1, 0.3}
-             ],
-    test_helper("test1~0.1 test2~0.2 test3~0.3", Expect).
-
-%% Proximity on a single phrase.
-proximity1_test() ->
-    Expect = [
-              {string, 1, "test"},
-              {proximity, 1, 5}
-             ],
-    test_helper("test~5", Expect).
-
-proximity2_test() ->
-    Expect = [
-              {string, 1, "test1 test2"},
-              {proximity, 1, 5}
-             ],
-    test_helper("'test1 test2'~5", Expect),
-    test_helper("\"test1 test2\"~5", Expect).
-
-group1_test() ->
-    Expect = [
-              {string, 1, "test1"},
-              {group_start, 1, "("},
-              {string, 1, "test2"},
-              {string, 1, "test3"},
-              {group_end, 1, ")"}
-             ],
-    test_helper("test1 (test2 test3)", Expect),
-    test_helper("'test1' ('test2' \"test3\")", Expect).
-
-group2_test() ->
-    Expect = [
-              {group_start, 1, "("},
-              {string, 1, "test1"},
-              {group_start, 1, "("},
-              {string, 1, "test2"},
-              {string, 1, "test3"},
-              {group_end, 1, ")"},
-              {group_end, 1, ")"}
-             ],
-    test_helper("(test1 (test2 test3))", Expect),
-    test_helper("('test1' ('test2' \"test3\"))", Expect).
-
-group3_test() ->
-    Expect = [
-              {string, 1, "scope"},
-              {scope, 1, ":"},
-              {group_start, 1, "("},
-              {required, 1, "+"},
-              {string, 1, "test1"},
-              {required, 1, "+"},
-              {string, 1, "test2 test3"},
-              {group_end, 1, ")"}
-             ],
-    test_helper("scope:(+test1 +\"test2 test3\")", Expect).
-
-range1_test() ->
-    Expect = [
-              {inclusive_start, 1, "["},
-              {string, 1, "begin"},
-              {range_to, 1, "TO"},
-              {string, 1, "end"},
-              {inclusive_end, 1, "]"}
-             ],
-    test_helper("[begin TO end]", Expect).
-
-range2_test() ->
-    Expect = [
-              {string, 1, "scope"},
-              {scope, 1, ":"},
-              {inclusive_start, 1, "["},
-              {string, 1, "begin"},
-              {range_to, 1, "TO"},
-              {string, 1, "end"},
-              {inclusive_end, 1, "]"}
-             ],
-    test_helper("scope:[begin TO end]", Expect).
-
-range3_test() ->
-    Expect = [
-              {exclusive_start, 1, "{"},
-              {string, 1, "begin"},
-              {range_to, 1, "TO"},
-              {string, 1, "end"},
-              {exclusive_end, 1, "}"}
-             ],
-    test_helper("{begin TO end}", Expect).
-
-range4_test() ->
-    Expect = [
-              {string, 1, "scope"},
-              {scope, 1, ":"},
-              {exclusive_start, 1, "{"},
-              {string, 1, "begin"},
-              {range_to, 1, "TO"},
-              {string, 1, "end"},
-              {exclusive_end, 1, "}"}
-             ],
-    test_helper("scope:{begin TO end}", Expect).
-
-boost1_test() ->
-    Expect = [
-              {string, 1, "test"},
-              {boost, 1, 1}
-             ],
-    test_helper("test^", Expect).
-
-boost2_test() ->
-    Expect = [
-              {string, 1, "test0"},
-              {boost, 1, 0.5},
-              {string, 1, "test1"},
-              {boost, 1, 1.0},
-              {string, 1, "test2"},
-              {boost, 1, 2.0},
-              {string, 1, "test 3"},
-              {boost, 1, 3.0}
-             ],
-    test_helper("test0^0.5 test1^1 test2^2.0 \"test 3\"^3.0", Expect),
-    test_helper("test0^0.5 test1^ test2^2.0 'test 3'^3.0", Expect).
-
-wildcard1_test() ->
-    Expect = [
-              {wildcard_char, 1, "test?"}
-             ],
-    test_helper("test?", Expect).
-
-wildcard2_test() ->
-    Expect = [
-              {wildcard_glob, 1, "test*"}
-             ],
-    test_helper("test*", Expect).
-
-wildcard3_test() ->
-    Expect = [
-              {string, 1, "test\\*"}
-             ],
-    test_helper("test\\*", Expect).
-
-integer1_test() ->
-    Expect = [
-              {string, 1, "scope"},
-              {scope, 1, ":"},
-              {string, 1, "123456789"}
-             ],
-    test_helper("scope:123456789", Expect).
-
-integer2_test() ->
-    Expect = [
-              {string, 1, "scope"},
-              {scope, 1, ":"},
-              {string, 1, "-123456789"}
-             ],
-    test_helper("scope:\\-123456789", Expect),
-    test_helper("scope:'-123456789'", Expect),
-    test_helper("scope:\"-123456789\"", Expect).
-
-time1_test() ->
-    Expect = [
-              {string, 1, "2007-04-05T14:30"}
-             ],
-    test_helper("2007\\-04\\-05T14\\:30", Expect),
-    test_helper("'2007-04-05T14:30'", Expect).
-
-time2_test() ->
-    Expect = [
-              {string, 1, "scope"},
-              {scope, 1, ":"},
-              {string, 1, "2007-04-05T14:30"}
-             ],
-    test_helper("scope:2007\\-04\\-05T14\\:30", Expect),
-    test_helper("scope:'2007-04-05T14:30'", Expect),
-    test_helper("scope:\"2007-04-05T14:30\"", Expect).
-    
-test_helper(String, Expect) ->
-    {ok, Actual, _} = lucene_scan:string(String),
-    Actual == Expect orelse throw({error, String, Actual, Expect}).
-
diff --git a/apps/lucene_parser/test/lucene_parse_test.erl b/apps/lucene_parser/test/lucene_parse_test.erl
new file mode 100644
index 0000000..fa58775
--- /dev/null
+++ b/apps/lucene_parser/test/lucene_parse_test.erl
@@ -0,0 +1,558 @@
+%% -------------------------------------------------------------------
+%%
+%% Copyright (c) 2007-2010 Basho Technologies, Inc.  All Rights Reserved.
+%%
+%% -------------------------------------------------------------------
+
+-module(lucene_parse_test).
+-include_lib("eunit/include/eunit.hrl").
+-include("lucene_parser.hrl").
+
+%% Simple string parsing.
+string1_test() ->
+    Expect = [
+        #string { s="test" }
+    ],
+    test_helper("test", Expect).
+
+%% Two terms.
+string2_test() ->
+    Expect = [
+        #string { s="test1"},
+        #string { s="test2"}
+    ],
+    test_helper("test1 test2", Expect).
+
+%% Combinations of quoted and unquoted strings. 
+string3_test() ->
+    Expect = [
+        #string { s="test1"}, 
+        #string { s="test2"}
+    ],
+    test_helper("\"test1\" test2", Expect),
+    test_helper("'test1' test2", Expect),
+    test_helper("test1 \"test2\"", Expect),
+    test_helper("test1 'test2'", Expect),
+    test_helper("'test1' 'test2'", Expect),
+    test_helper("\"test1\" \"test2\"", Expect).
+
+%% Some special characters.
+string4_test() ->
+    Expect = [
+        #string { s="test1!+-:'\"" },
+        #string { s="!+-:'\"test2"}
+    ],
+    test_helper("'test1!+-:\\'\\\"' '!+-:\\'\\\"test2'", Expect),
+    test_helper("\"test1!+-:'\\\"\" \"!+-:'\\\"test2\"", Expect),
+    test_helper("test1\\!\\+\\-\\:\\'\\\" \\!\\+\\-\\:\\'\\\"test2", Expect).
+
+%% All special characters.
+string5_test() ->
+    Expect = [
+        #string { s="test\"' +-!():^[]{}~*?^|\\test"}
+    ],
+    test_helper("test\\\"\\'\\ \\+\\-\\!\\(\\)\\:\\^\\[\\]\\{\\}\\~*?\\^\\|\\\\test", Expect),
+    test_helper("'test\"\\' +-!():^[]{}~*?^|\\\\test'", Expect),
+    test_helper("\"test\\\"' +-!():^[]{}~*?^|\\\\test\"", Expect).
+
+%% Spaces and tabs.
+string6_test() ->
+    Expect = [
+        #string { s="This is a\ttab."}
+    ],
+    test_helper("'This is a\ttab.'", Expect),
+    test_helper("\"This is a\ttab.\"", Expect).
+
+%% Fields.
+field_test() ->
+    Expect = [
+        #scope {
+            field="field",
+            ops=[#string { s="test" }]
+        }
+    ],
+    test_helper("field:test", Expect),
+    test_helper("field:\"test\"", Expect),
+    test_helper("field:'test'", Expect).
+
+%% Required term, single word.
+required1_test() ->
+    Expect = [
+        #string { s="test", flags=[required] }
+    ],
+    test_helper("+test", Expect),
+    test_helper("+'test'", Expect),
+    test_helper("+\"test\"", Expect).
+
+%% Required term, multiple words.
+required2_test() ->
+    Expect = [
+        #string { s="test1" },
+        #string { s="test2", flags=[required] }
+    ],
+    test_helper("test1 +test2", Expect),
+    test_helper("test1 +'test2'", Expect),
+    test_helper("test1 +\"test2\"", Expect).
+
+%% Prohibited term, single word.
+prohibited1_test() ->
+    Expect = [
+        #negation { op=#string { s="test" } }
+    ],
+    test_helper("-test", Expect),
+    test_helper("-'test'", Expect),
+    test_helper("-\"test\"", Expect).
+
+%% Prohibited term, multiple words.
+prohibited2_test() ->
+    Expect = [
+        #string { s="test1"},
+        #negation { op=#string { s="test2" } }
+    ],
+    test_helper("test1 -test2", Expect),
+    test_helper("test1 -'test2'", Expect),
+    test_helper("test1 -\"test2\"", Expect).
+
+required_and_prohibited1_test() ->
+    Expect = [
+        #intersection { ops=[
+            #scope { field="acc", ops=[#string { s="aab", flags=[required] }] },
+            #negation { op=#scope { field="acc", ops=[#string { s="aac" }] } }
+        ]}
+    ],
+    test_helper("+acc:aab AND -acc:aac", Expect).
+    
+
+%% Intersection.
+intersection1_test() ->
+    Expect = [
+        #intersection { ops=[
+              #string { s="test1"},
+              #string { s="test2"}
+        ]}
+    ],
+    test_helper("test1 AND test2", Expect).
+
+%% Intersection style 2.
+intersection2_test() ->
+    Expect = [
+        #intersection { ops=[
+              #string { s="test1"},
+              #string { s="test2"}
+        ]}
+    ],
+    test_helper("test1 && test2", Expect).
+
+%% Union.
+union1_test() ->
+    Expect = [
+        #union { ops=[
+              #string { s="test1"},
+              #string { s="test2"}
+        ]}
+    ],
+    test_helper("test1 OR test2", Expect).
+
+%% Union style 2.
+union2_test() ->
+    Expect = [
+        #union { ops=[
+              #string { s="test1"},
+              #string { s="test2"}
+        ]}
+    ],
+    test_helper("test1 || test2", Expect).
+
+%% Negation.
+negate1_test() ->
+    Expect = [
+        #string { s="test1" },
+        #negation { op=#string { s="test2" } }
+    ],
+    test_helper("test1 NOT test2", Expect).
+
+%% Negation style 2.
+negate2_test() ->
+    Expect = [
+        #string { s="test1" },
+        #negation { op=#string { s="test2" } }
+    ],
+    test_helper("test1 !test2", Expect).
+
+%% Negate a phrase.
+negate3_test() ->
+    Expect = [
+        #negation { op=#string { s="test1 test2" } }
+    ],
+    test_helper("NOT 'test1 test2'", Expect).
+
+%% Fuzzy without a value.
+fuzzy1_test() ->
+    Expect = [
+        #string { s="test", flags=[{fuzzy, 0.5}]}
+    ],
+    test_helper("test~", Expect).
+
+%% Fuzzy with a value.
+fuzzy2_test() ->
+    Expect = [
+        #string { s="test", flags=[{fuzzy, 0.8}]}
+    ],
+    test_helper("test~0.8", Expect).
+
+%% Multiple fuzzy values.
+fuzzy3_test() ->
+    Expect = [
+        #string { s="test1", flags=[{fuzzy, 0.1}]},
+        #string { s="test2", flags=[{fuzzy, 0.2}]},
+        #string { s="test3", flags=[{fuzzy, 0.3}]}
+    ],
+    test_helper("test1~0.1 test2~0.2 test3~0.3", Expect).
+
+%% Proximity on a single phrase.
+proximity1_test() ->
+    Expect = [
+        #string { s="test", flags=[{proximity, 5}]}
+    ],
+    test_helper("test~5", Expect).
+
+proximity2_test() ->
+    Expect = [
+        #string { s="test1 test2", flags=[{proximity, 5}]}
+    ],
+    test_helper("'test1 test2'~5", Expect),
+    test_helper("\"test1 test2\"~5", Expect).
+
+group1_test() ->
+    Expect = [
+        #string { s="test1"},
+        #group { ops=[
+            #string { s="test2"},
+            #string { s="test3"}
+        ]}
+    ],
+    test_helper("test1 (test2 test3)", Expect),
+    test_helper("'test1' ('test2' \"test3\")", Expect).
+
+group2_test() ->
+    Expect = [
+        #group { ops=[
+            #string { s="test1"},
+            #group { ops=[
+                #string { s="test2"},
+                #string { s="test3"}
+            ]}
+        ]}
+    ],
+    test_helper("(test1 (test2 test3))", Expect),
+    test_helper("('test1' ('test2' \"test3\"))", Expect).
+
+group3_test() ->
+    Expect = [
+        #scope { index="index", field="field", ops=[
+            #group { ops=[
+              #string { s="test1", flags=[required] },
+              #string { s="test2 test3", flags=[required] }
+            ]}
+        ]}
+    ],
+    test_helper("index.field:(+test1 +\"test2 test3\")", Expect).
+
+range1_test() ->
+    Expect = [
+        #range {
+            from=#inclusive { s="begin" },
+            to=#inclusive { s="end" }
+        }
+    ],
+    test_helper("[begin TO end]", Expect).
+
+range2_test() ->
+    Expect = [
+        #scope { field="field", ops=[
+            #range {
+                from=#inclusive { s="begin" },
+                to=#inclusive { s="end" }
+            }
+        ]}
+    ],
+    test_helper("field:[begin TO end]", Expect).
+
+range3_test() ->
+    Expect = [
+        #range {
+            from=#exclusive { s="begin" },
+            to=#exclusive { s="end" }
+        }
+    ],
+    test_helper("{begin TO end}", Expect).
+
+range4_test() ->
+    Expect = [
+        #scope { field="field", ops=[
+            #range {
+                from=#exclusive { s="begin" },
+                to=#exclusive { s="end" }
+            }
+        ]}
+    ],
+    test_helper("field:{begin TO end}", Expect).
+
+boost1_test() ->
+    Expect = [
+        #string { s="test", flags=[{boost, 1.0}] }
+    ],
+    test_helper("test^", Expect).
+
+boost2_test() ->
+    Expect = [
+        #string { s="test0", flags=[{boost, 0.5}] },
+        #string { s="test1", flags=[{boost, 1.0}] },
+        #string { s="test2", flags=[{boost, 2.0}] },
+        #string { s="test 3", flags=[{boost, 3.0}] }
+    ],
+    test_helper("test0^0.5 test1^1 test2^2.0 \"test 3\"^3.0", Expect),
+    test_helper("test0^0.5 test1^ test2^2.0 'test 3'^3.0", Expect).
+
+wildcard1_test() ->
+    Expect = [
+        #string { s="test", flags=[{wildcard,char}] }
+    ],
+    test_helper("test?", Expect).
+
+wildcard2_test() ->
+    Expect = [
+        #string { s="test", flags=[{wildcard,glob}] }
+    ],
+    test_helper("test*", Expect).
+
+integer1_test() ->
+    Expect = [
+        #scope { field="field", ops=[
+            #string { s="123456789"}
+        ]}
+    ],
+    test_helper("field:123456789", Expect).
+
+integer2_test() ->
+    Expect = [
+        #scope { field="field", ops=[
+            #string { s="-123456789"}
+        ]}
+    ],
+    test_helper("field:\\-123456789", Expect),
+    test_helper("field:'-123456789'", Expect),
+    test_helper("field:\"-123456789\"", Expect).
+
+date1_test() ->
+    Expect = [
+        #string { s="2007-04-05T14:30"}
+    ],
+    test_helper("2007\\-04\\-05T14\\:30", Expect),
+    test_helper("'2007-04-05T14:30'", Expect),
+    test_helper("\"2007-04-05T14:30\"", Expect).
+
+date2_test() ->
+    Expect = [
+        #scope { field="field", ops=[
+            #string { s="2007-04-05T14:30"}
+        ]}
+    ],
+    test_helper("field:2007\\-04\\-05T14\\:30", Expect),
+    test_helper("field:'2007-04-05T14:30'", Expect),
+    test_helper("field:\"2007-04-05T14:30\"", Expect).
+
+
+complex1_test() ->
+    Expect = [
+        #scope { field="color", ops=[
+            #group { ops=[
+                #string { s="red" },
+                #string { s="blue" }
+            ]}
+        ]}
+    ],
+    test_helper("color:(red blue)", Expect).
+
+complex2_test() ->
+    Expect = [
+        #intersection { ops=[
+            #scope { field="acc", ops=[#string { s="afa" }]},
+            #scope { field="color", ops=[#string { s="red" }]},
+            #scope { field="parity", ops=[#string { s="even" }]}
+        ]}
+    ],
+    test_helper("acc:afa AND color:red AND parity:even", Expect).
+
+complex3_test() ->
+    Expect = [
+        #scope { field="color", ops=[
+            #union { ops=[
+                #string { s="red" },
+                #string { s="blue" }
+            ]}
+        ]}
+    ],
+    test_helper("color:(red OR blue)", Expect).
+
+complex4_test() ->
+    Expect = [
+        #union { ops=[
+            #scope { field="color", ops=[#string { s="red" }] },
+            #scope { field="parity", ops=[#string { s="odd" }] },
+            #scope { field="key", ops=[#string { s="AAB" }] }
+        ]}
+    ],
+    test_helper("color:red OR parity:odd OR key:AAB", Expect).
+
+complex5_test() ->
+    Expect = [
+        #scope { field="acc", ops=[
+            #intersection { ops=[
+                #string { s="aab" },
+                #negation { op=#string { s="aac" } }
+            ]}
+        ]}
+    ],
+    test_helper( "acc:(aab AND NOT aac)", Expect).
+
+complex7_test() ->
+    Expect = [
+        #scope { field="acc", ops=[
+            #intersection { ops=[
+                #string { s="aab" },
+                #negation { op=#string { s="aac" } }
+            ]}
+        ]}
+    ],
+    test_helper( "acc:(aab AND (NOT aac))", Expect).
+
+complex9_test() ->
+    Expect = [
+        #negation { op=#scope { field="acc", ops=[#string { s="AEB" }] } },
+        #negation { op=#scope { field="parity", ops=[#string { s="even" }] } },
+        #negation { op=#scope { field="color", ops=[#string { s="red" }] } },
+        #negation { op=#scope { field="color", ops=[#string { s="orange" }] } },
+        #negation { op=#scope { field="color", ops=[#string { s="yellow" }] } }
+    ],
+    test_helper( "-acc:AEB -parity:even -color:red -color:orange -color:yellow", Expect).
+
+complex10_test() ->
+    Expect = [
+        #union { ops=[
+            #intersection { ops=[
+                #scope { field="color", ops=[#string { s="red" }] },
+                #union { ops=[
+                    #scope { field="parity", ops=[#string { s="even" }] },
+                    #scope { field="key", ops=[#string { s="ABE" }] }
+                ]}
+            ]},
+            #intersection { ops=[
+                #union { ops=[
+                    #scope { field="color", ops=[#string { s="blue" }] },
+                    #scope { field="key", ops=[#string { s="ABC" }] }
+                ]},
+                #scope { field="parity", ops=[#string { s="odd" }] }
+            ]}
+        ]}
+    ],
+    test_helper( "(color:red AND (parity:even OR key:ABE)) OR ((color:blue OR key:ABC) AND parity:odd)", Expect).
+
+complex11_test() ->
+    Expect = [
+        #intersection { ops=[
+            #union { ops=[
+                #scope { field="color", ops=[#string { s="re", flags=[{wildcard,glob}] }] },
+                #scope { field="color", ops=[#string { s="blub", flags=[{fuzzy, 0.5}] }]}
+            ]},
+            #scope { field="parity", ops=[
+                #range { from={exclusive, "d"}, to={exclusive, "f"} }
+            ]}
+        ]}
+    ],
+    test_helper( "(color:re* OR color:blub~) AND (parity:{d TO f})", Expect).
+
+complex12_test() ->
+    Expect = [
+        #intersection { ops=[
+            #scope { field="acc", ops=[#string { s="afa" }] },
+            #negation { op=#scope { field="acc", ops=[#string { s="aga" }] } },
+            #negation { op=#scope { field="color",
+                                    ops=[#string { s="oran",
+                                                   flags=[{wildcard,glob}] }] }}
+        ]}
+    ],
+    test_helper( "(acc:afa AND -acc:aga) AND -color:oran*", Expect).
+
+complex13_test() ->
+    Expect = [
+        #intersection { ops=[
+            #scope { field="acc", ops=[#string { s="afa" }] },
+            #negation { op=#scope { field="acc", ops=[#string { s="aga" }] } },
+            #negation { op=#scope { field="color",
+                                    ops=[#string { s="oran",
+                                                   flags=[{wildcard,glob}] }] }}
+        ]}
+    ],
+    test_helper( "(acc:afa AND (NOT acc:aga)) AND (NOT color:oran*)", Expect).
+
+complex14_test() ->
+    Expect = [
+        #intersection { ops=[
+            #scope { field="acc", ops=[
+                #group { ops=[
+                    #string { s="afa" },
+                    #negation { op=#string { s="aga" } }
+                ]}
+            ]},
+            #negation { op=#scope { field="color",
+                                    ops=[#string { s="oran",
+                                                   flags=[{wildcard,glob}] }] }}
+        ]}
+    ],
+    test_helper( "acc:(afa NOT aga) AND -color:oran*", Expect).
+
+complex15_test() ->
+    Expect = [
+        #intersection { ops=[
+            #scope { field="acc", ops=[
+                #intersection { ops=[
+                    #string { s="afa" },
+                    #negation { op=#string { s="aga" } }
+                ]}
+            ]},
+            #negation { op=#scope { field="color",
+                                    ops=[#string { s="oran",
+                                                   flags=[{wildcard,glob}] }] }}
+        ]}
+    ],
+    test_helper( "acc:(afa AND (NOT aga)) AND (NOT color:oran*)", Expect).
+
+
+%% Scan and parse a query, compare to what we expect.
+test_helper(String, Expect) ->
+    {ok, Tokens, _} = lucene_scan:string(String),
+    {ok, Actual} = lucene_parse:parse(Tokens),
+    is_equal(Actual, Expect) orelse begin
+        Msg = 
+        "Query   : ~p~n"
+        "Expected: ~p~n"
+        "Actual  : ~p",
+        error_logger:error_msg(Msg, [String, Expect, Actual]),
+        throw({error_parsing_query, String})
+    end.
+
+%% Compare two query trees, ignoring the autogenerated ID.
+is_equal(R1, R2) when is_reference(R1) andalso is_reference(R2) ->
+    true;
+is_equal(L1, L2) 
+  when is_list(L1) andalso length(L1) > 0 andalso is_list(L2) andalso length(L2) > 0 -> 
+    is_equal(hd(L1), hd(L2)) andalso is_equal(tl(L1), tl(L2));
+is_equal(T1, T2) when is_tuple(T1) andalso is_tuple(T2) ->
+    is_equal(tuple_to_list(T1), tuple_to_list(T2));
+is_equal(Other, Other) -> 
+    true;
+is_equal(Other1, Other2) ->
+    error_logger:error_msg("Mismatch: ~p /= ~p", [Other1, Other2]),
+    false.
+
diff --git a/apps/lucene_parser/test/lucene_scan_test.erl b/apps/lucene_parser/test/lucene_scan_test.erl
new file mode 100644
index 0000000..951bc27
--- /dev/null
+++ b/apps/lucene_parser/test/lucene_scan_test.erl
@@ -0,0 +1,382 @@
+%% -------------------------------------------------------------------
+%%
+%% Copyright (c) 2007-2010 Basho Technologies, Inc.  All Rights Reserved.
+%%
+%% -------------------------------------------------------------------
+
+-module(lucene_scan_test).
+-include_lib("eunit/include/eunit.hrl").
+
+%% Simple string parsing.
+string1_test() ->
+    Expect = [
+              {string, 1, "test"}
+             ],
+    test_helper("test", Expect).
+
+%% Two terms.
+string2_test() ->
+    Expect = [
+              {string, 1, "test1"},
+              {string, 1, "test2"}
+             ],
+    test_helper("test1 test2", Expect).
+
+%% Combinations of quoted and unquoted strings. 
+string3_test() ->
+    Expect = [
+              {string, 1, "test1"},
+              {string, 1, "test2"}
+             ],
+    test_helper("\"test1\" test2", Expect),
+    test_helper("'test1' test2", Expect),
+    test_helper("test1 \"test2\"", Expect),
+    test_helper("test1 'test2'", Expect),
+    test_helper("'test1' 'test2'", Expect),
+    test_helper("\"test1\" \"test2\"", Expect).
+
+%% Some special characters.
+string4_test() ->
+    Expect = [
+              {string, 1, "test1!+-:'\""},
+              {string, 1, "!+-:'\"test2"}
+             ],
+    test_helper("'test1!+-:\\'\\\"' '!+-:\\'\\\"test2'", Expect),
+    test_helper("\"test1!+-:'\\\"\" \"!+-:'\\\"test2\"", Expect),
+    test_helper("test1\\!\\+\\-\\:\\'\\\" \\!\\+\\-\\:\\'\\\"test2", Expect).
+
+%% All special characters.
+string5_test() ->
+    Expect = [
+              {string, 1, "test\"' +-!():^[]{}~*?^|\\test"}
+             ],
+    test_helper("test\\\"\\'\\ \\+\\-\\!\\(\\)\\:\\^\\[\\]\\{\\}\\~*?\\^\\|\\\\test", Expect),
+    test_helper("'test\"\\' +-!():^[]{}~*?^|\\\\test'", Expect),
+    test_helper("\"test\\\"' +-!():^[]{}~*?^|\\\\test\"", Expect).
+
+%% Spaces and tabs.
+string6_test() ->
+    Expect = [
+              {string, 1, "This is a\ttab."}
+             ],
+    test_helper("'This is a\ttab.'", Expect),
+    test_helper("\"This is a\ttab.\"", Expect).
+
+%% Scopes.
+scope_test() ->
+    Expect = [
+              {string, 1, "scope"},
+              {scope, 1, ":"},
+              {string, 1, "test"}
+             ],
+    test_helper("scope:test", Expect),
+    test_helper("scope:\"test\"", Expect),
+    test_helper("scope:'test'", Expect).
+
+%% Required term, single word.
+required1_test() ->
+    Expect = [
+              {required, 1, "+"},
+              {string, 1, "test"}
+             ],
+    test_helper("+test", Expect),
+    test_helper("+'test'", Expect),
+    test_helper("+\"test\"", Expect).
+
+%% Required term, multiple words.
+required2_test() ->
+    Expect = [
+              {string, 1, "test1"},
+              {required, 1, "+"},
+              {string, 1, "test2"}
+             ],
+    test_helper("test1 +test2", Expect),
+    test_helper("test1 +'test2'", Expect),
+    test_helper("test1 +\"test2\"", Expect).
+
+%% Prohibited term, single word.
+prohibited1_test() ->
+    Expect = [
+              {prohibited, 1, "-"},
+              {string, 1, "test"}
+             ],
+    test_helper("-test", Expect),
+    test_helper("-'test'", Expect),
+    test_helper("-\"test\"", Expect).
+
+%% Prohibited term, multiple words.
+prohibited2_test() ->
+    Expect = [
+              {string, 1, "test1"},
+              {prohibited, 1, "-"},
+              {string, 1, "test2"}
+             ],
+    test_helper("test1 -test2", Expect),
+    test_helper("test1 -'test2'", Expect),
+    test_helper("test1 -\"test2\"", Expect).
+
+%% Intersection.
+intersection1_test() ->
+    Expect = [
+              {string, 1, "test1"},
+              {intersection, 1, "AND"},
+              {string, 1, "test2"}
+             ],
+    test_helper("test1 AND test2", Expect).
+
+%% Intersection style 2.
+intersection2_test() ->
+    Expect = [
+              {string, 1, "test1"},
+              {intersection, 1, "&&"},
+              {string, 1, "test2"}
+             ],
+    test_helper("test1 && test2", Expect).
+
+%% Union.
+union1_test() ->
+    Expect = [
+              {string, 1, "test1"},
+              {union, 1, "OR"},
+              {string, 1, "test2"}
+             ],
+    test_helper("test1 OR test2", Expect).
+
+%% Union style 2.
+union2_test() ->
+    Expect = [
+              {string, 1, "test1"},
+              {union, 1, "||"},
+              {string, 1, "test2"}
+             ],
+    test_helper("test1 || test2", Expect).
+    
+%% Negation.
+negate1_test() ->
+    Expect = [
+              {string, 1, "test1"},
+              {negation, 1, "NOT"},
+              {string, 1, "test2"}
+             ],
+    test_helper("test1 NOT test2", Expect).
+
+%% Negation style 2.
+negation2_test() ->
+    Expect = [
+              {string, 1, "test1"},
+              {negation, 1, "!"},
+              {string, 1, "test2"}
+             ],
+    test_helper("test1 !test2", Expect).
+
+%% Negation a phrase.
+negation3_test() ->
+    Expect = [
+              {negation, 1, "NOT"},
+              {string, 1, "test1 test2"}
+             ],
+    test_helper("NOT 'test1 test2'", Expect).
+
+%% Fuzzy without a value.
+fuzzy1_test() ->
+    Expect = [
+              {string, 1, "test"},
+              {fuzzy, 1, 0.5}
+             ],
+    test_helper("test~", Expect).
+
+%% Fuzzy with a value.
+fuzzy2_test() ->
+    Expect = [
+              {string, 1, "test"},
+              {fuzzy, 1, 0.8}
+             ],
+    test_helper("test~0.8", Expect).
+
+%% Multiple fuzzy values.
+fuzzy3_test() ->
+    Expect = [
+              {string, 1, "test1"},
+              {fuzzy, 1, 0.1},
+              {string, 1, "test2"},
+              {fuzzy, 1, 0.2},
+              {string, 1, "test3"},
+              {fuzzy, 1, 0.3}
+             ],
+    test_helper("test1~0.1 test2~0.2 test3~0.3", Expect).
+
+%% Proximity on a single phrase.
+proximity1_test() ->
+    Expect = [
+              {string, 1, "test"},
+              {proximity, 1, 5}
+             ],
+    test_helper("test~5", Expect).
+
+proximity2_test() ->
+    Expect = [
+              {string, 1, "test1 test2"},
+              {proximity, 1, 5}
+             ],
+    test_helper("'test1 test2'~5", Expect),
+    test_helper("\"test1 test2\"~5", Expect).
+
+group1_test() ->
+    Expect = [
+              {string, 1, "test1"},
+              {group_start, 1, "("},
+              {string, 1, "test2"},
+              {string, 1, "test3"},
+              {group_end, 1, ")"}
+             ],
+    test_helper("test1 (test2 test3)", Expect),
+    test_helper("'test1' ('test2' \"test3\")", Expect).
+
+group2_test() ->
+    Expect = [
+              {group_start, 1, "("},
+              {string, 1, "test1"},
+              {group_start, 1, "("},
+              {string, 1, "test2"},
+              {string, 1, "test3"},
+              {group_end, 1, ")"},
+              {group_end, 1, ")"}
+             ],
+    test_helper("(test1 (test2 test3))", Expect),
+    test_helper("('test1' ('test2' \"test3\"))", Expect).
+
+group3_test() ->
+    Expect = [
+              {string, 1, "scope"},
+              {scope, 1, ":"},
+              {group_start, 1, "("},
+              {required, 1, "+"},
+              {string, 1, "test1"},
+              {required, 1, "+"},
+              {string, 1, "test2 test3"},
+              {group_end, 1, ")"}
+             ],
+    test_helper("scope:(+test1 +\"test2 test3\")", Expect).
+
+range1_test() ->
+    Expect = [
+              {inclusive_start, 1, "["},
+              {string, 1, "begin"},
+              {range_to, 1, "TO"},
+              {string, 1, "end"},
+              {inclusive_end, 1, "]"}
+             ],
+    test_helper("[begin TO end]", Expect).
+
+range2_test() ->
+    Expect = [
+              {string, 1, "scope"},
+              {scope, 1, ":"},
+              {inclusive_start, 1, "["},
+              {string, 1, "begin"},
+              {range_to, 1, "TO"},
+              {string, 1, "end"},
+              {inclusive_end, 1, "]"}
+             ],
+    test_helper("scope:[begin TO end]", Expect).
+
+range3_test() ->
+    Expect = [
+              {exclusive_start, 1, "{"},
+              {string, 1, "begin"},
+              {range_to, 1, "TO"},
+              {string, 1, "end"},
+              {exclusive_end, 1, "}"}
+             ],
+    test_helper("{begin TO end}", Expect).
+
+range4_test() ->
+    Expect = [
+              {string, 1, "scope"},
+              {scope, 1, ":"},
+              {exclusive_start, 1, "{"},
+              {string, 1, "begin"},
+              {range_to, 1, "TO"},
+              {string, 1, "end"},
+              {exclusive_end, 1, "}"}
+             ],
+    test_helper("scope:{begin TO end}", Expect).
+
+boost1_test() ->
+    Expect = [
+              {string, 1, "test"},
+              {boost, 1, 1}
+             ],
+    test_helper("test^", Expect).
+
+boost2_test() ->
+    Expect = [
+              {string, 1, "test0"},
+              {boost, 1, 0.5},
+              {string, 1, "test1"},
+              {boost, 1, 1.0},
+              {string, 1, "test2"},
+              {boost, 1, 2.0},
+              {string, 1, "test 3"},
+              {boost, 1, 3.0}
+             ],
+    test_helper("test0^0.5 test1^1 test2^2.0 \"test 3\"^3.0", Expect),
+    test_helper("test0^0.5 test1^ test2^2.0 'test 3'^3.0", Expect).
+
+wildcard1_test() ->
+    Expect = [
+              {wildcard_char, 1, "test?"}
+             ],
+    test_helper("test?", Expect).
+
+wildcard2_test() ->
+    Expect = [
+              {wildcard_glob, 1, "test*"}
+             ],
+    test_helper("test*", Expect).
+
+wildcard3_test() ->
+    Expect = [
+              {string, 1, "test\\*"}
+             ],
+    test_helper("test\\*", Expect).
+
+integer1_test() ->
+    Expect = [
+              {string, 1, "scope"},
+              {scope, 1, ":"},
+              {string, 1, "123456789"}
+             ],
+    test_helper("scope:123456789", Expect).
+
+integer2_test() ->
+    Expect = [
+              {string, 1, "scope"},
+              {scope, 1, ":"},
+              {string, 1, "-123456789"}
+             ],
+    test_helper("scope:\\-123456789", Expect),
+    test_helper("scope:'-123456789'", Expect),
+    test_helper("scope:\"-123456789\"", Expect).
+
+time1_test() ->
+    Expect = [
+              {string, 1, "2007-04-05T14:30"}
+             ],
+    test_helper("2007\\-04\\-05T14\\:30", Expect),
+    test_helper("'2007-04-05T14:30'", Expect).
+
+time2_test() ->
+    Expect = [
+              {string, 1, "scope"},
+              {scope, 1, ":"},
+              {string, 1, "2007-04-05T14:30"}
+             ],
+    test_helper("scope:2007\\-04\\-05T14\\:30", Expect),
+    test_helper("scope:'2007-04-05T14:30'", Expect),
+    test_helper("scope:\"2007-04-05T14:30\"", Expect).
+    
+test_helper(String, Expect) ->
+    {ok, Actual, _} = lucene_scan:string(String),
+    Actual == Expect orelse throw({error, String, Actual, Expect}).
+