private async Task <List <BenchmarkTestContent> > PrepareTestData(BenchmarkOption benchmarkOption)
        {
            var list = new List <BenchmarkTestContent>();

            if (!String.IsNullOrEmpty(benchmarkOption.Source))
            {
                // explicit test file
                list.Add(new BenchmarkTestContent(benchmarkOption.Source, false, BenchmarkContent.UserDefined));
                return(list);
            }

            // generate test data
            if ((benchmarkOption.Content & BenchmarkContent.Ascii) == BenchmarkContent.Ascii)
            {
                var testAsciiDataFolder = TestFileHelper.NewFolder();

                await Task.WhenAll(
                    Enumerable.Range(0, benchmarkOption.NumberOfFiles)
                    .Select(i => TestFileHelper.NewFile(testAsciiDataFolder, benchmarkOption.FileSize, true)));

                list.Add(new BenchmarkTestContent(testAsciiDataFolder, true, BenchmarkContent.Ascii));
            }

            if ((benchmarkOption.Content & BenchmarkContent.Binary) == BenchmarkContent.Binary)
            {
                var testBinaryDataFolder = TestFileHelper.NewFolder();

                await Task.WhenAll(
                    Enumerable.Range(0, benchmarkOption.NumberOfFiles)
                    .Select(i => TestFileHelper.NewFile(testBinaryDataFolder, benchmarkOption.FileSize)));

                list.Add(new BenchmarkTestContent(testBinaryDataFolder, true, BenchmarkContent.Binary));
            }
            return(list);
        }
        public async Task <PasswordOption> GenerateCompressPasswordOption(PasswordMode passwordMode, string keysFolder)
        {
            switch (passwordMode)
            {
            case PasswordMode.None:
                return(NoPasswordOption.Nop);

            case PasswordMode.InlinePassword:
                return(new InlinePasswordOption {
                    Password = _pass.ToString("N")
                });

            case PasswordMode.PasswordFile:
                string passwordFile = Path.Combine(keysFolder, "password.txt");
                TestFileHelper.FillFile(passwordFile, "123456");
                return(new PasswordFileOption {
                    PasswordFile = passwordFile
                });

            case PasswordMode.PublicKey:
            {
                var e       = _externalDependencies;
                var keyPair = await CreateKeyPairCommand(e.OpenSsl(), "keypair.pem", KeySize.Key4096).Run(keysFolder, _cancellationTokenSource.Token);

                var publicKey = await CreatePublicKeyCommand(e.OpenSsl(), "keypair.pem", "public.pem").Run(keysFolder, _cancellationTokenSource.Token);

                var privateKey = await CreatePrivateKeyCommand(e.OpenSsl(), "keypair.pem", "private.pem").Run(keysFolder, _cancellationTokenSource.Token);

                keyPair.ThrowOnError();
                publicKey.ThrowOnError();
                privateKey.ThrowOnError();

                return(new PublicKeyPasswordOption
                    {
                        PublicKeyFile = Path.Combine(keysFolder, "public.pem")
                    });
            }

            default:
                throw new ArgumentOutOfRangeException(nameof(passwordMode), passwordMode, null);
            }
        }
        public async Task <OperationSummary> RunBenchmark(BenchmarkOption benchmarkOption)
        {
            var operationSummaries = new List <OperationSummary>();
            var keysFolder         = TestFileHelper.NewFolder();

            var iterations = await _iterationGenerator.PrepareIteration(benchmarkOption);

            var threads = benchmarkOption.Threads == 0 ? Environment.ProcessorCount : benchmarkOption.Threads;

            foreach (var iteration in iterations)
            {
                PasswordMode pm = iteration.Encryption ? PasswordMode.PublicKey : PasswordMode.None;
                var          compressedFolder = TestFileHelper.NewFolder(benchmarkOption.OutputCompressed);
                var          outputFolder     = TestFileHelper.NewFolder(benchmarkOption.OutputDecompressed);

                // compress
                var compressOption = new CompressOption
                {
                    Algo             = iteration.Algo,
                    CompressionRatio = iteration.CompressionRatio,
                    BlockMode        = BlockMode.Individual,
                    SourceDirOrFile  = iteration.Content.Source,
                    DestinationDir   = compressedFolder,
                    Threads          = threads,
                    PasswordOption   = await _benchmarkOptionHelper.GenerateCompressPasswordOption(pm, keysFolder)
                };

                OperationSummary resultCompress = await _tarCompressCrypt.Compress(compressOption);

                if (_cancellationTokenSource.IsCancellationRequested)
                {
                    await Cleanup();

                    return(null);
                }
                operationSummaries.Add(resultCompress);
                resultCompress.ThrowOnError();

                // decompress
                var decompressOption = new DecompressOption
                {
                    SourceDirOrFile = compressedFolder,
                    DestinationDir  = outputFolder,
                    Threads         = threads,
                    PasswordOption  = _benchmarkOptionHelper.GenerateDecompressPasswordOption(pm, keysFolder)
                };

                OperationSummary resultDecompress = await _tarCompressCrypt.Decompress(decompressOption);

                if (_cancellationTokenSource.IsCancellationRequested)
                {
                    await Cleanup();

                    return(null);
                }

                operationSummaries.Add(resultDecompress);
                resultDecompress.ThrowOnError();

                StringBuilder sb = FormatResultSummary(iteration, resultCompress, resultDecompress);

                Console.Out.WriteLine(sb.ToString());

                async Task Cleanup()
                {
                    if (benchmarkOption.Cleanup)
                    {
                        await "del /f /s /q * > NUL".Run(compressedFolder, CancellationToken.None);
                        Directory.Delete(compressedFolder, true);
                        await "del /f /s /q * > NUL".Run(outputFolder, CancellationToken.None);
                        Directory.Delete(outputFolder, true);
                    }
                }

                await Cleanup();
            }

            return(new OperationSummary(operationSummaries.SelectMany(i => i.OperationBlocks), 0, default));
        }