/// <summary>
        /// Upload the test log to the test blob store
        /// </summary>
        /// <param name="testResult">Test result object that contains the test log </param>
        /// <param name="sasResponseContent">Sas response object containing access token for blob store</param>
        /// <returns>True if log uploaded successfully, otherwise false</returns>
        public static async Task <bool> UploadTestLog(TestLogs logs, JObject sasResponseContent)
        {
            string accessToken  = sasResponseContent["access_token"].ToObject <string>();
            string containerUri = sasResponseContent["container_uri"].ToObject <string>();
            Uri    blobHostUri  = new Uri(containerUri);


            HttpClient c              = new HttpClient();
            string     hash           = logs.LogHash;
            var        blobRequestUri = containerUri + "/" + hash + "?" + accessToken;

            c.DefaultRequestHeaders.Add("x-ms-blob-type", "BlockBlob");
            c.DefaultRequestHeaders.Add("Host", blobHostUri.Host);


            ByteArrayContent byteContent = new ByteArrayContent(Encoding.UTF8.GetBytes(logs.LogLines));

            using (var blobResponse = await c.PutAsync(blobRequestUri, byteContent))
            {
                return(blobResponse.IsSuccessStatusCode);
            }
        }
        /// <summary>
        /// Upload the test log to the test blob store 
        /// </summary>
        /// <param name="testResult">Test result object that contains the test log </param>
        /// <param name="sasResponseContent">Sas response object containing access token for blob store</param>
        /// <returns>True if log uploaded successfully, otherwise false</returns>
        public static async Task<bool> UploadTestLog(TestLogs logs, JObject sasResponseContent)
        {
            string accessToken = sasResponseContent["access_token"].ToObject<string>();
            string containerUri = sasResponseContent["container_uri"].ToObject<string>();
            Uri blobHostUri = new Uri(containerUri);


            HttpClient c = new HttpClient();
            string hash = logs.LogHash;
            var blobRequestUri = containerUri + "/" + hash + "?" + accessToken;
            c.DefaultRequestHeaders.Add("x-ms-blob-type", "BlockBlob");
            c.DefaultRequestHeaders.Add("Host", blobHostUri.Host);


            ByteArrayContent byteContent = new ByteArrayContent(Encoding.UTF8.GetBytes(logs.LogLines));

            using (var blobResponse = await c.PutAsync(blobRequestUri, byteContent))
            {
                return blobResponse.IsSuccessStatusCode;
            }
        }
        /// <summary>
        /// Run the unit tests.
        /// </summary>
        public async void RunAsync()
        {
            // Ensure there's an interface to display the test results.
            if (this.Reporter == null)
            {
                throw new ArgumentNullException("Reporter");
            }

            /// Record the test metadata to the test run object at the start of the test run
            FillTestRunMetaData();

            // Setup the progress/failure counters
            this.Progress = 0;
            this.Failures = 0;

            // Filter out any test methods based on the current settings
            int filteredTestCount = FilterTests();

            // get the actual count of tests going to run
            testRun.TestCount = filteredTestCount;

            // Write out the test status message which may be modified by the
            // filters
            Reporter.Status(this.Settings.TestRunStatusMessage);

            // Enumerators that track the current group and method to execute
            // (which allows reentrancy into the test loop below to resume at
            // the correct location).
            IEnumerator <TestGroup>  groups  = this.Groups.OrderBy(g => g.Name).GetEnumerator();
            IEnumerator <TestMethod> methods = null;

            // Keep a reference to the current group so we can pass it to the
            // Reporter's EndGroup (we don't need one for the test method,
            // however, because we close over in the continuation).
            TestGroup currentGroup = null;

            // Create daylight test run and get the run id
            string runId = String.Empty;

            if (!Settings.ManualMode)
            {
                runId = await TestLogger.CreateDaylightRun(testRun, Settings);
            }

            // Setup the UI
            this.Reporter.StartRun(this);

            // The primary test loop is a "recursive" closure that will pass
            // itself as the continuation to async tests.
            //
            // Note: It's really important for performance to note that any
            // calls to testLoop only occur in the tail position.
            JObject     sasResponseObject = null;
            DateTime    RunStartTime      = DateTime.UtcNow;
            Func <Task> testLoop          = null;

            // Get the SAS token to upload the test logs to upload test logs to blob store
            if (!Settings.ManualMode && !String.IsNullOrEmpty(runId))
            {
                sasResponseObject = await TestLogger.GetSaSToken(Settings);
            }
            testLoop =
                async() =>
            {
                if (methods != null && methods.MoveNext())
                {
                    // If we were in the middle of a test group and there
                    // are more methods to execute, let's move to the next
                    // test method.

                    // Update the progress
                    this.Progress++;
                    Reporter.Progress(this);
                    // Start the test method
                    Reporter.StartTest(methods.Current);
                    if (methods.Current.Excluded)
                    {
                        // Ignore excluded tests and immediately recurse.
                        Reporter.EndTest(methods.Current);
                        await testLoop();
                    }
                    else
                    {
                        // Get the start time for individual tests
                        DateTime testStartTime = DateTime.UtcNow;

                        // Record the test result, upload the test log as a blob and clear the
                        // log for next test
                        Func <Task> recordTestResult = async() =>
                        {
                            if (!Settings.ManualMode && !String.IsNullOrEmpty(runId))
                            {
                                var log = new TestLogs()
                                {
                                    LogLines = LogDump.ToString(),
                                    LogHash  = Guid.NewGuid().ToString()
                                };
                                // record the test result
                                var testResult = new TestResult()
                                {
                                    FullName  = methods.Current.Name,
                                    StartTime = testStartTime,
                                    EndTime   = DateTime.UtcNow,
                                    Outcome   = methods.Current.Passed ? "Passed" : "Failed",
                                    RunId     = runId,
                                    Tags      = new List <string> {
                                        Platform
                                    },
                                    Source = currentGroup.Name,
                                    Logs   = sasResponseObject != null ? log : null
                                };

                                // upload test log to the blob store
                                if (sasResponseObject != null)
                                {
                                    await TestLogger.UploadTestLog(log, sasResponseObject);
                                }

                                // Add the test result to the test result collection, which will eventually
                                // be uploaded to daylight
                                testRun.AddTestResult(testResult);
                                LogDump.Clear();
                            }
                        };
                        // Execute the test method
                        methods.Current.Test.Start(
                            new ActionContinuation
                        {
                            OnSuccess = async() =>
                            {
                                // Mark the test as passing, update the
                                // UI, and continue with the next test.
                                methods.Current.Passed = true;
                                methods.Current.Test   = null;
                                Reporter.EndTest(methods.Current);
                                await recordTestResult();
                                await testLoop();
                            },
                            OnError = async(message) =>
                            {
                                // Mark the test as failing, update the
                                // UI, and continue with the next test.
                                methods.Current.Passed    = false;
                                methods.Current.Test      = null;
                                methods.Current.ErrorInfo = message;
                                this.Failures++;
                                System.Diagnostics.Debug.WriteLine(message);
                                Reporter.Error(message);
                                LogDump.AppendLine(message);
                                Reporter.EndTest(methods.Current);
                                await recordTestResult();
                                await testLoop();
                            }
                        });
                    }
                }
                else if (groups.MoveNext())
                {
                    // If we've finished a test group and there are more,
                    // then move to the next one.

                    // Finish the UI for the last group.
                    if (currentGroup != null)
                    {
                        Reporter.EndGroup(currentGroup);
                        currentGroup = null;
                    }

                    // Setup the UI for this next group
                    currentGroup = groups.Current;
                    Reporter.StartGroup(currentGroup);

                    // Get the methods and immediately recurse which will
                    // start executing them.
                    methods = groups.Current.Methods.OrderBy(m => m.Name).GetEnumerator();
                    await testLoop();
                }
                else
                {
                    if (!Settings.ManualMode && !String.IsNullOrEmpty(runId))
                    {
                        // post all the test results to daylight
                        await TestLogger.PostTestResults(testRun.TestResults.ToList(), Settings);

                        // String to store the test result summary of the entire suite
                        StringBuilder resultLog = new StringBuilder("Total Tests:" + filteredTestCount);
                        resultLog.AppendLine();
                        resultLog.AppendLine("Passed Tests:" + (filteredTestCount - Failures).ToString());
                        resultLog.AppendLine("Failed Tests:" + Failures);
                        resultLog.AppendLine("Detailed Results:" + Settings.Custom["DayLightUrl"] + "/" + Settings.Custom["DaylightProject"] + "/runs/" + runId);

                        var logs = new TestLogs()
                        {
                            LogLines = resultLog.ToString(),
                            LogHash  = Guid.NewGuid().ToString()
                        };
                        // Record the the result of the entire test suite to master test run
                        var testResult = new TestResult()
                        {
                            FullName  = Platform + " " + Settings.Custom["RuntimeVersion"],
                            Name      = Platform + " " + Settings.Custom["RuntimeVersion"],
                            StartTime = RunStartTime,
                            EndTime   = DateTime.UtcNow,
                            Outcome   = Failures > 0 ? "Failed" : "Passed",
                            RunId     = Settings.Custom["MasterRunId"],
                            Tags      = new List <string> {
                                Platform
                            },
                            Source = "Managed",
                            Logs   = sasResponseObject != null ? logs : null
                        };

                        // Upload the log of the test result summary for the test suite
                        if (sasResponseObject != null)
                        {
                            await TestLogger.UploadTestLog(logs, sasResponseObject);
                        }

                        // Post the test suite result to master run
                        await TestLogger.PostTestResults(new List <TestResult> {
                            testResult
                        }, Settings);
                    }
                    // Otherwise if we've finished the entire test run

                    // Finish the UI for the last group and update the
                    // progress after the very last test method.
                    Reporter.EndGroup(currentGroup);
                    Reporter.Progress(this);

                    // Finish the UI for the test run.
                    Reporter.EndRun(this);
                }
            };

            // Start running the tests
            await testLoop();
        }
        /// <summary>
        /// Run the unit tests.
        /// </summary>
        public async void RunAsync()
        {
            // Ensure there's an interface to display the test results.
            if (this.Reporter == null)
            {
                throw new ArgumentNullException("Reporter");
            }

            /// Record the test metadata to the test run object at the start of the test run            
            FillTestRunMetaData();

            // Setup the progress/failure counters
            this.Progress = 0;
            this.Failures = 0;

            // Filter out any test methods based on the current settings
            int filteredTestCount = FilterTests();

            // get the actual count of tests going to run
            testRun.TestCount = filteredTestCount;

            // Write out the test status message which may be modified by the
            // filters
            Reporter.Status(this.Settings.TestRunStatusMessage);

            // Enumerators that track the current group and method to execute
            // (which allows reentrancy into the test loop below to resume at
            // the correct location).
            IEnumerator<TestGroup> groups = this.Groups.OrderBy(g => g.Name).GetEnumerator();
            IEnumerator<TestMethod> methods = null;

            // Keep a reference to the current group so we can pass it to the
            // Reporter's EndGroup (we don't need one for the test method,
            // however, because we close over in the continuation).
            TestGroup currentGroup = null;

            // Create daylight test run and get the run id
            string runId = String.Empty;
            if (!Settings.ManualMode)
            {
                runId = await TestLogger.CreateDaylightRun(testRun, Settings);
            }

            // Setup the UI
            this.Reporter.StartRun(this);

            // The primary test loop is a "recursive" closure that will pass
            // itself as the continuation to async tests.
            // 
            // Note: It's really important for performance to note that any
            // calls to testLoop only occur in the tail position.
            JObject sasResponseObject = null;
            DateTime RunStartTime = DateTime.UtcNow;
            Func<Task> testLoop = null;

            // Get the SAS token to upload the test logs to upload test logs to blob store
            if (!Settings.ManualMode && !String.IsNullOrEmpty(runId))
            {
                sasResponseObject = await TestLogger.GetSaSToken(Settings);

            }
            testLoop =
                async () =>
                {
                    if (methods != null && methods.MoveNext())
                    {
                        // If we were in the middle of a test group and there
                        // are more methods to execute, let's move to the next
                        // test method.

                        // Update the progress
                        this.Progress++;
                        Reporter.Progress(this);
                        // Start the test method
                        Reporter.StartTest(methods.Current);
                        if (methods.Current.Excluded)
                        {
                            // Ignore excluded tests and immediately recurse.
                            Reporter.EndTest(methods.Current);
                            await testLoop();
                        }
                        else
                        {
                            // Get the start time for individual tests
                            DateTime testStartTime = DateTime.UtcNow;

                            // Record the test result, upload the test log as a blob and clear the 
                            // log for next test
                            Func<Task> recordTestResult = async () =>
                            {
                                if (!Settings.ManualMode && !String.IsNullOrEmpty(runId))
                                {
                                    var log = new TestLogs()
                                    {
                                        LogLines = LogDump.ToString(),
                                        LogHash = Guid.NewGuid().ToString()
                                    };
                                    // record the test result
                                    var testResult = new TestResult()
                                    {
                                        FullName = methods.Current.Name,
                                        StartTime = testStartTime,
                                        EndTime = DateTime.UtcNow,
                                        Outcome = methods.Current.Passed ? "Passed" : "Failed",
                                        RunId = runId,
                                        Tags = new List<string> { Platform },
                                        Source = currentGroup.Name,
                                        Logs = sasResponseObject != null ? log : null
                                    };

                                    // upload test log to the blob store
                                    if (sasResponseObject != null)
                                        await TestLogger.UploadTestLog(log, sasResponseObject);

                                    // Add the test result to the test result collection, which will eventually 
                                    // be uploaded to daylight
                                    testRun.AddTestResult(testResult);
                                    LogDump.Clear();
                                }
                            };
                            // Execute the test method
                            methods.Current.Test.Start(
                                new ActionContinuation
                                {
                                    OnSuccess = async () =>
                                    {
                                        // Mark the test as passing, update the
                                        // UI, and continue with the next test.
                                        methods.Current.Passed = true;
                                        methods.Current.Test = null;
                                        Reporter.EndTest(methods.Current);
                                        await recordTestResult();
                                        await testLoop();
                                    },
                                    OnError = async (message) =>
                                    {
                                        // Mark the test as failing, update the
                                        // UI, and continue with the next test.
                                        methods.Current.Passed = false;
                                        methods.Current.Test = null;
                                        methods.Current.ErrorInfo = message;
                                        this.Failures++;
                                        System.Diagnostics.Debug.WriteLine(message);
                                        Reporter.Error(message);
                                        LogDump.AppendLine(message);
                                        Reporter.EndTest(methods.Current);
                                        await recordTestResult();
                                        await testLoop();
                                    }
                                });
                        }

                    }
                    else if (groups.MoveNext())
                    {
                        // If we've finished a test group and there are more,
                        // then move to the next one.

                        // Finish the UI for the last group.
                        if (currentGroup != null)
                        {
                            Reporter.EndGroup(currentGroup);
                            currentGroup = null;
                        }

                        // Setup the UI for this next group
                        currentGroup = groups.Current;
                        Reporter.StartGroup(currentGroup);

                        // Get the methods and immediately recurse which will
                        // start executing them.
                        methods = groups.Current.Methods.OrderBy(m => m.Name).GetEnumerator();
                        await testLoop();
                    }
                    else
                    {
                        if (!Settings.ManualMode && !String.IsNullOrEmpty(runId))
                        {
                            // post all the test results to daylight
                            await TestLogger.PostTestResults(testRun.TestResults.ToList(), Settings);

                            // String to store the test result summary of the entire suite
                            StringBuilder resultLog = new StringBuilder("Total Tests:" + filteredTestCount);
                            resultLog.AppendLine();
                            resultLog.AppendLine("Passed Tests:" + (filteredTestCount - Failures).ToString());
                            resultLog.AppendLine("Failed Tests:" + Failures);
                            resultLog.AppendLine("Detailed Results:" + Settings.Custom["DayLightUrl"] + "/" + Settings.Custom["DaylightProject"] + "/runs/" + runId);

                            var logs = new TestLogs()
                            {
                                LogLines = resultLog.ToString(),
                                LogHash = Guid.NewGuid().ToString()
                            };
                            // Record the the result of the entire test suite to master test run
                            var testResult = new TestResult()
                            {
                                FullName = Platform + " " + Settings.Custom["RuntimeVersion"],
                                Name = Platform + " " + Settings.Custom["RuntimeVersion"],
                                StartTime = RunStartTime,
                                EndTime = DateTime.UtcNow,
                                Outcome = Failures > 0 ? "Failed" : "Passed",
                                RunId = Settings.Custom["MasterRunId"],
                                Tags = new List<string> { Platform },
                                Source = "Managed",
                                Logs = sasResponseObject != null ? logs : null
                            };

                            // Upload the log of the test result summary for the test suite
                            if (sasResponseObject != null)
                                await TestLogger.UploadTestLog(logs, sasResponseObject);

                            // Post the test suite result to master run
                            await TestLogger.PostTestResults(new List<TestResult> { testResult }, Settings);
                        }
                        // Otherwise if we've finished the entire test run

                        // Finish the UI for the last group and update the
                        // progress after the very last test method.
                        Reporter.EndGroup(currentGroup);
                        Reporter.Progress(this);

                        // Finish the UI for the test run.
                        Reporter.EndRun(this);
                    }
                };

            // Start running the tests
            await testLoop();
        }