diff --git a/src/Lucene.Net.Tests/Support/Document/Extensions/TestIndexableFieldExtensions.cs b/src/Lucene.Net.Tests/Support/Document/Extensions/TestIndexableFieldExtensions.cs new file mode 100644 index 0000000000..94ba2bf376 --- /dev/null +++ b/src/Lucene.Net.Tests/Support/Document/Extensions/TestIndexableFieldExtensions.cs @@ -0,0 +1,63 @@ +using Lucene.Net.Attributes; +using Lucene.Net.Index; +using Lucene.Net.Util; +using NUnit.Framework; +using System; +using System.Collections.Generic; + +#nullable enable + +namespace Lucene.Net.Documents.Extensions +{ + /* + * 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. + */ + + [TestFixture] + public class TestIndexableFieldExtensions : LuceneTestCase + { + public static IEnumerable TestCases() + { +#pragma warning disable CS8974 // Converting method group to non-delegate type + yield return new TestCaseData(new Int32Field("field", byte.MaxValue, Field.Store.NO), byte.MaxValue, IndexableFieldExtensions.GetByteValueOrDefault); + yield return new TestCaseData(new Int32Field("field", short.MaxValue, Field.Store.NO), short.MaxValue, IndexableFieldExtensions.GetInt16ValueOrDefault); + yield return new TestCaseData(new Int32Field("field", int.MaxValue, Field.Store.NO), int.MaxValue, IndexableFieldExtensions.GetInt32ValueOrDefault); + yield return new TestCaseData(new Int64Field("field", long.MaxValue, Field.Store.NO), long.MaxValue, IndexableFieldExtensions.GetInt64ValueOrDefault); + yield return new TestCaseData(new SingleField("field", float.MaxValue, Field.Store.NO), float.MaxValue, IndexableFieldExtensions.GetSingleValueOrDefault); + yield return new TestCaseData(new DoubleField("field", double.MaxValue, Field.Store.NO), double.MaxValue, IndexableFieldExtensions.GetDoubleValueOrDefault); + yield return new TestCaseData(null, (byte)0, IndexableFieldExtensions.GetByteValueOrDefault); + yield return new TestCaseData(null, (short)0, IndexableFieldExtensions.GetInt16ValueOrDefault); + yield return new TestCaseData(null, 0, IndexableFieldExtensions.GetInt32ValueOrDefault); + yield return new TestCaseData(null, 0L, IndexableFieldExtensions.GetInt64ValueOrDefault); + yield return new TestCaseData(null, 0f, IndexableFieldExtensions.GetSingleValueOrDefault); + yield return new TestCaseData(null, 0d, IndexableFieldExtensions.GetDoubleValueOrDefault); + yield return new TestCaseData(new StringField("field", "value", Field.Store.NO), (byte)0, IndexableFieldExtensions.GetByteValueOrDefault); + yield return new TestCaseData(new StringField("field", "value", Field.Store.NO), (short)0, IndexableFieldExtensions.GetInt16ValueOrDefault); + yield return new TestCaseData(new StringField("field", "value", Field.Store.NO), 0, IndexableFieldExtensions.GetInt32ValueOrDefault); + yield return new TestCaseData(new StringField("field", "value", Field.Store.NO), 0L, IndexableFieldExtensions.GetInt64ValueOrDefault); + yield return new TestCaseData(new StringField("field", "value", Field.Store.NO), 0f, IndexableFieldExtensions.GetSingleValueOrDefault); + yield return new TestCaseData(new StringField("field", "value", Field.Store.NO), 0d, IndexableFieldExtensions.GetDoubleValueOrDefault); +#pragma warning restore CS8974 // Converting method group to non-delegate type + } + + [Test, LuceneNetSpecific] + [TestCaseSource(nameof(TestCases))] + public void TestIndexableFieldExtensions_TestCases(IIndexableField? field, object expected, Delegate func) + { + Assert.AreEqual(expected, func.DynamicInvoke(field)); + } + } +} diff --git a/src/Lucene.Net.Tests/Support/IO/TestByteArrayOutputStream.cs b/src/Lucene.Net.Tests/Support/IO/TestByteArrayOutputStream.cs new file mode 100644 index 0000000000..52fc167c97 --- /dev/null +++ b/src/Lucene.Net.Tests/Support/IO/TestByteArrayOutputStream.cs @@ -0,0 +1,37 @@ +using Lucene.Net.Attributes; +using Lucene.Net.Util; +using NUnit.Framework; +using System.Text; + +namespace Lucene.Net.Support.IO +{ + /* + * 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. + */ + + [TestFixture] + public class TestByteArrayOutputStream : LuceneTestCase + { + [Test, LuceneNetSpecific] + public void TestToString() + { + ByteArrayOutputStream s = new ByteArrayOutputStream(); + var bytes = Encoding.UTF8.GetBytes("hello, world"); + s.Write(bytes, 0, bytes.Length); + Assert.AreEqual("hello, world", s.ToString()); + } + } +} diff --git a/src/Lucene.Net.Tests/Support/TestAssemblyUtils.cs b/src/Lucene.Net.Tests/Support/TestAssemblyUtils.cs new file mode 100644 index 0000000000..0d16c41632 --- /dev/null +++ b/src/Lucene.Net.Tests/Support/TestAssemblyUtils.cs @@ -0,0 +1,36 @@ +using Lucene.Net.Attributes; +using Lucene.Net.Util; +using NUnit.Framework; +using System.Linq; + +namespace Lucene.Net.Support +{ + /* + * 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. + */ + + [TestFixture] + public class TestAssemblyUtils : LuceneTestCase + { + [Test, LuceneNetSpecific] + public void TestGetReferencedAssemblies() + { + var assemblies = AssemblyUtils.GetReferencedAssemblies().ToList(); + Assert.Greater(assemblies.Count, 0); + Assert.IsTrue(assemblies.Contains(typeof(LuceneVersion).Assembly)); // Lucene.Net should definitely be in the list + } + } +} diff --git a/src/Lucene.Net.Tests/Support/TestDictionaryExtensions.cs b/src/Lucene.Net.Tests/Support/TestDictionaryExtensions.cs new file mode 100644 index 0000000000..bbcefac977 --- /dev/null +++ b/src/Lucene.Net.Tests/Support/TestDictionaryExtensions.cs @@ -0,0 +1,70 @@ +using Lucene.Net.Attributes; +using Lucene.Net.Util; +using NUnit.Framework; +using System.Collections.Generic; + +namespace Lucene.Net.Support +{ + /* + * 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. + */ + + [TestFixture] + public class TestDictionaryExtensions : LuceneTestCase + { + [Test, LuceneNetSpecific] + public void TestPutAll() + { + var dictionary1 = new Dictionary + { + { "key1", "value1" }, + { "key2", "value2" } + }; + var dictionary2 = new Dictionary + { + { "key1", "value1.1" }, + { "key3", "value3" } + }; + + dictionary1.PutAll(dictionary2); + + Assert.AreEqual(3, dictionary1.Count); + Assert.AreEqual("value1.1", dictionary1["key1"]); + Assert.AreEqual("value2", dictionary1["key2"]); + Assert.AreEqual("value3", dictionary1["key3"]); + } + + [Test, LuceneNetSpecific] + public void TestPut() + { + var dictionary = new Dictionary + { + { "key1", "value1" }, + { "key2", "value2" } + }; + + var oldFirst = dictionary.Put("key1", "value1.1"); + var oldSecond = dictionary.Put("key3", "value3"); + + Assert.AreEqual(3, dictionary.Count); + Assert.AreEqual("value1.1", dictionary["key1"]); + Assert.AreEqual("value2", dictionary["key2"]); + Assert.AreEqual("value3", dictionary["key3"]); + Assert.AreEqual("value1", oldFirst); + Assert.IsNull(oldSecond); + } + } +} diff --git a/src/Lucene.Net.Tests/Support/Util/TestCastTo.cs b/src/Lucene.Net.Tests/Support/Util/TestCastTo.cs new file mode 100644 index 0000000000..e85f4f9faa --- /dev/null +++ b/src/Lucene.Net.Tests/Support/Util/TestCastTo.cs @@ -0,0 +1,96 @@ +using Lucene.Net.Attributes; +using NUnit.Framework; +using System; +using System.Collections.Generic; + +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. + */ + + [TestFixture] + public class TestCastTo : LuceneTestCase + { + public static IEnumerable TestFromSuccessCases() + { + yield return new TestCaseData((byte)1, (short)1); + yield return new TestCaseData((byte)1, 1); + yield return new TestCaseData((byte)1, 1L); + yield return new TestCaseData((byte)1, 1f); + yield return new TestCaseData((byte)1, 1d); + yield return new TestCaseData((short)2, (byte)2); + yield return new TestCaseData((short)2, 2); + yield return new TestCaseData((short)2, 2L); + yield return new TestCaseData((short)2, 2f); + yield return new TestCaseData((short)2, 2d); + yield return new TestCaseData(3, (byte)3); + yield return new TestCaseData(3, (short)3); + yield return new TestCaseData(3, 3L); + yield return new TestCaseData(3, 3f); + yield return new TestCaseData(3, 3d); + yield return new TestCaseData(4L, (byte)4); + yield return new TestCaseData(4L, (short)4); + yield return new TestCaseData(4L, 4); + yield return new TestCaseData(4L, 4f); + yield return new TestCaseData(4L, 4d); + yield return new TestCaseData(5f, (byte)5); + yield return new TestCaseData(5f, (short)5); + yield return new TestCaseData(5f, 5); + yield return new TestCaseData(5f, 5L); + yield return new TestCaseData(5f, 5d); + yield return new TestCaseData(6d, (byte)6); + yield return new TestCaseData(6d, (short)6); + yield return new TestCaseData(6d, 6); + yield return new TestCaseData(6d, 6L); + yield return new TestCaseData(6d, 6f); + } + + [Test, LuceneNetSpecific] + [TestCaseSource(nameof(TestFromSuccessCases))] + public void TestFrom_Success(object value, object expected) + { + var castTo = typeof(CastTo<>).MakeGenericType(expected.GetType()); + var from = castTo.GetMethod("From")?.MakeGenericMethod(value.GetType()) + ?? throw new InvalidOperationException("Could not find method CastTo.From"); + Assert.AreEqual(expected, from.Invoke(null, new[] { value })); + } + + public static IEnumerable TestFromInvalidCastCases() + { + yield return new TestCaseData(1, "1"); + yield return new TestCaseData(new object(), 1); + } + + [Test, LuceneNetSpecific] + [TestCaseSource(nameof(TestFromInvalidCastCases))] + public void TestFrom_InvalidCast(object value, object expected) + { + var castTo = typeof(CastTo<>).MakeGenericType(expected.GetType()); + var from = castTo.GetMethod("From")?.MakeGenericMethod(value.GetType()) + ?? throw new InvalidOperationException("Could not find method CastTo.From"); + try + { + from.Invoke(null, new[] { value }); + Assert.Fail("Expected an exception"); + } + catch + { + // ignored + } + } + } +} diff --git a/src/Lucene.Net.Tests/Support/Util/TestListExtensions.cs b/src/Lucene.Net.Tests/Support/Util/TestListExtensions.cs new file mode 100644 index 0000000000..29df968226 --- /dev/null +++ b/src/Lucene.Net.Tests/Support/Util/TestListExtensions.cs @@ -0,0 +1,257 @@ +using J2N.Collections.Generic.Extensions; +using Lucene.Net.Attributes; +using NUnit.Framework; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +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. + */ + + [TestFixture] + public class TestListExtensions : LuceneTestCase + { + /// + /// A custom list for the ListExtensions tests that should fall back to the unoptimized path. + /// + private class MyCustomList : IList + { + private readonly List _list = new(); + + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public void Add(int item) => _list.Add(item); + + public void Clear() => _list.Clear(); + + public bool Contains(int item) => _list.Contains(item); + + public void CopyTo(int[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex); + + public bool Remove(int item) => _list.Remove(item); + + public int Count => _list.Count; + + public bool IsReadOnly => false; + + public int IndexOf(int item) => _list.IndexOf(item); + + public void Insert(int index, int item) => _list.Insert(index, item); + + public void RemoveAt(int index) => _list.RemoveAt(index); + + public int this[int index] + { + get => _list[index]; + set => _list[index] = value; + } + } + + [Test, LuceneNetSpecific] + public void TestAddRange_SCGList() + { + IList list = new List { 1, 2, 3 }; + list.AddRange(new[] { 4, 5, 6 }); + Assert.AreEqual(6, list.Count); + Assert.AreEqual(1, list[0]); + Assert.AreEqual(2, list[1]); + Assert.AreEqual(3, list[2]); + Assert.AreEqual(4, list[3]); + Assert.AreEqual(5, list[4]); + Assert.AreEqual(6, list[5]); + } + + [Test, LuceneNetSpecific] + public void TestAddRange_JCGList() + { + IList list = new J2N.Collections.Generic.List { 1, 2, 3 }; + list.AddRange(new[] { 4, 5, 6 }); + Assert.AreEqual(6, list.Count); + Assert.AreEqual(1, list[0]); + Assert.AreEqual(2, list[1]); + Assert.AreEqual(3, list[2]); + Assert.AreEqual(4, list[3]); + Assert.AreEqual(5, list[4]); + Assert.AreEqual(6, list[5]); + } + + [Test, LuceneNetSpecific] + public void TestAddRange_NonOptimized() + { + IList list = new MyCustomList { 1, 2, 3 }; + list.AddRange(new[] { 4, 5, 6 }); + Assert.AreEqual(6, list.Count); + Assert.AreEqual(1, list[0]); + Assert.AreEqual(2, list[1]); + Assert.AreEqual(3, list[2]); + Assert.AreEqual(4, list[3]); + Assert.AreEqual(5, list[4]); + Assert.AreEqual(6, list[5]); + } + + [Test, LuceneNetSpecific] + public void TestSort_SCGList() + { + IList list = new List { 3, 2, 1 }; + list.Sort(); + Assert.AreEqual(1, list[0]); + Assert.AreEqual(2, list[1]); + Assert.AreEqual(3, list[2]); + } + + [Test, LuceneNetSpecific] + public void TestSort_JCGList() + { + IList list = new J2N.Collections.Generic.List { 3, 2, 1 }; + list.Sort(); + Assert.AreEqual(1, list[0]); + Assert.AreEqual(2, list[1]); + Assert.AreEqual(3, list[2]); + } + + [Test, LuceneNetSpecific] + public void TestSort_NonOptimized() + { + IList list = new MyCustomList { 3, 2, 1 }; + list.Sort(); + Assert.AreEqual(1, list[0]); + Assert.AreEqual(2, list[1]); + Assert.AreEqual(3, list[2]); + } + + private class ReverseComparer : IComparer + { + public int Compare(T x, T y) => Comparer.Default.Compare(y, x); + } + + [Test, LuceneNetSpecific] + public void TestSortWithComparer_SCGList() + { + IList list = new List { 2, 1, 3 }; + list.Sort(new ReverseComparer()); + Assert.AreEqual(3, list[0]); + Assert.AreEqual(2, list[1]); + Assert.AreEqual(1, list[2]); + } + + [Test, LuceneNetSpecific] + public void TestSortWithComparer_JCGList() + { + IList list = new J2N.Collections.Generic.List { 2, 1, 3 }; + list.Sort(new ReverseComparer()); + Assert.AreEqual(3, list[0]); + Assert.AreEqual(2, list[1]); + Assert.AreEqual(1, list[2]); + } + + [Test, LuceneNetSpecific] + public void TestSortWithComparer_NonOptimized() + { + IList list = new MyCustomList { 2, 1, 3 }; + list.Sort(new ReverseComparer()); + Assert.AreEqual(3, list[0]); + Assert.AreEqual(2, list[1]); + Assert.AreEqual(1, list[2]); + } + + [Test, LuceneNetSpecific] + public void TestSortWithComparison_SCGList() + { + IList list = new List { 2, 1, 3 }; + list.Sort((x, y) => y.CompareTo(x)); + Assert.AreEqual(3, list[0]); + Assert.AreEqual(2, list[1]); + Assert.AreEqual(1, list[2]); + } + + [Test, LuceneNetSpecific] + public void TestSortWithComparison_JCGList() + { + IList list = new J2N.Collections.Generic.List { 2, 1, 3 }; + list.Sort((x, y) => y.CompareTo(x)); + Assert.AreEqual(3, list[0]); + Assert.AreEqual(2, list[1]); + Assert.AreEqual(1, list[2]); + } + + [Test, LuceneNetSpecific] + public void TestSortWithComparison_NonOptimized() + { + IList list = new MyCustomList { 2, 1, 3 }; + list.Sort((x, y) => y.CompareTo(x)); + Assert.AreEqual(3, list[0]); + Assert.AreEqual(2, list[1]); + Assert.AreEqual(1, list[2]); + } + + [Test, LuceneNetSpecific] + public void TestTimSort() + { + // ensuring our list is big enough to trigger TimSort + List list = Enumerable.Range(1, 1000).ToList(); + list.Shuffle(); + list.TimSort(); + for (int i = 0; i < list.Count - 1; i++) + { + Assert.LessOrEqual(list[i], list[i + 1]); + } + } + + [Test, LuceneNetSpecific] + public void TestTimSortWithComparer() + { + // ensuring our list is big enough to trigger TimSort + List list = Enumerable.Range(1, 1000).ToList(); + list.Shuffle(); + list.TimSort(new ReverseComparer()); + for (int i = 0; i < list.Count - 1; i++) + { + Assert.GreaterOrEqual(list[i], list[i + 1]); + } + } + + [Test, LuceneNetSpecific] + public void TestIntroSort() + { + // ensuring our list is big enough to trigger IntroSort + List list = Enumerable.Range(1, 1000).ToList(); + list.Shuffle(); + list.IntroSort(); + for (int i = 0; i < list.Count - 1; i++) + { + Assert.LessOrEqual(list[i], list[i + 1]); + } + } + + [Test, LuceneNetSpecific] + public void TestIntroSortWithComparer() + { + // ensuring our list is big enough to trigger IntroSort + List list = Enumerable.Range(1, 1000).ToList(); + list.Shuffle(); + list.IntroSort(new ReverseComparer()); + for (int i = 0; i < list.Count - 1; i++) + { + Assert.GreaterOrEqual(list[i], list[i + 1]); + } + } + } +}