public static void GroupJoin_NotPipelined(Labeled <ParallelQuery <int> > left, int leftCount, Labeled <ParallelQuery <int> > right, int rightCount) { ParallelQuery <int> leftQuery = left.Item; ParallelQuery <int> rightQuery = right.Item; int seen = 0; Assert.All(leftQuery.GroupJoin(rightQuery, x => x * KeyFactor, y => y, (x, y) => KeyValuePair.Create(x, y)).ToList(), p => { Assert.Equal(seen++, p.Key); if (p.Key < (rightCount + (KeyFactor - 1)) / KeyFactor) { Assert.Equal(p.Key * KeyFactor, Assert.Single(p.Value)); } else { Assert.Empty(p.Value); } }); Assert.Equal(leftCount, seen); }
public static void GroupJoin_Unordered_NotPipelined(Labeled <ParallelQuery <int> > left, int leftCount, Labeled <ParallelQuery <int> > right, int rightCount) { ParallelQuery <int> leftQuery = left.Item; ParallelQuery <int> rightQuery = right.Item; IntegerRangeSet seen = new IntegerRangeSet(0, leftCount); Assert.All(leftQuery.GroupJoin(rightQuery, x => x * KeyFactor, y => y, (x, y) => KeyValuePair.Create(x, y)).ToList(), p => { seen.Add(p.Key); if (p.Key < (rightCount + (KeyFactor - 1)) / KeyFactor) { Assert.Equal(p.Key * KeyFactor, Assert.Single(p.Value)); } else { Assert.Empty(p.Value); } }); seen.AssertComplete(); }
public static void GroupJoin_CustomComparator(Labeled <ParallelQuery <int> > left, int leftCount, Labeled <ParallelQuery <int> > right, int rightCount) { ParallelQuery <int> leftQuery = left.Item; ParallelQuery <int> rightQuery = right.Item; int seenOuter = 0; Assert.All(leftQuery.GroupJoin(rightQuery, x => x, y => y % ElementFactor, (x, y) => KeyValuePair.Create(x, y), new ModularCongruenceComparer(KeyFactor)), p => { Assert.Equal(seenOuter++, p.Key); if (p.Key % KeyFactor < Math.Min(ElementFactor, rightCount)) { IntegerRangeSet seenInner = new IntegerRangeSet(0, (rightCount + (ElementFactor - 1) - p.Key % ElementFactor) / ElementFactor); Assert.All(p.Value, y => { Assert.Equal(p.Key % KeyFactor, y % ElementFactor); seenInner.Add(y / ElementFactor); }); seenInner.AssertComplete(); } else { Assert.Empty(p.Value); } }); Assert.Equal(leftCount, seenOuter); }
// GroupJoin doesn't always return elements from the right in order. See Issue #1155 public static void GroupJoin_Multiple(Labeled <ParallelQuery <int> > left, int leftCount, Labeled <ParallelQuery <int> > right, int rightCount) { ParallelQuery <int> leftQuery = left.Item; ParallelQuery <int> rightQuery = right.Item; int seenOuter = 0; Assert.All(leftQuery.GroupJoin(rightQuery, x => x, y => y / KeyFactor, (x, y) => KeyValuePair.Create(x, y)), p => { Assert.Equal(seenOuter++, p.Key); if (p.Key < (rightCount + (KeyFactor - 1)) / KeyFactor) { IntegerRangeSet seenInner = new IntegerRangeSet(p.Key * KeyFactor, Math.Min(rightCount - p.Key * KeyFactor, KeyFactor)); Assert.All(p.Value, y => { Assert.Equal(p.Key, y / KeyFactor); seenInner.Add(y); }); seenInner.AssertComplete(); } else { Assert.Empty(p.Value); } }); Assert.Equal(leftCount, seenOuter); }
public static void GroupJoin_Unordered_CustomComparator(int leftCount, int rightCount) { ParallelQuery <int> leftQuery = UnorderedSources.Default(leftCount); ParallelQuery <int> rightQuery = UnorderedSources.Default(rightCount); IntegerRangeSet seenOuter = new IntegerRangeSet(0, leftCount); Assert.All(leftQuery.GroupJoin(rightQuery, x => x, y => y % ElementFactor, (x, y) => KeyValuePair.Create(x, y), new ModularCongruenceComparer(KeyFactor)), p => { seenOuter.Add(p.Key); if (p.Key % KeyFactor < Math.Min(ElementFactor, rightCount)) { IntegerRangeSet seenInner = new IntegerRangeSet(0, (rightCount + (ElementFactor - 1) - p.Key % ElementFactor) / ElementFactor); Assert.All(p.Value, y => { Assert.Equal(p.Key % KeyFactor, y % ElementFactor); seenInner.Add(y / ElementFactor); }); seenInner.AssertComplete(); } else { Assert.Empty(p.Value); } }); seenOuter.AssertComplete(); }
public static void GroupJoin_Unordered_Multiple(int leftCount, int rightCount) { ParallelQuery <int> leftQuery = UnorderedSources.Default(leftCount); ParallelQuery <int> rightQuery = UnorderedSources.Default(rightCount); IntegerRangeSet seenOuter = new IntegerRangeSet(0, leftCount); Assert.All(leftQuery.GroupJoin(rightQuery, x => x, y => y / KeyFactor, (x, y) => KeyValuePair.Create(x, y)), p => { seenOuter.Add(p.Key); if (p.Key < (rightCount + (KeyFactor - 1)) / KeyFactor) { IntegerRangeSet seenInner = new IntegerRangeSet(p.Key * KeyFactor, Math.Min(rightCount - p.Key * KeyFactor, KeyFactor)); Assert.All(p.Value, y => { Assert.Equal(p.Key, y / KeyFactor); seenInner.Add(y); }); seenInner.AssertComplete(); } else { Assert.Empty(p.Value); } }); seenOuter.AssertComplete(); }
private static void RunAllTests( TestTracker result, ParallelQuery <int> q, bool orderPreserved, string leftOpName, bool leftOrderDefined) { LogTestRun(leftOpName, "All1", orderPreserved); result.MustEqual( q.All(i => i > 100), q.ToArray().Any(i => i > 100)); LogTestRun(leftOpName, "All2", orderPreserved); result.MustEqual( q.All(i => i == 75), q.ToArray().All(i => i == 75)); LogTestRun(leftOpName, "Any1", orderPreserved); result.MustEqual( q.Any(i => i > 100), q.ToArray().Any(i => i > 100)); LogTestRun(leftOpName, "Any2", orderPreserved); result.MustEqual( q.Any(i => i == 75), q.ToArray().Any(i => i == 75)); LogTestRun(leftOpName, "Concat", orderPreserved); result.MustSequenceEqual( q.Concat(q).Concat(new int[] { 1, 2, 3 }.AsParallel()), q.Reverse().Reverse().ToArray().Concat(q.Reverse().Reverse()).Concat(new int[] { 1, 2, 3 }), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "DefaultIfEmpty", orderPreserved); result.MustSequenceEqual( q.DefaultIfEmpty(), q.ToArray().DefaultIfEmpty(), orderPreserved && leftOrderDefined); LogTestRun(leftOpName, "ElementAt", orderPreserved); IEnumerable <int> q2 = q.ToArray(); int count1 = q.Count(), count2 = q2.Count(); List <int> list1 = new List <int>(); List <int> list2 = new List <int>(); for (int i = 0; i < count1; i++) { list1.Add(q.ElementAt(i)); } for (int i = 0; i < count2; i++) { list2.Add(q2.ElementAt(i)); } result.MustSequenceEqual(list1, list2, leftOrderDefined); LogTestRun(leftOpName, "Except", orderPreserved); result.MustSequenceEqual( q.Except(Enumerable.Range(90, 50).AsParallel()), q.ToArray().Except(Enumerable.Range(90, 50)), false); LogTestRun(leftOpName, "First", orderPreserved); CheckFirstOrLast( result, q.First(), q.ToArray().First(), leftOrderDefined); LogTestRun(leftOpName, "GroupBy", orderPreserved); result.MustGroupByEqual( q.GroupBy(i => i % 5, (i, e) => new Pair <int, IEnumerable <int> >(i, e)), q.ToArray().GroupBy(i => i % 5, (i, e) => new Pair <int, IEnumerable <int> >(i, e))); LogTestRun(leftOpName, "GroupJoin", orderPreserved); result.MustSequenceEqual( q.GroupJoin(q, i => i, i => i, (i, e) => e.FirstOrDefault()), q.ToArray().GroupJoin(q.ToArray(), i => i, i => i, (i, e) => e.FirstOrDefault()), false); LogTestRun(leftOpName, "Intersect", orderPreserved); result.MustSequenceEqual( q.Intersect(Enumerable.Range(90, 50).AsParallel()), q.ToArray().Intersect(Enumerable.Range(90, 50)), false); LogTestRun(leftOpName, "Join1", orderPreserved); result.MustSequenceEqual( q.Join((new int[] { 1, 1, 2, 3, 3 }).AsParallel(), i => i, i => i, (i, j) => i + j), q.ToArray().Join(new int[] { 1, 1, 2, 3, 3 }, i => i, i => i, (i, j) => i + j), false); LogTestRun(leftOpName, "Join2", orderPreserved); result.MustSequenceEqual( q.Join((new int[] { 1, 1, 100, 3, 3 }).AsParallel(), i => new String('a', i), i => new String('a', i), (i, j) => i + j), q.ToArray().Join(new int[] { 1, 1, 100, 3, 3 }, i => new String('a', i), i => new String('a', i), (i, j) => i + j), false); LogTestRun(leftOpName, "Last", orderPreserved); CheckFirstOrLast( result, q.Last(), q.ToArray().Last(), leftOrderDefined); LogTestRun(leftOpName, "Min", orderPreserved); CheckFirstOrLast( result, q.Min(), q.ToArray().Min(), leftOrderDefined); LogTestRun(leftOpName, "Max", orderPreserved); CheckFirstOrLast( result, q.Min(), q.ToArray().Min(), leftOrderDefined); LogTestRun(leftOpName, "OrderBy-ThenBy", orderPreserved); result.MustSequenceEqual( q.Concat(q).OrderBy(i => i % 5).ThenBy(i => - i), q.ToArray().Concat(q).OrderBy(i => i % 5).ThenBy(i => - i), true); LogTestRun(leftOpName, "OrderByDescending-ThenByDescending", orderPreserved); result.MustSequenceEqual( q.Concat(q).OrderByDescending(i => i % 5).ThenByDescending(i => - i), q.ToArray().Concat(q).OrderByDescending(i => i % 5).ThenByDescending(i => - i), true); LogTestRun(leftOpName, "Reverse", orderPreserved); result.MustSequenceEqual( q.Concat(q).Reverse(), q.ToArray().Concat(q).Reverse(), orderPreserved && leftOrderDefined); LogTestRun(leftOpName, "Select", orderPreserved); result.MustSequenceEqual( q.Select(i => 5 * i - 17), q.ToArray().Select(i => 5 * i - 17), orderPreserved && leftOrderDefined); LogTestRun(leftOpName, "SelectMany", orderPreserved); result.MustSequenceEqual( q.SelectMany(i => new int[] { 1, 2, 3 }, (i, j) => i + 100 * j), q.ToArray().SelectMany(i => new int[] { 1, 2, 3 }, (i, j) => i + 100 * j), false); LogTestRun(leftOpName, "SequenceEqual", orderPreserved); if (orderPreserved && leftOrderDefined) { result.MustEqual(q.SequenceEqual(q), true); } else { // We don't check the return value as it can be either true or false q.SequenceEqual(q); } LogTestRun(leftOpName, "Skip", orderPreserved); CheckTakeSkip( result, q.Skip(10), q.ToArray().Skip(10), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "SkipWhile", orderPreserved); CheckTakeSkip( result, q.SkipWhile(i => i < 30), q.ToArray().SkipWhile(i => i < 30), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "SkipWhileIndexed", orderPreserved); CheckTakeSkip( result, q.SkipWhile((i, j) => j < 30), q.ToArray().SkipWhile((i, j) => j < 30), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "Take", orderPreserved); CheckTakeSkip( result, q.Take(10), q.ToArray().Take(10), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "TakeWhile", orderPreserved); CheckTakeSkip( result, q.TakeWhile(i => i < 30), q.ToArray().TakeWhile(i => i < 30), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "TakeWhileIndexed", orderPreserved); CheckTakeSkip( result, q.TakeWhile((i, j) => j < 30), q.ToArray().TakeWhile((i, j) => j < 30), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "Union", orderPreserved); result.MustSequenceEqual( q.Union(Enumerable.Range(90, 50).AsParallel()), q.ToArray().Union(Enumerable.Range(90, 50)), false); LogTestRun(leftOpName, "Where", orderPreserved); result.MustSequenceEqual( q.Where(i => i < 20 || i > 80), q.ToArray().Where(i => i < 20 || i > 80), orderPreserved && leftOrderDefined); LogTestRun(leftOpName, "Zip", orderPreserved); IEnumerable <KeyValuePair <int, int> > zipQ = q.Zip(q, (i, j) => new KeyValuePair <int, int>(i, j)); result.MustSequenceEqual( zipQ.Select(p => p.Key), q.Reverse().Reverse().ToArray(), orderPreserved && leftOrderDefined); result.MustSequenceEqual( zipQ.Select(p => p.Value), q.Reverse().Reverse().ToArray(), orderPreserved && leftOrderDefined); }
public static void GroupJoin_CustomComparator_LeftWithOrderingColisions(Labeled <ParallelQuery <int> > left, int leftCount, Labeled <ParallelQuery <int> > right, int rightCount) { ParallelQuery <int> leftQuery = left.Item.AsUnordered().OrderBy(x => x / KeyFactor); ParallelQuery <int> rightQuery = right.Item; int seenNonEmpty = 0; int seenEmpty = 0; int seenLeftGroup = 0; int seenLeftCount = 0; Assert.All(leftQuery.GroupJoin(rightQuery, x => x, y => y % ElementFactor, (x, y) => KeyValuePair.Create(x, y), new ModularCongruenceComparer(KeyFactor)), p => { seenLeftCount++; if (p.Key / KeyFactor > seenLeftGroup) { seenLeftGroup++; try { Assert.Equal(KeyFactor, seenEmpty + seenNonEmpty); } finally { seenEmpty = 0; seenNonEmpty = 0; } } Assert.Equal(seenLeftGroup, p.Key / KeyFactor); if (p.Key % KeyFactor < Math.Min(ElementFactor, rightCount)) { try { Assert.Equal((seenLeftGroup * KeyFactor) + seenNonEmpty, p.Key); } finally { seenNonEmpty++; } int expectedInner = p.Key % ElementFactor; int seenInnerCount = 0; Assert.All(p.Value, y => { seenInnerCount++; Assert.Equal(p.Key % KeyFactor, y % ElementFactor); try { Assert.Equal(expectedInner, y); } finally { expectedInner += ElementFactor; } }); Assert.Equal((rightCount / ElementFactor) + (((rightCount % ElementFactor) > (p.Key % KeyFactor)) ? 1 : 0), seenInnerCount); } else { seenEmpty++; Assert.Equal(0, seenNonEmpty); Assert.Empty(p.Value); } }); Assert.Equal(leftCount, seenLeftCount); }
public static ParallelQuery <TResult> LeftJoin <TOuter, TInner, TKey, TResult>(this ParallelQuery <TOuter> outer, ParallelQuery <TInner> inner, Func <TOuter, TKey> outerKeySelector, Func <TInner, TKey> innerKeySelector, Func <TOuter, TInner, TResult> resultSelector) { ParallelQuery <TResult> results = outer.GroupJoin(inner, outerKeySelector, innerKeySelector, (x, y) => new { Outer = x, Inner = y.SingleOrDefault() }).Select(x => resultSelector(x.Outer, x.Inner)); return(results); }
public static ParallelQuery <TOuter> NotJoin <TOuter, TInner, TKey>(this ParallelQuery <TOuter> outer, ParallelQuery <TInner> inner, Func <TOuter, TKey> outerKeySelector, Func <TInner, TKey> innerKeySelector) { ParallelQuery <TOuter> results = outer.GroupJoin(inner, outerKeySelector, innerKeySelector, (x, y) => new { Outer = x, Inner = y.Any() }).Where(x => !x.Inner).Select(x => x.Outer); return(results); }
public static void ForEach <TOuter, TInner, TKey>(this ParallelQuery <TOuter> outer, ParallelQuery <TInner> inner, Func <TOuter, TKey> outerKeySelector, Func <TInner, TKey> innerKeySelector, Action <TOuter, TInner> resultSelector) { outer.GroupJoin(inner, outerKeySelector, innerKeySelector, (x, y) => new { Outer = x, Inner = y.SingleOrDefault() }).ForAll(x => resultSelector(x.Outer, x.Inner)); }