Skip to content

Commit

Permalink
Merge pull request madelson#112 from Bartleby2718/net-8
Browse files Browse the repository at this point in the history
Support C# 12 by installing .NET 8 SDK in the Ubuntu pipeline
  • Loading branch information
madelson authored May 12, 2024
2 parents 2632299 + 9027293 commit c27d1f1
Show file tree
Hide file tree
Showing 17 changed files with 73 additions and 125 deletions.
4 changes: 2 additions & 2 deletions MedallionShell.Tests/CommandLineSyntaxTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ 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<ArgumentException>(() => syntax.CreateArgumentString(["a", null!, "b"]));
}

[TestCase(" ")]
Expand All @@ -43,7 +43,7 @@ public void TestArgumentsRoundTrip(object[] arguments)
}

[Test]
public void TestEmptyArgumentsRoundTrip() => this.TestArgumentsRoundTripHelper(Array.Empty<string>());
public void TestEmptyArgumentsRoundTrip() => this.TestArgumentsRoundTripHelper([]);

private void TestArgumentsRoundTripHelper(string[] arguments)
{
Expand Down
36 changes: 18 additions & 18 deletions MedallionShell.Tests/GeneralTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public void TestExitCode()

var shell = MakeTestShell(o => o.ThrowOnError());
var ex = Assert.Throws<AggregateException>(() => shell.Run(SampleCommand, "exit", -1).Task.Wait());
ex!.InnerExceptions.Select(e => e.GetType()).SequenceEqual(new[] { typeof(ErrorExitCodeException) })
ex!.InnerExceptions.Select(e => e.GetType()).SequenceEqual([typeof(ErrorExitCodeException)])
.ShouldEqual(true);

shell.Run(SampleCommand, "exit", 0).Task.Wait();
Expand All @@ -119,24 +119,24 @@ public void TestExitCode()
[Test]
public void TestThrowOnErrorWithTimeout()
{
var command = TestShell.Run(SampleCommand, new object[] { "exit", 1 }, o => o.ThrowOnError().Timeout(TimeSpan.FromDays(1)));
var command = TestShell.Run(SampleCommand, ["exit", 1], o => o.ThrowOnError().Timeout(TimeSpan.FromDays(1)));
var ex = Assert.Throws<AggregateException>(() => command.Task.Wait());
ex!.InnerExceptions.Select(e => e.GetType()).SequenceEqual(new[] { typeof(ErrorExitCodeException) })
ex!.InnerExceptions.Select(e => e.GetType()).SequenceEqual([typeof(ErrorExitCodeException)])
.ShouldEqual(true);
}

[Test]
public void TestTimeout()
{
var willTimeout = TestShell.Run(SampleCommand, new object[] { "sleep", 1000000 }, o => o.Timeout(TimeSpan.FromMilliseconds(200)));
var willTimeout = TestShell.Run(SampleCommand, ["sleep", 1000000], o => o.Timeout(TimeSpan.FromMilliseconds(200)));
var ex = Assert.Throws<AggregateException>(() => willTimeout.Task.Wait());
Assert.IsInstanceOf<TimeoutException>(ex!.InnerException);
}

[Test]
public void TestZeroTimeout()
{
var willTimeout = TestShell.Run(SampleCommand, new object[] { "sleep", 1000000 }, o => o.Timeout(TimeSpan.Zero));
var willTimeout = TestShell.Run(SampleCommand, ["sleep", 1000000], o => o.Timeout(TimeSpan.Zero));
var ex = Assert.Throws<AggregateException>(() => willTimeout.Task.Wait());
Assert.IsInstanceOf<TimeoutException>(ex!.InnerException);
}
Expand All @@ -145,7 +145,7 @@ public void TestZeroTimeout()
public void TestCancellationAlreadyCanceled()
{
using var alreadyCanceled = new CancellationTokenSource(millisecondsDelay: 0);
var command = TestShell.Run(SampleCommand, new object[] { "sleep", 1000000 }, o => o.CancellationToken(alreadyCanceled.Token));
var command = TestShell.Run(SampleCommand, ["sleep", 1000000], o => o.CancellationToken(alreadyCanceled.Token));
Assert.Throws<TaskCanceledException>(() => command.Wait());
Assert.Throws<TaskCanceledException>(() => command.Result.ToString());
command.Task.Status.ShouldEqual(TaskStatus.Canceled);
Expand All @@ -156,7 +156,7 @@ public void TestCancellationAlreadyCanceled()
public void TestCancellationNotCanceled()
{
using var notCanceled = new CancellationTokenSource();
var command = TestShell.Run(SampleCommand, new object[] { "sleep", 1000000 }, o => o.CancellationToken(notCanceled.Token));
var command = TestShell.Run(SampleCommand, ["sleep", 1000000], o => o.CancellationToken(notCanceled.Token));
command.Task.Wait(50).ShouldEqual(false);
command.Kill();
command.Task.Wait(1000).ShouldEqual(true);
Expand All @@ -168,7 +168,7 @@ public void TestCancellationCanceledPartway()
{
using var cancellationTokenSource = new CancellationTokenSource();
var results = new SyncCollection();
var command = TestShell.Run(SampleCommand, new object[] { "echo", "--per-char" }, o => o.CancellationToken(cancellationTokenSource.Token)) > results;
var command = TestShell.Run(SampleCommand, ["echo", "--per-char"], o => o.CancellationToken(cancellationTokenSource.Token)) > results;
command.StandardInput.WriteLine("hello");
var timeout = Task.Delay(TimeSpan.FromSeconds(10));
while (results.Count == 0 && !timeout.IsCompleted) { }
Expand Down Expand Up @@ -202,7 +202,7 @@ public void TestCancellationCanceledAfterCompletion()
{
using var cancellationTokenSource = new CancellationTokenSource();
var results = new List<string>();
var command = TestShell.Run(SampleCommand, new object[] { "echo" }, o => o.CancellationToken(cancellationTokenSource.Token)) > results;
var command = TestShell.Run(SampleCommand, ["echo"], o => o.CancellationToken(cancellationTokenSource.Token)) > results;
command.StandardInput.WriteLine("hello");
command.StandardInput.Close();
command.Task.Wait(1000).ShouldEqual(true);
Expand All @@ -216,7 +216,7 @@ public void TestCancellationWithTimeoutTimeoutWins()
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var command = TestShell.Run(
SampleCommand,
new object[] { "sleep", 1000000 },
["sleep", 1000000],
o => o.CancellationToken(cancellationTokenSource.Token)
.Timeout(TimeSpan.FromMilliseconds(50))
);
Expand All @@ -229,7 +229,7 @@ public void TestCancellationWithTimeoutCancellationWins()
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(50));
var command = TestShell.Run(
SampleCommand,
new object[] { "sleep", 1000000 },
["sleep", 1000000],
o => o.CancellationToken(cancellationTokenSource.Token)
.Timeout(TimeSpan.FromSeconds(5))
);
Expand Down Expand Up @@ -484,10 +484,10 @@ void TestHelper(bool disposeOnExit)
command1.Process.StartInfo.Arguments.ShouldContain("--id1");
command2.Process.StartInfo.Arguments.ShouldContain("--id2");
#endif
command1.Processes.SequenceEqual(new[] { command1.Process });
command2.Processes.SequenceEqual(new[] { command2.Process }).ShouldEqual(true);
command1.Processes.SequenceEqual([command1.Process]);
command2.Processes.SequenceEqual([command2.Process]).ShouldEqual(true);
pipeCommand.Process.ShouldEqual(command2.Process);
pipeCommand.Processes.SequenceEqual(new[] { command1.Process, command2.Process }).ShouldEqual(true);
pipeCommand.Processes.SequenceEqual([command1.Process, command2.Process]).ShouldEqual(true);
}

#if NETFRAMEWORK
Expand All @@ -504,10 +504,10 @@ static string GetCommandLine(int processId)
}
#endif

command1.ProcessIds.SequenceEqual(new[] { command1.ProcessId }).ShouldEqual(true);
command2.ProcessIds.SequenceEqual(new[] { command2.ProcessId }).ShouldEqual(true);
command1.ProcessIds.SequenceEqual([command1.ProcessId]).ShouldEqual(true);
command2.ProcessIds.SequenceEqual([command2.ProcessId]).ShouldEqual(true);
pipeCommand.ProcessId.ShouldEqual(command2.ProcessId);
pipeCommand.ProcessIds.SequenceEqual(new[] { command1.ProcessId, command2.ProcessId }).ShouldEqual(true);
pipeCommand.ProcessIds.SequenceEqual([command1.ProcessId, command2.ProcessId]).ShouldEqual(true);
}
finally
{
Expand Down Expand Up @@ -609,7 +609,7 @@ public async Task TestCustomCommandLineSyntaxIsUsed()
{
using var command = TestShell.Run(
SampleCommand,
new object[] { "exit", 0 },
["exit", 0],
options: o => o.Syntax((CommandLineSyntax)Activator.CreateInstance(PlatformCompatibilityHelper.DefaultCommandLineSyntax.GetType())!)
.DisposeOnExit(false)
);
Expand Down
8 changes: 4 additions & 4 deletions MedallionShell.Tests/Streams/MergedLinesEnumerableTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ public void TestOneIsEmpty()

var enumerable1 = new MergedLinesEnumerable(empty1, nonEmpty1);
var list1 = enumerable1.ToList();
list1.SequenceEqual(new[] { "abc", "def", "ghi", "jkl" })
list1.SequenceEqual(["abc", "def", "ghi", "jkl"])
.ShouldEqual(true, string.Join(", ", list1));

var empty2 = new StringReader(string.Empty);
var nonEmpty2 = new StringReader("a\nbb\nccc\n");
var enumerable2 = new MergedLinesEnumerable(nonEmpty2, empty2);
var list2 = enumerable2.ToList();
list2.SequenceEqual(new[] { "a", "bb", "ccc" })
list2.SequenceEqual(["a", "bb", "ccc"])
.ShouldEqual(true, string.Join(", ", list2));
}

Expand All @@ -53,8 +53,8 @@ public void TestBothArePopulatedEqualSizes()
[Test]
public void TestBothArePopulatedDifferenceSizes()
{
var lines1 = string.Join("\n", new[] { "x", "y", "z" });
var lines2 = string.Join("\n", new[] { "1", "2", "3", "4", "5" });
var lines1 = string.Join("\n", ["x", "y", "z"]);
var lines2 = string.Join("\n", ["1", "2", "3", "4", "5"]);

var list1 = new MergedLinesEnumerable(new StringReader(lines1), new StringReader(lines2))
.ToList();
Expand Down
4 changes: 2 additions & 2 deletions MedallionShell.Tests/Streams/ProcessIOCancellationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public void TestProcessIOIsCancellable()
Arguments = "echo",
#else
FileName = PlatformCompatibilityTests.DotNetPath,
Arguments = PlatformCompatibilityHelper.DefaultCommandLineSyntax.CreateArgumentString(new[] { PlatformCompatibilityTests.SampleCommandPath, "echo" }),
Arguments = PlatformCompatibilityHelper.DefaultCommandLineSyntax.CreateArgumentString([PlatformCompatibilityTests.SampleCommandPath, "echo"]),
#endif
RedirectStandardInput = true,
RedirectStandardOutput = true,
Expand All @@ -45,7 +45,7 @@ public void TestProcessIOIsCancellable()
// For write, loop to fill up the buffer; eventually we'll block
while (true) { await DoIOWithCancellationAsync(process.StandardInput.BaseStream, cancellationTokenSource.Token); }
});
Task.WaitAny(new[] { readTask, writeTask }, TimeSpan.FromSeconds(0.5)).ShouldEqual(-1);
Task.WaitAny([readTask, writeTask], TimeSpan.FromSeconds(0.5)).ShouldEqual(-1);

cancellationTokenSource.Cancel();

Expand Down
4 changes: 2 additions & 2 deletions MedallionShell/AttachedCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ internal AttachedCommand(
TaskContinuationOptions.ExecuteSynchronously
);

this.processes = new Lazy<ReadOnlyCollection<Process>>(() => new ReadOnlyCollection<Process>(new[] { this.process }));
this.processes = new Lazy<ReadOnlyCollection<Process>>(() => new ReadOnlyCollection<Process>([this.process]));
}

