Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add InstanceId to communication with dotnet test #5279

Merged
merged 13 commits into from
Mar 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ internal sealed class DotnetTestConnection : IPushOnlyProtocol,

private NamedPipeClient? _dotnetTestPipeClient;

public static string InstanceId { get; } = Guid.NewGuid().ToString("N");

public DotnetTestConnection(CommandLineHandler commandLineHandler, IProcessHandler processHandler, IEnvironment environment, ITestApplicationModuleInfo testApplicationModuleInfo, ITestApplicationCancellationTokenSource cancellationTokenSource)
{
_commandLineHandler = commandLineHandler;
Expand Down Expand Up @@ -103,6 +105,7 @@ public async Task<bool> IsCompatibleProtocolAsync(string hostType)
{ HandshakeMessagePropertyNames.HostType, hostType },
{ HandshakeMessagePropertyNames.ModulePath, _testApplicationModuleInfo?.GetCurrentTestApplicationFullPath() ?? string.Empty },
{ HandshakeMessagePropertyNames.ExecutionId, _environment.GetEnvironmentVariable(EnvironmentVariableConstants.TESTINGPLATFORM_DOTNETTEST_EXECUTIONID) ?? string.Empty },
{ HandshakeMessagePropertyNames.InstanceId, InstanceId },
});

HandshakeMessage response = await _dotnetTestPipeClient.RequestReplyAsync<HandshakeMessage, HandshakeMessage>(handshakeMessage, _cancellationTokenSource.CancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ internal static class HandshakeMessagePropertyNames
internal const byte HostType = 5;
internal const byte ModulePath = 6;
internal const byte ExecutionId = 7;
internal const byte InstanceId = 8;
}

internal static class ProtocolConstants
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public async Task ConsumeAsync(IDataProducer dataProducer, IData value, Cancella
new DiscoveredTestMessage(
testNodeUpdateMessage.TestNode.Uid.Value,
testNodeUpdateMessage.TestNode.DisplayName),
});
},
DotnetTestConnection.InstanceId);

await _dotnetTestConnection.SendMessageAsync(discoveredTestMessages);
break;
Expand All @@ -81,7 +82,8 @@ public async Task ConsumeAsync(IDataProducer dataProducer, IData value, Cancella
testNodeDetails.StandardError ?? string.Empty,
testNodeUpdateMessage.SessionUid.Value),
},
Array.Empty<FailedTestResultMessage>());
Array.Empty<FailedTestResultMessage>(),
DotnetTestConnection.InstanceId);

await _dotnetTestConnection.SendMessageAsync(testResultMessages);
break;
Expand All @@ -105,7 +107,8 @@ public async Task ConsumeAsync(IDataProducer dataProducer, IData value, Cancella
testNodeDetails.StandardOutput ?? string.Empty,
testNodeDetails.StandardError ?? string.Empty,
testNodeUpdateMessage.SessionUid.Value),
});
},
DotnetTestConnection.InstanceId);

await _dotnetTestConnection.SendMessageAsync(testResultMessages);
break;
Expand All @@ -125,7 +128,8 @@ public async Task ConsumeAsync(IDataProducer dataProducer, IData value, Cancella
testNodeFileArtifact.TestNode.Uid.Value,
testNodeFileArtifact.TestNode.DisplayName,
testNodeFileArtifact.SessionUid.Value),
});
},
DotnetTestConnection.InstanceId);

await _dotnetTestConnection.SendMessageAsync(fileArtifactMessages);
break;
Expand All @@ -142,7 +146,8 @@ public async Task ConsumeAsync(IDataProducer dataProducer, IData value, Cancella
string.Empty,
string.Empty,
sessionFileArtifact.SessionUid.Value),
});
},
DotnetTestConnection.InstanceId);

await _dotnetTestConnection.SendMessageAsync(fileArtifactMessages);
break;
Expand All @@ -159,7 +164,8 @@ public async Task ConsumeAsync(IDataProducer dataProducer, IData value, Cancella
string.Empty,
string.Empty,
string.Empty),
});
},
DotnetTestConnection.InstanceId);

