/// <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;
        }
示例#2
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;
            }
        }
示例#3
0
        private void Dispose(bool disposing)
        {
            if (disposing && !this.isDisposed)
            {
                this.isDisposed      = true;
                Logger.OnLogMessage -= this.redirectedStandardOutput.WriteLine;
                Logger.OnLogMessage -= this.redirectedStandardError.WriteLine;

                this.redirectedStandardOutput.Dispose();
                this.redirectedStandardError.Dispose();

                if (this.captureDebugTraces)
                {
                    lock (traceLock)
                    {
                        if (listenerCount == 1)
                        {
                            try
                            {
                                if (traceListener != null)
                                {
                                    this.traceListenerManager.Remove(traceListener);
                                }
                            }
                            catch (Exception e)
                            {
                                // Catch all exceptions since Dispose should not throw.
                                PlatformServiceProvider.Instance.AdapterTraceLogger.LogError("ConsoleOutputRedirector.Dispose threw exception: {0}", e);
                            }

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

                        listenerCount--;
                    }
                }
            }
        }
示例#4
0
        /// <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.redirectedStandardOutput = new ThreadSafeStringWriter(CultureInfo.InvariantCulture, "out");
            this.redirectedStandardError  = new ThreadSafeStringWriter(CultureInfo.InvariantCulture, "err");

            Logger.OnLogMessage += this.redirectedStandardOutput.WriteLine;

            if (this.captureDebugTraces)
            {
                // This is awkward, it has a side-effect of setting up Console output redirection, but the naming is suggesting that we are
                // just getting TraceListener manager.
                this.traceListenerManager = PlatformServiceProvider.Instance.GetTraceListenerManager(this.redirectedStandardOutput, this.redirectedStandardError);

                // The Debug listener uses Debug.WriteLine and Debug.Write to write the messages, which end up written into Trace.Listeners.
                // These listeners are static and hence shared across the whole process. We need to capture Debug output only for the current
                // test, which was historically done by registering a listener in constructor of this class, and by removing the listener on Dispose.
                // The newly created listener replaced previously registered listener, which was remembered, and put back on dispose.
                //
                // This works well as long as there are no tests running in parallel. But as soon as there are tests running in parallel. Then all the
                // debug output of all tests will be output into the test that was most recently created (because it registered the listener most recently).
                //
                // To prevent mixing of outputs, the ThreadSafeStringWriter was re-implemented for net46 and newer to leverage AsyncLocal, which allows the writer to
                // write only to the output of the current test. This leaves the LogMessageListener with only one task. Make sure that a trace listener is registered
                // as long as there is any active test. This is still done by constructor and Dispose, but instead of replacing the listener every time, we use listenerCount
                // to only add the listerner when there is none, and remove it when we are the last one to dispose.
                //
                // This would break the behavior for net451, but that functionality was moved further into ThreadSafeStringWriter.
                lock (traceLock)
                {
                    if (listenerCount == 0)
                    {
                        redirectedDebugTrace = new ThreadSafeStringWriter(CultureInfo.InvariantCulture, "trace");
                        traceListener        = PlatformServiceProvider.Instance.GetTraceListener(redirectedDebugTrace);
                        this.traceListenerManager.Add(traceListener);
                    }

                    listenerCount++;
                }
            }
        }