예제 #1
0
        [Test] public void ForEachStopsAsSoonAsExceptionThrownAt(
            [Values(Parallelism / 2, Parallelism, Parallelism * 2)] int cancelAt)
        {
            T[] sources = TestData <T> .MakeTestArray(_sampleSize);

            List <T> completed = new List <T>(_sampleSize);

            _sut = new ParallelCompletion <T, int>(_executor,
                                                   _localInit,
                                                   (t, s, l) =>
            {
                Thread.Sleep(s.CurrentIndex == 0 ? Delays.ShortMillis : 10);
                if (s.CurrentIndex == cancelAt)
                {
                    throw new Exception();
                }
                if (!s.ShouldExitCurrentIteration)
                {
                    lock (completed) completed.Add(t);
                }
                else
                {
                    Assert.That(s.LowestBreakIteration, Is.Null);
                    Assert.That(s.IsExceptional, Is.True);
                    Assert.That(s.IsStopped, Is.False);
                }
                return(0);
            },
                                                   _localFinally);
            Assert.Catch(() => _sut.ForEach(sources, Parallelism));
            Assert.That(completed, Has.No.Member(sources[0]));
            ThreadManager.JoinAndVerify();
        }
예제 #2
0
        [Test] public void ForEachStopsAsSoonAsStopCalledAt(
            [Values(Parallelism / 2, Parallelism, Parallelism * 2)] int cancelAt)
        {
            T[] sources = TestData <T> .MakeTestArray(_sampleSize);

            List <T> completed = new List <T>(_sampleSize);

            _sut = new ParallelCompletion <T>(_executor,
                                              (t, s) =>
            {
                Thread.Sleep(s.CurrentIndex == 0 ? Delays.ShortMillis : 10);
                if (s.CurrentIndex == cancelAt)
                {
                    s.Stop();
                }
                else
                {
                    if (!s.ShouldExitCurrentIteration)
                    {
                        lock (completed) completed.Add(t);
                    }
                    else
                    {
                        Assert.That(s.LowestBreakIteration, Is.Null);
                        Assert.That(s.IsExceptional, Is.False);
                        Assert.That(s.IsStopped, Is.True);
                    }
                }
            });
            var result = _sut.ForEach(sources, Parallelism);

            Assert.That(result.IsCompleted, Is.False);
            Assert.That(completed, Has.No.Member(sources[0]));
            ThreadManager.JoinAndVerify();
        }
예제 #3
0
        [Test] public void ForEachCallsLocalInitBodyLocalFinallyInOrder()
        {
            T[] sources = TestData <T> .MakeTestArray(_sampleSize);

            _sut = new ParallelCompletion <T, int>(_executor, _localInit, _body, _localFinally);
            _sut.ForEach(sources, Parallelism);

            (
                _localFinally.ActivityOf(x => x(Arg <int> .Is.Anything)).First
                >
                _body.ActivityOf(x => x(Arg <T> .Is.Anything, Arg <ILoopState> .Is.Anything, Arg <int> .Is.Anything)).First
                >
                _localInit.ActivityOf(x => x()).First
            )
            .AssertOccured();

            (
                _localFinally.ActivityOf(x => x(Arg <int> .Is.Anything)).Last
                >
                _body.ActivityOf(x => x(Arg <T> .Is.Anything, Arg <ILoopState> .Is.Anything, Arg <int> .Is.Anything)).Last
                >
                _localInit.ActivityOf(x => x()).Last
            )
            .AssertOccured();

            ThreadManager.JoinAndVerify();
        }
예제 #4
0
        [Test] public void ForEachLimitsParallismToThreadPoolExecutorCoreSize(
            [Values(Parallelism - 2, Parallelism + 2)] int coreSize)
        {
            var tf       = new ManagedThreadFactory(ThreadManager);
            var executor = new ThreadPoolExecutor(coreSize, Parallelism + 2,
                                                  TimeSpan.MaxValue, new LinkedBlockingQueue <IRunnable>(1), tf);

            try
            {
                T[] sources = TestData <T> .MakeTestArray(_sampleSize);

                List <T> results  = new List <T>(_sampleSize);
                var      parallel = new ParallelCompletion <T, int>(executor,
                                                                    _localInit,
                                                                    (t, s, l) =>
                {
                    Thread.Sleep(10); lock (results) results.Add(t);
                    return(0);
                },
                                                                    _localFinally);
                parallel.ForEach(sources, Parallelism);
                Assert.That(results, Is.EquivalentTo(sources));
                Assert.That(parallel.ActualDegreeOfParallelism, Is.EqualTo(Math.Min(Parallelism, coreSize)));
            }
            finally
            {
                executor.ShutdownNow();
            }

            ThreadManager.JoinAndVerify();
        }