await _dotnetTestConnection.SendMessageAsync(fileArtifactMessages);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ namespace Microsoft.Testing.Platform.IPC.Models;

internal sealed record DiscoveredTestMessage(string? Uid, string? DisplayName);

internal sealed record DiscoveredTestMessages(string? ExecutionId, DiscoveredTestMessage[] DiscoveredMessages) : IRequest;
internal sealed record DiscoveredTestMessages(string? ExecutionId, DiscoveredTestMessage[] DiscoveredMessages, string? InstanceId) : IRequest;
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ namespace Microsoft.Testing.Platform.IPC.Models;

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;
internal sealed record FileArtifactMessages(string? ExecutionId, FileArtifactMessage[] FileArtifacts, string? InstanceId) : IRequest;
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ internal sealed record SuccessfulTestResultMessage(string? Uid, string? DisplayN

internal sealed record FailedTestResultMessage(string? Uid, string? DisplayName, byte? State, long? Duration, string? Reason, ExceptionMessage[]? Exceptions, string? StandardOutput, string? ErrorOutput, string? SessionUid);

internal sealed record TestResultMessages(string? ExecutionId, SuccessfulTestResultMessage[] SuccessfulTestMessages, FailedTestResultMessage[] FailedTestMessages) : IRequest;

internal sealed record ExceptionMessage(string? ErrorMessage, string? ErrorType, string? StackTrace);

internal sealed record TestResultMessages(string? ExecutionId, SuccessfulTestResultMessage[] SuccessfulTestMessages, FailedTestResultMessage[] FailedTestMessages, string? InstanceId) : IRequest;
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ internal static class DiscoveredTestMessagesFieldsId

public const ushort ExecutionId = 1;
public const ushort DiscoveredTestMessageList = 2;
public const ushort InstanceId = 3;
}

internal static class DiscoveredTestMessageFieldsId
Expand All @@ -59,6 +60,7 @@ internal static class TestResultMessagesFieldsId
public const ushort ExecutionId = 1;
public const ushort SuccessfulTestMessageList = 2;
public const ushort FailedTestMessageList = 3;
public const ushort InstanceId = 4;
}

internal static class SuccessfulTestResultMessageFieldsId
Expand Down Expand Up @@ -99,6 +101,7 @@ internal static class FileArtifactMessagesFieldsId

public const ushort ExecutionId = 1;
public const ushort FileArtifactMessageList = 2;
public const ushort InstanceId = 3;
}

internal static class FileArtifactMessageFieldsId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ namespace Microsoft.Testing.Platform.IPC.Serializers;
|---DiscoveredTestMessageList[0].DisplayName Id---| (2 bytes)
|---DiscoveredTestMessageList[0].DisplayName Size---| (4 bytes)
|---DiscoveredTestMessageList[0].DisplayName Value---| (n bytes)

|---InstanceId---| (2 bytes)
|---InstanceId Size---| (4 bytes)
|---InstanceId Value---| (n bytes)
*/

internal sealed class DiscoveredTestMessagesSerializer : BaseSerializer, INamedPipeSerializer
Expand All @@ -36,6 +40,7 @@ public object Deserialize(Stream stream)
{
string? executionId = null;
List<DiscoveredTestMessage>? discoveredTestMessages = null;
string? instanceId = null;

ushort fieldCount = ReadShort(stream);

Expand All @@ -54,14 +59,18 @@ public object Deserialize(Stream stream)
discoveredTestMessages = ReadDiscoveredTestMessagesPayload(stream);
break;

case DiscoveredTestMessagesFieldsId.InstanceId:
instanceId = ReadStringValue(stream, fieldSize);
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]);
return new DiscoveredTestMessages(executionId, discoveredTestMessages is null ? [] : [.. discoveredTestMessages], instanceId);
}

private static List<DiscoveredTestMessage> ReadDiscoveredTestMessagesPayload(Stream stream)
Expand Down Expand Up @@ -112,6 +121,7 @@ public void Serialize(object objectToSerialize, Stream stream)