public override Process Process
Expand Down Expand Up @@ -77,7 +77,7 @@ public override int ProcessId
}
}

public override IReadOnlyList<int> ProcessIds => new ReadOnlyCollection<int>(new[] { this.ProcessId });
public override IReadOnlyList<int> ProcessIds => new ReadOnlyCollection<int>([this.ProcessId]);

public override ProcessStreamWriter StandardInput => throw new InvalidOperationException(StreamPropertyExceptionMessage);

Expand Down
4 changes: 2 additions & 2 deletions MedallionShell/ProcessCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public override Process Process
}

private IReadOnlyList<Process>? processes;
public override IReadOnlyList<Process> Processes => this.processes ??= new ReadOnlyCollection<Process>(new[] { this.Process });
public override IReadOnlyList<Process> Processes => this.processes ??= new ReadOnlyCollection<Process>([this.Process]);

private readonly object processIdOrExceptionDispatchInfo;
public override int ProcessId
Expand All @@ -137,7 +137,7 @@ public override int ProcessId
}

private IReadOnlyList<int>? processIds;
public override IReadOnlyList<int> ProcessIds => this.processIds ??= new ReadOnlyCollection<int>(new[] { this.ProcessId });
public override IReadOnlyList<int> ProcessIds => this.processIds ??= new ReadOnlyCollection<int>([this.ProcessId]);

