summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core.UnitTests/ListProxyTests.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Core.UnitTests/ListProxyTests.cs')
-rw-r--r--Xamarin.Forms.Core.UnitTests/ListProxyTests.cs426
1 files changed, 426 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core.UnitTests/ListProxyTests.cs b/Xamarin.Forms.Core.UnitTests/ListProxyTests.cs
new file mode 100644
index 00000000..6fa85d2c
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ListProxyTests.cs
@@ -0,0 +1,426 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ListProxyTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void ListCount()
+ {
+ var list = new List<string> { "foo", "bar" };
+ var proxy = new ListProxy (list);
+
+ Assert.AreEqual (list.Count, proxy.Count);
+ list.Add ("baz");
+ Assert.AreEqual (list.Count, proxy.Count);
+ }
+
+ [Test]
+ public void CollectionCount()
+ {
+ var list = new Collection<string> { "foo", "bar" };
+ var proxy = new ListProxy (list);
+
+ Assert.AreEqual (list.Count, proxy.Count);
+ list.Add ("baz");
+ Assert.AreEqual (list.Count, proxy.Count);
+ }
+
+ [Test]
+ [Description ("Count should ensure that the window is created if neccessary")]
+ public void EnumerableInitialCount()
+ {
+ var enumerable = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (enumerable, 10);
+
+ Assert.AreEqual (10, proxy.Count);
+ }
+
+ [Test]
+ public void EnumerableCount()
+ {
+ var enumerable = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (enumerable, 10);
+
+ int changed = 0;
+ proxy.CountChanged += (o, e) => changed++;
+
+ var enumerator = proxy.GetEnumerator();
+ enumerator.MoveNext();
+
+ Assert.AreEqual (10, proxy.Count);
+ Assert.AreEqual (1, changed);
+
+ enumerator.MoveNext();
+
+ Assert.AreEqual (10, proxy.Count);
+ Assert.AreEqual (1, changed);
+
+ while (enumerator.MoveNext()) {
+ }
+
+ enumerator.Dispose();
+
+ Assert.AreEqual (100, proxy.Count);
+ Assert.AreEqual (19, changed);
+
+ using (enumerator = proxy.GetEnumerator()) {
+
+ Assert.AreEqual (100, proxy.Count);
+
+ while (enumerator.MoveNext())
+ Assert.AreEqual (100, proxy.Count);
+
+ Assert.AreEqual (100, proxy.Count);
+ }
+
+ Assert.AreEqual (19, changed);
+ }
+
+ [Test]
+ public void InsideWindowSize()
+ {
+ var numbers = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (numbers, 10);
+
+ int i = (int)proxy[5];
+ Assert.That (i, Is.EqualTo (5));
+ }
+
+ [Test]
+ public void IndexOutsideWindowSize()
+ {
+ var numbers = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (numbers, 10);
+
+ int i = (int)proxy[50];
+ Assert.That (i, Is.EqualTo (50));
+ }
+
+ [Test]
+ public void IndexInsideToOutsideWindowSize()
+ {
+ var numbers = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (numbers, 10);
+
+ int i = (int)proxy[5];
+ Assert.That (i, Is.EqualTo (5));
+
+ i = (int)proxy[50];
+ Assert.That (i, Is.EqualTo (50));
+ }
+
+ [Test]
+ public void IndexOutsideToPreWindowSize()
+ {
+ var numbers = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (numbers, 10);
+
+ int i = (int)proxy[50];
+ Assert.That (i, Is.EqualTo (50));
+
+ i = (int)proxy[5];
+ Assert.That (i, Is.EqualTo (5));
+ }
+
+ [Test]
+ public void EnumerableIndexOutOfRange()
+ {
+ var numbers = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (numbers);
+
+ Assert.That (() => proxy[100], Throws.InstanceOf<ArgumentOutOfRangeException>());
+ }
+
+ class IntCollection
+ : ICollection
+ {
+ readonly List<int> ints;
+
+ public IntCollection (IEnumerable<int> ints)
+ {
+ this.ints = ints.ToList();
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return ints.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public void CopyTo (Array array, int index)
+ {
+ throw new NotImplementedException();
+ }
+
+ public int Count { get { return ints.Count; }}
+
+ public object SyncRoot
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public bool IsSynchronized
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public bool IsReadOnly { get { return true; } }
+ }
+
+ [Test]
+ public void CollectionIndexOutOfRange()
+ {
+ var numbers = new IntCollection (Enumerable.Range (0, 100));
+ var proxy = new ListProxy (numbers);
+
+ Assert.That (() => proxy[100], Throws.InstanceOf<ArgumentOutOfRangeException>());
+ }
+
+ [Test]
+ public void ListIndexOutOfRange()
+ {
+ var numbers = Enumerable.Range (0, 100).ToList();
+ var proxy = new ListProxy (numbers);
+
+ Assert.That (() => proxy[100], Throws.InstanceOf<ArgumentOutOfRangeException>());
+ }
+
+ [Test]
+ public void CollectionChangedWhileEnumerating()
+ {
+ var c = new ObservableCollection<string> { "foo", "bar" };
+ var p = new ListProxy (c);
+
+ IEnumerator<object> e = p.GetEnumerator();
+ Assert.IsTrue (e.MoveNext(), "Initial MoveNext() failed, test can't continue");
+
+ c.Add ("baz");
+
+ Assert.That (() => e.MoveNext(), Throws.InvalidOperationException,
+ "MoveNext did not throw an exception when the underlying collection had changed");
+ }
+
+ [Test]
+ public void SynchronizedCollectionAccess()
+ {
+ var collection = new ObservableCollection<string> { "foo" };
+ var context = new object();
+
+ var list = new ListProxy (collection);
+
+ bool executed = false;
+ BindingBase.EnableCollectionSynchronization (collection, context, (enumerable, o, method, access) => {
+ executed = true;
+ Assert.AreSame (collection, enumerable);
+ Assert.AreSame (context, o);
+ Assert.IsNotNull (method);
+ Assert.IsFalse (access);
+
+ lock (enumerable)
+ method();
+ });
+
+ object value = list[0];
+
+ Assert.IsTrue (executed, "Callback was not executed");
+ }
+
+ [Test]
+ public void SynchronizedCollectionAdd()
+ {
+ bool invoked = false;
+ Device.PlatformServices = new MockPlatformServices (invokeOnMainThread: action => {
+ invoked = true;
+ action();
+ });
+
+ var collection = new ObservableCollection<string> { "foo" };
+ var context = new object();
+
+ var list = new ListProxy (collection);
+
+ Assert.IsFalse (invoked, "An invoke shouldn't be executed just setting up ListProxy");
+
+ bool executed = false;
+ BindingBase.EnableCollectionSynchronization (collection, context, (enumerable, o, method, access) => {
+ executed = true;
+ Assert.AreSame (collection, enumerable);
+ Assert.AreSame (context, o);
+ Assert.IsNotNull (method);
+ Assert.IsFalse (access);
+
+ lock (enumerable)
+ method();
+ });
+
+ var mre = new ManualResetEvent (false);
+
+ Task.Factory.StartNew (() => {
+ lock (collection)
+ collection.Add ("foo");
+
+ mre.Set();
+ }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+
+ mre.WaitOne (5000);
+
+ Assert.IsTrue (executed, "Callback was not executed");
+ Assert.IsTrue (invoked, "Callback was not executed on the UI thread");
+ }
+
+ [Test]
+ public void ClearEnumerable()
+ {
+ var proxy = new ListProxy (Enumerable.Range (0, 100));
+ var enumerator = proxy.GetEnumerator();
+ enumerator.MoveNext();
+ enumerator.MoveNext();
+
+ proxy.Clear();
+
+ Assert.AreEqual (100, proxy.Count);
+ Assert.That (() => enumerator.MoveNext(), Throws.InvalidOperationException);
+ }
+
+ [Test]
+ public void ClearCollection()
+ {
+ var proxy = new ListProxy (new IntCollection (Enumerable.Range (0, 100)));
+ var enumerator = proxy.GetEnumerator();
+ enumerator.MoveNext();
+ enumerator.MoveNext();
+
+ proxy.Clear();
+
+ Assert.AreEqual (100, proxy.Count);
+ Assert.That (() => enumerator.MoveNext(), Throws.InvalidOperationException);
+ }
+
+ [Test]
+ public void ClearList()
+ {
+ var proxy = new ListProxy (Enumerable.Range (0, 100).ToList());
+ var enumerator = proxy.GetEnumerator();
+ enumerator.MoveNext();
+ enumerator.MoveNext();
+
+ proxy.Clear();
+
+ Assert.AreEqual (100, proxy.Count);
+ Assert.That (() => enumerator.MoveNext(), Throws.InvalidOperationException);
+ }
+
+ [Test]
+ public void IndexOfValueTypeNonList()
+ {
+ var proxy = new ListProxy (Enumerable.Range (0, 100));
+ Assert.AreEqual (1, proxy.IndexOf (1));
+ }
+
+ [Test]
+ public void EnumeratorForEnumerable()
+ {
+ var proxy = new ListProxy (Enumerable.Range (0, 2));
+
+ var enumerator = proxy.GetEnumerator();
+ Assert.That (enumerator.Current, Is.Null);
+ Assert.That (enumerator.MoveNext(), Is.True);
+ Assert.That (enumerator.Current, Is.EqualTo (0));
+ Assert.That (enumerator.MoveNext(), Is.True);
+ Assert.That (enumerator.Current, Is.EqualTo (1));
+ Assert.That (enumerator.MoveNext(), Is.False);
+ }
+
+ [Test]
+ public void ProxyIsWeaklyHeldByINotifyCollectionChanged()
+ {
+ ObservableCollection<string> collection = new ObservableCollection<string>();
+
+ WeakReference weakProxy = null;
+
+ int i = 0;
+ Action create = null;
+ create = () => {
+ if (i++ < 1024) {
+ create();
+ return;
+ }
+
+ var proxy = new ListProxy (collection);
+ weakProxy = new WeakReference (proxy);
+ };
+
+ create();
+
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ GC.Collect();
+
+ Assert.That (weakProxy.IsAlive, Is.False);
+ }
+
+ [Test]
+ public void IEnumerableAddDoesNotReport0()
+ {
+ var custom = new CustomINCC();
+ custom.Add ("test");
+ custom.Add ("test2");
+
+ var proxy = new ListProxy (custom);
+ Assert.That (proxy.Count, Is.EqualTo (2));
+
+ custom.Add ("testing");
+ Assert.That (proxy.Count, Is.EqualTo (3));
+ }
+
+ class CustomINCC : IEnumerable<string>, INotifyCollectionChanged
+ {
+ public event NotifyCollectionChangedEventHandler CollectionChanged;
+ List<string> Items = new List<string> ();
+
+ public void Add (string s)
+ {
+ Items.Add(s);
+ if (CollectionChanged != null)
+ CollectionChanged (this, new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Add, s));
+ }
+
+ public IEnumerator<string> GetEnumerator ()
+ {
+ return Items.GetEnumerator ();
+ }
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
+ return Items.GetEnumerator ();
+ }
+ }
+ }
+}