/// <summary>
        /// Converts the log entries stored within the provided test result into equivalent
        /// Microsoft.VisualStudio.TestPlatform.ObjectModel.TestResultMessages
        /// </summary>
        /// <param name="result">The Boost.Test.Result.TestResult whose LogEntries are to be converted.</param>
        /// <returns>An enumeration of TestResultMessage equivalent to the Boost log entries stored within the provided TestResult.</returns>
        private static IEnumerable <TestResultMessage> GetTestMessages(BoostTestAdapter.Boost.Results.TestResult result)
        {
            foreach (LogEntry entry in result.LogEntries)
            {
                string category = null;

                if (
                    (entry is LogEntryInfo) ||
                    (entry is LogEntryMessage) ||
                    (entry is LogEntryStandardOutputMessage)
                    )
                {
                    category = TestResultMessage.StandardOutCategory;
                }
                else if (
                    (entry is LogEntryWarning) ||
                    (entry is LogEntryError) ||
                    (entry is LogEntryFatalError) ||
                    (entry is LogEntryMemoryLeak) ||
                    (entry is LogEntryException) ||
                    (entry is LogEntryStandardErrorMessage)
                    )
                {
                    category = TestResultMessage.StandardErrorCategory;
                }
                else
                {
                    // Skip unknown message types
                    continue;
                }

                yield return(new TestResultMessage(category, GetTestResultMessageText(result.Unit, entry)));
            }
        }
        /// <summary>
        /// Asserts BoostTestResult against the expected details
        /// </summary>
        /// <param name="testResult">The BoostTestResult to test</param>
        /// <param name="parentTestResult">The expected parent BoostTestResult of testResult</param>
        /// <param name="name">The expected TestCase display name</param>
        /// <param name="result">The expected TestCase execution result</param>
        /// <param name="assertionsPassed">The expected number of passed assertions (e.g. BOOST_CHECKS)</param>
        /// <param name="assertionsFailed">The expected number of failed assertions (e.g. BOOST_CHECKS, BOOST_REQUIRE, BOOST_FAIL etc.)</param>
        /// <param name="expectedFailures">The expected number of expected test failures</param>
        private void AssertReportDetails(
            BoostTestResult testResult,
            BoostTestResult parentTestResult,
            string name,
            TestResultType result,
            uint assertionsPassed,
            uint assertionsFailed,
            uint expectedFailures
            )
        {
            Assert.That(testResult.Unit.Name, Is.EqualTo(name));

            if (parentTestResult == null)
            {
                Assert.That(testResult.Unit.Parent, Is.Null);
            }
            else
            {
                Assert.That(parentTestResult.Unit, Is.EqualTo(testResult.Unit.Parent));
            }

            Assert.That(testResult.Result, Is.EqualTo(result));

            Assert.That(testResult.AssertionsPassed, Is.EqualTo(assertionsPassed));
            Assert.That(testResult.AssertionsFailed, Is.EqualTo(assertionsFailed));
            Assert.That(testResult.ExpectedFailures, Is.EqualTo(expectedFailures));
        }
        /// <summary>
        /// Enumerates all log entries which are deemed to be an error (i.e. Warning, Error, Fatal Error and Exception).
        /// </summary>
        /// <param name="result">The TestResult which hosts the log entries.</param>
        /// <returns>An enumeration of error flagging log entries.</returns>
        private static IEnumerable <LogEntry> GetErrors(BoostTestAdapter.Boost.Results.TestResult result)
        {
            IEnumerable <LogEntry> errors = result.LogEntries.Where((e) =>
                                                                    (e is LogEntryWarning) ||
                                                                    (e is LogEntryError) ||
                                                                    (e is LogEntryFatalError) ||
                                                                    (e is LogEntryException)
                                                                    );

            // Only provide a single memory leak error if the test succeeded successfully (i.e. all asserts passed)
            return(errors.Any() ? errors : result.LogEntries.Where((e) => (e is LogEntryMemoryLeak)).Take(1));
        }
