/// <summary>
        /// Initializes a new instance of the <see cref="LogMessageListener"/> class.
        /// </summary>
        /// <param name="captureDebugTraces">Captures debug traces if true.</param>
        public LogMessageListener(bool captureDebugTraces)
        {
            this.captureDebugTraces = captureDebugTraces;

            // Cache the original output/error streams and replace it with the own stream.
            this.redirectLoggerOut = new ThreadSafeStringWriter(CultureInfo.InvariantCulture);
            this.redirectStdErr    = new ThreadSafeStringWriter(CultureInfo.InvariantCulture);

            Logger.OnLogMessage += this.redirectLoggerOut.WriteLine;

            // Cache the previous redirector if any and replace the trace listener.
            this.previousRedirector = activeRedirector;

            if (this.captureDebugTraces)
            {
                this.traceListener        = PlatformServiceProvider.Instance.GetTraceListener(new ThreadSafeStringWriter(CultureInfo.InvariantCulture));
                this.traceListenerManager = PlatformServiceProvider.Instance.GetTraceListenerManager(this.redirectLoggerOut, this.redirectStdErr);

                // If there was a previous LogMessageListener active, remove its
                // TraceListener (it will be restored when this one is disposed).
                if (this.previousRedirector != null && this.previousRedirector.traceListener != null)
                {
                    this.traceListenerManager.Remove(this.previousRedirector.traceListener);
                }

                this.traceListenerManager.Add(this.traceListener);
            }

            activeRedirector = this;
        }
Esempio n. 2
0
        /// <summary>
        /// Runs the class cleanup method.
        /// It returns any error information during the execution of the cleanup method
        /// </summary>
        /// <returns> The <see cref="RunCleanupResult"/>. </returns>
        internal RunCleanupResult RunCleanup()
        {
            // No cleanup methods to execute, then return.
            var assemblyInfoCache = this.typeCache.AssemblyInfoListWithExecutableCleanupMethods;
            var classInfoCache    = this.typeCache.ClassInfoListWithExecutableCleanupMethods;

            if (!assemblyInfoCache.Any() && !classInfoCache.Any())
            {
                return(null);
            }

            var result = new RunCleanupResult {
                Warnings = new List <string>()
            };

            using (var redirector = new LogMessageListener(MSTestSettings.CurrentSettings.CaptureDebugTraces))
            {
                try
                {
                    this.RunClassCleanupMethods(classInfoCache, result.Warnings);
                    this.RunAssemblyCleanup(assemblyInfoCache, result.Warnings);
                }
                finally
                {
                    // Replacing the null character with a string.replace should work.
                    // If this does not work for a specific dotnet version a custom function doing the same needs to be put in place.
                    result.StandardOut   = redirector.GetAndClearStandardOutput()?.Replace("\0", "\\0");
                    result.StandardError = redirector.GetAndClearStandardError()?.Replace("\0", "\\0");
                    result.DebugTrace    = redirector.GetAndClearDebugTrace()?.Replace("\0", "\\0");
                }
            }

            return(result);
        }
