Bläddra i källkod

Additional tests; use FluentAssertions for it's collection testing and diagnostic ability

Oren Novotny 9 år sedan
förälder
incheckning
cb05cf3472

+ 3 - 0
Ix.NET/Source/System.Interactive.Tests.Uwp.DeviceRunner/System.Interactive.Tests.Uwp.DeviceRunner.csproj

@@ -198,6 +198,9 @@
     <Reference Include="System.Interactive.Providers">
       <HintPath>..\System.Interactive.Providers\bin\$(Configuration)\netstandard1.0\System.Interactive.Providers.dll</HintPath>
     </Reference>
+    <Reference Include="System.ServiceModel.Internals">
+      <HintPath>..\..\..\..\..\Windows\Microsoft.NET\assembly\GAC_MSIL\System.ServiceModel.Internals\v4.0_4.0.0.0__31bf3856ad364e35\System.ServiceModel.Internals.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
     <VisualStudioVersion>14.0</VisualStudioVersion>

+ 2 - 1
Ix.NET/Source/System.Interactive.Tests.Uwp.DeviceRunner/project.json

@@ -2,7 +2,8 @@
   "dependencies": {
     "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2",
     "xunit": "2.2.0-beta2-build3300",
-    "xunit.runner.devices": "2.1.0" 
+    "FluentAssertions": "4.13.0",
+    "xunit.runner.devices": "2.1.0"
   },
   "frameworks": {
     "uap10.0": {}

+ 14 - 0
Ix.NET/Source/Tests/AsyncTests.Aggregates.cs

@@ -785,6 +785,13 @@ namespace Tests
             AssertThrows<Exception>(() => res.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is InvalidOperationException);
         }
 
+        [Fact]
+        public void Single11()
+        {
+            var res = new int[0].ToAsyncEnumerable().Single();
+            AssertThrows<Exception>(() => res.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is InvalidOperationException);
+        }
+
         [Fact]
         public async Task SingleOrDefault_Null()
         {
@@ -876,6 +883,13 @@ namespace Tests
             AssertThrows<Exception>(() => res.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is InvalidOperationException);
         }
 
+        [Fact]
+        public void SingleOrDefault12()
+        {
+            var res = new int[0].ToAsyncEnumerable().SingleOrDefault();
+            Assert.Equal(0, res.Result);
+        }
+
         [Fact]
         public async Task ElementAt_Null()
         {

+ 8 - 0
Ix.NET/Source/Tests/AsyncTests.Creation.cs

@@ -142,6 +142,14 @@ namespace Tests
             e.Dispose();
         }
 
+        [Fact]
+        public async Task Repeat4()
+        {
+            var xs = AsyncEnumerable.Repeat(2).Take(5);
+
+            await SequenceIdentity(xs);
+        }
+
         [Fact]
         public void Defer_Null()
         {

+ 3 - 3
Ix.NET/Source/Tests/AsyncTests.Multiple.cs

@@ -172,7 +172,7 @@ namespace Tests
             var ys = new[] { 4, 5 }.ToAsyncEnumerable();
             var zs = new[] { 6, 7, 8 }.ToAsyncEnumerable();
 
-            var c = AsyncEnumerable.Concat(xs, ys, zs);
+            var c = xs.Concat(ys).Concat(zs);
 
             var res = new[] { 1, 2, 3, 4, 5, 6, 7, 8 };
             Assert.True(res.SequenceEqual(await c.ToArray()));
@@ -185,7 +185,7 @@ namespace Tests
             var ys = new[] { 4, 5 }.ToAsyncEnumerable();
             var zs = new[] { 6, 7, 8 }.ToAsyncEnumerable();
 
-            var c = AsyncEnumerable.Concat(xs, ys, zs);
+            var c = xs.Concat(ys).Concat(zs);
 
             var res = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8 };
             Assert.True(res.SequenceEqual(await c.ToList()));
