Abstract the console
This commit is contained in:
Родитель
587376200b
Коммит
40d4670463
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче