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) â 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) â 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], â, 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) â 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) â 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
