You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2017/02/26 23:36:59 UTC
[11/72] [abbrv] [partial] lucenenet git commit: Lucene.Net.Tests:
Removed \core directory and put its contents in root directory
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/Spans/TestFieldMaskingSpanQuery.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Search/Spans/TestFieldMaskingSpanQuery.cs b/src/Lucene.Net.Tests/Search/Spans/TestFieldMaskingSpanQuery.cs
new file mode 100644
index 0000000..7e78239
--- /dev/null
+++ b/src/Lucene.Net.Tests/Search/Spans/TestFieldMaskingSpanQuery.cs
@@ -0,0 +1,326 @@
+using System.Collections.Generic;
+using Lucene.Net.Documents;
+
+namespace Lucene.Net.Search.Spans
+{
+ using NUnit.Framework;
+ using Directory = Lucene.Net.Store.Directory;
+ using Document = Documents.Document;
+ using Field = Field;
+ using IndexReader = Lucene.Net.Index.IndexReader;
+ using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
+
+ /*
+ * 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.
+ */
+
+ using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+ using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+ using Term = Lucene.Net.Index.Term;
+ using TFIDFSimilarity = Lucene.Net.Search.Similarities.TFIDFSimilarity;
+
+ [TestFixture]
+ public class TestFieldMaskingSpanQuery : LuceneTestCase
+ {
+ protected internal static Document Doc(Field[] fields)
+ {
+ Document doc = new Document();
+ for (int i = 0; i < fields.Length; i++)
+ {
+ doc.Add(fields[i]);
+ }
+ return doc;
+ }
+
+ protected internal Field GetField(string name, string value)
+ {
+ return NewTextField(name, value, Field.Store.NO);
+ }
+
+ protected internal static IndexSearcher Searcher;
+ protected internal static Directory Directory;
+ protected internal static IndexReader Reader;
+
+ /// <summary>
+ /// LUCENENET specific
+ /// Is non-static because NewIndexWriterConfig is no longer static.
+ /// </summary>
+ [OneTimeSetUp]
+ public void BeforeClass()
+ {
+ Directory = NewDirectory();
+ RandomIndexWriter writer = new RandomIndexWriter(Random(), Directory, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
+
+ writer.AddDocument(Doc(new Field[] { GetField("id", "0"), GetField("gender", "male"), GetField("first", "james"), GetField("last", "jones") }));
+
+ writer.AddDocument(Doc(new Field[] { GetField("id", "1"), GetField("gender", "male"), GetField("first", "james"), GetField("last", "smith"), GetField("gender", "female"), GetField("first", "sally"), GetField("last", "jones") }));
+
+ writer.AddDocument(Doc(new Field[] { GetField("id", "2"), GetField("gender", "female"), GetField("first", "greta"), GetField("last", "jones"), GetField("gender", "female"), GetField("first", "sally"), GetField("last", "smith"), GetField("gender", "male"), GetField("first", "james"), GetField("last", "jones") }));
+
+ writer.AddDocument(Doc(new Field[] { GetField("id", "3"), GetField("gender", "female"), GetField("first", "lisa"), GetField("last", "jones"), GetField("gender", "male"), GetField("first", "bob"), GetField("last", "costas") }));
+
+ writer.AddDocument(Doc(new Field[] { GetField("id", "4"), GetField("gender", "female"), GetField("first", "sally"), GetField("last", "smith"), GetField("gender", "female"), GetField("first", "linda"), GetField("last", "dixit"), GetField("gender", "male"), GetField("first", "bubba"), GetField("last", "jones") }));
+ Reader = writer.Reader;
+ writer.Dispose();
+ Searcher = NewSearcher(Reader);
+ }
+
+ [OneTimeTearDown]
+ public static void AfterClass()
+ {
+ Searcher = null;
+ Reader.Dispose();
+ Reader = null;
+ Directory.Dispose();
+ Directory = null;
+ }
+
+ protected internal virtual void Check(SpanQuery q, int[] docs)
+ {
+ CheckHits.CheckHitCollector(Random(), q, null, Searcher, docs, Similarity);
+ }
+
+ [Test]
+ public virtual void TestRewrite0()
+ {
+ SpanQuery q = new FieldMaskingSpanQuery(new SpanTermQuery(new Term("last", "sally")), "first");
+ q.Boost = 8.7654321f;
+ SpanQuery qr = (SpanQuery)Searcher.Rewrite(q);
+
+ QueryUtils.CheckEqual(q, qr);
+
+ HashSet<Term> terms = new HashSet<Term>();
+ qr.ExtractTerms(terms);
+ Assert.AreEqual(1, terms.Count);
+ }
+
+ [Test]
+ public virtual void TestRewrite1()
+ {
+ // mask an anon SpanQuery class that rewrites to something else.
+ SpanQuery q = new FieldMaskingSpanQuery(new SpanTermQueryAnonymousInnerClassHelper(this, new Term("last", "sally")), "first");
+
+ SpanQuery qr = (SpanQuery)Searcher.Rewrite(q);
+
+ QueryUtils.CheckUnequal(q, qr);
+
+ HashSet<Term> terms = new HashSet<Term>();
+ qr.ExtractTerms(terms);
+ Assert.AreEqual(2, terms.Count);
+ }
+
+ private class SpanTermQueryAnonymousInnerClassHelper : SpanTermQuery
+ {
+ private readonly TestFieldMaskingSpanQuery OuterInstance;
+
+ public SpanTermQueryAnonymousInnerClassHelper(TestFieldMaskingSpanQuery outerInstance, Term term)
+ : base(term)
+ {
+ this.OuterInstance = outerInstance;
+ }
+
+ public override Query Rewrite(IndexReader reader)
+ {
+ return new SpanOrQuery(new SpanTermQuery(new Term("first", "sally")), new SpanTermQuery(new Term("first", "james")));
+ }
+ }
+
+ [Test]
+ public virtual void TestRewrite2()
+ {
+ SpanQuery q1 = new SpanTermQuery(new Term("last", "smith"));
+ SpanQuery q2 = new SpanTermQuery(new Term("last", "jones"));
+ SpanQuery q = new SpanNearQuery(new SpanQuery[] { q1, new FieldMaskingSpanQuery(q2, "last") }, 1, true);
+ Query qr = Searcher.Rewrite(q);
+
+ QueryUtils.CheckEqual(q, qr);
+
+ HashSet<Term> set = new HashSet<Term>();
+ qr.ExtractTerms(set);
+ Assert.AreEqual(2, set.Count);
+ }
+
+ [Test]
+ public virtual void TestEquality1()
+ {
+ SpanQuery q1 = new FieldMaskingSpanQuery(new SpanTermQuery(new Term("last", "sally")), "first");
+ SpanQuery q2 = new FieldMaskingSpanQuery(new SpanTermQuery(new Term("last", "sally")), "first");
+ SpanQuery q3 = new FieldMaskingSpanQuery(new SpanTermQuery(new Term("last", "sally")), "XXXXX");
+ SpanQuery q4 = new FieldMaskingSpanQuery(new SpanTermQuery(new Term("last", "XXXXX")), "first");
+ SpanQuery q5 = new FieldMaskingSpanQuery(new SpanTermQuery(new Term("xXXX", "sally")), "first");
+ QueryUtils.CheckEqual(q1, q2);
+ QueryUtils.CheckUnequal(q1, q3);
+ QueryUtils.CheckUnequal(q1, q4);
+ QueryUtils.CheckUnequal(q1, q5);
+
+ SpanQuery qA = new FieldMaskingSpanQuery(new SpanTermQuery(new Term("last", "sally")), "first");
+ qA.Boost = 9f;
+ SpanQuery qB = new FieldMaskingSpanQuery(new SpanTermQuery(new Term("last", "sally")), "first");
+ QueryUtils.CheckUnequal(qA, qB);
+ qB.Boost = 9f;
+ QueryUtils.CheckEqual(qA, qB);
+ }
+
+ [Test]
+ public virtual void TestNoop0()
+ {
+ SpanQuery q1 = new SpanTermQuery(new Term("last", "sally"));
+ SpanQuery q = new FieldMaskingSpanQuery(q1, "first");
+ Check(q, new int[] { }); // :EMPTY:
+ }
+
+ [Test]
+ public virtual void TestNoop1()
+ {
+ SpanQuery q1 = new SpanTermQuery(new Term("last", "smith"));
+ SpanQuery q2 = new SpanTermQuery(new Term("last", "jones"));
+ SpanQuery q = new SpanNearQuery(new SpanQuery[] { q1, new FieldMaskingSpanQuery(q2, "last") }, 0, true);
+ Check(q, new int[] { 1, 2 });
+ q = new SpanNearQuery(new SpanQuery[] { new FieldMaskingSpanQuery(q1, "last"), new FieldMaskingSpanQuery(q2, "last") }, 0, true);
+ Check(q, new int[] { 1, 2 });
+ }
+
+ [Test]
+ public virtual void TestSimple1()
+ {
+ SpanQuery q1 = new SpanTermQuery(new Term("first", "james"));
+ SpanQuery q2 = new SpanTermQuery(new Term("last", "jones"));
+ SpanQuery q = new SpanNearQuery(new SpanQuery[] { q1, new FieldMaskingSpanQuery(q2, "first") }, -1, false);
+ Check(q, new int[] { 0, 2 });
+ q = new SpanNearQuery(new SpanQuery[] { new FieldMaskingSpanQuery(q2, "first"), q1 }, -1, false);
+ Check(q, new int[] { 0, 2 });
+ q = new SpanNearQuery(new SpanQuery[] { q2, new FieldMaskingSpanQuery(q1, "last") }, -1, false);
+ Check(q, new int[] { 0, 2 });
+ q = new SpanNearQuery(new SpanQuery[] { new FieldMaskingSpanQuery(q1, "last"), q2 }, -1, false);
+ Check(q, new int[] { 0, 2 });
+ }
+
+ [Test]
+ public virtual void TestSimple2()
+ {
+ AssumeTrue("Broken scoring: LUCENE-3723", Searcher.Similarity is TFIDFSimilarity);
+ SpanQuery q1 = new SpanTermQuery(new Term("gender", "female"));
+ SpanQuery q2 = new SpanTermQuery(new Term("last", "smith"));
+ SpanQuery q = new SpanNearQuery(new SpanQuery[] { q1, new FieldMaskingSpanQuery(q2, "gender") }, -1, false);
+ Check(q, new int[] { 2, 4 });
+ q = new SpanNearQuery(new SpanQuery[] { new FieldMaskingSpanQuery(q1, "id"), new FieldMaskingSpanQuery(q2, "id") }, -1, false);
+ Check(q, new int[] { 2, 4 });
+ }
+
+ [Test]
+ public virtual void TestSpans0()
+ {
+ SpanQuery q1 = new SpanTermQuery(new Term("gender", "female"));
+ SpanQuery q2 = new SpanTermQuery(new Term("first", "james"));
+ SpanQuery q = new SpanOrQuery(q1, new FieldMaskingSpanQuery(q2, "gender"));
+ Check(q, new int[] { 0, 1, 2, 3, 4 });
+
+ Spans span = MultiSpansWrapper.Wrap(Searcher.TopReaderContext, q);
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(0, 0, 1), s(span));
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(1, 0, 1), s(span));
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(1, 1, 2), s(span));
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(2, 0, 1), s(span));
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(2, 1, 2), s(span));
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(2, 2, 3), s(span));
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(3, 0, 1), s(span));
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(4, 0, 1), s(span));
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(4, 1, 2), s(span));
+
+ Assert.AreEqual(false, span.Next());
+ }
+
+ [Test]
+ public virtual void TestSpans1()
+ {
+ SpanQuery q1 = new SpanTermQuery(new Term("first", "sally"));
+ SpanQuery q2 = new SpanTermQuery(new Term("first", "james"));
+ SpanQuery qA = new SpanOrQuery(q1, q2);
+ SpanQuery qB = new FieldMaskingSpanQuery(qA, "id");
+
+ Check(qA, new int[] { 0, 1, 2, 4 });
+ Check(qB, new int[] { 0, 1, 2, 4 });
+
+ Spans spanA = MultiSpansWrapper.Wrap(Searcher.TopReaderContext, qA);
+ Spans spanB = MultiSpansWrapper.Wrap(Searcher.TopReaderContext, qB);
+
+ while (spanA.Next())
+ {
+ Assert.IsTrue(spanB.Next(), "spanB not still going");
+ Assert.AreEqual(s(spanA), s(spanB), "spanA not equal spanB");
+ }
+ Assert.IsTrue(!(spanB.Next()), "spanB still going even tough spanA is done");
+ }
+
+ [Test]
+ public virtual void TestSpans2()
+ {
+ AssumeTrue("Broken scoring: LUCENE-3723", Searcher.Similarity is TFIDFSimilarity);
+ SpanQuery qA1 = new SpanTermQuery(new Term("gender", "female"));
+ SpanQuery qA2 = new SpanTermQuery(new Term("first", "james"));
+ SpanQuery qA = new SpanOrQuery(qA1, new FieldMaskingSpanQuery(qA2, "gender"));
+ SpanQuery qB = new SpanTermQuery(new Term("last", "jones"));
+ SpanQuery q = new SpanNearQuery(new SpanQuery[] { new FieldMaskingSpanQuery(qA, "id"), new FieldMaskingSpanQuery(qB, "id") }, -1, false);
+ Check(q, new int[] { 0, 1, 2, 3 });
+
+ Spans span = MultiSpansWrapper.Wrap(Searcher.TopReaderContext, q);
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(0, 0, 1), s(span));
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(1, 1, 2), s(span));
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(2, 0, 1), s(span));
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(2, 2, 3), s(span));
+
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(3, 0, 1), s(span));
+
+ Assert.AreEqual(false, span.Next());
+ }
+
+ public virtual string s(Spans span)
+ {
+ return s(span.Doc, span.Start, span.End);
+ }
+
+ public virtual string s(int doc, int start, int end)
+ {
+ return "s(" + doc + "," + start + "," + end + ")";
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/Spans/TestNearSpansOrdered.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Search/Spans/TestNearSpansOrdered.cs b/src/Lucene.Net.Tests/Search/Spans/TestNearSpansOrdered.cs
new file mode 100644
index 0000000..0bbcafb
--- /dev/null
+++ b/src/Lucene.Net.Tests/Search/Spans/TestNearSpansOrdered.cs
@@ -0,0 +1,203 @@
+using Lucene.Net.Documents;
+
+namespace Lucene.Net.Search.Spans
+{
+ using Lucene.Net.Index;
+ using NUnit.Framework;
+ using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
+ using Directory = Lucene.Net.Store.Directory;
+ using Document = Documents.Document;
+ using Field = Field;
+ using IndexReader = Lucene.Net.Index.IndexReader;
+ using IndexReaderContext = Lucene.Net.Index.IndexReaderContext;
+ using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
+
+ /*
+ * 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.
+ */
+
+ using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+ using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+ using Term = Lucene.Net.Index.Term;
+
+ [TestFixture]
+ public class TestNearSpansOrdered : LuceneTestCase
+ {
+ protected internal IndexSearcher Searcher;
+ protected internal Directory Directory;
+ protected internal IndexReader Reader;
+
+ public const string FIELD = "field";
+
+ [TearDown]
+ public override void TearDown()
+ {
+ Reader.Dispose();
+ Directory.Dispose();
+ base.TearDown();
+ }
+
+ [SetUp]
+ public override void SetUp()
+ {
+ base.SetUp();
+ Directory = NewDirectory();
+ RandomIndexWriter writer = new RandomIndexWriter(Random(), Directory, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
+ for (int i = 0; i < DocFields.Length; i++)
+ {
+ Document doc = new Document();
+ doc.Add(NewTextField(FIELD, DocFields[i], Field.Store.NO));
+ writer.AddDocument(doc);
+ }
+ Reader = writer.Reader;
+ writer.Dispose();
+ Searcher = NewSearcher(Reader);
+ }
+
+ protected internal string[] DocFields = new string[] { "w1 w2 w3 w4 w5", "w1 w3 w2 w3 zz", "w1 xx w2 yy w3", "w1 w3 xx w2 yy w3 zz" };
+
+ protected internal virtual SpanNearQuery MakeQuery(string s1, string s2, string s3, int slop, bool inOrder)
+ {
+ return new SpanNearQuery(new SpanQuery[] { new SpanTermQuery(new Term(FIELD, s1)), new SpanTermQuery(new Term(FIELD, s2)), new SpanTermQuery(new Term(FIELD, s3)) }, slop, inOrder);
+ }
+
+ protected internal virtual SpanNearQuery MakeQuery()
+ {
+ return MakeQuery("w1", "w2", "w3", 1, true);
+ }
+
+ [Test]
+ public virtual void TestSpanNearQuery()
+ {
+ SpanNearQuery q = MakeQuery();
+ CheckHits.DoCheckHits(Random(), q, FIELD, Searcher, new int[] { 0, 1 }, Similarity);
+ }
+
+ public virtual string s(Spans span)
+ {
+ return s(span.Doc, span.Start, span.End);
+ }
+
+ public virtual string s(int doc, int start, int end)
+ {
+ return "s(" + doc + "," + start + "," + end + ")";
+ }
+
+ [Test]
+ public virtual void TestNearSpansNext()
+ {
+ SpanNearQuery q = MakeQuery();
+ Spans span = MultiSpansWrapper.Wrap(Searcher.TopReaderContext, q);
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(0, 0, 3), s(span));
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(1, 0, 4), s(span));
+ Assert.AreEqual(false, span.Next());
+ }
+
+ /// <summary>
+ /// test does not imply that skipTo(doc+1) should work exactly the
+ /// same as next -- it's only applicable in this case since we know doc
+ /// does not contain more than one span
+ /// </summary>
+ [Test]
+ public virtual void TestNearSpansSkipToLikeNext()
+ {
+ SpanNearQuery q = MakeQuery();
+ Spans span = MultiSpansWrapper.Wrap(Searcher.TopReaderContext, q);
+ Assert.AreEqual(true, span.SkipTo(0));
+ Assert.AreEqual(s(0, 0, 3), s(span));
+ Assert.AreEqual(true, span.SkipTo(1));
+ Assert.AreEqual(s(1, 0, 4), s(span));
+ Assert.AreEqual(false, span.SkipTo(2));
+ }
+
+ [Test]
+ public virtual void TestNearSpansNextThenSkipTo()
+ {
+ SpanNearQuery q = MakeQuery();
+ Spans span = MultiSpansWrapper.Wrap(Searcher.TopReaderContext, q);
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(0, 0, 3), s(span));
+ Assert.AreEqual(true, span.SkipTo(1));
+ Assert.AreEqual(s(1, 0, 4), s(span));
+ Assert.AreEqual(false, span.Next());
+ }
+
+ [Test]
+ public virtual void TestNearSpansNextThenSkipPast()
+ {
+ SpanNearQuery q = MakeQuery();
+ Spans span = MultiSpansWrapper.Wrap(Searcher.TopReaderContext, q);
+ Assert.AreEqual(true, span.Next());
+ Assert.AreEqual(s(0, 0, 3), s(span));
+ Assert.AreEqual(false, span.SkipTo(2));
+ }
+
+ [Test]
+ public virtual void TestNearSpansSkipPast()
+ {
+ SpanNearQuery q = MakeQuery();
+ Spans span = MultiSpansWrapper.Wrap(Searcher.TopReaderContext, q);
+ Assert.AreEqual(false, span.SkipTo(2));
+ }
+
+ [Test]
+ public virtual void TestNearSpansSkipTo0()
+ {
+ SpanNearQuery q = MakeQuery();
+ Spans span = MultiSpansWrapper.Wrap(Searcher.TopReaderContext, q);
+ Assert.AreEqual(true, span.SkipTo(0));
+ Assert.AreEqual(s(0, 0, 3), s(span));
+ }
+
+ [Test]
+ public virtual void TestNearSpansSkipTo1()
+ {
+ SpanNearQuery q = MakeQuery();
+ Spans span = MultiSpansWrapper.Wrap(Searcher.TopReaderContext, q);
+ Assert.AreEqual(true, span.SkipTo(1));
+ Assert.AreEqual(s(1, 0, 4), s(span));
+ }
+
+ /// <summary>
+ /// not a direct test of NearSpans, but a demonstration of how/when
+ /// this causes problems
+ /// </summary>
+ [Test]
+ public virtual void TestSpanNearScorerSkipTo1()
+ {
+ SpanNearQuery q = MakeQuery();
+ Weight w = Searcher.CreateNormalizedWeight(q);
+ IndexReaderContext topReaderContext = Searcher.TopReaderContext;
+ AtomicReaderContext leave = topReaderContext.Leaves[0];
+ Scorer s = w.GetScorer(leave, ((AtomicReader)leave.Reader).LiveDocs);
+ Assert.AreEqual(1, s.Advance(1));
+ }
+
+ /// <summary>
+ /// not a direct test of NearSpans, but a demonstration of how/when
+ /// this causes problems
+ /// </summary>
+ [Test]
+ public virtual void TestSpanNearScorerExplain()
+ {
+ SpanNearQuery q = MakeQuery();
+ Explanation e = Searcher.Explain(q, 1);
+ Assert.IsTrue(0.0f < e.Value, "Scorer explanation value for doc#1 isn't positive: " + e.ToString());
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/Spans/TestPayloadSpans.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Search/Spans/TestPayloadSpans.cs b/src/Lucene.Net.Tests/Search/Spans/TestPayloadSpans.cs
new file mode 100644
index 0000000..a9393b4
--- /dev/null
+++ b/src/Lucene.Net.Tests/Search/Spans/TestPayloadSpans.cs
@@ -0,0 +1,589 @@
+using Lucene.Net.Analysis.TokenAttributes;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Lucene.Net.Documents;
+
+namespace Lucene.Net.Search.Spans
+{
+ using NUnit.Framework;
+ using System.IO;
+
+ /*
+ /// Copyright 2004 The Apache Software Foundation
+ ///
+ /// Licensed 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.
+ */
+
+ using Analyzer = Lucene.Net.Analysis.Analyzer;
+ using BytesRef = Lucene.Net.Util.BytesRef;
+ using DefaultSimilarity = Lucene.Net.Search.Similarities.DefaultSimilarity;
+ using Directory = Lucene.Net.Store.Directory;
+ using Document = Documents.Document;
+ using Field = Field;
+ using IndexReader = Lucene.Net.Index.IndexReader;
+ using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
+ using MockTokenizer = Lucene.Net.Analysis.MockTokenizer;
+ using PayloadHelper = Lucene.Net.Search.Payloads.PayloadHelper;
+ using PayloadSpanUtil = Lucene.Net.Search.Payloads.PayloadSpanUtil;
+ using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+ using Similarity = Lucene.Net.Search.Similarities.Similarity;
+ using Term = Lucene.Net.Index.Term;
+ using TextField = TextField;
+ using TokenFilter = Lucene.Net.Analysis.TokenFilter;
+ using Tokenizer = Lucene.Net.Analysis.Tokenizer;
+ using TokenStream = Lucene.Net.Analysis.TokenStream;
+
+ [TestFixture]
+ public class TestPayloadSpans : LuceneTestCase
+ {
+ private IndexSearcher Searcher_Renamed;
+ private Similarity similarity = new DefaultSimilarity();
+ protected internal IndexReader IndexReader;
+ private IndexReader CloseIndexReader;
+ private Directory Directory;
+
+ [SetUp]
+ public override void SetUp()
+ {
+ base.SetUp();
+ PayloadHelper helper = new PayloadHelper();
+ Searcher_Renamed = helper.SetUp(Random(), similarity, 1000);
+ IndexReader = Searcher_Renamed.IndexReader;
+ }
+
+ [Test]
+ public virtual void TestSpanTermQuery()
+ {
+ SpanTermQuery stq;
+ Spans spans;
+ stq = new SpanTermQuery(new Term(PayloadHelper.FIELD, "seventy"));
+ spans = MultiSpansWrapper.Wrap(IndexReader.Context, stq);
+ Assert.IsTrue(spans != null, "spans is null and it shouldn't be");
+ CheckSpans(spans, 100, 1, 1, 1);
+
+ stq = new SpanTermQuery(new Term(PayloadHelper.NO_PAYLOAD_FIELD, "seventy"));
+ spans = MultiSpansWrapper.Wrap(IndexReader.Context, stq);
+ Assert.IsTrue(spans != null, "spans is null and it shouldn't be");
+ CheckSpans(spans, 100, 0, 0, 0);
+ }
+
+ [Test]
+ public virtual void TestSpanFirst()
+ {
+ SpanQuery match;
+ SpanFirstQuery sfq;
+ match = new SpanTermQuery(new Term(PayloadHelper.FIELD, "one"));
+ sfq = new SpanFirstQuery(match, 2);
+ Spans spans = MultiSpansWrapper.Wrap(IndexReader.Context, sfq);
+ CheckSpans(spans, 109, 1, 1, 1);
+ //Test more complicated subclause
+ SpanQuery[] clauses = new SpanQuery[2];
+ clauses[0] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "one"));
+ clauses[1] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "hundred"));
+ match = new SpanNearQuery(clauses, 0, true);
+ sfq = new SpanFirstQuery(match, 2);
+ CheckSpans(MultiSpansWrapper.Wrap(IndexReader.Context, sfq), 100, 2, 1, 1);
+
+ match = new SpanNearQuery(clauses, 0, false);
+ sfq = new SpanFirstQuery(match, 2);
+ CheckSpans(MultiSpansWrapper.Wrap(IndexReader.Context, sfq), 100, 2, 1, 1);
+ }
+
+ [Test]
+ public virtual void TestSpanNot()
+ {
+ SpanQuery[] clauses = new SpanQuery[2];
+ clauses[0] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "one"));
+ clauses[1] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "three"));
+ SpanQuery spq = new SpanNearQuery(clauses, 5, true);
+ SpanNotQuery snq = new SpanNotQuery(spq, new SpanTermQuery(new Term(PayloadHelper.FIELD, "two")));
+
+ Directory directory = NewDirectory();
+ RandomIndexWriter writer = new RandomIndexWriter(Random(), directory, NewIndexWriterConfig(TEST_VERSION_CURRENT, new PayloadAnalyzer(this)).SetSimilarity(similarity));
+
+ Document doc = new Document();
+ doc.Add(NewTextField(PayloadHelper.FIELD, "one two three one four three", Field.Store.YES));
+ writer.AddDocument(doc);
+ IndexReader reader = writer.Reader;
+ writer.Dispose();
+
+ CheckSpans(MultiSpansWrapper.Wrap(reader.Context, snq), 1, new int[] { 2 });
+ reader.Dispose();
+ directory.Dispose();
+ }
+
+ [Test]
+ public virtual void TestNestedSpans()
+ {
+ SpanTermQuery stq;
+ Spans spans;
+ IndexSearcher searcher = Searcher;
+ stq = new SpanTermQuery(new Term(PayloadHelper.FIELD, "mark"));
+ spans = MultiSpansWrapper.Wrap(searcher.TopReaderContext, stq);
+ Assert.IsTrue(spans != null, "spans is null and it shouldn't be");
+ CheckSpans(spans, 0, null);
+
+ SpanQuery[] clauses = new SpanQuery[3];
+ clauses[0] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "rr"));
+ clauses[1] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "yy"));
+ clauses[2] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "xx"));
+ SpanNearQuery spanNearQuery = new SpanNearQuery(clauses, 12, false);
+
+ spans = MultiSpansWrapper.Wrap(searcher.TopReaderContext, spanNearQuery);
+ Assert.IsTrue(spans != null, "spans is null and it shouldn't be");
+ CheckSpans(spans, 2, new int[] { 3, 3 });
+
+ clauses[0] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "xx"));
+ clauses[1] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "rr"));
+ clauses[2] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "yy"));
+
+ spanNearQuery = new SpanNearQuery(clauses, 6, true);
+
+ spans = MultiSpansWrapper.Wrap(searcher.TopReaderContext, spanNearQuery);
+
+ Assert.IsTrue(spans != null, "spans is null and it shouldn't be");
+ CheckSpans(spans, 1, new int[] { 3 });
+
+ clauses = new SpanQuery[2];
+
+ clauses[0] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "xx"));
+ clauses[1] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "rr"));
+
+ spanNearQuery = new SpanNearQuery(clauses, 6, true);
+
+ // xx within 6 of rr
+
+ SpanQuery[] clauses2 = new SpanQuery[2];
+
+ clauses2[0] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "yy"));
+ clauses2[1] = spanNearQuery;
+
+ SpanNearQuery nestedSpanNearQuery = new SpanNearQuery(clauses2, 6, false);
+
+ // yy within 6 of xx within 6 of rr
+
+ spans = MultiSpansWrapper.Wrap(searcher.TopReaderContext, nestedSpanNearQuery);
+ Assert.IsTrue(spans != null, "spans is null and it shouldn't be");
+ CheckSpans(spans, 2, new int[] { 3, 3 });
+ CloseIndexReader.Dispose();
+ Directory.Dispose();
+ }
+
+ [Test]
+ public virtual void TestFirstClauseWithoutPayload()
+ {
+ Spans spans;
+ IndexSearcher searcher = Searcher;
+
+ SpanQuery[] clauses = new SpanQuery[3];
+ clauses[0] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "nopayload"));
+ clauses[1] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "qq"));
+ clauses[2] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "ss"));
+
+ SpanNearQuery spanNearQuery = new SpanNearQuery(clauses, 6, true);
+
+ SpanQuery[] clauses2 = new SpanQuery[2];
+
+ clauses2[0] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "pp"));
+ clauses2[1] = spanNearQuery;
+
+ SpanNearQuery snq = new SpanNearQuery(clauses2, 6, false);
+
+ SpanQuery[] clauses3 = new SpanQuery[2];
+
+ clauses3[0] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "np"));
+ clauses3[1] = snq;
+
+ SpanNearQuery nestedSpanNearQuery = new SpanNearQuery(clauses3, 6, false);
+ spans = MultiSpansWrapper.Wrap(searcher.TopReaderContext, nestedSpanNearQuery);
+
+ Assert.IsTrue(spans != null, "spans is null and it shouldn't be");
+ CheckSpans(spans, 1, new int[] { 3 });
+ CloseIndexReader.Dispose();
+ Directory.Dispose();
+ }
+
+ [Test]
+ public virtual void TestHeavilyNestedSpanQuery()
+ {
+ Spans spans;
+ IndexSearcher searcher = Searcher;
+
+ SpanQuery[] clauses = new SpanQuery[3];
+ clauses[0] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "one"));
+ clauses[1] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "two"));
+ clauses[2] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "three"));
+
+ SpanNearQuery spanNearQuery = new SpanNearQuery(clauses, 5, true);
+
+ clauses = new SpanQuery[3];
+ clauses[0] = spanNearQuery;
+ clauses[1] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "five"));
+ clauses[2] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "six"));
+
+ SpanNearQuery spanNearQuery2 = new SpanNearQuery(clauses, 6, true);
+
+ SpanQuery[] clauses2 = new SpanQuery[2];
+ clauses2[0] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "eleven"));
+ clauses2[1] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "ten"));
+ SpanNearQuery spanNearQuery3 = new SpanNearQuery(clauses2, 2, false);
+
+ SpanQuery[] clauses3 = new SpanQuery[3];
+ clauses3[0] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "nine"));
+ clauses3[1] = spanNearQuery2;
+ clauses3[2] = spanNearQuery3;
+
+ SpanNearQuery nestedSpanNearQuery = new SpanNearQuery(clauses3, 6, false);
+
+ spans = MultiSpansWrapper.Wrap(searcher.TopReaderContext, nestedSpanNearQuery);
+ Assert.IsTrue(spans != null, "spans is null and it shouldn't be");
+ CheckSpans(spans, 2, new int[] { 8, 8 });
+ CloseIndexReader.Dispose();
+ Directory.Dispose();
+ }
+
+ [Test]
+ public virtual void TestShrinkToAfterShortestMatch()
+ {
+ Directory directory = NewDirectory();
+ RandomIndexWriter writer = new RandomIndexWriter(Random(), directory, NewIndexWriterConfig(TEST_VERSION_CURRENT, new TestPayloadAnalyzer(this)));
+
+ Document doc = new Document();
+ doc.Add(new TextField("content", new StringReader("a b c d e f g h i j a k")));
+ writer.AddDocument(doc);
+
+ IndexReader reader = writer.Reader;
+ IndexSearcher @is = NewSearcher(reader);
+ writer.Dispose();
+
+ SpanTermQuery stq1 = new SpanTermQuery(new Term("content", "a"));
+ SpanTermQuery stq2 = new SpanTermQuery(new Term("content", "k"));
+ SpanQuery[] sqs = new SpanQuery[] { stq1, stq2 };
+ SpanNearQuery snq = new SpanNearQuery(sqs, 1, true);
+ Spans spans = MultiSpansWrapper.Wrap(@is.TopReaderContext, snq);
+
+ TopDocs topDocs = @is.Search(snq, 1);
+ HashSet<string> payloadSet = new HashSet<string>();
+ for (int i = 0; i < topDocs.ScoreDocs.Length; i++)
+ {
+ while (spans.Next())
+ {
+ var payloads = spans.GetPayload();
+ foreach (var payload in payloads)
+ {
+ payloadSet.Add(Encoding.UTF8.GetString(payload));
+ }
+ }
+ }
+ Assert.AreEqual(2, payloadSet.Count);
+ Assert.IsTrue(payloadSet.Contains("a:Noise:10"));
+ Assert.IsTrue(payloadSet.Contains("k:Noise:11"));
+ reader.Dispose();
+ directory.Dispose();
+ }
+
+ [Test]
+ public virtual void TestShrinkToAfterShortestMatch2()
+ {
+ Directory directory = NewDirectory();
+ RandomIndexWriter writer = new RandomIndexWriter(Random(), directory, NewIndexWriterConfig(TEST_VERSION_CURRENT, new TestPayloadAnalyzer(this)));
+
+ Document doc = new Document();
+ doc.Add(new TextField("content", new StringReader("a b a d k f a h i k a k")));
+ writer.AddDocument(doc);
+ IndexReader reader = writer.Reader;
+ IndexSearcher @is = NewSearcher(reader);
+ writer.Dispose();
+
+ SpanTermQuery stq1 = new SpanTermQuery(new Term("content", "a"));
+ SpanTermQuery stq2 = new SpanTermQuery(new Term("content", "k"));
+ SpanQuery[] sqs = { stq1, stq2 };
+ SpanNearQuery snq = new SpanNearQuery(sqs, 0, true);
+ Spans spans = MultiSpansWrapper.Wrap(@is.TopReaderContext, snq);
+
+ TopDocs topDocs = @is.Search(snq, 1);
+ HashSet<string> payloadSet = new HashSet<string>();
+ for (int i = 0; i < topDocs.ScoreDocs.Length; i++)
+ {
+ while (spans.Next())
+ {
+ var payloads = spans.GetPayload();
+ foreach (var payload in payloads)
+ {
+ payloadSet.Add(Encoding.UTF8.GetString((byte[])(Array)payload));
+ }
+ }
+ }
+ Assert.AreEqual(2, payloadSet.Count);
+ Assert.IsTrue(payloadSet.Contains("a:Noise:10"));
+ Assert.IsTrue(payloadSet.Contains("k:Noise:11"));
+ reader.Dispose();
+ directory.Dispose();
+ }
+
+ [Test]
+ public virtual void TestShrinkToAfterShortestMatch3()
+ {
+ Directory directory = NewDirectory();
+ RandomIndexWriter writer = new RandomIndexWriter(Random(), directory, NewIndexWriterConfig(TEST_VERSION_CURRENT, new TestPayloadAnalyzer(this)));
+
+ Document doc = new Document();
+ doc.Add(new TextField("content", new StringReader("j k a l f k k p a t a k l k t a")));
+ writer.AddDocument(doc);
+ IndexReader reader = writer.Reader;
+ IndexSearcher @is = NewSearcher(reader);
+ writer.Dispose();
+
+ SpanTermQuery stq1 = new SpanTermQuery(new Term("content", "a"));
+ SpanTermQuery stq2 = new SpanTermQuery(new Term("content", "k"));
+ SpanQuery[] sqs = new SpanQuery[] { stq1, stq2 };
+ SpanNearQuery snq = new SpanNearQuery(sqs, 0, true);
+ Spans spans = MultiSpansWrapper.Wrap(@is.TopReaderContext, snq);
+
+ TopDocs topDocs = @is.Search(snq, 1);
+ HashSet<string> payloadSet = new HashSet<string>();
+ for (int i = 0; i < topDocs.ScoreDocs.Length; i++)
+ {
+ while (spans.Next())
+ {
+ var payloads = spans.GetPayload();
+ foreach (var payload in payloads)
+ {
+ payloadSet.Add(Encoding.UTF8.GetString(payload));
+ }
+ }
+ }
+ Assert.AreEqual(2, payloadSet.Count);
+ if (VERBOSE)
+ {
+ foreach (String payload in payloadSet)
+ {
+ Console.WriteLine("match:" + payload);
+ }
+ }
+ Assert.IsTrue(payloadSet.Contains("a:Noise:10"));
+ Assert.IsTrue(payloadSet.Contains("k:Noise:11"));
+ reader.Dispose();
+ directory.Dispose();
+ }
+
+ [Test]
+ public virtual void TestPayloadSpanUtil()
+ {
+ Directory directory = NewDirectory();
+ RandomIndexWriter writer = new RandomIndexWriter(Random(), directory, NewIndexWriterConfig(TEST_VERSION_CURRENT, new PayloadAnalyzer(this)).SetSimilarity(similarity));
+
+ Document doc = new Document();
+ doc.Add(NewTextField(PayloadHelper.FIELD, "xx rr yy mm pp", Field.Store.YES));
+ writer.AddDocument(doc);
+
+ IndexReader reader = writer.Reader;
+ writer.Dispose();
+ IndexSearcher searcher = NewSearcher(reader);
+
+ PayloadSpanUtil psu = new PayloadSpanUtil(searcher.TopReaderContext);
+
+ var payloads = psu.GetPayloadsForQuery(new TermQuery(new Term(PayloadHelper.FIELD, "rr")));
+ if (VERBOSE)
+ {
+ Console.WriteLine("Num payloads:" + payloads.Count);
+ foreach (var bytes in payloads)
+ {
+ Console.WriteLine(Encoding.UTF8.GetString((byte[])(Array)bytes));
+ }
+ }
+ reader.Dispose();
+ directory.Dispose();
+ }
+
+ private void CheckSpans(Spans spans, int expectedNumSpans, int expectedNumPayloads, int expectedPayloadLength, int expectedFirstByte)
+ {
+ Assert.IsTrue(spans != null, "spans is null and it shouldn't be");
+ //each position match should have a span associated with it, since there is just one underlying term query, there should
+ //only be one entry in the span
+ int seen = 0;
+ while (spans.Next() == true)
+ {
+ //if we expect payloads, then isPayloadAvailable should be true
+ if (expectedNumPayloads > 0)
+ {
+ Assert.IsTrue(spans.IsPayloadAvailable == true, "isPayloadAvailable is not returning the correct value: " + spans.IsPayloadAvailable + " and it should be: " + (expectedNumPayloads > 0));
+ }
+ else
+ {
+ Assert.IsTrue(spans.IsPayloadAvailable == false, "isPayloadAvailable should be false");
+ }
+ //See payload helper, for the PayloadHelper.FIELD field, there is a single byte payload at every token
+ if (spans.IsPayloadAvailable)
+ {
+ var payload = spans.GetPayload();
+ Assert.IsTrue(payload.Count == expectedNumPayloads, "payload Size: " + payload.Count + " is not: " + expectedNumPayloads);
+ foreach (var thePayload in payload)
+ {
+ Assert.IsTrue(thePayload.Length == expectedPayloadLength, "payload[0] Size: " + thePayload.Length + " is not: " + expectedPayloadLength);
+ Assert.IsTrue(thePayload[0] == expectedFirstByte, thePayload[0] + " does not equal: " + expectedFirstByte);
+ }
+ }
+ seen++;
+ }
+ Assert.IsTrue(seen == expectedNumSpans, seen + " does not equal: " + expectedNumSpans);
+ }
+
+ private IndexSearcher Searcher
+ {
+ get
+ {
+ Directory = NewDirectory();
+ string[] docs = new string[] { "xx rr yy mm pp", "xx yy mm rr pp", "nopayload qq ss pp np", "one two three four five six seven eight nine ten eleven", "nine one two three four five six seven eight eleven ten" };
+ RandomIndexWriter writer = new RandomIndexWriter(Random(), Directory, NewIndexWriterConfig(TEST_VERSION_CURRENT, new PayloadAnalyzer(this)).SetSimilarity(similarity));
+
+ Document doc = null;
+ for (int i = 0; i < docs.Length; i++)
+ {
+ doc = new Document();
+ string docText = docs[i];
+ doc.Add(NewTextField(PayloadHelper.FIELD, docText, Field.Store.YES));
+ writer.AddDocument(doc);
+ }
+
+ CloseIndexReader = writer.Reader;
+ writer.Dispose();
+
+ IndexSearcher searcher = NewSearcher(CloseIndexReader);
+ return searcher;
+ }
+ }
+
+ private void CheckSpans(Spans spans, int numSpans, int[] numPayloads)
+ {
+ int cnt = 0;
+
+ while (spans.Next() == true)
+ {
+ if (VERBOSE)
+ {
+ Console.WriteLine("\nSpans Dump --");
+ }
+ if (spans.IsPayloadAvailable)
+ {
+ var payload = spans.GetPayload();
+ if (VERBOSE)
+ {
+ Console.WriteLine("payloads for span:" + payload.Count);
+ foreach (var bytes in payload)
+ {
+ Console.WriteLine("doc:" + spans.Doc + " s:" + spans.Start + " e:" + spans.End + " " + Encoding.UTF8.GetString((byte[])(Array)bytes));
+ }
+ }
+
+ Assert.AreEqual(numPayloads[cnt], payload.Count);
+ }
+ else
+ {
+ Assert.IsFalse(numPayloads.Length > 0 && numPayloads[cnt] > 0, "Expected spans:" + numPayloads[cnt] + " found: 0");
+ }
+ cnt++;
+ }
+
+ Assert.AreEqual(numSpans, cnt);
+ }
+
+ internal sealed class PayloadAnalyzer : Analyzer
+ {
+ private readonly TestPayloadSpans OuterInstance;
+
+ public PayloadAnalyzer(TestPayloadSpans outerInstance)
+ {
+ this.OuterInstance = outerInstance;
+ }
+
+ protected internal override TokenStreamComponents CreateComponents(string fieldName, TextReader reader)
+ {
+ Tokenizer result = new MockTokenizer(reader, MockTokenizer.SIMPLE, true);
+ return new TokenStreamComponents(result, new PayloadFilter(OuterInstance, result));
+ }
+ }
+
+ internal sealed class PayloadFilter : TokenFilter
+ {
+ private readonly TestPayloadSpans OuterInstance;
+
+ internal HashSet<string> Entities = new HashSet<string>();
+ internal HashSet<string> Nopayload = new HashSet<string>();
+ internal int Pos;
+ internal IPayloadAttribute PayloadAtt;
+ internal ICharTermAttribute TermAtt;
+ internal IPositionIncrementAttribute PosIncrAtt;
+
+ public PayloadFilter(TestPayloadSpans outerInstance, TokenStream input)
+ : base(input)
+ {
+ this.OuterInstance = outerInstance;
+ Pos = 0;
+ Entities.Add("xx");
+ Entities.Add("one");
+ Nopayload.Add("nopayload");
+ Nopayload.Add("np");
+ TermAtt = AddAttribute<ICharTermAttribute>();
+ PosIncrAtt = AddAttribute<IPositionIncrementAttribute>();
+ PayloadAtt = AddAttribute<IPayloadAttribute>();
+ }
+
+ public override bool IncrementToken()
+ {
+ if (m_input.IncrementToken())
+ {
+ string token = TermAtt.ToString();
+
+ if (!Nopayload.Contains(token))
+ {
+ if (Entities.Contains(token))
+ {
+ PayloadAtt.Payload = new BytesRef(token + ":Entity:" + Pos);
+ }
+ else
+ {
+ PayloadAtt.Payload = new BytesRef(token + ":Noise:" + Pos);
+ }
+ }
+ Pos += PosIncrAtt.PositionIncrement;
+ return true;
+ }
+ return false;
+ }
+
+ public override void Reset()
+ {
+ base.Reset();
+ this.Pos = 0;
+ }
+ }
+
+ public sealed class TestPayloadAnalyzer : Analyzer
+ {
+ private readonly TestPayloadSpans OuterInstance;
+
+ public TestPayloadAnalyzer(TestPayloadSpans outerInstance)
+ {
+ this.OuterInstance = outerInstance;
+ }
+
+ protected internal override TokenStreamComponents CreateComponents(string fieldName, TextReader reader)
+ {
+ Tokenizer result = new MockTokenizer(reader, MockTokenizer.SIMPLE, true);
+ return new TokenStreamComponents(result, new PayloadFilter(OuterInstance, result));
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/Spans/TestSpanExplanations.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Search/Spans/TestSpanExplanations.cs b/src/Lucene.Net.Tests/Search/Spans/TestSpanExplanations.cs
new file mode 100644
index 0000000..a5b92ec
--- /dev/null
+++ b/src/Lucene.Net.Tests/Search/Spans/TestSpanExplanations.cs
@@ -0,0 +1,260 @@
+using NUnit.Framework;
+
+namespace Lucene.Net.Search.Spans
+{
+ /*
+ * 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.
+ */
+
+ using Lucene.Net.Search;
+
+ /// <summary>
+ /// TestExplanations subclass focusing on span queries
+ /// </summary>
+ [TestFixture]
+ public class TestSpanExplanations : TestExplanations
+ {
+ /* simple SpanTermQueries */
+
+ [Test]
+ public virtual void TestST1()
+ {
+ SpanQuery q = St("w1");
+ Qtest(q, new int[] { 0, 1, 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestST2()
+ {
+ SpanQuery q = St("w1");
+ q.Boost = 1000;
+ Qtest(q, new int[] { 0, 1, 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestST4()
+ {
+ SpanQuery q = St("xx");
+ Qtest(q, new int[] { 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestST5()
+ {
+ SpanQuery q = St("xx");
+ q.Boost = 1000;
+ Qtest(q, new int[] { 2, 3 });
+ }
+
+ /* some SpanFirstQueries */
+
+ [Test]
+ public virtual void TestSF1()
+ {
+ SpanQuery q = Sf(("w1"), 1);
+ Qtest(q, new int[] { 0, 1, 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestSF2()
+ {
+ SpanQuery q = Sf(("w1"), 1);
+ q.Boost = 1000;
+ Qtest(q, new int[] { 0, 1, 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestSF4()
+ {
+ SpanQuery q = Sf(("xx"), 2);
+ Qtest(q, new int[] { 2 });
+ }
+
+ [Test]
+ public virtual void TestSF5()
+ {
+ SpanQuery q = Sf(("yy"), 2);
+ Qtest(q, new int[] { });
+ }
+
+ [Test]
+ public virtual void TestSF6()
+ {
+ SpanQuery q = Sf(("yy"), 4);
+ q.Boost = 1000;
+ Qtest(q, new int[] { 2 });
+ }
+
+ /* some SpanOrQueries */
+
+ [Test]
+ public virtual void TestSO1()
+ {
+ SpanQuery q = Sor("w1", "QQ");
+ Qtest(q, new int[] { 0, 1, 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestSO2()
+ {
+ SpanQuery q = Sor("w1", "w3", "zz");
+ Qtest(q, new int[] { 0, 1, 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestSO3()
+ {
+ SpanQuery q = Sor("w5", "QQ", "yy");
+ Qtest(q, new int[] { 0, 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestSO4()
+ {
+ SpanQuery q = Sor("w5", "QQ", "yy");
+ Qtest(q, new int[] { 0, 2, 3 });
+ }
+
+ /* some SpanNearQueries */
+
+ [Test]
+ public virtual void TestSNear1()
+ {
+ SpanQuery q = Snear("w1", "QQ", 100, true);
+ Qtest(q, new int[] { });
+ }
+
+ [Test]
+ public virtual void TestSNear2()
+ {
+ SpanQuery q = Snear("w1", "xx", 100, true);
+ Qtest(q, new int[] { 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestSNear3()
+ {
+ SpanQuery q = Snear("w1", "xx", 0, true);
+ Qtest(q, new int[] { 2 });
+ }
+
+ [Test]
+ public virtual void TestSNear4()
+ {
+ SpanQuery q = Snear("w1", "xx", 1, true);
+ Qtest(q, new int[] { 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestSNear5()
+ {
+ SpanQuery q = Snear("xx", "w1", 0, false);
+ Qtest(q, new int[] { 2 });
+ }
+
+ [Test]
+ public virtual void TestSNear6()
+ {
+ SpanQuery q = Snear("w1", "w2", "QQ", 100, true);
+ Qtest(q, new int[] { });
+ }
+
+ [Test]
+ public virtual void TestSNear7()
+ {
+ SpanQuery q = Snear("w1", "xx", "w2", 100, true);
+ Qtest(q, new int[] { 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestSNear8()
+ {
+ SpanQuery q = Snear("w1", "xx", "w2", 0, true);
+ Qtest(q, new int[] { 2 });
+ }
+
+ [Test]
+ public virtual void TestSNear9()
+ {
+ SpanQuery q = Snear("w1", "xx", "w2", 1, true);
+ Qtest(q, new int[] { 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestSNear10()
+ {
+ SpanQuery q = Snear("xx", "w1", "w2", 0, false);
+ Qtest(q, new int[] { 2 });
+ }
+
+ [Test]
+ public virtual void TestSNear11()
+ {
+ SpanQuery q = Snear("w1", "w2", "w3", 1, true);
+ Qtest(q, new int[] { 0, 1 });
+ }
+
+ /* some SpanNotQueries */
+
+ [Test]
+ public virtual void TestSNot1()
+ {
+ SpanQuery q = Snot(Sf("w1", 10), St("QQ"));
+ Qtest(q, new int[] { 0, 1, 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestSNot2()
+ {
+ SpanQuery q = Snot(Sf("w1", 10), St("QQ"));
+ q.Boost = 1000;
+ Qtest(q, new int[] { 0, 1, 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestSNot4()
+ {
+ SpanQuery q = Snot(Sf("w1", 10), St("xx"));
+ Qtest(q, new int[] { 0, 1, 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestSNot5()
+ {
+ SpanQuery q = Snot(Sf("w1", 10), St("xx"));
+ q.Boost = 1000;
+ Qtest(q, new int[] { 0, 1, 2, 3 });
+ }
+
+ [Test]
+ public virtual void TestSNot7()
+ {
+ SpanQuery f = Snear("w1", "w3", 10, true);
+ f.Boost = 1000;
+ SpanQuery q = Snot(f, St("xx"));
+ Qtest(q, new int[] { 0, 1, 3 });
+ }
+
+ [Test]
+ public virtual void TestSNot10()
+ {
+ SpanQuery t = St("xx");
+ t.Boost = 10000;
+ SpanQuery q = Snot(Snear("w1", "w3", 10, true), t);
+ Qtest(q, new int[] { 0, 1, 3 });
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/Spans/TestSpanExplanationsOfNonMatches.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Search/Spans/TestSpanExplanationsOfNonMatches.cs b/src/Lucene.Net.Tests/Search/Spans/TestSpanExplanationsOfNonMatches.cs
new file mode 100644
index 0000000..307c51f
--- /dev/null
+++ b/src/Lucene.Net.Tests/Search/Spans/TestSpanExplanationsOfNonMatches.cs
@@ -0,0 +1,251 @@
+using NUnit.Framework;
+
+namespace Lucene.Net.Search.Spans
+{
+ /*
+ * 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.
+ */
+
+ /// <summary>
+ /// subclass of TestSimpleExplanations that verifies non matches.
+ /// </summary>
+ [TestFixture]
+ public class TestSpanExplanationsOfNonMatches : TestSpanExplanations
+ {
+ /// <summary>
+ /// Overrides superclass to ignore matches and focus on non-matches
+ /// </summary>
+ /// <seealso> cref= CheckHits#checkNoMatchExplanations </seealso>
+ public override void Qtest(Query q, int[] expDocNrs)
+ {
+ CheckHits.CheckNoMatchExplanations(q, FIELD, Searcher, expDocNrs);
+ }
+
+
+ #region TestSpanExplanations
+ // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+ // context in Visual Studio. This fixes that with the minimum amount of code necessary
+ // to run them in the correct context without duplicating all of the tests.
+
+ [Test]
+ public override void TestST1()
+ {
+ base.TestST1();
+ }
+
+ [Test]
+ public override void TestST2()
+ {
+ base.TestST2();
+ }
+
+ [Test]
+ public override void TestST4()
+ {
+ base.TestST4();
+ }
+
+ [Test]
+ public override void TestST5()
+ {
+ base.TestST5();
+ }
+
+ /* some SpanFirstQueries */
+
+ [Test]
+ public override void TestSF1()
+ {
+ base.TestSF1();
+ }
+
+ [Test]
+ public override void TestSF2()
+ {
+ base.TestSF2();
+ }
+
+ [Test]
+ public override void TestSF4()
+ {
+ base.TestSF4();
+ }
+
+ [Test]
+ public override void TestSF5()
+ {
+ base.TestSF5();
+ }
+
+ [Test]
+ public override void TestSF6()
+ {
+ base.TestSF6();
+ }
+
+ /* some SpanOrQueries */
+
+ [Test]
+ public override void TestSO1()
+ {
+ base.TestSO1();
+ }
+
+ [Test]
+ public override void TestSO2()
+ {
+ base.TestSO2();
+ }
+
+ [Test]
+ public override void TestSO3()
+ {
+ base.TestSO3();
+ }
+
+ [Test]
+ public override void TestSO4()
+ {
+ base.TestSO4();
+ }
+
+ /* some SpanNearQueries */
+
+ [Test]
+ public override void TestSNear1()
+ {
+ base.TestSNear1();
+ }
+
+ [Test]
+ public override void TestSNear2()
+ {
+ base.TestSNear2();
+ }
+
+ [Test]
+ public override void TestSNear3()
+ {
+ base.TestSNear3();
+ }
+
+ [Test]
+ public override void TestSNear4()
+ {
+ base.TestSNear4();
+ }
+
+ [Test]
+ public override void TestSNear5()
+ {
+ base.TestSNear5();
+ }
+
+ [Test]
+ public override void TestSNear6()
+ {
+ base.TestSNear6();
+ }
+
+ [Test]
+ public override void TestSNear7()
+ {
+ base.TestSNear7();
+ }
+
+ [Test]
+ public override void TestSNear8()
+ {
+ base.TestSNear8();
+ }
+
+ [Test]
+ public override void TestSNear9()
+ {
+ base.TestSNear9();
+ }
+
+ [Test]
+ public override void TestSNear10()
+ {
+ base.TestSNear10();
+ }
+
+ [Test]
+ public override void TestSNear11()
+ {
+ base.TestSNear11();
+ }
+
+ /* some SpanNotQueries */
+
+ [Test]
+ public override void TestSNot1()
+ {
+ base.TestSNot1();
+ }
+
+ [Test]
+ public override void TestSNot2()
+ {
+ base.TestSNot2();
+ }
+
+ [Test]
+ public override void TestSNot4()
+ {
+ base.TestSNot4();
+ }
+
+ [Test]
+ public override void TestSNot5()
+ {
+ base.TestSNot5();
+ }
+
+ [Test]
+ public override void TestSNot7()
+ {
+ base.TestSNot7();
+ }
+
+ [Test]
+ public override void TestSNot10()
+ {
+ base.TestSNot10();
+ }
+
+ #endregion
+
+ #region TestExplanations
+ // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+ // context in Visual Studio. This fixes that with the minimum amount of code necessary
+ // to run them in the correct context without duplicating all of the tests.
+
+
+ /// <summary>
+ /// Placeholder: JUnit freaks if you don't have one test ... making
+ /// class abstract doesn't help
+ /// </summary>
+ [Test]
+ public override void TestNoop()
+ {
+ base.TestNoop();
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/Spans/TestSpanFirstQuery.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Search/Spans/TestSpanFirstQuery.cs b/src/Lucene.Net.Tests/Search/Spans/TestSpanFirstQuery.cs
new file mode 100644
index 0000000..2266bf7
--- /dev/null
+++ b/src/Lucene.Net.Tests/Search/Spans/TestSpanFirstQuery.cs
@@ -0,0 +1,74 @@
+using Lucene.Net.Documents;
+
+namespace Lucene.Net.Search.Spans
+{
+ using NUnit.Framework;
+
+ /*
+ * 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.
+ */
+
+ using Analyzer = Lucene.Net.Analysis.Analyzer;
+ using CharacterRunAutomaton = Lucene.Net.Util.Automaton.CharacterRunAutomaton;
+ using Directory = Lucene.Net.Store.Directory;
+ using Document = Documents.Document;
+ using Field = Field;
+ using IndexReader = Lucene.Net.Index.IndexReader;
+ using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
+ using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+ using MockTokenizer = Lucene.Net.Analysis.MockTokenizer;
+ using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+ using RegExp = Lucene.Net.Util.Automaton.RegExp;
+ using Term = Lucene.Net.Index.Term;
+
+ [TestFixture]
+ public class TestSpanFirstQuery : LuceneTestCase
+ {
+ [Test]
+ public virtual void TestStartPositions()
+ {
+ Directory dir = NewDirectory();
+
+ // mimic StopAnalyzer
+ CharacterRunAutomaton stopSet = new CharacterRunAutomaton((new RegExp("the|a|of")).ToAutomaton());
+ Analyzer analyzer = new MockAnalyzer(Random(), MockTokenizer.SIMPLE, true, stopSet);
+
+ RandomIndexWriter writer = new RandomIndexWriter(Random(), dir, analyzer, Similarity, TimeZone);
+ Document doc = new Document();
+ doc.Add(NewTextField("field", "the quick brown fox", Field.Store.NO));
+ writer.AddDocument(doc);
+ Document doc2 = new Document();
+ doc2.Add(NewTextField("field", "quick brown fox", Field.Store.NO));
+ writer.AddDocument(doc2);
+
+ IndexReader reader = writer.Reader;
+ IndexSearcher searcher = NewSearcher(reader);
+
+ // user queries on "starts-with quick"
+ SpanQuery sfq = new SpanFirstQuery(new SpanTermQuery(new Term("field", "quick")), 1);
+ Assert.AreEqual(1, searcher.Search(sfq, 10).TotalHits);
+
+ // user queries on "starts-with the quick"
+ SpanQuery include = new SpanFirstQuery(new SpanTermQuery(new Term("field", "quick")), 2);
+ sfq = new SpanNotQuery(include, sfq);
+ Assert.AreEqual(1, searcher.Search(sfq, 10).TotalHits);
+
+ writer.Dispose();
+ reader.Dispose();
+ dir.Dispose();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/Spans/TestSpanMultiTermQueryWrapper.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Search/Spans/TestSpanMultiTermQueryWrapper.cs b/src/Lucene.Net.Tests/Search/Spans/TestSpanMultiTermQueryWrapper.cs
new file mode 100644
index 0000000..4d27ecc
--- /dev/null
+++ b/src/Lucene.Net.Tests/Search/Spans/TestSpanMultiTermQueryWrapper.cs
@@ -0,0 +1,245 @@
+using Lucene.Net.Documents;
+
+namespace Lucene.Net.Search.Spans
+{
+ using NUnit.Framework;
+ using Directory = Lucene.Net.Store.Directory;
+
+ /*
+ * 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.
+ */
+
+ using Document = Documents.Document;
+ using Field = Field;
+ using IndexReader = Lucene.Net.Index.IndexReader;
+ using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
+ using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+ using Term = Lucene.Net.Index.Term;
+
+ /// <summary>
+ /// Tests for <seealso cref="SpanMultiTermQueryWrapper"/>, wrapping a few MultiTermQueries.
+ /// </summary>
+ [TestFixture]
+ public class TestSpanMultiTermQueryWrapper : LuceneTestCase
+ {
+ private Directory Directory;
+ private IndexReader Reader;
+ private IndexSearcher Searcher;
+
+ [SetUp]
+ public override void SetUp()
+ {
+ base.SetUp();
+ Directory = NewDirectory();
+ RandomIndexWriter iw = new RandomIndexWriter(Random(), Directory, Similarity, TimeZone);
+ Document doc = new Document();
+ Field field = NewTextField("field", "", Field.Store.NO);
+ doc.Add(field);
+
+ field.SetStringValue("quick brown fox");
+ iw.AddDocument(doc);
+ field.SetStringValue("jumps over lazy broun dog");
+ iw.AddDocument(doc);
+ field.SetStringValue("jumps over extremely very lazy broxn dog");
+ iw.AddDocument(doc);
+ Reader = iw.Reader;
+ iw.Dispose();
+ Searcher = NewSearcher(Reader);
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ Reader.Dispose();
+ Directory.Dispose();
+ base.TearDown();
+ }
+
+ [Test]
+ public virtual void TestWildcard()
+ {
+ WildcardQuery wq = new WildcardQuery(new Term("field", "bro?n"));
+ SpanQuery swq = new SpanMultiTermQueryWrapper<MultiTermQuery>(wq);
+ // will only match quick brown fox
+ SpanFirstQuery sfq = new SpanFirstQuery(swq, 2);
+ Assert.AreEqual(1, Searcher.Search(sfq, 10).TotalHits);
+ }
+
+ [Test]
+ public virtual void TestPrefix()
+ {
+ WildcardQuery wq = new WildcardQuery(new Term("field", "extrem*"));
+ SpanQuery swq = new SpanMultiTermQueryWrapper<MultiTermQuery>(wq);
+ // will only match "jumps over extremely very lazy broxn dog"
+ SpanFirstQuery sfq = new SpanFirstQuery(swq, 3);
+ Assert.AreEqual(1, Searcher.Search(sfq, 10).TotalHits);
+ }
+
+ [Test]
+ public virtual void TestFuzzy()
+ {
+ FuzzyQuery fq = new FuzzyQuery(new Term("field", "broan"));
+ SpanQuery sfq = new SpanMultiTermQueryWrapper<MultiTermQuery>(fq);
+ // will not match quick brown fox
+ SpanPositionRangeQuery sprq = new SpanPositionRangeQuery(sfq, 3, 6);
+ Assert.AreEqual(2, Searcher.Search(sprq, 10).TotalHits);
+ }
+
+ [Test]
+ public virtual void TestFuzzy2()
+ {
+ // maximum of 1 term expansion
+ FuzzyQuery fq = new FuzzyQuery(new Term("field", "broan"), 1, 0, 1, false);
+ SpanQuery sfq = new SpanMultiTermQueryWrapper<MultiTermQuery>(fq);
+ // will only match jumps over lazy broun dog
+ SpanPositionRangeQuery sprq = new SpanPositionRangeQuery(sfq, 0, 100);
+ Assert.AreEqual(1, Searcher.Search(sprq, 10).TotalHits);
+ }
+
+ [Test]
+ public virtual void TestNoSuchMultiTermsInNear()
+ {
+ //test to make sure non existent multiterms aren't throwing null pointer exceptions
+ FuzzyQuery fuzzyNoSuch = new FuzzyQuery(new Term("field", "noSuch"), 1, 0, 1, false);
+ SpanQuery spanNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(fuzzyNoSuch);
+ SpanQuery term = new SpanTermQuery(new Term("field", "brown"));
+ SpanQuery near = new SpanNearQuery(new SpanQuery[] { term, spanNoSuch }, 1, true);
+ Assert.AreEqual(0, Searcher.Search(near, 10).TotalHits);
+ //flip order
+ near = new SpanNearQuery(new SpanQuery[] { spanNoSuch, term }, 1, true);
+ Assert.AreEqual(0, Searcher.Search(near, 10).TotalHits);
+
+ WildcardQuery wcNoSuch = new WildcardQuery(new Term("field", "noSuch*"));
+ SpanQuery spanWCNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(wcNoSuch);
+ near = new SpanNearQuery(new SpanQuery[] { term, spanWCNoSuch }, 1, true);
+ Assert.AreEqual(0, Searcher.Search(near, 10).TotalHits);
+
+ RegexpQuery rgxNoSuch = new RegexpQuery(new Term("field", "noSuch"));
+ SpanQuery spanRgxNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(rgxNoSuch);
+ near = new SpanNearQuery(new SpanQuery[] { term, spanRgxNoSuch }, 1, true);
+ Assert.AreEqual(0, Searcher.Search(near, 10).TotalHits);
+
+ PrefixQuery prfxNoSuch = new PrefixQuery(new Term("field", "noSuch"));
+ SpanQuery spanPrfxNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(prfxNoSuch);
+ near = new SpanNearQuery(new SpanQuery[] { term, spanPrfxNoSuch }, 1, true);
+ Assert.AreEqual(0, Searcher.Search(near, 10).TotalHits);
+
+ //test single noSuch
+ near = new SpanNearQuery(new SpanQuery[] { spanPrfxNoSuch }, 1, true);
+ Assert.AreEqual(0, Searcher.Search(near, 10).TotalHits);
+
+ //test double noSuch
+ near = new SpanNearQuery(new SpanQuery[] { spanPrfxNoSuch, spanPrfxNoSuch }, 1, true);
+ Assert.AreEqual(0, Searcher.Search(near, 10).TotalHits);
+ }
+
+ [Test]
+ public virtual void TestNoSuchMultiTermsInNotNear()
+ {
+ //test to make sure non existent multiterms aren't throwing non-matching field exceptions
+ FuzzyQuery fuzzyNoSuch = new FuzzyQuery(new Term("field", "noSuch"), 1, 0, 1, false);
+ SpanQuery spanNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(fuzzyNoSuch);
+ SpanQuery term = new SpanTermQuery(new Term("field", "brown"));
+ SpanNotQuery notNear = new SpanNotQuery(term, spanNoSuch, 0, 0);
+ Assert.AreEqual(1, Searcher.Search(notNear, 10).TotalHits);
+
+ //flip
+ notNear = new SpanNotQuery(spanNoSuch, term, 0, 0);
+ Assert.AreEqual(0, Searcher.Search(notNear, 10).TotalHits);
+
+ //both noSuch
+ notNear = new SpanNotQuery(spanNoSuch, spanNoSuch, 0, 0);
+ Assert.AreEqual(0, Searcher.Search(notNear, 10).TotalHits);
+
+ WildcardQuery wcNoSuch = new WildcardQuery(new Term("field", "noSuch*"));
+ SpanQuery spanWCNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(wcNoSuch);
+ notNear = new SpanNotQuery(term, spanWCNoSuch, 0, 0);
+ Assert.AreEqual(1, Searcher.Search(notNear, 10).TotalHits);
+
+ RegexpQuery rgxNoSuch = new RegexpQuery(new Term("field", "noSuch"));
+ SpanQuery spanRgxNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(rgxNoSuch);
+ notNear = new SpanNotQuery(term, spanRgxNoSuch, 1, 1);
+ Assert.AreEqual(1, Searcher.Search(notNear, 10).TotalHits);
+
+ PrefixQuery prfxNoSuch = new PrefixQuery(new Term("field", "noSuch"));
+ SpanQuery spanPrfxNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(prfxNoSuch);
+ notNear = new SpanNotQuery(term, spanPrfxNoSuch, 1, 1);
+ Assert.AreEqual(1, Searcher.Search(notNear, 10).TotalHits);
+ }
+
+ [Test]
+ public virtual void TestNoSuchMultiTermsInOr()
+ {
+ //test to make sure non existent multiterms aren't throwing null pointer exceptions
+ FuzzyQuery fuzzyNoSuch = new FuzzyQuery(new Term("field", "noSuch"), 1, 0, 1, false);
+ SpanQuery spanNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(fuzzyNoSuch);
+ SpanQuery term = new SpanTermQuery(new Term("field", "brown"));
+ SpanOrQuery near = new SpanOrQuery(new SpanQuery[] { term, spanNoSuch });
+ Assert.AreEqual(1, Searcher.Search(near, 10).TotalHits);
+
+ //flip
+ near = new SpanOrQuery(new SpanQuery[] { spanNoSuch, term });
+ Assert.AreEqual(1, Searcher.Search(near, 10).TotalHits);
+
+ WildcardQuery wcNoSuch = new WildcardQuery(new Term("field", "noSuch*"));
+ SpanQuery spanWCNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(wcNoSuch);
+ near = new SpanOrQuery(new SpanQuery[] { term, spanWCNoSuch });
+ Assert.AreEqual(1, Searcher.Search(near, 10).TotalHits);
+
+ RegexpQuery rgxNoSuch = new RegexpQuery(new Term("field", "noSuch"));
+ SpanQuery spanRgxNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(rgxNoSuch);
+ near = new SpanOrQuery(new SpanQuery[] { term, spanRgxNoSuch });
+ Assert.AreEqual(1, Searcher.Search(near, 10).TotalHits);
+
+ PrefixQuery prfxNoSuch = new PrefixQuery(new Term("field", "noSuch"));
+ SpanQuery spanPrfxNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(prfxNoSuch);
+ near = new SpanOrQuery(new SpanQuery[] { term, spanPrfxNoSuch });
+ Assert.AreEqual(1, Searcher.Search(near, 10).TotalHits);
+
+ near = new SpanOrQuery(new SpanQuery[] { spanPrfxNoSuch });
+ Assert.AreEqual(0, Searcher.Search(near, 10).TotalHits);
+
+ near = new SpanOrQuery(new SpanQuery[] { spanPrfxNoSuch, spanPrfxNoSuch });
+ Assert.AreEqual(0, Searcher.Search(near, 10).TotalHits);
+ }
+
+ [Test]
+ public virtual void TestNoSuchMultiTermsInSpanFirst()
+ {
+ //this hasn't been a problem
+ FuzzyQuery fuzzyNoSuch = new FuzzyQuery(new Term("field", "noSuch"), 1, 0, 1, false);
+ SpanQuery spanNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(fuzzyNoSuch);
+ SpanQuery spanFirst = new SpanFirstQuery(spanNoSuch, 10);
+
+ Assert.AreEqual(0, Searcher.Search(spanFirst, 10).TotalHits);
+
+ WildcardQuery wcNoSuch = new WildcardQuery(new Term("field", "noSuch*"));
+ SpanQuery spanWCNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(wcNoSuch);
+ spanFirst = new SpanFirstQuery(spanWCNoSuch, 10);
+ Assert.AreEqual(0, Searcher.Search(spanFirst, 10).TotalHits);
+
+ RegexpQuery rgxNoSuch = new RegexpQuery(new Term("field", "noSuch"));
+ SpanQuery spanRgxNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(rgxNoSuch);
+ spanFirst = new SpanFirstQuery(spanRgxNoSuch, 10);
+ Assert.AreEqual(0, Searcher.Search(spanFirst, 10).TotalHits);
+
+ PrefixQuery prfxNoSuch = new PrefixQuery(new Term("field", "noSuch"));
+ SpanQuery spanPrfxNoSuch = new SpanMultiTermQueryWrapper<MultiTermQuery>(prfxNoSuch);
+ spanFirst = new SpanFirstQuery(spanPrfxNoSuch, 10);
+ Assert.AreEqual(0, Searcher.Search(spanFirst, 10).TotalHits);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/Spans/TestSpanSearchEquivalence.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Search/Spans/TestSpanSearchEquivalence.cs b/src/Lucene.Net.Tests/Search/Spans/TestSpanSearchEquivalence.cs
new file mode 100644
index 0000000..569a03e
--- /dev/null
+++ b/src/Lucene.Net.Tests/Search/Spans/TestSpanSearchEquivalence.cs
@@ -0,0 +1,134 @@
+using NUnit.Framework;
+
+namespace Lucene.Net.Search.Spans
+{
+ using Occur = Lucene.Net.Search.Occur;
+
+ /*
+ * 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.
+ */
+
+ using Term = Lucene.Net.Index.Term;
+
+ /// <summary>
+ /// Basic equivalence tests for span queries
+ /// </summary>
+ [TestFixture]
+ public class TestSpanSearchEquivalence : SearchEquivalenceTestBase
+ {
+ // TODO: we could go a little crazy for a lot of these,
+ // but these are just simple minimal cases in case something
+ // goes horribly wrong. Put more intense tests elsewhere.
+
+ /// <summary>
+ /// SpanTermQuery(A) = TermQuery(A) </summary>
+ [Test]
+ public virtual void TestSpanTermVersusTerm()
+ {
+ Term t1 = RandomTerm();
+ AssertSameSet(new TermQuery(t1), new SpanTermQuery(t1));
+ }
+
+ /// <summary>
+ /// SpanOrQuery(A, B) = (A B) </summary>
+ [Test]
+ public virtual void TestSpanOrVersusBoolean()
+ {
+ Term t1 = RandomTerm();
+ Term t2 = RandomTerm();
+ BooleanQuery q1 = new BooleanQuery();
+ q1.Add(new TermQuery(t1), Occur.SHOULD);
+ q1.Add(new TermQuery(t2), Occur.SHOULD);
+ SpanOrQuery q2 = new SpanOrQuery(new SpanTermQuery(t1), new SpanTermQuery(t2));
+ AssertSameSet(q1, q2);
+ }
+
+ /// <summary>
+ /// SpanNotQuery(A, B) \u2286 SpanTermQuery(A) </summary>
+ [Test]
+ public virtual void TestSpanNotVersusSpanTerm()
+ {
+ Term t1 = RandomTerm();
+ Term t2 = RandomTerm();
+ AssertSubsetOf(new SpanNotQuery(new SpanTermQuery(t1), new SpanTermQuery(t2)), new SpanTermQuery(t1));
+ }
+
+ /// <summary>
+ /// SpanFirstQuery(A, 10) \u2286 SpanTermQuery(A) </summary>
+ [Test]
+ public virtual void TestSpanFirstVersusSpanTerm()
+ {
+ Term t1 = RandomTerm();
+ AssertSubsetOf(new SpanFirstQuery(new SpanTermQuery(t1), 10), new SpanTermQuery(t1));
+ }
+
+ /// <summary>
+ /// SpanNearQuery([A, B], 0, true) = "A B" </summary>
+ [Test]
+ public virtual void TestSpanNearVersusPhrase()
+ {
+ Term t1 = RandomTerm();
+ Term t2 = RandomTerm();
+ SpanQuery[] subquery = new SpanQuery[] { new SpanTermQuery(t1), new SpanTermQuery(t2) };
+ SpanNearQuery q1 = new SpanNearQuery(subquery, 0, true);
+ PhraseQuery q2 = new PhraseQuery();
+ q2.Add(t1);
+ q2.Add(t2);
+ AssertSameSet(q1, q2);
+ }
+
+ /// <summary>
+ /// SpanNearQuery([A, B], \u221e, false) = +A +B </summary>
+ [Test]
+ public virtual void TestSpanNearVersusBooleanAnd()
+ {
+ Term t1 = RandomTerm();
+ Term t2 = RandomTerm();
+ SpanQuery[] subquery = new SpanQuery[] { new SpanTermQuery(t1), new SpanTermQuery(t2) };
+ SpanNearQuery q1 = new SpanNearQuery(subquery, int.MaxValue, false);
+ BooleanQuery q2 = new BooleanQuery();
+ q2.Add(new TermQuery(t1), Occur.MUST);
+ q2.Add(new TermQuery(t2), Occur.MUST);
+ AssertSameSet(q1, q2);
+ }
+
+ /// <summary>
+ /// SpanNearQuery([A B], 0, false) \u2286 SpanNearQuery([A B], 1, false) </summary>
+ [Test]
+ public virtual void TestSpanNearVersusSloppySpanNear()
+ {
+ Term t1 = RandomTerm();
+ Term t2 = RandomTerm();
+ SpanQuery[] subquery = new SpanQuery[] { new SpanTermQuery(t1), new SpanTermQuery(t2) };
+ SpanNearQuery q1 = new SpanNearQuery(subquery, 0, false);
+ SpanNearQuery q2 = new SpanNearQuery(subquery, 1, false);
+ AssertSubsetOf(q1, q2);
+ }
+
+ /// <summary>
+ /// SpanNearQuery([A B], 3, true) \u2286 SpanNearQuery([A B], 3, false) </summary>
+ [Test]
+ public virtual void TestSpanNearInOrderVersusOutOfOrder()
+ {
+ Term t1 = RandomTerm();
+ Term t2 = RandomTerm();
+ SpanQuery[] subquery = new SpanQuery[] { new SpanTermQuery(t1), new SpanTermQuery(t2) };
+ SpanNearQuery q1 = new SpanNearQuery(subquery, 3, true);
+ SpanNearQuery q2 = new SpanNearQuery(subquery, 3, false);
+ AssertSubsetOf(q1, q2);
+ }
+ }
+}
\ No newline at end of file