Exemple #4
0
        /// <summary>
        /// Converts a Boost Test Result into an equivalent Visual Studio Test result
        /// </summary>
        /// <param name="test">The test case under consideration</param>
        /// <param name="result">The Boost test result for the test case under consideration</param>
        /// <param name="start">The test starting time</param>
        /// <param name="end">The test ending time</param>
        /// <returns>A Visual Studio test result equivalent to the Boost Test result</returns>
        private static VSTestResult GenerateResult(VSTestCase test, BoostTestResult result, DateTimeOffset start, DateTimeOffset end)
        {
            Code.Require(test, "test");
            Code.Require(result, "result");

            // Convert the Boost.Test.Result data structure into an equivalent Visual Studio model
            VSTestResult vsResult = result.AsVSTestResult(test);

            vsResult.StartTime = start;
            vsResult.EndTime   = end;

            return(vsResult);
        }
        /// <summary>
        /// Compresses a message so that it is suitable for the UI.
        /// </summary>
        /// <param name="result">The erroneous LogEntry whose message is to be displayed.</param>
        /// <returns>A compressed message suitable for UI.</returns>
        private static string GetErrorMessage(BoostTestAdapter.Boost.Results.TestResult result)
        {
            StringBuilder sb = new StringBuilder();

            foreach (LogEntry error in GetErrors(result))
            {
                sb.Append(error.Detail).Append(Environment.NewLine);
            }

            // Remove redundant NewLine at the end
            sb.Remove((sb.Length - Environment.NewLine.Length), Environment.NewLine.Length);

            return(sb.ToString());
        }
Exemple #6
0
        /// <summary>
        /// Converts a Boost.Test.Result.TestResult model into an equivalent
        /// Microsoft.VisualStudio.TestPlatform.ObjectModel.TestResult model.
        /// </summary>
        /// <param name="result">The Boost.Test.Result.TestResult model to convert.</param>
        /// <param name="test">The Microsoft.VisualStudio.TestPlatform.ObjectModel.TestCase model which is related to the result.</param>
        /// <returns>The Boost.Test.Result.TestResult model converted into its Microsoft.VisualStudio.TestPlatform.ObjectModel.TestResult counterpart.</returns>
        public static VSTestResult AsVSTestResult(this BoostTestAdapter.Boost.Results.TestResult result, VSTestCase test)
        {
            Utility.Code.Require(result, "result");
            Utility.Code.Require(test, "test");

            VSTestResult vsResult = new VSTestResult(test);

            vsResult.ComputerName = Environment.MachineName;

            vsResult.Outcome = GetTestOutcome(result.Result);

            // Boost.Test.Result.TestResult.Duration is in microseconds

            // 1 millisecond = 10,000 ticks
            // => 1 microsecond = 10 ticks
            // Reference: https://msdn.microsoft.com/en-us/library/zz841zbz(v=vs.110).aspx
            long ticks = (long)Math.Min((result.Duration * 10), long.MaxValue);

            // Clamp tick count to 1 in case Boost duration is listed as 0
            vsResult.Duration = new TimeSpan(Math.Max(ticks, 1));

            if (result.LogEntries.Count > 0)
            {
                foreach (TestResultMessage message in GetTestMessages(result))
                {
                    vsResult.Messages.Add(message);
                }

                // Test using the TestOutcome type since elements from the
                // Boost Result type may be collapsed into a particular value
                if (vsResult.Outcome == VSTestOutcome.Failed)
                {
                    LogEntry error = GetLastError(result);

                    if (error != null)
                    {
                        vsResult.ErrorMessage = GetErrorMessage(result);

                        if (error.Source != null)
                        {
                            //String format for a hyper linkable Stack Trace
                            //Reference: NUnit3 Test Adapter.
                            vsResult.ErrorStackTrace = string.Format(CultureInfo.InvariantCulture, "at {0}() in {1}:line {2}", vsResult.TestCase.DisplayName, ConvertSlashes(error.Source.File), error.Source.LineNumber);
                        }
                    }
                }
            }

            return(vsResult);
        }
        /// <summary>
        /// Generates TestResults based on Boost Test result output.
        /// </summary>
        /// <param name="testRun">The tests which have been executed in the prior test run.</param>
        /// <param name="start">The test execution start time.</param>
        /// <param name="end">The test execution end time.</param>
        /// <param name="settings">boost test adapter settings</param>
        /// <returns>A Visual Studio TestResult related to the executed test.</returns>
        private static IEnumerable <VSTestResult> GenerateTestResults(TestRun testRun, DateTimeOffset start, DateTimeOffset end, BoostTestAdapterSettings settings)
        {
            TestResultCollection results = new TestResultCollection();

            try
            {
                results.Parse(testRun.Arguments, settings);
            }
            catch (XmlException)
            {
                string text = ((File.Exists(testRun.Arguments.ReportFile)) ? File.ReadAllText(testRun.Arguments.ReportFile) : string.Empty);

                if (text.Trim().StartsWith(TestNotFound, StringComparison.Ordinal))
                {
                    return(testRun.Tests.Select(GenerateNotFoundResult));
                }
                else
                {
                    // Represent result parsing exception as a test fatal error
                    if (string.IsNullOrEmpty(text))
                    {
                        text = "Boost Test result file was not found or is empty.";
                    }

                    return(testRun.Tests.Select(test => {
                        Boost.Results.TestResult exception = new Boost.Results.TestResult(results);

                        exception.Unit = Boost.Test.TestUnit.FromFullyQualifiedName(test.FullyQualifiedName);

                        // NOTE Divide by 10 to compensate for duration calculation described in VSTestResult.AsVSTestResult(this Boost.Results.TestResult, VSTestCase)
                        exception.Duration = ((ulong)(end - start).Ticks) / 10;

                        exception.Result = TestResultType.Failed;
                        exception.LogEntries.Add(new Boost.Results.LogEntryTypes.LogEntryFatalError(text));

                        return GenerateResult(test, exception, start, end);
                    }));
                }
            }

            return(testRun.Tests.
                   Select(test =>
            {
                // Locate the test result associated to the current test
                Boost.Results.TestResult result = results[test.FullyQualifiedName];
                return (result == null) ? null : GenerateResult(test, result, start, end);
            }).
                   Where(result => (result != null)));
        }
