Commit 2ec68701 authored by An Ionescu's avatar An Ionescu

Switching from a Unity3D project to a normal VS class library project.

parent a6c0fb3d
using System;
using NUnit.Framework.Interfaces;
namespace Anvoker.Tests.Collections
{
/// <summary>
/// Has the sole purpose of easily allowing us to create an instance of
/// <see cref="ITestFixtureData"/> and set its properties.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.DocumentationRules",
"SA1600:ElementsMustBeDocumented",
Justification = "Properties documented in NUnit's documentation.")]
public class ExposedTestFixtureParams : ITestFixtureData
{
public Type[] TypeArgs { get; set; }
public string TestName { get; set; }
public RunState RunState { get; set; }
public object[] Arguments { get; set; }
public IPropertyBag Properties { get; set; }
}
}
......@@ -2,15 +2,40 @@
using System.Collections.Generic;
using System.Linq;
namespace Anvoker.Collections.Maps.Tests
namespace Anvoker.Tests.Collections
{
// TODO: Break this static class into less nondescript static classes once
// there are enough methods to justify their existence. Having "misc"
// static classes is kind of messy.
/// <summary>
/// Contains misc helper methods for unit testing.
/// </summary>
public static class HelperMethods
{
/// <summary>
/// Instantiates an array of collections where each collection is
/// constructed from a pairwise union between the collections in the
/// <paramref name="first"/> and <paramref name="second"/> arrays.
/// </summary>
/// <typeparam name="TCollection">Type of the collection.
/// </typeparam>
/// <typeparam name="TValue">Type of the element in the collection.
/// </typeparam>
/// <param name="first">The first array of collections.</param>
/// <param name="second">The second array of collections.</param>
/// <param name="comparer">The comparer for
/// <typeparamref name="TValue"/></param>
/// <param name="collectionConstructor">A delegate pointing to a
/// constructor of <typeparamref name="TCollection"/> that takes
/// <see cref="IEnumerable{T}"/> as its parameter.</param>
/// <returns>An array with new collections, created from pairwise
/// unions.</returns>
public static TCollection[] UnionValues<TCollection, TValue>(
TCollection[] first,
TCollection[] second,
IEqualityComparer<TValue> comparer,
Func<IEnumerable<TValue>, TCollection> colConstructor)
Func<IEnumerable<TValue>, TCollection> collectionConstructor)
where TCollection : IEnumerable<TValue>
{
TCollection[] longer;
......@@ -32,7 +57,7 @@ namespace Anvoker.Collections.Maps.Tests
{
if (i < shorter.Length)
{
values[i] = colConstructor(
values[i] = collectionConstructor(
longer[i].Union(shorter[i], comparer));
}
else
......
using System;
using System.Collections.Generic;
namespace Anvoker.Tests.Collections
{
/// <summary>
/// Provides key, values and comparers appropriate for testing maps.
/// </summary>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <typeparam name="TVal">The type of the value.</typeparam>
public class MapTestData<TKey, TVal>
{
/// <summary>
/// Initializes a new instance of the
/// <see cref="MapTestData{TKey, TVal}"/> class using the specified
/// keys, values and comparers.
/// </summary>
/// <param name="keysInitial">An array of keys initially contained
/// in the collection.</param>
/// <param name="keysToAdd">An array of keys to be added to the
/// collection. Not initially contained.</param>
/// <param name="keysExcluded">An array of keys not contained in
/// the collection.</param>
/// <param name="valuesInitial">An array of values associated with
/// <paramref name="keysInitial"/>.</param>
/// <param name="valuesToAdd">An array of values associated with
/// <paramref name="keysToAdd"/>.</param>
/// <param name="valuesExcluded">An array of values associated with
/// <paramref name="keysExcluded"/>.</param>
/// <param name="comparerKey">The comparer to use for key types.
/// </param>
/// <param name="comparerValue">The comparer to use for value types.
/// </param>
public MapTestData(
TKey[] keysInitial,
TKey[] keysToAdd,
TKey[] keysExcluded,
TVal[][] valuesInitial,
TVal[][] valuesToAdd,
TVal[][] valuesExcluded,
IEqualityComparer<TKey> comparerKey,
IEqualityComparer<TVal> comparerValue)
{
KeysInitial = keysInitial
?? throw new ArgumentNullException(nameof(keysInitial));
KeysToAdd = keysToAdd
?? throw new ArgumentNullException(nameof(keysToAdd));
KeysExcluded = keysExcluded
?? throw new ArgumentNullException(nameof(keysExcluded));
ValuesInitial = valuesInitial
?? throw new ArgumentNullException(nameof(valuesInitial));
ValuesToAdd = valuesToAdd
?? throw new ArgumentNullException(nameof(valuesToAdd));
ValuesExcluded = valuesExcluded
?? throw new ArgumentNullException(nameof(valuesExcluded));
ComparerKey = comparerKey ?? EqualityComparer<TKey>.Default;
ComparerValue = comparerValue ?? EqualityComparer<TVal>.Default;
HasDuplicatesThrow(keysInitial, nameof(keysInitial), ComparerKey);
HasDuplicatesThrow(keysToAdd, nameof(keysToAdd), ComparerKey);
HasDuplicatesThrow(keysExcluded, nameof(keysExcluded), ComparerKey);
LengthDiffersThrow(
keysInitial,
valuesInitial,
nameof(keysInitial),
nameof(valuesInitial));
LengthDiffersThrow(
keysToAdd,
valuesToAdd,
nameof(keysToAdd),
nameof(valuesToAdd));
LengthDiffersThrow(
keysExcluded,
valuesExcluded,
nameof(keysExcluded),
nameof(valuesExcluded));
HasOverlapThrow(
keysInitial,
keysToAdd,
nameof(keysInitial),
nameof(keysToAdd),
ComparerKey);
HasOverlapThrow(
keysInitial,
keysExcluded,
nameof(keysInitial),
nameof(keysExcluded),
ComparerKey);
}
/// <summary>
/// Initializes a new instance of the
/// <see cref="MapTestData{TKey, TVal}"/> class by copying members from
/// another <see cref="MapTestData{TKey, TVal}"/> instance.
/// </summary>
/// <param name="data">Instance to copy from.</param>
public MapTestData(MapTestData<TKey, TVal> data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
KeysInitial = data.KeysInitial;
KeysToAdd = data.KeysToAdd;
KeysExcluded = data.KeysExcluded;
ValuesInitial = data.ValuesInitial;
ValuesToAdd = data.ValuesToAdd;
ValuesExcluded = data.ValuesExcluded;
ComparerKey = data.ComparerKey;
ComparerValue = data.ComparerValue;
}
/// <summary>
/// Gets a unique set of keys.
/// </summary>
public TKey[] KeysInitial { get; }
/// <summary>
/// Gets a unique set of keys to add to the collection. Has no elements
/// in common with <see cref="KeysInitial"/> or <see cref="KeysExcluded"/>.
/// </summary>
public TKey[] KeysToAdd { get; }
/// <summary>
/// Gets a unique set of keys to guaranteed to not be in the collection.
/// Has no elements in common with <see cref="KeysInitial"/> or
/// <see cref="KeysToAdd"/>.
/// </summary>
public TKey[] KeysExcluded { get; }
/// <summary>
/// Gets a set of values associated with <see cref="KeysInitial"/>.
/// </summary>
public TVal[][] ValuesInitial { get; }
/// <summary>
/// Gets a set of values associated with <see cref="KeysToAdd"/>.
/// </summary>
public TVal[][] ValuesToAdd { get; }
/// <summary>
/// Gets a set of values associated with <see cref="KeysExcluded"/>.
/// </summary>
public TVal[][] ValuesExcluded { get; }
/// <summary>
/// Gets the comparer for the key type.
/// </summary>
public IEqualityComparer<TKey> ComparerKey { get; }
/// <summary>
/// Gets the comparer for the value type.
/// </summary>
public IEqualityComparer<TVal> ComparerValue { get; }
private static void HasOverlapThrow(
TKey[] arr1,
TKey[] arr2,
string name1,
string name2,
IEqualityComparer<TKey> comparer)
{
if (new HashSet<TKey>(arr1, comparer).Overlaps(
new HashSet<TKey>(arr2, comparer)))
{
throw new ArgumentException($"{name1} and {name2} can't have " +
"any keys in common.");
}
}
private static void LengthDiffersThrow(
TKey[] arr1, TVal[][] arr2, string name1, string name2)
{
if (arr1.Length != arr2.Length)
{
throw new ArgumentException(
$"{name1} and {name2} must have equal length.");
}
}
private static void HasDuplicatesThrow(
TKey[] array, string name, IEqualityComparer<TKey> comparer)
{
var hashset = new HashSet<TKey>(comparer);
foreach (TKey item in array)
{
if (!hashset.Add(item))
{
throw new ArgumentException($"{name} must have no " +
"duplicate keys.");
}
}
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
namespace Anvoker.Tests.Collections
{
/// <summary>
/// Provides key and values appropriate for testing maps.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.DocumentationRules",
"SA1600:ElementsMustBeDocumented",
Justification = "Naked data class.")]
public static class MapTestDataSource
{
public static readonly MapTestData<int, decimal> IntDecimal
= new MapTestData<int, decimal>(
keysInitial: new int[] { 25, 37, 99, 20, -5 },
keysToAdd: new int[] { 900, 901, 525 },
keysExcluded: new int[] { 24, 2, -8 },
valuesInitial: new decimal[][]
{
new decimal[] { 0.1m },
new decimal[] { 5.25m, 0.0m },
new decimal[] { 5.25m, 0.0m, 2.0m, 5.0m },
new decimal[] { },
new decimal[] { 3.75m },
},
valuesToAdd: new decimal[][]
{
new decimal[] { 99.1m },
new decimal[] { },
new decimal[] { 5.25m, 0.0m, 25.0m },
},
valuesExcluded: new decimal[][]
{
new decimal[] { 5.25m, 0.0m },
new decimal[] { },
new decimal[] { 5.25m, 0.0m, 25.0m },
},
comparerKey: null,
comparerValue: null);
public static readonly
MapTestData<string, string> StringStringCaseSensitive
= new MapTestData<string, string>(
keysInitial: new string[] { "nyaa", "nyAA", "\"\"", string.Empty },
keysToAdd: new string[] { "meow", "meoW", "Meow" },
keysExcluded: new string[] { "NYAA", "NYaA", " " },
valuesInitial: new string[][]
{
new string[] { "aaaa" },
new string[] { "aaaa", "bbbb", "cccc" },
new string[] { },
new string[] { "ffff" },
},
valuesToAdd: new string[][]
{
new string[] { "aaaa" },
new string[] { },
new string[] { "ffff", "eeee" },
},
valuesExcluded: new string[][]
{
new string[] { "aaaa" },
new string[] { },
new string[] { "zzzz", "\"\"", "wwww" },
},
comparerKey: StringComparer.InvariantCulture,
comparerValue: StringComparer.InvariantCulture);
public static readonly
MapTestData<string, string> StringStringCaseInsensitive
= new MapTestData<string, string>(
keysInitial: new string[]
{
"nyaa1", "nyaa2", string.Empty, " "
},
keysToAdd: new string[] { "meow", "\"\"", "Meow3" },
keysExcluded: new string[] { "Nyaa3", "nyaA4", " " },
valuesInitial: new string[][]
{
new string[] { "aaaa" },
new string[] { "aaAA", "bbbb", "cccc" },
new string[] { },
new string[] { "ffff" },
},
valuesToAdd: new string[][]
{
new string[] { "aaaa" },
new string[] { },
new string[] { "ffff", "eeee" },
},
valuesExcluded: new string[][]
{
new string[] { "aaaa" },
new string[] { },
new string[] { "zzzz", "\"\"", "wwww" },
},
comparerKey: StringComparer.InvariantCultureIgnoreCase,
comparerValue: StringComparer.InvariantCultureIgnoreCase);
public static readonly
MapTestData<List<int>, Type> ListType
= new MapTestData<List<int>, Type>(
keysInitial: new List<int>[]
{
new List<int>(),
new List<int>(),
new List<int>() { 5, 7 },
new List<int>() { 5, 7 },
},
keysToAdd: new List<int>[]
{
new List<int>(),
new List<int>() { 1, 2, 3 },
new List<int>() { 1, 2, 5 }
},
keysExcluded: new List<int>[]
{
new List<int>(),
new List<int>() { 1, 2, 3 },
new List<int>() { 1, 2, 5 }
},
valuesInitial: new Type[][]
{
new Type[] { typeof(int) },
new Type[] { },
new Type[] { typeof(int), typeof(float) },
new Type[] { typeof(decimal) },
},
valuesToAdd: new Type[][]
{
new Type[] { typeof(int) },
new Type[] { },
new Type[] { typeof(int?) },
},
valuesExcluded: new Type[][]
{
new Type[] { typeof(int) },
new Type[] { },
new Type[] { typeof(DateTime) },
},
comparerKey: null,
comparerValue: null);
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using NUnit.Framework;
using NUnit.Framework.Internal;
namespace Anvoker.Tests.Collections.MultiBiMapTests
{
using Anvoker.Collections.Maps;
using NestedIDictionary;
/// <summary>
/// Provides test data for a
/// <see cref="NestedIDictionaryBase{TKey, TVal, TIDict, TValCol}"/> test
/// fixture.
/// </summary>
public static class NestedIDictionary_FixtureSource
{
/// <summary>
/// Provides the arguments for a test fixture that is decorated with
/// <see cref="TestCaseSourceAttribute"/> and has a constructor with
/// matching parameter types.
/// </summary>
/// <returns>An array of objects where each object is a collection
/// that contains all of the necessary parameters to run a constructor
/// of matching type.</returns>
public static TestFixtureParameters[] GetFixtureArgs()
=> new TestFixtureParameters[]
{
ConstructFixtureParams(MapTestDataSource.IntDecimal),
ConstructFixtureParams(MapTestDataSource.StringStringCaseInsensitive),
ConstructFixtureParams(MapTestDataSource.StringStringCaseSensitive),
ConstructFixtureParams(MapTestDataSource.ListType)
};
private static Func<MultiBiMap<TKey, TVal>> GetCtor<TKey, TVal>(
TKey[] keys, TVal[][] values)
{
return () =>
{
var multiMap = new MultiBiMap<TKey, TVal>();
for (int i = 0; i < keys.Length; i++)
{
multiMap.Add(keys[i], values[i]);
}
return multiMap;
};
}
private static TestFixtureParameters ConstructFixtureParams<TKey, TVal>(
MapTestData<TKey, TVal> data)
{
return NestedIDictionaryBase<TKey, TVal,
MultiBiMap<TKey, TVal>, ICollection<TVal>>
.ConstructFixtureParams(
GetCtor(data.KeysInitial, data.ValuesInitial),
(x) => new HashSet<TVal>(x),
data);
}
}
}
\ No newline at end of file
using System;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
namespace Anvoker.Collections.Maps.Tests.MultiMap
namespace Anvoker.Tests.Collections.MultiMapTests
{
using Anvoker.Collections.Maps;
/// <summary>
/// Unit tests for <see cref="MultiMap{TKey, TVal}"/>'s constructors.
/// </summary>
......
using System;
using System.Collections.Generic;
using NUnit.Framework;
using NUnit.Framework.Internal;
namespace Anvoker.Tests.Collections.MultiMapTests
{
using Anvoker.Collections.Maps;
using NestedIDictionary;
/// <summary>
/// Provides test data for a
/// <see cref="NestedIDictionaryBase{TKey, TVal, TIDict, TValCol}"/> test
/// fixture.
/// </summary>
public static class NestedIDictionary_FixtureSource
{
/// <summary>
/// Provides the arguments for a test fixture that is decorated with
/// <see cref="TestCaseSourceAttribute"/> and has a constructor with
/// matching parameter types.
/// </summary>
/// <returns>An array of objects where each object is a collection
/// that contains all of the necessary parameters to run a constructor
/// of matching type.</returns>
public static TestFixtureParameters[] GetFixtureArgs()
=> new TestFixtureParameters[]
{
ConstructFixtureParams(MapTestDataSource.IntDecimal),
ConstructFixtureParams(MapTestDataSource.StringStringCaseInsensitive),
ConstructFixtureParams(MapTestDataSource.StringStringCaseSensitive),
ConstructFixtureParams(MapTestDataSource.ListType)
};
private static Func<MultiMap<TKey, TVal>> GetCtor<TKey, TVal>(
TKey[] keys, TVal[][] values)
{
return () =>