From 16b996f25b0276b9f54138d6617c1b722cb80cfd Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Mon, 2 May 2016 17:46:48 -0500 Subject: [PATCH] Fixing the BuiltInCommandTests to not mutate global shared state. The BuiltInCommandTests sets the current Console.Out and Console.Error, which causes the test to fail if some other test is running and writes to the console at the same time. Fix #2768 --- .../BuiltInCommand.cs | 58 ++++++++++++++++--- .../IBuiltInCommandEnvironment.cs | 19 ++++++ .../Properties/AssemblyInfo.cs | 3 + .../BuiltInCommandTests.cs | 55 +++++++++++++++--- .../project.json | 3 +- 5 files changed, 121 insertions(+), 17 deletions(-) create mode 100644 src/Microsoft.DotNet.Cli.Utils/IBuiltInCommandEnvironment.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs diff --git a/src/Microsoft.DotNet.Cli.Utils/BuiltInCommand.cs b/src/Microsoft.DotNet.Cli.Utils/BuiltInCommand.cs index 55db7cb73..0f25e43c3 100644 --- a/src/Microsoft.DotNet.Cli.Utils/BuiltInCommand.cs +++ b/src/Microsoft.DotNet.Cli.Utils/BuiltInCommand.cs @@ -18,6 +18,7 @@ namespace Microsoft.DotNet.Cli.Utils { private readonly IEnumerable _commandArgs; private readonly Func _builtInCommand; + private readonly IBuiltInCommandEnvironment _environment; private readonly StreamForwarder _stdOut; private readonly StreamForwarder _stdErr; private string _workingDirectory; @@ -26,10 +27,16 @@ namespace Microsoft.DotNet.Cli.Utils public string CommandArgs => string.Join(" ", _commandArgs); public BuiltInCommand(string commandName, IEnumerable commandArgs, Func builtInCommand) + : this(commandName, commandArgs, builtInCommand, new BuiltInCommandEnvironment()) + { + } + + internal BuiltInCommand(string commandName, IEnumerable commandArgs, Func builtInCommand, IBuiltInCommandEnvironment environment) { CommandName = commandName; _commandArgs = commandArgs; _builtInCommand = builtInCommand; + _environment = environment; _stdOut = new StreamForwarder(); _stdErr = new StreamForwarder(); @@ -37,9 +44,9 @@ namespace Microsoft.DotNet.Cli.Utils public CommandResult Execute() { - TextWriter originalConsoleOut = Console.Out; - TextWriter originalConsoleError = Console.Error; - string originalWorkingDirectory = Directory.GetCurrentDirectory(); + TextWriter originalConsoleOut = _environment.GetConsoleOut(); + TextWriter originalConsoleError = _environment.GetConsoleError(); + string originalWorkingDirectory = _environment.GetWorkingDirectory(); try { @@ -48,15 +55,15 @@ namespace Microsoft.DotNet.Cli.Utils using (BlockingMemoryStream outStream = new BlockingMemoryStream()) using (BlockingMemoryStream errorStream = new BlockingMemoryStream()) { - Console.SetOut(new StreamWriter(outStream) { AutoFlush = true }); - Console.SetError(new StreamWriter(errorStream) { AutoFlush = true }); + _environment.SetConsoleOut(new StreamWriter(outStream) { AutoFlush = true }); + _environment.SetConsoleError(new StreamWriter(errorStream) { AutoFlush = true }); // Reset the Reporters to the new Console Out and Error. Reporter.Reset(); if (!string.IsNullOrEmpty(_workingDirectory)) { - Directory.SetCurrentDirectory(_workingDirectory); + _environment.SetWorkingDirectory(_workingDirectory); } var taskOut = _stdOut.BeginRead(new StreamReader(outStream)); @@ -76,9 +83,9 @@ namespace Microsoft.DotNet.Cli.Utils } finally { - Console.SetOut(originalConsoleOut); - Console.SetError(originalConsoleError); - Directory.SetCurrentDirectory(originalWorkingDirectory); + _environment.SetConsoleOut(originalConsoleOut); + _environment.SetConsoleError(originalConsoleError); + _environment.SetWorkingDirectory(originalWorkingDirectory); Reporter.Reset(); } @@ -115,6 +122,39 @@ namespace Microsoft.DotNet.Cli.Utils return this; } + private class BuiltInCommandEnvironment : IBuiltInCommandEnvironment + { + public TextWriter GetConsoleOut() + { + return Console.Out; + } + + public void SetConsoleOut(TextWriter newOut) + { + Console.SetOut(newOut); + } + + public TextWriter GetConsoleError() + { + return Console.Error; + } + + public void SetConsoleError(TextWriter newError) + { + Console.SetError(newError); + } + + public string GetWorkingDirectory() + { + return Directory.GetCurrentDirectory(); + } + + public void SetWorkingDirectory(string path) + { + Directory.SetCurrentDirectory(path); + } + } + public CommandResolutionStrategy ResolutionStrategy { get diff --git a/src/Microsoft.DotNet.Cli.Utils/IBuiltInCommandEnvironment.cs b/src/Microsoft.DotNet.Cli.Utils/IBuiltInCommandEnvironment.cs new file mode 100644 index 000000000..e71cbdb22 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/IBuiltInCommandEnvironment.cs @@ -0,0 +1,19 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.IO; + +namespace Microsoft.DotNet.Cli.Utils +{ + internal interface IBuiltInCommandEnvironment + { + TextWriter GetConsoleOut(); + void SetConsoleOut(TextWriter newOut); + + TextWriter GetConsoleError(); + void SetConsoleError(TextWriter newError); + + string GetWorkingDirectory(); + void SetWorkingDirectory(string path); + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..7766a7151 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.DotNet.Cli.Utils.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/BuiltInCommandTests.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/BuiltInCommandTests.cs index 78184781f..c91c202c0 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/BuiltInCommandTests.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/BuiltInCommandTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.IO; using System.Linq; using Microsoft.DotNet.Tools.Test.Utilities; using Xunit; @@ -35,16 +36,20 @@ namespace Microsoft.DotNet.Cli.Utils [Fact] public void TestOnOutputLines() { - int exitCode = 29; + const int exitCode = 29; + + TestBuiltInCommandEnvironment environment = new TestBuiltInCommandEnvironment(); Func testCommand = args => { - Console.Out.Write("first"); - Console.Out.WriteLine("second"); - Console.Out.WriteLine("third"); + TextWriter outWriter = environment.GetConsoleOut(); + outWriter.Write("first"); + outWriter.WriteLine("second"); + outWriter.WriteLine("third"); - Console.Error.WriteLine("fourth"); - Console.Error.WriteLine("fifth"); + TextWriter errorWriter = environment.GetConsoleError(); + errorWriter.WriteLine("fourth"); + errorWriter.WriteLine("fifth"); return exitCode; }; @@ -52,7 +57,7 @@ namespace Microsoft.DotNet.Cli.Utils int onOutputLineCallCount = 0; int onErrorLineCallCount = 0; - CommandResult result = new BuiltInCommand("fakeCommand", Enumerable.Empty(), testCommand) + CommandResult result = new BuiltInCommand("fakeCommand", Enumerable.Empty(), testCommand, environment) .OnOutputLine(line => { onOutputLineCallCount++; @@ -85,5 +90,41 @@ namespace Microsoft.DotNet.Cli.Utils Assert.Equal(2, onOutputLineCallCount); Assert.Equal(2, onErrorLineCallCount); } + + private class TestBuiltInCommandEnvironment : IBuiltInCommandEnvironment + { + private TextWriter _consoleOut; + private TextWriter _consoleError; + + public TextWriter GetConsoleOut() + { + return _consoleOut; + } + + public void SetConsoleOut(TextWriter newOut) + { + _consoleOut = newOut; + } + + public TextWriter GetConsoleError() + { + return _consoleError; + } + + public void SetConsoleError(TextWriter newError) + { + _consoleError = newError; + } + + public string GetWorkingDirectory() + { + return Directory.GetCurrentDirectory(); + } + + public void SetWorkingDirectory(string path) + { + // no-op + } + } } } diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json index 7e050fabe..9739c7552 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json @@ -1,7 +1,8 @@ { "version": "1.0.0-*", "compilationOptions": { - "emitEntryPoint": true + "emitEntryPoint": true, + "keyFile": "../../tools/Key.snk" }, "dependencies": { "Microsoft.NETCore.App": {