📄 multidictionarytests.cs
字号:
//******************************
// Written by Peter Golde
// Copyright (c) 2004-2005, Wintellect
//
// Use and restribution of this code is subject to the license agreement
// contained in the file "License.txt" accompanying this file.
//******************************
using System;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
using Wintellect.PowerCollections.Tests;
namespace Wintellect.PowerCollections.Tests
{
using MyInt = OrderedDictionaryTests.MyInt;
[TestFixture]
public class MultiDictionaryTests
{
// Check the contents of a Multi-Dictionary non-destructively. Keys and Values must be in order.
internal static void CheckMultiDictionaryContents<TKey, TValue>(MultiDictionary<TKey, TValue> dict, TKey[] keys, TValue[][] values, TKey nonKey, TValue nonValue, BinaryPredicate<TKey> keyEquals, BinaryPredicate<TValue> valueEquals)
{
int iKey, iValue;
ICollection<TValue> getValues;
if (keyEquals == null)
keyEquals = delegate(TKey x, TKey y) { return object.Equals(x, y); };
if (valueEquals == null)
valueEquals = delegate(TValue x, TValue y) { return object.Equals(x, y); };
// Check Count.
Assert.AreEqual(keys.Length, dict.Count);
// Check indexer, ContainsKey, Contains, TryGetValue for each key.
for (iKey = 0; iKey < keys.Length; ++iKey) {
Assert.IsTrue(dict.ContainsKey(keys[iKey]));
Assert.IsTrue(dict.Contains(new KeyValuePair<TKey, ICollection<TValue>>(keys[iKey], values[iKey])));
bool b = ((IDictionary<TKey, ICollection<TValue>>)dict).TryGetValue(keys[iKey], out getValues);
Assert.IsTrue(b);
iValue = 0;
InterfaceTests.TestEnumerableElementsAnyOrder(getValues, values[iKey]);
iValue = 0;
foreach (TValue val in values[iKey]) {
Assert.IsTrue(dict.Contains(keys[iKey], val));
++iValue;
}
Assert.IsTrue(iValue == values[iKey].Length);
iValue = 0;
getValues = dict[keys[iKey]];
InterfaceTests.TestEnumerableElementsAnyOrder(getValues, values[iKey]);
}
// Check Keys collection.
InterfaceTests.TestReadonlyCollectionGeneric<TKey>(dict.Keys, keys, false, null, keyEquals);
// Check Values collection
int a = 0;
TValue[] vals = new TValue[dict.Values.Count];
for (iKey = 0; iKey < keys.Length; ++iKey) {
for (iValue = 0; iValue < values[iKey].Length; ++iValue) {
vals[a++] = values[iKey][iValue];
}
}
Assert.AreEqual(dict.Values.Count, a);
InterfaceTests.TestReadonlyCollectionGeneric<TValue>(dict.Values, vals, false, null, valueEquals);
// Check KeyValuePairs collection.
a = 0;
KeyValuePair<TKey, TValue>[] pairs = new KeyValuePair<TKey, TValue>[dict.Values.Count];
for (iKey = 0; iKey < keys.Length; ++iKey) {
for (iValue = 0; iValue < values[iKey].Length; ++iValue) {
pairs[a++] = new KeyValuePair<TKey, TValue>(keys[iKey], values[iKey][iValue]);
}
}
InterfaceTests.TestReadonlyCollectionGeneric<KeyValuePair<TKey, TValue>>(dict.KeyValuePairs, pairs, false, null, InterfaceTests.KeyValueEquals<TKey,TValue>(keyEquals,valueEquals));
// Tests Contains, ContainsKey, TryGetValue for wrong values.
Assert.IsFalse(dict.ContainsKey(nonKey));
Assert.IsFalse(((IDictionary<TKey, ICollection<TValue>>)dict).TryGetValue(nonKey, out getValues));
for (iKey = 0; iKey < keys.Length; ++iKey) {
Assert.IsFalse(dict.Contains(keys[iKey], nonValue));
Assert.IsFalse(dict.Contains(new KeyValuePair<TKey, ICollection<TValue>>(keys[iKey], new TValue[1] { nonValue })));
}
// Test IDictionary<TKey,IEnumerable<TValue>> implementation
InterfaceTests.TestReadWriteMultiDictionaryGeneric<TKey, TValue>(dict, keys, values, nonKey, nonValue, false, "MultiDictionary", keyEquals, valueEquals);
}
// Do random add,remove,replaces and create an array.
private int[,] AddRemoveRandom(Random rand, MultiDictionary<int, string> dict, bool useDups, int iter)
{
const int MAXKEY = 100, MAXVAL = 50;
int[,] counts = new int[MAXKEY, MAXVAL];
for (int x = 0; x < iter; ++x) {
int key = rand.Next(MAXKEY);
int val = rand.Next(MAXVAL);
string valString = string.Format("A{0:0000}", val);
if (counts[key, val] == 0) {
if (rand.Next(30) == 0) {
// Do a replace
dict.Replace(key, valString);
for (int i = 0; i < MAXVAL; ++i)
counts[key, i] = 0;
counts[key, val] = 1;
}
else {
// Do an add
dict.Add(key, valString);
counts[key, val] = 1;
}
}
else {
if (rand.Next(30) == 0) {
// Do a replace
dict.Replace(key, valString);
for (int i = 0; i < MAXVAL; ++i)
counts[key, i] = 0;
counts[key, val] = 1;
}
else if (rand.Next(5) < 2) {
// Do an add
dict.Add(key, valString);
if (useDups)
counts[key, val] += 1;
}
else {
// Do a remove
dict.Remove(key, valString);
counts[key, val] -= 1;
}
}
}
return counts;
}
// Check an ordered multi-dictionary against an array.
private void CheckAgainstArray(MultiDictionary<int, string> dict, int[,] array)
{
List<string[]> values = new List<string[]>();
List<int> keys = new List<int>();
List<string> vals = new List<string>();
for (int i = 0; i < array.GetLength(0); ++i) {
bool hasval = false;
for (int j = 0; j < array.GetLength(1); ++j) {
if (array[i, j] > 0) {
hasval = true;
for (int x = 0; x < array[i, j]; ++x)
vals.Add(string.Format("A{0:0000}", j));
}
}
if (hasval) {
keys.Add(i);
values.Add(vals.ToArray());
vals.Clear();
}
}
int[] keysArray = keys.ToArray();
string[][] valsArray = values.ToArray();
CheckMultiDictionaryContents<int, string>(dict,
keysArray,
valsArray,
-1, "Foo", null, null);
}
[Test]
public void RandomAdd()
{
Random rand = new Random(14);
MultiDictionary<int, string> dict = new MultiDictionary<int, string>(true);
int[,] array = AddRemoveRandom(rand, dict, true, 3000);
CheckAgainstArray(dict, array);
}
[Test]
public void Add()
{
// Test without duplicate values.
MultiDictionary<string, double> dict1 = new MultiDictionary<string, double>(false);
dict1.Add("foo", 3.5);
dict1.Add("foo", -1.2);
dict1.Add(null, 11.1);
dict1.Add("foo", 8.8);
dict1.Add(null, 11.1);
dict1.Add("bar", 9.8);
dict1.Add("foo", 8.8);
dict1.Add("gib", 7.1);
dict1.Add("S", -9);
dict1.Add(null, 5.5);
CheckMultiDictionaryContents<string, double>(dict1,
new string[] { null, "bar", "foo", "gib", "S" },
new double[][] { new double[] { 5.5, 11.1 }, new double[] { 9.8 }, new double[] { -1.2, 3.5, 8.8 }, new double[] { 7.1 }, new double[] { -9 } },
"zip", -100, null, null);
// Test with duplicate values.
dict1 = new MultiDictionary<string, double>(true);
dict1.Add("foo", 3.5);
dict1.Add("foo", -1.2);
dict1.Add(null, 11.1);
dict1.Add("foo", 8.8);
dict1.Add(null, 11.1);
dict1.Add("bar", 9.8);
dict1.Add("foo", 8.8);
dict1.Add("gib", 7.1);
dict1.Add("S", -9);
dict1.Add(null, 5.5);
CheckMultiDictionaryContents<string, double>(dict1,
new string[] { null, "bar", "foo", "gib", "S" },
new double[][] { new double[] { 5.5, 11.1, 11.1 }, new double[] { 9.8 }, new double[] { -1.2, 3.5, 8.8, 8.8 }, new double[] { 7.1 }, new double[] { -9 } },
"zip", -100, null, null);
// Test duplicate values with distinct equal values.
MultiDictionary<string, string> dict2 = new MultiDictionary<string, string>(false, StringComparer.InvariantCultureIgnoreCase, StringComparer.InvariantCultureIgnoreCase);
dict2.Add("foo", "BAR");
dict2.Add("Foo", "bar");
InterfaceTests.TestEnumerableElementsAnyOrder<string>(dict2.Keys, new string[] { "foo" });
InterfaceTests.TestEnumerableElementsAnyOrder<string>(dict2["FOO"], new string[] { "bar" });
dict2 = new MultiDictionary<string, string>(true, StringComparer.InvariantCultureIgnoreCase, StringComparer.InvariantCultureIgnoreCase);
dict2.Add("foo", "BAR");
dict2.Add("Foo", "bar");
InterfaceTests.TestEnumerableElementsAnyOrder<string>(dict2.Keys, new string[] { "foo" });
InterfaceTests.TestEnumerableElementsAnyOrder<string>(dict2["FOO"], new string[] { "BAR", "bar" });
InterfaceTests.TestEnumerableElementsAnyOrder<KeyValuePair<string, string>>
(dict2.KeyValuePairs, new KeyValuePair<string, string>[] { new KeyValuePair<string,string>("foo", "BAR"),
new KeyValuePair<string,string>("foo", "bar")}, InterfaceTests.KeyValueEquals<string, string>());
}
[Test]
public void AddMany1()
{
// Test without duplicate values.
MultiDictionary<string, double> dict1 = new MultiDictionary<string, double>(false, StringComparer.InvariantCultureIgnoreCase);
dict1.AddMany("foo", AlgorithmsTests.EnumerableFromArray(new double[] { 9.8, 1.2, -9, 9.8, -9, 4 }));
dict1.AddMany("hi", new double[0]);
dict1.AddMany("FOO", AlgorithmsTests.EnumerableFromArray(new double[] { 8, -9 }));
Assert.AreEqual(1, dict1.Count);
Assert.IsTrue(dict1.ContainsKey("foo"));
Assert.IsFalse(dict1.ContainsKey("hi"));
InterfaceTests.TestEnumerableElementsAnyOrder(dict1.Keys, new string[] { "foo" });
InterfaceTests.TestEnumerableElementsAnyOrder(dict1["fOo"], new double[] { -9, 1.2, 4, 8, 9.8 });
InterfaceTests.TestEnumerableElementsAnyOrder<KeyValuePair<string, double>>
(dict1.KeyValuePairs, new KeyValuePair<string, double>[] {
new KeyValuePair<string,double>("foo", -9),
new KeyValuePair<string,double>("foo", 1.2),
new KeyValuePair<string,double>("foo", 4),
new KeyValuePair<string,double>("foo",8),
new KeyValuePair<string,double>("foo",9.8)
});
// Test with duplicate values
dict1 = new MultiDictionary<string, double>(true, StringComparer.InvariantCultureIgnoreCase);
dict1.AddMany("foo", AlgorithmsTests.EnumerableFromArray(new double[] { 9.8, 1.2, -9, 9.8, -9, 4 }));
dict1.AddMany("hi", new double[0]);
dict1.AddMany("a", new double[] { 2, 1, 2 });
dict1.AddMany("FOO", AlgorithmsTests.EnumerableFromArray(new double[] { 8, -9 }));
Assert.AreEqual(2, dict1.Count);
Assert.IsTrue(dict1.ContainsKey("foo"));
Assert.IsFalse(dict1.ContainsKey("hi"));
InterfaceTests.TestEnumerableElementsAnyOrder(dict1.Keys, new string[] { "a", "foo" });
InterfaceTests.TestEnumerableElementsAnyOrder(dict1["fOo"], new double[] { -9, -9, -9, 1.2, 4, 8, 9.8, 9.8 });
InterfaceTests.TestEnumerableElementsAnyOrder<KeyValuePair<string, double>>
(dict1.KeyValuePairs, new KeyValuePair<string, double>[] {
new KeyValuePair<string,double>("a", 1),
new KeyValuePair<string,double>("a", 2),
new KeyValuePair<string,double>("a", 2),
new KeyValuePair<string,double>("foo", -9),
new KeyValuePair<string,double>("foo", -9),
new KeyValuePair<string,double>("foo", -9),
new KeyValuePair<string,double>("foo", 1.2),
new KeyValuePair<string,double>("foo", 4),
new KeyValuePair<string,double>("foo",8),
new KeyValuePair<string,double>("foo",9.8),
new KeyValuePair<string,double>("foo",9.8)
});
}
[Test]
public void Replace()
{
MultiDictionary<string, int> dict1 = new MultiDictionary<string, int>(true);
dict1.Add("foo", 4);
dict1.Add("bar", 7);
dict1.Add("foo", 6);
dict1.Add("z", 3);
dict1.Add("bar", 8);
dict1.Add("z", 3);
dict1.Add("foo", 1);
dict1.Replace("foo", 13);
dict1.Replace("z", 19);
dict1.Replace("hello", 193);
dict1.Replace("foo", 123);
dict1.Add("foo", 123);
CheckMultiDictionaryContents(dict1,
new string[] { "bar", "foo", "hello", "z" },
new int[][] { new int[] { 7, 8 }, new int[] { 123, 123 }, new int[] { 193 }, new int[] { 19 } },
"sailor", 19921, null, null);
}
[Test]
public void ReplaceMany()
{
MultiDictionary<string, int> dict1 = new MultiDictionary<string, int>(false);
dict1.Add("foo", 4);
dict1.Add("bar", 7);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -