//[Theory] //[InlineData(null)] //[InlineData(typeof(CustomEqualityComparerDummyRefType))] public async Task DictionaryDevConcurrentAccessDetection_ReferenceTypeKey(Type comparerType) { IEqualityComparer <DummyRefType> customComparer = null; DictionaryDev <DummyRefType, DummyRefType> dic = comparerType == null ? new DictionaryDev <DummyRefType, DummyRefType>() : new DictionaryDev <DummyRefType, DummyRefType>((customComparer = (IEqualityComparer <DummyRefType>)Activator.CreateInstance(comparerType))); var keyValueSample = new DummyRefType() { Value = 1 }; dic.Add(keyValueSample, keyValueSample); await DictionaryDevConcurrentAccessDetection(dic, typeof(DummyRefType).IsValueType, customComparer, d => d.Add(keyValueSample, keyValueSample), d => { var v = d[keyValueSample]; }, d => d.Remove(keyValueSample), d => d.Remove(keyValueSample, out DummyRefType value), d => d.RemoveAll(kvp => true) ); }
private async Task DictionaryDevConcurrentAccessDetection <TKey, TValue>(DictionaryDev <TKey, TValue> dictionary, bool isValueType, object comparer, Action <DictionaryDev <TKey, TValue> > add, Action <DictionaryDev <TKey, TValue> > get, Action <DictionaryDev <TKey, TValue> > remove, Action <DictionaryDev <TKey, TValue> > removeOutParam, Action <DictionaryDev <TKey, TValue> > removeAll) { Task task = Task.Factory.StartNew(() => { // Get the DictionaryDev into a corrupted state, as if it had been corrupted by concurrent access. // We this deterministically by clearing the _entries array using reflection; // this means that every Entry struct has a 'next' field of zero, which causes the infinite loop // that we want DictionaryDev to break out of FieldInfo entriesType = dictionary.GetType().GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance); Array entriesInstance = (Array)entriesType.GetValue(dictionary); //Array entryArray = (Array)Activator.CreateInstance(entriesInstance.GetType(), new object[] { entriesInstance.Length }); //entriesType.SetValue(dictionary, entryArray); var entryType = entriesType.GetValue(dictionary).GetType().GetElementType(); var nextField = entryType.GetField("next"); int firstNext = 0; for (int index = 0; index < entriesInstance.Length; index += 1) { //int next = (int)nextField.GetValue(entriesInstance.GetValue(index)); //if (next!=0) //{ // if (firstNext==0) // { // firstNext=next; // } // else // { // nextField.SetValue(entriesInstance.GetValue(index), firstNext); // } //} nextField.SetValue(entriesInstance.GetValue(index), 0); } //Assert.Equal(comparer, dictionary.GetType().GetField("_comparer", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(dictionary)); //Assert.Equal(isValueType, dictionary.GetType().GetGenericArguments()[0].IsValueType); //Assert.Equal("ThrowInvalidOperationException_ConcurrentOperationsNotSupported", Assert.Throws<InvalidOperationException>(() => add(dictionary)).TargetSite.Name); //Assert.Equal("ThrowInvalidOperationException_ConcurrentOperationsNotSupported", Assert.Throws<InvalidOperationException>(() => get(dictionary)).TargetSite.Name); //Assert.Equal("ThrowInvalidOperationException_ConcurrentOperationsNotSupported", Assert.Throws<InvalidOperationException>(() => remove(dictionary)).TargetSite.Name); //Assert.Equal("ThrowInvalidOperationException_ConcurrentOperationsNotSupported", Assert.Throws<InvalidOperationException>(() => removeOutParam(dictionary)).TargetSite.Name); Assert.Equal("ThrowInvalidOperationException_ConcurrentOperationsNotSupported", Assert.Throws <InvalidOperationException>(() => removeAll(dictionary)).TargetSite.Name); }, TaskCreationOptions.LongRunning); // If DictionaryDev regresses, we do not want to hang here indefinitely Assert.True((await Task.WhenAny(task, Task.Delay(TimeSpan.FromSeconds(60))) == task) && task.IsCompletedSuccessfully); }
public void Setup() { keys = new int[10000]; values = new object[keys.Length]; for (int index = 0; index < keys.Length; index += 1) { keys[index] = index; values[index] = new object(); } devDict = new DictionaryDev <int, object>(keys.Length); refDict = new DictionaryRef <int, object>(keys.Length); //for (int index = 0; index<keys.Length; index+=1) //{ // devDict.Add(keys[index], values[index]); // refDict.Add(keys[index], values[index]); //} }
//[Theory] //[InlineData(null)] //[InlineData(typeof(CustomEqualityComparerInt32ValueType))] public async Task DictionaryDevConcurrentAccessDetection_ValueTypeKey(Type comparerType) { IEqualityComparer <int> customComparer = null; DictionaryDev <int, int> dic = comparerType == null ? new DictionaryDev <int, int>() : new DictionaryDev <int, int>((customComparer = (IEqualityComparer <int>)Activator.CreateInstance(comparerType))); dic.Add(1, 1); dic.Add(4, 2); await DictionaryDevConcurrentAccessDetection(dic, typeof(int).IsValueType, customComparer, d => d.Add(1, 1), d => { var v = d[1]; }, d => d.Remove(1), d => d.Remove(1, out int value), d => d.RemoveAll(kvp => true) ); }