lucenenet-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From synhers...@apache.org
Subject [02/50] [abbrv] lucenenet git commit: Ported tests for the QueryParser.Classic namespace and refactored QueryParserTestBase so the test runner will run all of the tests.
Date Sun, 11 Sep 2016 21:30:33 GMT
Ported tests for the QueryParser.Classic namespace and refactored QueryParserTestBase so the test runner will run all of the tests.


Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/6d711567
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/6d711567
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/6d711567

Branch: refs/heads/master
Commit: 6d711567c20492c89fc59be440be8a56d918235c
Parents: ca1a374
Author: Shad Storhaug <shad@shadstorhaug.com>
Authored: Sun Jul 31 16:48:21 2016 +0700
Committer: Shad Storhaug <shad@shadstorhaug.com>
Committed: Fri Sep 2 22:29:37 2016 +0700

----------------------------------------------------------------------
 .../Classic/TestMultiAnalyzer.cs                |  278 ++++
 .../Classic/TestMultiFieldQueryParser.cs        |  376 +++++
 .../Classic/TestMultiPhraseQueryParsing.cs      |  121 ++
 .../Classic/TestQueryParser.cs                  |  554 +++++++
 .../Lucene.Net.Tests.QueryParser.csproj         |   82 +
 .../Properties/AssemblyInfo.cs                  |   36 +
 .../Util/QueryParserTestBase.cs                 | 1499 ++++++++++++++++++
 Lucene.Net.Tests.QueryParser/packages.config    |    4 +
 Lucene.Net.sln                                  |   12 +
 9 files changed, 2962 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/6d711567/Lucene.Net.Tests.QueryParser/Classic/TestMultiAnalyzer.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.Tests.QueryParser/Classic/TestMultiAnalyzer.cs b/Lucene.Net.Tests.QueryParser/Classic/TestMultiAnalyzer.cs