Esempio n. 3
0
        internal UnitTestResult[] Execute()
        {
            string initLogs  = string.Empty;
            string initTrace = string.Empty;
            string errorLogs = string.Empty;

            UnitTestResult[] result = null;
            try
            {
                using (LogMessageListener logListener = new LogMessageListener(this.captureDebugTraces))
                {
                    try
                    {
                        // Run the assembly and class Initialize methods if required.
                        // Assembly or class initialize can throw exceptions in which case we need to ensure that we fail the test.
                        this.testMethodInfo.Parent.Parent.RunAssemblyInitialize(this.testContext.Context);
                        this.testMethodInfo.Parent.RunClassInitialize(this.testContext.Context);
                    }
                    finally
                    {
                        initLogs  = logListener.StandardOutput;
                        initTrace = logListener.DebugTrace;
                        errorLogs = logListener.StandardError;
                    }
                }

                // Listening to log messages when running the test method with its Test Initialize and cleanup later on in the stack.
                // This allows us to differentiate logging when data driven methods are used.
                result = this.RunTestMethod();
            }
            catch (TestFailedException ex)
            {
                result = new[] { new UnitTestResult(ex) };
            }
            catch (Exception ex)
            {
                if (result == null || result.Length == 0)
                {
                    result = new[] { new UnitTestResult() };
                }

                var newResult =
                    new UnitTestResult(new TestFailedException(UnitTestOutcome.Error, ex.TryGetMessage(), ex.TryGetStackTraceInformation()));
                newResult.StandardOut     = result[result.Length - 1].StandardOut;
                newResult.StandardError   = result[result.Length - 1].StandardError;
                newResult.DebugTrace      = result[result.Length - 1].DebugTrace;
                newResult.Duration        = result[result.Length - 1].Duration;
                result[result.Length - 1] = newResult;
            }
            finally
            {
                var firstResult = result[0];
                firstResult.StandardOut   = initLogs + firstResult.StandardOut;
                firstResult.StandardError = errorLogs + firstResult.StandardError;
                firstResult.DebugTrace    = initTrace + firstResult.DebugTrace;
            }

            return(result);
        }
Esempio n. 4
0
        /// <summary>
        /// Execute test method. Capture failures, handle async and return result.
        /// </summary>
        /// <param name="arguments">
        ///  Arguments to pass to test method. (E.g. For data driven)
        /// </param>
        /// <returns>Result of test method invocation.</returns>
        public virtual TestResult Invoke(object[] arguments)
        {
            Stopwatch  watch  = new Stopwatch();
            TestResult result = null;

            // check if arguments are set for data driven tests
            if (arguments == null)
            {
                arguments = this.Arguments;
            }

            using (LogMessageListener listener = new LogMessageListener(this.TestMethodOptions.CaptureDebugTraces))
            {
                var testElement = new UnitTestElement(new TestMethod(this))
                {
                    TestId = this.TestId
                };

                watch.Start();
                try
                {
                    this.TestExecutionRecorder.RecordStart(testElement);

                    if (this.IsTimeoutSet)
                    {
                        result = this.ExecuteInternalWithTimeout(arguments);
                    }
                    else
                    {
                        result = this.ExecuteInternal(arguments);
                    }
                }
                finally
                {
                    // Handle logs & debug traces.
                    watch.Stop();

                    if (result != null)
                    {
                        result.Duration            = watch.Elapsed;
                        result.DebugTrace          = listener.DebugTrace;
                        result.LogOutput           = listener.StandardOutput;
                        result.LogError            = listener.StandardError;
                        result.TestContextMessages = this.TestMethodOptions.TestContext.GetAndClearDiagnosticMessages();
                        result.ResultFiles         = this.TestMethodOptions.TestContext.GetResultFiles();
                        result.TestId = this.TestId;
                    }

                    this.TestExecutionRecorder.RecordEnd(
                        testElement,
                        result?.Outcome.ToUnitTestOutcome() ?? UnitTestOutcome.Error);
                }
            }

            return(result);
        }
