From e58421b2c2b509aba53c8d0cf0db674bee73f26c Mon Sep 17 00:00:00 2001 From: neuecc Date: Thu, 12 Aug 2021 18:48:34 +0900 Subject: [PATCH] list and dict test ok --- .../IObservableCollection.cs | 2 + .../Internal/FreezedView.cs | 4 +- .../ObservableDictionaryTest.cs | 55 +++++++++++++ .../ObservableListTest.cs | 82 +++++++++++++++++++ .../ViewContainer.cs | 80 ++++++++++++++++++ 5 files changed, 221 insertions(+), 2 deletions(-) diff --git a/src/ObservableCollections/IObservableCollection.cs b/src/ObservableCollections/IObservableCollection.cs index 942ccef..d706aa0 100644 --- a/src/ObservableCollections/IObservableCollection.cs +++ b/src/ObservableCollections/IObservableCollection.cs @@ -26,7 +26,9 @@ namespace ObservableCollections public interface ISynchronizedView : IReadOnlyCollection<(T Value, TView View)>, IDisposable { + // TODO:Remove SyncRoot object SyncRoot { get; } + event NotifyCollectionChangedEventHandler? RoutingCollectionChanged; event Action? CollectionStateChanged; diff --git a/src/ObservableCollections/Internal/FreezedView.cs b/src/ObservableCollections/Internal/FreezedView.cs index 1a2fd52..0051081 100644 --- a/src/ObservableCollections/Internal/FreezedView.cs +++ b/src/ObservableCollections/Internal/FreezedView.cs @@ -45,7 +45,7 @@ namespace ObservableCollections.Internal this.filter = filter; foreach (var (value, view) in list) { - filter.Invoke(value, view); + filter.InvokeOnAttach(value, view); } } } @@ -125,7 +125,7 @@ namespace ObservableCollections.Internal this.filter = filter; foreach (var (value, view) in array) { - filter.Invoke(value, view); + filter.InvokeOnAttach(value, view); } } } diff --git a/tests/ObservableCollections.Tests/ObservableDictionaryTest.cs b/tests/ObservableCollections.Tests/ObservableDictionaryTest.cs index 170a8c4..15c58bb 100644 --- a/tests/ObservableCollections.Tests/ObservableDictionaryTest.cs +++ b/tests/ObservableCollections.Tests/ObservableDictionaryTest.cs @@ -99,5 +99,60 @@ namespace ObservableCollections.Tests view.Select(x => x.Value.Value).Should().Equal(60, 50, 40, 30, 20, 10); view.Select(x => x.View).Should().Equal(60, 50, 40, 30, 20, 10); } + + [Fact] + public void FilterTest() + { + var dict = new ObservableDictionary(); + var view1 = dict.CreateView(x => new ViewContainer(x.Value)); + var view2 = dict.CreateSortedView(x => x.Key, x => new ViewContainer(x.Value), x => x.Value, true); + var view3 = dict.CreateSortedView(x => new ViewContainer(x.Value), viewComparer: Comparer>.Default); + var filter1 = new TestFilter2((x, v) => x.Value % 2 == 0); + var filter2 = new TestFilter2((x, v) => x.Value % 2 == 0); + var filter3 = new TestFilter2((x, v) => x.Value % 2 == 0); + + dict.Add(10, -12); // 0 + dict.Add(50, -53); // 1 + dict.Add(30, -34); // 2 + dict.Add(20, -25); // 3 + dict.Add(40, -40); // 4 + + view1.AttachFilter(filter1); + view2.AttachFilter(filter2); + view3.AttachFilter(filter3); + + filter1.CalledWhenTrue.Select(x => x.Item1.Value).Should().Equal(-12, -34, -40); + filter2.CalledWhenTrue.Select(x => x.Item1.Value).Should().Equal(-40, -34, -12); + filter3.CalledWhenTrue.Select(x => x.Item1.Value).Should().Equal(-40, -34, -12); + + dict.Add(99, -100); + filter1.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value.Value)).Should().Equal((ChangedKind.Add, -100)); + filter2.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value.Value)).Should().Equal((ChangedKind.Add, -100)); + filter3.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value.Value)).Should().Equal((ChangedKind.Add, -100)); + foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); + + dict[10] = -1090; + filter1.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value.Value)).Should().Equal((ChangedKind.Remove, -12), (ChangedKind.Add, -1090)); + filter2.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value.Value)).Should().Equal((ChangedKind.Remove, -12), (ChangedKind.Add, -1090)); + filter3.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value.Value)).Should().Equal((ChangedKind.Remove, -12), (ChangedKind.Add, -1090)); + foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); + + dict.Remove(20); + filter1.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value.Value)).Should().Equal((ChangedKind.Remove, -25)); + filter2.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value.Value)).Should().Equal((ChangedKind.Remove, -25)); + filter3.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value.Value)).Should().Equal((ChangedKind.Remove, -25)); + foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); + + dict.Clear(); + filter1.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value.Value)) + .OrderBy(x => x.Value) + .Should().Equal((ChangedKind.Remove, -1090), (ChangedKind.Remove, -100), (ChangedKind.Remove, -53), (ChangedKind.Remove, -40), (ChangedKind.Remove, -34)); + filter2.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value.Value)) + .OrderBy(x => x.Value) + .Should().Equal((ChangedKind.Remove, -1090), (ChangedKind.Remove, -100), (ChangedKind.Remove, -53), (ChangedKind.Remove, -40), (ChangedKind.Remove, -34)); + filter3.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value.Value)) + .OrderBy(x => x.Value) + .Should().Equal((ChangedKind.Remove, -1090), (ChangedKind.Remove, -100), (ChangedKind.Remove, -53), (ChangedKind.Remove, -40), (ChangedKind.Remove, -34)); + } } } diff --git a/tests/ObservableCollections.Tests/ObservableListTest.cs b/tests/ObservableCollections.Tests/ObservableListTest.cs index 4f52710..e4acbac 100644 --- a/tests/ObservableCollections.Tests/ObservableListTest.cs +++ b/tests/ObservableCollections.Tests/ObservableListTest.cs @@ -136,5 +136,87 @@ namespace ObservableCollections.Tests view.Select(x => x.Value).Should().Equal(60, 50, 40, 30, 20, 10); view.Select(x => x.View).Should().Equal(60, 50, 40, 30, 20, 10); } + + [Fact] + public void FilterTest() + { + var list = new ObservableList(); + var view1 = list.CreateView(x => new ViewContainer(x)); + var view2 = list.CreateSortedView(x => x, x => new ViewContainer(x), comparer: Comparer.Default); + var view3 = list.CreateSortedView(x => x, x => new ViewContainer(x), viewComparer: Comparer>.Default); + list.AddRange(new[] { 10, 21, 30, 44, 45, 66, 90 }); + + var filter1 = new TestFilter((x, v) => x % 2 == 0); + var filter2 = new TestFilter((x, v) => x % 2 == 0); + var filter3 = new TestFilter((x, v) => x % 2 == 0); + view1.AttachFilter(filter1); + view2.AttachFilter(filter2); + view3.AttachFilter(filter3); + + filter1.CalledWhenTrue.Select(x => x.Item1).Should().Equal(10, 30, 44, 66, 90); + filter2.CalledWhenTrue.Select(x => x.Item1).Should().Equal(10, 30, 44, 66, 90); + filter3.CalledWhenTrue.Select(x => x.Item1).Should().Equal(10, 30, 44, 66, 90); + + filter1.CalledWhenFalse.Select(x => x.Item1).Should().Equal(21, 45); + filter2.CalledWhenFalse.Select(x => x.Item1).Should().Equal(21, 45); + filter3.CalledWhenFalse.Select(x => x.Item1).Should().Equal(21, 45); + + view1.Select(x => x.Value).Should().Equal(10, 30, 44, 66, 90); + view2.Select(x => x.Value).Should().Equal(10, 30, 44, 66, 90); + view3.Select(x => x.Value).Should().Equal(10, 30, 44, 66, 90); + + filter1.Clear(); + filter2.Clear(); + filter3.Clear(); + + list.Add(100); + list.AddRange(new[] { 101 }); + filter1.CalledWhenTrue.Select(x => x.Item1).Should().Equal(100); + filter2.CalledWhenTrue.Select(x => x.Item1).Should().Equal(100); + filter3.CalledWhenTrue.Select(x => x.Item1).Should().Equal(100); + filter1.CalledWhenFalse.Select(x => x.Item1).Should().Equal(101); + filter2.CalledWhenFalse.Select(x => x.Item1).Should().Equal(101); + filter3.CalledWhenFalse.Select(x => x.Item1).Should().Equal(101); + + filter1.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Add, 100), (ChangedKind.Add, 101)); + filter2.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Add, 100), (ChangedKind.Add, 101)); + filter3.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Add, 100), (ChangedKind.Add, 101)); + + foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); + + list.Insert(0, 1000); + list.InsertRange(0, new[] { 999 }); + + filter1.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Add, 1000), (ChangedKind.Add, 999)); + filter2.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Add, 1000), (ChangedKind.Add, 999)); + filter3.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Add, 1000), (ChangedKind.Add, 999)); + foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); + + list.RemoveAt(0); + list.RemoveRange(0, 1); + + filter1.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Remove, 999), (ChangedKind.Remove, 1000)); + filter2.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Remove, 999), (ChangedKind.Remove, 1000)); + filter3.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Remove, 999), (ChangedKind.Remove, 1000)); + foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); + + list[0] = 9999; + + filter1.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Remove, 10), (ChangedKind.Add, 9999)); + filter2.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Remove, 10), (ChangedKind.Add, 9999)); + filter3.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Remove, 10), (ChangedKind.Add, 9999)); + foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); + + list.Move(3, 0); + filter1.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Move, 44)); + filter2.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Move, 44)); + filter3.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Move, 44)); + foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); + + list.Clear(); + filter1.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Remove, 44), (ChangedKind.Remove, 9999), (ChangedKind.Remove, 21), (ChangedKind.Remove, 30), (ChangedKind.Remove, 45), (ChangedKind.Remove, 66), (ChangedKind.Remove, 90), (ChangedKind.Remove, 100), (ChangedKind.Remove, 101)); + filter2.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Remove, 21), (ChangedKind.Remove, 30), (ChangedKind.Remove, 44), (ChangedKind.Remove, 45), (ChangedKind.Remove, 66), (ChangedKind.Remove, 90), (ChangedKind.Remove, 100), (ChangedKind.Remove, 101), (ChangedKind.Remove, 9999)); + filter3.CalledOnCollectionChanged.Select(x => (x.changedKind, x.value)).Should().Equal((ChangedKind.Remove, 21), (ChangedKind.Remove, 30), (ChangedKind.Remove, 44), (ChangedKind.Remove, 45), (ChangedKind.Remove, 66), (ChangedKind.Remove, 90), (ChangedKind.Remove, 100), (ChangedKind.Remove, 101), (ChangedKind.Remove, 9999)); + } } } diff --git a/tests/ObservableCollections.Tests/ViewContainer.cs b/tests/ObservableCollections.Tests/ViewContainer.cs index e574a60..d6f26e3 100644 --- a/tests/ObservableCollections.Tests/ViewContainer.cs +++ b/tests/ObservableCollections.Tests/ViewContainer.cs @@ -29,4 +29,84 @@ namespace ObservableCollections.Tests return EqualityComparer.Default.Equals(Value, other.Value); } } + + public class TestFilter : ISynchronizedViewFilter> + { + readonly Func, bool> filter; + public List<(T, ViewContainer)> CalledWhenTrue = new(); + public List<(T, ViewContainer)> CalledWhenFalse = new(); + public List<(ChangedKind changedKind, T value, ViewContainer view)> CalledOnCollectionChanged = new(); + + public TestFilter(Func, bool> filter) + { + this.filter = filter; + } + + public void Clear() + { + CalledWhenTrue.Clear(); + CalledWhenFalse.Clear(); + CalledOnCollectionChanged.Clear(); + } + + public bool IsMatch(T value, ViewContainer view) + { + return this.filter.Invoke(value, view); + } + + public void OnCollectionChanged(ChangedKind changedKind, T value, ViewContainer view) + { + CalledOnCollectionChanged.Add((changedKind, value, view)); + } + + public void WhenTrue(T value, ViewContainer view) + { + CalledWhenTrue.Add((value, view)); + } + + public void WhenFalse(T value, ViewContainer view) + { + CalledWhenFalse.Add((value, view)); + } + } + + public class TestFilter2 : ISynchronizedViewFilter, ViewContainer> + { + readonly Func, ViewContainer, bool> filter; + public List<(KeyValuePair, ViewContainer)> CalledWhenTrue = new(); + public List<(KeyValuePair, ViewContainer)> CalledWhenFalse = new(); + public List<(ChangedKind changedKind, KeyValuePair value, ViewContainer view)> CalledOnCollectionChanged = new(); + + public TestFilter2(Func, ViewContainer, bool> filter) + { + this.filter = filter; + } + + public void Clear() + { + CalledWhenTrue.Clear(); + CalledWhenFalse.Clear(); + CalledOnCollectionChanged.Clear(); + } + + public bool IsMatch(KeyValuePair value, ViewContainer view) + { + return this.filter.Invoke(value, view); + } + + public void OnCollectionChanged(ChangedKind changedKind, KeyValuePair value, ViewContainer view) + { + CalledOnCollectionChanged.Add((changedKind, value, view)); + } + + public void WhenTrue(KeyValuePair value, ViewContainer view) + { + CalledWhenTrue.Add((value, view)); + } + + public void WhenFalse(KeyValuePair value, ViewContainer view) + { + CalledWhenFalse.Add((value, view)); + } + } }