blob: 903d31548cad81c0ca567b6ef32967702eb838db [file] [log] [blame]
using J2N.Collections.Generic.Extensions;
using Lucene.Net.Documents;
using Lucene.Net.Expressions.JS;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Store;
using Lucene.Net.Support;
using Lucene.Net.Util;
using NUnit.Framework;
using System.Globalization;
namespace Lucene.Net.Expressions
{
/*
* 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>
/// Tests some basic expressions against different queries,
/// and fieldcache/docvalues fields against an equivalent sort.
/// </summary>
/// <remarks>
/// Tests some basic expressions against different queries,
/// and fieldcache/docvalues fields against an equivalent sort.
/// </remarks>
[SuppressCodecs("Lucene3x")]
public class TestExpressionSorts : LuceneTestCase
{
private Directory dir;
private IndexReader reader;
private IndexSearcher searcher;
[SetUp]
public override void SetUp()
{
base.SetUp();
dir = NewDirectory();
var iw = new RandomIndexWriter(
#if FEATURE_INSTANCE_TESTDATA_INITIALIZATION
this,
#endif
Random, dir);
int numDocs = TestUtil.NextInt32(Random, 2049, 4000);
for (int i = 0; i < numDocs; i++)
{
var document = new Document
{
NewTextField("english", English.Int32ToEnglish(i), Field.Store.NO),
NewTextField("oddeven", (i % 2 == 0) ? "even" : "odd", Field.Store.NO),
NewStringField("byte", string.Empty + (unchecked((byte) Random.Next())).ToString(CultureInfo.InvariantCulture), Field.Store.NO),
NewStringField("short", string.Empty + ((short) Random.Next()).ToString(CultureInfo.InvariantCulture), Field.Store.NO),
new Int32Field("int", Random.Next(), Field.Store.NO),
new Int64Field("long", Random.NextInt64(), Field.Store.NO),
new SingleField("float", Random.NextSingle(), Field.Store.NO),
new DoubleField("double", Random.NextDouble(), Field.Store.NO),
new NumericDocValuesField("intdocvalues", Random.Next()),
new SingleDocValuesField("floatdocvalues", Random.NextSingle())
};
iw.AddDocument(document);
}
reader = iw.GetReader();
iw.Dispose();
searcher = NewSearcher(reader);
}
[TearDown]
public override void TearDown()
{
reader.Dispose();
dir.Dispose();
base.TearDown();
}
// LUCENENET TODO: Fails on x86, Release, net45 (but doesn't fail if any of these 3 parameters are changed)
[Test]
public virtual void TestQueries()
{
int n = AtLeast(4);
for (int i = 0; i < n; i++)
{
Filter odd = new QueryWrapperFilter(new TermQuery(new Term("oddeven", "odd")));
AssertQuery(new MatchAllDocsQuery(), null);
AssertQuery(new TermQuery(new Term("english", "one")), null);
AssertQuery(new MatchAllDocsQuery(), odd);
AssertQuery(new TermQuery(new Term("english", "four")), odd);
BooleanQuery bq = new BooleanQuery();
bq.Add(new TermQuery(new Term("english", "one")), Occur.SHOULD);
bq.Add(new TermQuery(new Term("oddeven", "even")), Occur.SHOULD);
AssertQuery(bq, null);
// force in order
bq.Add(new TermQuery(new Term("english", "two")), Occur.SHOULD);
bq.MinimumNumberShouldMatch = 2;
AssertQuery(bq, null);
}
}
internal virtual void AssertQuery(Query query, Filter filter)
{
for (int i = 0; i < 10; i++)
{
bool reversed = Random.NextBoolean();
SortField[] fields =
{
new SortField("int", SortFieldType.INT32, reversed),
new SortField("long", SortFieldType.INT64, reversed),
new SortField("float", SortFieldType.SINGLE, reversed),
new SortField("double", SortFieldType.DOUBLE, reversed),
new SortField("intdocvalues", SortFieldType.INT32, reversed),
new SortField("floatdocvalues", SortFieldType.SINGLE, reversed),
new SortField("score", SortFieldType.SCORE)
};
fields.Shuffle(Random);
int numSorts = TestUtil.NextInt32(Random, 1, fields.Length);
AssertQuery(query, filter, new Sort(Arrays.CopyOfRange(fields, 0, numSorts)));
}
}
internal virtual void AssertQuery(Query query, Filter filter, Sort sort)
{
int size = TestUtil.NextInt32(Random, 1, searcher.IndexReader.MaxDoc / 5);
TopDocs expected = searcher.Search(query, filter, size, sort, Random.NextBoolean(), Random.NextBoolean());
// make our actual sort, mutating original by replacing some of the
// sortfields with equivalent expressions
SortField[] original = sort.GetSort();
SortField[] mutated = new SortField[original.Length];
for (int i = 0; i < mutated.Length; i++)
{
if (Random.Next(3) > 0)
{
SortField s = original[i];
Expression expr = JavascriptCompiler.Compile(s.Field);
SimpleBindings simpleBindings = new SimpleBindings();
simpleBindings.Add(s);
bool reverse = s.Type == SortFieldType.SCORE || s.IsReverse;
mutated[i] = expr.GetSortField(simpleBindings, reverse);
}
else
{
mutated[i] = original[i];
}
}
Sort mutatedSort = new Sort(mutated);
TopDocs actual = searcher.Search(query, filter, size, mutatedSort, Random.NextBoolean(), Random.NextBoolean());
CheckHits.CheckEqual(query, expected.ScoreDocs, actual.ScoreDocs);
if (size < actual.TotalHits)
{
expected = searcher.SearchAfter(expected.ScoreDocs[size - 1], query, filter, size, sort);
actual = searcher.SearchAfter(actual.ScoreDocs[size - 1], query, filter, size, mutatedSort);
CheckHits.CheckEqual(query, expected.ScoreDocs, actual.ScoreDocs);
}
}
}
}