Esempio n. 5
0
        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                Logger.OnLogMessage -= this.redirectLoggerOut.WriteLine;
                Logger.OnLogMessage -= this.redirectStdErr.WriteLine;

                this.redirectLoggerOut.Dispose();
                this.redirectStdErr.Dispose();

                if (this.captureDebugTraces)
                {
                    try
                    {
                        if (this.traceListener != null)
                        {
                            this.traceListenerManager.Remove(this.traceListener);
                        }

                        // Restore the previous LogMessageListener's TraceListener (if there was one)
                        if (this.previousRedirector != null && this.previousRedirector.traceListener != null)
                        {
                            this.traceListenerManager.Add(this.previousRedirector.traceListener);
                        }
                    }
                    catch (Exception e)
                    {
                        // Catch all exceptions since Dispose should not throw.
                        PlatformServiceProvider.Instance.AdapterTraceLogger.LogError(
                            "ConsoleOutputRedirector.Dispose threw exception: {0}",
                            e);
                    }

                    if (this.traceListener != null)
                    {
                        // Dispose trace manager and listeners
                        this.traceListenerManager.Dispose(this.traceListener);
                        this.traceListenerManager = null;
                        this.traceListener        = null;
                    }
                }

                activeRedirector = this.previousRedirector;
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Execute test method. Capture failures, handle async and return result.
        /// </summary>
        /// <param name="arguments">
        ///  Arguments to pass to test method. (E.g. For data driven)
        /// </param>
        /// <returns>Result of test method invocation.</returns>
        public virtual TestResult Invoke(object[] arguments)
        {
            Stopwatch  watch  = new Stopwatch();
            TestResult result = null;

            // check if arguments are set for data driven tests
            if (arguments == null)
            {
                arguments = this.Arguments;
            }

            using (LogMessageListener listener = new LogMessageListener(this.TestMethodOptions.CaptureDebugTraces))
            {
                watch.Start();
                try
                {
                    if (this.IsTimeoutSet)
                    {
                        result = this.ExecuteInternalWithTimeout(arguments);
                    }
                    else
                    {
                        result = this.ExecuteInternal(arguments);
                    }
                }
                finally
                {
                    // Handle logs & debug traces.
                    watch.Stop();

                    if (result != null)
                    {
                        result.Duration            = watch.Elapsed;
                        result.DebugTrace          = listener.GetAndClearDebugTrace();
                        result.LogOutput           = listener.GetAndClearStandardOutput();
                        result.LogError            = listener.GetAndClearStandardError();
                        result.TestContextMessages = this.TestMethodOptions.TestContext.GetAndClearDiagnosticMessages();
                        result.ResultFiles         = this.TestMethodOptions.TestContext.GetResultFiles();
                    }
                }
            }

            return(result);
        }
Esempio n. 7
0
        private void RunClassCleanupIfEndOfClass(TestMethodInfo testMethodInfo, TestMethod testMethod, UnitTestResult[] results)
        {
            bool shouldRunClassCleanup = false;

            this.classCleanupManager?.MarkTestComplete(testMethodInfo, testMethod, out shouldRunClassCleanup);
            if (shouldRunClassCleanup)
            {
                string cleanupLogs      = string.Empty;
                string cleanupTrace     = string.Empty;
                string cleanupErrorLogs = string.Empty;

                try
                {
                    using (LogMessageListener logListener =
                               new LogMessageListener(MSTestSettings.CurrentSettings.CaptureDebugTraces))
                    {
                        try
                        {
                            // Class cleanup can throw exceptions in which case we need to ensure that we fail the test.
                            testMethodInfo.Parent.RunClassCleanup(ClassCleanupBehavior.EndOfClass);
                        }
                        finally
                        {
                            cleanupLogs      = logListener.StandardOutput;
                            cleanupTrace     = logListener.DebugTrace;
                            cleanupErrorLogs = logListener.StandardError;
                            var lastResult = results[results.Length - 1];
                            lastResult.StandardOut   = lastResult.StandardOut + cleanupLogs;
                            lastResult.StandardError = lastResult.StandardError + cleanupErrorLogs;
                            lastResult.DebugTrace    = lastResult.DebugTrace + cleanupTrace;
                        }
                    }
                }
                catch (Exception e)
                {
                    results[results.Length - 1].Outcome         = ObjectModel.UnitTestOutcome.Failed;
                    results[results.Length - 1].ErrorMessage    = e.Message;
                    results[results.Length - 1].ErrorStackTrace = e.StackTrace;
                }
            }
        }
Esempio n. 8
0
        /// <inheritdoc/>
        /// <remarks>
        /// Execute test method. Capture failures, handle async and return result.
        /// </remarks>
        public virtual TestResult Invoke(object[] arguments)
        {
            Stopwatch  watch  = new Stopwatch();
            TestResult result = null;

            using (LogMessageListener listener = new LogMessageListener(this.TestMethodOptions.CaptureDebugTraces))
            {
                watch.Start();
                try
                {
                    if (this.IsTimeoutSet)
                    {
                        result = this.ExecuteInternalWithTimeout(arguments);
                    }
                    else
                    {
                        result = this.ExecuteInternal(arguments);
                    }
                }
                finally
                {
                    // Handle logs & debug traces.
                    watch.Stop();

                    if (result != null)
                    {
                        result.Duration    = watch.Elapsed;
                        result.DebugTrace  = listener.DebugTrace;
                        result.LogOutput   = listener.StandardOutput;
                        result.LogError    = listener.StandardError;
                        result.ResultFiles = this.TestMethodOptions.TestContext.GetResultFiles();
                    }
                }
            }

            return(result);
        }
