Skip to content

Commit

Permalink
Remove Newtonsoft.Json dependency
Browse files Browse the repository at this point in the history
Instead, use System.Text.Json everywhere.

### JSON Configuration File

Since there's [no equivalent][1] to `MissingMemberHandling` with `System.Text.Json`, the error messages in case of erroneous keys in the JSON configuration file have been improved. For example, if you have a typo in the `enabled` key you would get this error:

> The allowed keys for the "stryker-config.since" object are { "enabled", "ignore-changes-in", "target" } but "enable" was found in the config file at "[…]/tests/stryker-config.json"

Those better error messages also required to have a `JsonPropertyName` attribute on _all_ the properties. This is probably a good thing anyway since it makes the code more _greppable_.

### Newtonsoft.Json transitive dependency

Unfortunately, `Newtonsoft.Json` is still there transitively (through Buildalyzer/3.2.2 → Microsoft.Extensions.DependencyModel/2.1.0 → Newtonsoft.Json/9.0.1) but there's nothing we can do about it for now, see microsoft/vstest#2488 (comment) for a full explanation.

[1]: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to#missingmemberhandling
  • Loading branch information
0xced committed Oct 1, 2021
1 parent 4adff65 commit 519fbc5
Show file tree
Hide file tree
Showing 21 changed files with 625 additions and 201 deletions.
4 changes: 2 additions & 2 deletions src/Stryker.CLI/Stryker.CLI.UnitTest/ConfigFileTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public void WithNoArgumentsAndNoConfigFile_ShouldStartStrykerWithConfigOptions()
var mock = new Mock<IStrykerRunner>(MockBehavior.Strict);
var options = new StrykerOptions()
{
Thresholds = new Thresholds()
Thresholds = new Stryker.Core.Options.Thresholds()
{
High = 80,
Low = 60,
Expand All @@ -45,7 +45,7 @@ public void WithConfigFile_ShouldStartStrykerWithConfigFileOptions(string argNam
{
IStrykerInputs actualInputs = null;
var options = new StrykerOptions() {
Thresholds = new Thresholds() {
Thresholds = new Stryker.Core.Options.Thresholds() {
High = 80,
Low = 60,
Break = 0
Expand Down
12 changes: 6 additions & 6 deletions src/Stryker.CLI/Stryker.CLI.UnitTest/StrykerCLITests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class StrykerCLITests

public StrykerCLITests()
{
_options = new StrykerOptions() { Thresholds = new Thresholds { Break = 0 } };
_options = new StrykerOptions() { Thresholds = new Stryker.Core.Options.Thresholds { Break = 0 } };
_runResults = new StrykerRunResult(_options, 0.3);
_strykerRunnerMock.Setup(x => x.RunMutationTest(It.IsAny<IStrykerInputs>(), It.IsAny<ILoggerFactory>(), It.IsAny<IProjectOrchestrator>()))
.Callback<IStrykerInputs, ILoggerFactory, IProjectOrchestrator>((c, l, p) => _inputs = c)
Expand Down Expand Up @@ -113,7 +113,7 @@ public void OnMutationScoreBelowThresholdBreak_ShouldReturn_ExitCodeBreakThresho
var mock = new Mock<IStrykerRunner>(MockBehavior.Strict);
var options = new StrykerOptions()
{
Thresholds = new Thresholds
Thresholds = new Stryker.Core.Options.Thresholds
{
Break = 40
}
Expand All @@ -124,7 +124,7 @@ public void OnMutationScoreBelowThresholdBreak_ShouldReturn_ExitCodeBreakThresho
.Callback<IStrykerInputs, ILoggerFactory, IProjectOrchestrator>((c, l, p) => Core.Logging.ApplicationLogging.LoggerFactory = l)
.Returns(strykerRunResult)
.Verifiable();

var target = new StrykerCli(mock.Object);
var result = target.Run(new string[] { });

Expand All @@ -139,7 +139,7 @@ public void OnMutationScoreEqualToNullAndThresholdBreakEqualTo0_ShouldReturnExit
var mock = new Mock<IStrykerRunner>(MockBehavior.Strict);
var options = new StrykerOptions()
{
Thresholds = new Thresholds
Thresholds = new Stryker.Core.Options.Thresholds
{
Break = 0
}
Expand All @@ -163,7 +163,7 @@ public void OnMutationScoreEqualToNullAndThresholdBreakAbove0_ShouldReturnExitCo
var mock = new Mock<IStrykerRunner>(MockBehavior.Strict);
var options = new StrykerOptions()
{
Thresholds = new Thresholds
Thresholds = new Stryker.Core.Options.Thresholds
{
Break = 40
}
Expand All @@ -187,7 +187,7 @@ public void OnMutationScoreAboveThresholdBreak_ShouldReturnExitCode0()
var mock = new Mock<IStrykerRunner>(MockBehavior.Strict);
var options = new StrykerOptions()
{
Thresholds = new Thresholds
Thresholds = new Stryker.Core.Options.Thresholds
{
Break = 0
}
Expand Down
58 changes: 55 additions & 3 deletions src/Stryker.CLI/Stryker.CLI.UnitTest/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -621,8 +621,32 @@
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.1",
"contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A=="
"resolved": "9.0.1",
"contentHash": "U82mHQSKaIk+lpSVCbWYKNavmNH1i5xrExDEquU1i6I5pV6UMOqRnJRSlKO3cMPfcpp0RgDY+8jUXHdQ4IfXvw==",
"dependencies": {
"Microsoft.CSharp": "4.0.1",
"System.Collections": "4.0.11",
"System.Diagnostics.Debug": "4.0.11",
"System.Dynamic.Runtime": "4.0.11",
"System.Globalization": "4.0.11",
"System.IO": "4.1.0",
"System.Linq": "4.1.0",
"System.Linq.Expressions": "4.1.0",
"System.ObjectModel": "4.0.12",
"System.Reflection": "4.1.0",
"System.Reflection.Extensions": "4.0.1",
"System.Resources.ResourceManager": "4.0.1",
"System.Runtime": "4.1.0",
"System.Runtime.Extensions": "4.1.0",
"System.Runtime.Serialization.Primitives": "4.1.1",
"System.Text.Encoding": "4.0.11",
"System.Text.Encoding.Extensions": "4.0.11",
"System.Text.RegularExpressions": "4.1.0",
"System.Threading": "4.0.11",
"System.Threading.Tasks": "4.0.11",
"System.Xml.ReaderWriter": "4.0.11",
"System.Xml.XDocument": "4.0.11"
}
},
"NuGet.Frameworks": {
"type": "Transitive",
Expand Down Expand Up @@ -1119,6 +1143,16 @@
"System.Security.Principal.Windows": "5.0.0"
}
},
"System.Diagnostics.Tools": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "xBfJ8pnd4C17dWaC9FM6aShzbJcRNMChUMD42I6772KGGrqaFdumwhn9OdM68erj1ueNo3xdQ1EwiFjK5k8p0g==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1",
"Microsoft.NETCore.Targets": "1.0.1",
"System.Runtime": "4.1.0"
}
},
"System.Diagnostics.TraceSource": {
"type": "Transitive",
"resolved": "4.3.0",
Expand Down Expand Up @@ -2041,6 +2075,25 @@
"System.Threading.Tasks.Extensions": "4.3.0"
}
},
"System.Xml.XDocument": {
"type": "Transitive",
"resolved": "4.0.11",
"contentHash": "Mk2mKmPi0nWaoiYeotq1dgeNK1fqWh61+EK+w4Wu8SWuTYLzpUnschb59bJtGywaPq7SmTuPf44wrXRwbIrukg==",
"dependencies": {
"System.Collections": "4.0.11",
"System.Diagnostics.Debug": "4.0.11",
"System.Diagnostics.Tools": "4.0.1",
"System.Globalization": "4.0.11",
"System.IO": "4.1.0",
"System.Reflection": "4.1.0",
"System.Resources.ResourceManager": "4.0.1",
"System.Runtime": "4.1.0",
"System.Runtime.Extensions": "4.1.0",
"System.Text.Encoding": "4.0.11",
"System.Threading": "4.0.11",
"System.Xml.ReaderWriter": "4.0.11"
}
},
"System.Xml.XmlDocument": {
"type": "Transitive",
"resolved": "4.3.0",
Expand Down Expand Up @@ -2130,7 +2183,6 @@
"Microsoft.TestPlatform.TranslationLayer": "16.10.0",
"Microsoft.Web.LibraryManager.Build": "2.1.113",
"Mono.Cecil": "0.11.4",
"Newtonsoft.Json": "13.0.1",
"Serilog": "2.10.0",
"Serilog.Extensions.Logging": "3.0.1",
"Serilog.Extensions.Logging.File": "2.0.0",
Expand Down
170 changes: 111 additions & 59 deletions src/Stryker.CLI/Stryker.CLI/FileBasedInput.cs
Original file line number Diff line number Diff line change
@@ -1,103 +1,155 @@
using Newtonsoft.Json;
using Stryker.Core.Options;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Stryker.CLI
{
public class FileBasedInputOuter
public interface IExtraData
{
[JsonProperty(PropertyName = "stryker-config")]
public FileBasedInput Input { get; set; }
Dictionary<string, JsonElement> ExtraData { get; init; }
}

public class FileBasedInput
public class FileBasedInputOuter : IExtraData
{
[JsonProperty(PropertyName = "project-info")]
public ProjectInfo ProjectInfo { get; set; }
[JsonPropertyName("stryker-config")]
public FileBasedInput Input { get; init; }

public int? Concurrency { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement> ExtraData { get; init; }
}

public class FileBasedInput : IExtraData
{
[JsonPropertyName("project-info")]
public ProjectInfo ProjectInfo { get; init; }

[JsonPropertyName("concurrency")]
public int? Concurrency { get; init; }

[JsonPropertyName("mutation-level")]
public string MutationLevel { get; init; }

[JsonPropertyName("language-version")]
public string LanguageVersion { get; init; }

[JsonPropertyName("additional-timeout")]
public int? AdditionalTimeout { get; init; }

[JsonPropertyName("mutate")]
public string[] Mutate { get; init; }

[JsonProperty(PropertyName = "mutation-level")]
public string MutationLevel { get; set; }
[JsonPropertyName("solution")]
public string Solution { get; init; }

[JsonProperty(PropertyName = "language-version")]
public string LanguageVersion { get; set; }
[JsonPropertyName("target-framework")]
public string TargetFramework { get; init; }

[JsonProperty(PropertyName = "additional-timeout")]
public int AdditionalTimeout { get; set; }
[JsonPropertyName("project")]
public string Project { get; init; }

public string[] Mutate { get; set; }
[JsonPropertyName("coverage-analysis")]
public string CoverageAnalysis { get; init; }

public string Solution { get; set; }
[JsonPropertyName("disable-bail")]
public bool? DisableBail { get; init; }

[JsonProperty(PropertyName = "target-framework")]
public string TargetFramework { get; set; }
[JsonPropertyName("disable-mix-mutants")]
public bool? DisableMixMutants { get; init; }

public string Project { get; set; }
[JsonPropertyName("thresholds")]
public Thresholds Thresholds { get; init; }

[JsonProperty(PropertyName = "coverage-analysis")]
public string CoverageAnalysis { get; set; }
[JsonPropertyName("verbosity")]
public string Verbosity { get; init; }

[JsonProperty(PropertyName = "disable-bail")]
public bool DisableBail { get; set; }
[JsonPropertyName("reporters")]
public string[] Reporters { get; init; }

[JsonProperty(PropertyName = "disable-mix-mutants")]
public bool DisableMixMutants { get; set; }
[JsonPropertyName("since")]
public Since Since { get; init; }

public Thresholds Thresholds { get; set; }
[JsonPropertyName("baseline")]
public Baseline Baseline { get; init; }

public string Verbosity { get; set; }
[JsonPropertyName("dashboard-url")]
public string DashboardUrl { get; init; }

public string[] Reporters { get; set; }
[JsonPropertyName("test-projects")]
public string[] TestProjects { get; init; }

public Since Since { get; set; }
[JsonPropertyName("test-case-filter")]
public string TestCaseFilter { get; init; }

public Baseline Baseline { get; set; }
[JsonPropertyName("ignore-mutations")]
public string[] IgnoreMutations { get; init; }

[JsonProperty(PropertyName = "dashboard-url")]
public string DashboardUrl { get; set; }
[JsonPropertyName("ignore-methods")]
public string[] IgnoreMethods { get; init; }

[JsonProperty(PropertyName = "test-projects")]
public string[] TestProjects { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement> ExtraData { get; init; }
}

public class Since : IExtraData
{
[JsonPropertyName("enabled")]
public bool? Enabled { get; init; }

[JsonProperty(PropertyName = "test-case-filter")]
public string TestCaseFilter { get; set; }
[JsonPropertyName("ignore-changes-in")]
public string[] IgnoreChangesIn { get; init; }

[JsonProperty(PropertyName = "ignore-mutations")]
public string[] IgnoreMutations { get; set; }
[JsonPropertyName("target")]
public string Target { get; init; }

[JsonProperty(PropertyName = "ignore-methods")]
public string[] IgnoreMethods { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement> ExtraData { get; init; }
}

public class Since
public class Baseline : IExtraData
{
public bool? Enabled { get; set; }
[JsonPropertyName("enabled")]
public bool? Enabled { get; init; }

[JsonPropertyName("provider")]
public string Provider { get; init; }

[JsonProperty(PropertyName = "ignore-changes-in")]
public string[] IgnoreChangesIn { get; set; }
[JsonPropertyName("azure-fileshare-url")]
public string AzureFileShareUrl { get; init; }

[JsonProperty(PropertyName = "target")]
public string Target { get; set; }
[JsonPropertyName("fallback-version")]
public string FallbackVersion { get; init; }

[JsonExtensionData]
public Dictionary<string, JsonElement> ExtraData { get; init; }
}

public class Baseline
public class ProjectInfo : IExtraData
{
public bool? Enabled { get; set; }
[JsonPropertyName("name")]
public string Name { get; init; }

[JsonProperty(PropertyName = "provider")]
public string Provider { get; set; }
[JsonPropertyName("module")]
public string Module { get; init; }

[JsonProperty(PropertyName = "azure-fileshare-url")]
public string AzureFileShareUrl { get; set; }
[JsonPropertyName("version")]
public string Version { get; init; }

[JsonProperty(PropertyName = "fallback-version")]
public string FallbackVersion { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement> ExtraData { get; init; }
}

public class ProjectInfo
public class Thresholds : IExtraData
{
public string Name { get; set; }
public string Module { get; set; }
public string Version { get; set; }
[JsonPropertyName("high")]
public int? High { get; init; }

[JsonPropertyName("low")]
public int? Low { get; init; }

[JsonPropertyName("break")]
public int? Break { get; init; }

[JsonExtensionData]
public Dictionary<string, JsonElement> ExtraData { get; init; }
}
}
Loading

0 comments on commit 519fbc5

Please sign in to comment.