Skip to content

Commit

Permalink
Merge pull request #63 from madelson/release-1.6.1
Browse files Browse the repository at this point in the history
Release 1.6.1
  • Loading branch information
madelson authored Dec 23, 2019
2 parents 679a82e + 78020f9 commit 2afc719
Show file tree
Hide file tree
Showing 29 changed files with 316 additions and 226 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ solution: MedallionShell.sln
mono: latest
# recommended here: https://travis-ci.community/t/c-builds-are-failing-net-core-installation-error/3063
dist: xenial
dotnet: 2.2.1
dotnet: 3.1
install:
- nuget restore MedallionShell.sln
- nuget install NUnit.Console -Version 3.10.0 -OutputDirectory testrunner
Expand All @@ -13,4 +13,4 @@ script:
- msbuild /p:Configuration=Release MedallionShell.ProcessSignaler/MedallionShell.ProcessSignaler.csproj
- msbuild /p:Configuration=Release MedallionShell.sln
- mono ./testrunner/NUnit.ConsoleRunner.3.10.0/tools/nunit3-console.exe ./MedallionShell.Tests/bin/Release/net46/MedallionShell.Tests.dll
- dotnet test --no-build -f netcoreapp2.2 -c Release
- dotnet test --no-build -f netcoreapp3.1 -c Release
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,28 @@
<TargetFrameworks>net45;netstandard1.3</TargetFrameworks>
<OutputType>Exe</OutputType>
<IsPackable>false</IsPackable>
<LangVersion>7.2</LangVersion>
<LangVersion>Latest</LangVersion>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<CodeAnalysisRuleSet>..\stylecop.analyzers.ruleset</CodeAnalysisRuleSet>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<DefineConstants>TRACE;DEBUG</DefineConstants>
<NoWarn />
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Release'">
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<TreatSpecificWarningsAsErrors />
<Optimize>True</Optimize>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.1.1-rc.94">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" />
</ItemGroup>

<ItemGroup>
Expand Down
13 changes: 7 additions & 6 deletions MedallionShell.Tests/AttachingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public void TestWaitingForAttachedProcessExit()
var processCommand = TestShell.Run(SampleCommand, new[] { "sleep", "100" });
Command.TryAttachToProcess(processCommand.ProcessId, out var attachedCommand)
.ShouldEqual(true, "Attaching to process failed.");
var commandResult = attachedCommand.Task;
var commandResult = attachedCommand!.Task;
commandResult.IsCompleted.ShouldEqual(false, "Task has finished too early.");
Thread.Sleep(300);
commandResult.IsCompleted.ShouldEqual(true, "Task has not finished on time.");
Expand All @@ -36,7 +36,7 @@ public void TestGettingExitCodeFromAttachedProcess()
var processCommand = TestShell.Run(SampleCommand, new[] { "exit", "16" });
Command.TryAttachToProcess(processCommand.ProcessId, out var attachedCommand)
.ShouldEqual(true, "Attaching to process failed.");
var task = attachedCommand.Task;
var task = attachedCommand!.Task;
task.Wait(1000).ShouldEqual(true, "Task has not finished on time.");
task.Result.ExitCode.ShouldEqual(16, "Exit code was not correct.");
}
Expand All @@ -61,7 +61,7 @@ public void TestKillingAttachedProcess()
out var attachedCommand)
.ShouldEqual(true, "Attaching to process failed.");

attachedCommand.Kill();
attachedCommand!.Kill();

attachedCommand.Task.Wait(TimeSpan.FromSeconds(1))
.ShouldEqual(true, "The process is still alive after Kill() has finished.");
Expand All @@ -81,7 +81,7 @@ public void TestAttachingWithAlreadyCanceledToken()
.ShouldEqual(true, "attaching failed");
using (attachedCommand)
{
attachedCommand.Process.WaitForExit(1000).ShouldEqual(true, "The process wasn't killed.");
attachedCommand!.Process.WaitForExit(1000).ShouldEqual(true, "The process wasn't killed.");
}
}

Expand All @@ -94,10 +94,11 @@ public void TestTimeout()
Command.TryAttachToProcess(
processId,
options => options.Timeout(TimeSpan.FromMilliseconds(150)),
out var attachedCommand);
out var attachedCommand)
.ShouldEqual(true);

// the timeout is counted from the moment we attached to the process so it shouldn't throw at this moment
attachedCommand.Task.Wait(100);
attachedCommand!.Task.Wait(100);

