blob: 7dfe8f1d041f638db59431ffb6e09c4076e10b17 [file] [log] [blame]
using NUnit.Framework;
using Assert = Lucene.Net.TestFramework.Assert;
namespace Lucene.Net.Search
{
/*
* 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 AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
using Directory = Lucene.Net.Store.Directory;
using Document = Documents.Document;
using IndexReader = Lucene.Net.Index.IndexReader;
using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
[TestFixture]
public class TestTopDocsCollector : LuceneTestCase
{
private sealed class MyTopsDocCollector : TopDocsCollector<ScoreDoc>
{
private int idx = 0;
private int @base = 0;
public MyTopsDocCollector(int size)
: base(new HitQueue(size, false))
{
}
protected override TopDocs NewTopDocs(ScoreDoc[] results, int start)
{
if (results == null)
{
return EMPTY_TOPDOCS;
}
float maxScore = float.NaN;
if (start == 0)
{
maxScore = results[0].Score;
}
else
{
for (int i = m_pq.Count; i > 1; i--)
{
m_pq.Pop();
}
maxScore = m_pq.Pop().Score;
}
return new TopDocs(TotalHits, results, maxScore);
}
public override void Collect(int doc)
{
++TotalHits;
m_pq.InsertWithOverflow(new ScoreDoc(doc + @base, scores[idx++]));
}
public override void SetNextReader(AtomicReaderContext context)
{
@base = context.DocBase;
}
public override void SetScorer(Scorer scorer)
{
// Don't do anything. Assign scores in random
}
public override bool AcceptsDocsOutOfOrder => true;
}
// Scores array to be used by MyTopDocsCollector. If it is changed, MAX_SCORE
// must also change.
private static readonly float[] scores = new float[] { 0.7767749f, 1.7839992f, 8.9925785f, 7.9608946f, 0.07948637f, 2.6356435f, 7.4950366f, 7.1490803f, 8.108544f, 4.961808f, 2.2423935f, 7.285586f, 4.6699767f, 2.9655676f, 6.953706f, 5.383931f, 6.9916306f, 8.365894f, 7.888485f, 8.723962f, 3.1796896f, 0.39971232f, 1.3077754f, 6.8489285f, 9.17561f, 5.060466f, 7.9793315f, 8.601509f, 4.1858315f, 0.28146625f };
private const float MAX_SCORE = 9.17561f;
private Directory dir;
private IndexReader reader;
private TopDocsCollector<ScoreDoc> DoSearch(int numResults)
{
Query q = new MatchAllDocsQuery();
IndexSearcher searcher = NewSearcher(reader);
TopDocsCollector<ScoreDoc> tdc = new MyTopsDocCollector(numResults);
searcher.Search(q, tdc);
return tdc;
}
[SetUp]
public override void SetUp()
{
base.SetUp();
// populate an index with 30 documents, this should be enough for the test.
// The documents have no content - the test uses MatchAllDocsQuery().
dir = NewDirectory();
RandomIndexWriter writer = new RandomIndexWriter(
#if FEATURE_INSTANCE_TESTDATA_INITIALIZATION
this,
#endif
Random, dir);
for (int i = 0; i < 30; i++)
{
writer.AddDocument(new Document());
}
reader = writer.GetReader();
writer.Dispose();
}
[TearDown]
public override void TearDown()
{
reader.Dispose();
dir.Dispose();
dir = null;
base.TearDown();
}
[Test]
public virtual void TestInvalidArguments()
{
int numResults = 5;
TopDocsCollector<ScoreDoc> tdc = DoSearch(numResults);
// start < 0
Assert.AreEqual(0, tdc.GetTopDocs(-1).ScoreDocs.Length);
// start > pq.Size()
Assert.AreEqual(0, tdc.GetTopDocs(numResults + 1).ScoreDocs.Length);
// start == pq.Size()
Assert.AreEqual(0, tdc.GetTopDocs(numResults).ScoreDocs.Length);
// howMany < 0
Assert.AreEqual(0, tdc.GetTopDocs(0, -1).ScoreDocs.Length);
// howMany == 0
Assert.AreEqual(0, tdc.GetTopDocs(0, 0).ScoreDocs.Length);
}
[Test]
public virtual void TestZeroResults()
{
TopDocsCollector<ScoreDoc> tdc = new MyTopsDocCollector(5);
Assert.AreEqual(0, tdc.GetTopDocs(0, 1).ScoreDocs.Length);
}
[Test]
public virtual void TestFirstResultsPage()
{
TopDocsCollector<ScoreDoc> tdc = DoSearch(15);
Assert.AreEqual(10, tdc.GetTopDocs(0, 10).ScoreDocs.Length);
}
[Test]
public virtual void TestSecondResultsPages()
{
TopDocsCollector<ScoreDoc> tdc = DoSearch(15);
// ask for more results than are available
Assert.AreEqual(5, tdc.GetTopDocs(10, 10).ScoreDocs.Length);
// ask for 5 results (exactly what there should be
tdc = DoSearch(15);
Assert.AreEqual(5, tdc.GetTopDocs(10, 5).ScoreDocs.Length);
// ask for less results than there are
tdc = DoSearch(15);
Assert.AreEqual(4, tdc.GetTopDocs(10, 4).ScoreDocs.Length);
}
[Test]
public virtual void TestGetAllResults()
{
TopDocsCollector<ScoreDoc> tdc = DoSearch(15);
Assert.AreEqual(15, tdc.GetTopDocs().ScoreDocs.Length);
}
[Test]
public virtual void TestGetResultsFromStart()
{
TopDocsCollector<ScoreDoc> tdc = DoSearch(15);
// should bring all results
Assert.AreEqual(15, tdc.GetTopDocs(0).ScoreDocs.Length);
tdc = DoSearch(15);
// get the last 5 only.
Assert.AreEqual(5, tdc.GetTopDocs(10).ScoreDocs.Length);
}
[Test]
public virtual void TestMaxScore()
{
// ask for all results
TopDocsCollector<ScoreDoc> tdc = DoSearch(15);
TopDocs td = tdc.GetTopDocs();
Assert.AreEqual(MAX_SCORE, td.MaxScore, 0f);
// ask for 5 last results
tdc = DoSearch(15);
td = tdc.GetTopDocs(10);
Assert.AreEqual(MAX_SCORE, td.MaxScore, 0f);
}
// this does not test the PQ's correctness, but whether topDocs()
// implementations return the results in decreasing score order.
[Test]
public virtual void TestResultsOrder()
{
TopDocsCollector<ScoreDoc> tdc = DoSearch(15);
ScoreDoc[] sd = tdc.GetTopDocs().ScoreDocs;
Assert.AreEqual(MAX_SCORE, sd[0].Score, 0f);
for (int i = 1; i < sd.Length; i++)
{
Assert.IsTrue(sd[i - 1].Score >= sd[i].Score);
}
}
}
}