Exemple #8
0
            /// <summary>
            /// Generates a BoostTestResult instance from the contained configuration.
            /// </summary>
            /// <returns>A BoostTestResult instance based on the pre-set configuration</returns>
            public BoostTestResult Build()
            {
                BoostTestResult result = new BoostTestResult(null);

                result.Result   = this.ResultType;
                result.Unit     = this.Unit;
                result.Duration = this.TimeDuration;

                foreach (LogEntry entry in this.Logs)
                {
                    result.LogEntries.Add(entry);
                }

                return(result);
            }
Exemple #9
0
        /// <summary>
        /// Generates TestResults based on Boost Test result output.
        /// </summary>
        /// <param name="testRun">The tests which have been executed in the prior test run.</param>
        /// <param name="start">The test execution start time.</param>
        /// <param name="end">The test execution end time.</param>
        /// <param name="settings">boost test adapter settings</param>
        /// <returns>A Visual Studio Test result related to the executed test.</returns>
        private static IEnumerable <VSTestResult> GenerateTestResults(TestRun testRun, DateTimeOffset start, DateTimeOffset end, BoostTestAdapterSettings settings)
        {
            IDictionary <string, BoostTestResult> results;

            try
            {
                results = BoostTestResultParser.Parse(testRun.Arguments, settings);
            }
            catch (FileNotFoundException ex)
            {
                Logger.Exception(ex, "Boost.Test result file [{0}] was not found", ex.FileName);

                // Represent result parsing exception as a test fatal error
                return(testRun.Tests.Select(test => GenerateTestFailure(test, "Boost.Test result file was not found.", start, end)));
            }
            catch (XmlException ex)
            {
                Logger.Exception(ex, "Failed to parse Boost.Test result file as XML");

                string text = File.ReadAllText(testRun.Arguments.ReportFile);

                if (text.Trim().StartsWith(TestNotFound, StringComparison.Ordinal))
                {
                    Logger.Warn("Boost.Test could not run test batch [{0}] since a test could not be found", testRun.Tests);

                    return(testRun.Tests.Select(GenerateNotFoundResult));
                }
                else
                {
                    if (string.IsNullOrEmpty(text))
                    {
                        Logger.Warn("Boost.Test report file was empty");
                    }

                    return(testRun.Tests.Select(test => GenerateTestFailure(test, text, start, end)));
                }
            }

            return(testRun.Tests.
                   Select(test =>
            {
                // Locate the test result associated to the current test
                BoostTestResult result = null;
                return (results.TryGetValue(test.FullyQualifiedName, out result)) ? GenerateResult(test, result, start, end) : null;
            }).
                   Where(result => (result != null)));
        }