@@ -198,7 +198,7 @@ namespace Tests
             var ys = new[] { 4, 5 }.ToAsyncEnumerable();
             var zs = new[] { 6, 7, 8 }.ToAsyncEnumerable();
 
-            var c = AsyncEnumerable.Concat(xs, ys, zs);
+            var c = xs.Concat(ys).Concat(zs);
 
             Assert.Equal(8, await c.Count());
         }

+ 185 - 0
Ix.NET/Source/Tests/AsyncTests.Single.cs

@@ -1375,6 +1375,48 @@ namespace Tests
             Assert.Equal(5, await xs.Count());
         }
 
+        [Fact]
+        public async Task Distinct6()
+        {
+            var xs = new[] { 1, 2, 1, 3, 5, 2, 1, 4 }.ToAsyncEnumerable().Distinct(k => k);
+
+            var res = new[] { 1, 2, 3, 5, 4 };
+            Assert.True(res.SequenceEqual(await xs.ToArray()));
+        }
+
+        [Fact]
+        public async Task Distinct7()
+        {
+            var xs = new[] { 1, 2, 1, 3, 5, 2, 1, 4 }.ToAsyncEnumerable().Distinct(k => k);
+
+            var res = new List<int> { 1, 2, 3, 5, 4 };
+            Assert.True(res.SequenceEqual(await xs.ToList()));
+        }
+
+        [Fact]
+        public async Task Distinct8()
+        {
+            var xs = new[] { 1, 2, 1, 3, 5, 2, 1, 4 }.ToAsyncEnumerable().Distinct(k => k);
+
+            Assert.Equal(5, await xs.Count());
+        }
+
+        [Fact]
+        public async Task Distinct9()
+        {
+            var xs = new[] { 1, 2, 1, 3, 5, 2, 1, 4 }.ToAsyncEnumerable().Distinct(k => k);
+
+            await SequenceIdentity(xs);
+        }
+
+        [Fact]
+        public async Task Distinct10()
+        {
+            var xs = new[] { 1, 2, 1, 3, 5, 2, 1, 4 }.ToAsyncEnumerable().Distinct();
+
+            await SequenceIdentity(xs);
+        }
+
         [Fact]
         public void Reverse_Null()
         {
@@ -1510,6 +1552,15 @@ namespace Tests
             AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
+        [Fact]
+        public async Task OrderBy3()
+        {
+            var xs = new[] { 2, 6, 1, 5, 7, 8, 9, 3, 4, 0 }.ToAsyncEnumerable();
+            var ys = xs.OrderBy(x => x);
+
+            await SequenceIdentity(ys);
+        }
+
         [Fact]
         public void ThenBy2()
         {
@@ -1544,6 +1595,15 @@ namespace Tests
             AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
+        [Fact]
+        public async Task OrderByDescending3()
+        {
+            var xs = new[] { 2, 6, 1, 5, 7, 8, 9, 3, 4, 0 }.ToAsyncEnumerable();
+            var ys = xs.OrderByDescending(x => x);
+
+            await SequenceIdentity(ys);
+        }
+
         [Fact]
         public void ThenByDescending2()
         {
@@ -2149,6 +2209,75 @@ namespace Tests
             Assert.False(e.MoveNext().Result);
         }
 
+        [Fact]
+        public async Task GroupBy19()
+        {
+            // We're using Kvp here because the types will eval as equal for this test
+            var xs = new[]
+            {
+                new Kvp("Bart", 27),
+                new Kvp("John", 62),
+                new Kvp("Eric", 27),
+                new Kvp("Lisa", 14),
+                new Kvp("Brad", 27),
+                new Kvp("Lisa", 23),
+                new Kvp("Eric", 42)
+            };
+
+            var ys = xs.ToAsyncEnumerable();
+
+            var res = ys.GroupBy(x => x.Item/10);
+
+            await SequenceIdentity(res);
+        }
+
+        class Kvp : IEquatable<Kvp>
+        {
+            public bool Equals(Kvp other)
+            {
+                if (ReferenceEquals(null, other)) return false;
+                if (ReferenceEquals(this, other)) return true;
+                return string.Equals(Key, other.Key) && Item == other.Item;
+            }
+
+            public override bool Equals(object obj)
+            {
+                if (ReferenceEquals(null, obj)) return false;
+                if (ReferenceEquals(this, obj)) return true;
+                if (obj.GetType() != this.GetType()) return false;
+                return Equals((Kvp)obj);
+            }
+
+            public override int GetHashCode()
+            {
+                unchecked
+                {
+                    return ((Key != null ? Key.GetHashCode() : 0)*397) ^ Item;
+                }
+            }
+
+            public static bool operator ==(Kvp left, Kvp right)
+            {
+                return Equals(left, right);
+            }
+
+            public static bool operator !=(Kvp left, Kvp right)
+            {
+                return !Equals(left, right);
+            }
+
+
+            public string Key { get; }
+            public int Item { get; }
+
+            public Kvp(string key, int item)
+            {
+                Key = key;
+                Item = item;
+            }
+        }
+
+
         class EqMod : IEqualityComparer<int>
         {
             private readonly int _d;
@@ -2260,6 +2389,14 @@ namespace Tests
             NoNext(e);
         }
 
+        [Fact]
+        public async Task RepeatSeq6()
+        {
+            var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Repeat(3);
+
+            await SequenceIdentity(xs);
+        }
+
         static IEnumerable<int> RepeatXs(Action started)
         {
             started();
@@ -2524,6 +2661,22 @@ namespace Tests
             AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
+        [Fact]
+        public async Task DistinctUntilChanged4()
+        {
+            var xs = new[] { 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 6, 7, 3, 2, 2, 1, 1 }.ToAsyncEnumerable().DistinctUntilChanged();
+
+            await SequenceIdentity(xs);
+        }
+
+        [Fact]
+        public async Task DistinctUntilChanged5()
+        {
+            var xs = new[] { 1, 2, 3, 4, 3, 5, 2 }.ToAsyncEnumerable().DistinctUntilChanged(x => (x + 1) / 2);
+
+            await SequenceIdentity(xs);
+        }
+
         [Fact]
         public void Expand_Null()
         {
@@ -2568,6 +2721,14 @@ namespace Tests
             AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is NullReferenceException);
         }
 
+        [Fact]
+        public async Task Expand4()
+        {
+            var xs = new[] { 2, 3 }.ToAsyncEnumerable().Expand(x => AsyncEnumerable.Return(x - 1).Repeat(x - 1));
+
+            await SequenceIdentity(xs);
+        }
+
         [Fact]
         public void Scan_Null()
         {
@@ -2621,6 +2782,14 @@ namespace Tests
             AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
+        [Fact]
+        public async Task Scan5()
+        {
+            var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Scan(8, (x, y) => x + y);
+
+            await SequenceIdentity(xs);
+        }
+
         [Fact]
         public void DistinctKey_Null()
         {
@@ -2683,6 +2852,14 @@ namespace Tests
             NoNext(e);
         }
 
+        [Fact]
+        public async Task TakeLast3()
+        {
+            var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable().TakeLast(2);
+
+            await SequenceIdentity(xs);
+        }
+
         [Fact]
         public void TakeLast_BugFix_TakeLast_Zero_TakesForever()
         {
@@ -2726,5 +2903,13 @@ namespace Tests
             var e = xs.GetEnumerator();
             NoNext(e);
         }
+
+        [Fact]
+        public async Task SkipLast3()
+        {
+            var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable().SkipLast(2);
+
+            await SequenceIdentity(xs);
+        }
     }
 }

+ 14 - 70
Ix.NET/Source/Tests/AsyncTests.cs

@@ -8,8 +8,11 @@ using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Reflection;
+using System.Threading;
 using System.Threading.Tasks;
 using Xunit;
+using FluentAssertions;
+
 
 namespace Tests
 {
@@ -63,83 +66,24 @@ namespace Tests
 
         public async Task SequenceIdentity<T>(IAsyncEnumerable<T> enumerable)
         {
-            Assert.True(await enumerable.SequenceEqual(enumerable, SequenceIdentityComparer<T>.Instance));
-        }
-
-        private class SequenceIdentityComparer<T> : IEqualityComparer<T>
-        {
-            readonly IEqualityComparer<T> innerComparer = EqualityComparer<T>.Default;
-            public SequenceIdentityComparer()
-            {
-                var itemType = GetAnyElementType(typeof(T));
-
-                // if not the same as T, then it's a list
-                if (itemType != typeof(T))
-                {
-                    // invoke the Instance method of the type we need
-
-                    var eqType = typeof(SequenceIdentityComparer<,>).MakeGenericType(typeof(T), itemType);
-                    innerComparer = (IEqualityComparer<T>)eqType.GetRuntimeProperty("Instance").GetValue(null);
-                }
-            }
-
-
-            public static SequenceIdentityComparer<T> Instance => new SequenceIdentityComparer<T>();
-            public bool Equals(T x, T y)
-            {
-                return innerComparer.Equals(x, y);
-            }
+            var en1 = enumerable.GetEnumerator();
+            var en2 = enumerable.GetEnumerator();
 
-            public int GetHashCode(T obj)
-            {
-                return innerComparer.GetHashCode(obj);
-            }
+            Assert.Equal(en1.GetType(), en2.GetType());
 
-            static Type GetAnyElementType(Type type)
-            {
-                // Type is Array
-                // short-circuit if you expect lots of arrays 
-                if (typeof(Array).IsAssignableFrom(type))
-                    return type.GetElementType();
-
-                // type is IEnumerable<T>;
-                if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
-                    return type.GetGenericArguments()[0];
-
-                // type implements/extends IEnumerable<T>;
-                var enumType = type.GetInterfaces()
-                                        .Where(t => t.GetTypeInfo().IsGenericType &&
-                                               t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
-                                        .Select(t => t.GenericTypeArguments[0]).FirstOrDefault();
-                return enumType ?? type;
-            }
-        
-        }
+            en1.Dispose();
+            en2.Dispose();
 
+            var e1t = enumerable.ToList();
+            var e2t = enumerable.ToList();
 
-        private class SequenceIdentityComparer<TList, TItem> : IEqualityComparer<TList> where TList : IEnumerable<TItem>
-        {
-            readonly IEqualityComparer<TItem> innerComparer = EqualityComparer<TItem>.Default;
+            await Task.WhenAll(e1t, e2t);
 
 
-            public static IEqualityComparer<TList> Instance => new SequenceIdentityComparer<TList, TItem>();
-            public bool Equals(TList x, TList y)
-            {
-                return x.SequenceEqual(y);
-            }
+            var e1Result = e1t.Result;
+            var e2Result = e2t.Result;
 
-            public int GetHashCode(TList obj)
-            {
-                return obj.Aggregate(0, (i, item) =>
-                                        {
-                                            unchecked
-                                            {
-                                                i += innerComparer.GetHashCode(item);
-                                            }
-                                            return i;
-                                        }
-                                        );
-            }
+            e1Result.ShouldAllBeEquivalentTo(e2Result);
         }
     }
 }

+ 2 - 1
Ix.NET/Source/Tests/project.json

@@ -26,7 +26,8 @@
     "System.Interactive.Providers": { "target": "project" },
     "System.Interactive.Async.Providers": { "target": "project" },
     "xunit": "2.2.0-beta3-build3342",
-    "dotnet-test-xunit": "2.2.0-preview3-build1039"
+    "dotnet-test-xunit": "2.2.0-preview3-build1039",
+    "FluentAssertions": "4.13.0"
   },
 
   "testRunner": "xunit",