From 876072642c408b8a240325005229f907770a9824 Mon Sep 17 00:00:00 2001 From: mariam-abdulla Date: Wed, 4 Sep 2024 14:57:42 +0200 Subject: [PATCH 1/2] Update dotnet test protocol messages --- .../commands/dotnet-test/CliConstants.cs | 2 +- .../commands/dotnet-test/CustomEventArgs.cs | 33 +- .../IPC/Models/CommandLineOptionMessages.cs | 2 +- ...stMessage.cs => DiscoveredTestMessages.cs} | 4 +- .../IPC/Models/FileArtifactInfo.cs | 9 - .../IPC/Models/FileArtifactMessages.cs | 11 + .../{HandshakeInfo.cs => HandshakeMessage.cs} | 2 +- ...ResultMessage.cs => TestResultMessages.cs} | 6 +- .../dotnet-test/IPC/ObjectFieldIds.cs | 40 ++- .../CommandLineOptionMessagesSerializer.cs | 29 +- .../DiscoveredTestMessageSerializer.cs | 87 ----- .../DiscoveredTestMessagesSerializer.cs | 157 ++++++++ .../Serializers/FileArtifactInfoSerializer.cs | 130 ------- .../FileArtifactMessagesSerializer.cs | 197 +++++++++++ ...lizer.cs => HandshakeMessageSerializer.cs} | 15 +- .../IPC/Serializers/RegisterSerializers.cs | 20 +- .../TestResultMessageSerializer.cs | 249 ------------- .../TestResultMessagesSerializer.cs | 334 ++++++++++++++++++ .../dotnet-test/MSBuildConnectionHandler.cs | 1 - src/Cli/dotnet/commands/dotnet-test/Models.cs | 21 ++ .../commands/dotnet-test/TestApplication.cs | 94 +++-- .../dotnet-test/TestModulesFilterHandler.cs | 1 - .../TestingPlatformCommand.Help.cs | 43 ++- .../dotnet-test/TestingPlatformCommand.cs | 73 ++-- 24 files changed, 915 insertions(+), 645 deletions(-) rename src/Cli/dotnet/commands/dotnet-test/IPC/Models/{DiscoveredTestMessage.cs => DiscoveredTestMessages.cs} (66%) delete mode 100644 src/Cli/dotnet/commands/dotnet-test/IPC/Models/FileArtifactInfo.cs create mode 100644 src/Cli/dotnet/commands/dotnet-test/IPC/Models/FileArtifactMessages.cs rename src/Cli/dotnet/commands/dotnet-test/IPC/Models/{HandshakeInfo.cs => HandshakeMessage.cs} (68%) rename src/Cli/dotnet/commands/dotnet-test/IPC/Models/{TestResultMessage.cs => TestResultMessages.cs} (66%) delete mode 100644 src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/DiscoveredTestMessageSerializer.cs create mode 100644 src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/DiscoveredTestMessagesSerializer.cs delete mode 100644 src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/FileArtifactInfoSerializer.cs create mode 100644 src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/FileArtifactMessagesSerializer.cs rename src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/{HandshakeInfoSerializer.cs => HandshakeMessageSerializer.cs} (67%) delete mode 100644 src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/TestResultMessageSerializer.cs create mode 100644 src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/TestResultMessagesSerializer.cs create mode 100644 src/Cli/dotnet/commands/dotnet-test/Models.cs diff --git a/src/Cli/dotnet/commands/dotnet-test/CliConstants.cs b/src/Cli/dotnet/commands/dotnet-test/CliConstants.cs index 3604c74df456..50f9e375fd6b 100644 --- a/src/Cli/dotnet/commands/dotnet-test/CliConstants.cs +++ b/src/Cli/dotnet/commands/dotnet-test/CliConstants.cs @@ -35,7 +35,7 @@ internal static class SessionEventTypes internal const byte TestSessionEnd = 1; } - internal static class HandshakeInfoPropertyNames + internal static class HandshakeMessagePropertyNames { internal const byte PID = 0; internal const byte Architecture = 1; diff --git a/src/Cli/dotnet/commands/dotnet-test/CustomEventArgs.cs b/src/Cli/dotnet/commands/dotnet-test/CustomEventArgs.cs index ec2c5fa5a63f..a3139d6df88b 100644 --- a/src/Cli/dotnet/commands/dotnet-test/CustomEventArgs.cs +++ b/src/Cli/dotnet/commands/dotnet-test/CustomEventArgs.cs @@ -1,43 +1,46 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.DotNet.Tools.Test; - namespace Microsoft.DotNet.Cli { - internal class HandshakeInfoArgs : EventArgs + internal class HandshakeArgs : EventArgs { - public HandshakeInfo handshakeInfo { get; set; } + public Handshake Handshake { get; set; } } internal class HelpEventArgs : EventArgs { - public CommandLineOptionMessages CommandLineOptionMessages { get; set; } + public string ModulePath { get; set; } + + public CommandLineOption[] CommandLineOptions { get; set; } } internal class DiscoveredTestEventArgs : EventArgs { - public DiscoveredTestMessage DiscoveredTestMessage { get; set; } - } + public string ExecutionId { get; set; } - internal class SuccessfulTestResultEventArgs : EventArgs - { - public SuccessfulTestResultMessage SuccessfulTestResultMessage { get; set; } + public DiscoveredTest[] DiscoveredTests { get; set; } } - internal class FailedTestResultEventArgs : EventArgs + internal class TestResultEventArgs : EventArgs { - public FailedTestResultMessage FailedTestResultMessage { get; set; } + public string ExecutionId { get; set; } + + public SuccessfulTestResult[] SuccessfulTestResults { get; set; } + + public FailedTestResult[] FailedTestResults { get; set; } } - internal class FileArtifactInfoEventArgs : EventArgs + internal class FileArtifactEventArgs : EventArgs { - public FileArtifactInfo FileArtifactInfo { get; set; } + public string ExecutionId { get; set; } + + public FileArtifact[] FileArtifacts { get; set; } } internal class SessionEventArgs : EventArgs { - public TestSessionEvent SessionEvent { get; set; } + public TestSession SessionEvent { get; set; } } internal class ErrorEventArgs : EventArgs diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Models/CommandLineOptionMessages.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Models/CommandLineOptionMessages.cs index da147078e075..18c1c377e4c6 100644 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Models/CommandLineOptionMessages.cs +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Models/CommandLineOptionMessages.cs @@ -5,7 +5,7 @@ namespace Microsoft.DotNet.Tools.Test { - internal sealed record CommandLineOptionMessage(string? Name, string? Description, bool? IsHidden, bool? IsBuiltIn) : IRequest; + internal sealed record CommandLineOptionMessage(string? Name, string? Description, bool? IsHidden, bool? IsBuiltIn); internal sealed record CommandLineOptionMessages(string? ModulePath, CommandLineOptionMessage[]? CommandLineOptionMessageList) : IRequest; } diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Models/DiscoveredTestMessage.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Models/DiscoveredTestMessages.cs similarity index 66% rename from src/Cli/dotnet/commands/dotnet-test/IPC/Models/DiscoveredTestMessage.cs rename to src/Cli/dotnet/commands/dotnet-test/IPC/Models/DiscoveredTestMessages.cs index cb3683c029ff..94ceaf749a8d 100644 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Models/DiscoveredTestMessage.cs +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Models/DiscoveredTestMessages.cs @@ -5,5 +5,7 @@ namespace Microsoft.DotNet.Tools.Test { - internal sealed record DiscoveredTestMessage(string? Uid, string? DisplayName, string? ExecutionId) : IRequest; + internal sealed record DiscoveredTestMessage(string? Uid, string? DisplayName); + + internal sealed record DiscoveredTestMessages(string? ExecutionId, DiscoveredTestMessage[] DiscoveredMessages) : IRequest; } diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Models/FileArtifactInfo.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Models/FileArtifactInfo.cs deleted file mode 100644 index e1f7f137ee34..000000000000 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Models/FileArtifactInfo.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -#nullable enable - -namespace Microsoft.DotNet.Tools.Test -{ - internal sealed record FileArtifactInfo(string? FullPath, string? DisplayName, string? Description, string? TestUid, string? TestDisplayName, string? SessionUid, string? ExecutionId) : IRequest; -} diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Models/FileArtifactMessages.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Models/FileArtifactMessages.cs new file mode 100644 index 000000000000..8e7f2f6a7c3f --- /dev/null +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Models/FileArtifactMessages.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#nullable enable + +namespace Microsoft.DotNet.Tools.Test +{ + internal sealed record FileArtifactMessage(string? FullPath, string? DisplayName, string? Description, string? TestUid, string? TestDisplayName, string? SessionUid); + + internal sealed record FileArtifactMessages(string? ExecutionId, FileArtifactMessage[] FileArtifacts) : IRequest; +} diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Models/HandshakeInfo.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Models/HandshakeMessage.cs similarity index 68% rename from src/Cli/dotnet/commands/dotnet-test/IPC/Models/HandshakeInfo.cs rename to src/Cli/dotnet/commands/dotnet-test/IPC/Models/HandshakeMessage.cs index 7233aae31dcc..8d7c922536e6 100644 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Models/HandshakeInfo.cs +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Models/HandshakeMessage.cs @@ -5,5 +5,5 @@ namespace Microsoft.DotNet.Tools.Test { - internal sealed record HandshakeInfo(Dictionary? Properties) : IRequest, IResponse; + internal sealed record HandshakeMessage(Dictionary? Properties) : IRequest, IResponse; } diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Models/TestResultMessage.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Models/TestResultMessages.cs similarity index 66% rename from src/Cli/dotnet/commands/dotnet-test/IPC/Models/TestResultMessage.cs rename to src/Cli/dotnet/commands/dotnet-test/IPC/Models/TestResultMessages.cs index 7e2febe287c0..0efbdcb92e12 100644 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Models/TestResultMessage.cs +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Models/TestResultMessages.cs @@ -5,7 +5,9 @@ namespace Microsoft.DotNet.Tools.Test { - internal sealed record SuccessfulTestResultMessage(string? Uid, string? DisplayName, byte? State, string? Reason, string? SessionUid, string? ExecutionId) : IRequest; + internal sealed record SuccessfulTestResultMessage(string? Uid, string? DisplayName, byte? State, string? Reason, string? SessionUid); - internal sealed record FailedTestResultMessage(string? Uid, string? DisplayName, byte? State, string? Reason, string? ErrorMessage, string? ErrorStackTrace, string? SessionUid, string? ExecutionId) : IRequest; + internal sealed record FailedTestResultMessage(string? Uid, string? DisplayName, byte? State, string? Reason, string? ErrorMessage, string? ErrorStackTrace, string? SessionUid); + + internal sealed record TestResultMessages(string? ExecutionId, SuccessfulTestResultMessage[] SuccessfulTestMessages, FailedTestResultMessage[] FailedTestMessages) : IRequest; } diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/ObjectFieldIds.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/ObjectFieldIds.cs index 536e46211a9f..20fbaea21c02 100644 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/ObjectFieldIds.cs +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/ObjectFieldIds.cs @@ -43,32 +43,40 @@ internal static class ModuleFieldsId public const int MessagesSerializerId = 4; } - internal static class DiscoveredTestMessageFieldsId + internal static class DiscoveredTestMessagesFieldsId { public const int MessagesSerializerId = 5; + public const ushort ExecutionId = 1; + public const ushort DiscoveredTestMessageList = 2; + } + + internal static class DiscoveredTestMessageFieldsId + { public const ushort Uid = 1; public const ushort DisplayName = 2; - public const ushort ExecutionId = 3; } - - internal static class SuccessfulTestResultMessageFieldsId + internal static class TestResultMessagesFieldsId { public const int MessagesSerializerId = 6; + public const ushort ExecutionId = 1; + public const ushort SuccessfulTestMessageList = 2; + public const ushort FailedTestMessageList = 3; + } + + internal static class SuccessfulTestResultMessageFieldsId + { public const ushort Uid = 1; public const ushort DisplayName = 2; public const ushort State = 3; public const ushort Reason = 4; public const ushort SessionUid = 5; - public const ushort ExecutionId = 6; } internal static class FailedTestResultMessageFieldsId { - public const int MessagesSerializerId = 7; - public const ushort Uid = 1; public const ushort DisplayName = 2; public const ushort State = 3; @@ -76,33 +84,37 @@ internal static class FailedTestResultMessageFieldsId public const ushort ErrorMessage = 5; public const ushort ErrorStackTrace = 6; public const ushort SessionUid = 7; - public const ushort ExecutionId = 8; } - internal static class FileArtifactInfoFieldsId + internal static class FileArtifactMessagesFieldsId { - public const int MessagesSerializerId = 8; + public const int MessagesSerializerId = 7; + public const ushort ExecutionId = 1; + public const ushort FileArtifactMessageList = 2; + } + + internal static class FileArtifactMessageFieldsId + { public const ushort FullPath = 1; public const ushort DisplayName = 2; public const ushort Description = 3; public const ushort TestUid = 4; public const ushort TestDisplayName = 5; public const ushort SessionUid = 6; - public const ushort ExecutionId = 7; } internal static class TestSessionEventFieldsId { - public const int MessagesSerializerId = 9; + public const int MessagesSerializerId = 8; public const ushort SessionType = 1; public const ushort SessionUid = 2; public const ushort ExecutionId = 3; } - internal static class HandshakeInfoFieldsId + internal static class HandshakeMessageFieldsId { - public const int MessagesSerializerId = 10; + public const int MessagesSerializerId = 9; } } diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/CommandLineOptionMessagesSerializer.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/CommandLineOptionMessagesSerializer.cs index 163df2dcdf0c..23c6db5532e0 100644 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/CommandLineOptionMessagesSerializer.cs +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/CommandLineOptionMessagesSerializer.cs @@ -23,21 +23,21 @@ namespace Microsoft.DotNet.Tools.Test |---CommandLineOptionMessageList[0] FieldCount---| 2 bytes - |---CommandLineOptionMessageList[0] Name Id---| (2 bytes) - |---CommandLineOptionMessageList[0] Name Size---| (4 bytes) - |---CommandLineOptionMessageList[0] Name Value---| (n bytes) + |---CommandLineOptionMessageList[0].Name Id---| (2 bytes) + |---CommandLineOptionMessageList[0].Name Size---| (4 bytes) + |---CommandLineOptionMessageList[0].Name Value---| (n bytes) - |---CommandLineOptionMessageList[1] Description Id---| (2 bytes) - |---CommandLineOptionMessageList[1] Description Size---| (4 bytes) - |---CommandLineOptionMessageList[1] Description Value---| (n bytes) + |---CommandLineOptionMessageList[0].Description Id---| (2 bytes) + |---CommandLineOptionMessageList[0].Description Size---| (4 bytes) + |---CommandLineOptionMessageList[0].Description Value---| (n bytes) - |---CommandLineOptionMessageList[3] IsHidden Id---| (2 bytes) - |---CommandLineOptionMessageList[3] IsHidden Size---| (4 bytes) - |---CommandLineOptionMessageList[3] IsHidden Value---| (1 byte) + |---CommandLineOptionMessageList[0].IsHidden Id---| (2 bytes) + |---CommandLineOptionMessageList[0].IsHidden Size---| (4 bytes) + |---CommandLineOptionMessageList[0].IsHidden Value---| (1 byte) - |---CommandLineOptionMessageList[4] IsBuiltIn Id---| (2 bytes) - |---CommandLineOptionMessageList[4] IsBuiltIn Size---| (4 bytes) - |---CommandLineOptionMessageList[4] IsBuiltIn Value---| (1 byte) + |---CommandLineOptionMessageList[0].IsBuiltIn Id---| (2 bytes) + |---CommandLineOptionMessageList[0].IsBuiltIn Size---| (4 bytes) + |---CommandLineOptionMessageList[0].IsBuiltIn Value---| (1 byte) */ internal sealed class CommandLineOptionMessagesSerializer : BaseSerializer, INamedPipeSerializer @@ -167,11 +167,12 @@ private static void WriteCommandLineOptionMessagesPayload(Stream stream, Command private static ushort GetFieldCount(CommandLineOptionMessages commandLineOptionMessages) => (ushort)((commandLineOptionMessages.ModulePath is null ? 0 : 1) + - (commandLineOptionMessages is null ? 0 : 1)); + (commandLineOptionMessages.CommandLineOptionMessageList is null ? 0 : 1)); private static ushort GetFieldCount(CommandLineOptionMessage commandLineOptionMessage) => (ushort)((commandLineOptionMessage.Name is null ? 0 : 1) + (commandLineOptionMessage.Description is null ? 0 : 1) + - 2); + (commandLineOptionMessage.IsHidden is null ? 0 : 1) + + (commandLineOptionMessage.IsBuiltIn is null ? 0 : 1)); } } diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/DiscoveredTestMessageSerializer.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/DiscoveredTestMessageSerializer.cs deleted file mode 100644 index 7be8e8691990..000000000000 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/DiscoveredTestMessageSerializer.cs +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -#if NETCOREAPP -#nullable enable -#endif - -using System.Diagnostics; - -namespace Microsoft.DotNet.Tools.Test -{ - /* - |---FieldCount---| 2 bytes - - |---File Uid Id---| (2 bytes) - |---File Uid Size---| (4 bytes) - |---File Uid Value---| (n bytes) - - |---File DisplayName Id---| (2 bytes) - |---File DisplayName Size---| (4 bytes) - |---File DisplayName Value---| (n bytes) - - |---File ExecutionId Id---| (2 bytes) - |---File ExecutionId Size---| (4 bytes) - |---File ExecutionId Value---| (n bytes) - */ - - internal sealed class DiscoveredTestMessageSerializer : BaseSerializer, INamedPipeSerializer - { - public int Id => DiscoveredTestMessageFieldsId.MessagesSerializerId; - - public object Deserialize(Stream stream) - { - string? uid = null; - string? displayName = null; - string? executionId = null; - - ushort fieldCount = ReadShort(stream); - - for (int i = 0; i < fieldCount; i++) - { - int fieldId = ReadShort(stream); - int fieldSize = ReadInt(stream); - - switch (fieldId) - { - case DiscoveredTestMessageFieldsId.Uid: - uid = ReadString(stream); - break; - - case DiscoveredTestMessageFieldsId.DisplayName: - displayName = ReadString(stream); - break; - - case DiscoveredTestMessageFieldsId.ExecutionId: - executionId = ReadString(stream); - break; - - default: - // If we don't recognize the field id, skip the payload corresponding to that field - SetPosition(stream, stream.Position + fieldSize); - break; - } - } - - return new DiscoveredTestMessage(uid, displayName, executionId); - } - - public void Serialize(object objectToSerialize, Stream stream) - { - Debug.Assert(stream.CanSeek, "We expect a seekable stream."); - - var discoveredTestMessage = (DiscoveredTestMessage)objectToSerialize; - - WriteShort(stream, GetFieldCount(discoveredTestMessage)); - - WriteField(stream, DiscoveredTestMessageFieldsId.Uid, discoveredTestMessage.Uid); - WriteField(stream, DiscoveredTestMessageFieldsId.DisplayName, discoveredTestMessage.DisplayName); - WriteField(stream, DiscoveredTestMessageFieldsId.ExecutionId, discoveredTestMessage.ExecutionId); - } - - private static ushort GetFieldCount(DiscoveredTestMessage discoveredTestMessage) => - (ushort)((discoveredTestMessage.Uid is null ? 0 : 1) + - (discoveredTestMessage.DisplayName is null ? 0 : 1) + - (discoveredTestMessage.ExecutionId is null ? 0 : 1)); - } -} diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/DiscoveredTestMessagesSerializer.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/DiscoveredTestMessagesSerializer.cs new file mode 100644 index 000000000000..a9aa0c0c5cc7 --- /dev/null +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/DiscoveredTestMessagesSerializer.cs @@ -0,0 +1,157 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if NETCOREAPP +#nullable enable +#endif + +using System.Diagnostics; + +namespace Microsoft.DotNet.Tools.Test +{ + /* + |---FieldCount---| 2 bytes + + |---ExecutionId Id---| (2 bytes) + |---ExecutionId Size---| (4 bytes) + |---ExecutionId Value---| (n bytes) + + |---DiscoveredTestMessageList Id---| (2 bytes) + |---DiscoveredTestMessageList Size---| (4 bytes) + |---DiscoveredTestMessageList Value---| (n bytes) + |---DiscoveredTestMessageList Length---| (4 bytes) + + |---DiscoveredTestMessageList[0] FieldCount---| 2 bytes + + |---DiscoveredTestMessageList[0].Uid Id---| (2 bytes) + |---DiscoveredTestMessageList[0].Uid Size---| (4 bytes) + |---DiscoveredTestMessageList[0].Uid Value---| (n bytes) + + |---DiscoveredTestMessageList[0].DisplayName Id---| (2 bytes) + |---DiscoveredTestMessageList[0].DisplayName Size---| (4 bytes) + |---DiscoveredTestMessageList[0].DisplayName Value---| (n bytes) + */ + + internal sealed class DiscoveredTestMessagesSerializer : BaseSerializer, INamedPipeSerializer + { + public int Id => DiscoveredTestMessagesFieldsId.MessagesSerializerId; + + public object Deserialize(Stream stream) + { + string? executionId = null; + List? discoveredTestMessages = null; + + ushort fieldCount = ReadShort(stream); + + for (int i = 0; i < fieldCount; i++) + { + int fieldId = ReadShort(stream); + int fieldSize = ReadInt(stream); + + switch (fieldId) + { + case DiscoveredTestMessagesFieldsId.ExecutionId: + executionId = ReadString(stream); + break; + + case DiscoveredTestMessagesFieldsId.DiscoveredTestMessageList: + discoveredTestMessages = ReadDiscoveredTestMessagesPayload(stream); + break; + + default: + // If we don't recognize the field id, skip the payload corresponding to that field + SetPosition(stream, stream.Position + fieldSize); + break; + } + } + + return new DiscoveredTestMessages(executionId, discoveredTestMessages is null ? [] : [.. discoveredTestMessages]); + } + + private static List ReadDiscoveredTestMessagesPayload(Stream stream) + { + List discoveredTestMessages = []; + + int length = ReadInt(stream); + for (int i = 0; i < length; i++) + { + string? uid = null, displayName = null; + + int fieldCount = ReadShort(stream); + + for (int j = 0; j < fieldCount; j++) + { + int fieldId = ReadShort(stream); + int fieldSize = ReadInt(stream); + + switch (fieldId) + { + case DiscoveredTestMessageFieldsId.Uid: + uid = ReadString(stream); + break; + + case DiscoveredTestMessageFieldsId.DisplayName: + displayName = ReadString(stream); + break; + + default: + SetPosition(stream, stream.Position + fieldSize); + break; + } + } + + discoveredTestMessages.Add(new DiscoveredTestMessage(uid, displayName)); + } + + return discoveredTestMessages; + } + + public void Serialize(object objectToSerialize, Stream stream) + { + Debug.Assert(stream.CanSeek, "We expect a seekable stream."); + + var discoveredTestMessages = (DiscoveredTestMessages)objectToSerialize; + + WriteShort(stream, GetFieldCount(discoveredTestMessages)); + + WriteField(stream, DiscoveredTestMessagesFieldsId.ExecutionId, discoveredTestMessages.ExecutionId); + WriteDiscoveredTestMessagesPayload(stream, discoveredTestMessages.DiscoveredMessages); + } + + private static void WriteDiscoveredTestMessagesPayload(Stream stream, DiscoveredTestMessage[]? discoveredTestMessageList) + { + if (discoveredTestMessageList is null || discoveredTestMessageList.Length == 0) + { + return; + } + + WriteShort(stream, DiscoveredTestMessagesFieldsId.DiscoveredTestMessageList); + + // We will reserve an int (4 bytes) + // so that we fill the size later, once we write the payload + WriteInt(stream, 0); + + long before = stream.Position; + WriteInt(stream, discoveredTestMessageList.Length); + foreach (DiscoveredTestMessage discoveredTestMessage in discoveredTestMessageList) + { + WriteShort(stream, GetFieldCount(discoveredTestMessage)); + + WriteField(stream, DiscoveredTestMessageFieldsId.Uid, discoveredTestMessage.Uid); + WriteField(stream, DiscoveredTestMessageFieldsId.DisplayName, discoveredTestMessage.DisplayName); + } + + // NOTE: We are able to seek only if we are using a MemoryStream + // thus, the seek operation is fast as we are only changing the value of a property + WriteAtPosition(stream, (int)(stream.Position - before), before - sizeof(int)); + } + + private static ushort GetFieldCount(DiscoveredTestMessages discoveredTestMessages) => + (ushort)((discoveredTestMessages.ExecutionId is null ? 0 : 1) + + (discoveredTestMessages.DiscoveredMessages is null ? 0 : 1)); + + private static ushort GetFieldCount(DiscoveredTestMessage discoveredTestMessage) => + (ushort)((discoveredTestMessage.Uid is null ? 0 : 1) + + (discoveredTestMessage.DisplayName is null ? 0 : 1)); + } +} diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/FileArtifactInfoSerializer.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/FileArtifactInfoSerializer.cs deleted file mode 100644 index 744d108771ce..000000000000 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/FileArtifactInfoSerializer.cs +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -#nullable enable - -using System.Diagnostics; - -namespace Microsoft.DotNet.Tools.Test -{ - /* - |---FieldCount---| 2 bytes - - |---File FullPath Id---| (2 bytes) - |---File FullPath Size---| (4 bytes) - |---File FullPath Value---| (n bytes) - - |---File DisplayName Id---| (2 bytes) - |---File DisplayName Size---| (4 bytes) - |---File DisplayName Value---| (n bytes) - - |---File Description Id---| (2 bytes) - |---File Description Size---| (4 bytes) - |---File Description Value---| (n bytes) - - |---File TestUid Id---| (2 bytes) - |---File TestUid Size---| (4 bytes) - |---File TestUid Value---| (n bytes) - - |---File TestDisplayName Id---| (2 bytes) - |---File TestDisplayName Size---| (4 bytes) - |---File TestDisplayName Value---| (n bytes) - - |---File SessionUid Id---| (2 bytes) - |---File SessionUid Size---| (4 bytes) - |---File SessionUid Value---| (n bytes) - - |---File ExecutionId Id---| (2 bytes) - |---File ExecutionId Size---| (4 bytes) - |---File ExecutionId Value---| (n bytes) - */ - - internal sealed class FileArtifactInfoSerializer : BaseSerializer, INamedPipeSerializer - { - public int Id => FileArtifactInfoFieldsId.MessagesSerializerId; - - public object Deserialize(Stream stream) - { - string? fullPath = null; - string? displayName = null; - string? description = null; - string? testUid = null; - string? testDisplayName = null; - string? sessionUid = null; - string? executionId = null; - - ushort fieldCount = ReadShort(stream); - - for (int i = 0; i < fieldCount; i++) - { - int fieldId = ReadShort(stream); - int fieldSize = ReadInt(stream); - - switch (fieldId) - { - case FileArtifactInfoFieldsId.FullPath: - fullPath = ReadString(stream); - break; - - case FileArtifactInfoFieldsId.DisplayName: - displayName = ReadString(stream); - break; - - case FileArtifactInfoFieldsId.Description: - description = ReadString(stream); - break; - - case FileArtifactInfoFieldsId.TestUid: - testUid = ReadString(stream); - break; - - case FileArtifactInfoFieldsId.TestDisplayName: - testDisplayName = ReadString(stream); - break; - - case FileArtifactInfoFieldsId.SessionUid: - sessionUid = ReadString(stream); - break; - - case FileArtifactInfoFieldsId.ExecutionId: - executionId = ReadString(stream); - break; - - default: - // If we don't recognize the field id, skip the payload corresponding to that field - SetPosition(stream, stream.Position + fieldSize); - break; - } - } - - return new FileArtifactInfo(fullPath, displayName, description, testUid, testDisplayName, sessionUid, executionId); - } - - public void Serialize(object objectToSerialize, Stream stream) - { - Debug.Assert(stream.CanSeek, "We expect a seekable stream."); - - var fileArtifactInfo = (FileArtifactInfo)objectToSerialize; - - WriteShort(stream, GetFieldCount(fileArtifactInfo)); - - WriteField(stream, FileArtifactInfoFieldsId.FullPath, fileArtifactInfo.FullPath); - WriteField(stream, FileArtifactInfoFieldsId.DisplayName, fileArtifactInfo.DisplayName); - WriteField(stream, FileArtifactInfoFieldsId.Description, fileArtifactInfo.Description); - WriteField(stream, FileArtifactInfoFieldsId.TestUid, fileArtifactInfo.TestUid); - WriteField(stream, FileArtifactInfoFieldsId.TestDisplayName, fileArtifactInfo.TestDisplayName); - WriteField(stream, FileArtifactInfoFieldsId.SessionUid, fileArtifactInfo.SessionUid); - WriteField(stream, FileArtifactInfoFieldsId.ExecutionId, fileArtifactInfo.ExecutionId); - - } - - private static ushort GetFieldCount(FileArtifactInfo fileArtifactInfo) => - (ushort)((fileArtifactInfo.FullPath is null ? 0 : 1) + - (fileArtifactInfo.DisplayName is null ? 0 : 1) + - (fileArtifactInfo.Description is null ? 0 : 1) + - (fileArtifactInfo.TestUid is null ? 0 : 1) + - (fileArtifactInfo.TestDisplayName is null ? 0 : 1) + - (fileArtifactInfo.SessionUid is null ? 0 : 1) + - (fileArtifactInfo.ExecutionId is null ? 0 : 1)); - } -} diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/FileArtifactMessagesSerializer.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/FileArtifactMessagesSerializer.cs new file mode 100644 index 000000000000..9510343e623c --- /dev/null +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/FileArtifactMessagesSerializer.cs @@ -0,0 +1,197 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if NETCOREAPP +#nullable enable +#endif + +using System.Diagnostics; + +namespace Microsoft.DotNet.Tools.Test +{ + /* + |---FieldCount---| 2 bytes + + |---ExecutionId Id---| (2 bytes) + |---ExecutionId Size---| (4 bytes) + |---ExecutionId Value---| (n bytes) + + |---FileArtifactMessageList Id---| (2 bytes) + |---FileArtifactMessageList Size---| (4 bytes) + |---FileArtifactMessageList Value---| (n bytes) + |---FileArtifactMessageList Length---| (4 bytes) + + |---FileArtifactMessageList[0] FieldCount---| 2 bytes + + |---FileArtifactMessageList[0].FullPath Id---| (2 bytes) + |---FileArtifactMessageList[0].FullPath Size---| (4 bytes) + |---FileArtifactMessageList[0].FullPath Value---| (n bytes) + + |---FileArtifactMessageList[0].DisplayName Id---| (2 bytes) + |---FileArtifactMessageList[0].DisplayName Size---| (4 bytes) + |---FileArtifactMessageList[0].DisplayName Value---| (n bytes) + + |---FileArtifactMessageList[0].Description Id---| (2 bytes) + |---FileArtifactMessageList[0].Description Size---| (4 bytes) + |---FileArtifactMessageList[0].Description Value---| (n bytes) + + |---FileArtifactMessageList[0].TestUid Id---| (2 bytes) + |---FileArtifactMessageList[0].TestUid Size---| (4 bytes) + |---FileArtifactMessageList[0].TestUid Value---| (n bytes) + + |---FileArtifactMessageList[0].TestDisplayName Id---| (2 bytes) + |---FileArtifactMessageList[0].TestDisplayName Size---| (4 bytes) + |---FileArtifactMessageList[0].TestDisplayName Value---| (n bytes) + + |---FileArtifactMessageList[0].SessionUid Id---| (2 bytes) + |---FileArtifactMessageList[0].SessionUid Size---| (4 bytes) + |---FileArtifactMessageList[0].SessionUid Value---| (n bytes) + */ + + internal sealed class FileArtifactMessagesSerializer : BaseSerializer, INamedPipeSerializer + { + public int Id => FileArtifactMessagesFieldsId.MessagesSerializerId; + + public object Deserialize(Stream stream) + { + string? executionId = null; + List? fileArtifactMessages = null; + + ushort fieldCount = ReadShort(stream); + + for (int i = 0; i < fieldCount; i++) + { + int fieldId = ReadShort(stream); + int fieldSize = ReadInt(stream); + + switch (fieldId) + { + case FileArtifactMessagesFieldsId.ExecutionId: + executionId = ReadString(stream); + break; + + case FileArtifactMessagesFieldsId.FileArtifactMessageList: + fileArtifactMessages = ReadFileArtifactMessagesPayload(stream); + break; + + default: + // If we don't recognize the field id, skip the payload corresponding to that field + SetPosition(stream, stream.Position + fieldSize); + break; + } + } + + return new FileArtifactMessages(executionId, fileArtifactMessages is null ? [] : [.. fileArtifactMessages]); + } + + private static List ReadFileArtifactMessagesPayload(Stream stream) + { + List fileArtifactMessages = []; + + int length = ReadInt(stream); + for (int i = 0; i < length; i++) + { + string? fullPath = null, displayName = null, description = null, testUid = null, testDisplayName = null, sessionUid = null; + + int fieldCount = ReadShort(stream); + + for (int j = 0; j < fieldCount; j++) + { + int fieldId = ReadShort(stream); + int fieldSize = ReadInt(stream); + + switch (fieldId) + { + case FileArtifactMessageFieldsId.FullPath: + fullPath = ReadString(stream); + break; + + case FileArtifactMessageFieldsId.DisplayName: + displayName = ReadString(stream); + break; + + case FileArtifactMessageFieldsId.Description: + description = ReadString(stream); + break; + + case FileArtifactMessageFieldsId.TestUid: + testUid = ReadString(stream); + break; + + case FileArtifactMessageFieldsId.TestDisplayName: + testDisplayName = ReadString(stream); + break; + + case FileArtifactMessageFieldsId.SessionUid: + sessionUid = ReadString(stream); + break; + + default: + SetPosition(stream, stream.Position + fieldSize); + break; + } + } + + fileArtifactMessages.Add(new FileArtifactMessage(fullPath, displayName, description, testUid, testDisplayName, sessionUid)); + } + + return fileArtifactMessages; + } + + public void Serialize(object objectToSerialize, Stream stream) + { + Debug.Assert(stream.CanSeek, "We expect a seekable stream."); + + var fileArtifactMessages = (FileArtifactMessages)objectToSerialize; + + WriteShort(stream, GetFieldCount(fileArtifactMessages)); + + WriteField(stream, FileArtifactMessagesFieldsId.ExecutionId, fileArtifactMessages.ExecutionId); + WriteFileArtifactMessagesPayload(stream, fileArtifactMessages.FileArtifacts); + } + + private static void WriteFileArtifactMessagesPayload(Stream stream, FileArtifactMessage[]? fileArtifactMessageList) + { + if (fileArtifactMessageList is null || fileArtifactMessageList.Length == 0) + { + return; + } + + WriteShort(stream, FileArtifactMessagesFieldsId.FileArtifactMessageList); + + // We will reserve an int (4 bytes) + // so that we fill the size later, once we write the payload + WriteInt(stream, 0); + + long before = stream.Position; + WriteInt(stream, fileArtifactMessageList.Length); + foreach (FileArtifactMessage fileArtifactMessage in fileArtifactMessageList) + { + WriteShort(stream, GetFieldCount(fileArtifactMessage)); + + WriteField(stream, FileArtifactMessageFieldsId.FullPath, fileArtifactMessage.FullPath); + WriteField(stream, FileArtifactMessageFieldsId.DisplayName, fileArtifactMessage.DisplayName); + WriteField(stream, FileArtifactMessageFieldsId.Description, fileArtifactMessage.Description); + WriteField(stream, FileArtifactMessageFieldsId.TestUid, fileArtifactMessage.TestUid); + WriteField(stream, FileArtifactMessageFieldsId.TestDisplayName, fileArtifactMessage.TestDisplayName); + WriteField(stream, FileArtifactMessageFieldsId.SessionUid, fileArtifactMessage.SessionUid); + } + + // NOTE: We are able to seek only if we are using a MemoryStream + // thus, the seek operation is fast as we are only changing the value of a property + WriteAtPosition(stream, (int)(stream.Position - before), before - sizeof(int)); + } + + private static ushort GetFieldCount(FileArtifactMessages fileArtifactMessages) => + (ushort)((fileArtifactMessages.ExecutionId is null ? 0 : 1) + + (fileArtifactMessages.FileArtifacts is null ? 0 : 1)); + + private static ushort GetFieldCount(FileArtifactMessage fileArtifactMessage) => + (ushort)((fileArtifactMessage.FullPath is null ? 0 : 1) + + (fileArtifactMessage.DisplayName is null ? 0 : 1) + + (fileArtifactMessage.Description is null ? 0 : 1) + + (fileArtifactMessage.TestUid is null ? 0 : 1) + + (fileArtifactMessage.TestDisplayName is null ? 0 : 1) + + (fileArtifactMessage.SessionUid is null ? 0 : 1)); + } +} diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/HandshakeInfoSerializer.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/HandshakeMessageSerializer.cs similarity index 67% rename from src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/HandshakeInfoSerializer.cs rename to src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/HandshakeMessageSerializer.cs index 4fc86c3bcef4..ed9e30803826 100644 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/HandshakeInfoSerializer.cs +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/HandshakeMessageSerializer.cs @@ -5,9 +5,9 @@ namespace Microsoft.DotNet.Tools.Test { - internal sealed class HandshakeInfoSerializer : BaseSerializer, INamedPipeSerializer + internal sealed class HandshakeMessageSerializer : BaseSerializer, INamedPipeSerializer { - public int Id => HandshakeInfoFieldsId.MessagesSerializerId; + public int Id => HandshakeMessageFieldsId.MessagesSerializerId; public object Deserialize(Stream stream) { @@ -20,27 +20,26 @@ public object Deserialize(Stream stream) properties.Add(ReadByte(stream), ReadString(stream)); } - return new HandshakeInfo(properties); + return new HandshakeMessage(properties); } public void Serialize(object objectToSerialize, Stream stream) { Debug.Assert(stream.CanSeek, "We expect a seekable stream."); - var handshakeInfo = (HandshakeInfo)objectToSerialize; + var handshakeMessage = (HandshakeMessage)objectToSerialize; - if (handshakeInfo.Properties is null || handshakeInfo.Properties.Count == 0) + if (handshakeMessage.Properties is null || handshakeMessage.Properties.Count == 0) { return; } - WriteShort(stream, (ushort)handshakeInfo.Properties.Count); - foreach (KeyValuePair property in handshakeInfo.Properties) + WriteShort(stream, (ushort)handshakeMessage.Properties.Count); + foreach (KeyValuePair property in handshakeMessage.Properties) { WriteField(stream, property.Key); WriteField(stream, property.Value); } } } - } diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/RegisterSerializers.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/RegisterSerializers.cs index f41b6fcce0b3..7124e18aff83 100644 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/RegisterSerializers.cs +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/RegisterSerializers.cs @@ -11,12 +11,11 @@ namespace Microsoft.DotNet.Tools.Test; * TestHostProcessPIDRequestSerializer: 2 * CommandLineOptionMessagesSerializer: 3 * ModuleSerializer: 4 - * SuccessfulTestResultMessageSerializer: 5 - * FailedTestResultMessageSerializer: 6 - * FileArtifactInfoSerializer: 7 + * DiscoveredTestMessageSerializer: 5 + * TestResultMessageSerializer: 6 + * FileArtifactMessageSerializer: 7 * TestSessionEventSerializer: 8 - * HandshakeInfoSerializer: 9 - * DiscoveredTestMessageSerializer: 10 + * HandshakeMessageSerializer: 9 */ internal static class RegisterSerializers @@ -24,13 +23,12 @@ internal static class RegisterSerializers public static void RegisterAllSerializers(this NamedPipeBase namedPipeBase) { namedPipeBase.RegisterSerializer(new VoidResponseSerializer(), typeof(VoidResponse)); - namedPipeBase.RegisterSerializer(new ModuleSerializer(), typeof(Module)); namedPipeBase.RegisterSerializer(new CommandLineOptionMessagesSerializer(), typeof(CommandLineOptionMessages)); - namedPipeBase.RegisterSerializer(new SuccessfulTestResultMessageSerializer(), typeof(SuccessfulTestResultMessage)); - namedPipeBase.RegisterSerializer(new FailedTestResultMessageSerializer(), typeof(FailedTestResultMessage)); - namedPipeBase.RegisterSerializer(new FileArtifactInfoSerializer(), typeof(FileArtifactInfo)); + namedPipeBase.RegisterSerializer(new ModuleSerializer(), typeof(Module)); + namedPipeBase.RegisterSerializer(new DiscoveredTestMessagesSerializer(), typeof(DiscoveredTestMessages)); + namedPipeBase.RegisterSerializer(new TestResultMessagesSerializer(), typeof(TestResultMessages)); + namedPipeBase.RegisterSerializer(new FileArtifactMessagesSerializer(), typeof(FileArtifactMessages)); namedPipeBase.RegisterSerializer(new TestSessionEventSerializer(), typeof(TestSessionEvent)); - namedPipeBase.RegisterSerializer(new HandshakeInfoSerializer(), typeof(HandshakeInfo)); - namedPipeBase.RegisterSerializer(new DiscoveredTestMessageSerializer(), typeof(DiscoveredTestMessage)); + namedPipeBase.RegisterSerializer(new HandshakeMessageSerializer(), typeof(HandshakeMessage)); } } diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/TestResultMessageSerializer.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/TestResultMessageSerializer.cs deleted file mode 100644 index 9d5d7dfa84a8..000000000000 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/TestResultMessageSerializer.cs +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -#nullable enable - -using System.Diagnostics; - -namespace Microsoft.DotNet.Tools.Test -{ - /* - |---FieldCount---| 2 bytes - - |---Test Uid Id---| (2 bytes) - |---Test Uid Size---| (4 bytes) - |---Test Uid Value---| (n bytes) - - |---Test DisplayName Id---| (2 bytes) - |---Test DisplayName Size---| (4 bytes) - |---Test DisplayName Value---| (n bytes) - - |---Test State Id---| (2 bytes) - |---Test State Size---| (4 bytes) - |---Test State Value---| (n bytes) - - |---Test Reason Id---| (2 bytes) - |---Test Reason Size---| (4 bytes) - |---Test Reason Value---| (n bytes) - - |---Test SessionUid Id---| (2 bytes) - |---Test SessionUid Size---| (4 bytes) - |---Test SessionUid Value---| (n bytes) - - |---Test ExecutionId Id---| (2 bytes) - |---Test ExecutionId Size---| (4 bytes) - |---Test ExecutionId Value---| (n bytes) - */ - - internal sealed class SuccessfulTestResultMessageSerializer : BaseSerializer, INamedPipeSerializer - { - public int Id => SuccessfulTestResultMessageFieldsId.MessagesSerializerId; - - public object Deserialize(Stream stream) - { - string? uid = null; - string? displayName = null; - byte? state = null; - string? reason = null; - string? sessionUid = null; - string? executionId = null; - - ushort fieldCount = ReadShort(stream); - - for (int i = 0; i < fieldCount; i++) - { - int fieldId = ReadShort(stream); - int fieldSize = ReadInt(stream); - - switch (fieldId) - { - case SuccessfulTestResultMessageFieldsId.Uid: - uid = ReadString(stream); - break; - - case SuccessfulTestResultMessageFieldsId.DisplayName: - displayName = ReadString(stream); - break; - - case SuccessfulTestResultMessageFieldsId.State: - state = ReadByte(stream); - break; - - case SuccessfulTestResultMessageFieldsId.Reason: - reason = ReadString(stream); - break; - - case SuccessfulTestResultMessageFieldsId.SessionUid: - sessionUid = ReadString(stream); - break; - - case SuccessfulTestResultMessageFieldsId.ExecutionId: - executionId = ReadString(stream); - break; - - default: - // If we don't recognize the field id, skip the payload corresponding to that field - SetPosition(stream, stream.Position + fieldSize); - break; - } - } - - return new SuccessfulTestResultMessage(uid, displayName, state, reason, sessionUid, executionId); - } - - public void Serialize(object objectToSerialize, Stream stream) - { - Debug.Assert(stream.CanSeek, "We expect a seekable stream."); - - var testResultMessage = (SuccessfulTestResultMessage)objectToSerialize; - - WriteShort(stream, GetFieldCount(testResultMessage)); - - WriteField(stream, SuccessfulTestResultMessageFieldsId.Uid, testResultMessage.Uid); - WriteField(stream, SuccessfulTestResultMessageFieldsId.DisplayName, testResultMessage.DisplayName); - WriteField(stream, SuccessfulTestResultMessageFieldsId.State, testResultMessage.State); - WriteField(stream, SuccessfulTestResultMessageFieldsId.Reason, testResultMessage.Reason); - WriteField(stream, SuccessfulTestResultMessageFieldsId.SessionUid, testResultMessage.SessionUid); - WriteField(stream, SuccessfulTestResultMessageFieldsId.ExecutionId, testResultMessage.ExecutionId); - } - - private static ushort GetFieldCount(SuccessfulTestResultMessage testResultMessage) => - (ushort)((testResultMessage.Uid is null ? 0 : 1) + - (testResultMessage.DisplayName is null ? 0 : 1) + - (testResultMessage.State is null ? 0 : 1) + - (testResultMessage.Reason is null ? 0 : 1) + - (testResultMessage.SessionUid is null ? 0 : 1) + - (testResultMessage.ExecutionId is null ? 0 : 1)); - } - - /* - |---FieldCount---| 2 bytes - - |---Test Uid Id---| (2 bytes) - |---Test Uid Size---| (4 bytes) - |---Test Uid Value---| (n bytes) - - |---Test DisplayName Id---| (2 bytes) - |---Test DisplayName Size---| (4 bytes) - |---Test DisplayName Value---| (n bytes) - - |---Test State Id---| (2 bytes) - |---Test State Size---| (4 bytes) - |---Test State Value---| (n bytes) - - |---Test Reason Id---| (2 bytes) - |---Test Reason Size---| (4 bytes) - |---Test Reason Value---| (n bytes) - - |---Test ErrorMessage Id---| (2 bytes) - |---Test ErrorMessage Size---| (4 bytes) - |---Test ErrorMessage Value---| (n bytes) - - |---Test ErrorStackTrace Id---| (2 bytes) - |---Test ErrorStackTrace Size---| (4 bytes) - |---Test ErrorStackTrace Value---| (n bytes) - - |---Test SessionUid Id---| (2 bytes) - |---Test SessionUid Size---| (4 bytes) - |---Test SessionUid Value---| (n bytes) - - |---Test ExecutionId Id---| (2 bytes) - |---Test ExecutionId Size---| (4 bytes) - |---Test ExecutionId Value---| (n bytes) - */ - - internal sealed class FailedTestResultMessageSerializer : BaseSerializer, INamedPipeSerializer - { - public int Id => FailedTestResultMessageFieldsId.MessagesSerializerId; - - public object Deserialize(Stream stream) - { - string? uid = null; - string? displayName = null; - byte? state = null; - string? reason = null; - string? errorMessage = null; - string? errorStackTrace = null; - string? sessionUid = null; - string? executionId = null; - - ushort fieldCount = ReadShort(stream); - - for (int i = 0; i < fieldCount; i++) - { - int fieldId = ReadShort(stream); - int fieldSize = ReadInt(stream); - - switch (fieldId) - { - case FailedTestResultMessageFieldsId.Uid: - uid = ReadString(stream); - break; - - case FailedTestResultMessageFieldsId.DisplayName: - displayName = ReadString(stream); - break; - - case FailedTestResultMessageFieldsId.State: - state = ReadByte(stream); - break; - - case FailedTestResultMessageFieldsId.Reason: - reason = ReadString(stream); - break; - - case FailedTestResultMessageFieldsId.ErrorMessage: - errorMessage = ReadString(stream); - break; - - case FailedTestResultMessageFieldsId.ErrorStackTrace: - errorStackTrace = ReadString(stream); - break; - - case FailedTestResultMessageFieldsId.SessionUid: - sessionUid = ReadString(stream); - break; - - case FailedTestResultMessageFieldsId.ExecutionId: - executionId = ReadString(stream); - break; - - default: - // If we don't recognize the field id, skip the payload corresponding to that field - SetPosition(stream, stream.Position + fieldSize); - break; - } - } - - return new FailedTestResultMessage(uid, displayName, state, reason, errorMessage, errorStackTrace, sessionUid, executionId); - } - - public void Serialize(object objectToSerialize, Stream stream) - { - Debug.Assert(stream.CanSeek, "We expect a seekable stream."); - - var testResultMessage = (FailedTestResultMessage)objectToSerialize; - - WriteShort(stream, GetFieldCount(testResultMessage)); - - WriteField(stream, FailedTestResultMessageFieldsId.Uid, testResultMessage.Uid); - WriteField(stream, FailedTestResultMessageFieldsId.DisplayName, testResultMessage.DisplayName); - WriteField(stream, FailedTestResultMessageFieldsId.State, testResultMessage.State); - WriteField(stream, FailedTestResultMessageFieldsId.Reason, testResultMessage.Reason); - WriteField(stream, FailedTestResultMessageFieldsId.ErrorMessage, testResultMessage.ErrorMessage); - WriteField(stream, FailedTestResultMessageFieldsId.ErrorStackTrace, testResultMessage.ErrorStackTrace); - WriteField(stream, FailedTestResultMessageFieldsId.SessionUid, testResultMessage.SessionUid); - WriteField(stream, FailedTestResultMessageFieldsId.ExecutionId, testResultMessage.ExecutionId); - } - - private static ushort GetFieldCount(FailedTestResultMessage testResultMessage) => - (ushort)((testResultMessage.Uid is null ? 0 : 1) + - (testResultMessage.DisplayName is null ? 0 : 1) + - (testResultMessage.State is null ? 0 : 1) + - (testResultMessage.Reason is null ? 0 : 1) + - (testResultMessage.ErrorMessage is null ? 0 : 1) + - (testResultMessage.ErrorStackTrace is null ? 0 : 1) + - (testResultMessage.SessionUid is null ? 0 : 1) + - (testResultMessage.ExecutionId is null ? 0 : 1)); - } -} diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/TestResultMessagesSerializer.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/TestResultMessagesSerializer.cs new file mode 100644 index 000000000000..799e0d8fdb3d --- /dev/null +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/TestResultMessagesSerializer.cs @@ -0,0 +1,334 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if NETCOREAPP +#nullable enable +#endif + +using System.Diagnostics; + +namespace Microsoft.DotNet.Tools.Test +{ + /* + |---FieldCount---| 2 bytes + + |---ExecutionId Id---| (2 bytes) + |---ExecutionId Size---| (4 bytes) + |---ExecutionId Value---| (n bytes) + + |---SuccessfulTestMessageList Id---| (2 bytes) + |---SuccessfulTestMessageList Size---| (4 bytes) + |---SuccessfulTestMessageList Value---| (n bytes) + |---SuccessfulTestMessageList Length---| (4 bytes) + + |---SuccessfulTestMessageList[0] FieldCount---| 2 bytes + + |---SuccessfulTestMessageList[0].Uid Id---| (2 bytes) + |---SuccessfulTestMessageList[0].Uid Size---| (4 bytes) + |---SuccessfulTestMessageList[0].Uid Value---| (n bytes) + + |---SuccessfulTestMessageList[0].DisplayName Id---| (2 bytes) + |---SuccessfulTestMessageList[0].DisplayName Size---| (4 bytes) + |---SuccessfulTestMessageList[0].DisplayName Value---| (n bytes) + + |---SuccessfulTestMessageList[0].State Id---| (2 bytes) + |---SuccessfulTestMessageList[0].State Size---| (4 bytes) + |---SuccessfulTestMessageList[0].State Value---| (n bytes) + + |---SuccessfulTestMessageList[0].Reason Id---| (2 bytes) + |---SuccessfulTestMessageList[0].Reason Size---| (4 bytes) + |---SuccessfulTestMessageList[0].Reason Value---| (n bytes) + + |---SuccessfulTestMessageList[0].SessionUid Id---| (2 bytes) + |---SuccessfulTestMessageList[0].SessionUid Size---| (4 bytes) + |---SuccessfulTestMessageList[0].SessionUid Value---| (n bytes) + + |---FailedTestMessageList Id---| (2 bytes) + |---FailedTestMessageList Size---| (4 bytes) + |---FailedTestMessageList Value---| (n bytes) + |---FailedTestMessageList Length---| (4 bytes) + + |---FailedTestMessageList[0] FieldCount---| 2 bytes + + |---FailedTestMessageList[0].Uid Id---| (2 bytes) + |---FailedTestMessageList[0].Uid Size---| (4 bytes) + |---FailedTestMessageList[0].Uid Value---| (n bytes) + + |---FailedTestMessageList[0].DisplayName Id---| (2 bytes) + |---FailedTestMessageList[0].DisplayName Size---| (4 bytes) + |---FailedTestMessageList[0].DisplayName Value---| (n bytes) + + |---FailedTestMessageList[0].State Id---| (2 bytes) + |---FailedTestMessageList[0].State Size---| (4 bytes) + |---FailedTestMessageList[0].State Value---| (n bytes) + + |---FailedTestMessageList[0].Reason Id---| (2 bytes) + |---FailedTestMessageList[0].Reason Size---| (4 bytes) + |---FailedTestMessageList[0].Reason Value---| (n bytes) + + |---FailedTestMessageList[0].ErrorMessage Id---| (2 bytes) + |---FailedTestMessageList[0].ErrorMessage Size---| (4 bytes) + |---FailedTestMessageList[0].ErrorMessage Value---| (n bytes) + + |---FailedTestMessageList[0].ErrorStackTrace Id---| (2 bytes) + |---FailedTestMessageList[0].ErrorStackTrace Size---| (4 bytes) + |---FailedTestMessageList[0].ErrorStackTrace Value---| (n bytes) + + |---FailedTestMessageList[0].SessionUid Id---| (2 bytes) + |---FailedTestMessageList[0].SessionUid Size---| (4 bytes) + |---FailedTestMessageList[0].SessionUid Value---| (n bytes) + */ + + internal sealed class TestResultMessagesSerializer : BaseSerializer, INamedPipeSerializer + { + public int Id => TestResultMessagesFieldsId.MessagesSerializerId; + + public object Deserialize(Stream stream) + { + string? executionId = null; + List? successfulTestResultMessages = null; + List? failedTestResultMessages = null; + + ushort fieldCount = ReadShort(stream); + + for (int i = 0; i < fieldCount; i++) + { + int fieldId = ReadShort(stream); + int fieldSize = ReadInt(stream); + + switch (fieldId) + { + case TestResultMessagesFieldsId.ExecutionId: + executionId = ReadString(stream); + break; + + case TestResultMessagesFieldsId.SuccessfulTestMessageList: + successfulTestResultMessages = ReadSuccessfulTestMessagesPayload(stream); + break; + + case TestResultMessagesFieldsId.FailedTestMessageList: + failedTestResultMessages = ReadFailedTestMessagesPayload(stream); + break; + + default: + // If we don't recognize the field id, skip the payload corresponding to that field + SetPosition(stream, stream.Position + fieldSize); + break; + } + } + + return new TestResultMessages( + executionId, + successfulTestResultMessages is null ? [] : [.. successfulTestResultMessages], + failedTestResultMessages is null ? [] : [.. failedTestResultMessages]); + } + + private static List ReadSuccessfulTestMessagesPayload(Stream stream) + { + List successfulTestResultMessages = []; + + int length = ReadInt(stream); + for (int i = 0; i < length; i++) + { + string? uid = null, displayName = null, reason = null, sessionUid = null; + byte? state = null; + + int fieldCount = ReadShort(stream); + + for (int j = 0; j < fieldCount; j++) + { + int fieldId = ReadShort(stream); + int fieldSize = ReadInt(stream); + + switch (fieldId) + { + case SuccessfulTestResultMessageFieldsId.Uid: + uid = ReadString(stream); + break; + + case SuccessfulTestResultMessageFieldsId.DisplayName: + displayName = ReadString(stream); + break; + + case SuccessfulTestResultMessageFieldsId.State: + state = ReadByte(stream); + break; + + case SuccessfulTestResultMessageFieldsId.Reason: + reason = ReadString(stream); + break; + + case SuccessfulTestResultMessageFieldsId.SessionUid: + sessionUid = ReadString(stream); + break; + + default: + SetPosition(stream, stream.Position + fieldSize); + break; + } + } + + successfulTestResultMessages.Add(new SuccessfulTestResultMessage(uid, displayName, state, reason, sessionUid)); + } + + return successfulTestResultMessages; + } + + private static List ReadFailedTestMessagesPayload(Stream stream) + { + List failedTestResultMessages = []; + + int length = ReadInt(stream); + for (int i = 0; i < length; i++) + { + string? uid = null, displayName = null, reason = null, sessionUid = null, errorMessage = null, errorStackTrace = null; + byte? state = null; + + int fieldCount = ReadShort(stream); + + for (int j = 0; j < fieldCount; j++) + { + int fieldId = ReadShort(stream); + int fieldSize = ReadInt(stream); + + switch (fieldId) + { + case FailedTestResultMessageFieldsId.Uid: + uid = ReadString(stream); + break; + + case FailedTestResultMessageFieldsId.DisplayName: + displayName = ReadString(stream); + break; + + case FailedTestResultMessageFieldsId.State: + state = ReadByte(stream); + break; + + case FailedTestResultMessageFieldsId.Reason: + reason = ReadString(stream); + break; + + case FailedTestResultMessageFieldsId.ErrorMessage: + errorMessage = ReadString(stream); + break; + + case FailedTestResultMessageFieldsId.ErrorStackTrace: + errorStackTrace = ReadString(stream); + break; + + case FailedTestResultMessageFieldsId.SessionUid: + sessionUid = ReadString(stream); + break; + + default: + SetPosition(stream, stream.Position + fieldSize); + break; + } + } + + failedTestResultMessages.Add(new FailedTestResultMessage(uid, displayName, state, reason, errorMessage, errorStackTrace, sessionUid)); + } + + return failedTestResultMessages; + } + + public void Serialize(object objectToSerialize, Stream stream) + { + Debug.Assert(stream.CanSeek, "We expect a seekable stream."); + + var testResultMessages = (TestResultMessages)objectToSerialize; + + WriteShort(stream, GetFieldCount(testResultMessages)); + + WriteField(stream, TestResultMessagesFieldsId.ExecutionId, testResultMessages.ExecutionId); + WriteSuccessfulTestMessagesPayload(stream, testResultMessages.SuccessfulTestMessages); + WriteFailedTestMessagesPayload(stream, testResultMessages.FailedTestMessages); + } + + private static void WriteSuccessfulTestMessagesPayload(Stream stream, SuccessfulTestResultMessage[]? successfulTestResultMessages) + { + if (successfulTestResultMessages is null || successfulTestResultMessages.Length == 0) + { + return; + } + + WriteShort(stream, TestResultMessagesFieldsId.SuccessfulTestMessageList); + + // We will reserve an int (4 bytes) + // so that we fill the size later, once we write the payload + WriteInt(stream, 0); + + long before = stream.Position; + WriteInt(stream, successfulTestResultMessages.Length); + foreach (SuccessfulTestResultMessage successfulTestResultMessage in successfulTestResultMessages) + { + WriteShort(stream, GetFieldCount(successfulTestResultMessage)); + + WriteField(stream, SuccessfulTestResultMessageFieldsId.Uid, successfulTestResultMessage.Uid); + WriteField(stream, SuccessfulTestResultMessageFieldsId.DisplayName, successfulTestResultMessage.DisplayName); + WriteField(stream, SuccessfulTestResultMessageFieldsId.State, successfulTestResultMessage.State); + WriteField(stream, SuccessfulTestResultMessageFieldsId.Reason, successfulTestResultMessage.Reason); + WriteField(stream, SuccessfulTestResultMessageFieldsId.SessionUid, successfulTestResultMessage.SessionUid); + } + + // NOTE: We are able to seek only if we are using a MemoryStream + // thus, the seek operation is fast as we are only changing the value of a property + WriteAtPosition(stream, (int)(stream.Position - before), before - sizeof(int)); + } + + private static void WriteFailedTestMessagesPayload(Stream stream, FailedTestResultMessage[]? failedTestResultMessages) + { + if (failedTestResultMessages is null || failedTestResultMessages.Length == 0) + { + return; + } + + WriteShort(stream, TestResultMessagesFieldsId.SuccessfulTestMessageList); + + // We will reserve an int (4 bytes) + // so that we fill the size later, once we write the payload + WriteInt(stream, 0); + + long before = stream.Position; + WriteInt(stream, failedTestResultMessages.Length); + foreach (FailedTestResultMessage successfulTestResultMessage in failedTestResultMessages) + { + WriteShort(stream, GetFieldCount(successfulTestResultMessage)); + + WriteField(stream, FailedTestResultMessageFieldsId.Uid, successfulTestResultMessage.Uid); + WriteField(stream, FailedTestResultMessageFieldsId.DisplayName, successfulTestResultMessage.DisplayName); + WriteField(stream, FailedTestResultMessageFieldsId.State, successfulTestResultMessage.State); + WriteField(stream, FailedTestResultMessageFieldsId.Reason, successfulTestResultMessage.Reason); + WriteField(stream, FailedTestResultMessageFieldsId.ErrorMessage, successfulTestResultMessage.ErrorMessage); + WriteField(stream, FailedTestResultMessageFieldsId.ErrorStackTrace, successfulTestResultMessage.ErrorStackTrace); + WriteField(stream, FailedTestResultMessageFieldsId.SessionUid, successfulTestResultMessage.SessionUid); + } + + // NOTE: We are able to seek only if we are using a MemoryStream + // thus, the seek operation is fast as we are only changing the value of a property + WriteAtPosition(stream, (int)(stream.Position - before), before - sizeof(int)); + } + + private static ushort GetFieldCount(TestResultMessages testResultMessages) => + (ushort)((testResultMessages.ExecutionId is null ? 0 : 1) + + (testResultMessages.SuccessfulTestMessages is null ? 0 : 1) + + (testResultMessages.FailedTestMessages is null ? 0 : 1)); + + private static ushort GetFieldCount(SuccessfulTestResultMessage successfulTestResultMessage) => + (ushort)((successfulTestResultMessage.Uid is null ? 0 : 1) + + (successfulTestResultMessage.DisplayName is null ? 0 : 1) + + (successfulTestResultMessage.State is null ? 0 : 1) + + (successfulTestResultMessage.Reason is null ? 0 : 1) + + (successfulTestResultMessage.SessionUid is null ? 0 : 1)); + + private static ushort GetFieldCount(FailedTestResultMessage failedTestResultMessage) => + (ushort)((failedTestResultMessage.Uid is null ? 0 : 1) + + (failedTestResultMessage.DisplayName is null ? 0 : 1) + + (failedTestResultMessage.State is null ? 0 : 1) + + (failedTestResultMessage.Reason is null ? 0 : 1) + + (failedTestResultMessage.ErrorMessage is null ? 0 : 1) + + (failedTestResultMessage.ErrorStackTrace is null ? 0 : 1) + + (failedTestResultMessage.SessionUid is null ? 0 : 1)); + } +} diff --git a/src/Cli/dotnet/commands/dotnet-test/MSBuildConnectionHandler.cs b/src/Cli/dotnet/commands/dotnet-test/MSBuildConnectionHandler.cs index d3b02b9795e0..65832f8298c0 100644 --- a/src/Cli/dotnet/commands/dotnet-test/MSBuildConnectionHandler.cs +++ b/src/Cli/dotnet/commands/dotnet-test/MSBuildConnectionHandler.cs @@ -65,7 +65,6 @@ private Task OnRequest(IRequest request) var testApp = new TestApplication(module, _args); // Write the test application to the channel _actionQueue.Enqueue(testApp); - testApp.OnCreated(); } catch (Exception ex) { diff --git a/src/Cli/dotnet/commands/dotnet-test/Models.cs b/src/Cli/dotnet/commands/dotnet-test/Models.cs new file mode 100644 index 000000000000..44a254ffb4d8 --- /dev/null +++ b/src/Cli/dotnet/commands/dotnet-test/Models.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable enable + +namespace Microsoft.DotNet.Cli +{ + internal sealed record Handshake(Dictionary? Properties); + + internal sealed record CommandLineOption(string? Name, string? Description, bool? IsHidden, bool? IsBuiltIn); + + internal sealed record DiscoveredTest(string? Uid, string? DisplayName); + + internal sealed record SuccessfulTestResult(string? Uid, string? DisplayName, byte? State, string? Reason, string? SessionUid); + + internal sealed record FailedTestResult(string? Uid, string? DisplayName, byte? State, string? Reason, string? ErrorMessage, string? ErrorStackTrace, string? SessionUid); + + internal sealed record FileArtifact(string? FullPath, string? DisplayName, string? Description, string? TestUid, string? TestDisplayName, string? SessionUid); + + internal sealed record TestSession(byte? SessionType, string? SessionUid, string? ExecutionId); +} diff --git a/src/Cli/dotnet/commands/dotnet-test/TestApplication.cs b/src/Cli/dotnet/commands/dotnet-test/TestApplication.cs index 1c36d08d38b8..bfb788351003 100644 --- a/src/Cli/dotnet/commands/dotnet-test/TestApplication.cs +++ b/src/Cli/dotnet/commands/dotnet-test/TestApplication.cs @@ -22,16 +22,15 @@ internal sealed class TestApplication : IDisposable private Task _namedPipeConnectionLoop; private ConcurrentDictionary _executionIds = []; - public event EventHandler HandshakeInfoReceived; + public event EventHandler HandshakeReceived; public event EventHandler HelpRequested; - public event EventHandler DiscoveredTestReceived; - public event EventHandler SuccessfulTestResultReceived; - public event EventHandler FailedTestResultReceived; - public event EventHandler FileArtifactInfoReceived; + public event EventHandler DiscoveredTestsReceived; + public event EventHandler TestResultsReceived; + public event EventHandler FileArtifactsReceived; public event EventHandler SessionEventReceived; public event EventHandler ErrorReceived; public event EventHandler TestProcessExited; - public event EventHandler Created; + public event EventHandler Run; public event EventHandler ExecutionIdReceived; public Module Module => _module; @@ -49,6 +48,8 @@ public void AddExecutionId(string executionId) public async Task RunAsync(bool isFilterMode, bool enableHelp, BuiltInOptions builtInOptions) { + Run?.Invoke(this, EventArgs.Empty); + if (!ModulePathExists()) { return 1; @@ -101,12 +102,12 @@ private Task OnRequest(IRequest request) { switch (request) { - case HandshakeInfo handshakeInfo: - if (handshakeInfo.Properties.TryGetValue(HandshakeInfoPropertyNames.ModulePath, out string value)) + case HandshakeMessage handshakeMessage: + if (handshakeMessage.Properties.TryGetValue(HandshakeMessagePropertyNames.ModulePath, out string value)) { - OnHandshakeInfo(handshakeInfo); + OnHandshakeMessage(handshakeMessage); - return Task.FromResult((IResponse)CreateHandshakeInfo(GetSupportedProtocolVersion(handshakeInfo))); + return Task.FromResult((IResponse)CreateHandshakeMessage(GetSupportedProtocolVersion(handshakeMessage))); } break; @@ -114,20 +115,16 @@ private Task OnRequest(IRequest request) OnCommandLineOptionMessages(commandLineOptionMessages); break; - case DiscoveredTestMessage discoveredTestMessage: - OnDiscoveredTestMessage(discoveredTestMessage); - break; - - case SuccessfulTestResultMessage successfulTestResultMessage: - OnSuccessfulTestResultMessage(successfulTestResultMessage); + case DiscoveredTestMessages discoveredTestMessages: + OnDiscoveredTestMessages(discoveredTestMessages); break; - case FailedTestResultMessage failedTestResultMessage: - OnFailedTestResultMessage(failedTestResultMessage); + case TestResultMessages testResultMessages: + OnTestResultMessages(testResultMessages); break; - case FileArtifactInfo fileArtifactInfo: - OnFileArtifactInfo(fileArtifactInfo); + case FileArtifactMessages fileArtifactMessages: + OnFileArtifactMessages(fileArtifactMessages); break; case TestSessionEvent sessionEvent: @@ -160,9 +157,9 @@ private Task OnRequest(IRequest request) return Task.FromResult((IResponse)VoidResponse.CachedInstance); } - private static string GetSupportedProtocolVersion(HandshakeInfo handshakeInfo) + private static string GetSupportedProtocolVersion(HandshakeMessage handshakeMessage) { - handshakeInfo.Properties.TryGetValue(HandshakeInfoPropertyNames.SupportedProtocolVersions, out string protocolVersions); + handshakeMessage.Properties.TryGetValue(HandshakeMessagePropertyNames.SupportedProtocolVersions, out string protocolVersions); string version = string.Empty; if (protocolVersions is not null && protocolVersions.Split(";").Contains(ProtocolConstants.Version)) @@ -173,14 +170,14 @@ private static string GetSupportedProtocolVersion(HandshakeInfo handshakeInfo) return version; } - private static HandshakeInfo CreateHandshakeInfo(string version) => + private static HandshakeMessage CreateHandshakeMessage(string version) => new(new Dictionary { - { HandshakeInfoPropertyNames.PID, Process.GetCurrentProcess().Id.ToString() }, - { HandshakeInfoPropertyNames.Architecture, RuntimeInformation.OSArchitecture.ToString() }, - { HandshakeInfoPropertyNames.Framework, RuntimeInformation.FrameworkDescription }, - { HandshakeInfoPropertyNames.OS, RuntimeInformation.OSDescription }, - { HandshakeInfoPropertyNames.SupportedProtocolVersions, version } + { HandshakeMessagePropertyNames.PID, Process.GetCurrentProcess().Id.ToString() }, + { HandshakeMessagePropertyNames.Architecture, RuntimeInformation.ProcessArchitecture.ToString() }, + { HandshakeMessagePropertyNames.Framework, RuntimeInformation.FrameworkDescription }, + { HandshakeMessagePropertyNames.OS, RuntimeInformation.OSDescription }, + { HandshakeMessagePropertyNames.SupportedProtocolVersions, version } }); private async Task StartProcess(ProcessStartInfo processStartInfo) @@ -305,49 +302,48 @@ private string BuildHelpArgs(bool isDll) return builder.ToString(); } - public void OnHandshakeInfo(HandshakeInfo handshakeInfo) + public void OnHandshakeMessage(HandshakeMessage handshakeMessage) { - if (handshakeInfo.Properties.TryGetValue(HandshakeInfoPropertyNames.ExecutionId, out string executionId)) + if (handshakeMessage.Properties.TryGetValue(HandshakeMessagePropertyNames.ExecutionId, out string executionId)) { AddExecutionId(executionId); ExecutionIdReceived?.Invoke(this, new ExecutionEventArgs { ModulePath = _module.DLLPath, ExecutionId = executionId }); } - HandshakeInfoReceived?.Invoke(this, new HandshakeInfoArgs { handshakeInfo = handshakeInfo }); + HandshakeReceived?.Invoke(this, new HandshakeArgs { Handshake = new Handshake(handshakeMessage.Properties) }); } public void OnCommandLineOptionMessages(CommandLineOptionMessages commandLineOptionMessages) { - HelpRequested?.Invoke(this, new HelpEventArgs { CommandLineOptionMessages = commandLineOptionMessages }); + HelpRequested?.Invoke(this, new HelpEventArgs { CommandLineOptions = commandLineOptionMessages.CommandLineOptionMessageList.Select(message => new CommandLineOption(message.Name, message.Description, message.IsHidden, message.IsBuiltIn)).ToArray() }); } - internal void OnDiscoveredTestMessage(DiscoveredTestMessage discoveredTestMessage) + internal void OnDiscoveredTestMessages(DiscoveredTestMessages discoveredTestMessages) { - DiscoveredTestReceived?.Invoke(this, new DiscoveredTestEventArgs { DiscoveredTestMessage = discoveredTestMessage }); - } - - internal void OnSuccessfulTestResultMessage(SuccessfulTestResultMessage successfulTestResultMessage) - { - SuccessfulTestResultReceived?.Invoke(this, new SuccessfulTestResultEventArgs { SuccessfulTestResultMessage = successfulTestResultMessage }); + DiscoveredTestsReceived?.Invoke(this, new DiscoveredTestEventArgs + { + ExecutionId = discoveredTestMessages.ExecutionId, + DiscoveredTests = discoveredTestMessages.DiscoveredMessages.Select(message => new DiscoveredTest(message.Uid, message.DisplayName)).ToArray() + }); } - internal void OnFailedTestResultMessage(FailedTestResultMessage failedTestResultMessage) + internal void OnTestResultMessages(TestResultMessages testResultMessage) { - FailedTestResultReceived?.Invoke(this, new FailedTestResultEventArgs { FailedTestResultMessage = failedTestResultMessage }); + TestResultsReceived?.Invoke(this, new TestResultEventArgs + { + ExecutionId = testResultMessage.ExecutionId, + SuccessfulTestResults = testResultMessage.SuccessfulTestMessages.Select(message => new SuccessfulTestResult(message.Uid, message.DisplayName, message.State, message.Reason, message.SessionUid)).ToArray(), + FailedTestResults = testResultMessage.FailedTestMessages.Select(message => new FailedTestResult(message.Uid, message.DisplayName, message.State, message.Reason, message.ErrorMessage, message.ErrorStackTrace, message.SessionUid)).ToArray() + }); } - internal void OnFileArtifactInfo(FileArtifactInfo fileArtifactInfo) + internal void OnFileArtifactMessages(FileArtifactMessages fileArtifactMessages) { - FileArtifactInfoReceived?.Invoke(this, new FileArtifactInfoEventArgs { FileArtifactInfo = fileArtifactInfo }); + FileArtifactsReceived?.Invoke(this, new FileArtifactEventArgs { FileArtifacts = fileArtifactMessages.FileArtifacts.Select(message => new FileArtifact(message.FullPath, message.DisplayName, message.Description, message.TestUid, message.TestDisplayName, message.SessionUid)).ToArray() }); } internal void OnSessionEvent(TestSessionEvent sessionEvent) { - SessionEventReceived?.Invoke(this, new SessionEventArgs { SessionEvent = sessionEvent }); - } - - internal void OnCreated() - { - Created?.Invoke(this, EventArgs.Empty); + SessionEventReceived?.Invoke(this, new SessionEventArgs { SessionEvent = new TestSession(sessionEvent.SessionType, sessionEvent.SessionUid, sessionEvent.ExecutionId) }); } public override string ToString() diff --git a/src/Cli/dotnet/commands/dotnet-test/TestModulesFilterHandler.cs b/src/Cli/dotnet/commands/dotnet-test/TestModulesFilterHandler.cs index 897bb8c26691..83bf622caf39 100644 --- a/src/Cli/dotnet/commands/dotnet-test/TestModulesFilterHandler.cs +++ b/src/Cli/dotnet/commands/dotnet-test/TestModulesFilterHandler.cs @@ -53,7 +53,6 @@ public bool RunWithTestModulesFilter(ParseResult parseResult) var testApp = new TestApplication(new Module(testModule, null, null), _args); // Write the test application to the channel _actionQueue.Enqueue(testApp); - testApp.OnCreated(); } return true; diff --git a/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.Help.cs b/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.Help.cs index feeee09b0627..6499eb074933 100644 --- a/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.Help.cs +++ b/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.Help.cs @@ -4,13 +4,12 @@ using System.Buffers; using System.Collections.Concurrent; using System.CommandLine.Help; -using Microsoft.DotNet.Tools.Test; namespace Microsoft.DotNet.Cli { internal partial class TestingPlatformCommand { - private readonly ConcurrentDictionary _commandLineOptionNameToModuleNames = []; + private readonly ConcurrentDictionary _commandLineOptionNameToModuleNames = []; private readonly ConcurrentDictionary> _moduleNamesToCommandLineOptions = []; public IEnumerable> CustomHelpLayout() @@ -26,7 +25,7 @@ public IEnumerable> CustomHelpLayout() return; } - Dictionary> allOptions = GetAllOptions(); + Dictionary> allOptions = GetAllOptions(); WriteOptionsToConsole(allOptions); Console.ForegroundColor = ConsoleColor.Yellow; @@ -41,28 +40,28 @@ public IEnumerable> CustomHelpLayout() private void OnHelpRequested(object sender, HelpEventArgs args) { - CommandLineOptionMessages commandLineOptionMessages = args.CommandLineOptionMessages; - string moduleName = commandLineOptionMessages.ModulePath; + CommandLineOption[] commandLineOptionMessages = args.CommandLineOptions; + string moduleName = args.ModulePath; List builtInOptions = []; List nonBuiltInOptions = []; - foreach (CommandLineOptionMessage commandLineOptionMessage in commandLineOptionMessages.CommandLineOptionMessageList) + foreach (CommandLineOption commandLineOption in commandLineOptionMessages) { - if (commandLineOptionMessage.IsHidden.HasValue && commandLineOptionMessage.IsHidden.Value) continue; + if (commandLineOption.IsHidden.HasValue && commandLineOption.IsHidden.Value) continue; - if (commandLineOptionMessage.IsBuiltIn.HasValue && commandLineOptionMessage.IsBuiltIn.Value) + if (commandLineOption.IsBuiltIn.HasValue && commandLineOption.IsBuiltIn.Value) { - builtInOptions.Add(commandLineOptionMessage.Name); + builtInOptions.Add(commandLineOption.Name); } else { - nonBuiltInOptions.Add(commandLineOptionMessage.Name); + nonBuiltInOptions.Add(commandLineOption.Name); } _commandLineOptionNameToModuleNames.AddOrUpdate( - commandLineOptionMessage.Name, - commandLineOptionMessage, + commandLineOption.Name, + commandLineOption, (optionName, value) => (value)); } @@ -75,13 +74,13 @@ private void OnHelpRequested(object sender, HelpEventArgs args) (isBuiltIn, value) => [.. value, (moduleName, nonBuiltInOptions.ToArray())]); } - private Dictionary> GetAllOptions() + private Dictionary> GetAllOptions() { - Dictionary> builtInToOptions = []; + Dictionary> builtInToOptions = []; - foreach (KeyValuePair option in _commandLineOptionNameToModuleNames) + foreach (KeyValuePair option in _commandLineOptionNameToModuleNames) { - if (!builtInToOptions.TryGetValue(option.Value.IsBuiltIn.Value, out List value)) + if (!builtInToOptions.TryGetValue(option.Value.IsBuiltIn.Value, out List value)) { builtInToOptions.Add(option.Value.IsBuiltIn.Value, [option.Value]); } @@ -93,10 +92,10 @@ private Dictionary> GetAllOptions() return builtInToOptions; } - private Dictionary> GetModulesToMissingOptions(Dictionary> options) + private Dictionary> GetModulesToMissingOptions(Dictionary> options) { - IEnumerable builtInOptions = options.TryGetValue(true, out List builtIn) ? builtIn.Select(option => option.Name) : []; - IEnumerable nonBuiltInOptions = options.TryGetValue(false, out List nonBuiltIn) ? nonBuiltIn.Select(option => option.Name) : []; + IEnumerable builtInOptions = options.TryGetValue(true, out List builtIn) ? builtIn.Select(option => option.Name) : []; + IEnumerable nonBuiltInOptions = options.TryGetValue(false, out List nonBuiltIn) ? nonBuiltIn.Select(option => option.Name) : []; Dictionary> modulesWithMissingOptions = []; @@ -123,16 +122,16 @@ private Dictionary> GetAllOptions() return modulesWithMissingOptions; } - private void WriteOptionsToConsole(Dictionary> options) + private void WriteOptionsToConsole(Dictionary> options) { int maxOptionNameLength = _commandLineOptionNameToModuleNames.Keys.ToArray().Max(option => option.Length); - foreach (KeyValuePair> optionGroup in options) + foreach (KeyValuePair> optionGroup in options) { Console.WriteLine(); Console.WriteLine(optionGroup.Key ? "Options:" : "Extension options:"); - foreach (CommandLineOptionMessage option in optionGroup.Value) + foreach (CommandLineOption option in optionGroup.Value) { Console.WriteLine($"{new string(' ', 2)}--{option.Name}{new string(' ', maxOptionNameLength - option.Name.Length)} {option.Description}"); } diff --git a/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.cs b/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.cs index 04a96792c72a..25ec56f18bfc 100644 --- a/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.cs @@ -32,6 +32,12 @@ public int Run(ParseResult parseResult) degreeOfParallelism = Environment.ProcessorCount; bool filterModeEnabled = parseResult.HasOption(TestingPlatformOptions.TestModulesFilterOption); + + if (filterModeEnabled && parseResult.HasOption(TestingPlatformOptions.ArchitectureOption)) + { + VSTestTrace.SafeWriteTrace(() => $"The --arch option is not supported yet."); + } + BuiltInOptions builtInOptions = new( parseResult.HasOption(TestingPlatformOptions.NoRestoreOption), parseResult.HasOption(TestingPlatformOptions.NoBuildOption), @@ -45,7 +51,7 @@ public int Run(ParseResult parseResult) testApp.HelpRequested += OnHelpRequested; testApp.ErrorReceived += OnErrorReceived; testApp.TestProcessExited += OnTestProcessExited; - testApp.Created += OnTestApplicationCreated; + testApp.Run += OnTestApplicationRun; testApp.ExecutionIdReceived += OnExecutionIdReceived; return await testApp.RunAsync(filterModeEnabled, enableHelp: true, builtInOptions); @@ -55,15 +61,14 @@ public int Run(ParseResult parseResult) { _actionQueue = new(degreeOfParallelism, async (TestApplication testApp) => { - testApp.HandshakeInfoReceived += OnHandshakeInfoReceived; - testApp.DiscoveredTestReceived += OnDiscoveredTestReceived; - testApp.SuccessfulTestResultReceived += OnTestResultReceived; - testApp.FailedTestResultReceived += OnTestResultReceived; - testApp.FileArtifactInfoReceived += OnFileArtifactInfoReceived; + testApp.HandshakeReceived += OnHandshakeReceived; + testApp.DiscoveredTestsReceived += OnDiscoveredTestsReceived; + testApp.TestResultsReceived += OnTestResultsReceived; + testApp.FileArtifactsReceived += OnFileArtifactsReceived; testApp.SessionEventReceived += OnSessionEventReceived; testApp.ErrorReceived += OnErrorReceived; testApp.TestProcessExited += OnTestProcessExited; - testApp.Created += OnTestApplicationCreated; + testApp.Run += OnTestApplicationRun; testApp.ExecutionIdReceived += OnExecutionIdReceived; return await testApp.RunAsync(filterModeEnabled, enableHelp: false, builtInOptions); @@ -115,65 +120,75 @@ private void CleanUp() } } - private void OnHandshakeInfoReceived(object sender, HandshakeInfoArgs args) + private void OnHandshakeReceived(object sender, HandshakeArgs args) { if (!VSTestTrace.TraceEnabled) { return; } - var handshakeInfo = args.handshakeInfo; + var handshake = args.Handshake; - foreach (var property in handshakeInfo.Properties) + foreach (var property in handshake.Properties) { VSTestTrace.SafeWriteTrace(() => $"{property.Key}: {property.Value}"); } } - private void OnDiscoveredTestReceived(object sender, DiscoveredTestEventArgs args) + private void OnDiscoveredTestsReceived(object sender, DiscoveredTestEventArgs args) { if (!VSTestTrace.TraceEnabled) { return; } - var successfulTestResultMessage = args.DiscoveredTestMessage; - VSTestTrace.SafeWriteTrace(() => $"DiscoveredTestMessage: {successfulTestResultMessage.Uid}, {successfulTestResultMessage.DisplayName}, {successfulTestResultMessage.ExecutionId}"); + var discoveredTestMessages = args.DiscoveredTests; + + VSTestTrace.SafeWriteTrace(() => $"DiscoveredTests Execution Id: {args.ExecutionId}"); + foreach (DiscoveredTest discoveredTestMessage in discoveredTestMessages) + { + VSTestTrace.SafeWriteTrace(() => $"DiscoveredTest: {discoveredTestMessage.Uid}, {discoveredTestMessage.DisplayName}"); + } } - private void OnTestResultReceived(object sender, EventArgs args) + private void OnTestResultsReceived(object sender, TestResultEventArgs args) { if (!VSTestTrace.TraceEnabled) { return; } - if (args is SuccessfulTestResultEventArgs successfulTestResultEventArgs) + VSTestTrace.SafeWriteTrace(() => $"TestResults Execution Id: {args.ExecutionId}"); + + foreach (SuccessfulTestResult successfulTestResult in args.SuccessfulTestResults) { - var successfulTestResultMessage = successfulTestResultEventArgs.SuccessfulTestResultMessage; - VSTestTrace.SafeWriteTrace(() => $"TestResultMessage: {successfulTestResultMessage.Uid}, {successfulTestResultMessage.DisplayName}, " + - $"{successfulTestResultMessage.State}, {successfulTestResultMessage.Reason}, {successfulTestResultMessage.SessionUid}, {successfulTestResultMessage.ExecutionId}"); + VSTestTrace.SafeWriteTrace(() => $"SuccessfulTestResult: {successfulTestResult.Uid}, {successfulTestResult.DisplayName}, " + + $"{successfulTestResult.State}, {successfulTestResult.Reason}, {successfulTestResult.SessionUid}"); } - else if (args is FailedTestResultEventArgs failedTestResultEventArgs) + + foreach (FailedTestResult failedTestResult in args.FailedTestResults) { - var failedTestResultMessage = failedTestResultEventArgs.FailedTestResultMessage; - VSTestTrace.SafeWriteTrace(() => $"TestResultMessage: {failedTestResultMessage.Uid}, {failedTestResultMessage.DisplayName}, " + - $"{failedTestResultMessage.State}, {failedTestResultMessage.Reason}, {failedTestResultMessage.ErrorMessage}," + - $" {failedTestResultMessage.ErrorStackTrace}, {failedTestResultMessage.SessionUid}, {failedTestResultMessage.ExecutionId}"); + VSTestTrace.SafeWriteTrace(() => $"FailedTestResult: {failedTestResult.Uid}, {failedTestResult.DisplayName}, " + + $"{failedTestResult.State}, {failedTestResult.Reason}, {failedTestResult.ErrorMessage}," + + $" {failedTestResult.ErrorStackTrace}, {failedTestResult.SessionUid}"); } } - private void OnFileArtifactInfoReceived(object sender, FileArtifactInfoEventArgs args) + private void OnFileArtifactsReceived(object sender, FileArtifactEventArgs args) { if (!VSTestTrace.TraceEnabled) { return; } - var fileArtifactInfo = args.FileArtifactInfo; - VSTestTrace.SafeWriteTrace(() => $"FileArtifactInfo: {fileArtifactInfo.FullPath}, {fileArtifactInfo.DisplayName}, " + - $"{fileArtifactInfo.Description}, {fileArtifactInfo.TestUid}, {fileArtifactInfo.TestDisplayName}, " + - $"{fileArtifactInfo.SessionUid}, {fileArtifactInfo.ExecutionId}"); + VSTestTrace.SafeWriteTrace(() => $"FileArtifactMessages Execution Id: {args.ExecutionId}"); + + foreach (FileArtifact fileArtifactMessage in args.FileArtifacts) + { + VSTestTrace.SafeWriteTrace(() => $"FileArtifacr: {fileArtifactMessage.FullPath}, {fileArtifactMessage.DisplayName}, " + + $"{fileArtifactMessage.Description}, {fileArtifactMessage.TestUid}, {fileArtifactMessage.TestDisplayName}, " + + $"{fileArtifactMessage.SessionUid}"); + } } private void OnSessionEventReceived(object sender, SessionEventArgs args) @@ -220,7 +235,7 @@ private void OnTestProcessExited(object sender, TestProcessExitEventArgs args) } } - private void OnTestApplicationCreated(object sender, EventArgs args) + private void OnTestApplicationRun(object sender, EventArgs args) { TestApplication testApp = sender as TestApplication; _testApplications.Add(testApp); From 3d626d7fdf9041804ea6d948137d60ecf65d226f Mon Sep 17 00:00:00 2001 From: mariam-abdulla Date: Wed, 4 Sep 2024 16:28:51 +0200 Subject: [PATCH 2/2] Add new model --- .../IPC/Models/{Module.cs => ModuleMessage.cs} | 2 +- ...{ModuleSerializer.cs => ModuleMessageSerializer.cs} | 10 +++++----- .../dotnet-test/IPC/Serializers/RegisterSerializers.cs | 2 +- .../commands/dotnet-test/MSBuildConnectionHandler.cs | 4 ++-- src/Cli/dotnet/commands/dotnet-test/Models.cs | 2 ++ src/Tasks/Microsoft.NET.Build.Tasks/GetTestsProject.cs | 4 ++-- 6 files changed, 13 insertions(+), 11 deletions(-) rename src/Cli/dotnet/commands/dotnet-test/IPC/Models/{Module.cs => ModuleMessage.cs} (63%) rename src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/{ModuleSerializer.cs => ModuleMessageSerializer.cs} (57%) diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Models/Module.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Models/ModuleMessage.cs similarity index 63% rename from src/Cli/dotnet/commands/dotnet-test/IPC/Models/Module.cs rename to src/Cli/dotnet/commands/dotnet-test/IPC/Models/ModuleMessage.cs index b884bdf94a6e..e4ec0b1ac480 100644 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Models/Module.cs +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Models/ModuleMessage.cs @@ -5,4 +5,4 @@ namespace Microsoft.DotNet.Tools.Test; -internal sealed record Module(string? DLLPath, string? ProjectPath, string? TargetFramework) : IRequest; +internal sealed record ModuleMessage(string? DLLPath, string? ProjectPath, string? TargetFramework) : IRequest; diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/ModuleSerializer.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/ModuleMessageSerializer.cs similarity index 57% rename from src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/ModuleSerializer.cs rename to src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/ModuleMessageSerializer.cs index 3fbc7ae55642..9073671e337e 100644 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/ModuleSerializer.cs +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/ModuleMessageSerializer.cs @@ -3,7 +3,7 @@ namespace Microsoft.DotNet.Tools.Test { - internal sealed class ModuleSerializer : BaseSerializer, INamedPipeSerializer + internal sealed class ModuleMessageSerializer : BaseSerializer, INamedPipeSerializer { public int Id => ModuleFieldsId.MessagesSerializerId; @@ -12,14 +12,14 @@ public object Deserialize(Stream stream) string modulePath = ReadString(stream); string projectPath = ReadString(stream); string targetFramework = ReadString(stream); - return new Module(modulePath.Trim(), projectPath.Trim(), targetFramework.Trim()); + return new ModuleMessage(modulePath.Trim(), projectPath.Trim(), targetFramework.Trim()); } public void Serialize(object objectToSerialize, Stream stream) { - WriteString(stream, ((Module)objectToSerialize).DLLPath); - WriteString(stream, ((Module)objectToSerialize).ProjectPath); - WriteString(stream, ((Module)objectToSerialize).TargetFramework); + WriteString(stream, ((ModuleMessage)objectToSerialize).DLLPath); + WriteString(stream, ((ModuleMessage)objectToSerialize).ProjectPath); + WriteString(stream, ((ModuleMessage)objectToSerialize).TargetFramework); } } } diff --git a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/RegisterSerializers.cs b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/RegisterSerializers.cs index 7124e18aff83..c0f02ff7c0bd 100644 --- a/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/RegisterSerializers.cs +++ b/src/Cli/dotnet/commands/dotnet-test/IPC/Serializers/RegisterSerializers.cs @@ -24,7 +24,7 @@ public static void RegisterAllSerializers(this NamedPipeBase namedPipeBase) { namedPipeBase.RegisterSerializer(new VoidResponseSerializer(), typeof(VoidResponse)); namedPipeBase.RegisterSerializer(new CommandLineOptionMessagesSerializer(), typeof(CommandLineOptionMessages)); - namedPipeBase.RegisterSerializer(new ModuleSerializer(), typeof(Module)); + namedPipeBase.RegisterSerializer(new ModuleMessageSerializer(), typeof(ModuleMessage)); namedPipeBase.RegisterSerializer(new DiscoveredTestMessagesSerializer(), typeof(DiscoveredTestMessages)); namedPipeBase.RegisterSerializer(new TestResultMessagesSerializer(), typeof(TestResultMessages)); namedPipeBase.RegisterSerializer(new FileArtifactMessagesSerializer(), typeof(FileArtifactMessages)); diff --git a/src/Cli/dotnet/commands/dotnet-test/MSBuildConnectionHandler.cs b/src/Cli/dotnet/commands/dotnet-test/MSBuildConnectionHandler.cs index 65832f8298c0..f6bf2b63589d 100644 --- a/src/Cli/dotnet/commands/dotnet-test/MSBuildConnectionHandler.cs +++ b/src/Cli/dotnet/commands/dotnet-test/MSBuildConnectionHandler.cs @@ -57,12 +57,12 @@ private Task OnRequest(IRequest request) { try { - if (request is not Module module) + if (request is not ModuleMessage module) { throw new NotSupportedException($"Request '{request.GetType()}' is unsupported."); } - var testApp = new TestApplication(module, _args); + var testApp = new TestApplication(new Module(module.DLLPath, module.ProjectPath, module.TargetFramework), _args); // Write the test application to the channel _actionQueue.Enqueue(testApp); } diff --git a/src/Cli/dotnet/commands/dotnet-test/Models.cs b/src/Cli/dotnet/commands/dotnet-test/Models.cs index 44a254ffb4d8..979296e434e4 100644 --- a/src/Cli/dotnet/commands/dotnet-test/Models.cs +++ b/src/Cli/dotnet/commands/dotnet-test/Models.cs @@ -5,6 +5,8 @@ namespace Microsoft.DotNet.Cli { + internal sealed record Module(string? DLLPath, string? ProjectPath, string? TargetFramework); + internal sealed record Handshake(Dictionary? Properties); internal sealed record CommandLineOption(string? Name, string? Description, bool? IsHidden, bool? IsBuiltIn); diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/GetTestsProject.cs b/src/Tasks/Microsoft.NET.Build.Tasks/GetTestsProject.cs index d7b7838d0c97..57c5995a381b 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/GetTestsProject.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/GetTestsProject.cs @@ -29,11 +29,11 @@ public override bool Execute() NamedPipeClient dotnetTestPipeClient = new(GetTestsProjectPipeName.ItemSpec); - dotnetTestPipeClient.RegisterSerializer(new ModuleSerializer(), typeof(Module)); + dotnetTestPipeClient.RegisterSerializer(new ModuleMessageSerializer(), typeof(ModuleMessage)); dotnetTestPipeClient.RegisterSerializer(new VoidResponseSerializer(), typeof(VoidResponse)); dotnetTestPipeClient.ConnectAsync(CancellationToken.None).GetAwaiter().GetResult(); - dotnetTestPipeClient.RequestReplyAsync(new Module(TargetPath.ItemSpec, ProjectFullPath.ItemSpec, TargetFramework.ItemSpec), CancellationToken.None).GetAwaiter().GetResult(); + dotnetTestPipeClient.RequestReplyAsync(new ModuleMessage(TargetPath.ItemSpec, ProjectFullPath.ItemSpec, TargetFramework.ItemSpec), CancellationToken.None).GetAwaiter().GetResult(); } catch (Exception ex) {