WriteField(stream, DiscoveredTestMessagesFieldsId.ExecutionId, discoveredTestMessages.ExecutionId);
WriteDiscoveredTestMessagesPayload(stream, discoveredTestMessages.DiscoveredMessages);
WriteField(stream, DiscoveredTestMessagesFieldsId.InstanceId, discoveredTestMessages.InstanceId);
}

private static void WriteDiscoveredTestMessagesPayload(Stream stream, DiscoveredTestMessage[]? discoveredTestMessageList)
Expand Down Expand Up @@ -144,7 +154,8 @@ private static void WriteDiscoveredTestMessagesPayload(Stream stream, Discovered

private static ushort GetFieldCount(DiscoveredTestMessages discoveredTestMessages) =>
(ushort)((discoveredTestMessages.ExecutionId is null ? 0 : 1) +
(IsNullOrEmpty(discoveredTestMessages.DiscoveredMessages) ? 0 : 1));
(IsNullOrEmpty(discoveredTestMessages.DiscoveredMessages) ? 0 : 1) +
(discoveredTestMessages.InstanceId is null ? 0 : 1));

private static ushort GetFieldCount(DiscoveredTestMessage discoveredTestMessage) =>
(ushort)((discoveredTestMessage.Uid is null ? 0 : 1) +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ namespace Microsoft.Testing.Platform.IPC.Serializers;
|---FileArtifactMessageList[0].SessionUid Id---| (2 bytes)
|---FileArtifactMessageList[0].SessionUid Size---| (4 bytes)
|---FileArtifactMessageList[0].SessionUid Value---| (n bytes)

|---InstanceId---| (2 bytes)
|---InstanceId Size---| (4 bytes)
|---InstanceId Value---| (n bytes)
*/

internal sealed class FileArtifactMessagesSerializer : BaseSerializer, INamedPipeSerializer
Expand All @@ -52,6 +56,7 @@ public object Deserialize(Stream stream)
{
string? executionId = null;
List<FileArtifactMessage>? fileArtifactMessages = null;
string? instanceId = null;

ushort fieldCount = ReadShort(stream);

Expand All @@ -70,14 +75,18 @@ public object Deserialize(Stream stream)
fileArtifactMessages = ReadFileArtifactMessagesPayload(stream);
break;

case FileArtifactMessagesFieldsId.InstanceId:
instanceId = ReadStringValue(stream, fieldSize);
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]);
return new FileArtifactMessages(executionId, fileArtifactMessages is null ? [] : [.. fileArtifactMessages], instanceId);
}

private static List<FileArtifactMessage> ReadFileArtifactMessagesPayload(Stream stream)
Expand Down Expand Up @@ -144,6 +153,7 @@ public void Serialize(object objectToSerialize, Stream stream)

WriteField(stream, FileArtifactMessagesFieldsId.ExecutionId, fileArtifactMessages.ExecutionId);
WriteFileArtifactMessagesPayload(stream, fileArtifactMessages.FileArtifacts);
WriteField(stream, FileArtifactMessagesFieldsId.InstanceId, fileArtifactMessages.InstanceId);
}

private static void WriteFileArtifactMessagesPayload(Stream stream, FileArtifactMessage[]? fileArtifactMessageList)
Expand Down Expand Up @@ -180,7 +190,8 @@ private static void WriteFileArtifactMessagesPayload(Stream stream, FileArtifact

private static ushort GetFieldCount(FileArtifactMessages fileArtifactMessages) =>
(ushort)((fileArtifactMessages.ExecutionId is null ? 0 : 1) +
(IsNullOrEmpty(fileArtifactMessages.FileArtifacts) ? 0 : 1));
(IsNullOrEmpty(fileArtifactMessages.FileArtifacts) ? 0 : 1) +
(fileArtifactMessages.InstanceId is null ? 0 : 1));

