This commit is contained in:
Nate McMaster 2016-11-16 21:35:21 -08:00
Родитель 587376200b
Коммит 40d4670463
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: BD729980AA6A21BD
36 изменённых файлов: 235 добавлений и 155 удалений

Просмотреть файл

@ -1,12 +1,11 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.DotNet.Watcher.Tools;
using Microsoft.DotNet.Watcher.Internal;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Tools.Internal;
namespace Microsoft.DotNet.Watcher
{
@ -17,7 +16,7 @@ namespace Microsoft.DotNet.Watcher
public bool IsQuiet { get; private set; }
public bool IsVerbose { get; private set; }
public IList<string> RemainingArguments { get; private set; }
public static CommandLineOptions Parse(string[] args, TextWriter stdout, TextWriter stderr)
public static CommandLineOptions Parse(string[] args, IConsole console)
{
Ensure.NotNull(args, nameof(args));
@ -25,8 +24,8 @@ namespace Microsoft.DotNet.Watcher
{
Name = "dotnet watch",
FullName = "Microsoft DotNet File Watcher",
Out = stdout,
Error = stderr,
Out = console.Out,
Error = console.Error,
AllowArgumentSeparator = true,
ExtendedHelpText = @"
Environment variables:
@ -80,7 +79,7 @@ Examples:
if (optQuiet.HasValue() && optVerbose.HasValue())
{
stderr.WriteLine(Resources.Error_QuietAndVerboseSpecified.Bold().Red());
console.Error.WriteLine(Resources.Error_QuietAndVerboseSpecified.Bold().Red());
return null;
}

Просмотреть файл

@ -5,6 +5,7 @@ using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Tools.Internal;
namespace Microsoft.DotNet.Watcher.Internal
{

Просмотреть файл

@ -3,6 +3,7 @@
using System;
using System.IO;
using Microsoft.Extensions.Tools.Internal;
namespace Microsoft.DotNet.Watcher.Internal
{

Просмотреть файл

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using Microsoft.Extensions.Tools.Internal;
namespace Microsoft.DotNet.Watcher.Internal
{

Просмотреть файл

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;

Просмотреть файл

@ -5,6 +5,7 @@ using System;
using System.IO;
using System.Linq;
using Microsoft.DotNet.Watcher.Tools;
using Microsoft.Extensions.Tools.Internal;
namespace Microsoft.DotNet.Watcher.Internal
{

Просмотреть файл

@ -16,34 +16,36 @@ namespace Microsoft.DotNet.Watcher
public class Program
{
private const string LoggerName = "DotNetWatcher";
private readonly CancellationToken _cancellationToken;
private readonly TextWriter _stdout;
private readonly TextWriter _stderr;
private readonly IConsole _console;
private readonly string _workingDir;
public Program(TextWriter consoleOutput, TextWriter consoleError, string workingDir, CancellationToken cancellationToken)
public Program(IConsole console, string workingDir)
{
Ensure.NotNull(consoleOutput, nameof(consoleOutput));
Ensure.NotNull(consoleError, nameof(consoleError));
Ensure.NotNull(console, nameof(console));
Ensure.NotNullOrEmpty(workingDir, nameof(workingDir));
_cancellationToken = cancellationToken;
_stdout = consoleOutput;
_stderr = consoleError;
_console = console;
_workingDir = workingDir;
}
public static int Main(string[] args)
{
HandleDebugSwitch(ref args);
return new Program(PhysicalConsole.Singleton, Directory.GetCurrentDirectory())
.RunAsync(args)
.GetAwaiter()
.GetResult();
}
public async Task<int> RunAsync(string[] args)
{
using (CancellationTokenSource ctrlCTokenSource = new CancellationTokenSource())
{
Console.CancelKeyPress += (sender, ev) =>
_console.CancelKeyPress += (sender, ev) =>
{
if (!ctrlCTokenSource.IsCancellationRequested)
{
Console.WriteLine($"[{LoggerName}] Shutdown requested. Press Ctrl+C again to force exit.");
_console.Out.WriteLine($"[{LoggerName}] Shutdown requested. Press Ctrl+C again to force exit.");
ev.Cancel = true;
}
else
@ -55,10 +57,7 @@ namespace Microsoft.DotNet.Watcher
try
{
return new Program(Console.Out, Console.Error, Directory.GetCurrentDirectory(), ctrlCTokenSource.Token)
.MainInternalAsync(args)
.GetAwaiter()
.GetResult();
return await MainInternalAsync(args, ctrlCTokenSource.Token);
}
catch (Exception ex)
{
@ -68,16 +67,16 @@ namespace Microsoft.DotNet.Watcher
return 0;
}
Console.Error.WriteLine(ex.ToString());
Console.Error.WriteLine($"[{LoggerName}] An unexpected error occurred".Bold().Red());
_console.Error.WriteLine(ex.ToString());
_console.Error.WriteLine($"[{LoggerName}] An unexpected error occurred".Bold().Red());
return 1;
}
}
}
private async Task<int> MainInternalAsync(string[] args)
private async Task<int> MainInternalAsync(string[] args, CancellationToken cancellationToken)
{
var options = CommandLineOptions.Parse(args, _stdout, _stdout);
var options = CommandLineOptions.Parse(args, _console);
if (options == null)
{
// invalid args syntax
@ -105,7 +104,7 @@ namespace Microsoft.DotNet.Watcher
}
catch (FileNotFoundException ex)
{
_stderr.WriteLine(ex.Message.Bold().Red());
_console.Error.WriteLine(ex.Message.Bold().Red());
return 1;
}
@ -119,7 +118,7 @@ namespace Microsoft.DotNet.Watcher
};
await new DotNetWatcher(logger)
.WatchAsync(processInfo, fileSetFactory, _cancellationToken);
.WatchAsync(processInfo, fileSetFactory, cancellationToken);
return 0;
}

Просмотреть файл

@ -74,22 +74,6 @@ namespace Microsoft.DotNet.Watcher.Tools
return GetString("Error_QuietAndVerboseSpecified");
}
/// <summary>
/// Value cannot be null or an empty string.
/// </summary>
internal static string Error_StringNullOrEmpty
{
get { return GetString("Error_StringNullOrEmpty"); }
}
/// <summary>
/// Value cannot be null or an empty string.
/// </summary>
internal static string FormatError_StringNullOrEmpty()
{
return GetString("Error_StringNullOrEmpty");
}
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);

Просмотреть файл

@ -129,7 +129,4 @@
<data name="Error_QuietAndVerboseSpecified" xml:space="preserve">
<value>Cannot specify both '--quiet' and '--verbose' options.</value>
</data>
<data name="Error_StringNullOrEmpty" xml:space="preserve">
<value>Value cannot be null or an empty string.</value>
</data>
</root>

Просмотреть файл

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Tools.Internal;
namespace Microsoft.Extensions.SecretManager.Tools.Internal
{

Просмотреть файл

@ -4,6 +4,7 @@
using System.Reflection;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Tools.Internal;
namespace Microsoft.Extensions.SecretManager.Tools.Internal
{

Просмотреть файл

@ -5,6 +5,7 @@ using System;
using System.IO;
using System.Linq;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.Tools.Internal;
namespace Microsoft.Extensions.SecretManager.Tools.Internal
{
@ -14,10 +15,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal
public MsBuildProjectFinder(string directory)
{
if (string.IsNullOrEmpty(directory))
{
throw new ArgumentException(Resources.Common_StringNullOrEmpty, nameof(directory));
}
Ensure.NotNullOrEmpty(directory, nameof(directory));
_directory = directory;
}

Просмотреть файл

@ -9,6 +9,7 @@ using System.Text;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.UserSecrets;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Tools.Internal;
using Newtonsoft.Json.Linq;
namespace Microsoft.Extensions.SecretManager.Tools.Internal
@ -20,10 +21,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal
public SecretsStore(string userSecretsId, ILogger logger)
{
if (userSecretsId == null)
{
throw new ArgumentNullException(nameof(userSecretsId));
}
Ensure.NotNull(userSecretsId, nameof(userSecretsId));
_secretsFilePath = PathHelper.GetSecretsPathFromSecretsId(userSecretsId);

Просмотреть файл

@ -6,6 +6,7 @@ using System.IO;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.SecretManager.Tools.Internal;
using Microsoft.Extensions.Tools.Internal;
namespace Microsoft.Extensions.SecretManager.Tools
{
@ -39,29 +40,13 @@ namespace Microsoft.Extensions.SecretManager.Tools
public ILogger Logger
{
get { return _logger; }
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
_logger = value;
}
set { _logger = Ensure.NotNull(value, nameof(value)); }
}
public CommandOutputProvider CommandOutputProvider
{
get { return _loggerProvider; }
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
_loggerProvider = value;
}
set { _loggerProvider = Ensure.NotNull(value, nameof(value)); }
}
public bool TryRun(string[] args, out int returnCode)

Просмотреть файл

@ -10,22 +10,6 @@ namespace Microsoft.Extensions.SecretManager.Tools
private static readonly ResourceManager _resourceManager
= new ResourceManager("Microsoft.Extensions.SecretManager.Tools.Resources", typeof(Resources).GetTypeInfo().Assembly);
/// <summary>
/// Value cannot be null or an empty string.
/// </summary>
internal static string Common_StringNullOrEmpty
{
get { return GetString("Common_StringNullOrEmpty"); }
}
/// <summary>
/// Value cannot be null or an empty string.
/// </summary>
internal static string FormatCommon_StringNullOrEmpty()
{
return GetString("Common_StringNullOrEmpty");
}
/// <summary>
/// Command failed : {message}
/// </summary>

Просмотреть файл

@ -117,9 +117,6 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Common_StringNullOrEmpty" xml:space="preserve">
<value>Value cannot be null or an empty string.</value>
</data>
<data name="Error_Command_Failed" xml:space="preserve">
<value>Command failed : {message}</value>
</data>

Просмотреть файл

@ -2,9 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.DotNet.Watcher.Tools;
namespace Microsoft.DotNet.Watcher.Internal
namespace Microsoft.Extensions.Tools.Internal
{
internal static class Ensure
{
@ -22,7 +21,7 @@ namespace Microsoft.DotNet.Watcher.Internal
{
if (string.IsNullOrEmpty(obj))
{
throw new ArgumentException(Resources.Error_StringNullOrEmpty, paramName);
throw new ArgumentException("Value cannot be null or an empty string.", paramName);
}
return obj;
}

Просмотреть файл

@ -1,12 +1,14 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
namespace Microsoft.Extensions.SecretManager.Tools.Internal
namespace Microsoft.Extensions.Tools.Internal
{
public interface IConsole
{
event ConsoleCancelEventHandler CancelKeyPress;
TextWriter Out { get; }
TextWriter Error { get; }
TextReader In { get; }

Просмотреть файл

@ -4,13 +4,21 @@
using System;
using System.IO;
namespace Microsoft.Extensions.SecretManager.Tools.Internal
namespace Microsoft.Extensions.Tools.Internal
{
public class PhysicalConsole : IConsole
{
private PhysicalConsole() { }
private PhysicalConsole()
{
Console.CancelKeyPress += (o, e) =>
{
CancelKeyPress?.Invoke(o, e);
};
}
public static IConsole Singleton { get; } = new PhysicalConsole();
public event ConsoleCancelEventHandler CancelKeyPress;
public TextWriter Error => Console.Error;
public TextReader In => Console.In;
public TextWriter Out => Console.Out;

Просмотреть файл

@ -15,6 +15,7 @@
"Microsoft.DotNet.InternalAbstractions": "1.0.0",
"Microsoft.AspNetCore.Testing": "1.0.0",
"Microsoft.DotNet.Watcher.Tools": "1.0.0-*",
"Microsoft.DotNet.Watcher.Tools.Tests": "1.0.0-*",
"Microsoft.Extensions.Process.Sources": {
"type": "build",
"version": "1.0.0"

Просмотреть файл

@ -1,3 +1,5 @@
set -e
dotnet build
../../.build/dotnet/dotnet exec \

Просмотреть файл

@ -7,7 +7,7 @@ using System.IO;
using System.Linq;
using Xunit;
namespace Microsoft.DotNetWatcher.Tools.Tests
namespace Microsoft.DotNet.Watcher.Tools.Tests
{
public static class AssertEx
{

Просмотреть файл

@ -4,12 +4,27 @@
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Extensions.Tools.Internal;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.DotNet.Watcher.Tools.Tests
{
public class CommandLineOptionsTests
{
private readonly IConsole _console;
private readonly StringBuilder _stdout = new StringBuilder();
private readonly StringBuilder _stderr = new StringBuilder();
public CommandLineOptionsTests(ITestOutputHelper output)
{
_console = new TestConsole(output)
{
Out = new StringWriter(_stdout),
Error = new StringWriter(_stderr),
};
}
[Theory]
[InlineData(new object[] { new[] { "-h" } })]
[InlineData(new object[] { new[] { "-?" } })]
@ -19,12 +34,10 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests
[InlineData(new object[] { new string[0] })]
public void HelpArgs(string[] args)
{
var stdout = new StringBuilder();
var options = CommandLineOptions.Parse(args, new StringWriter(stdout), new StringWriter());
var options = CommandLineOptions.Parse(args, _console);
Assert.True(options.IsHelp);
Assert.Contains("Usage: dotnet watch ", stdout.ToString());
Assert.Contains("Usage: dotnet watch ", _stdout.ToString());
}
[Theory]
@ -34,22 +47,18 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests
[InlineData(new[] { "--unrecognized-arg" }, new[] { "--unrecognized-arg" })]
public void ParsesRemainingArgs(string[] args, string[] expected)
{
var stdout = new StringBuilder();
var options = CommandLineOptions.Parse(args, new StringWriter(stdout), new StringWriter());
var options = CommandLineOptions.Parse(args, _console);
Assert.Equal(expected, options.RemainingArguments.ToArray());
Assert.False(options.IsHelp);
Assert.Empty(stdout.ToString());
Assert.Empty(_stdout.ToString());
}
[Fact]
public void CannotHaveQuietAndVerbose()
{
var sb = new StringBuilder();
var stderr = new StringWriter(sb);
Assert.Null(CommandLineOptions.Parse(new[] { "--quiet", "--verbose" }, new StringWriter(), stderr));
Assert.Contains(Resources.Error_QuietAndVerboseSpecified, sb.ToString());
Assert.Null(CommandLineOptions.Parse(new[] { "--quiet", "--verbose" }, _console));
Assert.Contains(Resources.Error_QuietAndVerboseSpecified, _stderr.ToString());
}
}
}

Просмотреть файл

@ -6,13 +6,12 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.DotNet.Watcher;
using Microsoft.DotNet.Watcher.Internal;
using Microsoft.Extensions.Logging;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.DotNetWatcher.Tools.Tests
namespace Microsoft.DotNet.Watcher.Tools.Tests
{
using ItemSpec = TemporaryCSharpProject.ItemSpec;

Просмотреть файл

@ -0,0 +1,52 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Tools.Internal;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.DotNet.Watcher.Tools.Tests
{
public class ProgramTests : IDisposable
{
private readonly TemporaryDirectory _tempDir;
private readonly TestConsole _console;
public ProgramTests(ITestOutputHelper output)
{
_tempDir = new TemporaryDirectory();
_console = new TestConsole(output);
}
[Fact]
public async Task ConsoleCancelKey()
{
_tempDir
.WithCSharpProject("testproj")
.WithTargetFrameworks("netcoreapp1.0")
.Dir()
.WithFile("Program.cs")
.Create();
var stdout = new StringBuilder();
_console.Out = new StringWriter(stdout);
var program = new Program(_console, _tempDir.Root)
.RunAsync(new [] { "run" });
_console.ConsoleCancelKey();
var exitCode = await program.OrTimeout();
Assert.Contains("Shutdown requested. Press Ctrl+C again to force exit.", stdout.ToString());
Assert.Equal(0, exitCode);
}
public void Dispose()
{
_tempDir.Dispose();
}
}
}

Просмотреть файл

@ -1,11 +1,9 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
namespace System.Threading.Tasks
{
public static class TaskExtensions
{

Просмотреть файл

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace Microsoft.DotNetWatcher.Tools.Tests
namespace Microsoft.DotNet.Watcher.Tools.Tests
{
public class TemporaryCSharpProject
{

Просмотреть файл

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.IO;
namespace Microsoft.DotNetWatcher.Tools.Tests
namespace Microsoft.DotNet.Watcher.Tools.Tests
{
public class TemporaryDirectory : IDisposable
{

Просмотреть файл

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
namespace Microsoft.DotNetWatcher.Tools.Tests
namespace Microsoft.DotNet.Watcher.Tools.Tests
{
public class TestProjectGraph
{

Просмотреть файл

@ -5,7 +5,7 @@ using System;
using Microsoft.Extensions.Logging;
using Xunit.Abstractions;
namespace Microsoft.DotNetWatcher.Tools.Tests
namespace Microsoft.DotNet.Watcher.Tools.Tests
{
internal class XunitLogger : ILogger
{

Просмотреть файл

@ -2,7 +2,8 @@
"buildOptions": {
"warningsAsErrors": true,
"keyFile": "../../tools/Key.snk",
"debugType": "portable"
"debugType": "portable",
"compile": "../Shared/**/*.cs"
},
"dependencies": {
"dotnet-test-xunit": "2.2.0-preview2-build1029",

Просмотреть файл

@ -9,6 +9,7 @@ using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.Configuration.UserSecrets;
using Microsoft.Extensions.Configuration.UserSecrets.Tests;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Tools.Internal;
using Xunit;
using Xunit.Abstractions;
@ -16,19 +17,20 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests
{
public class SecretManagerTests : IClassFixture<UserSecretsTestFixture>
{
private TestLogger _logger;
private readonly TestLogger _logger;
private readonly TestConsole _console;
private readonly UserSecretsTestFixture _fixture;
public SecretManagerTests(UserSecretsTestFixture fixture, ITestOutputHelper output)
{
_fixture = fixture;
_logger = new TestLogger(output);
_console = new TestConsole(output);
}
private Program CreateProgram()
{
return new Program(new TestConsole(), Directory.GetCurrentDirectory())
return new Program(_console, Directory.GetCurrentDirectory())
{
Logger = _logger
};
@ -72,7 +74,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests
var projectPath = _fixture.GetTempSecretProject();
var cwd = Path.Combine(projectPath, "nested1");
Directory.CreateDirectory(cwd);
var secretManager = new Program(new TestConsole(), cwd) { Logger = _logger, CommandOutputProvider = _logger.CommandOutputProvider };
var secretManager = new Program(_console, cwd) { Logger = _logger, CommandOutputProvider = _logger.CommandOutputProvider };
secretManager.CommandOutputProvider.LogLevel = LogLevel.Debug;
secretManager.RunInternal("list", "-p", ".." + Path.DirectorySeparatorChar, "--verbose");
@ -97,7 +99,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests
var dir = fromCurrentDirectory
? projectPath
: Path.GetTempPath();
var secretManager = new Program(new TestConsole(), dir) { Logger = _logger };
var secretManager = new Program(_console, dir) { Logger = _logger };
foreach (var secret in secrets)
{
@ -237,16 +239,13 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests
public void List_Json()
{
var output = new StringBuilder();
var testConsole = new TestConsole
{
Out = new StringWriter(output)
};
_console.Out = new StringWriter(output);
string id;
var projectPath = _fixture.GetTempSecretProject(out id);
var secretsFile = PathHelper.GetSecretsPathFromSecretsId(id);
Directory.CreateDirectory(Path.GetDirectoryName(secretsFile));
File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8);
var secretManager = new Program(testConsole, Path.GetDirectoryName(projectPath)) { Logger = _logger };
var secretManager = new Program(_console, Path.GetDirectoryName(projectPath)) { Logger = _logger };
secretManager.RunInternal("list", "--id", id, "--json");
var stdout = output.ToString();
Assert.Contains("//BEGIN", stdout);
@ -297,7 +296,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests
? projectPath
: Path.GetTempPath();
var secretManager = new Program(new TestConsole(), dir) { Logger = _logger };
var secretManager = new Program(_console, dir) { Logger = _logger };
var secrets = new KeyValuePair<string, string>[]
{

Просмотреть файл

@ -1,17 +1,27 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Collections.Generic;
using Microsoft.Extensions.SecretManager.Tools.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Tools.Internal;
using Xunit;
using System;
using Xunit.Abstractions;
namespace Microsoft.Extensions.SecretManager.Tools.Tests
{
public class SetCommandTest
{
private readonly ITestOutputHelper _output;
public SetCommandTest(ITestOutputHelper output)
{
_output = output;
}
[Fact]
public void SetsFromPipedInput()
{
@ -21,7 +31,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests
""Key2"": 1234,
""Key3"": false
}";
var testConsole = new TestConsole
var testConsole = new TestConsole(_output)
{
IsInputRedirected = true,
In = new StringReader(input)
@ -48,7 +58,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests
""array"": [ 1, 2 ]
}";
var testConsole = new TestConsole
var testConsole = new TestConsole(_output)
{
IsInputRedirected = true,
In = new StringReader(input)
@ -68,7 +78,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests
[Fact]
public void OnlyPipesInIfNoArgs()
{
var testConsole = new TestConsole
var testConsole = new TestConsole(_output)
{
IsInputRedirected = true,
In = new StringReader("")

Просмотреть файл

@ -1,17 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using Microsoft.Extensions.SecretManager.Tools.Internal;
namespace Microsoft.Extensions.SecretManager.Tools.Tests
{
public class TestConsole : IConsole
{
public TextWriter Error { get; set; } = Console.Error;
public TextReader In { get; set; } = Console.In;
public TextWriter Out { get; set; } = Console.Out;
public bool IsInputRedirected { get; set; } = false;
}
}

Просмотреть файл

@ -1,7 +1,8 @@
{
"buildOptions": {
"warningsAsErrors": true,
"keyFile": "../../tools/Key.snk"
"keyFile": "../../tools/Key.snk",
"compile": "../Shared/**/*.cs"
},
"dependencies": {
"dotnet-test-xunit": "2.2.0-preview2-build1029",

Просмотреть файл

@ -0,0 +1,69 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Xunit.Abstractions;
namespace Microsoft.Extensions.Tools.Internal
{
public class TestConsole : IConsole
{
public TestConsole(ITestOutputHelper output)
{
var writer = new TestOutputWriter(output);
Error = writer;
Out = writer;
}
public event ConsoleCancelEventHandler CancelKeyPress;
public TextWriter Error { get; set; }
public TextWriter Out { get; set; }
public TextReader In { get; set; } = new StringReader(string.Empty);
public bool IsInputRedirected { get; set; } = false;
public ConsoleCancelEventArgs ConsoleCancelKey()
{
var ctor = typeof(ConsoleCancelEventArgs)
.GetTypeInfo()
.DeclaredConstructors
.Single(c => c.GetParameters().First().ParameterType == typeof(ConsoleSpecialKey));
var args = (ConsoleCancelEventArgs)ctor.Invoke(new object[] { ConsoleSpecialKey.ControlC });
CancelKeyPress?.Invoke(this, args);
return args;
}
private class TestOutputWriter : TextWriter
{
private readonly ITestOutputHelper _output;
private readonly StringBuilder _sb = new StringBuilder();
public TestOutputWriter(ITestOutputHelper output)
{
_output = output;
}
public override Encoding Encoding => Encoding.Unicode;
public override void Write(char value)
{
if (value == '\r' || value == '\n')
{
if (_sb.Length > 0)
{
_output.WriteLine(_sb.ToString());
_sb.Clear();
}
}
else
{
_sb.Append(value);
}
}
}
}
}