/* * 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 System; using NUnit.Framework; using CorruptIndexException = Lucene.Net.Index.CorruptIndexException; using Hits = Lucene.Net.Search.Hits; using IndexSearcher = Lucene.Net.Search.IndexSearcher; using Query = Lucene.Net.Search.Query; using QueryUtils = Lucene.Net.Search.QueryUtils; using ScoreDoc = Lucene.Net.Search.ScoreDoc; using TopDocs = Lucene.Net.Search.TopDocs; namespace Lucene.Net.Search.Function { /// Test search based on OrdFieldSource and ReverseOrdFieldSource. ///

/// Tests here create an index with a few documents, each having /// an indexed "id" field. /// The ord values of this field are later used for scoring. ///

/// The order tests use Hits to verify that docs are ordered as expected. ///

/// The exact score tests use TopDocs top to verify the exact score. ///

[TestFixture] public class TestOrdValues : FunctionTestSetup { /* @override constructor */ //public TestOrdValues(System.String name):base(name) //{ //} /* @override */ [TearDown] public override void TearDown() { base.TearDown(); } /* @override */ [SetUp] public override void SetUp() { // prepare a small index with just a few documents. base.SetUp(); } /// Test OrdFieldSource [Test] public virtual void TestOrdFieldRank() { DoTestRank(ID_FIELD, true); } /// Test ReverseOrdFieldSource [Test] public virtual void TestReverseOrdFieldRank() { DoTestRank(ID_FIELD, false); } // Test that queries based on reverse/ordFieldScore scores correctly private void DoTestRank(System.String field, bool inOrder) { IndexSearcher s = new IndexSearcher(dir); ValueSource vs; if (inOrder) { vs = new OrdFieldSource(field); } else { vs = new ReverseOrdFieldSource(field); } Query q = new ValueSourceQuery(vs); Log("test: " + q); QueryUtils.Check(q, s); Hits h = s.Search(q); Assert.AreEqual(N_DOCS, h.Length(), "All docs should be matched!"); System.String prevID = inOrder?"IE":"IC"; // smaller than all ids of docs in this test ("ID0001", etc.) for (int i = 0; i < h.Length(); i++) { System.String resID = h.Doc(i).Get(ID_FIELD); Log(i + ". score=" + h.Score(i) + " - " + resID); Log(s.Explain(q, h.Id(i))); if (inOrder) { Assert.IsTrue(String.CompareOrdinal(resID, prevID) < 0, "res id " + resID + " should be < prev res id " + prevID); } else { Assert.IsTrue(String.CompareOrdinal(resID, prevID) > 0, "res id " + resID + " should be > prev res id " + prevID); } prevID = resID; } } /// Test exact score for OrdFieldSource [Test] public virtual void TestOrdFieldExactScore() { DoTestExactScore(ID_FIELD, true); } /// Test exact score for ReverseOrdFieldSource [Test] public virtual void TestReverseOrdFieldExactScore() { DoTestExactScore(ID_FIELD, false); } // Test that queries based on reverse/ordFieldScore returns docs with expected score. private void DoTestExactScore(System.String field, bool inOrder) { IndexSearcher s = new IndexSearcher(dir); ValueSource vs; if (inOrder) { vs = new OrdFieldSource(field); } else { vs = new ReverseOrdFieldSource(field); } Query q = new ValueSourceQuery(vs); TopDocs td = s.Search(q, null, 1000); Assert.AreEqual(N_DOCS, td.totalHits, "All docs should be matched!"); ScoreDoc[] sd = td.scoreDocs; for (int i = 0; i < sd.Length; i++) { float score = sd[i].score; System.String id = s.GetIndexReader().Document(sd[i].doc).Get(ID_FIELD); Log("-------- " + i + ". Explain doc " + id); Log(s.Explain(q, sd[i].doc)); float expectedScore = N_DOCS - i; Assert.AreEqual(expectedScore, score, TEST_SCORE_TOLERANCE_DELTA, "score of result " + i + " shuould be " + expectedScore + " != " + score); System.String expectedId = inOrder?Id2String(N_DOCS - i):Id2String(i + 1); // reverse ==> smaller values first Assert.IsTrue(expectedId.Equals(id), "id of result " + i + " shuould be " + expectedId + " != " + score); } } /// Test caching OrdFieldSource [Test] public virtual void TestCachingOrd() { DoTestCaching(ID_FIELD, true); } /// Test caching for ReverseOrdFieldSource [Test] public virtual void TesCachingReverseOrd() { DoTestCaching(ID_FIELD, false); } // Test that values loaded for FieldScoreQuery are cached properly and consumes the proper RAM resources. private void DoTestCaching(System.String field, bool inOrder) { IndexSearcher s = new IndexSearcher(dir); System.Object innerArray = null; bool warned = false; // print warning once for (int i = 0; i < 10; i++) { ValueSource vs; if (inOrder) { vs = new OrdFieldSource(field); } else { vs = new ReverseOrdFieldSource(field); } ValueSourceQuery q = new ValueSourceQuery(vs); Hits h = s.Search(q); try { Assert.AreEqual(N_DOCS, h.Length(), "All docs should be matched!"); if (i == 0) { innerArray = q.ValSrc_ForNUnitTest.GetValues(s.GetIndexReader()).GetInnerArray(); } else { Log(i + ". compare: " + innerArray + " to " + q.ValSrc_ForNUnitTest.GetValues(s.GetIndexReader()).GetInnerArray()); Assert.AreSame(innerArray, q.ValSrc_ForNUnitTest.GetValues(s.GetIndexReader()).GetInnerArray(), "field values should be cached and reused!"); } } catch (System.NotSupportedException) { if (!warned) { System.Console.Error.WriteLine("WARNING: " + TestName() + " cannot fully test values of " + q); warned = true; } } } ValueSource vs2; ValueSourceQuery q2; Hits h2; // verify that different values are loaded for a different field System.String field2 = INT_FIELD; Assert.IsFalse(field.Equals(field2)); // otherwise this test is meaningless. if (inOrder) { vs2 = new OrdFieldSource(field2); } else { vs2 = new ReverseOrdFieldSource(field2); } q2 = new ValueSourceQuery(vs2); h2 = s.Search(q2); Assert.AreEqual(N_DOCS, h2.Length(), "All docs should be matched!"); try { Log("compare (should differ): " + innerArray + " to " + q2.ValSrc_ForNUnitTest.GetValues(s.GetIndexReader()).GetInnerArray()); Assert.AreNotSame(innerArray, q2.ValSrc_ForNUnitTest.GetValues(s.GetIndexReader()).GetInnerArray(), "different values shuold be loaded for a different field!"); } catch (System.NotSupportedException) { if (!warned) { System.Console.Error.WriteLine("WARNING: " + TestName() + " cannot fully test values of " + q2); warned = true; } } // verify new values are reloaded (not reused) for a new reader s = new IndexSearcher(dir); if (inOrder) { vs2 = new OrdFieldSource(field); } else { vs2 = new ReverseOrdFieldSource(field); } q2 = new ValueSourceQuery(vs2); h2 = s.Search(q2); Assert.AreEqual(N_DOCS, h2.Length(), "All docs should be matched!"); try { Log("compare (should differ): " + innerArray + " to " + q2.ValSrc_ForNUnitTest.GetValues(s.GetIndexReader()).GetInnerArray()); Assert.AreNotSame(innerArray, q2.ValSrc_ForNUnitTest.GetValues(s.GetIndexReader()).GetInnerArray(), "cached field values should not be reused if reader as changed!"); } catch (System.NotSupportedException) { if (!warned) { System.Console.Error.WriteLine("WARNING: " + TestName() + " cannot fully test values of " + q2); warned = true; } } } private System.String TestName() { return GetType().FullName; } } }