private static ushort GetFieldCount(FileArtifactMessage fileArtifactMessage) =>
(ushort)((fileArtifactMessage.FullPath is null ? 0 : 1) +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ namespace Microsoft.Testing.Platform.IPC.Serializers;
|---FailedTestMessageList[0].SessionUid Id---| (2 bytes)
|---FailedTestMessageList[0].SessionUid Size---| (4 bytes)
|---FailedTestMessageList[0].SessionUid Value---| (n bytes)

|---InstanceId Id---| (2 bytes)
|---InstanceId Size---| (4 bytes)
|---InstanceId Value---| (n bytes)

*/

internal sealed class TestResultMessagesSerializer : BaseSerializer, INamedPipeSerializer
Expand All @@ -108,6 +113,7 @@ public object Deserialize(Stream stream)
string? executionId = null;
List<SuccessfulTestResultMessage>? successfulTestResultMessages = null;
List<FailedTestResultMessage>? failedTestResultMessages = null;
string? instanceId = null;

ushort fieldCount = ReadShort(stream);

Expand All @@ -126,6 +132,10 @@ public object Deserialize(Stream stream)
successfulTestResultMessages = ReadSuccessfulTestMessagesPayload(stream);
break;

case TestResultMessagesFieldsId.InstanceId:
instanceId = ReadStringValue(stream, fieldSize);
break;

case TestResultMessagesFieldsId.FailedTestMessageList:
failedTestResultMessages = ReadFailedTestMessagesPayload(stream);
break;
Expand All @@ -140,7 +150,8 @@ public object Deserialize(Stream stream)
return new TestResultMessages(
executionId,
successfulTestResultMessages is null ? [] : [.. successfulTestResultMessages],
failedTestResultMessages is null ? [] : [.. failedTestResultMessages]);
failedTestResultMessages is null ? [] : [.. failedTestResultMessages],
instanceId);
}

private static List<SuccessfulTestResultMessage> ReadSuccessfulTestMessagesPayload(Stream stream)
Expand Down Expand Up @@ -327,6 +338,7 @@ public void Serialize(object objectToSerialize, Stream stream)
WriteField(stream, TestResultMessagesFieldsId.ExecutionId, testResultMessages.ExecutionId);
WriteSuccessfulTestMessagesPayload(stream, testResultMessages.SuccessfulTestMessages);
WriteFailedTestMessagesPayload(stream, testResultMessages.FailedTestMessages);
WriteField(stream, TestResultMessagesFieldsId.InstanceId, testResultMessages.InstanceId);
}

private static void WriteSuccessfulTestMessagesPayload(Stream stream, SuccessfulTestResultMessage[]? successfulTestResultMessages)
Expand Down Expand Up @@ -430,7 +442,8 @@ private static void WriteExceptionMessagesPayload(Stream stream, ExceptionMessag
private static ushort GetFieldCount(TestResultMessages testResultMessages) =>
(ushort)((testResultMessages.ExecutionId is null ? 0 : 1) +
(IsNullOrEmpty(testResultMessages.SuccessfulTestMessages) ? 0 : 1) +
(IsNullOrEmpty(testResultMessages.FailedTestMessages) ? 0 : 1));
(IsNullOrEmpty(testResultMessages.FailedTestMessages) ? 0 : 1) +
(testResultMessages.InstanceId is null ? 0 : 1));

private static ushort GetFieldCount(SuccessfulTestResultMessage successfulTestResultMessage) =>
(ushort)((successfulTestResultMessage.Uid is null ? 0 : 1) +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public void TestResultMessagesSerializeDeserialize()
{
var success = new SuccessfulTestResultMessage("uid", "displayName", 1, 100, "reason", "standardOutput", "errorOutput", "sessionUid");
var fail = new FailedTestResultMessage("uid", "displayName", 2, 200, "reason", [new ExceptionMessage("errorMessage", "errorType", "stackTrace")], "standardOutput", "errorOutput", "sessionUid");
var message = new TestResultMessages("executionId", new[] { success }, new[] { fail });
var message = new TestResultMessages("executionId", new[] { success }, new[] { fail }, "instanceId");

var stream = new MemoryStream();
new TestResultMessagesSerializer().Serialize(message, stream);
Expand Down
Loading