private readonly ProcessStreamWriter? standardInput;
public override ProcessStreamWriter StandardInput => this.standardInput ?? throw new InvalidOperationException("Standard input is not redirected");
Expand Down
4 changes: 2 additions & 2 deletions MedallionShell/Shims/Shims.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ public static T[] EmptyArray<T>() =>

private static class Empty<T>
{
public static readonly T[] Array = new T[0];
public static readonly T[] Array = [];
}
#else
Array.Empty<T>();
[];
#endif

public static Task<T> CanceledTask<T>(CancellationToken cancellationToken)
Expand Down
6 changes: 2 additions & 4 deletions MedallionShell/Shims/SpanShims.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,12 @@ public void CopyTo(Memory<T> destination) =>
System.Array.Copy(sourceArray: this.Array, sourceIndex: this.Offset, destinationArray: destination.Array, destinationIndex: destination.Offset, length: this.Length);
}

internal readonly ref struct Span<T>
internal readonly ref struct Span<T>(Memory<T> memory)
{
public readonly Memory<T> Memory;
public readonly Memory<T> Memory = memory;

public int Length => this.Memory.Length;

public Span(Memory<T> memory) { this.Memory = memory; }

public static implicit operator Span<T>(T[] array) => new(new(array, 0, array.Length));

public void CopyTo(Span<T> destination) => this.Memory.CopyTo(destination.Memory);
Expand Down
15 changes: 4 additions & 11 deletions MedallionShell/Shims/ValueTupleShims.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,10 @@

namespace System;

internal struct ValueTuple<T1, T2, T3>
internal struct ValueTuple<T1, T2, T3>(T1 item1, T2 item2, T3 item3)
{
public T1 Item1;
public T2 Item2;
public T3 Item3;

public ValueTuple(T1 item1, T2 item2, T3 item3)
{
this.Item1 = item1;
this.Item2 = item2;
this.Item3 = item3;
}
public T1 Item1 = item1;
public T2 Item2 = item2;
public T3 Item3 = item3;
}
#endif
2 changes: 1 addition & 1 deletion MedallionShell/Signals/WindowsProcessSignaler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static async Task<bool> TrySignalAsync(int processId, NativeMethods.CtrlT
var exeFile = await DeploySignalerExeAsync().ConfigureAwait(false);
try
{
var command = Command.Run(exeFile, new object[] { processId, (int)signal });
var command = Command.Run(exeFile, [processId, (int)signal]);
return (await command.Task.ConfigureAwait(false)).Success;
}
finally
Expand Down
2 changes: 1 addition & 1 deletion MedallionShell/Streams/LongRunningTaskScheduler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ protected override void QueueTask(Task task)
WorkerThreadState.StartNew(this, task);
}

protected override IEnumerable<Task> GetScheduledTasks() => Enumerable.Empty<Task>(); // all tasks run immediately
protected override IEnumerable<Task> GetScheduledTasks() => []; // all tasks run immediately

protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) => false;

