diff --git a/src/Cli/dotnet/Commands/Test/IPC/IClient.cs b/src/Cli/dotnet/Commands/Test/IPC/IClient.cs deleted file mode 100644 index 6fb6420565e6..000000000000 --- a/src/Cli/dotnet/Commands/Test/IPC/IClient.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable disable - -namespace Microsoft.DotNet.Cli.Commands.Test.IPC; - -internal interface IClient : -#if NETCOREAPP -IAsyncDisposable, -#endif -IDisposable -{ - bool IsConnected { get; } - - Task ConnectAsync(CancellationToken cancellationToken); - - Task RequestReplyAsync(TRequest request, CancellationToken cancellationToken) - where TRequest : IRequest - where TResponse : IResponse; -} diff --git a/src/Cli/dotnet/Commands/Test/IPC/IServer.cs b/src/Cli/dotnet/Commands/Test/IPC/IServer.cs deleted file mode 100644 index d7664d43f079..000000000000 --- a/src/Cli/dotnet/Commands/Test/IPC/IServer.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable disable - -namespace Microsoft.DotNet.Cli.Commands.Test.IPC; - -internal interface IServer : INamedPipeBase, -#if NETCOREAPP -IAsyncDisposable, -#endif -IDisposable -{ - PipeNameDescription PipeName { get; } - - Task WaitConnectionAsync(CancellationToken cancellationToken); -} diff --git a/src/Cli/dotnet/Commands/Test/IPC/NamedPipeBase.cs b/src/Cli/dotnet/Commands/Test/IPC/NamedPipeBase.cs index cce2177abc48..10da24500691 100644 --- a/src/Cli/dotnet/Commands/Test/IPC/NamedPipeBase.cs +++ b/src/Cli/dotnet/Commands/Test/IPC/NamedPipeBase.cs @@ -3,10 +3,6 @@ #nullable disable -#pragma warning disable IDE0240 // Remove redundant nullable directive -#nullable disable -#pragma warning restore IDE0240 // Remove redundant nullable directive - using System.Globalization; using Microsoft.DotNet.Cli.Commands.Test.IPC.Serializers; @@ -34,13 +30,9 @@ protected INamedPipeSerializer GetSerializer(int id, bool skipUnknownMessages = return skipUnknownMessages ? new UnknownMessageSerializer(id) : throw new ArgumentException((string.Format( - CultureInfo.InvariantCulture, -#if dotnet - LocalizableStrings.NoSerializerRegisteredWithIdErrorMessage, -#else - "No serializer registered with ID '{0}'", -#endif - id))); + CultureInfo.InvariantCulture, + CliCommandStrings.NoSerializerRegisteredWithIdErrorMessage, + id))); } } @@ -50,10 +42,6 @@ protected INamedPipeSerializer GetSerializer(Type type) ? serializer : throw new ArgumentException(string.Format( CultureInfo.InvariantCulture, -#if dotnet - LocalizableStrings.NoSerializerRegisteredWithTypeErrorMessage, -#else - "No serializer registered with type '{0}'", -#endif + CliCommandStrings.NoSerializerRegisteredWithTypeErrorMessage, type)); } diff --git a/src/Cli/dotnet/Commands/Test/IPC/NamedPipeClient.cs b/src/Cli/dotnet/Commands/Test/IPC/NamedPipeClient.cs deleted file mode 100644 index a4156154c7f8..000000000000 --- a/src/Cli/dotnet/Commands/Test/IPC/NamedPipeClient.cs +++ /dev/null @@ -1,207 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable disable - -using System.Buffers; -using System.IO.Pipes; - -namespace Microsoft.DotNet.Cli.Commands.Test.IPC; - -internal sealed class NamedPipeClient(string name) : NamedPipeBase, IClient -{ - private readonly NamedPipeClientStream _namedPipeClientStream = new(".", name, PipeDirection.InOut); - private readonly SemaphoreSlim _lock = new(1, 1); - - private readonly MemoryStream _serializationBuffer = new(); - private readonly MemoryStream _messageBuffer = new(); - private readonly byte[] _readBuffer = new byte[250000]; - - private bool _disposed; - - public string PipeName { get; } = name; - - public bool IsConnected => _namedPipeClientStream.IsConnected; - - public async Task ConnectAsync(CancellationToken cancellationToken) - => await _namedPipeClientStream.ConnectAsync(cancellationToken); - - public async Task RequestReplyAsync(TRequest request, CancellationToken cancellationToken) - where TRequest : IRequest - where TResponse : IResponse - { - await _lock.WaitAsync(cancellationToken); - try - { - INamedPipeSerializer requestNamedPipeSerializer = GetSerializer(typeof(TRequest)); - - // Ask to serialize the body - _serializationBuffer.Position = 0; - requestNamedPipeSerializer.Serialize(request, _serializationBuffer); - - // Write the message size - _messageBuffer.Position = 0; - - // The length of the message is the size of the message plus one byte to store the serializer id - // Space for the message - int sizeOfTheWholeMessage = (int)_serializationBuffer.Position; - - // Space for the serializer id - sizeOfTheWholeMessage += sizeof(int); - - // Write the message size -#if NETCOREAPP - byte[] bytes = ArrayPool.Shared.Rent(sizeof(int)); - try - { - BitConverter.TryWriteBytes(bytes, sizeOfTheWholeMessage); - await _messageBuffer.WriteAsync(bytes.AsMemory(0, sizeof(int)), cancellationToken); - } - finally - { - ArrayPool.Shared.Return(bytes); - } -#else - await _messageBuffer.WriteAsync(BitConverter.GetBytes(sizeOfTheWholeMessage), 0, sizeof(int), cancellationToken); -#endif - - // Write the serializer id -#if NETCOREAPP - bytes = ArrayPool.Shared.Rent(sizeof(int)); - try - { - BitConverter.TryWriteBytes(bytes, requestNamedPipeSerializer.Id); - await _messageBuffer.WriteAsync(bytes.AsMemory(0, sizeof(int)), cancellationToken); - } - finally - { - ArrayPool.Shared.Return(bytes); - } -#else - await _messageBuffer.WriteAsync(BitConverter.GetBytes(requestNamedPipeSerializer.Id), 0, sizeof(int), cancellationToken); -#endif - - try - { - // Write the message -#if NETCOREAPP - await _messageBuffer.WriteAsync(_serializationBuffer.GetBuffer().AsMemory(0, (int)_serializationBuffer.Position), cancellationToken); -#else - await _messageBuffer.WriteAsync(_serializationBuffer.GetBuffer(), 0, (int)_serializationBuffer.Position, cancellationToken); -#endif - } - finally - { - // Reset the serialization buffer - _serializationBuffer.Position = 0; - } - - // Send the message - try - { -#if NETCOREAPP - await _namedPipeClientStream.WriteAsync(_messageBuffer.GetBuffer().AsMemory(0, (int)_messageBuffer.Position), cancellationToken); -#else - await _namedPipeClientStream.WriteAsync(_messageBuffer.GetBuffer(), 0, (int)_messageBuffer.Position, cancellationToken); -#endif - await _namedPipeClientStream.FlushAsync(cancellationToken); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - _namedPipeClientStream.WaitForPipeDrain(); - } - } - finally - { - // Reset the buffers - _messageBuffer.Position = 0; - _serializationBuffer.Position = 0; - } - - // Read the response - int currentMessageSize = 0; - int missingBytesToReadOfWholeMessage = 0; - while (true) - { - int missingBytesToReadOfCurrentChunk = 0; - int currentReadIndex = 0; -#if NETCOREAPP - int currentReadBytes = await _namedPipeClientStream.ReadAsync(_readBuffer.AsMemory(currentReadIndex, _readBuffer.Length), cancellationToken); -#else - int currentReadBytes = await _namedPipeClientStream.ReadAsync(_readBuffer, currentReadIndex, _readBuffer.Length, cancellationToken); -#endif - // Reset the current chunk size - missingBytesToReadOfCurrentChunk = currentReadBytes; - - // If currentRequestSize is 0, we need to read the message size - if (currentMessageSize == 0) - { - // We need to read the message size, first 4 bytes - currentMessageSize = BitConverter.ToInt32(_readBuffer, 0); - missingBytesToReadOfCurrentChunk = currentReadBytes - sizeof(int); - missingBytesToReadOfWholeMessage = currentMessageSize; - currentReadIndex = sizeof(int); - } - - if (missingBytesToReadOfCurrentChunk > 0) - { - // We need to read the rest of the message -#if NETCOREAPP - await _messageBuffer.WriteAsync(_readBuffer.AsMemory(currentReadIndex, missingBytesToReadOfCurrentChunk), cancellationToken); -#else - await _messageBuffer.WriteAsync(_readBuffer, currentReadIndex, missingBytesToReadOfCurrentChunk, cancellationToken); -#endif - missingBytesToReadOfWholeMessage -= missingBytesToReadOfCurrentChunk; - } - - // If we have read all the message, we can deserialize it - if (missingBytesToReadOfWholeMessage == 0) - { - // Deserialize the message - _messageBuffer.Position = 0; - - // Get the serializer id - int serializerId = BitConverter.ToInt32(_messageBuffer.GetBuffer(), 0); - - // Get the serializer - _messageBuffer.Position += sizeof(int); // Skip the serializer id - INamedPipeSerializer responseNamedPipeSerializer = GetSerializer(serializerId); - - // Deserialize the message - try - { - return (TResponse)responseNamedPipeSerializer.Deserialize(_messageBuffer); - } - finally - { - // Reset the message buffer - _messageBuffer.Position = 0; - } - } - } - } - finally - { - _lock.Release(); - } - } - - public void Dispose() - { - if (!_disposed) - { - _namedPipeClientStream.Dispose(); - _disposed = true; - } - } - -#if NETCOREAPP - public async ValueTask DisposeAsync() - { - if (!_disposed) - { - await _namedPipeClientStream.DisposeAsync(); - _disposed = true; - } - } -#endif -} diff --git a/src/Cli/dotnet/Commands/Test/IPC/NamedPipeServer.cs b/src/Cli/dotnet/Commands/Test/IPC/NamedPipeServer.cs index 27f40d20d146..fa8ff49f2bd4 100644 --- a/src/Cli/dotnet/Commands/Test/IPC/NamedPipeServer.cs +++ b/src/Cli/dotnet/Commands/Test/IPC/NamedPipeServer.cs @@ -3,17 +3,13 @@ #nullable disable -#pragma warning disable IDE0240 // Remove redundant nullable directive -#nullable disable -#pragma warning restore IDE0240 // Remove redundant nullable directive - using System.Buffers; using System.Globalization; using System.IO.Pipes; namespace Microsoft.DotNet.Cli.Commands.Test.IPC; -internal sealed class NamedPipeServer : NamedPipeBase, IServer +internal sealed class NamedPipeServer : NamedPipeBase { private readonly Func> _callback; private readonly NamedPipeServerStream _namedPipeServerStream; @@ -21,37 +17,11 @@ internal sealed class NamedPipeServer : NamedPipeBase, IServer private readonly MemoryStream _serializationBuffer = new(); private readonly MemoryStream _messageBuffer = new(); private readonly byte[] _readBuffer = new byte[250000]; + private readonly byte[] _sizeOfIntArray = new byte[sizeof(int)]; private readonly bool _skipUnknownMessages; private Task _loopTask; private bool _disposed; - public NamedPipeServer( - string name, - Func> callback, - CancellationToken cancellationToken) - : this(GetPipeName(name), callback, cancellationToken) - { - } - - public NamedPipeServer( - PipeNameDescription pipeNameDescription, - Func> callback, - CancellationToken cancellationToken) - : this(pipeNameDescription, callback, maxNumberOfServerInstances: 1, cancellationToken) - { - } - - public NamedPipeServer( - PipeNameDescription pipeNameDescription, - Func> callback, - int maxNumberOfServerInstances, - CancellationToken cancellationToken) - { - _namedPipeServerStream = new((PipeName = pipeNameDescription).Name, PipeDirection.InOut, maxNumberOfServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); - _callback = callback; - _cancellationToken = cancellationToken; - } - public NamedPipeServer( PipeNameDescription pipeNameDescription, Func> callback, @@ -87,6 +57,10 @@ public async Task WaitConnectionAsync(CancellationToken cancellationToken) } catch (Exception ex) { + // TODO: it might be better idea to let this exception bubble to + // TestApplication. There, we should handle it by printing the exception without failing + // the whole dotnet process, and provide more info about the specific test app that failed. + // Potentially even knowing whether it's test host or test host controller that failed? Environment.FailFast($"[NamedPipeServer] Unhandled exception:{Environment.NewLine}{ex}", ex); } }, cancellationToken); @@ -106,11 +80,7 @@ private async Task InternalLoopAsync(CancellationToken cancellationToken) { int missingBytesToReadOfCurrentChunk = 0; int currentReadIndex = 0; -#if NET int currentReadBytes = await _namedPipeServerStream.ReadAsync(_readBuffer.AsMemory(currentReadIndex, _readBuffer.Length), cancellationToken); -#else - int currentReadBytes = await _namedPipeServerStream.ReadAsync(_readBuffer, currentReadIndex, _readBuffer.Length, cancellationToken); -#endif if (currentReadBytes == 0) { // The client has disconnected @@ -133,11 +103,7 @@ private async Task InternalLoopAsync(CancellationToken cancellationToken) if (missingBytesToReadOfCurrentChunk > 0) { // We need to read the rest of the message -#if NET await _messageBuffer.WriteAsync(_readBuffer.AsMemory(currentReadIndex, missingBytesToReadOfCurrentChunk), cancellationToken); -#else - await _messageBuffer.WriteAsync(_readBuffer, currentReadIndex, missingBytesToReadOfCurrentChunk, cancellationToken); -#endif missingBytesToReadOfWholeMessage -= missingBytesToReadOfCurrentChunk; } @@ -177,54 +143,23 @@ private async Task InternalLoopAsync(CancellationToken cancellationToken) sizeOfTheWholeMessage += sizeof(int); // Write the message size -#if NET - byte[] bytes = ArrayPool.Shared.Rent(sizeof(int)); - try - { - BitConverter.TryWriteBytes(bytes, sizeOfTheWholeMessage); - - await _messageBuffer.WriteAsync(bytes.AsMemory(0, sizeof(int)), cancellationToken); - } - finally - { - ArrayPool.Shared.Return(bytes); - } -#else - await _messageBuffer.WriteAsync(BitConverter.GetBytes(sizeOfTheWholeMessage), 0, sizeof(int), cancellationToken); -#endif + byte[] bytes = _sizeOfIntArray; + BitConverter.TryWriteBytes(bytes, sizeOfTheWholeMessage); + await _messageBuffer.WriteAsync(bytes, cancellationToken); // Write the serializer id -#if NET - bytes = ArrayPool.Shared.Rent(sizeof(int)); - try - { - BitConverter.TryWriteBytes(bytes, responseNamedPipeSerializer.Id); + bytes = _sizeOfIntArray; + BitConverter.TryWriteBytes(bytes, responseNamedPipeSerializer.Id); - await _messageBuffer.WriteAsync(bytes.AsMemory(0, sizeof(int)), cancellationToken); - } - finally - { - ArrayPool.Shared.Return(bytes); - } -#else - await _messageBuffer.WriteAsync(BitConverter.GetBytes(responseNamedPipeSerializer.Id), 0, sizeof(int), cancellationToken); -#endif + await _messageBuffer.WriteAsync(bytes.AsMemory(0, sizeof(int)), cancellationToken); // Write the message -#if NET await _messageBuffer.WriteAsync(_serializationBuffer.GetBuffer().AsMemory(0, (int)_serializationBuffer.Position), cancellationToken); -#else - await _messageBuffer.WriteAsync(_serializationBuffer.GetBuffer(), 0, (int)_serializationBuffer.Position, cancellationToken); -#endif // Send the message try { -#if NET await _namedPipeServerStream.WriteAsync(_messageBuffer.GetBuffer().AsMemory(0, (int)_messageBuffer.Position), cancellationToken); -#else - await _namedPipeServerStream.WriteAsync(_messageBuffer.GetBuffer(), 0, (int)_messageBuffer.Position, cancellationToken); -#endif await _namedPipeServerStream.FlushAsync(cancellationToken); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { @@ -287,35 +222,4 @@ public void Dispose() _disposed = true; } - -#if NET - public async ValueTask DisposeAsync() - { - if (_disposed) - { - return; - } - - if (WasConnected) - { - // If the loop task is null at this point we have race condition, means that the task didn't start yet and we already dispose. - // This is unexpected and we throw an exception. - - try - { - // To close gracefully we need to ensure that the client closed the stream line 103. - await _loopTask.WaitAsync(TimeSpan.FromSeconds(90)); - } - catch (TimeoutException) - { - throw new InvalidOperationException("InternalLoopAsyncDidNotExitSuccessfullyErrorMessage"); - } - } - - _namedPipeServerStream.Dispose(); - PipeName.Dispose(); - - _disposed = true; - } -#endif } diff --git a/src/Cli/dotnet/Commands/Test/IPC/Serializers/BaseSerializer.cs b/src/Cli/dotnet/Commands/Test/IPC/Serializers/BaseSerializer.cs index a0e285c056d7..aa71a568f0ee 100644 --- a/src/Cli/dotnet/Commands/Test/IPC/Serializers/BaseSerializer.cs +++ b/src/Cli/dotnet/Commands/Test/IPC/Serializers/BaseSerializer.cs @@ -1,15 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETCOREAPP using System.Buffers; -#endif namespace Microsoft.DotNet.Cli.Commands.Test.IPC.Serializers; internal abstract class BaseSerializer { -#if NETCOREAPP protected static string ReadString(Stream stream) { Span len = stackalloc byte[sizeof(int)]; @@ -32,11 +29,7 @@ protected static string ReadStringValue(Stream stream, int size) byte[] bytes = ArrayPool.Shared.Rent(size); try { -#if NET7_0_OR_GREATER stream.ReadExactly(bytes, 0, size); -#else - _ = stream.Read(bytes, 0, size); -#endif return Encoding.UTF8.GetString(bytes, 0, size); } finally @@ -161,106 +154,6 @@ protected static bool ReadBool(Stream stream) return BitConverter.ToBoolean(bytes); } -#else - protected static string ReadString(Stream stream) - { - byte[] len = new byte[sizeof(int)]; - stream.Read(len, 0, len.Length); - int length = BitConverter.ToInt32(len, 0); - byte[] bytes = new byte[length]; - stream.Read(bytes, 0, bytes.Length); - return Encoding.UTF8.GetString(bytes); - } - - protected static string ReadStringValue(Stream stream, int size) - { - byte[] bytes = new byte[size]; - _ = stream.Read(bytes, 0, bytes.Length); - - return Encoding.UTF8.GetString(bytes); - } - - protected static void WriteString(Stream stream, string str) - { - byte[] bytes = Encoding.UTF8.GetBytes(str); - byte[] len = BitConverter.GetBytes(bytes.Length); - stream.Write(len, 0, len.Length); - stream.Write(bytes, 0, bytes.Length); - } - - protected static void WriteStringValue(Stream stream, string str) - { - byte[] bytes = Encoding.UTF8.GetBytes(str); - stream.Write(bytes, 0, bytes.Length); - } - - protected static void WriteStringSize(Stream stream, string str) - { - byte[] bytes = Encoding.UTF8.GetBytes(str); - byte[] len = BitConverter.GetBytes(bytes.Length); - stream.Write(len, 0, len.Length); - } - - protected static void WriteSize(Stream stream) - where T : struct - { - int sizeInBytes = GetSize(); - byte[] len = BitConverter.GetBytes(sizeInBytes); - stream.Write(len, 0, len.Length); - } - - protected static void WriteInt(Stream stream, int value) - { - byte[] bytes = BitConverter.GetBytes(value); - stream.Write(bytes, 0, bytes.Length); - } - - protected static int ReadInt(Stream stream) - { - byte[] bytes = new byte[sizeof(int)]; - stream.Read(bytes, 0, bytes.Length); - return BitConverter.ToInt32(bytes, 0); - } - - protected static void WriteLong(Stream stream, long value) - { - byte[] bytes = BitConverter.GetBytes(value); - stream.Write(bytes, 0, bytes.Length); - } - - protected static void WriteShort(Stream stream, ushort value) - { - byte[] bytes = BitConverter.GetBytes(value); - stream.Write(bytes, 0, bytes.Length); - } - - protected static long ReadLong(Stream stream) - { - byte[] bytes = new byte[sizeof(long)]; - stream.Read(bytes, 0, bytes.Length); - return BitConverter.ToInt64(bytes, 0); - } - - protected static ushort ReadShort(Stream stream) - { - byte[] bytes = new byte[sizeof(ushort)]; - stream.Read(bytes, 0, bytes.Length); - return BitConverter.ToUInt16(bytes, 0); - } - - protected static void WriteBool(Stream stream, bool value) - { - byte[] bytes = BitConverter.GetBytes(value); - stream.Write(bytes, 0, bytes.Length); - } - - protected static bool ReadBool(Stream stream) - { - byte[] bytes = new byte[sizeof(bool)]; - stream.Read(bytes, 0, bytes.Length); - return BitConverter.ToBoolean(bytes, 0); - } -#endif protected static byte ReadByte(Stream stream) => (byte)stream.ReadByte(); diff --git a/src/Cli/dotnet/Commands/Test/IPC/Serializers/DiscoveredTestMessagesSerializer.cs b/src/Cli/dotnet/Commands/Test/IPC/Serializers/DiscoveredTestMessagesSerializer.cs index 0806d2e5b089..7e41a42f0fc1 100644 --- a/src/Cli/dotnet/Commands/Test/IPC/Serializers/DiscoveredTestMessagesSerializer.cs +++ b/src/Cli/dotnet/Commands/Test/IPC/Serializers/DiscoveredTestMessagesSerializer.cs @@ -1,9 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETCOREAPP -#endif - using System.Diagnostics; using Microsoft.DotNet.Cli.Commands.Test.IPC.Models; diff --git a/src/Cli/dotnet/Commands/Test/IPC/Serializers/FileArtifactMessagesSerializer.cs b/src/Cli/dotnet/Commands/Test/IPC/Serializers/FileArtifactMessagesSerializer.cs index 20d92deeda8f..3f01223cc0f3 100644 --- a/src/Cli/dotnet/Commands/Test/IPC/Serializers/FileArtifactMessagesSerializer.cs +++ b/src/Cli/dotnet/Commands/Test/IPC/Serializers/FileArtifactMessagesSerializer.cs @@ -1,9 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETCOREAPP -#endif - using System.Diagnostics; using Microsoft.DotNet.Cli.Commands.Test.IPC.Models; diff --git a/src/Cli/dotnet/Commands/Test/Terminal/ExceptionFlattener.cs b/src/Cli/dotnet/Commands/Test/Terminal/ExceptionFlattener.cs index 8797a590f34e..07f175f7f58a 100644 --- a/src/Cli/dotnet/Commands/Test/Terminal/ExceptionFlattener.cs +++ b/src/Cli/dotnet/Commands/Test/Terminal/ExceptionFlattener.cs @@ -3,47 +3,4 @@ namespace Microsoft.DotNet.Cli.Commands.Test.Terminal; -internal sealed class ExceptionFlattener -{ - internal static FlatException[] Flatten(string? errorMessage, Exception? exception) - { - if (errorMessage is null && exception is null) - { - return []; - } - - string? message = !string.IsNullOrWhiteSpace(errorMessage) ? errorMessage : exception?.Message; - string? type = exception?.GetType().FullName; - string? stackTrace = exception?.StackTrace; - var flatException = new FlatException(message, type, stackTrace); - - List flatExceptions = [flatException]; - - // Add all inner exceptions. This will flatten top level AggregateExceptions, - // and all AggregateExceptions that are directly in AggregateExceptions, but won't expand - // AggregateExceptions that are in non-aggregate exception inner exceptions. - IEnumerable aggregateExceptions = exception switch - { - AggregateException aggregate => aggregate.Flatten().InnerExceptions, - _ => [exception?.InnerException!], - }; - - foreach (Exception? aggregate in aggregateExceptions) - { - Exception? currentException = aggregate; - while (currentException is not null) - { - flatExceptions.Add(new FlatException( - aggregate?.Message, - aggregate?.GetType().FullName, - aggregate?.StackTrace)); - - currentException = currentException.InnerException; - } - } - - return [.. flatExceptions]; - } -} - internal sealed record FlatException(string? ErrorMessage, string? ErrorType, string? StackTrace); diff --git a/src/Cli/dotnet/Commands/Test/Terminal/SystemConsole.cs b/src/Cli/dotnet/Commands/Test/Terminal/SystemConsole.cs index 5ed9064cb000..d175d7ca452b 100644 --- a/src/Cli/dotnet/Commands/Test/Terminal/SystemConsole.cs +++ b/src/Cli/dotnet/Commands/Test/Terminal/SystemConsole.cs @@ -23,8 +23,6 @@ internal sealed class SystemConsole : IConsole /// public bool IsOutputRedirected => Console.IsOutputRedirected; - private bool _suppressOutput; - static SystemConsole() => // From https://github.com/dotnet/runtime/blob/main/src/libraries/System.Console/src/System/Console.cs#L236 CaptureConsoleOutWriter = new StreamWriter( @@ -40,173 +38,71 @@ static SystemConsole() => // but can just kill the app in the device via a gesture public event ConsoleCancelEventHandler? CancelKeyPress { - add - { -#if NET8_0_OR_GREATER - if (RuntimeInformation.RuntimeIdentifier.Contains("ios") || - RuntimeInformation.RuntimeIdentifier.Contains("android")) - { - return; - } -#endif - -#pragma warning disable IDE0027 // Use expression body for accessor - Console.CancelKeyPress += value; -#pragma warning restore IDE0027 // Use expression body for accessor - } - - remove - { -#if NET8_0_OR_GREATER - if (RuntimeInformation.RuntimeIdentifier.Contains("ios") || - RuntimeInformation.RuntimeIdentifier.Contains("android")) - { - return; - } -#endif -#pragma warning disable IDE0027 // Use expression body for accessor - Console.CancelKeyPress -= value; -#pragma warning restore IDE0027 // Use expression body for accessor - } + add => Console.CancelKeyPress += value; + remove => Console.CancelKeyPress -= value; } - public void SuppressOutput() => _suppressOutput = true; - public void WriteLine() { - if (!_suppressOutput) - { - CaptureConsoleOutWriter.WriteLine(); - } + CaptureConsoleOutWriter.WriteLine(); } public void WriteLine(string? value) { - if (!_suppressOutput) - { - CaptureConsoleOutWriter.WriteLine(value); - } + CaptureConsoleOutWriter.WriteLine(value); } public void WriteLine(object? value) { - if (!_suppressOutput) - { - CaptureConsoleOutWriter.WriteLine(value); - } + CaptureConsoleOutWriter.WriteLine(value); } public void WriteLine(string format, object? arg0) { - if (!_suppressOutput) - { - CaptureConsoleOutWriter.WriteLine(format, arg0); - } + CaptureConsoleOutWriter.WriteLine(format, arg0); } public void WriteLine(string format, object? arg0, object? arg1) { - if (!_suppressOutput) - { - CaptureConsoleOutWriter.WriteLine(format, arg0, arg1); - } + CaptureConsoleOutWriter.WriteLine(format, arg0, arg1); } public void WriteLine(string format, object? arg0, object? arg1, object? arg2) { - if (!_suppressOutput) - { - CaptureConsoleOutWriter.WriteLine(format, arg0, arg1, arg2); - } + CaptureConsoleOutWriter.WriteLine(format, arg0, arg1, arg2); } public void WriteLine(string format, object?[]? args) { - if (!_suppressOutput) - { - CaptureConsoleOutWriter.WriteLine(format, args!); - } + CaptureConsoleOutWriter.WriteLine(format, args!); } public void Write(string format, object?[]? args) { - if (!_suppressOutput) - { - CaptureConsoleOutWriter.Write(format, args!); - } + CaptureConsoleOutWriter.Write(format, args!); } public void Write(string? value) { - if (!_suppressOutput) - { - CaptureConsoleOutWriter.Write(value); - } + CaptureConsoleOutWriter.Write(value); } public void Write(char value) { - if (!_suppressOutput) - { - CaptureConsoleOutWriter.Write(value); - } + CaptureConsoleOutWriter.Write(value); } public void SetForegroundColor(ConsoleColor color) - { -#if NET8_0_OR_GREATER - if (RuntimeInformation.RuntimeIdentifier.Contains("ios") || - RuntimeInformation.RuntimeIdentifier.Contains("android")) - { - return; - } -#endif -#pragma warning disable IDE0022 // Use expression body for method - Console.ForegroundColor = color; -#pragma warning restore IDE0022 // Use expression body for method - } + => Console.ForegroundColor = color; public void SetBackgroundColor(ConsoleColor color) - { -#if NET8_0_OR_GREATER - if (RuntimeInformation.RuntimeIdentifier.Contains("ios") || - RuntimeInformation.RuntimeIdentifier.Contains("android")) - { - return; - } -#endif -#pragma warning disable IDE0022 // Use expression body for method - Console.BackgroundColor = color; -#pragma warning restore IDE0022 // Use expression body for method - } + => Console.BackgroundColor = color; public ConsoleColor GetForegroundColor() - { -#if NET8_0_OR_GREATER - if (RuntimeInformation.RuntimeIdentifier.Contains("ios") || - RuntimeInformation.RuntimeIdentifier.Contains("android")) - { - return ConsoleColor.Black; - } -#endif -#pragma warning disable IDE0022 // Use expression body for method - return Console.ForegroundColor; -#pragma warning restore IDE0022 // Use expression body for method - } + => Console.ForegroundColor; public ConsoleColor GetBackgroundColor() - { -#if NET8_0_OR_GREATER - if (RuntimeInformation.RuntimeIdentifier.Contains("ios") || - RuntimeInformation.RuntimeIdentifier.Contains("android")) - { - return ConsoleColor.Black; - } -#endif -#pragma warning disable IDE0022 // Use expression body for method - return Console.BackgroundColor; -#pragma warning restore IDE0022 // Use expression body for method - } + => Console.BackgroundColor; public void Clear() => Console.Clear(); } diff --git a/src/Cli/dotnet/Commands/Test/Terminal/TerminalTestReporter.cs b/src/Cli/dotnet/Commands/Test/Terminal/TerminalTestReporter.cs index a977e74849af..658d7f2bafde 100644 --- a/src/Cli/dotnet/Commands/Test/Terminal/TerminalTestReporter.cs +++ b/src/Cli/dotnet/Commands/Test/Terminal/TerminalTestReporter.cs @@ -63,62 +63,10 @@ internal event EventHandler OnProgressStopUpdate public bool HasHandshakeFailure => _handshakeFailuresCount > 0; -#if NET7_0_OR_GREATER // Specifying no timeout, the regex is linear. And the timeout does not measure the regex only, but measures also any // thread suspends, so the regex gets blamed incorrectly. [GeneratedRegex(@$"^ at ((?.+) in (?.+):line (?\d+)|(?.+))$", RegexOptions.ExplicitCapture)] private static partial Regex GetFrameRegex(); -#else - private static Regex? s_regex; - - [MemberNotNull(nameof(s_regex))] - private static Regex GetFrameRegex() - { - if (s_regex != null) - { - return s_regex; - } - - string atResourceName = "Word_At"; - string inResourceName = "StackTrace_InFileLineNumber"; - - string? atString = null; - string? inString = null; - - // Grab words from localized resource, in case the stack trace is localized. - try - { - // Get these resources: https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx -#pragma warning disable RS0030 // Do not use banned APIs - MethodInfo? getResourceStringMethod = typeof(Environment).GetMethod( - "GetResourceString", - BindingFlags.Static | BindingFlags.NonPublic, null, [typeof(string)], null); -#pragma warning restore RS0030 // Do not use banned APIs - if (getResourceStringMethod is not null) - { - // at - atString = (string?)getResourceStringMethod.Invoke(null, [atResourceName]); - - // in {0}:line {1} - inString = (string?)getResourceStringMethod.Invoke(null, [inResourceName]); - } - } - catch - { - // If we fail, populate the defaults below. - } - - atString = atString == null || atString == atResourceName ? "at" : atString; - inString = inString == null || inString == inResourceName ? "in {0}:line {1}" : inString; - - string inPattern = string.Format(CultureInfo.InvariantCulture, inString, "(?.+)", @"(?\d+)"); - - // Specifying no timeout, the regex is linear. And the timeout does not measure the regex only, but measures also any - // thread suspends, so the regex gets blamed incorrectly. - s_regex = new Regex(@$"^ {atString} ((?.+) {inPattern}|(?.+))$", RegexOptions.Compiled | RegexOptions.ExplicitCapture); - return s_regex; - } -#endif private int _counter; private bool _disableTestRunSummary; diff --git a/src/Cli/dotnet/Commands/Test/TestApplication.cs b/src/Cli/dotnet/Commands/Test/TestApplication.cs index f16e8142af35..cc000aa39fe3 100644 --- a/src/Cli/dotnet/Commands/Test/TestApplication.cs +++ b/src/Cli/dotnet/Commands/Test/TestApplication.cs @@ -3,7 +3,6 @@ #nullable disable -using System.CommandLine; using System.Diagnostics; using System.IO.Pipes; using Microsoft.DotNet.Cli.Commands.Test.IPC; diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj b/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj index b0356f4a0c04..157fde746f9d 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj +++ b/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj @@ -104,7 +104,6 @@ -