예제 #5
0
        [Test] public void ForEachChokesOnAnyExceptionFromBody()
        {
            var exception = new Exception("exception message");

            T[] sources = TestData <T> .MakeTestArray(_sampleSize);

            _sut = new ParallelCompletion <T, int>(_executor,
                                                   _localInit,
                                                   (t, s, l) =>
            {
                if (Equals(t, sources[0]))
                {
                    Thread.Sleep(Delays.Short);
                    throw exception;
                }
                return(0);
            },
                                                   _localFinally);
            ThreadManager.StartAndAssertRegistered("Driver",
                                                   () =>
            {
                var e = Assert.Throws <AggregateException>(() =>
                                                           _sut.ForEach(sources, Parallelism));
                Assert.That(e.InnerException, Is.SameAs(exception));
                Assert.That(_executor.ThreadCount.Value, Is.GreaterThanOrEqualTo(2));
            });
            Thread.Sleep(Delays.Short);
            ThreadManager.JoinAndVerify();
        }
예제 #6
0
        [Test] public void ForEachChokesOnNullParallelOptions()
        {
            _sut = new ParallelCompletion <T>(_executor, (t, s) => { });
            var e = Assert.Throws <ArgumentNullException>(
                () => _sut.ForEach(new T[0], null));

            Assert.That(e.ParamName, Is.EqualTo("parallelOptions"));
        }
예제 #7
0
        [Test] public void ForEachReturnsImmediatelyOnEmptySource()
        {
            List <T> results = new List <T>();

            _sut = new ParallelCompletion <T>(_executor, (t, s) => { lock (results) results.Add(t); });
            _sut.ForEach(new T[0], new ParallelOptions());
            Assert.That(results, Is.Empty);
            Assert.That(_executor.ThreadCount.Value, Is.EqualTo(0));
        }
예제 #8
0
        [Test] public void ForEachChokesOnNullParallelOptions()
        {
            _sut = new ParallelCompletion <T, int>(_executor,
                                                   _localInit, _body, _localFinally);
            var e = Assert.Throws <ArgumentNullException>(
                () => _sut.ForEach(new T[0], null));

            Assert.That(e.ParamName, Is.EqualTo("parallelOptions"));
        }
예제 #9
0
        [Test] public void ForEachUseCurrentThreadWhenParallelistIsOne()
        {
            List <T> results = new List <T>(_sampleSize);

            _sut = new ParallelCompletion <T>(_executor,
                                              (t, s) => { Thread.Sleep(10); lock (results) results.Add(t); });
            T[] sources = TestData <T> .MakeTestArray(_sampleSize);

            _sut.ForEach(sources, 1);
            Assert.That(results, Is.EquivalentTo(sources));
            Assert.That(_executor.ThreadCount.Value, Is.EqualTo(0));
        }
예제 #10
0
        [Test] public void ForEachRecordsTheLowestOfMultipleBreaks(
            [Values(Parallelism / 2, Parallelism, Parallelism * 2)] int breakAt)
        {
            T[] sources = TestData <T> .MakeTestArray(_sampleSize);

            _sut = new ParallelCompletion <T>(_executor,
                                              (t, s) => BreakAt(s, breakAt));
            var result = _sut.ForEach(sources, Parallelism);

            Assert.That(result.IsCompleted, Is.False);
            Assert.That(result.LowestBreakIteration, Is.EqualTo(breakAt));
            ThreadManager.JoinAndVerify();
        }
예제 #11
0
        [Test] public void ForEachDoesNotSumitMoreThenMaxDegreeOfParallelism()
        {
            _executor.Delay = Delays.Short;
            T[] sources = TestData <T> .MakeTestArray(_sampleSize);

            List <T> results = new List <T>(_sampleSize);

            _sut = new ParallelCompletion <T>(_executor,
                                              (t, s) => { Thread.Sleep(10); lock (results) results.Add(t); });
            _sut.ForEach(sources, Parallelism);
            Assert.That(_executor.ThreadCount.Value, Is.EqualTo(Parallelism));
            Assert.That(results, Is.EquivalentTo(sources));
            ThreadManager.JoinAndVerify();
        }
예제 #12
0
        [Test] public void ForEachCompletesAllSlowTasks([Values(int.MaxValue, 3, 1, 0)] int maxThread)
        {
            _executor.Threshold = maxThread;
            T[] sources = TestData <T> .MakeTestArray(_sampleSize);

            List <T> results = new List <T>(_sampleSize);

            _sut = new ParallelCompletion <T>(_executor,
                                              (t, s) => { Thread.Sleep(10); lock (results) results.Add(t); });
            _sut.ForEach(sources, Parallelism);
            Assert.That(results, Is.EquivalentTo(sources));
            Assert.That(_executor.ThreadCount.Value, Is.EqualTo(Math.Min(Parallelism, maxThread)));
            ThreadManager.JoinAndVerify();
        }
예제 #13
0
        [Test] public void ForEachCompletesAllFaskTasks()
        {
            _sampleSize = 200;
            T[] sources = TestData <T> .MakeTestArray(_sampleSize);

            List <T> results = new List <T>(_sampleSize);

            _sut = new ParallelCompletion <T>(_executor, (t, s) => { lock (results) results.Add(t); });
            _sut.ForEach(sources, new ParallelOptions {
                MaxDegreeOfParallelism = Parallelism
            });
            Assert.That(results, Is.EquivalentTo(sources));
            Assert.That(_executor.ThreadCount.Value, Is.LessThanOrEqualTo(Parallelism));
            ThreadManager.JoinAndVerify();
        }
