Skip to content

Commit

Permalink
Add a few more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
xoofx committed Jul 4, 2024
1 parent 1bd58aa commit cb2944f
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 2 deletions.
166 changes: 166 additions & 0 deletions src/XenoAtom.Collections.Tests/UnsafeDictionaryTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// Copyright (c) Alexandre Mutel. All rights reserved.
// Licensed under the BSD-Clause 2 license.
// See license.txt file in the project root for full license information.

using System.Runtime.CompilerServices;

namespace XenoAtom.Collections.Tests;

[TestClass]
public class UnsafeDictionaryTests
{
// TODO: Add more tests

[TestMethod]
public void TestAdd()
{
var dict = new UnsafeDictionary<int, int>();
dict.Add(1, 1);
Assert.IsTrue(dict.ContainsKey(1));
Assert.AreEqual(1, dict[1]);
Assert.AreEqual(1, dict.Count);

dict.Add(2, 2);
Assert.IsTrue(dict.ContainsKey(2));
Assert.AreEqual(2, dict[2]);
Assert.AreEqual(2, dict.Count);

dict.Add(3, 3);
Assert.IsTrue(dict.ContainsKey(3));
Assert.AreEqual(3, dict[3]);
Assert.AreEqual(3, dict.Count);

dict.Add(4, 4);
Assert.IsTrue(dict.ContainsKey(4));
Assert.AreEqual(4, dict[4]);
Assert.AreEqual(4, dict.Count);

Assert.IsTrue(dict.ContainsKey(1));
Assert.IsTrue(dict.ContainsKey(2));
Assert.IsTrue(dict.ContainsKey(3));
Assert.IsTrue(dict.ContainsKey(4));
}

[TestMethod]
public void TestAddRemove()
{
var dict = new UnsafeDictionary<int, int>();
dict.Add(1, 1);
Assert.IsTrue(dict.ContainsKey(1));
dict.Remove(1);
Assert.IsFalse(dict.ContainsKey(1));

Assert.AreEqual(0, dict.Count);
}

// Generate lots of different test cases with other methods

[TestMethod]
public void TestKeys()
{
var dict = new UnsafeDictionary<int, int>();
dict.Add(1, 1);
dict.Add(2, 2);
dict.Add(3, 3);
dict.Add(4, 4);

var keys = dict.Keys;
Assert.AreEqual(4, keys.Count);
Assert.IsTrue(keys.Contains(1));
Assert.IsTrue(keys.Contains(2));
Assert.IsTrue(keys.Contains(3));
Assert.IsTrue(keys.Contains(4));
}

[TestMethod]
public void TestValues()
{
var dict = new UnsafeDictionary<int, int>();
dict.Add(1, 5);
dict.Add(2, 6);
dict.Add(3, 7);
dict.Add(4, 8);

var values = dict.Values;
Assert.AreEqual(4, values.Count);
Assert.IsTrue(values.Contains(5));
Assert.IsTrue(values.Contains(6));
Assert.IsTrue(values.Contains(7));
Assert.IsTrue(values.Contains(8));
}

[TestMethod]
public void TestClear()
{
var dict = new UnsafeDictionary<int, int>();
dict.Add(1, 1);
dict.Add(2, 2);
dict.Add(3, 3);
dict.Add(4, 4);

Assert.AreEqual(4, dict.Count);
dict.Clear();
Assert.AreEqual(0, dict.Count);
}

[TestMethod]
public void TestTryGetValue()
{
var dict = new UnsafeDictionary<int, int>();
dict.Add(1, 1);
dict.Add(2, 2);
dict.Add(3, 3);
dict.Add(4, 4);

Assert.IsTrue(dict.TryGetValue(1, out var value));
Assert.AreEqual(1, value);

Assert.IsTrue(dict.TryGetValue(2, out value));
Assert.AreEqual(2, value);

Assert.IsTrue(dict.TryGetValue(3, out value));
Assert.AreEqual(3, value);

Assert.IsTrue(dict.TryGetValue(4, out value));
Assert.AreEqual(4, value);

Assert.IsFalse(dict.TryGetValue(5, out _));
}

[TestMethod]
public void TestContainsKey()
{
var dict = new UnsafeDictionary<int, int>();
dict.Add(1, 1);
dict.Add(2, 2);
dict.Add(3, 3);
dict.Add(4, 4);

Assert.IsTrue(dict.ContainsKey(1));
Assert.IsTrue(dict.ContainsKey(2));
Assert.IsTrue(dict.ContainsKey(3));
Assert.IsTrue(dict.ContainsKey(4));
Assert.IsFalse(dict.ContainsKey(5));
}

[TestMethod]
public void TestAddByRef()
{
var dict = new UnsafeDictionary<int, int>();
dict.Add(1, 1);
dict.Add(2, 2);
dict.Add(3, 3);
dict.Add(4, 4);

ref var value = ref dict.GetValueRefOrAddDefault(5, out bool exists);
Assert.IsFalse(exists);
value = 6;
Assert.IsTrue(dict.ContainsKey(5));
Assert.AreEqual(6, dict[5]);


ref var nullRef = ref dict.GetValueRefOrNullRef(6, out exists);
Assert.IsFalse(exists);
Assert.IsTrue(Unsafe.IsNullRef(ref nullRef));
}
}
15 changes: 15 additions & 0 deletions src/XenoAtom.Collections.Tests/UnsafeHashSetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ namespace XenoAtom.Collections.Tests;
[TestClass]
public class UnsafeHashSetTests
{
// TODO: Add more tests

[TestMethod]
public void TestAdd()
{
Expand Down Expand Up @@ -88,4 +90,17 @@ public void TestAddRemoveAddRemoveAddRemove()
set.Remove(1);
Assert.IsFalse(set.Contains(1));
}

[TestMethod]
public void TestMultipleAdds()
{
var set = new UnsafeHashSet<int>();
for (int i = 0; i < 1000; i++)
{
Assert.IsTrue(set.Add(i));
Assert.IsFalse(set.Add(i));
Assert.IsTrue(set.Contains(i));
}
Assert.AreEqual(1000, set.Count);
}
}
57 changes: 57 additions & 0 deletions src/XenoAtom.Collections.Tests/UnsafeListTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -785,4 +785,61 @@ public void TestUnsafeGetBatch()
firstItem = 1;
Assert.AreEqual(1, list[0]);
}