// but should eventually throw
var exception = Assert.Throws<AggregateException>(
Expand Down
4 changes: 2 additions & 2 deletions MedallionShell.Tests/CommandLineSyntaxTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public class CommandLineSyntaxTest
public void TestArgumentValidation([Values] bool isWindowsSyntax)
{
var syntax = isWindowsSyntax ? new WindowsCommandLineSyntax() : new MonoUnixCommandLineSyntax().As<CommandLineSyntax>();
Assert.Throws<ArgumentNullException>(() => syntax.CreateArgumentString(null));
Assert.Throws<ArgumentException>(() => syntax.CreateArgumentString(new[] { "a", null, "b" }));
Assert.Throws<ArgumentNullException>(() => syntax.CreateArgumentString(null!));
Assert.Throws<ArgumentException>(() => syntax.CreateArgumentString(new[] { "a", null!, "b" }));
}

[TestCase(" ")]
Expand Down
24 changes: 20 additions & 4 deletions MedallionShell.Tests/GeneralTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -575,16 +575,32 @@ public void TestCommandOption()
[Test]
public void TestProcessKeepsWritingAfterOutputIsClosed()
{
var command = TestShell.Run(SampleCommand, new[] { "pipe" }, options: o => o.ThrowOnError());
var command = TestShell.Run(SampleCommand, new[] { "pipe" });
command.StandardOutput.Dispose();
for (var i = 0; i < 100; ++i)
{
command.StandardInput.WriteLine(new string('a', i));
}
command.Task.IsCompleted.ShouldEqual(false);

command.StandardInput.Dispose();
command.Task.Wait(TimeSpan.FromSeconds(1000)).ShouldEqual(true);
// workaround for https://github.com/mono/mono/issues/18279; so far
// I've encountered this only on Mono Linux
if (PlatformCompatibilityHelper.IsMono
&& !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
command.StandardInput.Dispose();
command.Task.Wait(TimeSpan.FromSeconds(1000)).ShouldEqual(true);
command.Result.ExitCode.ShouldEqual(1);
// SampleCommand fails because it's attempt to write to Console.Out fails hard
Assert.That(command.Result.StandardError, Does.Contain("System.IO.IOException: Write fault"));
}
else
{
command.Task.IsCompleted.ShouldEqual(false);

command.StandardInput.Dispose();
command.Task.Wait(TimeSpan.FromSeconds(1000)).ShouldEqual(true);
command.Result.Success.ShouldEqual(true);
}
}

private IEnumerable<string> ErrorLines()
Expand Down
72 changes: 72 additions & 0 deletions MedallionShell.Tests/IoCommandTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Medallion.Shell.Tests;
using NUnit.Framework;

namespace MedallionShell.Tests
{
using static UnitTestHelpers;

public class IOCommandTest
{
[Test]
public void TestStandardOutCannotBeAccessedAfterRedirectingIt()
{
var output = new List<string>();
var command = TestShell.Run(SampleCommand, "argecho", "a");
var ioCommand = command.RedirectTo(output);

var errorMessage = Assert.Throws<InvalidOperationException>(() => ioCommand.StandardOutput.GetHashCode()).Message;
errorMessage.ShouldEqual("StandardOutput is unavailable because it is already being piped to System.Collections.Generic.List`1[System.String]");

Assert.DoesNotThrow(() => command.StandardOutput.GetHashCode());

Assert.Throws<InvalidOperationException>(() => ioCommand.Result.StandardOutput.GetHashCode())
.Message
.ShouldEqual(errorMessage);
Assert.Throws<ObjectDisposedException>(() => command.Result.StandardOutput.GetHashCode());

CollectionAssert.AreEqual(new[] { "a" }, output);
ioCommand.Result.StandardError.ShouldEqual(command.Result.StandardError).ShouldEqual(string.Empty);
}

[Test]
public void TestStandardErrorCannotBeAccessedAfterRedirectingIt()
{
var output = new List<string>();
var command = TestShell.Run(SampleCommand, "argecho", "a");
var ioCommand = command.RedirectStandardErrorTo(output);

var errorMessage = Assert.Throws<InvalidOperationException>(() => ioCommand.StandardError.GetHashCode()).Message;
errorMessage.ShouldEqual("StandardError is unavailable because it is already being piped to System.Collections.Generic.List`1[System.String]");

Assert.DoesNotThrow(() => command.StandardError.GetHashCode());

Assert.Throws<InvalidOperationException>(() => ioCommand.Result.StandardError.GetHashCode())
.Message
.ShouldEqual(errorMessage);
Assert.Throws<ObjectDisposedException>(() => command.Result.StandardError.GetHashCode());

Assert.IsEmpty(output);
ioCommand.Result.StandardOutput.ShouldEqual(command.Result.StandardOutput).ShouldEqual($"a{Environment.NewLine}");
}

[Test]
public void TestStandardInputCannotBeAccessedAfterRedirectingIt()
{
var command = TestShell.Run(SampleCommand, "echo");
var ioCommand = command.RedirectFrom(new[] { "a" });

var errorMessage = Assert.Throws<InvalidOperationException>(() => ioCommand.StandardInput.GetHashCode()).Message;
errorMessage.ShouldEqual("StandardInput is unavailable because it is already being piped from System.String[]");

Assert.DoesNotThrow(() => command.StandardInput.GetHashCode());

ioCommand.Result.StandardOutput.ShouldEqual(command.Result.StandardOutput).ShouldEqual($"a{Environment.NewLine}");
ioCommand.Result.StandardError.ShouldEqual(command.Result.StandardError).ShouldEqual(string.Empty);
}
}
}
9 changes: 5 additions & 4 deletions MedallionShell.Tests/MedallionShell.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
<PropertyGroup>
<TargetFrameworks>net46;netcoreapp2.2</TargetFrameworks>
<IsPackable>false</IsPackable>
<LangVersion>7.2</LangVersion>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<CodeAnalysisRuleSet>..\stylecop.analyzers.ruleset</CodeAnalysisRuleSet>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<LangVersion>Latest</LangVersion>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<CodeAnalysisRuleSet>..\stylecop.analyzers.ruleset</CodeAnalysisRuleSet>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>1591</NoWarn>
</PropertyGroup>

Expand Down
4 changes: 2 additions & 2 deletions MedallionShell.Tests/SignalTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public async Task CanSendControlCToPipeline()
public async Task HandlesEdgeCases()
{
var command = TestShell.Run(SampleCommand, "sleep", "10000");
Assert.Throws<ArgumentNullException>(() => command.TrySignalAsync(null).GetType());
Assert.Throws<ArgumentNullException>(() => command.TrySignalAsync(null!).GetType());

command.Kill();
await command.Task;
Expand Down Expand Up @@ -99,7 +99,7 @@ public async Task CanSendSignalToSelf(int signal)

try
{
(await thisCommand.TrySignalAsync(CommandSignal.FromSystemValue(signal))).ShouldEqual(true);
(await thisCommand!.TrySignalAsync(CommandSignal.FromSystemValue(signal))).ShouldEqual(true);
manualResetEvent.Wait(TimeSpan.FromSeconds(5)).ShouldEqual(true);
}
finally
Expand Down
4 changes: 2 additions & 2 deletions MedallionShell.Tests/Streams/PipeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ public void TestPipeChainWithFixedLengthPipes()
asyncWrite.Wait(TimeSpan.FromSeconds(10)).ShouldEqual(true);
asyncRead.Wait(TimeSpan.FromSeconds(10)).ShouldEqual(true);
asyncRead.Result.ShouldNotEqual(null);
asyncRead.Result.Length.ShouldEqual(longText.Length);
asyncRead.Result!.Length.ShouldEqual(longText.Length);
asyncRead.Result.ShouldEqual(longText);
}

Expand Down Expand Up @@ -364,7 +364,7 @@ public static Task WriteTextAsync(this Pipe @this, string text)
return new StreamWriter(@this.InputStream) { AutoFlush = true }.WriteAsync(text);
}

