blob: cfd018ba9ab55df124305f60fd2ae34dc77632bb [file] [log] [blame]
using System.Collections.Generic;
using System.Linq;
using Lucene.Net.Support;
using NUnit.Framework;
using System;
using Assert = Lucene.Net.TestFramework.Assert;
namespace Lucene.Net.Util
{
/*
* 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 abstract class BaseSortTestCase : LuceneTestCase
{
public class Entry : IComparable<Entry>
{
public int Value { get; }
public int Ord { get; }
public Entry(int value, int ord)
{
this.Value = value;
this.Ord = ord;
}
public virtual int CompareTo(Entry other)
{
return Value < other.Value ? -1 : Value == other.Value ? 0 : 1;
}
}
private readonly bool stable;
private readonly Random random;
protected BaseSortTestCase(bool stable)
{
this.stable = stable;
this.random = Random;
}
public abstract Sorter NewSorter(Entry[] arr);
public class StableEntryComparer : IComparer<Entry>
{
public int Compare(Entry a, Entry b)
{
if (a.Value < b.Value) return -1;
else if (a.Value > b.Value) return 1;
//required for stable sorting
return a.Ord < b.Ord ? -1 : a.Ord == b.Ord ? 0 : 1;
}
}
public virtual void AssertSorted(Entry[] original, Entry[] sorted)
{
Assert.AreEqual(original.Length, sorted.Length);
Entry[] stableSorted = original.OrderBy(e => e, new StableEntryComparer()).ToArray();
for (int i = 0; i < original.Length; ++i)
{
Assert.AreEqual(stableSorted[i].Value, sorted[i].Value);
if (stable)
{
Assert.AreEqual(stableSorted[i].Ord, sorted[i].Ord);
}
}
}
public virtual void SortTest(Entry[] arr)
{
int o = random.Next(1000);
var toSort = new Entry[o + arr.Length + random.Next(3)];
Array.Copy(arr, 0, toSort, o, arr.Length);
Sorter sorter = NewSorter(toSort);
sorter.Sort(o, o + arr.Length);
AssertSorted(arr, Arrays.CopyOfRange(toSort, o, o + arr.Length));
}
private delegate void Strategy(Entry[] arr, int i);
private void RandomStrategy(Entry[] arr, int i)
{
arr[i] = new Entry(random.Next(), i);
}
private void RandomLowCardinalityStrategy(Entry[] arr, int i)
{
arr[i] = new Entry(random.nextInt(6), i);
}
private void AscendingStrategy(Entry[] arr, int i)
{
arr[i] = i == 0
? new Entry(random.nextInt(6), 0)
: new Entry(arr[i - 1].Value + random.nextInt(6), i);
}
private void DescendingStrategy(Entry[] arr, int i)
{
arr[i] = i == 0
? new Entry(random.nextInt(6), 0)
: new Entry(arr[i - 1].Value - random.nextInt(6), i);
}
private void StrictlyDescendingStrategy(Entry[] arr, int i)
{
arr[i] = i == 0
? new Entry(random.nextInt(6), 0)
: new Entry(arr[i - 1].Value - TestUtil.NextInt32(random, 1, 5), i);
}
private void AscendingSequencesStrategy(Entry[] arr, int i)
{
arr[i] = i == 0
? new Entry(random.nextInt(6), 0)
: new Entry(Rarely(random) ? random.nextInt(1000) : arr[i - 1].Value + random.nextInt(6), i);
}
private void MostlyAscendingStrategy(Entry[] arr, int i)
{
arr[i] = i == 0
? new Entry(random.nextInt(6), 0)
: new Entry(arr[i - 1].Value + TestUtil.NextInt32(random, -8, 10), i);
}
private void DoTest(Strategy strategy, int length)
{
Entry[] arr = new Entry[length];
for (int i = 0; i < arr.Length; ++i) {
strategy(arr, i);
}
SortTest(arr);
}
private void DoTest(Strategy strategy)
{
DoTest(strategy, Random.Next(20000));
}
[Test]
public virtual void TestEmpty()
{
SortTest(new Entry[0]);
}
[Test]
public virtual void TestOne()
{
DoTest(RandomStrategy, 1);
}
[Test]
public virtual void TestTwo()
{
DoTest(RandomStrategy, 2);
}
[Test]
public virtual void TestRandom()
{
DoTest(RandomStrategy);
}
[Test]
public virtual void TestRandomLowCardinality()
{
DoTest(RandomLowCardinalityStrategy, 2);
}
[Test]
public virtual void TestAscending()
{
DoTest(AscendingStrategy, 2);
}
[Test]
public virtual void TestAscendingSequences()
{
DoTest(AscendingSequencesStrategy, 2);
}
[Test]
public virtual void TestDescending()
{
DoTest(DescendingStrategy, 2);
}
[Test]
public virtual void TestStrictlyDescendingStrategy()
{
DoTest(StrictlyDescendingStrategy, 2);
}
}
}