[TestMethod]
public void TestSort()
{
var list = new UnsafeList<int>(4)
{
4,
3,
2,
1
};
list.Sort((left, right) => left.CompareTo(right));
Assert.AreEqual(1, list[0]);
Assert.AreEqual(2, list[1]);
Assert.AreEqual(3, list[2]);
Assert.AreEqual(4, list[3]);
}

[TestMethod]
public void TestSortStringWithComparer()
{
var list = new UnsafeList<string>(4)
{
"4",
"3",
"2",
"1"
};
list.Sort(StringComparer.Ordinal);

Assert.AreEqual("1", list[0]);
Assert.AreEqual("2", list[1]);
Assert.AreEqual("3", list[2]);
Assert.AreEqual("4", list[3]);
}

[TestMethod]
public void TestSortByRef()
{
var list = new UnsafeList<int>(4)
{
4,
3,
2,
1
};
list.SortByRef(new IntComparerByRef());
Assert.AreEqual(1, list[0]);
Assert.AreEqual(2, list[1]);
Assert.AreEqual(3, list[2]);
Assert.AreEqual(4, list[3]);
}

private struct IntComparerByRef : IComparerByRef<int>
{
public bool LessThan(in int left, in int right) => left.CompareTo(right) < 0;
}
}
4 changes: 2 additions & 2 deletions src/XenoAtom.Collections/SpanSortExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ public static class SpanSortExtensions
internal const int IntrosortSizeThreshold = 16;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Sort<T, TComparer>(this T[] keys, in TComparer comparer) where TComparer : struct, IComparerByRef<T>
public static void SortByRef<T, TComparer>(this T[] keys, in TComparer comparer) where TComparer : struct, IComparerByRef<T>
{
SortHelperByRef<T, TComparer>.Sort(keys, comparer);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Sort<T, TComparer>(this Span<T> keys, in TComparer comparer) where TComparer : struct, IComparerByRef<T>
public static void SortByRef<T, TComparer>(this Span<T> keys, in TComparer comparer) where TComparer : struct, IComparerByRef<T>
{
SortHelperByRef<T, TComparer>.Sort(keys, comparer);
}
Expand Down
5 changes: 5 additions & 0 deletions src/XenoAtom.Collections/UnsafeDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@

namespace XenoAtom.Collections;

/// <summary>
/// Implements a dictionary requiring the key to be <see cref="IEquatable{T}"/> for fast lookup.
/// </summary>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
[DebuggerTypeProxy(typeof(UnsafeDictionary<,>.IDictionaryDebugView))]
[DebuggerDisplay("Count = {Count}")]
public struct UnsafeDictionary<TKey, TValue> : IDictionary<TKey, TValue> where TKey : IEquatable<TKey>
Expand Down
4 changes: 4 additions & 0 deletions src/XenoAtom.Collections/UnsafeHashSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@

namespace XenoAtom.Collections;

/// <summary>
/// Implements a HashSet requiring the element to implement <see cref="IEquatable{T}"/> for fast lookup.
/// </summary>
/// <typeparam name="T">The type of the element.</typeparam>
[DebuggerTypeProxy(typeof(UnsafeHashSet<>.DebugHashSetView))]
[DebuggerDisplay("Count = {Count}")]
[Serializable]
Expand Down
14 changes: 14 additions & 0 deletions src/XenoAtom.Collections/UnsafeList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,20 @@ public bool Remove(T element)
return false;
}

public void Sort(Comparison<T> comparison) => AsSpan().Sort(comparison);

public void Sort<TComparer>() where TComparer : IComparer<T>, new() => Sort(new TComparer());

public void Sort<TComparer>(TComparer comparer) where TComparer : IComparer<T>
{
AsSpan().Sort(comparer);
}

public void SortByRef<TComparer>(in TComparer comparer) where TComparer : struct, IComparerByRef<T>
{
AsSpan().SortByRef(comparer);
}

public readonly int IndexOf(T element) => Array.IndexOf(_items, element, 0, (int)_count);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down

0 comments on commit cb2944f

Please sign in to comment.