public static async Task<string> ReadTextAsync(this Pipe @this, int count, CancellationToken token = default(CancellationToken))
public static async Task<string?> ReadTextAsync(this Pipe @this, int count, CancellationToken token = default(CancellationToken))
{
var bytes = new byte[count];
var bytesRead = 0;
Expand Down
6 changes: 3 additions & 3 deletions MedallionShell.Tests/UnitTestHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@ public static class UnitTestHelpers

public static Shell MakeTestShell(Action<Shell.Options> options) => new Shell(TestShell.Configuration + options);

public static T ShouldEqual<T>(this T @this, T that, string message = null)
public static T ShouldEqual<T>(this T @this, T that, string? message = null)
{
Assert.AreEqual(that, @this, message);
return @this;
}

public static T ShouldNotEqual<T>(this T @this, T that, string message = null)
public static T ShouldNotEqual<T>(this T @this, T that, string? message = null)
{
Assert.AreNotEqual(that, @this, message);
return @this;
}

public static string ShouldContain(this string haystack, string needle, string message = null)
public static string ShouldContain(this string haystack, string needle, string? message = null)
{
Assert.IsNotNull(haystack, $"Expected: contains '{needle}'. Was: NULL{(message != null ? $" ({message})" : string.Empty)}");
if (!haystack.Contains(needle))
Expand Down
Loading

0 comments on commit 2afc719

Please sign in to comment.