public void SearchTaskRunsWithVariousParallelismValueTest(
            [Values(2, 4, 6, 8, 10, 12, 16, 24, 32)] int degreeOfParallelism)
        {
            // Arrange
            var outputItems = new ConcurrentBag <string>();

            var customHierarchyDelpth = HierarchyDepth - 1;
            var expectedItemsCount    = GetExpectedItems(customHierarchyDelpth, InitialItemsCount, SubItemsCount);

            var options =
                new SearchTaskOptions
            {
                MaxDegreeOfParallelism = degreeOfParallelism,
                MaxHierarchyDepth      = customHierarchyDelpth,
                MaxQueueLength         = int.MaxValue,
                DequeueWaitTimeout     = 10
            };

            // Act
            var cancellationTokenSource = new CancellationTokenSource();
            var task = StartUrlTest(outputItems, cancellationTokenSource.Token, options);

            task.Wait(cancellationTokenSource.Token);

            // Assert
            //if (expectedItemsCount != outputItems.Count)
            //{
            //	outputItems.ToList().ForEach(System.Console.WriteLine);
            //}

            Assert.AreEqual(expectedItemsCount, outputItems.Count);
        }
        public void SearchTaskCompletesWithCustomOptionsTest()
        {
            // Arrange
            var outputItems = new ConcurrentBag <string>();

            var customHierarchyDelpth = HierarchyDepth - 1;
            var expectedItemsCount    = GetExpectedItems(customHierarchyDelpth, InitialItemsCount, SubItemsCount);

            var options =
                new SearchTaskOptions
            {
                MaxDegreeOfParallelism = 2,                         //Environment.ProcessorCount * 2,
                MaxHierarchyDepth      = customHierarchyDelpth,
                MaxQueueLength         = int.MaxValue,
                DequeueWaitTimeout     = 10
            };

            // Act
            var cancellationTokenSource = new CancellationTokenSource();
            var task = StartUrlTest(outputItems, cancellationTokenSource.Token, options);

            task.Wait(cancellationTokenSource.Token);

            // Assert
            //if (expectedItemsCount != outputItems.Count)
            //{
            //	outputItems.ToList().ForEach(System.Console.WriteLine);
            //}

            Assert.AreEqual(expectedItemsCount, outputItems.Count);
        }
        private async Task StartUrlTest(ConcurrentBag <string> outputItems, CancellationToken cancellationToken,
                                        SearchTaskOptions options = null)
        {
            Assert.IsNotNull(outputItems);
            Assert.IsNotNull(cancellationToken);

            var searchOptions = options ??
                                new SearchTaskOptions
            {
                MaxDegreeOfParallelism = Environment.ProcessorCount,
                MaxHierarchyDepth      = HierarchyDepth,
                MaxQueueLength         = int.MaxValue,
                DequeueWaitTimeout     = 5
            };

            var initialUrls = new Collection <string>();

            for (var i = 0; i < InitialItemsCount; i++)
            {
                initialUrls.Add($"http://{i}");
            }

            await SearchTask.StartNew
            (
                initialUrls,
                (url, token) =>
            {
                outputItems.Add(url);

                Thread.Sleep(10);

                var subItems = new Collection <string>();

                for (var i = 0; i < SubItemsCount; i++)
                {
                    subItems.Add($"{url}/{i}");
                }

                return(subItems);
            },
                cancellationToken,
                searchOptions
            );
        }