[fix] Fix data collection channels to use negotiated protocol version instead of V1 - #16096
Conversation
…ad of V1 The datacollector IPC channels (vstest.console↔datacollector and testhost↔datacollector) were always using V1 serialization because all SendMessage calls omitted the version parameter, which defaults to 1 in SocketCommunicationManager. This meant TestCase objects in DataCollectionTestStart/DataCollectionTestEnd messages used the slow V1 serializer instead of the modern serializer. Main channel (DataCollectionRequestSender / DataCollectionRequestHandler): - Sender sends BeforeTestRunStart at HighestSupportedVersion (V7) to advertise its capability. - Handler reads the request version, stores min(request, own highest) as _protocolVersion, and echoes that version in BeforeTestRunStartResult. - Sender reads the response version and adopts it as _protocolVersion for all subsequent messages (TestHostLaunched, AfterTestRunEnd). - Handler uses _protocolVersion for all outgoing messages (BeforeTestRunStartResult, AfterTestRunEndResult, DataCollectionMessage). Test-case event channel (DataCollectionTestCaseEventSender / DataCollectionTestCaseEventHandler): - Sender always sends at HighestSupportedVersion. - Handler echoes the incoming message version in DataCollectionTestEndResult. Backward compatibility is preserved: an old handler responds at V1 (no version param), which the sender reads and stores; an old sender sends at V1, which the handler stores. Fixes #15623 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the data collection IPC channels (vstest.console ↔ datacollector and testhost ↔ datacollector) to stop defaulting to protocol V1 serialization by ensuring the protocol version is explicitly included on SendMessage(type, payload, version) calls and (partially) negotiated.
Changes:
- Add protocol version negotiation state to
DataCollectionRequestSender/DataCollectionRequestHandlerand use it for subsequent messages on that channel. - Update
DataCollectionTestCaseEventSender/DataCollectionTestCaseEventHandlerto send/echo protocol versions for test-case start/end events. - Update CommunicationUtilities unit tests to validate the 3-argument
SendMessageoverload is used.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Microsoft.TestPlatform.CommunicationUtilities/DataCollectionRequestSender.cs | Tracks negotiated protocol version and uses it for datacollector-bound messages. |
| src/Microsoft.TestPlatform.CommunicationUtilities/DataCollectionRequestHandler.cs | Negotiates protocol version on BeforeTestRunStart and uses it for responses. |
| src/Microsoft.TestPlatform.CommunicationUtilities/DataCollectionTestCaseEventSender.cs | Sends test-case event messages using HighestSupportedVersion. |
| src/Microsoft.TestPlatform.CommunicationUtilities/DataCollectionTestCaseEventHandler.cs | Sends test-case end result using the incoming message version. |
| test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionRequestSenderTests.cs | Verifies BeforeTestRunStart is sent with an explicit protocol version. |
| test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionRequestHandlerTests.cs | Updates verifications to expect the versioned SendMessage overload. |
| test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionTestCaseEventSenderTests.cs | Verifies test-case start/end messages are sent with an explicit protocol version. |
| test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionTestCaseEventHandlerTests.cs | Updates verification to expect the versioned SendMessage overload. |
| if (message.Version > 0) | ||
| { | ||
| _protocolVersion = message.Version; | ||
| } |
| } | ||
|
|
||
| _communicationManager.SendMessage(MessageType.DataCollectionTestEndResult, attachmentSets); | ||
| _communicationManager.SendMessage(MessageType.DataCollectionTestEndResult, attachmentSets, message.Version); |
Jakub Jareš (nohwnd)
left a comment
There was a problem hiding this comment.
Review: Fix data collection channels to use negotiated protocol version
The main channel fix (DataCollectionRequestSender ↔ DataCollectionRequestHandler) is mechanically correct end-to-end:
- Sender advertises
HighestSupportedVersioninBeforeTestRunStart. - Handler computes
Math.Min(request.Version, HighestSupportedVersion), stores the result, echoes it inBeforeTestRunStartResult. - Sender adopts the echoed version for all subsequent messages (
TestHostLaunched,AfterTestRunEnd). - Old-sender / old-handler backward compat is preserved via the
>0guard and the default1fallback.
Three issues flagged with inline comments:
-
Sub-channel missing negotiation (medium) —
DataCollectionTestCaseEventSenderalways sends atHighestSupportedVersion(V7) with no_protocolVersionfield and noMath.Minguard. The PR's backward-compat table covers the main channel only. If the datacollector was built before V7 was added to theGetPayloadOptionsswitch, it would throwNotSupportedExceptionfor every incoming test-case event. This is mitigated by the fact that V7 is already in both the STJ and Jsonite version switches today, but the risk is undocumented and the guarantee is fragile. -
Tests don't assert the negotiated version value (medium) — All handler tests set
BeforeTestRunStart.Version = 7and then verify withIt.IsAny<int>(). BecauseMath.Min(7, 7) == 7, the invariant is never exercised with a request version lower thanHighestSupportedVersion. A test withVersion = 4asserting the response sends exactly4would catch silent regressions in the negotiation logic. -
DataCollectionTestStartAckcarries no version (low) —DataCollectionTestEndResultechoesmessage.Versionbut the start ack is sent with the 1-arg overload. Currently harmless; noted for consistency and forward-compat.
🧠 Reviewed by Expert Code Review · Dimensions: IPC Transport & Protocol Stability, Backward Compatibility & Rollback Safety
🧠 Reviewed by Expert Code Reviewer 🧠
| public void SendTestCaseStart(TestCaseStartEventArgs e) | ||
| { | ||
| _communicationManager.SendMessage(MessageType.DataCollectionTestStart, e); | ||
| _communicationManager.SendMessage(MessageType.DataCollectionTestStart, e, ProtocolVersioning.HighestSupportedVersion); |
There was a problem hiding this comment.
[IPC Transport & Protocol Stability] Unlike the main data collection channel (DataCollectionRequestSender/DataCollectionRequestHandler) — which negotiates via Math.Min(request.Version, HighestSupportedVersion) and stores the result in _protocolVersion — the test case event sub-channel always sends at HighestSupportedVersion with no negotiation and no _protocolVersion field.
The backward-compat table in the PR description covers the main channel only. For this sub-channel, if the DataCollectionTestCaseEventHandler in the datacollector process is from an older vstest build whose GetPayloadOptions switch does not yet include V7 (the current HighestSupportedVersion), it will throw NotSupportedException on every incoming test-case event.
This is mitigated today because both the STJ and Jsonite implementations already list 7 in their version switches, so any datacollector built against a recent vstest can handle V7 payloads. However:
- V7 carries no documented change in
ProtocolVersioning.cs(no summary comment), so the boundary where "old" becomes "unsafe" is unclear. - The handler side properly guards
DataCollectionTestEndResultby echoingmessage.Version, but the sender never uses that echoed value to adapt future sends — so the echo only helps the sender deserialize the response, not to detect version mismatches before they happen.
Consider threading the negotiated _protocolVersion from the main-channel handshake into DataCollectionTestCaseEventSender (e.g. via BeforeTestRunStartResult), or adding a minimal echo/ack round-trip on this channel similar to CheckVersionWithTestHostAsync, so the sub-channel enjoys the same Math.Min safety as the main channel.
There was a problem hiding this comment.
Fixed. The sub-channel now has proper Math.Min negotiation on both sides:
DataCollectionTestCaseEventSendergains a_protocolVersionfield (initialized toHighestSupportedVersion). After eachSendTestCaseStart, the negotiated version is adopted from theDataCollectionTestStartAckversion echo for all subsequent sends (SendTestCaseEnd,SendTestSessionEnd).DataCollectionTestCaseEventHandlernow sendsDataCollectionTestStartAckwithMath.Min(message.Version, ProtocolVersioning.HighestSupportedVersion)so the handler's capability boundary is communicated back to the sender.
New tests verify: (1) DataCollectionTestStartAck echoes the min of sender version and highest supported, (2) SendTestCaseEnd and SendTestSessionEnd use the negotiated version after a test-case start negotiation.
🔧 Iterated by PR Iteration Agent 🔧
| // Verify SessionStarted events | ||
| _mockDataCollectionManager.Verify(x => x.SessionStarted(It.IsAny<SessionStartEventArgs>()), Times.Once); | ||
| _mockCommunicationManager.Verify(x => x.SendMessage(MessageType.BeforeTestRunStartResult, It.IsAny<BeforeTestRunStartResult>()), Times.Once); | ||
| _mockCommunicationManager.Verify(x => x.SendMessage(MessageType.BeforeTestRunStartResult, It.IsAny<BeforeTestRunStartResult>(), It.IsAny<int>()), Times.Once); |
There was a problem hiding this comment.
[Backward Compatibility & Rollback Safety / Test Coverage] It.IsAny<int>() verifies that the 3-arg SendMessage overload is called, but it does not validate the negotiated version value.
The critical invariant is _protocolVersion = Math.Min(request.Version, HighestSupportedVersion). A test that sends BeforeTestRunStart at a version lower than HighestSupportedVersion (e.g. Version = 4) and then asserts the response uses exactly 4 — not 7 — would catch regressions where the handler accidentally uses the wrong version (e.g. always responds at HighestSupportedVersion, or always responds at 1). The current tests all set Version = 7, so Math.Min(7, 7) == 7 and the It.IsAny<int>() matcher would accept any wrong value silently.
There was a problem hiding this comment.
Added. A new test ProcessRequestsShouldNegotiateProtocolVersionToMinOfRequestAndHighest sends BeforeTestRunStart at version 4 (less than HighestSupportedVersion = 7) and asserts that both BeforeTestRunStartResult and AfterTestRunEndResult are sent at exactly version 4 — verifying the Math.Min(4, 7) = 4 invariant and catching regressions where the handler might respond at the wrong version.
🔧 Iterated by PR Iteration Agent 🔧
| } | ||
|
|
||
| _communicationManager.SendMessage(MessageType.DataCollectionTestEndResult, attachmentSets); | ||
| _communicationManager.SendMessage(MessageType.DataCollectionTestEndResult, attachmentSets, message.Version); |
There was a problem hiding this comment.
[IPC Transport & Protocol Stability] DataCollectionTestEndResult now correctly echoes message.Version, but DataCollectionTestStartAck (nine lines earlier) is still sent with the 1-arg overload and carries no version. The sender currently ignores the ack version so this is harmless, but the asymmetry is a maintenance hazard: if the sender ever starts tracking version from the ack (e.g. to initialise _protocolVersion on the sub-channel), it would silently read 0 instead of the handler's supported version. For consistency, consider echoing message.Version here too.
There was a problem hiding this comment.
Fixed. DataCollectionTestStartAck now uses the 3-arg overload and echoes Math.Min(message.Version, ProtocolVersioning.HighestSupportedVersion), matching the pattern of DataCollectionTestEndResult. A new test ProcessRequestsShouldEchoNegotiatedVersionInTestCaseStartAck verifies the echo.
🔧 Iterated by PR Iteration Agent 🔧
… coverage - DataCollectionTestCaseEventHandler: echo Math.Min(message.Version, HighestSupportedVersion) in DataCollectionTestStartAck so the sender can detect the handler's maximum supported version - DataCollectionTestCaseEventSender: add _protocolVersion field (initialized to HighestSupportedVersion); adopt the negotiated version from the DataCollectionTestStartAck for all subsequent sends (SendTestCaseEnd, SendTestSessionEnd), giving the sub-channel the same Math.Min safety as the main DataCollection channel - DataCollectionRequestHandlerTests: add test that sends BeforeTestRunStart at version 4 and asserts both BeforeTestRunStartResult and AfterTestRunEndResult are sent at exactly version 4, verifying the Math.Min negotiation invariant - DataCollectionTestCaseEventHandlerTests: add test verifying DataCollectionTestStartAck echoes Math.Min(incomingVersion, HighestSupportedVersion) - DataCollectionTestCaseEventSenderTests: add tests verifying SendTestCaseEnd and SendTestSessionEnd use the version negotiated via the DataCollectionTestStartAck Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Commit pushed:
|
Jakub Jareš (nohwnd)
left a comment
There was a problem hiding this comment.
Review: Iteration update (commit 4b99347)
All three issues from the prior review have been addressed in the second commit:
- ✅ Sub-channel negotiation —
DataCollectionTestCaseEventSendernow tracks_protocolVersion, initialised toHighestSupportedVersionand updated from theDataCollectionTestStartAckecho.DataCollectionTestCaseEventHandlerresponds withMath.Min(message.Version, HighestSupportedVersion). - ✅ Test coverage for negotiation invariant — New test sends
BeforeTestRunStartat version 4 and asserts bothBeforeTestRunStartResultandAfterTestRunEndResultare sent at exactly 4, covering theMath.Min(4, 7) = 4invariant. - ✅
DataCollectionTestStartAckversion — Now sends withMath.Min(message.Version, HighestSupportedVersion), matchingDataCollectionTestEndResult.
Two follow-up observations on the iterated code (see inline comments):
-
DataCollectionTestEndResultmissingMath.Minguard (low) —DataCollectionTestStartAckusesMath.Min(message.Version, HighestSupportedVersion), butDataCollectionTestEndResultechoes rawmessage.Version. Not a correctness issue in the current negotiated flow (the sender's_protocolVersionis already bounded by the ack), but the asymmetry is a maintenance hazard. -
_protocolVersionadoption withoutMath.Min(low) — BothDataCollectionRequestSender(line 147) andDataCollectionTestCaseEventSender(line 101) adopt the handler-echoed version without clamping. If a buggy/out-of-sync handler ever reported a version aboveHighestSupportedVersion, the sender would crash on the next serialization. The handler side is correctly guarded; addingMath.Minon the adoption side would close the loop.
Description drift: The PR description's sub-channel section ("Sender always sends at HighestSupportedVersion. Handler echoes the incoming message version in DataCollectionTestEndResult.") no longer fully describes the post-iteration behavior. The sub-channel now has a proper _protocolVersion field and ack-based Math.Min negotiation — worth updating the description to reflect this.
🧠 Reviewed by Expert Code Reviewer 🧠 · Dimensions: IPC Transport & Protocol Stability, Backward Compatibility & Rollback Safety
🧠 Reviewed by Expert Code Reviewer 🧠
🧠 Reviewed by Expert Code Reviewer 🧠
| } | ||
|
|
||
| _communicationManager.SendMessage(MessageType.DataCollectionTestEndResult, attachmentSets); | ||
| _communicationManager.SendMessage(MessageType.DataCollectionTestEndResult, attachmentSets, message.Version); |
There was a problem hiding this comment.
[IPC Transport & Protocol Stability] DataCollectionTestStartAck (line 100) uses Math.Min(message.Version, ProtocolVersioning.HighestSupportedVersion), but DataCollectionTestEndResult here echoes message.Version unguarded.
In the current negotiated flow this is harmless — the sender's _protocolVersion was already bounded by the ack's Math.Min, so the version arriving in DataCollectionTestEnd cannot exceed HighestSupportedVersion. However, the asymmetry is a maintenance hazard: if message.Version ever arrived out of range (buggy/rogue sender), GetPayloadOptions would throw NotSupportedException on this response path while the ack path would not.
For consistency with the ack and with the main-channel handler (DataCollectionRequestHandler.HandleBeforeTestRunStart), consider:
_communicationManager.SendMessage(MessageType.DataCollectionTestEndResult, attachmentSets, Math.Min(message.Version, ProtocolVersioning.HighestSupportedVersion));There was a problem hiding this comment.
Fixed. DataCollectionTestEndResult now echoes Math.Min(message.Version, ProtocolVersioning.HighestSupportedVersion) for consistency with DataCollectionTestStartAck and the main-channel handler. A new test ProcessRequestsShouldNegotiateVersionInTestCaseEndResult verifies the guard with a sender at version 4.
🔧 Iterated by PR Iteration Agent 🔧
🔧 Iterated by PR Iteration Agent 🔧
| // protocol version for all subsequent messages on this channel. | ||
| if (message.Version > 0) | ||
| { | ||
| _protocolVersion = message.Version; |
There was a problem hiding this comment.
[IPC Transport & Protocol Stability] _protocolVersion is adopted directly from message.Version with no Math.Min guard. The same pattern appears in DataCollectionTestCaseEventSender.SendTestCaseStart (line 101).
In practice the handler always responds with Math.Min(request.Version, HighestSupportedVersion), so the echoed value will never exceed HighestSupportedVersion. But if a rogue or out-of-sync handler ever reported a higher version, the sender would try to serialize subsequent messages at an unsupported version and hit NotSupportedException in GetPayloadOptions.
Defense-in-depth suggestion for both sites:
if (message.Version > 0)
{
_protocolVersion = Math.Min(message.Version, ProtocolVersioning.HighestSupportedVersion);
}There was a problem hiding this comment.
Fixed. Both DataCollectionRequestSender (line 147) and DataCollectionTestCaseEventSender (line 101) now use _protocolVersion = Math.Min(message.Version, ProtocolVersioning.HighestSupportedVersion) when adopting the echoed version, guarding against a rogue/out-of-sync handler reporting a version above HighestSupportedVersion.
🔧 Iterated by PR Iteration Agent 🔧
🔧 Iterated by PR Iteration Agent 🔧
…estEndResult echo - DataCollectionTestCaseEventHandler: echo Math.Min(message.Version, HighestSupportedVersion) in DataCollectionTestEndResult (defense-in-depth, consistent with TestStartAck) - DataCollectionRequestSender: guard _protocolVersion = Math.Min(message.Version, HighestSupportedVersion) when adopting BeforeTestRunStartResult version - DataCollectionTestCaseEventSender: guard _protocolVersion = Math.Min(message.Version, HighestSupportedVersion) when adopting TestStartAck version - Add test ProcessRequestsShouldNegotiateVersionInTestCaseEndResult to verify Math.Min for TestEndResult Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Commit pushed:
|
| var message = _communicationManager.ReceiveMessage(); | ||
| if (message != null && message.MessageType != MessageType.DataCollectionTestStartAck) | ||
| { | ||
| EqtTrace.Error("DataCollectionTestCaseEventSender.SendTestCaseStart : MessageType.DataCollectionTestStartAck not received."); | ||
| } | ||
|
|
||
| // Adopt the version echoed by the handler as the negotiated protocol version for all | ||
| // subsequent sends on this sub-channel. | ||
| if (message?.Version > 0) | ||
| { | ||
| _protocolVersion = Math.Min(message.Version, ProtocolVersioning.HighestSupportedVersion); | ||
| } | ||
| } |
| } | ||
|
|
||
| _communicationManager.SendMessage(MessageType.DataCollectionTestStartAck); | ||
| _communicationManager.SendMessage(MessageType.DataCollectionTestStartAck, string.Empty, Math.Min(message.Version, ProtocolVersioning.HighestSupportedVersion)); |
| } | ||
|
|
||
| _communicationManager.SendMessage(MessageType.DataCollectionTestEndResult, attachmentSets); | ||
| _communicationManager.SendMessage(MessageType.DataCollectionTestEndResult, attachmentSets, Math.Min(message.Version, ProtocolVersioning.HighestSupportedVersion)); |
| var message = new Message | ||
| { | ||
| MessageType = MessageType.DataCollectionTestStart, | ||
| Version = 4, | ||
| RawMessage = JsonDataSerializer.Instance.SerializePayload(MessageType.DataCollectionTestStart, new TestCaseEndEventArgs(), 4), | ||
| }; |
| var testCase = new TestCase("hello", new Uri("world://how"), "1.dll"); | ||
| var message = new Message | ||
| { | ||
| MessageType = MessageType.DataCollectionTestEnd, | ||
| Version = 4, | ||
| RawMessage = JsonDataSerializer.Instance.SerializePayload(MessageType.DataCollectionTestEnd, new TestResultEventArgs(new VisualStudio.TestPlatform.ObjectModel.TestResult(testCase)), 4), | ||
| }; |
| // After negotiating version 4 via the ack, SendTestSessionEnd must use version 4. | ||
| _mockCommunicationManager.Verify(x => x.SendMessage(MessageType.SessionEnd, It.IsAny<SessionEndEventArgs>(), 4), Times.Once); | ||
| } | ||
| } |
Jakub Jareš (nohwnd)
left a comment
There was a problem hiding this comment.
Review: Iteration update (commit a0f6309)
Both issues from the third review have been resolved in this commit:
- ✅
DataCollectionTestEndResultMath.Minguard —DataCollectionTestCaseEventHandlernow echoesMath.Min(message.Version, ProtocolVersioning.HighestSupportedVersion)in bothDataCollectionTestStartAckandDataCollectionTestEndResult, fully symmetric. - ✅
_protocolVersionadoption guard — BothDataCollectionRequestSender(BeforeTestRunStartResult path) andDataCollectionTestCaseEventSender(DataCollectionTestStartAck path) now adopt the echoed version withMath.Min(message.Version, ProtocolVersioning.HighestSupportedVersion), closing the defense-in-depth gap.
New tests cover both fixes:
ProcessRequestsShouldNegotiateVersionInTestCaseEndResult— verifiesDataCollectionTestEndResultechoesMath.Min(4, 7) = 4- The sender-side
Math.Minis implicitly exercised bySendTestCaseEndShouldUseVersionNegotiatedFromTestCaseStartAckandSendTestSessionEndShouldUseVersionNegotiatedFromTestCaseStartAck
The code is now in a clean, consistent state: every version adoption and version echo in all four classes uses Math.Min with the same > 0 guard. No correctness, compatibility, or protocol-safety issues remain.
One remaining housekeeping item — PR description: The sub-channel section of the description still reflects the state after the first iteration, not the final design:
"Sender always sends at
HighestSupportedVersion. Handler echoes the incoming message version inDataCollectionTestEndResult."
The final implementation goes further: the sender now carries _protocolVersion and adapts from the DataCollectionTestStartAck echo; the handler guards both responses with Math.Min; and the sender adoption itself is Math.Min-guarded. The backward-compat table only covers the main channel but the sub-channel has an equivalent negotiation path now. Worth a quick description update before merge so it accurately reflects what landed.
🧠 Reviewed by Expert Code Reviewer 🧠 · Dimensions: IPC Transport & Protocol Stability, Backward Compatibility & Rollback Safety
🧠 Reviewed by Expert Code Reviewer 🧠
🧠 Reviewed by Expert Code Reviewer 🧠
This comment has been minimized.
This comment has been minimized.
|
The expert reviewer flagged that the PR description's sub-channel section is out of date. Here is a suggested replacement for the "Data Collection Sub-Channel Protocol" portion: Before:
Suggested updated text:
|
Fixes #15623
Root Cause
The data collection IPC channels (
vstest.console ↔ datacollectorandtesthost ↔ datacollector) always used V1 serialization because everySendMessage(type, payload)call omitted the version parameter, which defaults to1inSocketCommunicationManager. This meantTestCaseobjects inDataCollectionTestStart/DataCollectionTestEndmessages were serialized with the slow V1 serializer instead of the modern V2+ serializer.By contrast, the primary test execution channel (
vstest.console ↔ testhost) already performs a proper version-negotiation handshake viaCheckVersionWithTestHostAsync.What the Fix Does
Main channel (
DataCollectionRequestSender/DataCollectionRequestHandler)Version negotiation is piggybacked on the existing
BeforeTestRunStart/BeforeTestRunStartResultexchange (no new round-trip needed):BeforeTestRunStartatProtocolVersioning.HighestSupportedVersion(V7) to advertise its capability.message.Version, computes_protocolVersion = Math.Min(request.Version, HighestSupportedVersion), stores it, and echoes it in theBeforeTestRunStartResultresponse.message.VersionfromBeforeTestRunStartResult, adopts it as_protocolVersionfor all subsequent messages (TestHostLaunched,AfterTestRunEnd)._protocolVersionfor all outgoing messages (BeforeTestRunStartResult,AfterTestRunEndResult,DataCollectionMessage).Test-case event channel (
DataCollectionTestCaseEventSender/DataCollectionTestCaseEventHandler)HighestSupportedVersion.DataCollectionTestEndResult.Backward compatibility
No new public API surface is added.
Tests
Updated unit tests in
DataCollectionRequestSenderTests,DataCollectionRequestHandlerTests,DataCollectionTestCaseEventSenderTests, andDataCollectionTestCaseEventHandlerTeststo verify the 3-argumentSendMessage(type, payload, version)overload is called.All 625
Microsoft.TestPlatform.CommunicationUtilities.UnitTeststests pass.