예제 #14
0
        [Test] public void UseLocalToCollect()
        {
            List <T> collected = new List <T>();

            T[] sources = TestData <T> .MakeTestArray(100);

            var sut = new ParallelCompletion <T, IList <T> >(_executor,
                                                             () => new List <T>(),
                                                             (t, s, l) => { l.Add(t); return(l); },
                                                             l => { lock (collected) collected.AddRange(l); });

            sut.ForEach(sources, Parallelism);

            Assert.That(collected, Is.EquivalentTo(sources));
            ThreadManager.JoinAndVerify();
        }
예제 #15
0
        [Test] public void UseLocalToCount()
        {
            object @lock = new object();
            int    count = 0;

            T[] sources = TestData <T> .MakeTestArray(_sampleSize);

            _sut = new ParallelCompletion <T, int>(_executor,
                                                   () => 0,
                                                   (t, s, l) => l + 1,
                                                   l => { lock (@lock) count += l; });

            _sut.ForEach(sources, Parallelism);
            Assert.That(count, Is.EqualTo(_sampleSize));
            ThreadManager.JoinAndVerify();
        }
예제 #16
0
        [Test] public void ForEachCallsLocalFinallyOnExceptionFromBody()
        {
            T[] sources = TestData <T> .MakeTestArray(_sampleSize);

            Thread failedThread          = null;
            var    failedThreadFinalized = false;
            var    sut = new ParallelCompletion <T, Thread>(
                _executor,
                () => Thread.CurrentThread,
                (t, s, l) =>
            {
                if (TestData <T> .Three.Equals(t))
                {
                    failedThread = l;
                    throw new Exception();
                }
                return(l);
            },
                l =>
            {
                if (l == failedThread)
                {
                    failedThreadFinalized = true;
                }
            });

            ThreadManager.StartAndAssertRegistered(
                "Driver", () =>
            {
                try
                {
                    sut.ForEach(sources, Parallelism);
                    Assert.Fail("Expecting System.AggregateException, but didn't occur.");
                }
                catch (AggregateException)
                {
                }
            }
                );
            Thread.Sleep(Delays.Short);
            ThreadManager.JoinAndVerify();
            Assert.That(failedThreadFinalized);
        }
예제 #17
0
        [Test] public void ForEachCompletesIterationsLessThenBreakIndexOf(
            [Values(Parallelism / 2, Parallelism, Parallelism * 2)] int cancelAt)
        {
            T[] sources = TestData <T> .MakeTestArray(_sampleSize);

            List <T> completed = new List <T>(_sampleSize);

            _sut = new ParallelCompletion <T, int>(_executor,
                                                   _localInit,
                                                   (t, s, l) =>
            {
                Thread.Sleep(s.CurrentIndex == 0 ? Delays.ShortMillis : 10);
                if (s.CurrentIndex == cancelAt)
                {
                    s.Break();
                }
                else
                {
                    if (!s.ShouldExitCurrentIteration)
                    {
                        lock (completed) completed.Add(t);
                    }
                    else
                    {
                        Assert.That(s.LowestBreakIteration, Is.EqualTo(cancelAt));
                        Assert.That(s.IsExceptional, Is.False);
                        Assert.That(s.IsStopped, Is.False);
                    }
                }
                return(0);
            },
                                                   _localFinally);
            var result = _sut.ForEach(sources, Parallelism);

            _localFinally.AssertWasCalled(x => x(0));
            Assert.That(result.IsCompleted, Is.False);
            Assert.That(result.LowestBreakIteration, Is.EqualTo(cancelAt));
            Assert.That(completed.Count, Is.GreaterThanOrEqualTo(cancelAt));
            Assert.That(completed, Has.Member(sources[0]));
            ThreadManager.JoinAndVerify();
        }
예제 #18
0
        [Test] public void ForEachInnerExceptionIsFromFinallyNotBody()
        {
            T[] sources = TestData <T> .MakeTestArray(_sampleSize);

            Thread failedThread = null;
            var    sut          = new ParallelCompletion <T, Thread>(
                _executor,
                () => Thread.CurrentThread,
                (t, s, l) =>
            {
                if (TestData <T> .Three.Equals(t))
                {
                    failedThread = l;
                    throw new Exception("body");
                }
                return(l);
            },
                l =>
            {
                if (l == failedThread)
                {
                    throw new Exception("localFinally");
                }
            });

            ThreadManager.StartAndAssertRegistered("Driver",
                                                   () =>
            {
                try
                {
                    sut.ForEach(sources, Parallelism);
                    Assert.Fail("Expecting System.AggregateException, but didn't occur.");
                }
                catch (AggregateException e)
                {
                    Assert.That(e.InnerExceptions.Count, Is.GreaterThanOrEqualTo(1));
                    Assert.That(e.InnerException.Message, Is.EqualTo("localFinally"));
                }
            });
            ThreadManager.JoinAndVerify();
        }