public async Task RunAsync_SubProcessListSupplied_AllAreRun(int processCount)
        {
            // arrange
            var processId    = 0;
            var expectedKeys = Enumerable.Range(1, processCount);
            var dict         = new ConcurrentDictionary <int, DateTime>();

            _fixture.Register(() =>
            {
                var process = A.Fake <IProcess>();
                A.CallTo(() => process.RunAsync(CancellationToken.None)).ReturnsLazily(() =>
                {
                    var id = Interlocked.Increment(ref processId);
                    dict.TryAdd(id, DateTime.Now);
                    return(Task.CompletedTask);
                });
                return(process);
            });

            var processes = _fixture.CreateMany <IProcess>(processCount);
            var sut       = new ParallelProcess(processes);

            // act
            await sut.RunAsync(CancellationToken.None);

            // assert
            dict.Should().ContainKeys(expectedKeys);
        }
        public async Task RunAsync_ManyProcesses_RunInParallel(int processCount)
        {
            // arrange
            var processIdCounter              = 0;
            var runOrder                      = new BlockingCollection <int>(processCount);
            var parallelProcessCounter        = 0;
            var maxProcessesRunningInParallel = 0;
            var randomizer                    = new Random(Environment.TickCount);

            _fixture.Register(() =>
            {
                var process   = A.Fake <IProcess>();
                var processId = Interlocked.Increment(ref processIdCounter);

                A.CallTo(() => process.RunAsync(CancellationToken.None)).ReturnsLazily(async() =>
                {
                    var runningProcesses = Interlocked.Increment(ref parallelProcessCounter);

                    maxProcessesRunningInParallel = Math.Max(runningProcesses, maxProcessesRunningInParallel);
                    await Task.Delay(randomizer.Next(minValue: 1, maxValue: 100));

                    runOrder.Add(processId);
                    Interlocked.Decrement(ref parallelProcessCounter);
                });

                return(process);
            });

            var processes = _fixture.CreateMany <IProcess>(processCount);
            var sut       = new ParallelProcess(processes);

            // act
            await sut.RunAsync(CancellationToken.None);

            // assert
            maxProcessesRunningInParallel.Should().BeGreaterOrEqualTo(2);
            runOrder.Should().HaveCount(processCount);
            runOrder.Should().NotBeAscendingInOrder();
        }