blob: 185120611ae2443dd8d8501002619793ba8619ac [file] [log] [blame]
using J2N.Collections.Generic.Extensions;
using Lucene.Net.Store;
using NUnit.Framework;
using RandomizedTesting.Generators;
using System;
using System.Collections.Generic;
using System.Linq;
using Console = Lucene.Net.Util.SystemConsole;
using JCG = J2N.Collections.Generic;
using Int64 = J2N.Numerics.Int64;
namespace Lucene.Net.Util.Fst
{
/*
* 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.
*/
public class TestFSTsMisc : LuceneTestCase
{
private MockDirectoryWrapper dir;
public override void SetUp()
{
base.SetUp();
dir = NewMockDirectory();
dir.PreventDoubleWrite = false;
}
public override void TearDown()
{
// can be null if we force simpletext (funky, some kind of bug in test runner maybe)
if (dir != null) dir.Dispose();
base.TearDown();
}
[Test]
public void TestRandomWords()
{
TestRandomWords(1000, LuceneTestCase.AtLeast(Random, 2));
//TestRandomWords(100, 1);
}
private void TestRandomWords(int maxNumWords, int numIter)
{
Random random = new J2N.Randomizer(Random.NextInt64());
for (int iter = 0; iter < numIter; iter++)
{
if (Verbose)
{
Console.WriteLine("\nTEST: iter " + iter);
}
for (int inputMode = 0; inputMode < 2; inputMode++)
{
int numWords = random.nextInt(maxNumWords + 1);
ISet<Int32sRef> termsSet = new JCG.HashSet<Int32sRef>();
//Int32sRef[] terms = new Int32sRef[numWords]; // LUCENENET: Not used
while (termsSet.size() < numWords)
{
string term = FSTTester<object>.GetRandomString(random);
termsSet.Add(FSTTester<object>.ToInt32sRef(term, inputMode));
}
DoTest(inputMode, termsSet.ToArray());
}
}
}
private void DoTest(int inputMode, Int32sRef[] terms)
{
Array.Sort(terms);
// Up to two positive ints, shared, generally but not
// monotonically increasing
{
if (Verbose)
{
Console.WriteLine("TEST: now test UpToTwoPositiveIntOutputs");
}
UpToTwoPositiveInt64Outputs outputs = UpToTwoPositiveInt64Outputs.GetSingleton(true);
IList<InputOutput<object>> pairs = new JCG.List<InputOutput<object>>(terms.Length);
long lastOutput = 0;
for (int idx = 0; idx < terms.Length; idx++)
{
// Sometimes go backwards
long value = lastOutput + TestUtil.NextInt32(Random, -100, 1000);
while (value < 0)
{
value = lastOutput + TestUtil.NextInt32(Random, -100, 1000);
}
object output;
if (Random.nextInt(5) == 3)
{
long value2 = lastOutput + TestUtil.NextInt32(Random, -100, 1000);
while (value2 < 0)
{
value2 = lastOutput + TestUtil.NextInt32(Random, -100, 1000);
}
IList<Int64> values = new JCG.List<Int64>();
values.Add(value);
values.Add(value2);
output = values;
}
else
{
output = outputs.Get(value);
}
pairs.Add(new InputOutput<object>(terms[idx], output));
}
new FSTTesterHelper<object>(Random, dir, inputMode, pairs, outputs, false).DoTest(false);
// ListOfOutputs(PositiveIntOutputs), generally but not
// monotonically increasing
{
if (Verbose)
{
Console.WriteLine("TEST: now test OneOrMoreOutputs");
}
PositiveInt32Outputs _outputs = PositiveInt32Outputs.Singleton;
ListOfOutputs<Int64> outputs2 = new ListOfOutputs<Int64>(_outputs);
IList<InputOutput<object>> pairs2 = new JCG.List<InputOutput<object>>(terms.Length);
long lastOutput2 = 0;
for (int idx = 0; idx < terms.Length; idx++)
{
int outputCount = TestUtil.NextInt32(Random, 1, 7);
IList<Int64> values = new JCG.List<Int64>();
for (int i = 0; i < outputCount; i++)
{
// Sometimes go backwards
long value = lastOutput2 + TestUtil.NextInt32(Random, -100, 1000);
while (value < 0)
{
value = lastOutput2 + TestUtil.NextInt32(Random, -100, 1000);
}
values.Add(value);
lastOutput2 = value;
}
object output;
if (values.Count == 1)
{
output = values[0];
}
else
{
output = values;
}
pairs2.Add(new InputOutput<object>(terms[idx], output));
}
new FSTTester<object>(Random, dir, inputMode, pairs2, outputs2, false).DoTest(false);
}
}
}
private class FSTTesterHelper<T> : FSTTester<T> where T : class // LUCENENET specific - added class constraint, since we compare reference equality
{
public FSTTesterHelper(Random random, Directory dir, int inputMode, IList<InputOutput<T>> pairs, Outputs<T> outputs, bool doReverseLookup)
: base(random, dir, inputMode, pairs, outputs, doReverseLookup)
{
}
protected override bool OutputsEqual(T output1, T output2)
{
if (output1 is UpToTwoPositiveInt64Outputs.TwoInt64s twoLongs1 && output2 is JCG.List<Int64> output2List)
{
return output2List.Equals(new Int64[] { twoLongs1.First, twoLongs1.Second });
}
else if (output2 is UpToTwoPositiveInt64Outputs.TwoInt64s twoLongs2 && output1 is JCG.List<Int64> output1List)
{
return output1List.Equals(new Int64[] { twoLongs2.First, twoLongs2.Second });
}
return output1.Equals(output2);
}
}
[Test]
public void TestListOfOutputs()
{
PositiveInt32Outputs _outputs = PositiveInt32Outputs.Singleton;
ListOfOutputs<Int64> outputs = new ListOfOutputs<Int64>(_outputs);
Builder<object> builder = new Builder<object>(FST.INPUT_TYPE.BYTE1, outputs);
Int32sRef scratch = new Int32sRef();
// Add the same input more than once and the outputs
// are merged:
builder.Add(Util.ToInt32sRef(new BytesRef("a"), scratch), (Int64)1L);
builder.Add(Util.ToInt32sRef(new BytesRef("a"), scratch), (Int64)3L);
builder.Add(Util.ToInt32sRef(new BytesRef("a"), scratch), (Int64)0L);
builder.Add(Util.ToInt32sRef(new BytesRef("b"), scratch), (Int64)17L);
FST<object> fst = builder.Finish();
object output = Util.Get(fst, new BytesRef("a"));
assertNotNull(output);
IList<Int64> outputList = outputs.AsList(output);
assertEquals(3, outputList.size());
assertEquals(1L, outputList[0]);
assertEquals(3L, outputList[1]);
assertEquals(0L, outputList[2]);
output = Util.Get(fst, new BytesRef("b"));
assertNotNull(output);
outputList = outputs.AsList(output);
assertEquals(1, outputList.size());
assertEquals(17L, outputList[0]);
}
[Test]
public void TestListOfOutputsEmptyString()
{
PositiveInt32Outputs _outputs = PositiveInt32Outputs.Singleton;
ListOfOutputs<Int64> outputs = new ListOfOutputs<Int64>(_outputs);
Builder<object> builder = new Builder<object>(FST.INPUT_TYPE.BYTE1, outputs);
Int32sRef scratch = new Int32sRef();
builder.Add(scratch, (Int64)0L);
builder.Add(scratch, (Int64)1L);
builder.Add(scratch, (Int64)17L);
builder.Add(scratch, (Int64)1L);
builder.Add(Util.ToInt32sRef(new BytesRef("a"), scratch), (Int64)1L);
builder.Add(Util.ToInt32sRef(new BytesRef("a"), scratch), (Int64)3L);
builder.Add(Util.ToInt32sRef(new BytesRef("a"), scratch), (Int64)0L);
builder.Add(Util.ToInt32sRef(new BytesRef("b"), scratch), (Int64)0L);
FST<object> fst = builder.Finish();
object output = Util.Get(fst, new BytesRef(""));
assertNotNull(output);
IList<Int64> outputList = outputs.AsList(output);
assertEquals(4, outputList.size());
assertEquals(0L, outputList[0]);
assertEquals(1L, outputList[1]);
assertEquals(17L, outputList[2]);
assertEquals(1L, outputList[3]);
output = Util.Get(fst, new BytesRef("a"));
assertNotNull(output);
outputList = outputs.AsList(output);
assertEquals(3, outputList.size());
assertEquals(1L, outputList[0]);
assertEquals(3L, outputList[1]);
assertEquals(0L, outputList[2]);
output = Util.Get(fst, new BytesRef("b"));
assertNotNull(output);
outputList = outputs.AsList(output);
assertEquals(1, outputList.size());
assertEquals(0L, outputList[0]);
}
}
}