Expand Down
25 changes: 6 additions & 19 deletions MedallionShell/Streams/MergedLinesEnumerable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,10 @@

namespace Medallion.Shell.Streams
{
internal sealed class MergedLinesEnumerable : IEnumerable<string>
internal sealed class MergedLinesEnumerable(TextReader standardOutput, TextReader standardError) : IEnumerable<string>
{
private readonly TextReader standardOutput, standardError;
private int consumed;

public MergedLinesEnumerable(TextReader standardOutput, TextReader standardError)
{
this.standardOutput = standardOutput;
this.standardError = standardError;
}

public IEnumerator<string> GetEnumerator()
{
Throw<InvalidOperationException>.If(
Expand All @@ -35,8 +28,8 @@ public IEnumerator<string> GetEnumerator()
private IEnumerator<string> GetEnumeratorInternal()
{
var tasks = new List<ReaderAndTask>(capacity: 2);
tasks.Add(new ReaderAndTask(this.standardOutput));
tasks.Add(new ReaderAndTask(this.standardError));
tasks.Add(new ReaderAndTask(standardOutput));
tasks.Add(new ReaderAndTask(standardError));

// phase 1: read both streams simultaneously, alternating between which is given priority.
// Stop when one (or both) streams is exhausted
Expand Down Expand Up @@ -92,16 +85,10 @@ private IEnumerator<string> GetEnumeratorInternal()
}
}

private struct ReaderAndTask : IEquatable<ReaderAndTask>
private struct ReaderAndTask(TextReader reader) : IEquatable<ReaderAndTask>
{
public ReaderAndTask(TextReader reader)
{
this.Reader = reader;
this.Task = reader.ReadLineAsync();
}

public TextReader Reader { get; }
public Task<string?> Task { get; }
public TextReader Reader { get; } = reader;
public Task<string?> Task { get; } = reader.ReadLineAsync();

public bool Equals(ReaderAndTask that) => this.Reader == that.Reader && this.Task == that.Task;

Expand Down
Loading

0 comments on commit c27d1f1

Please sign in to comment.