new file mode 100644
index 0000000..fc1ce0c
--- /dev/null
+++ b/Lucene.Net.Tests.QueryParser/Classic/TestMultiAnalyzer.cs
@@ -0,0 +1,278 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NUnit.Framework;
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Tokenattributes;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+
+namespace Lucene.Net.QueryParser.Classic
+{
+    [TestFixture]
+    public class TestMultiAnalyzer_ : BaseTokenStreamTestCase
+    {
+
+        private static int multiToken = 0;
+
+        [Test]
+        public void TestMultiAnalyzer()
+        {
+
+            QueryParser qp = new QueryParser(TEST_VERSION_CURRENT, "", new MultiAnalyzer());
+
+            // trivial, no multiple tokens:
+            assertEquals("foo", qp.Parse("foo").toString());
+            assertEquals("foo", qp.Parse("\"foo\"").toString());
+            assertEquals("foo foobar", qp.Parse("foo foobar").toString());
+            assertEquals("\"foo foobar\"", qp.Parse("\"foo foobar\"").toString());
+            assertEquals("\"foo foobar blah\"", qp.Parse("\"foo foobar blah\"").toString());
+
+            // two tokens at the same position:
+            assertEquals("(multi multi2) foo", qp.Parse("multi foo").toString());
+            assertEquals("foo (multi multi2)", qp.Parse("foo multi").toString());
+            assertEquals("(multi multi2) (multi multi2)", qp.Parse("multi multi").toString());
+            assertEquals("+(foo (multi multi2)) +(bar (multi multi2))",
+                qp.Parse("+(foo multi) +(bar multi)").toString());
+            assertEquals("+(foo (multi multi2)) field:\"bar (multi multi2)\"",
+                qp.Parse("+(foo multi) field:\"bar multi\"").toString());
+
+            // phrases:
+            assertEquals("\"(multi multi2) foo\"", qp.Parse("\"multi foo\"").toString());
+            assertEquals("\"foo (multi multi2)\"", qp.Parse("\"foo multi\"").toString());
+            assertEquals("\"foo (multi multi2) foobar (multi multi2)\"",
+                qp.Parse("\"foo multi foobar multi\"").toString());
+
+            // fields:
+            assertEquals("(field:multi field:multi2) field:foo", qp.Parse("field:multi field:foo").toString());
+            assertEquals("field:\"(multi multi2) foo\"", qp.Parse("field:\"multi foo\"").toString());
+
+            // three tokens at one position:
+            assertEquals("triplemulti multi3 multi2", qp.Parse("triplemulti").toString());
+            assertEquals("foo (triplemulti multi3 multi2) foobar",
+                qp.Parse("foo triplemulti foobar").toString());
+
+            // phrase with non-default slop:
+            assertEquals("\"(multi multi2) foo\"~10", qp.Parse("\"multi foo\"~10").toString());
+
+            // phrase with non-default boost:
+            assertEquals("\"(multi multi2) foo\"^2.0", qp.Parse("\"multi foo\"^2").toString());
+
+            // phrase after changing default slop
+            qp.PhraseSlop=(99);
+            assertEquals("\"(multi multi2) foo\"~99 bar",
+                         qp.Parse("\"multi foo\" bar").toString());
+            assertEquals("\"(multi multi2) foo\"~99 \"foo bar\"~2",
+                         qp.Parse("\"multi foo\" \"foo bar\"~2").toString());
+            qp.PhraseSlop=(0);
+
+            // non-default operator:
+            qp.DefaultOperator=(QueryParserBase.AND_OPERATOR);
+            assertEquals("+(multi multi2) +foo", qp.Parse("multi foo").toString());
+
+        }
+
+        [Test]
+        public void TestMultiAnalyzerWithSubclassOfQueryParser()
+        {
+
+            DumbQueryParser qp = new DumbQueryParser("", new MultiAnalyzer());
+            qp.PhraseSlop = (99); // modified default slop
+
+            // direct call to (super's) getFieldQuery to demonstrate differnce
+            // between phrase and multiphrase with modified default slop
+            assertEquals("\"foo bar\"~99",
+                         qp.GetSuperFieldQuery("", "foo bar", true).toString());
+            assertEquals("\"(multi multi2) bar\"~99",
+                         qp.GetSuperFieldQuery("", "multi bar", true).toString());
+
+
+            // ask sublcass to parse phrase with modified default slop
+            assertEquals("\"(multi multi2) foo\"~99 bar",
+                         qp.Parse("\"multi foo\" bar").toString());
+
+        }
+
+        [Test]
+        public void TestPosIncrementAnalyzer()
+        {
+            QueryParser qp = new QueryParser(LuceneVersion.LUCENE_40, "", new PosIncrementAnalyzer());
+            assertEquals("quick brown", qp.Parse("the quick brown").toString());
+            assertEquals("quick brown fox", qp.Parse("the quick brown fox").toString());
+        }
+
+        /// <summary>
+        /// Expands "multi" to "multi" and "multi2", both at the same position,
+        /// and expands "triplemulti" to "triplemulti", "multi3", and "multi2".  
+        /// </summary>
+        private class MultiAnalyzer : Analyzer
+        {
+            public override TokenStreamComponents CreateComponents(string fieldName, System.IO.TextReader reader)
+            {
+                Tokenizer result = new MockTokenizer(reader, MockTokenizer.WHITESPACE, true);
+                return new TokenStreamComponents(result, new TestFilter(result));
+            }
+        }
+
+        private sealed class TestFilter : TokenFilter
+        {
+
+            private string prevType;
+            private int prevStartOffset;
+            private int prevEndOffset;
+
+            private readonly ICharTermAttribute termAtt;
+            private readonly IPositionIncrementAttribute posIncrAtt;
+            private readonly IOffsetAttribute offsetAtt;
+            private readonly ITypeAttribute typeAtt;
+
+            public TestFilter(TokenStream @in)
+                : base(@in)
+            {
+                termAtt = AddAttribute<ICharTermAttribute>();
+                posIncrAtt = AddAttribute<IPositionIncrementAttribute>();
+                offsetAtt = AddAttribute<IOffsetAttribute>();
+                typeAtt = AddAttribute<ITypeAttribute>();
+            }
+
+            public override bool IncrementToken()
+            {
+                if (multiToken > 0)
+                {
+                    termAtt.SetEmpty().Append("multi" + (multiToken + 1));
+                    offsetAtt.SetOffset(prevStartOffset, prevEndOffset);
+                    typeAtt.Type = (prevType);
+                    posIncrAtt.PositionIncrement = (0);
+                    multiToken--;
+                    return true;
+                }
+                else
+                {
+                    bool next = input.IncrementToken();
+                    if (!next)
+                    {
+                        return false;
+                    }
+                    prevType = typeAtt.Type;
+                    prevStartOffset = offsetAtt.StartOffset();
+                    prevEndOffset = offsetAtt.EndOffset();
+                    string text = termAtt.toString();
+                    if (text.equals("triplemulti"))
+                    {
+                        multiToken = 2;
+                        return true;
+                    }
+                    else if (text.equals("multi"))
+                    {
+                        multiToken = 1;
+                        return true;
+                    }
+                    else
+                    {
+                        return true;
+                    }
+                }
+            }
+
+            public override void Reset()
+            {
+                base.Reset();
+                this.prevType = null;
+                this.prevStartOffset = 0;
+                this.prevEndOffset = 0;
+            }
+        }
+
+        /// <summary>
+        /// Analyzes "the quick brown" as: quick(incr=2) brown(incr=1).
+        /// Does not work correctly for input other than "the quick brown ...".
+        /// </summary>
+        private class PosIncrementAnalyzer : Analyzer
+        {
+            public override TokenStreamComponents CreateComponents(string fieldName, System.IO.TextReader reader)
+            {
+                Tokenizer result = new MockTokenizer(reader, MockTokenizer.WHITESPACE, true);
+                return new TokenStreamComponents(result, new TestPosIncrementFilter(result));
+            }
+        }
+
+        private sealed class TestPosIncrementFilter : TokenFilter
+        {
+            ICharTermAttribute termAtt;
+            IPositionIncrementAttribute posIncrAtt;
+
+            public TestPosIncrementFilter(TokenStream @in)
+                : base(@in)
+            {
+                termAtt = AddAttribute<ICharTermAttribute>();
+                posIncrAtt = AddAttribute<IPositionIncrementAttribute>();
+            }
+
+            public override bool IncrementToken()
+            {
+                while (input.IncrementToken())
+                {
+                    if (termAtt.toString().equals("the"))
+                    {
+                        // stopword, do nothing
+                    }
+                    else if (termAtt.toString().equals("quick"))
+                    {
+                        posIncrAtt.PositionIncrement = (2);
+                        return true;
+                    }
+                    else
+                    {
+                        posIncrAtt.PositionIncrement = (1);
+                        return true;
+                    }
+                }
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// a very simple subclass of QueryParser
+        /// </summary>
+        private sealed class DumbQueryParser : QueryParser
+        {
+            public DumbQueryParser(string f, Analyzer a)
+                : base(TEST_VERSION_CURRENT, f, a)
+            {
+            }
+
+            // expose super's version 
+            public Query GetSuperFieldQuery(string f, string t, bool quoted)
+            {
+                return base.GetFieldQuery(f, t, quoted);
+            }
+
+            // wrap super's version
+            protected override Query GetFieldQuery(string field, string queryText, bool quoted)
+            {
+                return new DumbQueryWrapper(GetSuperFieldQuery(field, queryText, quoted));
+            }
+        }
+
+        /// <summary>
+        /// A very simple wrapper to prevent instanceof checks but uses
+        /// the toString of the query it wraps.
+        /// </summary>
+        private sealed class DumbQueryWrapper : Query
+        {
+            private Query q;
+            public DumbQueryWrapper(Query q)
+            {
+                this.q = q;
+            }
+
+            public override string ToString(string field)
+            {
+                return q.ToString(field);
+            }
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/6d711567/Lucene.Net.Tests.QueryParser/Classic/TestMultiFieldQueryParser.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.Tests.QueryParser/Classic/TestMultiFieldQueryParser.cs b/Lucene.Net.Tests.QueryParser/Classic/TestMultiFieldQueryParser.cs
new file mode 100644
index 0000000..f233c02
--- /dev/null
+++ b/Lucene.Net.Tests.QueryParser/Classic/TestMultiFieldQueryParser.cs
@@ -0,0 +1,376 @@
+using Lucene.Net.Analysis;
+using Lucene.Net.Documents;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Lucene.Net.QueryParser.Classic
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    [TestFixture]
+    public class TestMultiFieldQueryParser : LuceneTestCase
+    {
+        /// <summary>
+        /// test stop words parsing for both the non static form, and for the 
+        /// corresponding static form (qtxt, fields[]).
+        /// </summary>
+        [Test]
+        public void TestStopwordsParsing()
+        {
+            AssertStopQueryEquals("one", "b:one t:one");
+            AssertStopQueryEquals("one stop", "b:one t:one");
+            AssertStopQueryEquals("one (stop)", "b:one t:one");
+            AssertStopQueryEquals("one ((stop))", "b:one t:one");
+            AssertStopQueryEquals("stop", "");
+            AssertStopQueryEquals("(stop)", "");
+            AssertStopQueryEquals("((stop))", "");
+        }
+
+        /// <summary>
+        /// verify parsing of query using a stopping analyzer  
+        /// </summary>
+        /// <param name="qtxt"></param>
+        /// <param name="expectedRes"></param>
+        private void AssertStopQueryEquals(string qtxt, string expectedRes)
+        {
+            string[] fields = { "b", "t" };
+            BooleanClause.Occur[] occur = new BooleanClause.Occur[] { BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD };
+            TestQueryParser.QPTestAnalyzer a = new TestQueryParser.QPTestAnalyzer();
+            MultiFieldQueryParser mfqp = new MultiFieldQueryParser(TEST_VERSION_CURRENT, fields, a);
+
+            Query q = mfqp.Parse(qtxt);
+            assertEquals(expectedRes, q.toString());
+
+            q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, qtxt, fields, occur, a);
+            assertEquals(expectedRes, q.toString());
+        }
+
+        [Test]
+        public void TestSimple()
+        {
+            string[] fields = { "b", "t" };
+            MultiFieldQueryParser mfqp = new MultiFieldQueryParser(TEST_VERSION_CURRENT, fields, new MockAnalyzer(Random()));
+
+            Query q = mfqp.Parse("one");
+            assertEquals("b:one t:one", q.toString());
+
+            q = mfqp.Parse("one two");
+            assertEquals("(b:one t:one) (b:two t:two)", q.toString());
+
+            q = mfqp.Parse("+one +two");
+            assertEquals("+(b:one t:one) +(b:two t:two)", q.toString());
+
+            q = mfqp.Parse("+one -two -three");
+            assertEquals("+(b:one t:one) -(b:two t:two) -(b:three t:three)", q.toString());
+
+            q = mfqp.Parse("one^2 two");
+            assertEquals("((b:one t:one)^2.0) (b:two t:two)", q.toString());
+
+            q = mfqp.Parse("one~ two");
+            assertEquals("(b:one~2 t:one~2) (b:two t:two)", q.toString());
+
+            q = mfqp.Parse("one~0.8 two^2");
+            assertEquals("(b:one~0 t:one~0) ((b:two t:two)^2.0)", q.toString());
+
+            q = mfqp.Parse("one* two*");
+            assertEquals("(b:one* t:one*) (b:two* t:two*)", q.toString());
+
+            q = mfqp.Parse("[a TO c] two");
+            assertEquals("(b:[a TO c] t:[a TO c]) (b:two t:two)", q.toString());
+
+            q = mfqp.Parse("w?ldcard");
+            assertEquals("b:w?ldcard t:w?ldcard", q.toString());
+
+            q = mfqp.Parse("\"foo bar\"");
+            assertEquals("b:\"foo bar\" t:\"foo bar\"", q.toString());
+
+            q = mfqp.Parse("\"aa bb cc\" \"dd ee\"");
+            assertEquals("(b:\"aa bb cc\" t:\"aa bb cc\") (b:\"dd ee\" t:\"dd ee\")", q.toString());
+
+            q = mfqp.Parse("\"foo bar\"~4");
+            assertEquals("b:\"foo bar\"~4 t:\"foo bar\"~4", q.toString());
+
+            // LUCENE-1213: MultiFieldQueryParser was ignoring slop when phrase had a field.
+            q = mfqp.Parse("b:\"foo bar\"~4");
+            assertEquals("b:\"foo bar\"~4", q.toString());
+
+            // make sure that terms which have a field are not touched:
+            q = mfqp.Parse("one f:two");
+            assertEquals("(b:one t:one) f:two", q.toString());
+
+            // AND mode:
+            mfqp.DefaultOperator = QueryParserBase.AND_OPERATOR;
+            q = mfqp.Parse("one two");
+            assertEquals("+(b:one t:one) +(b:two t:two)", q.toString());
+            q = mfqp.Parse("\"aa bb cc\" \"dd ee\"");
+            assertEquals("+(b:\"aa bb cc\" t:\"aa bb cc\") +(b:\"dd ee\" t:\"dd ee\")", q.toString());
+        }
+
+        [Test]
+        public void TestBoostsSimple()
+        {
+            IDictionary<string, float> boosts = new Dictionary<string, float>();
+            boosts["b"] = (float)5;
+            boosts["t"] = (float)10;
+            string[] fields = { "b", "t" };
+            MultiFieldQueryParser mfqp = new MultiFieldQueryParser(TEST_VERSION_CURRENT, fields, new MockAnalyzer(Random()), boosts);
+
+
+            //Check for simple
+            Query q = mfqp.Parse("one");
+            assertEquals("b:one^5.0 t:one^10.0", q.toString());
+
+            //Check for AND
+            q = mfqp.Parse("one AND two");
+            assertEquals("+(b:one^5.0 t:one^10.0) +(b:two^5.0 t:two^10.0)", q.toString());
+
+            //Check for OR
+            q = mfqp.Parse("one OR two");
+            assertEquals("(b:one^5.0 t:one^10.0) (b:two^5.0 t:two^10.0)", q.toString());
+
+            //Check for AND and a field
+            q = mfqp.Parse("one AND two AND foo:test");
+            assertEquals("+(b:one^5.0 t:one^10.0) +(b:two^5.0 t:two^10.0) +foo:test", q.toString());
+
+            q = mfqp.Parse("one^3 AND two^4");
+            assertEquals("+((b:one^5.0 t:one^10.0)^3.0) +((b:two^5.0 t:two^10.0)^4.0)", q.toString());
+        }
+
+        [Test]
+        public void TestStaticMethod1()
+        {
+            string[] fields = { "b", "t" };
+            string[] queries = { "one", "two" };
+            Query q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, queries, fields, new MockAnalyzer(Random()));
+            assertEquals("b:one t:two", q.toString());
+
+            string[] queries2 = { "+one", "+two" };
+            q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, queries2, fields, new MockAnalyzer(Random()));
+            assertEquals("(+b:one) (+t:two)", q.toString());
+
+            string[] queries3 = { "one", "+two" };
+            q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, queries3, fields, new MockAnalyzer(Random()));
+            assertEquals("b:one (+t:two)", q.toString());
+
+            string[] queries4 = { "one +more", "+two" };
+            q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, queries4, fields, new MockAnalyzer(Random()));
+            assertEquals("(b:one +b:more) (+t:two)", q.toString());
+
+            string[] queries5 = { "blah" };
+            try
+            {
+                q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, queries5, fields, new MockAnalyzer(Random()));
+                fail();
+            }
+            catch (ArgumentException e)
+            {
+                // expected exception, array length differs
+            }
+
+            // check also with stop words for this static form (qtxts[], fields[]).
+            TestQueryParser.QPTestAnalyzer stopA = new TestQueryParser.QPTestAnalyzer();
+
+            string[] queries6 = { "((+stop))", "+((stop))" };
+            q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, queries6, fields, stopA);
+            assertEquals("", q.toString());
+
+            string[] queries7 = { "one ((+stop)) +more", "+((stop)) +two" };
+            q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, queries7, fields, stopA);
+            assertEquals("(b:one +b:more) (+t:two)", q.toString());
+        }
+
+        [Test]
+        public void TestStaticMethod2()
+        {
+            string[] fields = { "b", "t" };
+            BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST, BooleanClause.Occur.MUST_NOT };
+            Query q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, "one", fields, flags, new MockAnalyzer(Random()));
+            assertEquals("+b:one -t:one", q.toString());
+
+            q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, "one two", fields, flags, new MockAnalyzer(Random()));
+            assertEquals("+(b:one b:two) -(t:one t:two)", q.toString());
+
+            try
+            {
+                BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+                q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, "blah", fields, flags2, new MockAnalyzer(Random()));
+                fail();
+            }
+            catch (ArgumentException e)
+            {
+                // expected exception, array length differs
+            }
+        }
+
+        [Test]
+        public void TestStaticMethod2Old()
+        {
+            string[] fields = { "b", "t" };
+            //int[] flags = {MultiFieldQueryParser.REQUIRED_FIELD, MultiFieldQueryParser.PROHIBITED_FIELD};
+            BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST, BooleanClause.Occur.MUST_NOT };
+
+            Query q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, "one", fields, flags, new MockAnalyzer(Random()));//, fields, flags, new MockAnalyzer(random));
+            assertEquals("+b:one -t:one", q.toString());
+
+            q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, "one two", fields, flags, new MockAnalyzer(Random()));
+            assertEquals("+(b:one b:two) -(t:one t:two)", q.toString());
+
+            try
+            {
+                BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+                q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, "blah", fields, flags2, new MockAnalyzer(Random()));
+                fail();
+            }
+            catch (ArgumentException e)
+            {
+                // expected exception, array length differs
+            }
+        }
+
+        [Test]
+        public void TestStaticMethod3()
+        {
+            string[] queries = { "one", "two", "three" };
+            string[] fields = { "f1", "f2", "f3" };
+            BooleanClause.Occur[] flags = {BooleanClause.Occur.MUST,
+                BooleanClause.Occur.MUST_NOT, BooleanClause.Occur.SHOULD};
+            Query q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, queries, fields, flags, new MockAnalyzer(Random()));
+            assertEquals("+f1:one -f2:two f3:three", q.toString());
+
+            try
+            {
+                BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+                q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, queries, fields, flags2, new MockAnalyzer(Random()));
+                fail();
+            }
+            catch (ArgumentException e)
+            {
+                // expected exception, array length differs
+            }
+        }
+
+        [Test]
+        public void TestStaticMethod3Old()
+        {
+            string[] queries = { "one", "two" };
+            string[] fields = { "b", "t" };
+            BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST, BooleanClause.Occur.MUST_NOT };
+            Query q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, queries, fields, flags, new MockAnalyzer(Random()));
+            assertEquals("+b:one -t:two", q.toString());
+
+            try
+            {
+                BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+                q = MultiFieldQueryParser.Parse(TEST_VERSION_CURRENT, queries, fields, flags2, new MockAnalyzer(Random()));
+                fail();
+            }
+            catch (ArgumentException e)
+            {
+                // expected exception, array length differs
+            }
+        }
+
+        [Test]
+        public void TestAnalyzerReturningNull()
+        {
+            string[] fields = new string[] { "f1", "f2", "f3" };
+            MultiFieldQueryParser parser = new MultiFieldQueryParser(TEST_VERSION_CURRENT, fields, new AnalyzerReturningNull());
+            Query q = parser.Parse("bla AND blo");
+            assertEquals("+(f2:bla f3:bla) +(f2:blo f3:blo)", q.toString());
+            // the following queries are not affected as their terms are not analyzed anyway:
+            q = parser.Parse("bla*");
+            assertEquals("f1:bla* f2:bla* f3:bla*", q.toString());
+            q = parser.Parse("bla~");
+            assertEquals("f1:bla~2 f2:bla~2 f3:bla~2", q.toString());
+            q = parser.Parse("[a TO c]");
+            assertEquals("f1:[a TO c] f2:[a TO c] f3:[a TO c]", q.toString());
+        }
+
+        [Test]
+        public void TestStopWordSearching()
+        {
+            Analyzer analyzer = new MockAnalyzer(Random());
+            using (var ramDir = NewDirectory())
+            {
+                using (IndexWriter iw = new IndexWriter(ramDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, analyzer)))
+                {
+                    Document doc = new Document();
+                    doc.Add(NewTextField("body", "blah the footest blah", Field.Store.NO));
+                    iw.AddDocument(doc);
+                }
+
+                MultiFieldQueryParser mfqp =
+                  new MultiFieldQueryParser(TEST_VERSION_CURRENT, new string[] { "body" }, analyzer);
+                mfqp.DefaultOperator = QueryParser.Operator.AND;
+                Query q = mfqp.Parse("the footest");
+                using (IndexReader ir = DirectoryReader.Open(ramDir))
+                {
+                    IndexSearcher @is = NewSearcher(ir);
+                    ScoreDoc[] hits = @is.Search(q, null, 1000).ScoreDocs;
+                    assertEquals(1, hits.Length);
+                }
+            }
+        }
+
+        private class AnalyzerReturningNull : Analyzer
+        {
+            MockAnalyzer stdAnalyzer = new MockAnalyzer(Random());
+
+            public AnalyzerReturningNull()
+                : base(PER_FIELD_REUSE_STRATEGY)
+            { }
+
+            public override System.IO.TextReader InitReader(string fieldName, TextReader reader)
+            {
+                if ("f1".equals(fieldName))
+                {
+                    // we don't use the reader, so close it:
+                    IOUtils.CloseWhileHandlingException(reader);
+                    // return empty reader, so MockTokenizer returns no tokens:
+                    return new StringReader("");
+                }
+                else
+                {
+                    return base.InitReader(fieldName, reader);
+                }
+            }
+
+            public override TokenStreamComponents CreateComponents(string fieldName, TextReader reader)
+            {
+                return stdAnalyzer.CreateComponents(fieldName, reader);
+            }
+        }
+
+        [Test]
+        public void TestSimpleRegex()
+        {
+            string[] fields = new string[] { "a", "b" };
+            MultiFieldQueryParser mfqp = new MultiFieldQueryParser(TEST_VERSION_CURRENT, fields, new MockAnalyzer(Random()));
+
+            BooleanQuery bq = new BooleanQuery(true);
+            bq.Add(new RegexpQuery(new Term("a", "[a-z][123]")), BooleanClause.Occur.SHOULD);
+            bq.Add(new RegexpQuery(new Term("b", "[a-z][123]")), BooleanClause.Occur.SHOULD);
+            assertEquals(bq, mfqp.Parse("/[a-z][123]/"));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/6d711567/Lucene.Net.Tests.QueryParser/Classic/TestMultiPhraseQueryParsing.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.Tests.QueryParser/Classic/TestMultiPhraseQueryParsing.cs b/Lucene.Net.Tests.QueryParser/Classic/TestMultiPhraseQueryParsing.cs
new file mode 100644
index 0000000..3aaa9b2
--- /dev/null
+++ b/Lucene.Net.Tests.QueryParser/Classic/TestMultiPhraseQueryParsing.cs
@@ -0,0 +1,121 @@
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Tokenattributes;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using NUnit.Framework;
+
+namespace Lucene.Net.QueryParser.Classic
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    [TestFixture]
+    public class TestMultiPhraseQueryParsing_ : LuceneTestCase
+    {
+        private class TokenAndPos
+        {
+            public readonly string token;
+            public readonly int pos;
+            public TokenAndPos(string token, int pos)
+            {
+                this.token = token;
+                this.pos = pos;
+            }
+        }
+
+        private class CannedAnalyzer : Analyzer
+        {
+            private readonly TokenAndPos[] tokens;
+
+            public CannedAnalyzer(TokenAndPos[] tokens)
+            {
+                this.tokens = tokens;
+            }
+
+            public override TokenStreamComponents CreateComponents(string fieldName, System.IO.TextReader reader)
+            {
+                return new TokenStreamComponents(new CannedTokenizer(reader, tokens));
+            }
+        }
+
+        private class CannedTokenizer : Tokenizer
+        {
+            private readonly TokenAndPos[] tokens;
+            private int upto = 0;
+            private int lastPos = 0;
+            private readonly ICharTermAttribute termAtt;
+            private readonly IPositionIncrementAttribute posIncrAtt;
+
+            public CannedTokenizer(System.IO.TextReader reader, TokenAndPos[] tokens)
+                : base(reader)
+            {
+                this.tokens = tokens;
+                this.termAtt = AddAttribute<ICharTermAttribute>();
+                this.posIncrAtt = AddAttribute<IPositionIncrementAttribute>();
+            }
+
+            public override sealed bool IncrementToken()
+            {
+                ClearAttributes();
+                if (upto < tokens.Length)
+                {
+                    TokenAndPos token = tokens[upto++];
+                    termAtt.SetEmpty();
+                    termAtt.Append(token.token);
+                    posIncrAtt.PositionIncrement = (token.pos - lastPos);
+                    lastPos = token.pos;
+                    return true;
+                }
+                else
+                {
+                    return false;
+                }
+            }
+            public override void Reset()
+            {
+                base.Reset();
+                this.upto = 0;
+                this.lastPos = 0;
+            }
+        }
+
+        [Test]
+        public void TestMultiPhraseQueryParsing()
+        {
+            TokenAndPos[] INCR_0_QUERY_TOKENS_AND = new TokenAndPos[]
+            {
+                new TokenAndPos("a", 0),
+                new TokenAndPos("1", 0),
+                new TokenAndPos("b", 1),
+                new TokenAndPos("1", 1),
+                new TokenAndPos("c", 2)
+            };
+
+            QueryParser qp = new QueryParser(TEST_VERSION_CURRENT, "field", new CannedAnalyzer(INCR_0_QUERY_TOKENS_AND));
+            Query q = qp.Parse("\"this text is acually ignored\"");
+            assertTrue("wrong query type!", q is MultiPhraseQuery);
+
+            MultiPhraseQuery multiPhraseQuery = new MultiPhraseQuery();
+            multiPhraseQuery.Add(new Term[] { new Term("field", "a"), new Term("field", "1") }, -1);
+            multiPhraseQuery.Add(new Term[] { new Term("field", "b"), new Term("field", "1") }, 0);
+            multiPhraseQuery.Add(new Term[] { new Term("field", "c") }, 1);
+
+            assertEquals(multiPhraseQuery, q);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/6d711567/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs b/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs
new file mode 100644
index 0000000..0130bca
--- /dev/null
+++ b/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs
@@ -0,0 +1,554 @@
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Tokenattributes;
+using Lucene.Net.Documents;
+using Lucene.Net.QueryParser.Flexible.Standard;
+using Lucene.Net.QueryParser.Util;
+using Lucene.Net.Search;
+using Lucene.Net.Support;
+using NUnit.Framework;
+using System;
+using System.Diagnostics;
+
+namespace Lucene.Net.QueryParser.Classic
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    [TestFixture]
+    public class TestQueryParser : QueryParserTestBase
+    {
+        public class QPTestParser : QueryParser
+        {
+            public QPTestParser(string f, Analyzer a)
+                : base(TEST_VERSION_CURRENT, f, a)
+            {
+            }
+
+            protected override Query GetFuzzyQuery(string field, string termStr, float minSimilarity)
+            {
+                throw new ParseException("Fuzzy queries not allowed");
+            }
+
+            protected override Query GetWildcardQuery(string field, string termStr)
+            {
+                throw new ParseException("Wildcard queries not allowed");
+            }
+
+        }
+
+        public QueryParser GetParser(Analyzer a)
+        {
+            if (a == null) a = new MockAnalyzer(Random(), MockTokenizer.SIMPLE, true);
+            QueryParser qp = new QueryParser(TEST_VERSION_CURRENT, DefaultField, a);
+            qp.DefaultOperator = (QueryParserBase.OR_OPERATOR);
+            return qp;
+        }
+
+        public override ICommonQueryParserConfiguration GetParserConfig(Analyzer a)
+        {
+            return GetParser(a);
+        }
+
+        public override Query GetQuery(string query, ICommonQueryParserConfiguration cqpC)
+        {
+            Debug.Assert(cqpC != null, "Parameter must not be null");
+            Debug.Assert(cqpC is QueryParser, "Parameter must be instance of QueryParser");
+            QueryParser qp = (QueryParser)cqpC;
+            return qp.Parse(query);
+        }
+
+        public override Query GetQuery(string query, Analyzer a)
+        {
+            return GetParser(a).Parse(query);
+        }
+
+        public override bool IsQueryParserException(Exception exception)
+        {
+            return exception is ParseException;
+        }
+
+        public override void SetDefaultOperatorOR(ICommonQueryParserConfiguration cqpC)
+        {
+            Debug.Assert(cqpC is QueryParser);
+            QueryParser qp = (QueryParser)cqpC;
+            qp.DefaultOperator = QueryParserBase.Operator.OR;
+        }
+
+        public override void SetDefaultOperatorAND(ICommonQueryParserConfiguration cqpC)
+        {
+            Debug.Assert(cqpC is QueryParser);
+            QueryParser qp = (QueryParser)cqpC;
+            qp.DefaultOperator = QueryParserBase.Operator.AND;
+        }
+
+        public override void SetAnalyzeRangeTerms(ICommonQueryParserConfiguration cqpC, bool value)
+        {
+            Debug.Assert(cqpC is QueryParser);
+            QueryParser qp = (QueryParser)cqpC;
+            qp.AnalyzeRangeTerms = (value);
+        }
+
+        public override void SetAutoGeneratePhraseQueries(ICommonQueryParserConfiguration cqpC, bool value)
+        {
+            Debug.Assert(cqpC is QueryParser);
+            QueryParser qp = (QueryParser)cqpC;
+            qp.AutoGeneratePhraseQueries = value;
+        }
+
+        public override void SetDateResolution(ICommonQueryParserConfiguration cqpC, ICharSequence field, DateTools.Resolution value)
+        {
+            Debug.Assert(cqpC is QueryParser);
+            QueryParser qp = (QueryParser)cqpC;
+            qp.SetDateResolution(field.toString(), value);
+        }
+
+        [Test]
+        public override void TestDefaultOperator()
+        {
+            QueryParser qp = GetParser(new MockAnalyzer(Random()));
+            // make sure OR is the default:
+            assertEquals(QueryParserBase.OR_OPERATOR, qp.DefaultOperator);
+            SetDefaultOperatorAND(qp);
+            assertEquals(QueryParserBase.AND_OPERATOR, qp.DefaultOperator);
+            SetDefaultOperatorOR(qp);
+            assertEquals(QueryParserBase.OR_OPERATOR, qp.DefaultOperator);
+        }
+
+        // LUCENE-2002: when we run javacc to regen QueryParser,
+        // we also run a replaceregexp step to fix 2 of the public
+        // ctors (change them to protected):
+        //
+        // protected QueryParser(CharStream stream)
+        //
+        // protected QueryParser(QueryParserTokenManager tm)
+        //
+        // This test is here as a safety, in case that ant step
+        // doesn't work for some reason.
+        [Test]
+        public void TestProtectedCtors()
+        {
+            try
+            {
+                typeof(QueryParser).GetConstructor(new Type[] { typeof(ICharStream) });
+                fail("please switch public QueryParser(CharStream) to be protected");
+            }
+            catch (Exception nsme)
+            {
+                // expected
+            }
+            try
+            {
+                typeof(QueryParser).GetConstructor(new Type[] { typeof(QueryParserTokenManager) });
+                fail("please switch public QueryParser(QueryParserTokenManager) to be protected");
+            }
+            catch (Exception nsme)
+            {
+                // expected
+            }
+        }
+
+        private class TestFuzzySlopeExtendabilityQueryParser : QueryParser
+        {
+            public TestFuzzySlopeExtendabilityQueryParser()
+                : base(TEST_VERSION_CURRENT, "a", new MockAnalyzer(Random(), MockTokenizer.WHITESPACE, false))
+            {}
+
+            protected override Query HandleBareFuzzy(string qfield, Token fuzzySlop, string termImage)
+            {
+                if (fuzzySlop.image.EndsWith("€"))
+                {
+                    float fms = FuzzyMinSim;
+                    try
+                    {
+                        fms = float.Parse(fuzzySlop.image.Substring(1, fuzzySlop.image.Length - 1));
+                    }
+                    catch (Exception ignored) { }
+                    float value = float.Parse(termImage);
+                    return GetRangeQuery(qfield, (value - fms / 2.0f).ToString(), (value + fms / 2.0f).ToString(), true, true);
+                }
+                return base.HandleBareFuzzy(qfield, fuzzySlop, termImage);
+            }
+        }
+
+        [Test]
+        public void TestFuzzySlopeExtendability()
+        {
+            QueryParser qp = new TestFuzzySlopeExtendabilityQueryParser();
+            assertEquals(qp.Parse("a:[11.95 TO 12.95]"), qp.Parse("12.45~1€"));
+        }
+
+        private class TestStarParsingQueryParser : QueryParser
+        {
+            public readonly int[] type = new int[1];
+
+            public TestStarParsingQueryParser()
+                : base(TEST_VERSION_CURRENT, "field", new MockAnalyzer(Random(), MockTokenizer.WHITESPACE, false))
+            { }
+
+            protected override Query GetWildcardQuery(string field, string termStr)
+            {
+                // override error checking of superclass
+                type[0] = 1;
+                return new TermQuery(new Index.Term(field, termStr));
+            }
+
+            protected override Query GetPrefixQuery(string field, string termStr)
+            {
+                // override error checking of superclass
+                type[0] = 2;
+                return new TermQuery(new Index.Term(field, termStr));
+            }
+
+            protected override Query GetFieldQuery(string field, string queryText, bool quoted)
+            {
+                type[0] = 3;
+                return base.GetFieldQuery(field, queryText, quoted);
+            }
+        }
+
+        [Test]
+        public override void TestStarParsing()
+        {
+            TestStarParsingQueryParser qp = new TestStarParsingQueryParser();
+
+            TermQuery tq;
+
+            tq = (TermQuery)qp.Parse("foo:zoo*");
+            assertEquals("zoo", tq.Term.Text());
+            assertEquals(2, qp.type[0]);
+
+            tq = (TermQuery)qp.Parse("foo:zoo*^2");
+            assertEquals("zoo", tq.Term.Text());
+            assertEquals(2, qp.type[0]);
+            assertEquals(tq.Boost, 2, 0);
+
+            tq = (TermQuery)qp.Parse("foo:*");
+            assertEquals("*", tq.Term.Text());
+            assertEquals(1, qp.type[0]); // could be a valid prefix query in the future too
+
+            tq = (TermQuery)qp.Parse("foo:*^2");
+            assertEquals("*", tq.Term.Text());
+            assertEquals(1, qp.type[0]);
+            assertEquals(tq.Boost, 2, 0);
+
+            tq = (TermQuery)qp.Parse("*:foo");
+            assertEquals("*", tq.Term.Field);
+            assertEquals("foo", tq.Term.Text());
+            assertEquals(3, qp.type[0]);
+
+            tq = (TermQuery)qp.Parse("*:*");
+            assertEquals("*", tq.Term.Field);
+            assertEquals("*", tq.Term.Text());
+            assertEquals(1, qp.type[0]); // could be handled as a prefix query in the
+            // future
+
+            tq = (TermQuery)qp.Parse("(*:*)");
+            assertEquals("*", tq.Term.Field);
+            assertEquals("*", tq.Term.Text());
+            assertEquals(1, qp.type[0]);
+        }
+
+        [Test]
+        public void TestCustomQueryParserWildcard()
+        {
+            try
+            {
+                new QPTestParser("contents", new MockAnalyzer(Random(),
+                    MockTokenizer.WHITESPACE, false)).Parse("a?t");
+                fail("Wildcard queries should not be allowed");
+            }
+            catch (ParseException expected)
+            {
+                // expected exception
+            }
+        }
+
+        [Test]
+        public void TestCustomQueryParserFuzzy()
+        {
+            try
+            {
+                new QPTestParser("contents", new MockAnalyzer(Random(),
+                    MockTokenizer.WHITESPACE, false)).Parse("xunit~");
+                fail("Fuzzy queries should not be allowed");
+            }
+            catch (ParseException expected)
+            {
+                // expected exception
+            }
+        }
+
+        /// <summary>
+        /// query parser that doesn't expand synonyms when users use double quotes
+        /// </summary>
+        private class SmartQueryParser : QueryParser
+        {
+            Analyzer morePrecise = new Analyzer2();
+
+            public SmartQueryParser()
+                : base(TEST_VERSION_CURRENT, "field", new Analyzer1())
+            {
+            }
+
+            protected override Query GetFieldQuery(string field, string queryText, bool quoted)
+            {
+                if (quoted) return NewFieldQuery(morePrecise, field, queryText, quoted);
+                else return base.GetFieldQuery(field, queryText, quoted);
+            }
+        }
+
+        public override void TestNewFieldQuery()
+        {
+            /** ordinary behavior, synonyms form uncoordinated boolean query */
+            QueryParser dumb = new QueryParser(TEST_VERSION_CURRENT, "field",
+                new Analyzer1());
+            BooleanQuery expanded = new BooleanQuery(true);
+            expanded.Add(new TermQuery(new Index.Term("field", "dogs")),
+                BooleanClause.Occur.SHOULD);
+            expanded.Add(new TermQuery(new Index.Term("field", "dog")),
+                BooleanClause.Occur.SHOULD);
+            assertEquals(expanded, dumb.Parse("\"dogs\""));
+            /** even with the phrase operator the behavior is the same */
+            assertEquals(expanded, dumb.Parse("dogs"));
+
+            /**
+             * custom behavior, the synonyms are expanded, unless you use quote operator
+             */
+            QueryParser smart = new SmartQueryParser();
+            assertEquals(expanded, smart.Parse("dogs"));
+
+            Query unexpanded = new TermQuery(new Index.Term("field", "dogs"));
+            assertEquals(unexpanded, smart.Parse("\"dogs\""));
+        }
+
+        // LUCENETODO: fold these into QueryParserTestBase
+
+        /// <summary>
+        /// adds synonym of "dog" for "dogs".
+        /// </summary>
+        public class MockSynonymAnalyzer : Analyzer
+        {
+            public override TokenStreamComponents CreateComponents(string fieldName, System.IO.TextReader reader)
+            {
+                MockTokenizer tokenizer = new MockTokenizer(reader);
+                return new TokenStreamComponents(tokenizer, new MockSynonymFilter(tokenizer));
+            }
+        }
+
+        /// <summary>
+        /// simple synonyms test
+        /// </summary>
+        [Test]
+        public void TestSynonyms()
+        {
+            BooleanQuery expected = new BooleanQuery(true);
+            expected.Add(new TermQuery(new Index.Term("field", "dogs")), BooleanClause.Occur.SHOULD);
+            expected.Add(new TermQuery(new Index.Term("field", "dog")), BooleanClause.Occur.SHOULD);
+            QueryParser qp = new QueryParser(TEST_VERSION_CURRENT, "field", new MockSynonymAnalyzer());
+            assertEquals(expected, qp.Parse("dogs"));
+            assertEquals(expected, qp.Parse("\"dogs\""));
+            qp.DefaultOperator = (QueryParserBase.Operator.AND);
+            assertEquals(expected, qp.Parse("dogs"));
+            assertEquals(expected, qp.Parse("\"dogs\""));
+            expected.Boost = (2.0f);
+            assertEquals(expected, qp.Parse("dogs^2"));
+            assertEquals(expected, qp.Parse("\"dogs\"^2"));
+        }
+
+        /// <summary>
+        /// forms multiphrase query
+        /// </summary>
+        [Test]
+        public void TestSynonymsPhrase()
+        {
+            MultiPhraseQuery expected = new MultiPhraseQuery();
+            expected.Add(new Index.Term("field", "old"));
+            expected.Add(new Index.Term[] { new Index.Term("field", "dogs"), new Index.Term("field", "dog") });
+            QueryParser qp = new QueryParser(TEST_VERSION_CURRENT, "field", new MockSynonymAnalyzer());
+            assertEquals(expected, qp.Parse("\"old dogs\""));
+            qp.DefaultOperator = (QueryParserBase.Operator.AND);
+            assertEquals(expected, qp.Parse("\"old dogs\""));
+            expected.Boost = (2.0f);
+            assertEquals(expected, qp.Parse("\"old dogs\"^2"));
+            expected.Slop = (3);
+            assertEquals(expected, qp.Parse("\"old dogs\"~3^2"));
+        }
+
+        /// <summary>
+        /// adds synonym of "國" for "国".
+        /// </summary>
+        protected class MockCJKSynonymFilter : TokenFilter
+        {
+            ICharTermAttribute termAtt;
+            IPositionIncrementAttribute posIncAtt;
+            bool addSynonym = false;
+
+            public MockCJKSynonymFilter(TokenStream input)
+                : base(input)
+            {
+                ICharTermAttribute termAtt = AddAttribute<ICharTermAttribute>();
+                IPositionIncrementAttribute posIncAtt = AddAttribute<IPositionIncrementAttribute>();
+            }
+
+            public override bool IncrementToken()
+            {
+                if (addSynonym)
+                { // inject our synonym
+                    ClearAttributes();
+                    termAtt.SetEmpty().Append("國");
+                    posIncAtt.PositionIncrement = (0);
+                    addSynonym = false;
+                    return true;
+                }
+
+                if (input.IncrementToken())
+                {
+                    addSynonym = termAtt.toString().equals("国");
+                    return true;
+                }
+                else
+                {
+                    return false;
+                }
+            }
+        }
+
+        protected class MockCJKSynonymAnalyzer : Analyzer
+        {
+            public override TokenStreamComponents CreateComponents(string fieldName, System.IO.TextReader reader)
+            {
+                Tokenizer tokenizer = new SimpleCJKTokenizer(reader);
+                return new TokenStreamComponents(tokenizer, new MockCJKSynonymFilter(tokenizer));
+            }
+        }
+
+        /// <summary>
+        /// simple CJK synonym test
+        /// </summary>
+        [Test]
+        public void TestCJKSynonym()
+        {
+            BooleanQuery expected = new BooleanQuery(true);
+            expected.Add(new TermQuery(new Index.Term("field", "国")), BooleanClause.Occur.SHOULD);
+            expected.Add(new TermQuery(new Index.Term("field", "國")), BooleanClause.Occur.SHOULD);
+            QueryParser qp = new QueryParser(TEST_VERSION_CURRENT, "field", new MockCJKSynonymAnalyzer());
+            assertEquals(expected, qp.Parse("国"));
+            qp.DefaultOperator = (QueryParserBase.Operator.AND);
+            assertEquals(expected, qp.Parse("国"));
+            expected.Boost = (2.0f);
+            assertEquals(expected, qp.Parse("国^2"));
+        }
+
+        /// <summary>
+        /// synonyms with default OR operator 
+        /// </summary>
+        [Test]
+        public void TestCJKSynonymsOR()
+        {
+            BooleanQuery expected = new BooleanQuery();
+            expected.Add(new TermQuery(new Index.Term("field", "中")), BooleanClause.Occur.SHOULD);
+            BooleanQuery inner = new BooleanQuery(true);
+            inner.Add(new TermQuery(new Index.Term("field", "国")), BooleanClause.Occur.SHOULD);
+            inner.Add(new TermQuery(new Index.Term("field", "國")), BooleanClause.Occur.SHOULD);
+            expected.Add(inner, BooleanClause.Occur.SHOULD);
+            QueryParser qp = new QueryParser(TEST_VERSION_CURRENT, "field", new MockCJKSynonymAnalyzer());
+            assertEquals(expected, qp.Parse("中国"));
+            expected.Boost = (2.0f);
+            assertEquals(expected, qp.Parse("中国^2"));
+        }
+
+        /// <summary>
+        /// more complex synonyms with default OR operator
+        /// </summary>
+        [Test]
+        public void TestCJKSynonymsOR2()
+        {
+            BooleanQuery expected = new BooleanQuery();
+            expected.Add(new TermQuery(new Index.Term("field", "中")), BooleanClause.Occur.SHOULD);
+            BooleanQuery inner = new BooleanQuery(true);
+            inner.Add(new TermQuery(new Index.Term("field", "国")), BooleanClause.Occur.SHOULD);
+            inner.Add(new TermQuery(new Index.Term("field", "國")), BooleanClause.Occur.SHOULD);
+            expected.Add(inner, BooleanClause.Occur.SHOULD);
+            BooleanQuery inner2 = new BooleanQuery(true);
+            inner2.Add(new TermQuery(new Index.Term("field", "国")), BooleanClause.Occur.SHOULD);
+            inner2.Add(new TermQuery(new Index.Term("field", "國")), BooleanClause.Occur.SHOULD);
+            expected.Add(inner2, BooleanClause.Occur.SHOULD);
+            QueryParser qp = new QueryParser(TEST_VERSION_CURRENT, "field", new MockCJKSynonymAnalyzer());
+            assertEquals(expected, qp.Parse("中国国"));
+            expected.Boost = (2.0f);
+            assertEquals(expected, qp.Parse("中国国^2"));
+        }
+
+        /// <summary>
+        /// synonyms with default AND operator
+        /// </summary>
+        [Test]
+        public void TestCJKSynonymsAND()
+        {
+            BooleanQuery expected = new BooleanQuery();
+            expected.Add(new TermQuery(new Index.Term("field", "中")), BooleanClause.Occur.MUST);
+            BooleanQuery inner = new BooleanQuery(true);
+            inner.Add(new TermQuery(new Index.Term("field", "国")), BooleanClause.Occur.SHOULD);
+            inner.Add(new TermQuery(new Index.Term("field", "國")), BooleanClause.Occur.SHOULD);
+            expected.Add(inner, BooleanClause.Occur.MUST);
+            QueryParser qp = new QueryParser(TEST_VERSION_CURRENT, "field", new MockCJKSynonymAnalyzer());
+            qp.DefaultOperator = (QueryParserBase.Operator.AND);
+            assertEquals(expected, qp.Parse("中国"));
+            expected.Boost = (2.0f);
+            assertEquals(expected, qp.Parse("中国^2"));
+        }
+
+        /// <summary>
+        /// more complex synonyms with default AND operator
+        /// </summary>
+        [Test]
+        public void TestCJKSynonymsAND2()
+        {
+            BooleanQuery expected = new BooleanQuery();
+            expected.Add(new TermQuery(new Index.Term("field", "中")), BooleanClause.Occur.MUST);
+            BooleanQuery inner = new BooleanQuery(true);
+            inner.Add(new TermQuery(new Index.Term("field", "国")), BooleanClause.Occur.SHOULD);
+            inner.Add(new TermQuery(new Index.Term("field", "國")), BooleanClause.Occur.SHOULD);
+            expected.Add(inner, BooleanClause.Occur.MUST);
+            BooleanQuery inner2 = new BooleanQuery(true);
+            inner2.Add(new TermQuery(new Index.Term("field", "国")), BooleanClause.Occur.SHOULD);
+            inner2.Add(new TermQuery(new Index.Term("field", "國")), BooleanClause.Occur.SHOULD);
+            expected.Add(inner2, BooleanClause.Occur.MUST);
+            QueryParser qp = new QueryParser(TEST_VERSION_CURRENT, "field", new MockCJKSynonymAnalyzer());
+            qp.DefaultOperator = (QueryParserBase.Operator.AND);
+            assertEquals(expected, qp.Parse("中国国"));
+            expected.Boost = (2.0f);
+            assertEquals(expected, qp.Parse("中国国^2"));
+        }
+
+        [Test]
+        public void TestCJKSynonymsPhrase()
+        {
+            MultiPhraseQuery expected = new MultiPhraseQuery();
+            expected.Add(new Index.Term("field", "中"));
+            expected.Add(new Index.Term[] { new Index.Term("field", "国"), new Index.Term("field", "國") });
+            QueryParser qp = new QueryParser(TEST_VERSION_CURRENT, "field", new MockCJKSynonymAnalyzer());
+            qp.DefaultOperator = (QueryParserBase.Operator.AND);
+            assertEquals(expected, qp.Parse("\"中国\""));
+            expected.Boost = (2.0f);
+            assertEquals(expected, qp.Parse("\"中国\"^2"));
+            expected.Slop = (3);
+            assertEquals(expected, qp.Parse("\"中国\"~3^2"));
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/6d711567/Lucene.Net.Tests.QueryParser/Lucene.Net.Tests.QueryParser.csproj
----------------------------------------------------------------------
diff --git a/Lucene.Net.Tests.QueryParser/Lucene.Net.Tests.QueryParser.csproj b/Lucene.Net.Tests.QueryParser/Lucene.Net.Tests.QueryParser.csproj
new file mode 100644
index 0000000..99a5e91
--- /dev/null
+++ b/Lucene.Net.Tests.QueryParser/Lucene.Net.Tests.QueryParser.csproj
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{5719FB4F-BF80-40E5-BACC-37E8E18FCA2E}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Lucene.Net.Tests.QueryParser</RootNamespace>
+    <AssemblyName>Lucene.Net.Tests.QueryParser</AssemblyName>
+    <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="nunit.framework, Version=2.6.3.13283, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Classic\TestMultiFieldQueryParser.cs" />
+    <Compile Include="Classic\TestMultiPhraseQueryParsing.cs" />
+    <Compile Include="Classic\TestQueryParser.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Classic\TestMultiAnalyzer.cs" />
+    <Compile Include="Util\QueryParserTestBase.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Lucene.Net.QueryParser\Lucene.Net.QueryParser.csproj">
+      <Project>{949ba34b-6ae6-4ce3-b578-61e13e4d76bf}</Project>
+      <Name>Lucene.Net.QueryParser</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\src\Lucene.Net.Analysis.Common\Lucene.Net.Analysis.Common.csproj">
+      <Project>{4add0bbc-b900-4715-9526-d871de8eea64}</Project>
+      <Name>Lucene.Net.Analysis.Common</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\src\Lucene.Net.Core\Lucene.Net.csproj">
+      <Project>{5d4ad9be-1ffb-41ab-9943-25737971bf57}</Project>
+      <Name>Lucene.Net</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\src\Lucene.Net.TestFramework\Lucene.Net.TestFramework.csproj">
+      <Project>{b2c0d749-ce34-4f62-a15e-00cb2ff5ddb3}</Project>
+      <Name>Lucene.Net.TestFramework</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/6d711567/Lucene.Net.Tests.QueryParser/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.Tests.QueryParser/Properties/AssemblyInfo.cs b/Lucene.Net.Tests.QueryParser/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..549c7bf
--- /dev/null
+++ b/Lucene.Net.Tests.QueryParser/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Lucene.Net.Tests.QueryParser")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Lucene.Net.Tests.QueryParser")]
+[assembly: AssemblyCopyright("Copyright ©  2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("27d0ae76-3e51-454c-9c4a-f913fde0ed0a")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]


Mime
View raw message