public Test
     (TestReporter reporter,
     CloudStorageAccount storageAccount,
     CloudBlobContainer container)
 {
     Reporter       = reporter;
     StorageAccount = storageAccount;
     Container      = container;
 }
        public UploadTestBlobs
            (TestReporter testReporter,
            CloudStorageAccount storageAccount,
            CloudBlobContainer container,
            string[] testArgs) :
            base(testReporter, storageAccount, container)
        {
            if (!ParseArguments(testArgs, out string blobPrefix, out ulong nBlobsToUpload, out ulong blobSizeBytes))
            {
                throw new ArgumentException("The provided parameters were incorrect.");
            }

            BlobPrefix     = blobPrefix;
            NBlobsToUpload = nBlobsToUpload;
            BlobSizeBytes  = blobSizeBytes;
        }
        public RandomDownloadTest
            (TestReporter testReporter,
            CloudStorageAccount storageAccount,
            CloudBlobContainer container,
            string[] downloadTestArgs) :
            base(testReporter, storageAccount, container)
        {
            if (!ParseArguments(downloadTestArgs, out string blobPrefix, out ulong nBlobsToDownload, out long nBytesToDownloadPerBlob, out ulong?nBlobsAvailable, out uint?reportFrequency, out double?percentile))
            {
                throw new ArgumentException("The provided parameters were incorrect.");
            }
            BlobPrefix       = blobPrefix;
            NBlobsToDownload = nBlobsToDownload;

            if (reportFrequency != null && percentile != null)
            {
                TestProgressReporter progressReporter = new TestProgressReporter(reportFrequency.Value, percentile.Value, NBlobsToDownload);
                testReporter.EntryAddedEvent += progressReporter.ProcessTestEntry;
            }

            if (nBlobsAvailable != null)
            {
                NBlobsAvailable = nBlobsAvailable.Value;
            }
            else
            {
                // Determine the number of blobs that exist in the container (not interested in tracking ListBlob perf here).
                NBlobsAvailable = GetNumBlobsInContainer().Result;
            }
            if (NBlobsAvailable > 0)
            {
                NBytesPerBlob = GetBytesPerBlob().Result;
                if (nBytesToDownloadPerBlob > NBytesPerBlob)
                {
                    throw new Exception($"Requested number of bytes to download per blob ({nBytesToDownloadPerBlob}) is greater than the size of blobs in container '{container.Name}' ({NBytesPerBlob}).");
                }
                NBytesPerBlob = nBytesToDownloadPerBlob;
            }
            else
            {
                throw new Exception($"No blobs exist in the specified container '{container.Name}'.");
            }
        }
        public ListBlobsTest
            (TestReporter testReporter,
            CloudStorageAccount storageAccount,
            CloudBlobContainer container,
            string[] args) :
            base(testReporter, storageAccount, container)
        {
            if (!ParseArguments(args, out string blobPrefix, out ulong nListOperations, out uint?reportFrequency, out double?percentile))
            {
                throw new ArgumentException("The provided parameters were incorrect.");
            }

            BlobPrefix      = blobPrefix;
            NListOperations = nListOperations;

            if (reportFrequency != null && percentile != null)
            {
                TestProgressReporter progressReporter = new TestProgressReporter(reportFrequency.Value, percentile.Value, NListOperations);
                testReporter.EntryAddedEvent += progressReporter.ProcessTestEntry;
            }
        }
        public PutBlockTest
            (TestReporter testReporter,
            CloudStorageAccount storageAccount,
            CloudBlobContainer container,
            string[] testArgs) :
            base(testReporter, storageAccount, container)
        {
            if (!ParseArguments(testArgs, out string blobPrefix, out ulong nBlocksToUpload, out ulong blockSizeBytes, out uint?reportFrequency, out double?percentile))
            {
                throw new ArgumentException("The provided parameters were incorrect.");
            }

            BlobPrefix      = blobPrefix;
            NBlocksToUpload = nBlocksToUpload;
            BlockSizeBytes  = blockSizeBytes;

            if (reportFrequency != null && percentile != null)
            {
                TestProgressReporter progressReporter = new TestProgressReporter(reportFrequency.Value, percentile.Value, nBlocksToUpload);
                testReporter.EntryAddedEvent += progressReporter.ProcessTestEntry;
            }
        }
        static void Main(string[] args)
        {
            // Parse base-level commmand line arguments.
            if (!ParseBaseArguments(args, out string containerName, out string storageAccountNameEnvVar, out string storageAccountSasEnvVar, out string outputFilePath, out string environment, out bool useHttps, out string testType, out string[] testArgs))
            {
                return;
            }

            try
            {
                CloudStorageAccount storageAccount = GetStorageAccount(storageAccountNameEnvVar, storageAccountSasEnvVar, environment);
                CloudBlobClient     blobClient     = storageAccount.CreateCloudBlobClient();
                CloudBlobContainer  container      = blobClient.GetContainerReference(containerName);

                // Create and Execute the Test.
                TestReporter reporter = new TestReporter();

                Test test = null;
                switch (testType.ToUpper())
                {
                case "PUTBLOBTEST":
                    test = new PutBlobTest(reporter, storageAccount, container, testArgs);
                    break;

                case "PUTBLOCKTEST":
                    test = new PutBlockTest(reporter, storageAccount, container, testArgs);
                    break;

                case "RANDOMDOWNLOADTEST":
                    test = new RandomDownloadTest(reporter, storageAccount, container, testArgs);
                    break;

                case "UPLOADTESTBLOBS":
                    test = new UploadTestBlobs(reporter, storageAccount, container, testArgs);
                    break;

                case "LISTBLOBSTEST":
                    test = new ListBlobsTest(reporter, storageAccount, container, testArgs);
                    break;

                default:
                    throw new NotImplementedException($"A test named {testType} has not been implemented.");
                }

                // Run the test on the managed thread pool.
                Task testTask = Task.Run(async() => { await test.Run(); });

                Console.WriteLine($"Test running.  Streaming details to output file '{outputFilePath}'.");

                // Flush the logs once per second to file until the test is complete.
                using (FileStream filestream = new FileStream(outputFilePath, FileMode.CreateNew, FileAccess.Write))
                {
                    // Periodically trigger a log flush (run on the thread pool) while we wait for the test to complete.
                    while (!testTask.IsCompleted)
                    {
                        Task.Run(async() =>
                        {
                            Task[] reportingTasks = new Task[]
                            {
                                reporter.ReportAllAsync(filestream, false),
                                Task.Delay(1000)
                            };

                            await Task.WhenAll(reportingTasks);
                        }).Wait();
                    }

                    if (testTask.IsFaulted)
                    {
                        throw testTask.Exception;
                    }

                    // One last flush to capture any final logs.
                    reporter.ReportAllAsync(filestream, false).Wait();
                }

                Console.WriteLine($"The test completed successfully.");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Test failed.  Details: {ex.Message}");
            }
        }