feat: migrate from Newtonsoft.Json to System.Text.Json / Jsonite#15540
feat: migrate from Newtonsoft.Json to System.Text.Json / Jsonite#15540nohwnd merged 81 commits intomicrosoft:rel/18.7-stjfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Migrates VSTest’s serialization infrastructure from Newtonsoft.Json to System.Text.Json, including protocol payload handling and test updates, while introducing golden baseline tests to preserve wire-format compatibility.
Changes:
- Replaced
JToken/JObjectusage withJsonElement/JsonDocumentand STJ nodes across runtime + tests. - Rewrote core serializer configuration (
JsonDataSerializer) and multiple custom converters for protocol v1/v2 payload shapes. - Updated package references and added golden JSON baseline tests to validate compatibility.
Reviewed changes
Copilot reviewed 45 out of 45 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| test/TranslationLayer.UnitTests/VsTestConsoleRequestSenderTests.cs | Updates test message payloads from JToken to JsonElement via STJ serialization. |
| test/Microsoft.TestPlatform.TestUtilities/IntegrationTestBuild.cs | Switches checksum serialization from Newtonsoft to STJ with indented output. |
| test/Microsoft.TestPlatform.ObjectModel.UnitTests/Microsoft.TestPlatform.ObjectModel.UnitTests.csproj | Replaces Newtonsoft.Json package reference with System.Text.Json. |
| test/Microsoft.TestPlatform.ObjectModel.UnitTests/Client/DiscoveryCriteriaTests.cs | Migrates serialization/deserialization assertions to STJ. |
| test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/EventHandlers/TestRequestHandlerTests.cs | Updates protocol message payloads to JsonElement. |
| test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/Parallel/ParallelRunEventsHandlerTests.cs | Updates mocked message payloads to STJ JsonElement. |
| test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/Parallel/ParallelDiscoveryEventsHandlerTests.cs | Updates mocked message payloads to STJ JsonElement. |
| test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/TestResultSerializationTests.cs | Replaces JObject/dynamic JSON assertions with JsonDocument/JsonElement. |
| test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/TestCaseSerializationTests.cs | Replaces Newtonsoft JSON parsing/formatting with STJ equivalents. |
| test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/SerializationGoldenTests.cs | Adds golden baseline serialization tests for v1/v2 protocol formats. |
| test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs | Updates serializer tests for STJ behavior (cycle handling, payload assertions). |
| test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionTestCaseEventSenderTests.cs | Updates payload creation to STJ JsonElement. |
| test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionTestCaseEventHandlerTests.cs | Updates message payloads to STJ and adjusts a complex payload construction. |
| test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionRequestHandlerTests.cs | Updates test messages’ payloads to STJ JsonElement. |
| test/Microsoft.TestPlatform.Client.UnitTests/DesignMode/DesignModeClientTests.cs | Updates design-mode protocol message payloads to STJ JsonElement. |
| test/Microsoft.TestPlatform.AdapterUtilities.UnitTests/Microsoft.TestPlatform.AdapterUtilities.UnitTests.csproj | Replaces Newtonsoft.Json package reference with System.Text.Json. |
| test/Microsoft.TestPlatform.Acceptance.IntegrationTests/DotnetHostArchitectureVerifierTests.cs | Replaces runtimeconfig JSON patching with JsonNode + ToJsonString(). |
| test/Microsoft.TestPlatform.Acceptance.IntegrationTests/DotnetArchitectureSwitchTests.Windows.cs | Replaces runtimeconfig JSON patching with JsonNode + ToJsonString(). |
| src/package/Microsoft.TestPlatform/Microsoft.TestPlatform.csproj | Packages System.Text.Json instead of Newtonsoft.Json. |
| src/package/Microsoft.TestPlatform.Portable/Microsoft.TestPlatform.Portable.csproj | Packages System.Text.Json instead of Newtonsoft.Json. |
| src/package/Microsoft.TestPlatform.CLI/Microsoft.TestPlatform.CLI.csproj | Swaps Newtonsoft.Json packaging/copy logic to System.Text.Json. |
| src/Microsoft.TestPlatform.TestHostProvider/Microsoft.TestPlatform.TestHostProvider.csproj | Replaces Newtonsoft.Json dependency with System.Text.Json. |
| src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs | Replaces JObject/JToken parsing with JsonDocument for runtimeconfig probing paths. |
| src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestRunStatisticsConverter.cs | Rewrites to JsonConverter<ITestRunStatistics> for STJ. |
| src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestResultConverterV2.cs | Introduces STJ converter implementing v2 flat TestResult JSON shape. |
| src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestResultConverter.cs | Rewrites v1 TestResult converter from Newtonsoft to STJ. |
| src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestPropertyConverter.cs | Adds STJ converter to serialize TestProperty without delegate members. |
| src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestPlatformContractResolver1.cs | Removes Newtonsoft contract resolver (now STJ options setup lives in JsonDataSerializer). |
| src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestObjectConverter.cs | Rewrites TestObject property-bag converter for STJ and removes experimental v7 code. |
| src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestObjectBaseConverter.cs | Adds factory + converter for TestObject-derived types that only serialize the property bag. |
| src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestExecutionContextConverter.cs | Adds STJ converter ensuring DataMember-only behavior for TestExecutionContext. |
| src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestCaseConverterV2.cs | Adds STJ converter implementing v2 flat TestCase JSON shape. |
| src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestCaseConverter.cs | Rewrites v1 TestCase converter from Newtonsoft to STJ. |
| src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/DefaultTestPlatformContractResolver.cs | Removes Newtonsoft contract resolver (moved to STJ options in JsonDataSerializer). |
| src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/AttachmentConverters.cs | Adds STJ converters for AttachmentSet and UriDataAttachment ctor constraints. |
| src/Microsoft.TestPlatform.CommunicationUtilities/PublicAPI/PublicAPI.Shipped.txt | Updates shipped API surface for Message.Payload to JsonElement? and converter overrides. |
| src/Microsoft.TestPlatform.CommunicationUtilities/ObjectModel/TestRunCriteriaWithTests.cs | Replaces Newtonsoft Json attributes namespace with STJ. |
| src/Microsoft.TestPlatform.CommunicationUtilities/ObjectModel/TestRunCriteriaWithSources.cs | Replaces Newtonsoft Json attributes namespace with STJ. |
| src/Microsoft.TestPlatform.CommunicationUtilities/Microsoft.TestPlatform.CommunicationUtilities.csproj | Replaces Newtonsoft.Json dependency with System.Text.Json. |
| src/Microsoft.TestPlatform.CommunicationUtilities/Messages/Message.cs | Changes Message.Payload type to JsonElement? and updates ToString(). |
| src/Microsoft.TestPlatform.CommunicationUtilities/JsonDataSerializer.cs | Rewrites serializer core to STJ with protocol-specific options and “fast path”. |
| eng/Versions.props | Adds SystemTextJsonVersion and updates projects to consume it. |
| docs/stj-migration-overview.md | Adds manager-facing overview and risks (including breaking API). |
| docs/stj-migration-detailed.md | Adds detailed migration plan and critical compat details. |
| docs/stj-migration-changelog.md | Adds file-by-file migration change log. |
Comments suppressed due to low confidence (2)
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1
- The updated comment describes the expected post-deserialization shape, but the test no longer asserts it. This reduces the test’s ability to catch regressions in cycle-handling semantics. Add assertions for the expected object graph (e.g.,
result.InfiniteReferencepresence and itsInfiniteReferencebeing null) to match the documented behavior.
test/Microsoft.TestPlatform.ObjectModel.UnitTests/Client/DiscoveryCriteriaTests.cs:1 - This assertion is order-sensitive and relies on the serializer emitting properties in a specific order. Since JSON object order is not semantically significant, this can make the test brittle across runtime/tooling changes. Consider comparing parsed JSON (e.g., via
JsonDocument) or reusing the normalization approach used in the golden tests, unless strict ordering is explicitly required for the wire protocol here.
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestResultConverterV2.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.TestPlatform.CommunicationUtilities/JsonDataSerializer.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestResultConverter.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.TestPlatform.CommunicationUtilities/JsonDataSerializer.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 63 changed files in this pull request and generated 6 comments.
Comments suppressed due to low confidence (4)
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/TestRunStatsChangeSerializationTests.cs:1
- These new wire-format tests are currently disabled via
[Ignore], which leaves the STJ migration unvalidated for deserialization/round-trip ofTestRunStatsPayload. Since this PR is explicitly about preserving protocol compatibility, it would be better to either (1) implement the required custom converter(s) (e.g., forTestRunChangedEventArgs) and enable these tests, or (2) move ignored cases into a tracked work item with an explicit TODO + target milestone so the gap can’t silently persist.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/ExecutionCompleteSerializationTests.cs:1 - Same issue as above but more critical:
ExecutionCompleteis described as the most complex message in the protocol, yet deserialization/round-trip tests are ignored. For a migration with wire-format guarantees, enabling these by adding aJsonConverterforTestRunCompleteEventArgs(and any other required types) should be treated as required before considering the migration complete.
test/TranslationLayer.UnitTests/VsTestConsoleRequestSenderTests.cs:1 - Many tests now construct
Message.PayloadusingJsonSerializer.SerializeToElement(...)with default STJ options. This bypasses the customJsonDataSerializeroptions/converters (and protocol-version-specific shapes), so the tests may no longer be exercising the real wire format. Prefer constructing payload elements via the production serializer (e.g., serialize withJsonDataSerializer.Instance.Serialize(..., version)and parse/clone into aJsonElement) to keep unit tests aligned with the protocol behavior.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.UnitTests.csproj:1 - This introduces a hard-coded Newtonsoft.Json version while the repo already has a central
$(NewtonsoftJsonVersion)property ineng/Versions.props. Using the shared property here would avoid accidental version drift between production and test comparison infrastructure.
src/Microsoft.TestPlatform.CommunicationUtilities/Messages/Message.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestObjectConverter.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestObjectConverter.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.TestPlatform.CommunicationUtilities/JsonDataSerializer.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.TestPlatform.CommunicationUtilities/JsonDataSerializer.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 81 out of 81 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (11)
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionRequestHandlerTests.cs:1
AfterTestRunEndpayload is wire-formatted as a JSON boolean in the new serialization tests (e.g.,AfterTestRunEndSerializationTestsexpectsfalse, not"false"). UsingSerializeToElement("false")produces a JSON string and can breakDeserializePayload<bool>behavior or mask mismatches; switch this toJsonSerializer.SerializeToElement(false)to match the protocol payload type.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/StopTestSessionSerializationTests.cs:1- These tests are ignored because STJ cannot populate
TestSessionInfo.Id(private setter), which likely reflects a real runtime incompatibility forStopTestSessionpayloads. Instead of ignoring, address deserialization by adding an explicit STJ solution (e.g., a customJsonConverter<TestSessionInfo>that readsIdand sets it via reflection, or adjusting the model to be STJ-deserializable via a[JsonConstructor]/[JsonInclude]-compatible approach). Keeping these ignored reduces confidence that stop-session flows work cross-process.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/StopTestSessionSerializationTests.cs:1 - These tests are ignored because STJ cannot populate
TestSessionInfo.Id(private setter), which likely reflects a real runtime incompatibility forStopTestSessionpayloads. Instead of ignoring, address deserialization by adding an explicit STJ solution (e.g., a customJsonConverter<TestSessionInfo>that readsIdand sets it via reflection, or adjusting the model to be STJ-deserializable via a[JsonConstructor]/[JsonInclude]-compatible approach). Keeping these ignored reduces confidence that stop-session flows work cross-process.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/StopTestSessionSerializationTests.cs:1 - These tests are ignored because STJ cannot populate
TestSessionInfo.Id(private setter), which likely reflects a real runtime incompatibility forStopTestSessionpayloads. Instead of ignoring, address deserialization by adding an explicit STJ solution (e.g., a customJsonConverter<TestSessionInfo>that readsIdand sets it via reflection, or adjusting the model to be STJ-deserializable via a[JsonConstructor]/[JsonInclude]-compatible approach). Keeping these ignored reduces confidence that stop-session flows work cross-process.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/AttachDebuggerSerializationTests.cs:1 - The ignored tests indicate STJ cannot deserialize
TestProcessAttachDebuggerPayloaddue to constructor parameter name mismatch (pidvsProcessID). This is typically fixable via a STJ-friendly constructor binding (e.g., renaming the parameter to match the JSON property, or annotating the constructor/parameter with STJ metadata such as[JsonConstructor]and[JsonPropertyName("ProcessID")], or providing a custom converter). Leaving this ignored risks breaking theAttachDebuggermessage handling at runtime.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/AttachDebuggerSerializationTests.cs:1 - The ignored tests indicate STJ cannot deserialize
TestProcessAttachDebuggerPayloaddue to constructor parameter name mismatch (pidvsProcessID). This is typically fixable via a STJ-friendly constructor binding (e.g., renaming the parameter to match the JSON property, or annotating the constructor/parameter with STJ metadata such as[JsonConstructor]and[JsonPropertyName("ProcessID")], or providing a custom converter). Leaving this ignored risks breaking theAttachDebuggermessage handling at runtime.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/AttachDebuggerSerializationTests.cs:1 - The ignored tests indicate STJ cannot deserialize
TestProcessAttachDebuggerPayloaddue to constructor parameter name mismatch (pidvsProcessID). This is typically fixable via a STJ-friendly constructor binding (e.g., renaming the parameter to match the JSON property, or annotating the constructor/parameter with STJ metadata such as[JsonConstructor]and[JsonPropertyName("ProcessID")], or providing a custom converter). Leaving this ignored risks breaking theAttachDebuggermessage handling at runtime.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionTestCaseEventHandlerTests.cs:1 JsonDocument.Parse(...)returns anIDisposabledocument, but it’s not disposed here. Wrap the parse in ausing var(and then clone the root element) to avoid leaking unmanaged buffers in the test process, especially since this pattern may repeat across tests.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1- The updated comment describes the expected post-deserialization object graph (
InfiniteReference.InfiniteReference = null), but the test no longer asserts that behavior (it only asserts the type). Add an assertion that matches the new expected structure so the test continues to validate the cycle-handling behavior rather than only “doesn’t throw”.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1 - The interpolated raw string literal uses 4
$plus{{{{version}}}}, which is hard to read and easy to get wrong when editing. Consider switching to a simpler construction (standard interpolation with escaped quotes, or a helper that builds expected JSON) to reduce brittleness and improve maintainability of these tests.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/VersionCheckSerializationTests.cs:1 - Normalizing by parsing and re-serializing can hide wire-format differences that are relevant for cross-version compatibility (notably escaping behavior like
\u003Cvs<, and any serializer-specific formatting quirks). If these are meant to be strict wire-format tests, consider comparing against a compact “golden” expected string directly (store the compact string instead of pretty JSON), or add targeted assertions for escaping/formatting that must match across serializers.
src/package/Microsoft.TestPlatform.CLI/Microsoft.TestPlatform.CLI.csproj
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 96 out of 96 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (6)
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestSessionInfoConverter.cs:1
Guid.NewGuid()as a fallback when"Id"is missing/null changes semantics and can break protocol expectations (missingIdshould not silently become a new unique session). Prefer preserving the default value (typicallyGuid.Empty) or treating missingIdas invalid/null rather than generating a new identifier.
src/package/Microsoft.TestPlatform.CLI/Microsoft.TestPlatform.CLI.csproj:1- The MSBuild condition compares against the literal string
NetFrameworkRunnerTargetFrameworkinstead of the property value. This will evaluate incorrectly and can cause the package references (and associated copy logic) to apply in unintended TFMs. Use$(NetFrameworkRunnerTargetFramework)in the condition, and ensure theSystemTextJsoninclude/copy logic is guarded by the same condition to avoid unresolved$(PkgSystem_Text_Json)paths in TFMs where the package isn’t referenced.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.UnitTests.csproj:1 - This introduces a hard-coded Newtonsoft.Json version while the repo already centralizes versions in
eng/Versions.props. To prevent version drift, reference$(NewtonsoftJsonVersion)here instead of a literal.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionTestCaseEventHandlerTests.cs:1 - This test constructs
Message.Payloadvia serialize → parse → clone, which is comparatively expensive and (in this test) likely unnecessary because deserialization is mocked. PreferJsonSerializer.SerializeToElement(...)(or even a minimalJsonDocument.Parse("{}")payload) unless the handler under test actually depends on the exact serialized shape.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1 - The comment directly above indicates a specific expected post-deserialization shape for cyclic references under STJ, but the assertion verifying that behavior was removed. This reduces coverage for an important behavior change between Newtonsoft vs STJ (and between protocol versions). Add an assertion that validates the expected cyclical-reference outcome (e.g.,
InfiniteReferenceexistence and/or its nested reference beingnull) so regressions are caught.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1 - The comment directly above indicates a specific expected post-deserialization shape for cyclic references under STJ, but the assertion verifying that behavior was removed. This reduces coverage for an important behavior change between Newtonsoft vs STJ (and between protocol versions). Add an assertion that validates the expected cyclical-reference outcome (e.g.,
InfiniteReferenceexistence and/or its nested reference beingnull) so regressions are caught.
src/Microsoft.TestPlatform.CommunicationUtilities/Messages/Message.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 119 out of 119 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (4)
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1
- This test’s assertions depend on the ambient
VSTEST_USE_NEWTONSOFT_JSON_SERIALIZERenvironment variable, which can make test results vary across machines/CI agents. To keep the unit test deterministic, set/unset the env var within the test (and restore the previous value in atry/finally) to explicitly cover both code paths.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1 - This test now documents a specific expected shape for the deserialized object (nested
InfiniteReferencebecomesnull), but it no longer asserts that behavior. Please add an assertion that validates the expected object graph (e.g., thatresult.InfiniteReferenceis non-null andresult.InfiniteReference.InfiniteReferenceis null), so the behavior is actually covered.
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestResultConverterV2.cs:1 - Parsing
Duration/StartTime/EndTimeusingCultureInfo.CurrentCulturemakes deserialization dependent on the executing machine’s culture, but these values are produced in a culture-invariant wire format (TimeSpan 'c' / DateTimeOffset ISO). UseCultureInfo.InvariantCulture(orRoundtripKindwhere applicable) to keep protocol parsing deterministic and avoid culture-specific failures.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/VersionCheckSerializationTests.cs:1 - Many of the new wire-format test classes repeat the same
AssertJsonEqual/Minifyhelpers. Consider extracting these into a shared internal test utility (e.g.,SerializationTestHelpers) to reduce duplication and keep future updates (like normalization options) consistent. This is optional but will make the suite easier to maintain.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 123 out of 123 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (4)
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestSessionInfoConverter.cs:1
- Falling back to
Guid.NewGuid()makes deserialization nondeterministic whenIdis missing/null, which can cause hard-to-reproduce behavior and flaky tests. Prefer a deterministic fallback (e.g.,Guid.Empty) or treat missingIdas invalid input and throw aJsonException.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1 - This test no longer asserts the expected post-deserialization shape of the self-referencing loop (the comment describes a specific structure, but the assertions only check the type). Add assertions that validate the intended STJ behavior (e.g., that
InfiniteReferenceexists and that its nested reference is null), so the test continues to protect against regressions.
test/Microsoft.TestPlatform.ObjectModel.UnitTests/Client/DiscoveryCriteriaTests.cs:1 - Comparing raw JSON strings makes this test brittle because STJ may legitimately change formatting/escaping or property ordering across runtimes/options. Prefer structural JSON comparison (parse both and compare normalized forms) or assert on the specific properties you care about.
src/package/Microsoft.TestPlatform.CLI/Microsoft.TestPlatform.CLI.csproj:1 - The MSBuild condition compares
$(TargetFramework)to the literal stringNetFrameworkRunnerTargetFramework, so it will almost always evaluate to true and include the package unexpectedly. If the intent is to compare against the property value, useCondition=\"'$(TargetFramework)' != '$(NetFrameworkRunnerTargetFramework)'\"(or the correct property name used in this repo).
samples/Microsoft.TestPlatform.Protocol/Communication/JsonDataSerializer.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 144 out of 145 changed files in this pull request and generated 2 comments.
Files not reviewed (1)
- src/Microsoft.TestPlatform.CommunicationUtilities/Resources/Resources.Designer.cs: Language not supported
Comments suppressed due to low confidence (7)
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestSessionInfoConverter.cs:1
- When the JSON omits Id (or has null), the converter generates a new Guid, making deserialization non-deterministic and potentially changing semantics (e.g., a missing Id should not silently become a brand-new session identifier). Prefer preserving the previous behavior (commonly Guid.Empty) or treating missing Id as an invalid payload (throw) depending on protocol expectations.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1 - StringBuilder is mutated from the Process error-data callback and read from other threads without synchronization. This can lead to data races and undefined behavior. Add a lock around both appends and reads (or switch to a thread-safe buffering strategy). Also consider capping the captured output size to prevent unbounded memory growth when a child process is noisy.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1 - StringBuilder is mutated from the Process error-data callback and read from other threads without synchronization. This can lead to data races and undefined behavior. Add a lock around both appends and reads (or switch to a thread-safe buffering strategy). Also consider capping the captured output size to prevent unbounded memory growth when a child process is noisy.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1 - StringBuilder is mutated from the Process error-data callback and read from other threads without synchronization. This can lead to data races and undefined behavior. Add a lock around both appends and reads (or switch to a thread-safe buffering strategy). Also consider capping the captured output size to prevent unbounded memory growth when a child process is noisy.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1 - These unit test expectations depend on an external environment variable, which can make test runs non-deterministic across machines/CI jobs. Set/clear the environment variable within the test (and restore the prior value) to explicitly test both code paths, or restructure the serializer to allow injecting the mode in tests without relying on ambient process state.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.UnitTests.csproj:1 - This hard-codes the Newtonsoft.Json version in the test csproj, which can drift from the repo’s central version management (e.g., eng/Versions.props). Consider using $(NewtonsoftJsonVersion) (and optionally PrivateAssets="All") so updates remain centralized and consistent.
test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/EventHandlers/TestRequestHandlerTests.cs:1 - This silently serializes a null payload whenever RawMessage is not set, which can hide mistakes in test setup and produce wire data that doesn’t match the intended message. Consider failing fast (e.g., Assert/throw) when RawMessage is unexpectedly null, or adjust the helper to require callers to provide the payload explicitly so the emitted JSON matches the constructed message semantics.
samples/Microsoft.TestPlatform.Protocol/Microsoft.TestPlatform.Protocol.csproj
Outdated
Show resolved
Hide resolved
src/Microsoft.TestPlatform.CommunicationUtilities/Resources/Resources.resx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 145 out of 146 changed files in this pull request and generated 3 comments.
Files not reviewed (1)
- src/Microsoft.TestPlatform.CommunicationUtilities/Resources/Resources.Designer.cs: Language not supported
Comments suppressed due to low confidence (7)
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestSessionInfoConverter.cs:1
- Generating a new Guid when
Idis missing changes semantics and makes deserialization non-deterministic. Prefer preserving the default (e.g., Guid.Empty) or leaving the property unset when the wire payload has noId.
test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/EventHandlers/TestRequestHandlerTests.cs:1 - This fallback path silently serializes a null payload when
RawMessageis missing, which can make tests send an invalid/incorrect wire message without failing. Consider failing fast (throw/assert) whenRawMessageis null in this helper, or restructure tests to always send explicit raw JSON so payload correctness is preserved.
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestPropertyConverter.cs:1 - Calling
Type.GetTypeon a string coming from the wire can trigger unintended type/assembly resolution. Since this is cross-process input, consider restrictingValueTypeto a safe allow-list (or mapping known type names) instead of usingType.GetTypedirectly.
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestResultConverterV2.cs:1 - These values are written in an invariant ISO/constant format by the serializer, but are parsed using
CurrentCulture. This can cause culture-specific parsing bugs. PreferCultureInfo.InvariantCulture(orParseExactwhere feasible) to make the wire format culture-independent.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1 IProcessManagerexposesProcessId/ExitCodeas get-only, but the implementation exposes public setters. To keep these values authoritative and avoid accidental mutation by consumers, consider making settersprivate(or at least internal) and updating them only fromStartProcess/exit handlers.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1- This test’s expectations vary based on an external environment variable, which makes it harder to ensure both code paths stay correct. Prefer explicitly setting/unsetting the variable within the test (and restoring it in a finally block), and assert both behaviors deterministically. Also consider using the
FeatureFlag.VSTEST_USE_NEWTONSOFT_JSON_SERIALIZERconstant to avoid string drift.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.UnitTests.csproj:1 - This hard-codes the Newtonsoft.Json version instead of using the repo property (e.g.,
$(NewtonsoftJsonVersion)), which can drift over time. Consider referencing the shared version property for consistency with the rest of the repo.
src/Microsoft.TestPlatform.CommunicationUtilities/Resources/xlf/Resources.de.xlf
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 150 out of 151 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- src/Microsoft.TestPlatform.CommunicationUtilities/Resources/Resources.Designer.cs: Language not supported
Comments suppressed due to low confidence (12)
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1
- StringBuilder is not thread-safe. Process_ErrorDataReceived can be raised on a different thread while ErrorOutput is being read (e.g., during timeout error reporting), which can cause torn reads or exceptions. Protect _vstestConsoleError with a lock, or replace it with a thread-safe buffer (e.g., ConcurrentQueue + string.Join) and consider capping stored output to prevent unbounded memory growth.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1 - StringBuilder is not thread-safe. Process_ErrorDataReceived can be raised on a different thread while ErrorOutput is being read (e.g., during timeout error reporting), which can cause torn reads or exceptions. Protect _vstestConsoleError with a lock, or replace it with a thread-safe buffer (e.g., ConcurrentQueue + string.Join) and consider capping stored output to prevent unbounded memory growth.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1 - StringBuilder is not thread-safe. Process_ErrorDataReceived can be raised on a different thread while ErrorOutput is being read (e.g., during timeout error reporting), which can cause torn reads or exceptions. Protect _vstestConsoleError with a lock, or replace it with a thread-safe buffer (e.g., ConcurrentQueue + string.Join) and consider capping stored output to prevent unbounded memory growth.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleWrapper.cs:1 - Including full childProcessErrorOutput in the thrown exception can be extremely large and may contain sensitive data (paths, environment hints, etc.), which can bloat logs/telemetry. Consider truncating error output to a bounded size (e.g., last N KB/lines) and/or stripping ANSI control characters before embedding it in the exception message.
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestSessionInfoConverter.cs:1 - Generating a new Guid when Id is missing/nullable changes semantics during deserialization (the same JSON can produce different objects across runs). Prefer a deterministic default (e.g., Guid.Empty) or treat missing Id as invalid and fail, depending on the protocol expectations.
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestCaseConverter.cs:1 - TestCase.ExecutorUri can be null (the v2 converter already accounts for this via ?.OriginalString). This v1 converter will throw NullReferenceException during serialization if ExecutorUri is unset. Write a null value (or empty string if the wire format requires it) when ExecutorUri is null.
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestResultConverterV2.cs:1 - These values are wire-format data and should be parsed culture-invariantly. Using CultureInfo.CurrentCulture introduces locale-dependent failures (especially for DateTimeOffset and potentially TimeSpan formats). Parse with CultureInfo.InvariantCulture and, ideally, round-trip formats consistent with how STJ writes these values.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1 - This test documents expected cycle-handling behavior but no longer asserts it. Add assertions that match the stated expectation (e.g., verify InfiniteReference is not null and InfiniteReference.InfiniteReference is null), so regressions in reference-handling don't silently pass.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.UnitTests.csproj:1 - This hard-codes Newtonsoft.Json version instead of using the repo’s version properties (e.g., $(NewtonsoftJsonVersion)). Using the central version property reduces drift when the dependency is updated.
test/Microsoft.TestPlatform.TestUtilities/IntegrationTestBuild.cs:1 - This JSON is used as a build cache/checksum identifier. System.Text.Json does not guarantee deterministic property ordering across all dictionary implementations/TFMs, which can cause spurious checksum changes and unnecessary rebuilds. Consider normalizing output (e.g., serialize via a JsonDocument/JsonNode with sorted properties, or use a deterministic representation) before writing checksum.json.
src/testhost.x86/app.config:1 - The System.Text.Json bindingRedirect newVersion (10.0.0.0) conflicts with the comment stating netframework uses an exact assembly version (and you keep the oldVersion range up to 10.0.0.5). If the shipped System.Text.Json assembly has version 10.0.0.5, redirecting to 10.0.0.0 can cause assembly load failures. Align the redirect target with the actual AssemblyVersion of the shipped DLL (or change what you ship) and keep System.Text.Json and System.Text.Encodings.Web consistent.
src/testhost.x86/app.config:1 - The System.Text.Json bindingRedirect newVersion (10.0.0.0) conflicts with the comment stating netframework uses an exact assembly version (and you keep the oldVersion range up to 10.0.0.5). If the shipped System.Text.Json assembly has version 10.0.0.5, redirecting to 10.0.0.0 can cause assembly load failures. Align the redirect target with the actual AssemblyVersion of the shipped DLL (or change what you ship) and keep System.Text.Json and System.Text.Encodings.Web consistent.
src/Microsoft.TestPlatform.CommunicationUtilities/Messages/Message.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 157 out of 158 changed files in this pull request and generated 5 comments.
Files not reviewed (1)
- src/Microsoft.TestPlatform.CommunicationUtilities/Resources/Resources.Designer.cs: Language not supported
Comments suppressed due to low confidence (9)
src/testhost.x86/app.config:1
- The comment indicates .NET Framework needs an “exact version” redirect, but the active redirect targets
10.0.0.0while the range ends at10.0.0.5. This mismatch can cause runtime binding failures depending on the shipped assembly version. Align thenewVersionwith the actualAssemblyVersionof theSystem.Text.Json.dllyou ship for netfx, and keep the comment consistent with the chosen redirect strategy.
src/testhost.x86/app.config:1 - The comment indicates .NET Framework needs an “exact version” redirect, but the active redirect targets
10.0.0.0while the range ends at10.0.0.5. This mismatch can cause runtime binding failures depending on the shipped assembly version. Align thenewVersionwith the actualAssemblyVersionof theSystem.Text.Json.dllyou ship for netfx, and keep the comment consistent with the chosen redirect strategy.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1 _vstestConsoleErrorgrows unbounded for the lifetime of the process manager, which can lead to high memory usage on noisy stderr (especially for long-running sessions). Consider bounding this buffer (e.g., keep last N KB/lines) and/or truncating when composing exceptions so diagnostics remain useful without risking memory pressure.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1_vstestConsoleErrorgrows unbounded for the lifetime of the process manager, which can lead to high memory usage on noisy stderr (especially for long-running sessions). Consider bounding this buffer (e.g., keep last N KB/lines) and/or truncating when composing exceptions so diagnostics remain useful without risking memory pressure.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1_vstestConsoleErrorgrows unbounded for the lifetime of the process manager, which can lead to high memory usage on noisy stderr (especially for long-running sessions). Consider bounding this buffer (e.g., keep last N KB/lines) and/or truncating when composing exceptions so diagnostics remain useful without risking memory pressure.
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestSessionInfoConverter.cs:1- Generating a new GUID when
Idis missing makes deserialization nondeterministic and can silently change semantics (a missing/invalidIdbecomes a brand-new session identity). Prefer preserving the default (Guid.Empty) or failing fast (throw) whenIdis missing/invalid, depending on expected contract, to avoid masking malformed payloads.
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/ObjectConverter.cs:1 - This converter auto-coerces JSON strings into
DateTimeOffsetwhen parseable. That can break consumers that expect the original JSON type to remain a string (and also contradicts the comment about “IConvertible/primitives” —DateTimeOffsetis not a primitive and may not be handled the same way downstream). Consider always returningstringforJsonTokenType.String(or making DateTime parsing opt-in via options) to avoid surprising type changes inIDictionary<string, object>payloads.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1 - This test no longer asserts the expected post-deserialization shape of the self-referencing loop (the previous assertion was removed, and the new comment suggests a specific structure). Add a concrete assertion that validates the intended behavior (e.g.,
result.InfiniteReferenceis non-null andresult.InfiniteReference.InfiniteReferenceis null, or whatever the correct expected structure is) so the test actually guards the cycle-handling contract.
test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/EventHandlers/TestRequestHandlerTests.cs:1 - When
RawMessageis null, this helper serializes a payload ofnulland ignoresmessage.Versionand any intended payload content. That can produce incorrect wire data for tests that constructMessageobjects withoutRawMessage. Consider either (1) requiringRawMessageto be set for all test messages and throwing/asserting when it’s missing, or (2) extending the helper to construct raw JSON using the intended protocol version and payload source(s).
src/Microsoft.TestPlatform.CommunicationUtilities/PublicAPI/PublicAPI.Unshipped.txt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 157 out of 158 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- src/Microsoft.TestPlatform.CommunicationUtilities/Resources/Resources.Designer.cs: Language not supported
Comments suppressed due to low confidence (9)
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestSessionInfoConverter.cs:1
- Generating a new GUID when
Idis absent makes deserialization nondeterministic and can silently change semantics (e.g., a missing/invalid payload becomes a new session). PreferGuid.Empty(or leaving the defaultTestSessionInfovalue) and consider treating missingIdas invalid input if the protocol expects it.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1 Process_ErrorDataReceivedcan run on a different thread than callers ofErrorOutput;StringBuilderis not thread-safe. Protect_vstestConsoleErrorwith a lock (or swap to a thread-safe buffer likeConcurrentQueue<string>and join on read) to avoid races/corruption.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1Process_ErrorDataReceivedcan run on a different thread than callers ofErrorOutput;StringBuilderis not thread-safe. Protect_vstestConsoleErrorwith a lock (or swap to a thread-safe buffer likeConcurrentQueue<string>and join on read) to avoid races/corruption.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1Process_ErrorDataReceivedcan run on a different thread than callers ofErrorOutput;StringBuilderis not thread-safe. Protect_vstestConsoleErrorwith a lock (or swap to a thread-safe buffer likeConcurrentQueue<string>and join on read) to avoid races/corruption.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleWrapper.cs:1- Including full stderr (
childProcessErrorOutput) in an exception can create very large exception messages and may leak sensitive data into logs/telemetry. Consider truncating to a reasonable size (e.g., last N KB/lines) and/or stripping control characters before formatting.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleWrapper.cs:1 - Including full stderr (
childProcessErrorOutput) in an exception can create very large exception messages and may leak sensitive data into logs/telemetry. Consider truncating to a reasonable size (e.g., last N KB/lines) and/or stripping control characters before formatting.
src/testhost.x86/app.config:1 - The comment states you ship the .NET Framework STJ assembly and therefore need an exact version redirect, but the active redirect uses
newVersion=\"10.0.0.0\"(and the exact redirect is commented out). Please align the comment and the actual binding redirect strategy (and ensurenewVersionmatches the assembly version you ship).
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1 - This test now documents a specific expected post-deserialization shape for cyclic references, but it no longer asserts it. Please add assertions that validate the new behavior (e.g.,
result.InfiniteReferenceexists andresult.InfiniteReference.InfiniteReferenceis null), otherwise regressions in cycle handling won’t be caught.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/VersionCheckSerializationTests.cs:1 - The new serialization test files duplicate the same
AssertJsonEqual/Minifyhelpers (and related docstrings). To reduce maintenance cost and keep behavior consistent across message tests, consider extracting these helpers into a shared internal test utility (e.g.,SerializationTestHelpers) and reusing it.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 157 out of 158 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- src/Microsoft.TestPlatform.CommunicationUtilities/Resources/Resources.Designer.cs: Language not supported
Comments suppressed due to low confidence (8)
src/testhost.x86/app.config:1
- The comment says the netframework build ships the .NET Framework version of
System.Text.Jsonand needs an exact redirect, but the active redirect targets10.0.0.0whileSystem.Text.Encodings.Webtargets10.0.0.5. If the shippedSystem.Text.Json.dllhas an assembly version ending in.5, redirecting to.0can cause binding failures at runtime. Align theSystem.Text.JsonredirectnewVersionwith the assembly version you actually ship for net462/net48 (and keep this consistent with the Encodings.Web redirect).
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestSessionInfoConverter.cs:1 - Generating a new random
GuidwhenIdis missing makes deserialization non-deterministic and can silently invent a session ID that never existed on the sender side. Prefer a deterministic default (e.g.,Guid.Empty) or treat a missingIdas invalid input and fail fast, depending on protocol expectations.
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestResultConverterV2.cs:1 - These values are on-the-wire protocol fields and are serialized in an invariant format (e.g., ISO 8601 / constant
TimeSpanformat). Parsing withCultureInfo.CurrentCulturecan break on machines with non-default cultures. UseCultureInfo.InvariantCulture(orDateTimeStyles.RoundtripKind/round-trip parsing patterns) to ensure protocol correctness across locales.
test/Microsoft.TestPlatform.ObjectModel.UnitTests/Client/DiscoveryCriteriaTests.cs:1 - This test compares raw JSON strings, which is brittle because property ordering/escaping can differ between runtimes and serializers even when the JSON is semantically equivalent. To keep this test stable, compare normalized JSON (parse both to
JsonDocumentand re-serialize) or compare the deserialized object graph instead of exact string equality.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1 - The test name/comment indicates a specific expected shape after round-trip (e.g.,
InfiniteReferencenot null and its nested reference null), but the assertions no longer validate that behavior. Add targeted assertions so this test actually guards the intended IgnoreCycles contract for both serialization and deserialization.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1 - Capturing all stderr into an unbounded
StringBuildercan lead to high memory usage (or OOM) if the child process is noisy over long runs. Consider capping the stored error output (e.g., keep only the last N KB/lines) since it’s primarily used for diagnostics on startup/connection failures.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1 - Capturing all stderr into an unbounded
StringBuildercan lead to high memory usage (or OOM) if the child process is noisy over long runs. Consider capping the stored error output (e.g., keep only the last N KB/lines) since it’s primarily used for diagnostics on startup/connection failures.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Microsoft.TestPlatform.CommunicationUtilities.UnitTests.csproj:1 - This introduces a hard-coded Newtonsoft.Json version in a repo that already centralizes versions via properties (e.g.,
$(NewtonsoftJsonVersion)). Consider switching to the shared property for consistency and easier upgrades.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 157 out of 158 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- src/Microsoft.TestPlatform.CommunicationUtilities/Resources/Resources.Designer.cs: Language not supported
Comments suppressed due to low confidence (9)
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleWrapper.cs:1
- The thrown message always uses
ConnectionTimeoutWithErrorMessage(“process … exited with exitCode …”), but timeouts can occur while the child process is still running (ExitCode remains-1). Consider choosing betweenConnectionTimeoutErrorMessage(still running) vsConnectionTimeoutWithErrorMessage(exited) based on actual process state/exit, and only include exit-code/error-output details when the process has exited or there is captured stderr.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1 StringBuilderis not thread-safe;Process.ErrorDataReceivedcan be raised on background threads while other code readsErrorOutput(which calls_vstestConsoleError.ToString()). Add synchronization (e.g., a private lock around append/read) or store stderr lines in a thread-safe collection to avoid data races and potentialStringBuilderstate corruption.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1StringBuilderis not thread-safe;Process.ErrorDataReceivedcan be raised on background threads while other code readsErrorOutput(which calls_vstestConsoleError.ToString()). Add synchronization (e.g., a private lock around append/read) or store stderr lines in a thread-safe collection to avoid data races and potentialStringBuilderstate corruption.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1- This test’s assertions now depend on an external environment variable, making the test outcome non-deterministic across machines/CI agents. Prefer setting/unsetting the variable inside the test (and restoring it), or better: drive the serializer selection via an injectable/configurable option in the test so both paths can be tested deterministically.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1 - The comment states an expected shape for cyclic references under STJ (
InfiniteReference.InfiniteReference = null), but the test no longer asserts that behavior. Add an assertion that validates the expected post-deserialization object graph so regressions in reference-loop handling are caught.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1 - The comment states an expected shape for cyclic references under STJ (
InfiniteReference.InfiniteReference = null), but the test no longer asserts that behavior. Add an assertion that validates the expected post-deserialization object graph so regressions in reference-loop handling are caught.
test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/EventHandlers/TestRequestHandlerTests.cs:1 - Falling back to
SerializePayload(message.MessageType, null)changes semantics vs the previousSerializePayload(message.MessageType, message.Payload)and can emit"Payload":nullwhen the intended wire format is a header-only message (or a message with a real payload). Consider using a dedicated “serialize message without payload” API (if available) or ensure tests always provideRawMessagefor messages that require payload, and include the correctVersionin the envelope when serializing.
test/Microsoft.TestPlatform.TestUtilities/IntegrationTestBuild.cs:1 - If
cacheIdis a dictionary-based object graph, STJ property ordering can differ (across runtimes/frameworks or due to dictionary enumeration), potentially causing nondeterministicchecksum.jsoncontent and unnecessary rebuilds. Consider producing a canonical JSON (e.g., write properties in sorted order or use a sorted dictionary/tree) before comparing/writing the checksum.
src/testhost.x86/app.config:1 - The comment says the testhost ships the .NET Framework STJ assembly and needs a redirect to the exact version, but the active redirect targets
10.0.0.0while the “exact version” redirect (10.0.0.5) is commented out. Either update the comment to match the intended “downgrade to major-only version” behavior, or change the redirect to the exact assembly version you actually ship to avoid confusing future maintenance and potential load issues.
src/Microsoft.TestPlatform.CommunicationUtilities/PublicAPI/PublicAPI.Shipped.txt
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 156 out of 157 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- src/Microsoft.TestPlatform.CommunicationUtilities/Resources/Resources.Designer.cs: Language not supported
Comments suppressed due to low confidence (8)
src/testhost.x86/app.config:1
- The comment says .NET Framework needs an exact-version redirect, but the active
bindingRedirectredirects to10.0.0.0while the commented line suggests10.0.0.5. If the shippedSystem.Text.Json.dllhas assembly version10.0.0.5, redirecting to10.0.0.0can cause load failures. AlignnewVersionwith the actual shipped assembly version (and keep the comment consistent with the chosen approach).
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1 Process.ErrorDataReceivedcallbacks can arrive on background threads; appending to a sharedStringBuilderwithout synchronization is not thread-safe. Protect_vstestConsoleErrorwith a lock (or switch to a thread-safe buffer such asConcurrentQueue<string>and join on read) to avoid memory corruption/races.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs:1Process.ErrorDataReceivedcallbacks can arrive on background threads; appending to a sharedStringBuilderwithout synchronization is not thread-safe. Protect_vstestConsoleErrorwith a lock (or switch to a thread-safe buffer such asConcurrentQueue<string>and join on read) to avoid memory corruption/races.
src/Microsoft.TestPlatform.CommunicationUtilities/Serialization/TestResultConverterV2.cs:1- Parsing wire-format
Duration/StartTime/EndTimeusingCultureInfo.CurrentCulturemakes deserialization culture-dependent and can break on machines with non-invariant cultures. UseCultureInfo.InvariantCulture(and forDateTimeOffset, prefer round-trip parsing such asDateTimeStyles.RoundtripKind) to reliably parse protocol JSON.
src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs:1 x.GetString()!will throw or produce anArgumentNullExceptioninPath.Combineif an element isnull/non-string inadditionalProbingPaths. Prefer reading the string once into a local, andcontinuewhen it’s null/empty, to avoid crashing when the runtimeconfig contains unexpected values.
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/JsonDataSerializerTests.cs:1- This test documents a new expected behavior (cycle becomes
null), but it no longer asserts it. Add an assertion that verifies the expected structure (e.g.,result.InfiniteReferenceis not null andresult.InfiniteReference.InfiniteReferenceis null), so the behavior change is actually guarded by the test.
src/Microsoft.TestPlatform.CommunicationUtilities/Resources/xlf/Resources.zh-Hans.xlf:1 - The new
ConnectionTimeoutWithErrorMessageresource is added with<target state=\"new\">containing the English source text. If this ships, localized builds will show English for this string. Either provide translations (or mark it as untranslated intentionally and ensure that’s acceptable for the release).
test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/VersionCheckSerializationTests.cs:1 AssertJsonEqual/Minifyhelpers are duplicated across many of the new wire-format test files in this PR. Consider centralizing them in a shared test helper (e.g., aSerializationTestUtils) to reduce duplication and ensure consistent normalization behavior across message tests.
Replace raw JsonDocument.Parse/Jsonite.Parse with actual production code: JsonDataSerializer.Instance.SerializePayload/DeserializeMessage/ DeserializePayload. These test what actually runs in vstest, including our custom converters and options. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…onite VerifySerializerName test proves that even on net10.0, the production code path uses Jsonite (not STJ) because CommunicationUtilities only compiles for net462;netstandard2.0 — NETCOREAPP is never defined. All #if NETCOREAPP conditionals in this project are dead code. The STJ converters are compiled but never used. To fix: add net8.0 or net10.0 to CommunicationUtilities TargetFrameworks so NETCOREAPP is defined and STJ code path is active on .NET Core. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Delete NewtonsoftReference/ folder and NewtonsoftFallbackTests.cs - Remove NewtonsoftComparison methods from all 23 serialization test files - Remove Regression performance tests (compared with Newtonsoft) - Make TestCaseConverter, TestObjectConverter, TestResultConverter internal - Add net8.0 PublicAPI files for new TFM - Keep Newtonsoft.Json PackageReference (still used for JToken normalization) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Tests JsonDataSerializer.Instance (production path) against NewtonsoftJsonDataSerializer for every MessageType on v1 and v7: - SerializePayload, DeserializeMessage, DeserializePayload roundtrip - SerializeMessage (no payload) - Performance comparison (must be on-par or faster) - VerifySerializerName (STJ on .NET Core, Jsonite on .NET Framework) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Performance_RoundTrip_TestMessage and Performance_RoundTrip_ExecutionComplete test full DeserializeMessage + DeserializePayload roundtrip against Newtonsoft baseline, asserting ratio <= 3x. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
All Newtonsoft comparison tests, helpers, and reference serializer moved to Serialization/Compatibility/ for easy future removal. Perf assertions show raw ms on failure instead of ratio. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix TestCaseConverterV2: use direct JsonElement instead of GetRawText() - Fix bare catch blocks in JsoniteConvert.cs: add EqtTrace.Warning logging - Pass version to JsoniteConvert.To<T>() in DeserializePayloadCore - Fix DiagnosticSource binding redirect version (8.0.0.1 -> 8.0.0.0) - Add serializer name diagnostic logging in JsonDataSerializer - Fix SerializerSelectionTests: enable diag, use correct runner data source, fix Assert.Contains parameter order Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MessageEnvelope and VersionedMessageEnvelope DTOs now use JsonIgnoreCondition.WhenWritingNull on the Payload property so that SerializeMessageCore produces correct wire format without Payload:null. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
STJ built-in dictionary converter deserializes JSON integers as double when value type is object, bypassing custom ObjectConverter. Add FixUpObjectDictionaries post-processing in DeserializePayloadCore that converts whole-number doubles back to int for known types with Metrics dictionaries (TestRunCompleteEventArgs, TestRunAttachmentsProcessing- CompleteEventArgs, AfterTestRunEndResult, DiscoveryCompletePayload). Also add ObjectDictionaryConverterFactory and improve ObjectConverter with TryGetInt32 for better numeric type preservation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
TestCaseEventArgs.TestCaseId, TestCaseName, IsChildTestCase, TestElement and TestCaseEndEventArgs.TestOutcome had private/internal setters that prevented STJ (and partially Jsonite) from populating them during deserialization. Changed to public setters. Added 26 serialization test files covering all 29 previously untested message types (1095 total serialization tests, all passing). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Wire Format Verification: main (Newtonsoft) vs STJ branchRan blame tests with Runner (vstest.console) — 8 message types
Testhost — 4 message types
Datacollector — 3 shared + 7 new
Property ordering detail
Same set, different dictionary iteration order. This is expected and does not affect deserialization since properties are identified by ConclusionZero structural or semantic wire format differences. The STJ migration produces identical JSON to Newtonsoft on the wire. |
Jsonite WriteString threw ArgumentException on control characters < 0x20 (e.g. \u0003 ETX, \u0001 SOH). Now escapes them as \uXXXX instead. Same fix as testfx#5120. Added round-trip edge case tests for: - Control characters (\u0001, \u0003) - Newlines and tabs (\n, \r\n, \t) - Unicode and emoji (CJK, accented chars, surrogate pairs) - Backslashes and quotes (Windows paths with escaped quotes) - Empty strings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Tests serialize/deserialize/round-trip a TestRunStatsChange payload with 1000 test results (900 passed, 100 failed with error messages). Each result has traits, code file path, and realistic property values. Observed perf (10 iterations of 1000-result batch): - STJ serialize: ~11ms avg, deserialize: ~60ms avg - Jsonite serialize: ~36ms avg, deserialize: ~96ms avg - JSON size: 911KB per batch Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixes symbol resolution issues. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…11.365" This reverts commit cd107fc.
|
Already built on main, we changed base. |
Summary
Migrate vstest JSON serialization from Newtonsoft.Json to System.Text.Json (on .NET Core) and Jsonite (on .NET Framework/netstandard2.0). Removes Newtonsoft.Json from all production code paths.
Architecture
#if NETCOREAPP#if !NETCOREAPP#if !NETCOREAPPKey Changes
#ifblocks in main filePayloadproperty, usesRawMessagestring + deferred deserializationDependencyContextJsonReaderon .NET Framework (eliminates transitive STJ dep)#if NETcompiler conditions in tests\uXXXXinstead of throwing (testfx#5120)doubleinIDictionary<string, object>(metrics)private set→setonTestCaseId,TestCaseName,IsChildTestCase,TestElement,TestOutcomefor serialization compatibilityTest Coverage
100% MessageType coverage — every single one of the 52 message types in
MessageTypeclass has serialization tests (V1 serialize, V7 serialize, V1 deserialize, V7 deserialize, round-trip).Wire Format Verification
Captured diag logs from blame test runs on both
main(Newtonsoft) andstj-migrationbranches. Parsed and compared all JSON messages from runner, testhost, and datacollector logs:Version,MessageType— ✅ Fast header parser compatiblePerformance: STJ vs Newtonsoft (1000-result batch, V7)
Performance: STJ vs Newtonsoft (single message, 1000 iterations)
Breaking Changes
Message.Payload(JToken?) removed — replaced byMessage.RawMessage(string?) +Message.VersionVersionedMessageclass removed — unified intoMessageTestCaseEventArgs.TestCaseId/TestCaseName/IsChildTestCase/TestElementsetters changed from private/internal to publicTestCaseEndEventArgs.TestOutcomesetter changed from private to publicCo-authored-by: Copilot 223556219+Copilot@users.noreply.github.com