public void ListChangingExceptionVetoesChanges() { if (!this._testExceptions) { return; } List <T> list; AList alist = this.NewList(100, out list); this.RemoveFromBoth(alist, list, 10); // ListChanging could throw an exception, which blocks changes. // We are also testing that alist doesn't go into an invalid state. ListChangingHandler <T> veto = (sender, args) => { throw new SuccessException("veto test"); }; alist.ListChanging += veto; AssertThrows <SuccessException>(() => alist.RemoveAt(10)); AssertThrows <SuccessException>(() => alist.RemoveRange(10, 80)); ExpectList(alist, list, false); AssertThrows <SuccessException>(() => this.AddToBoth(alist, list, 10, 10)); ExpectList(alist, list, true); // We can remove the veto and then changes should succeed. alist.ListChanging -= veto; this.RemoveAtInBoth(alist, list, 10); ExpectList(alist, list, false); this.AddToBoth(alist, list, 10, 10); ExpectList(alist, list, true); }
public void TestClear() { List <T> list; int sizeChange = 0; ListChangingHandler <T> clearCheck = (sender, args) => { Assert.AreEqual(NotifyCollectionChangedAction.Remove, args.Action); Assert.AreEqual(0, args.Index); sizeChange += args.SizeChange; }; AList alist = this.NewList(1, out list); alist.ListChanging += clearCheck; alist.Clear(); ExpectList(alist); alist = this.NewList(10, out list); alist.ListChanging += clearCheck; alist.Clear(); ExpectList(alist); alist = this.NewList(100, out list); alist.ListChanging += clearCheck; alist.Clear(); ExpectList(alist); Assert.AreEqual(-111, sizeChange); }
private void CheckListChange <Dict, K, V>(Dict list, Action <Dict> act, bool checkChangedEvent, bool expectEvent, IEnumerable <KeyValuePair <K, V> > newItems, IEnumerable <KeyValuePair <K, V> > oldItems, params KeyValuePair <K, V>[] listDuringEvent) where Dict : IDictionaryWithChangeEvents <K, V> { int numEvents = 0; ListChangingHandler <KeyValuePair <K, V>, IDictionary <K, V> > handler = (sender, args) => { numEvents++; ExpectList(args.OldItems, oldItems); ExpectList(args.NewItems, newItems); ExpectList(sender, listDuringEvent); AreEqual(int.MinValue, args.Index); AreEqual(args.SizeChange, args.NewItems.Count - args.OldItems.Count); }; if (checkChangedEvent) { list.ListChanged += handler; act(list); list.ListChanged -= handler; } else { list.ListChanging += handler; act(list); list.ListChanging -= handler; } if (expectEvent) { AreEqual(1, numEvents); } else { AreEqual(0, numEvents); } }
private void CheckListChange<List,T>(List list, Action<List> act, int index, bool checkChangedEvent, bool expectEvent, IEnumerable<T> newItems, IEnumerable<T> oldItems, params T[] listDuringEvent) where List:IListWithChangeEvents<T> { int numEvents = 0; ListChangingHandler<T, IListSource<T>> handler = (sender, args) => { numEvents++; ExpectList(args.OldItems, oldItems); ExpectList(args.NewItems, newItems); ExpectList(sender, listDuringEvent); AreEqual(index, args.Index); AreEqual(args.SizeChange, args.NewItems.Count - args.OldItems.Count); }; if (checkChangedEvent) { list.ListChanged += handler; act(list); list.ListChanged -= handler; } else { list.ListChanging += handler; act(list); list.ListChanging -= handler; } if (expectEvent) AreEqual(1, numEvents); else AreEqual(0, numEvents); }
AList <int> NewList(int start, int count, ListChangingHandler <int> observer) { AList <int> list = new AList <int>(this._maxLeafSize, this._maxInnerSize); for (int i = 0; i < count; i++) { list.Add(start + i); } if (observer != null) { list.ListChanging += observer; } return(list); }
SparseAList <int> NewList(int start, int count, ListChangingHandler <int> observer, out List <int> list) { var alist = new SparseAList <int>(_maxLeafSize, _maxInnerSize); list = new List <int>(); for (int i = 0; i < count; i++) { if (_r.Next(2) == 0) { alist.Add(start + i); list.Add(start + i); } else { alist.InsertSpace(i); list.Add(0); } } if (observer != null) { alist.ListChanging += observer; } return(alist); }
public void CloneAndObserveChanges() { List <T> list1, list2; AList alist1 = this.NewList(200, out list1); AList alist2 = alist1.Clone(); list2 = new List <T>(list1); // This test checks two separate issues that shouldn't interact, but // could interact in case of a bug: // (1) It checks whether list change events are sent and contain the // correct information // (2) It checks whether cloned lists can be modified independently. int changeIndex = -1, changeItem = -1, sizeChange = 0; ListChangingHandler <T> changeHandler = (sender, args) => { Assert.AreEqual(sizeChange, args.SizeChange); sizeChange = 0; Assert.AreEqual(changeIndex, args.Index); // Note: change notifications are sent before the add/remove happens if (sizeChange > 0) { Assert.AreEqual(NotifyCollectionChangedAction.Add, args.Action); Assert.That(args.NewItems != null && args.NewItems.Count == 1); Assert.AreEqual(changeItem, this.GetKey(args.NewItems[0])); } else if (sizeChange < 0) { Assert.AreEqual(NotifyCollectionChangedAction.Remove, args.Action); Assert.AreEqual(changeItem, this.GetKey(sender[args.Index])); } }; alist1.ListChanging += changeHandler; alist2.ListChanging += changeHandler; int nextNew = 1000; int i = 0; while (alist1.Count > 0) { // Modify first list sizeChange += -1; changeItem = this.GetKey(alist1[changeIndex = this._r.Next(alist1.Count)]); this.RemoveAtInBoth(alist1, list1, changeIndex); // Modify second list sizeChange += 1; this.AddToBoth(alist2, list2, changeItem = nextNew++, changeIndex = alist2.Count); sizeChange += -1; changeItem = this.GetKey(alist2[changeIndex = this._r.Next(alist2.Count)]); this.RemoveAtInBoth(alist2, list2, changeIndex); // verify results at every power of 2 if (MathEx.CountOnes(++i) == 1 || alist1.Count == 0) { ExpectList(alist1, list1, (i & 1) == 0); ExpectList(alist2, list2, (i & 1) == 0); } } // Call changeHandler again to verify that all notifications were sent changeIndex = 0; changeHandler(alist1, new ListChangeInfo <T>(NotifyCollectionChangedAction.Reset, 0, 0, null)); }