Exemple #10
0
        /// <summary>
        /// Generates a generic test failure
        /// </summary>
        /// <param name="test">The test which is to be considered as failed (regardless of its outcome)</param>
        /// <param name="error">The error detail string</param>
        /// <param name="start">The test execution start time</param>
        /// <param name="end">The test execution end time</param>
        /// <returns>A failing VSTestResult with the provided error information</returns>
        private static VSTestResult GenerateTestFailure(VSTestCase test, string error, DateTimeOffset start, DateTimeOffset end)
        {
            // Represent the test failure with a dummy result to make use of GenerateResult
            var exception = new BoostTestResult();

            exception.Unit = Boost.Test.TestUnit.FromFullyQualifiedName(test.FullyQualifiedName);

            // NOTE Divide by 10 to compensate for duration calculation described in VSTestResult.AsVSTestResult(this Boost.Results.TestResult, VSTestCase)
            exception.Duration = ((ulong)(end - start).Ticks) / 10;

            exception.Result = TestResultType.Failed;
            exception.LogEntries.Add(new Boost.Results.LogEntryTypes.LogEntryFatalError()
            {
                Detail = error
            });

            return(GenerateResult(test, exception, start, end));
        }
        /// <summary>
        /// Converts a Boost.Test.Result.TestResult model into an equivalent
        /// Microsoft.VisualStudio.TestPlatform.ObjectModel.TestResult model.
        /// </summary>
        /// <param name="result">The Boost.Test.Result.TestResult model to convert.</param>
        /// <param name="test">The Microsoft.VisualStudio.TestPlatform.ObjectModel.TestCase model which is related to the result.</param>
        /// <returns>The Boost.Test.Result.TestResult model converted into its Microsoft.VisualStudio.TestPlatform.ObjectModel.TestResult counterpart.</returns>
        public static VSTestResult AsVSTestResult(this BoostTestAdapter.Boost.Results.TestResult result, VSTestCase test)
        {
            Utility.Code.Require(result, "result");
            Utility.Code.Require(test, "test");

            VSTestResult vsResult = new VSTestResult(test);

            vsResult.ComputerName = Environment.MachineName;

            vsResult.Outcome = GetTestOutcome(result.Result);

            // Boost.Test.Result.TestResult.Duration is in microseconds

            // 1 millisecond = 10,000 ticks
            // => 1 microsecond = 10 ticks
            // Reference: https://msdn.microsoft.com/en-us/library/zz841zbz(v=vs.110).aspx
            long ticks = (long)Math.Min((result.Duration * 10), long.MaxValue);

            // Clamp tick count to 1 in case Boost duration is listed as 0
            vsResult.Duration = new TimeSpan(Math.Max(ticks, 1));

            if (result.LogEntries.Count > 0)
            {
                foreach (TestResultMessage message in GetTestMessages(result))
                {
                    vsResult.Messages.Add(message);
                }

                // Test using the TestOutcome type since elements from the
                // Boost Result type may be collapsed into a particular value
                if (vsResult.Outcome == VSTestOutcome.Failed)
                {
                    LogEntry error = GetLastError(result);

                    if (error != null)
                    {
                        vsResult.ErrorMessage    = GetErrorMessage(result);
                        vsResult.ErrorStackTrace = ((error.Source == null) ? null : error.Source.ToString());
                    }
                }
            }

            return(vsResult);
        }
        /// <summary>
        /// Aggregates the two results as one result structure if compatible.
        /// </summary>
        /// <param name="lhs">The left-hand side result to aggregate</param>
        /// <param name="rhs">The right-hand side result to aggregate</param>
        /// <returns>A TestResult instance consisting of both results as one or lhs in case of incompatibilities</returns>
        private static TestResult Aggregate(TestResult lhs, TestResult rhs)
        {
            // If lhs and rhs are incompatible, return the first non-null argument
            if ((lhs == null) || (rhs == null) || (lhs.Collection != rhs.Collection) || (lhs.Unit.FullyQualifiedName != rhs.Unit.FullyQualifiedName))
            {
                return ((lhs != null) ? lhs : rhs);
            }

            TestResult rvalue = new TestResult(lhs.Collection);
            rvalue.Unit = lhs.Unit;

            // Select the worst of the result types
            int result = Math.Max((int) lhs.Result, (int) rhs.Result);
            rvalue.Result = (TestResultType) result;

            // Sum up totals
            rvalue.AssertionsPassed = lhs.AssertionsPassed + rhs.AssertionsPassed;
            rvalue.AssertionsFailed = lhs.AssertionsFailed + rhs.AssertionsFailed;
            rvalue.ExpectedFailures = lhs.ExpectedFailures + rhs.ExpectedFailures;

            return rvalue;
        }
 /// <summary>
 /// Asserts general log details contained within a BoostTestResult
 /// </summary>
 /// <param name="testResult">The BoostTestResult to test</param>
 /// <param name="duration">The expected test case execution duration</param>
 private void AssertLogDetails(BoostTestResult testResult, uint duration)
 {
     AssertLogDetails(testResult, duration, new List<LogEntry>());
 }
        /// <summary>
        /// Parses a TestCase log node.
        /// </summary>
        /// <param name="node">The TestCase Xml node to parse.</param>
        /// <param name="path">The QualifiedNameBuilder which hosts the current fully qualified path.</param>
        /// <param name="collection">The TestResultCollection which will host the result.</param>
        private static void ParseTestCaseLog(XmlNode node, QualifiedNameBuilder path, TestResultCollection collection)
        {
            // Temporarily push TestCase on TestSuite name builder to acquire the fully qualified name of the TestCase
            path.Push(node.Attributes[Xml.Name].Value);

            // Acquire result record of this TestCase
            TestResult result = collection[path.ToString()];
            if (result == null)
            {
                result = new TestResult(collection);
                collection[path.ToString()] = result;
            }

            // Reset path to original value
            path.Pop();

            XmlNode testingTime = node.SelectSingleNode(Xml.TestingTime);

            if (testingTime != null)
            {
                // Boost test testing time is listed in microseconds
                result.Duration = ulong.Parse(testingTime.InnerText, CultureInfo.InvariantCulture);
            }

            ParseTestCaseLogEntries(node.ChildNodes, result);
        }
        /// <summary>
        /// Generates TestResults based on Boost Test result output.
        /// </summary>
        /// <param name="testRun">The tests which have been executed in the prior test run.</param>
        /// <param name="start">The test execution start time.</param>
        /// <param name="end">The test execution end time.</param>
        /// <param name="settings">boost test adapter settings</param>
        /// <returns>A Visual Studio TestResult related to the executed test.</returns>
        private static IEnumerable<VSTestResult> GenerateTestResults(TestRun testRun, DateTimeOffset start, DateTimeOffset end, BoostTestAdapterSettings settings)
        {
            TestResultCollection results = new TestResultCollection();

            try
            {
                results.Parse(testRun.Arguments, settings);
            }
            catch (XmlException)
            {
                string text = ((File.Exists(testRun.Arguments.ReportFile)) ? File.ReadAllText(testRun.Arguments.ReportFile) : string.Empty);

                if (text.Trim().StartsWith(TestNotFound, StringComparison.Ordinal))
                {
                    return testRun.Tests.Select(GenerateNotFoundResult);
                }
                else
                {
                    // Represent result parsing exception as a test fatal error
                    if (string.IsNullOrEmpty(text))
                    {
                        text = "Boost Test result file was not found or is empty.";
                    }

                    return testRun.Tests.Select(test => {
                        Boost.Results.TestResult exception = new Boost.Results.TestResult(results);

                        exception.Unit = Boost.Test.TestUnit.FromFullyQualifiedName(test.FullyQualifiedName);

                        // NOTE Divide by 10 to compensate for duration calculation described in VSTestResult.AsVSTestResult(this Boost.Results.TestResult, VSTestCase)
                        exception.Duration = ((ulong)(end - start).Ticks) / 10;

                        exception.Result = TestResultType.Failed;
                        exception.LogEntries.Add(new Boost.Results.LogEntryTypes.LogEntryFatalError(text));

                        return GenerateResult(test, exception, start, end);
                    });
                }
            }

            return testRun.Tests.
                Select(test =>
                {
                    // Locate the test result associated to the current test
                    Boost.Results.TestResult result = results[test.FullyQualifiedName];
                    return (result == null) ? null : GenerateResult(test, result, start, end);
                }).
                Where(result => (result != null));
        }
        /// <summary>
        /// Parses Log Entries from the collection of log nodes.
        /// </summary>
        /// <param name="nodes">The collection of Xml nodes which are valid LogEntry nodes.</param>
        /// <param name="result">The TestResult which will host the parsed LogEntries.</param>
        private static void ParseTestCaseLogEntries(XmlNodeList nodes, TestResult result)
        {
            foreach (XmlNode child in nodes)
            {
                if (child.NodeType == XmlNodeType.Element)
                {
                    LogEntry entry = null;

                    switch (child.Name)
                    {
                        case Xml.Info: entry = new LogEntryInfo(child.InnerText); break;
                        case Xml.Message: entry = new LogEntryMessage(child.InnerText); break;
                        case Xml.Warning: entry = new LogEntryWarning(child.InnerText); break;
                        case Xml.Error: entry = new LogEntryError(child.InnerText); break;
                        case Xml.FatalError: entry = new LogEntryFatalError(child.InnerText); break;
                        case Xml.Exception: entry = ParseTestCaseLogException(child); break;
                    }

                    if (entry != null)
                    {
                        entry.Source = ParseSourceInfo(child);
                        result.LogEntries.Add(entry);
                    }
                }
            }
        }
        /// <summary>
        /// Parses a general test result information from the provided node.
        /// </summary>
        /// <param name="node">The XPathNavigator pointing to a TestUnit node.</param>
        /// <param name="unit">The test unit for which the test results are related to.</param>
        /// <param name="collection">The TestResultCollection which will host the result.</param>
        private static TestResult ParseTestResult(XPathNavigator node, TestUnit unit, TestResultCollection collection)
        {
            TestResult result = new TestResult(collection);

            result.Unit = unit;
            result.Result = ParseResultType(node.GetAttribute(Xml.Result, string.Empty));

            result.AssertionsPassed = uint.Parse(node.GetAttribute(Xml.AssertionsPassed, string.Empty), CultureInfo.InvariantCulture);
            result.AssertionsFailed = uint.Parse(node.GetAttribute(Xml.AssertionsFailed, string.Empty), CultureInfo.InvariantCulture);
            result.ExpectedFailures = uint.Parse(node.GetAttribute(Xml.ExpectedFailures, string.Empty), CultureInfo.InvariantCulture);

            return result;
        }
 /// <summary>
 /// Given a TestResult returns the last error type log entry.
 /// </summary>
 /// <param name="result">The TestResult which hosts the necessary log entries</param>
 /// <returns>The last error type log entry or null if none are available.</returns>
 private static LogEntry GetLastError(BoostTestAdapter.Boost.Results.TestResult result)
 {
     // Select the last error issued within a Boost Test report
     return(GetErrors(result).LastOrDefault());
 }
        /// <summary>
        /// Asserts general log details contained within a BoostTestResult
        /// </summary>
        /// <param name="testResult">The BoostTestResult to test</param>
        /// <param name="duration">The expected test case execution duration</param>
        /// <param name="entries">The expected list of log entries generated from test case execution</param>
        private void AssertLogDetails(BoostTestResult testResult, uint duration, IList<LogEntry> entries)
        {
            Assert.That(testResult.LogEntries.Count, Is.EqualTo(expected: entries.Count));

            Assert.That(testResult.Duration, Is.EqualTo(duration));

            foreach (LogEntry entry in entries)
            {
                LogEntry found =
                    testResult.LogEntries.FirstOrDefault(
                        e =>
                        {
                            // serge: In BoostXmlLog.Parse(TestResultCollection collection) method
                            // Xml document is recreated. There are insignificant whitespaces
                            // are appearing during transformation. So let's truncate them.
                            var entryDetail = Regex.Replace(entry.Detail, @"\r|\n\s+", string.Empty);
                            var eDetail = Regex.Replace(e.Detail, @"\r|\n\s+", string.Empty);
                            return (e.ToString() == entry.ToString()) && (eDetail == entryDetail);
                        });
                Assert.That(found, Is.Not.Null);

                AssertSourceInfoDetails(found.Source, entry.Source);
            }

            var entriesMemLeaks = entries.Where((e) => e is LogEntryMemoryLeak).GetEnumerator();
            var testResultMemleaks = testResult.LogEntries.Where((e) => e is LogEntryMemoryLeak).GetEnumerator();

            while (testResultMemleaks.MoveNext() && entriesMemLeaks.MoveNext())
            {
                AssertMemoryLeakDetails((LogEntryMemoryLeak)testResultMemleaks.Current,
                    (LogEntryMemoryLeak)entriesMemLeaks.Current);
            }
        }
        /// <summary>
        /// Asserts BoostTestResult against the expected details
        /// </summary>
        /// <param name="testResult">The BoostTestResult to test</param>
        /// <param name="parentTestResult">The expected parent BoostTestResult of testResult</param>
        /// <param name="name">The expected TestCase display name</param>
        /// <param name="result">The expected TestCase execution result</param>
        /// <param name="assertionsPassed">The expected number of passed assertions (e.g. BOOST_CHECKS)</param>
        /// <param name="assertionsFailed">The expected number of failed assertions (e.g. BOOST_CHECKS, BOOST_REQUIRE, BOOST_FAIL etc.)</param>
        /// <param name="expectedFailures">The expected number of expected test failures</param>
        /// <param name="testCasesPassed">The expected number of passed child TestCases</param>
        /// <param name="testCasesFailed">The expected number of failed child TestCases</param>
        /// <param name="testCasesSkipped">The expected number of skipped child TestCases</param>
        /// <param name="testCasesAborted">The expected number of aborted child TestCases</param>
        private void AssertReportDetails(
            BoostTestResult testResult,
            BoostTestResult parentTestResult,
            string name,
            TestResultType result,
            uint assertionsPassed,
            uint assertionsFailed,
            uint expectedFailures,
            uint testCasesPassed,
            uint testCasesFailed,
            uint testCasesSkipped,
            uint testCasesAborted
            )
        {
            AssertReportDetails(testResult, parentTestResult, name, result, assertionsPassed, assertionsFailed,
                expectedFailures);

            Assert.That(testResult.TestCasesPassed, Is.EqualTo(testCasesPassed));
            Assert.That(testResult.TestCasesFailed, Is.EqualTo(testCasesFailed));
            Assert.That(testResult.TestCasesSkipped, Is.EqualTo(testCasesSkipped));
            Assert.That(testResult.TestCasesAborted, Is.EqualTo(testCasesAborted));
        }
            /// <summary>
            /// Generates a BoostTestResult instance from the contained configuration.
            /// </summary>
            /// <returns>A BoostTestResult instance based on the pre-set configuration</returns>
            public BoostTestResult Build()
            {
                BoostTestResult result = new BoostTestResult(null);

                result.Result = this.ResultType;
                result.Unit = this.Unit;
                result.Duration = this.TimeDuration;

                foreach (LogEntry entry in this.Logs)
                {
                    result.LogEntries.Add(entry);
                }

                return result;
            }
        /// <summary>
        /// Asserts general log details contained within a BoostTestResult
        /// </summary>
        /// <param name="testResult">The BoostTestResult to test</param>
        /// <param name="duration">The expected test case execution duration</param>
        /// <param name="entries">The expected list of log entries generated from test case execution</param>
        private void AssertLogDetails(BoostTestResult testResult, uint duration, IList<LogEntry> entries)
        {
            Assert.That(testResult.LogEntries.Count, Is.EqualTo(expected: entries.Count));

            Assert.That(testResult.Duration, Is.EqualTo(duration));

            foreach (LogEntry entry in entries)
            {
                LogEntry found =
                    testResult.LogEntries.FirstOrDefault(
                        e =>
                        {
                            var entryDetail = Regex.Replace(entry.Detail, @"\r|\n", string.Empty);
                            var eDetail = Regex.Replace(e.Detail, @"\r|\n", string.Empty);
                            return (e.ToString() == entry.ToString()) && (eDetail == entryDetail);
                        });
                Assert.That(found, Is.Not.Null);

                AssertSourceInfoDetails(found.Source, entry.Source);
            }

            var entriesMemLeaks = entries.Where((e) => e is LogEntryMemoryLeak).GetEnumerator();
            var testResultMemleaks = testResult.LogEntries.Where((e) => e is LogEntryMemoryLeak).GetEnumerator();

            while (testResultMemleaks.MoveNext() && entriesMemLeaks.MoveNext())
            {
                AssertMemoryLeakDetails((LogEntryMemoryLeak)testResultMemleaks.Current,
                    (LogEntryMemoryLeak)entriesMemLeaks.Current);
            }
        }