Esempio n. 9
0
        internal UnitTestResult[] Execute()
        {
            string initLogs                = string.Empty;
            string initTrace               = string.Empty;
            string initErrorLogs           = string.Empty;
            string inittestContextMessages = string.Empty;

            UnitTestResult[] result = null;

            string ignoreMessage             = null;
            var    isIgnoreAttributeOnClass  = this.reflectHelper.IsAttributeDefined(this.testMethodInfo.Parent.ClassType, typeof(UTF.IgnoreAttribute), false);
            var    isIgnoreAttributeOnMethod = this.reflectHelper.IsAttributeDefined(this.testMethodInfo.TestMethod, typeof(UTF.IgnoreAttribute), false);

            if (isIgnoreAttributeOnClass)
            {
                ignoreMessage = this.reflectHelper.GetIgnoreMessage(this.testMethodInfo.Parent.ClassType.GetTypeInfo());
            }

            if (string.IsNullOrEmpty(ignoreMessage) && isIgnoreAttributeOnMethod)
            {
                ignoreMessage = this.reflectHelper.GetIgnoreMessage(this.testMethodInfo.TestMethod);
            }

            if (isIgnoreAttributeOnClass || isIgnoreAttributeOnMethod)
            {
                return(new[] { new UnitTestResult(UnitTestOutcome.Ignored, ignoreMessage) });
            }

            try
            {
                using (LogMessageListener logListener = new LogMessageListener(this.captureDebugTraces))
                {
                    try
                    {
                        // Run the assembly and class Initialize methods if required.
                        // Assembly or class initialize can throw exceptions in which case we need to ensure that we fail the test.
                        this.testMethodInfo.Parent.Parent.RunAssemblyInitialize(this.testContext.Context);
                        this.testMethodInfo.Parent.RunClassInitialize(this.testContext.Context);
                    }
                    finally
                    {
                        initLogs                = logListener.StandardOutput;
                        initTrace               = logListener.DebugTrace;
                        initErrorLogs           = logListener.StandardError;
                        inittestContextMessages = this.testContext.GetAndClearDiagnosticMessages();
                    }
                }

                // Listening to log messages when running the test method with its Test Initialize and cleanup later on in the stack.
                // This allows us to differentiate logging when data driven methods are used.
                result = this.RunTestMethod();
            }
            catch (TestFailedException ex)
            {
                result = new[] { new UnitTestResult(ex) };
            }
            catch (Exception ex)
            {
                if (result == null || result.Length == 0)
                {
                    result = new[] { new UnitTestResult() };
                }

                var newResult =
                    new UnitTestResult(new TestFailedException(UnitTestOutcome.Error, ex.TryGetMessage(), ex.TryGetStackTraceInformation()));
                newResult.StandardOut         = result[result.Length - 1].StandardOut;
                newResult.StandardError       = result[result.Length - 1].StandardError;
                newResult.DebugTrace          = result[result.Length - 1].DebugTrace;
                newResult.TestContextMessages = result[result.Length - 1].TestContextMessages;
                newResult.Duration            = result[result.Length - 1].Duration;
                result[result.Length - 1]     = newResult;
            }
            finally
            {
                var firstResult = result[0];
                firstResult.StandardOut         = initLogs + firstResult.StandardOut;
                firstResult.StandardError       = initErrorLogs + firstResult.StandardError;
                firstResult.DebugTrace          = initTrace + firstResult.DebugTrace;
                firstResult.TestContextMessages = inittestContextMessages + firstResult.TestContextMessages;
            }

            return(result);
        }