in src/Lucene.Net.TestFramework/Util/Fst/FSTTester.cs [429:801]
private void VerifyUnPruned(int inputMode, FST<T> fst)
{
FST<Int64> fstLong;
ISet<Int64> validOutputs;
long minLong = long.MaxValue;
long maxLong = long.MinValue;
if (doReverseLookup)
{
FST<Int64> fstLong0 = fst as FST<Int64>;
fstLong = fstLong0;
validOutputs = new JCG.HashSet<Int64>();
foreach (InputOutput<T> pair in pairs)
{
Int64 output = (Int64)(object)pair.Output;
maxLong = Math.Max(maxLong, output);
minLong = Math.Min(minLong, output);
validOutputs.Add(output);
}
}
else
{
fstLong = null;
validOutputs = null;
}
if (pairs.Count == 0)
{
Assert.IsNull(fst);
return;
}
if (LuceneTestCase.Verbose)
{
Console.WriteLine("TEST: now verify " + pairs.Count + " terms");
foreach (InputOutput<T> pair in pairs)
{
Assert.IsNotNull(pair);
Assert.IsNotNull(pair.Input);
Assert.IsNotNull(pair.Output);
Console.WriteLine(" " + InputToString(inputMode, pair.Input) + ": " + outputs.OutputToString(pair.Output));
}
}
Assert.IsNotNull(fst);
// visit valid pairs in order -- make sure all words
// are accepted, and FSTEnum's next() steps through
// them correctly
if (LuceneTestCase.Verbose)
{
Console.WriteLine("TEST: check valid terms/next()");
}
{
Int32sRefFSTEnum<T> fstEnum = new Int32sRefFSTEnum<T>(fst);
foreach (InputOutput<T> pair in pairs)
{
Int32sRef term = pair.Input;
if (LuceneTestCase.Verbose)
{
Console.WriteLine("TEST: check term=" + InputToString(inputMode, term) + " output=" + fst.Outputs.OutputToString(pair.Output));
}
T output = Run(fst, term, null);
Assert.IsNotNull(output, "term " + InputToString(inputMode, term) + " is not accepted");
Assert.IsTrue(OutputsEqual(pair.Output, output));
// verify enum's next
Assert.IsTrue(fstEnum.MoveNext());
Int32sRefFSTEnum.InputOutput<T> t = fstEnum.Current;
Assert.IsNotNull(t);
Assert.AreEqual(term, t.Input, "expected input=" + InputToString(inputMode, term) + " but fstEnum returned " + InputToString(inputMode, t.Input));
Assert.IsTrue(OutputsEqual(pair.Output, t.Output));
}
Assert.IsFalse(fstEnum.MoveNext());
}
IDictionary<Int32sRef, T> termsMap = new Dictionary<Int32sRef, T>();
foreach (InputOutput<T> pair in pairs)
{
termsMap[pair.Input] = pair.Output;
}
if (doReverseLookup && maxLong > minLong)
{
// Do random lookups so we test null (output doesn't
// exist) case:
Assert.IsNull(Util.GetByOutput(fstLong, minLong - 7));
Assert.IsNull(Util.GetByOutput(fstLong, maxLong + 7));
int num = LuceneTestCase.AtLeast(random, 100);
for (int iter = 0; iter < num; iter++)
{
long v = TestUtil.NextInt64(random, minLong, maxLong);
Int32sRef input = Util.GetByOutput(fstLong, v);
Assert.IsTrue(validOutputs.Contains(v) || input is null);
}
}
// find random matching word and make sure it's valid
if (LuceneTestCase.Verbose)
{
Console.WriteLine("TEST: verify random accepted terms");
}
Int32sRef scratch = new Int32sRef(10);
int num_ = LuceneTestCase.AtLeast(random, 500);
for (int iter = 0; iter < num_; iter++)
{
T output = RandomAcceptedWord(fst, scratch);
Assert.IsTrue(termsMap.ContainsKey(scratch), "accepted word " + InputToString(inputMode, scratch) + " is not valid");
Assert.IsTrue(OutputsEqual(termsMap[scratch], output));
if (doReverseLookup)
{
//System.out.println("lookup output=" + output + " outs=" + fst.Outputs);
Int32sRef input = Util.GetByOutput(fstLong, (Int64)(object)output);
Assert.IsNotNull(input);
//System.out.println(" got " + Util.toBytesRef(input, new BytesRef()).utf8ToString());
Assert.AreEqual(scratch, input);
}
}
// test IntsRefFSTEnum.Seek:
if (LuceneTestCase.Verbose)
{
Console.WriteLine("TEST: verify seek");
}
Int32sRefFSTEnum<T> fstEnum_ = new Int32sRefFSTEnum<T>(fst);
num_ = LuceneTestCase.AtLeast(random, 100);
for (int iter = 0; iter < num_; iter++)
{
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" iter=" + iter);
}
if (random.NextBoolean())
{
// seek to term that doesn't exist:
while (true)
{
Int32sRef term = ToInt32sRef(GetRandomString(random), inputMode);
int pos = pairs.BinarySearch(new InputOutput<T>(term, default));
if (pos < 0)
{
pos = -(pos + 1);
// ok doesn't exist
//System.out.println(" seek " + inputToString(inputMode, term));
Int32sRefFSTEnum.InputOutput<T> seekResult;
if (random.Next(3) == 0)
{
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" do non-exist seekExact term=" + InputToString(inputMode, term));
}
seekResult = fstEnum_.SeekExact(term);
pos = -1;
}
else if (random.NextBoolean())
{
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" do non-exist seekFloor term=" + InputToString(inputMode, term));
}
seekResult = fstEnum_.SeekFloor(term);
pos--;
}
else
{
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" do non-exist seekCeil term=" + InputToString(inputMode, term));
}
seekResult = fstEnum_.SeekCeil(term);
}
if (pos != -1 && pos < pairs.Count)
{
//System.out.println(" got " + inputToString(inputMode,seekResult.input) + " output=" + fst.Outputs.outputToString(seekResult.Output));
Assert.IsNotNull(seekResult, "got null but expected term=" + InputToString(inputMode, pairs[pos].Input));
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" got " + InputToString(inputMode, seekResult.Input));
}
Assert.AreEqual(pairs[pos].Input, seekResult.Input, "expected " + InputToString(inputMode, pairs[pos].Input) + " but got " + InputToString(inputMode, seekResult.Input));
Assert.IsTrue(OutputsEqual(pairs[pos].Output, seekResult.Output));
}
else
{
// seeked before start or beyond end
//System.out.println("seek=" + seekTerm);
Assert.IsNull(seekResult, "expected null but got " + (seekResult is null ? "null" : InputToString(inputMode, seekResult.Input)));
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" got null");
}
}
break;
}
}
}
else
{
// seek to term that does exist:
InputOutput<T> pair = pairs[random.Next(pairs.Count)];
Int32sRefFSTEnum.InputOutput<T> seekResult;
if (random.Next(3) == 2)
{
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" do exists seekExact term=" + InputToString(inputMode, pair.Input));
}
seekResult = fstEnum_.SeekExact(pair.Input);
}
else if (random.NextBoolean())
{
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" do exists seekFloor " + InputToString(inputMode, pair.Input));
}
seekResult = fstEnum_.SeekFloor(pair.Input);
}
else
{
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" do exists seekCeil " + InputToString(inputMode, pair.Input));
}
seekResult = fstEnum_.SeekCeil(pair.Input);
}
Assert.IsNotNull(seekResult);
Assert.AreEqual(pair.Input, seekResult.Input, "got " + InputToString(inputMode, seekResult.Input) + " but expected " + InputToString(inputMode, pair.Input));
Assert.IsTrue(OutputsEqual(pair.Output, seekResult.Output));
}
}
if (LuceneTestCase.Verbose)
{
Console.WriteLine("TEST: mixed next/seek");
}
// test mixed next/seek
num_ = LuceneTestCase.AtLeast(random, 100);
for (int iter = 0; iter < num_; iter++)
{
if (LuceneTestCase.Verbose)
{
Console.WriteLine("TEST: iter " + iter);
}
// reset:
fstEnum_ = new Int32sRefFSTEnum<T>(fst);
int upto = -1;
while (true)
{
bool isDone = false;
if (upto == pairs.Count - 1 || random.NextBoolean())
{
// next
upto++;
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" do next");
}
isDone = fstEnum_.MoveNext() == false;
}
else if (upto != -1 && upto < 0.75 * pairs.Count && random.NextBoolean())
{
int attempt = 0;
for (; attempt < 10; attempt++)
{
Int32sRef term = ToInt32sRef(GetRandomString(random), inputMode);
if (!termsMap.ContainsKey(term) && term.CompareTo(pairs[upto].Input) > 0)
{
int pos = pairs.BinarySearch(new InputOutput<T>(term, default));
if (Debugging.AssertsEnabled) Debugging.Assert(pos < 0);
upto = -(pos + 1);
if (random.NextBoolean())
{
upto--;
Assert.IsTrue(upto != -1);
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" do non-exist seekFloor(" + InputToString(inputMode, term) + ")");
}
isDone = fstEnum_.SeekFloor(term) is null;
}
else
{
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" do non-exist seekCeil(" + InputToString(inputMode, term) + ")");
}
isDone = fstEnum_.SeekCeil(term) is null;
}
break;
}
}
if (attempt == 10)
{
continue;
}
}
else
{
int inc = random.Next(pairs.Count - upto - 1);
upto += inc;
if (upto == -1)
{
upto = 0;
}
if (random.NextBoolean())
{
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" do seekCeil(" + InputToString(inputMode, pairs[upto].Input) + ")");
}
isDone = fstEnum_.SeekCeil(pairs[upto].Input) is null;
}
else
{
if (LuceneTestCase.Verbose)
{
Console.WriteLine(" do seekFloor(" + InputToString(inputMode, pairs[upto].Input) + ")");
}
isDone = fstEnum_.SeekFloor(pairs[upto].Input) is null;
}
}
if (LuceneTestCase.Verbose)
{
if (!isDone)
{
Console.WriteLine(" got " + InputToString(inputMode, fstEnum_.Current.Input));
}
else
{
Console.WriteLine(" got null");
}
}
if (upto == pairs.Count)
{
Assert.IsTrue(isDone);
break;
}
else
{
Assert.IsFalse(isDone);
Assert.AreEqual(pairs[upto].Input, fstEnum_.Current.Input);
Assert.IsTrue(OutputsEqual(pairs[upto].Output, fstEnum_.Current.Output));
/*
if (upto < pairs.size()-1) {
int tryCount = 0;
while(tryCount < 10) {
final IntsRef t = toIntsRef(getRandomString(), inputMode);
if (pairs.get(upto).input.compareTo(t) < 0) {
final boolean expected = t.compareTo(pairs.get(upto+1).input) < 0;
if (LuceneTestCase.VERBOSE) {
System.out.println("TEST: call beforeNext(" + inputToString(inputMode, t) + "); current=" + inputToString(inputMode, pairs.get(upto).input) + " next=" + inputToString(inputMode, pairs.get(upto+1).input) + " expected=" + expected);
}
Assert.AreEqual(expected, fstEnum.beforeNext(t));
break;
}
tryCount++;
}
}
*/
}
}
}
}