diff --git a/Directory.Build.props b/Directory.Build.props
index 0b0e187d0..195bbb0a8 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,6 +2,9 @@
$(MSBuildThisFileDirectory)
+ net9.0
+ net8.0
+ net472
Debug
@@ -39,12 +42,12 @@
- $(RepoRoot)artifacts/testresults/$(Configuration.ToLowerInvariant())
+ $(RepoRoot)artifacts/reports/$(Configuration.ToLowerInvariant())
@(VSTestLogger)
- $(RepoRoot)artifacts\testresults\$(Configuration.ToLowerInvariant())
+ $(RepoRoot)artifacts\reports\$(Configuration.ToLowerInvariant())
@(VSTestLogger)
diff --git a/Directory.Packages.props b/Directory.Packages.props
index eba94e254..7b7ef4f56 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -8,20 +8,23 @@
- 17.13.9
- 4.12.0
+ 17.11.4
+ 4.13.0
17.13.0
6.13.2
2.0.0
3.0.2
+ 6.0.0
+ 4.5.5
+ 8.0.0
-
+
@@ -30,16 +33,6 @@
-
-
-
-
-
@@ -58,14 +51,14 @@
-
+
-
+
-
+
diff --git a/Documentation/VSTestIntegration.md b/Documentation/VSTestIntegration.md
index a2c4140e1..c0f5f355f 100644
--- a/Documentation/VSTestIntegration.md
+++ b/Documentation/VSTestIntegration.md
@@ -2,12 +2,12 @@
**Supported runtime versions**:
-Since version `6.0.0`
+Since version `8.0.0`
-* .NET Core >= 6.0
+* .NET Core >= 8.0
* .NET Framework >= 4.7.2
-As explained in quick start section, to use collectors you need to run *SDK v6.0.100* (LTS) or newer and your project file must reference `coverlet.collector` and a minimum version of `Microsoft.NET.Test.Sdk`.
+As explained in quick start section, to use collectors you need to run *SDK v8.0.100* (LTS) or newer and your project file must reference `coverlet.collector` and a minimum version of `Microsoft.NET.Test.Sdk`.
A sample project file looks like:
@@ -20,7 +20,7 @@ A sample project file looks like:
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -43,10 +43,10 @@ or
```text
dotnet publish
...
- ... -> C:\project\bin\Debug\net6.0\testdll.dll
- ... -> C:\project\bin\Debug\net6.0\publish\
+ ... -> C:\project\bin\Debug\net8.0\testdll.dll
+ ... -> C:\project\bin\Debug\net8.0\publish\
...
-dotnet vstest C:\project\bin\Debug\net6.0\publish\testdll.dll --collect:"XPlat Code Coverage"
+dotnet vstest C:\project\bin\Debug\net8.0\publish\testdll.dll --collect:"XPlat Code Coverage"
```
As you can see in case of `vstest` verb you **must** publish project before.
diff --git a/README.md b/README.md
index cea37fcfc..39aa23b69 100644
--- a/README.md
+++ b/README.md
@@ -44,8 +44,8 @@ Coverlet supports only SDK-style projects https://docs.microsoft.com/en-us/visua
```bash
dotnet add package coverlet.collector
```
-
-N.B. You **MUST** add package only to test projects and if you create xunit test projects (`dotnet new xunit`) you'll find the reference already present in `csproj` file because Coverlet is the default coverage tool for every .NET Core and >= .NET 6 applications, you've only to update to last version if needed. Do not add `coverlet.collector` and `coverlet.msbuild` package in a test project.
+> [!NOTE]
+> You **MUST** add package only to test projects and if you create xunit test projects (`dotnet new xunit`) you will find the reference already present in `csproj` file because Coverlet is the default coverage tool for every .NET Core and >= *.NET 8* applications, you've only to update to last version if needed. Add `coverlet.collector` *OR* `coverlet.msbuild` package in a test project.
### Usage (coverlet.collector)
@@ -61,11 +61,11 @@ See [documentation](Documentation/VSTestIntegration.md) for advanced usage.
#### Requirements (coverlet.collector)
-* _You need to be running .NET 6.0 SDK v6.0.316 or newer_
-* _You need to reference version 17.5.0 and above of Microsoft.NET.Test.Sdk_
+* _You need to be running .NET 8.0 SDK v8.0.112 or newer_
+* _You need to reference version 17.12.0 and above of Microsoft.NET.Test.Sdk_
```xml
-
+
```
### MSBuild Integration (suffers of possible [known issue](https://github.com/coverlet-coverage/coverlet/blob/master/Documentation/KnownIssues.md#1-vstest-stops-process-execution-earlydotnet-test))
@@ -120,7 +120,7 @@ See [documentation](Documentation/GlobalTool.md) for advanced usage.
.NET global tools rely on a .NET Core runtime installed on your machine https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools#what-could-go-wrong
-.NET Coverlet global tool requires _.NET Core 2.2 and above_
+.NET Coverlet global tool requires _.NET 8.0 or above_
## How It Works
diff --git a/eng/azure-pipelines-nightly.yml b/eng/azure-pipelines-nightly.yml
index ab78bae71..e2e8904da 100644
--- a/eng/azure-pipelines-nightly.yml
+++ b/eng/azure-pipelines-nightly.yml
@@ -4,13 +4,13 @@ pool:
steps:
- task: UseDotNet@2
inputs:
- version: 6.0.428
- displayName: Install .NET Core SDK 6.0.428
+ version: 8.0.408
+ displayName: Install .NET Core SDK 8.0.408
- task: UseDotNet@2
inputs:
useGlobalJson: true
- displayName: Install .NET Core SDK 8.0.113
+ displayName: Install .NET Core SDK 9.0.203
- task: NuGetAuthenticate@1
displayName: Authenticate with NuGet feeds
diff --git a/eng/build.sh b/eng/build.sh
index 35b5b75b7..a1e1891fa 100644
--- a/eng/build.sh
+++ b/eng/build.sh
@@ -22,12 +22,13 @@ dotnet pack -c release
dotnet build-server shutdown
# Run tests with code coverage
-dotnet test test/coverlet.core.tests/coverlet.core.tests.csproj -c debug --no-build -bl:test.core.binlog /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*%2c[coverlet.tests.projectsample]*" /p:ExcludeByAttribute="GeneratedCodeAttribute" -- --results-directory "artifacts/Reports" --report-xunit-trx --report-xunit-trx-filename "coverlet.core.tests.trx" --diagnostic --diagnostic-output-directory "artifacts/log/debug" --diagnostic-output-fileprefix "coverlet.core.tests"
+dotnet test test/coverlet.collector.tests /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*" --results-directory:"./artifacts/reports" --diag:"artifacts/log/debug/coverlet.collector.test.log;tracelevel=verbose"
dotnet build-server shutdown
-dotnet test test/coverlet.core.coverage.tests/coverlet.core.coverage.tests.csproj -c debug --no-build -bl:test.core.coverage.binlog /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*%2c[coverlet.tests.projectsample]*" /p:ExcludeByAttribute="GeneratedCodeAttribute" -- --results-directory "artifacts/Reports" --report-xunit-trx --report-xunit-trx-filename "coverlet.core.coverage.tests.trx" --diagnostic --diagnostic-output-directory "artifacts/log/debug" --diagnostic-output-fileprefix "coverlet.core.coverage.tests"
+dotnet test test/coverlet.core.tests /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*" --results-directory:"./artifacts/reports" --verbosity detailed --diag ./artifacts/log/debug/coverlet.core.tests.log
dotnet build-server shutdown
-dotnet test test/coverlet.msbuild.tasks.tests/coverlet.msbuild.tasks.tests.csproj -c debug --no-build -bl:test.msbuild.binlog /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*%2c[coverlet.tests.projectsample]*" /p:ExcludeByAttribute="GeneratedCodeAttribute" -- --results-directory:"artifacts/Reports" --report-xunit-trx --report-xunit-trx-filename "coverlet.msbuild.tasks.tests.trx" --diagnostic --diagnostic-output-directory "artifacts/log/debug" --diagnostic-output-fileprefix "coverlet.msbuild.tasks.tests"
+dotnet test test/coverlet.core.coverage.tests /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*" -- --results-directory "$(pwd)/artifacts/reports" --report-xunit-trx --report-xunit-trx-filename "coverlet.core.coverage.tests.trx" --diagnostic-verbosity debug --diagnostic --diagnostic-output-directory "$(pwd)/artifacts/log/debug"
dotnet build-server shutdown
-dotnet test test/coverlet.collector.tests/coverlet.collector.tests.csproj -c debug --no-build -bl:test.collector.binlog /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*%2c[coverlet.tests.projectsample]*" /p:ExcludeByAttribute="GeneratedCodeAttribute" --diag:"artifacts/log/debug/coverlet.collector.test.diag.log;tracelevel=verbose"
+dotnet test test/coverlet.msbuild.tasks.tests /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*" --results-directory:"./artifacts/reports" --verbosity detailed --diag ./artifacts/log/debug/coverlet.msbuild.tasks.tests.log
dotnet build-server shutdown
-dotnet test test/coverlet.integration.tests/coverlet.integration.tests.csproj -c debug --no-build -bl:test.integration.binlog -- --results-directory "artifacts/Reports" --report-xunit-trx --report-xunit-trx-filename "coverlet.integration.tests.trx" --diagnostic --diagnostic-output-directory "artifacts/log/debug" --diagnostic-output-fileprefix "coverlet.integration.tests"
+dotnet test test/coverlet.integration.tests -f net8.0 --results-directory:"./artifacts/reports" --verbosity detailed --diag ./artifacts/log/debug/coverlet.integration.tests.net8.log
+dotnet test test/coverlet.integration.tests -f net9.0 --results-directory:"./artifacts/reports" --verbosity detailed --diag ./artifacts/log/debug/coverlet.integration.tests.net9.log
diff --git a/eng/build.yml b/eng/build.yml
index 570bd0f2c..47d74c6a8 100644
--- a/eng/build.yml
+++ b/eng/build.yml
@@ -1,13 +1,13 @@
steps:
- task: UseDotNet@2
inputs:
- version: 6.0.428
- displayName: Install .NET Core SDK 6.0.428
+ version: 8.0.408
+ displayName: Install .NET Core SDK 8.0.408
- task: UseDotNet@2
inputs:
useGlobalJson: true
- displayName: Install .NET Core SDK 8.0.113
+ displayName: Install .NET Core SDK 9.0.203
# create artifact/package folder
- pwsh: |
@@ -25,11 +25,12 @@ steps:
displayName: Pack
- script: |
- dotnet test test/coverlet.core.tests/coverlet.core.tests.csproj -c $(BuildConfiguration) --no-build -bl:test.core.binlog /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*%2c[coverlet.tests.projectsample]*" /p:ExcludeByAttribute="GeneratedCodeAttribute" -- --results-directory "$(Build.SourcesDirectory)/artifacts/Reports" --report-xunit-trx --report-xunit-trx-filename "coverlet.core.tests.trx" --diagnostic --diagnostic-output-directory "$(Build.SourcesDirectory)/artifacts/log/$(buildConfiguration)" --diagnostic-output-fileprefix "coverlet.core.tests"
- dotnet test test/coverlet.core.coverage.tests/coverlet.core.coverage.tests.csproj -c $(BuildConfiguration) --no-build -bl:test.core.coverage.binlog /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*%2c[coverlet.tests.projectsample]*" /p:ExcludeByAttribute="GeneratedCodeAttribute" -- --results-directory "$(Build.SourcesDirectory)/artifacts/Reports" --report-xunit-trx --report-xunit-trx-filename "coverlet.core.coverage.tests.trx" --diagnostic --diagnostic-output-directory "$(Build.SourcesDirectory)/artifacts/log/$(buildConfiguration)" --diagnostic-output-fileprefix "coverlet.core.coverage.tests"
- dotnet test test/coverlet.msbuild.tasks.tests/coverlet.msbuild.tasks.tests.csproj -c $(BuildConfiguration) --no-build -bl:test.msbuild.binlog --results-directory:"$(Build.SourcesDirectory)\artifacts\Reports" /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*%2c[coverlet.tests.xunit.extensions]*%2c[coverlet.tests.projectsample]*%2c[testgen_]*" /p:ExcludeByAttribute="GeneratedCodeAttribute" --diag:"$(Build.SourcesDirectory)\artifacts\log\$(buildConfiguration)\coverlet.msbuild.test.diag.log;tracelevel=verbose"
- dotnet test test/coverlet.collector.tests/coverlet.collector.tests.csproj -c $(BuildConfiguration) --no-build -bl:test.collector.binlog /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*%2c[coverlet.tests.projectsample]*" /p:ExcludeByAttribute="GeneratedCodeAttribute" --diag:"$(Build.SourcesDirectory)/artifacts/log/$(buildConfiguration)/coverlet.collector.test.diag.log;tracelevel=verbose"
- dotnet test test/coverlet.integration.tests/coverlet.integration.tests.csproj -c $(BuildConfiguration) --no-build -bl:test.integration.binlog -- --results-directory "$(Build.SourcesDirectory)/artifacts/Reports" --report-xunit-trx --report-xunit-trx-filename "coverlet.integration.tests.trx" --diagnostic --diagnostic-output-directory "$(Build.SourcesDirectory)/artifacts/log/$(buildConfiguration)" --diagnostic-output-fileprefix "coverlet.integration.tests"
+ dotnet test test/coverlet.collector.tests/coverlet.collector.tests.csproj -c $(BuildConfiguration) --no-build -bl:test.collector.binlog /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*%2c[coverlet.tests.projectsample]*" /p:ExcludeByAttribute="GeneratedCodeAttribute" --diag:"$(Build.SourcesDirectory)/artifacts/log/coverlet.collector.tests.diag.$(buildConfiguration).log;tracelevel=verbose"
+ dotnet test test/coverlet.core.tests/coverlet.core.tests.csproj -c $(BuildConfiguration) --no-build -bl:test.core.binlog /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*%2c[coverlet.tests.projectsample]*" /p:ExcludeByAttribute="GeneratedCodeAttribute" --diag:"$(Build.SourcesDirectory)/artifacts/log/coverlet.core.tests.diag.$(buildConfiguration).log;tracelevel=verbose"
+ dotnet test test/coverlet.core.coverage.tests/coverlet.core.coverage.tests.csproj -c $(BuildConfiguration) --no-build -bl:test.core.coverage.binlog /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*%2c[coverlet.tests.projectsample]*" /p:ExcludeByAttribute="GeneratedCodeAttribute" -- --results-directory "$(Build.SourcesDirectory))/artifacts/reports" --report-xunit-trx --report-xunit-trx-filename "coverlet.core.coverage.tests.trx" --diagnostic-verbosity debug --diagnostic --diagnostic-output-directory "$(Build.SourcesDirectory)/artifacts/log/$(BuildConfiguration)"
+ dotnet test test/coverlet.msbuild.tasks.tests\coverlet.msbuild.tasks.tests.csproj -c $(BuildConfiguration) --no-build -bl:test.msbuild.tasks.binlog /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[coverlet.core.tests.samples.netstandard]*%2c[coverlet.tests.projectsample]*" /p:ExcludeByAttribute="GeneratedCodeAttribute" --diag:"$(Build.SourcesDirectory)/artifacts/log/coverlet.msbuild.tasks.tests.diag.$(buildConfiguration).log;tracelevel=verbose"
+ dotnet test test/coverlet.integration.tests/coverlet.integration.tests.csproj -c $(BuildConfiguration) -f net8.0 --no-build -bl:test.integration.binlog --diag:"$(Build.SourcesDirectory)/artifacts/log/coverlet.integration.tests.diag.net8.0.$(buildConfiguration).log;tracelevel=verbose"
+ dotnet test test/coverlet.integration.tests/coverlet.integration.tests.csproj -c $(BuildConfiguration) -f net9.0 --no-build -bl:test.integration.binlog --diag:"$(Build.SourcesDirectory)/artifacts/log/coverlet.integration.tests.diag.net9.0.$(buildConfiguration).log;tracelevel=verbose"
displayName: Run unit tests with coverage
env:
MSBUILDDISABLENODEREUSE: 1
diff --git a/eng/publish-coverlet-result-files.yml b/eng/publish-coverlet-result-files.yml
index c8addb84c..de280a2d3 100644
--- a/eng/publish-coverlet-result-files.yml
+++ b/eng/publish-coverlet-result-files.yml
@@ -15,6 +15,11 @@ steps:
**/log.txt
**/log.datacollector.*.txt
**/log.host.*.txt
+ **/coverlet.integration.tests.diag*.log
+ **/coverlet.collector.tests.diag*.log
+ **/coverlet.msbuild.tasks.tests.diag*.log
+ **/coverlet.core.coverage.tests.diag*.log
+ **/coverlet.core.tests.diag*.log
TargetFolder: '$(Build.SourcesDirectory)/artifacts/TestLogs'
- task: CopyFiles@2
@@ -34,7 +39,15 @@ steps:
condition: always()
inputs:
SourceFolder: '$(Build.SourcesDirectory)'
- Contents: '**/*.binlog'
+ Contents: '*.binlog'
+ TargetFolder: '$(Build.SourcesDirectory)/artifacts/TestLogs'
+
+- task: CopyFiles@2
+ displayName: Copy DeterministicBuild binlog files
+ condition: always()
+ inputs:
+ SourceFolder: '$(Build.SourcesDirectory)'
+ Contents: 'test\coverlet.integration.determisticbuild\*.binlog'
TargetFolder: '$(Build.SourcesDirectory)/artifacts/TestLogs'
- task: PublishPipelineArtifact@1
diff --git a/global.json b/global.json
index 6dfc6666e..a42b43018 100644
--- a/global.json
+++ b/global.json
@@ -1,5 +1,5 @@
{
"sdk": {
- "version": "8.0.407"
+ "version": "9.0.203"
}
}
diff --git a/src/coverlet.collector/coverlet.collector.csproj b/src/coverlet.collector/coverlet.collector.csproj
index 7630bb845..5a2b55fb2 100644
--- a/src/coverlet.collector/coverlet.collector.csproj
+++ b/src/coverlet.collector/coverlet.collector.csproj
@@ -1,6 +1,6 @@
- netstandard2.0
+ $(NetMinimum);netstandard2.0
coverlet.collector
true
true
@@ -40,8 +40,11 @@
+
+
+
diff --git a/src/coverlet.console/coverlet.console.csproj b/src/coverlet.console/coverlet.console.csproj
index 2a7181b18..88a695d6a 100644
--- a/src/coverlet.console/coverlet.console.csproj
+++ b/src/coverlet.console/coverlet.console.csproj
@@ -2,7 +2,7 @@
Exe
- net8.0
+ $(NetMinimum)
coverlet
true
coverlet.console
@@ -25,6 +25,7 @@
+
diff --git a/src/coverlet.core/Coverage.cs b/src/coverlet.core/Coverage.cs
index 3cc80c4c8..918d8aedf 100644
--- a/src/coverlet.core/Coverage.cs
+++ b/src/coverlet.core/Coverage.cs
@@ -6,11 +6,11 @@
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
+using System.Text.Json;
+using System.Text.Json.Nodes;
using Coverlet.Core.Abstractions;
using Coverlet.Core.Helpers;
using Coverlet.Core.Instrumentation;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
namespace Coverlet.Core
{
@@ -60,6 +60,14 @@ internal class Coverage
public string Identifier { get; }
+ readonly JsonSerializerOptions _options = new()
+ {
+ PropertyNameCaseInsensitive = true,
+ DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
+ IncludeFields = true,
+ WriteIndented = true
+ };
+
public Coverage(string moduleOrDirectory,
CoverageParameters parameters,
ILogger logger,
@@ -313,7 +321,7 @@ public CoverageResult GetCoverageResult()
{
_logger.LogInformation($"MergeWith: '{_parameters.MergeWith}'.");
string json = _fileSystem.ReadAllText(_parameters.MergeWith);
- coverageResult.Merge(JsonConvert.DeserializeObject(json));
+ coverageResult.Merge(JsonSerializer.Deserialize(json, _options));
}
else
{
@@ -366,8 +374,8 @@ private void CalculateCoverage()
var documents = result.Documents.Values.ToList();
if (_parameters.UseSourceLink && result.SourceLink != null)
{
- JToken jObject = JObject.Parse(result.SourceLink)["documents"];
- Dictionary sourceLinkDocuments = JsonConvert.DeserializeObject>(jObject.ToString());
+ JsonNode jObject = JsonNode.Parse(result.SourceLink)["documents"];
+ Dictionary sourceLinkDocuments = JsonSerializer.Deserialize>(jObject.ToString());
foreach (Document document in documents)
{
document.Path = GetSourceLinkUrl(sourceLinkDocuments, document.Path);
@@ -480,9 +488,9 @@ internal string GetSourceLinkUrl(Dictionary sourceLinkDocuments,
{
string key = sourceLinkDocument.Key;
if (Path.GetFileName(key) != "*") continue;
-
+#pragma warning disable IDE0057
IReadOnlyList rootMapping = _sourceRootTranslator.ResolvePathRoot(key.Substring(0, key.Length - 1));
-
+#pragma warning restore IDE0057
foreach (string keyMapping in rootMapping is null ? [key] : new List(rootMapping.Select(m => m.OriginalPath)))
{
string directoryDocument = Path.GetDirectoryName(document);
@@ -494,8 +502,9 @@ internal string GetSourceLinkUrl(Dictionary sourceLinkDocuments,
{
if (!directoryDocument.StartsWith(sourceLinkRoot + Path.DirectorySeparatorChar))
continue;
-
+#pragma warning disable IDE0057
relativePath = directoryDocument.Substring(sourceLinkRoot.Length + 1);
+#pragma warning restore IDE0057
}
if (relativePathOfBestMatch.Length == 0)
diff --git a/src/coverlet.core/CoverageResult.cs b/src/coverlet.core/CoverageResult.cs
index 7b002053c..c3a92ee29 100644
--- a/src/coverlet.core/CoverageResult.cs
+++ b/src/coverlet.core/CoverageResult.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
+using System.Text.Json.Serialization;
using Coverlet.Core.Enums;
using Coverlet.Core.Instrumentation;
@@ -22,6 +23,7 @@ internal class Branches : List { }
internal class Method
{
+ [JsonConstructor]
internal Method()
{
Lines = [];
diff --git a/src/coverlet.core/Exceptions.cs b/src/coverlet.core/Exceptions.cs
index d65b22096..365df85f3 100644
--- a/src/coverlet.core/Exceptions.cs
+++ b/src/coverlet.core/Exceptions.cs
@@ -5,25 +5,17 @@
namespace Coverlet.Core.Exceptions
{
- [Serializable]
public class CoverletException : Exception
{
public CoverletException() { }
public CoverletException(string message) : base(message) { }
public CoverletException(string message, System.Exception inner) : base(message, inner) { }
- protected CoverletException(
- System.Runtime.Serialization.SerializationInfo info,
- System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
- [Serializable]
internal class CecilAssemblyResolutionException : CoverletException
{
public CecilAssemblyResolutionException() { }
public CecilAssemblyResolutionException(string message) : base(message) { }
public CecilAssemblyResolutionException(string message, System.Exception inner) : base(message, inner) { }
- protected CecilAssemblyResolutionException(
- System.Runtime.Serialization.SerializationInfo info,
- System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
}
diff --git a/src/coverlet.core/Helpers/InstrumentationHelper.cs b/src/coverlet.core/Helpers/InstrumentationHelper.cs
index 0b1b3439c..e6e3f0702 100644
--- a/src/coverlet.core/Helpers/InstrumentationHelper.cs
+++ b/src/coverlet.core/Helpers/InstrumentationHelper.cs
@@ -415,8 +415,10 @@ private static string GetIncludeModuleKeysForValidFilters(char escapeSymbol, str
}
private static string CreateRegexExcludePattern(IEnumerable filters, char escapeSymbol)
- //only look for module filters here, types will be filtered out when instrumenting
+ //only look for module filters here, types will be filtered out when instrumenting
+#pragma warning disable IDE0057 // Use range operator
=> CreateRegexPattern(filters, escapeSymbol, filter => filter.Substring(filter.IndexOf(']') + 1) == "*");
+#pragma warning restore IDE0057 // Use range operator
private static string CreateRegexIncludePattern(IEnumerable filters, char escapeSymbol) =>
CreateRegexPattern(filters, escapeSymbol);
@@ -424,8 +426,10 @@ private static string CreateRegexIncludePattern(IEnumerable filters, cha
private static string CreateRegexPattern(IEnumerable filters, char escapeSymbol, Func filterPredicate = null)
{
IEnumerable filteredFilters = filterPredicate != null ? filters.Where(filterPredicate) : filters;
+#pragma warning disable IDE0057 // Use range operator
IEnumerable regexPatterns = filteredFilters.Select(x =>
$"{escapeSymbol}{WildcardToRegex(x.Substring(1, x.IndexOf(']') - 1)).Trim('^', '$')}{escapeSymbol}");
+#pragma warning restore IDE0057 // Use range operator
return string.Join("|", regexPatterns);
}
diff --git a/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs b/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs
index 649b6c369..ecef745e2 100644
--- a/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs
+++ b/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs
@@ -5,12 +5,12 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Text.Json;
using Coverlet.Core.Abstractions;
using Coverlet.Core.Exceptions;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.DependencyModel.Resolution;
using Mono.Cecil;
-using Newtonsoft.Json.Linq;
using NuGet.Versioning;
namespace Coverlet.Core.Instrumentation
@@ -296,29 +296,32 @@ public RuntimeConfigurationReader(string runtimeConfigFile)
{
string jsonString = File.ReadAllText(_runtimeConfigFile);
- var jsonLoadSettings = new JsonLoadSettings()
+ var documentOptions = new JsonDocumentOptions
{
- CommentHandling = CommentHandling.Ignore
+ CommentHandling = JsonCommentHandling.Skip
};
- var configuration = JObject.Parse(jsonString, jsonLoadSettings);
+ using var configuration = JsonDocument.Parse(jsonString, documentOptions);
- JToken rootElement = configuration.Root;
- JToken runtimeOptionsElement = rootElement["runtimeOptions"];
+ JsonElement rootElement = configuration.RootElement;
+ JsonElement runtimeOptionsElement = rootElement.GetProperty("runtimeOptions");
- if (runtimeOptionsElement?["framework"] != null)
+ if (runtimeOptionsElement.TryGetProperty("framework", out JsonElement frameworkElement))
{
- return [(runtimeOptionsElement["framework"]["name"]?.Value(), runtimeOptionsElement["framework"]["version"]?.Value())];
+ return new List<(string, string)>
+ {
+ (runtimeOptionsElement.GetProperty("framework").GetProperty("name").GetString(), runtimeOptionsElement.GetProperty("framework").GetProperty("version").GetString())
+ };
}
- if (runtimeOptionsElement?["frameworks"] != null)
+ if (runtimeOptionsElement.TryGetProperty("frameworks", out JsonElement frameworksElement))
{
- return runtimeOptionsElement["frameworks"].Select(x => (x["name"]?.Value(), x["version"]?.Value())).ToList();
+ return frameworksElement.EnumerateArray().Select(x => (x.GetProperty("name").GetString(), x.GetProperty("version").GetString())).ToList();
}
- if (runtimeOptionsElement?["includedFrameworks"] != null)
+ if (runtimeOptionsElement.TryGetProperty("includedFrameworks", out JsonElement runtimeoptionselement))
{
- return runtimeOptionsElement["includedFrameworks"].Select(x => (x["name"]?.Value(), x["version"]?.Value())).ToList();
+ return runtimeoptionselement.EnumerateArray().Select(x => (x.GetProperty("name").GetString(), x.GetProperty("version").GetString())).ToList();
}
throw new InvalidOperationException($"Unable to read runtime configuration from {_runtimeConfigFile}.");
diff --git a/src/coverlet.core/Reporters/JsonReporter.cs b/src/coverlet.core/Reporters/JsonReporter.cs
index e684e8c8a..62be3373a 100644
--- a/src/coverlet.core/Reporters/JsonReporter.cs
+++ b/src/coverlet.core/Reporters/JsonReporter.cs
@@ -1,8 +1,9 @@
// Copyright (c) Toni Solarin-Sodara
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System.Text.Encodings.Web;
+using System.Text.Json;
using Coverlet.Core.Abstractions;
-using Newtonsoft.Json;
namespace Coverlet.Core.Reporters
{
@@ -16,7 +17,13 @@ internal class JsonReporter : IReporter
public string Report(CoverageResult result, ISourceRootTranslator _)
{
- return JsonConvert.SerializeObject(result.Modules, Formatting.Indented);
+ var options = new JsonSerializerOptions
+ {
+ Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
+ IncludeFields = true,
+ WriteIndented = true,
+ };
+ return JsonSerializer.Serialize(result.Modules, options);
}
}
}
diff --git a/src/coverlet.core/coverlet.core.csproj b/src/coverlet.core/coverlet.core.csproj
index f3e16e3f1..7bac1e92d 100644
--- a/src/coverlet.core/coverlet.core.csproj
+++ b/src/coverlet.core/coverlet.core.csproj
@@ -1,24 +1,25 @@
-
+
Library
- netstandard2.0
+ $(NetMinimum);netstandard2.0
false
+ $(NoWarn);IDE0057
-
-
-
-
+
+
-
-
-
+
+
+
+
+
-
-
+
+
diff --git a/src/coverlet.msbuild.tasks/buildMultiTargeting/coverlet.msbuild.props b/src/coverlet.msbuild.tasks/buildMultiTargeting/coverlet.msbuild.props
new file mode 100644
index 000000000..ba0c4ed38
--- /dev/null
+++ b/src/coverlet.msbuild.tasks/buildMultiTargeting/coverlet.msbuild.props
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/coverlet.msbuild.tasks/coverlet.msbuild.props b/src/coverlet.msbuild.tasks/coverlet.msbuild.props
index 94f3d0d9d..53ec786b4 100644
--- a/src/coverlet.msbuild.tasks/coverlet.msbuild.props
+++ b/src/coverlet.msbuild.tasks/coverlet.msbuild.props
@@ -19,9 +19,11 @@
- $(MSBuildThisFileDirectory)..\tasks\netstandard2.0\
+ $(MSBuildThisFileDirectory)..\tasks\net8.0\
+ $(MSBuildThisFileDirectory)..\tasks\netstandard2.0\
- $(MSBuildThisFileDirectory)../tasks/netstandard2.0/
+ $(MSBuildThisFileDirectory)../tasks/net8.0/
+ $(MSBuildThisFileDirectory)../tasks/netstandard2.0/
diff --git a/src/coverlet.msbuild.tasks/coverlet.msbuild.targets b/src/coverlet.msbuild.tasks/coverlet.msbuild.targets
index e8bbfac20..0defe0138 100644
--- a/src/coverlet.msbuild.tasks/coverlet.msbuild.targets
+++ b/src/coverlet.msbuild.tasks/coverlet.msbuild.targets
@@ -6,7 +6,7 @@
<_CoverletSdkNETCoreSdkVersion>$(NETCoreSdkVersion)
<_CoverletSdkNETCoreSdkVersion Condition="$(_CoverletSdkNETCoreSdkVersion.Contains('-'))">$(_CoverletSdkNETCoreSdkVersion.Split('-')[0])
- <_CoverletSdkMinVersionWithDependencyTarget>6.0.100
+ <_CoverletSdkMinVersionWithDependencyTarget>8.0.100
<_CoverletSourceRootTargetName>CoverletGetPathMap
<_CoverletSourceRootTargetName Condition="'$([System.Version]::Parse($(_CoverletSdkNETCoreSdkVersion)).CompareTo($([System.Version]::Parse($(_CoverletSdkMinVersionWithDependencyTarget)))))' >= '0' ">InitializeSourceRootMappedPaths
diff --git a/src/coverlet.msbuild.tasks/coverlet.msbuild.tasks.csproj b/src/coverlet.msbuild.tasks/coverlet.msbuild.tasks.csproj
index c04e823b0..57104ff72 100644
--- a/src/coverlet.msbuild.tasks/coverlet.msbuild.tasks.csproj
+++ b/src/coverlet.msbuild.tasks/coverlet.msbuild.tasks.csproj
@@ -2,7 +2,7 @@
Library
- netstandard2.0
+ netstandard2.0;$(NetMinimum)
coverlet.msbuild.tasks
true
$(TargetsForTfmSpecificContentInPackage);PackBuildOutputs
@@ -40,6 +40,7 @@
+
@@ -51,6 +52,9 @@
Always
+
+ Always
+
Always
diff --git a/test/Directory.Build.targets b/test/Directory.Build.targets
index 3cd6c793b..8b989e8bd 100644
--- a/test/Directory.Build.targets
+++ b/test/Directory.Build.targets
@@ -14,8 +14,8 @@
This is required when the coverlet.msbuild imports are made in their src directory
(so that msbuild eval works even before they are built)
so that they can still find the tooling that will be built by the build. -->
-
- $(RepoRoot)artifacts\bin\coverlet.msbuild.tasks\$(Configuration.ToLower())\
+ $(RepoRoot)artifacts\bin\coverlet.msbuild.tasks\$(Configuration.ToLowerInvariant())_netstandard2.0\
+
diff --git a/test/coverlet.core.coverage.tests/coverlet.core.coverage.tests.csproj b/test/coverlet.core.coverage.tests/coverlet.core.coverage.tests.csproj
index 43b19b7ad..5eabe6aea 100644
--- a/test/coverlet.core.coverage.tests/coverlet.core.coverage.tests.csproj
+++ b/test/coverlet.core.coverage.tests/coverlet.core.coverage.tests.csproj
@@ -1,10 +1,10 @@
-
+
net8.0
- true
Exe
+ true
true
false
true
diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.cs b/test/coverlet.core.tests/Coverage/CoverageTests.cs
index 86a306269..f99dbb4e6 100644
--- a/test/coverlet.core.tests/Coverage/CoverageTests.cs
+++ b/test/coverlet.core.tests/Coverage/CoverageTests.cs
@@ -1,16 +1,17 @@
-// Copyright (c) Toni Solarin-Sodara
+// Copyright (c) Toni Solarin-Sodara
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
-using System.Collections;
using System.Collections.Generic;
using System.IO;
+using System.Text.Encodings.Web;
+using System.Text.Json;
+using System.Text.Json.Serialization;
using Coverlet.Core.Abstractions;
using Coverlet.Core.Helpers;
using Coverlet.Core.Instrumentation;
using Coverlet.Core.Symbols;
using Moq;
-using Newtonsoft.Json;
using Xunit;
namespace Coverlet.Core.Tests
@@ -18,6 +19,16 @@ namespace Coverlet.Core.Tests
public partial class CoverageTests
{
private readonly Mock _mockLogger = new();
+ readonly JsonSerializerOptions _options = new()
+ {
+ Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
+ IncludeFields = true,
+ WriteIndented = true,
+ Converters =
+ {
+ new BranchDictionaryConverterFactory()
+ }
+ };
[Fact]
public void TestCoverage()
@@ -90,7 +101,7 @@ public void TestCoverageWithTestAssembly()
new SourceRootTranslator(module, _mockLogger.Object, new FileSystem(), new AssemblyAdapter()), new CecilSymbolHelper());
coverage.PrepareModules();
- string result = JsonConvert.SerializeObject(coverage.GetCoverageResult(), Formatting.Indented, new BranchDictionaryConverter());
+ string result = JsonSerializer.Serialize(coverage.GetCoverageResult(), _options);
Assert.Contains("coverlet.core.tests.dll", result);
@@ -129,7 +140,7 @@ public void TestCoverageMergeWithParameter()
var coverage = new Coverage(Path.Combine(directory.FullName, Path.GetFileName(module)), parameters, _mockLogger.Object, instrumentationHelper, new FileSystem(), new SourceRootTranslator(_mockLogger.Object, new FileSystem()), new CecilSymbolHelper());
coverage.PrepareModules();
- string result = JsonConvert.SerializeObject(coverage.GetCoverageResult(), Formatting.Indented, new BranchDictionaryConverter());
+ string result = JsonSerializer.Serialize(coverage.GetCoverageResult(), _options);
Assert.Contains("DeepThought.cs", result);
@@ -170,7 +181,7 @@ public void TestCoverageMergeWithWrongParameter()
var coverage = new Coverage(Path.Combine(directory.FullName, Path.GetFileName(module)), parameters, _mockLogger.Object, instrumentationHelper, new FileSystem(), new SourceRootTranslator(_mockLogger.Object, new FileSystem()), new CecilSymbolHelper());
coverage.PrepareModules();
- JsonConvert.SerializeObject(coverage.GetCoverageResult());
+ string result = JsonSerializer.Serialize(coverage.GetCoverageResult(), _options);
_mockLogger.Verify(l => l.LogInformation(It.Is(v => v.Equals("MergeWith: file 'FileDoesNotExist.json' does not exist.")), It.IsAny()), Times.Once);
@@ -220,36 +231,43 @@ public void GetSourceLinkUrl_ReturnsOriginalDocument_WhenNoMatch()
}
}
- public class BranchDictionaryConverter : JsonConverter
+ public class BranchDictionaryConverterFactory : JsonConverterFactory
{
- public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ public override bool CanConvert(Type typeToConvert)
{
- Type type = value.GetType();
- var keys = (IEnumerable)type.GetProperty("Keys")?.GetValue(value, null);
- var values = (IEnumerable)type.GetProperty("Values")?.GetValue(value, null);
- IEnumerator valueEnumerator = values.GetEnumerator();
-
- writer.WriteStartArray();
- foreach (object key in keys)
- {
- valueEnumerator.MoveNext();
-
- writer.WriteStartArray();
- serializer.Serialize(writer, key);
- serializer.Serialize(writer, valueEnumerator.Current);
- writer.WriteEndArray();
- }
- writer.WriteEndArray();
+ return typeof(Dictionary).IsAssignableFrom(typeToConvert);
}
-
- public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
+ public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
- throw new NotImplementedException();
+ Type[] genericArgs = typeToConvert.GetGenericArguments();
+ Type keyType = genericArgs[0];
+ Type valueType = genericArgs[1];
+
+ JsonConverter converter = (JsonConverter)Activator.CreateInstance(
+ typeof(BranchDictionaryConverter<,>).MakeGenericType(new Type[] { keyType, valueType }));
+
+ return converter;
}
+ }
+}
- public override bool CanConvert(Type objectType)
+public class BranchDictionaryConverter : JsonConverter>
+{
+ public override Dictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void Write(Utf8JsonWriter writer, Dictionary value, JsonSerializerOptions options)
+ {
+ writer.WriteStartObject();
+
+ foreach (KeyValuePair pair in value)
{
- return typeof(Dictionary).IsAssignableFrom(objectType);
+ writer.WritePropertyName(pair.Key.ToString());
+ JsonSerializer.Serialize(writer, pair.Value, options);
}
+
+ writer.WriteEndObject();
}
}
diff --git a/test/coverlet.core.tests/coverlet.core.tests.csproj b/test/coverlet.core.tests/coverlet.core.tests.csproj
index ff6c28869..eeac7e12a 100644
--- a/test/coverlet.core.tests/coverlet.core.tests.csproj
+++ b/test/coverlet.core.tests/coverlet.core.tests.csproj
@@ -1,11 +1,10 @@
-
+
net8.0
Exe
true
- true
true
false
$(NoWarn);CS8002
diff --git a/test/coverlet.integration.determisticbuild/coverlet.integration.determisticbuild.csproj b/test/coverlet.integration.determisticbuild/coverlet.integration.determisticbuild.csproj
index 38d1c8820..28e6552aa 100644
--- a/test/coverlet.integration.determisticbuild/coverlet.integration.determisticbuild.csproj
+++ b/test/coverlet.integration.determisticbuild/coverlet.integration.determisticbuild.csproj
@@ -3,7 +3,7 @@
- net6.0
+ net9.0;net8.0
false
coverletsample.integration.determisticbuild
NU1604;NU1701
@@ -29,6 +29,5 @@
all
runtime; build; native; contentfiles; analyzers
-
diff --git a/test/coverlet.integration.template/nuget.config b/test/coverlet.integration.template/nuget.config
index fbcef1011..765346e53 100644
--- a/test/coverlet.integration.template/nuget.config
+++ b/test/coverlet.integration.template/nuget.config
@@ -2,6 +2,6 @@
-
+
diff --git a/test/coverlet.integration.tests/DeterministicBuild.cs b/test/coverlet.integration.tests/DeterministicBuild.cs
index 9c8a181db..343dd69be 100644
--- a/test/coverlet.integration.tests/DeterministicBuild.cs
+++ b/test/coverlet.integration.tests/DeterministicBuild.cs
@@ -16,21 +16,23 @@ namespace Coverlet.Integration.Tests
public class DeterministicBuild : BaseTest, IDisposable
{
private static readonly string s_projectName = "coverlet.integration.determisticbuild";
- //private readonly string _buildTargetFramework;
- private string? _testProjectTfm;
+ private readonly string _buildTargetFramework;
+ private string[] _testProjectTfms = [];
private readonly string _testProjectPath = TestUtils.GetTestProjectPath(s_projectName);
private readonly string _testBinaryPath = TestUtils.GetTestBinaryPath(s_projectName);
- private readonly string _testResultsPath = TestUtils.GetTestResultsPath(s_projectName);
+ private readonly string _testResultsPath = TestUtils.GetTestResultsPath();
private const string PropsFileName = "DeterministicTest.props";
private readonly string _buildConfiguration;
private readonly ITestOutputHelper _output;
private readonly Type _type;
private readonly FieldInfo? _testMember;
+ private readonly string _artifactsPivot;
public DeterministicBuild(ITestOutputHelper output)
{
_buildConfiguration = TestUtils.GetAssemblyBuildConfiguration().ToString();
- //_buildTargetFramework = TestUtils.GetAssemblyTargetFramework();
+ _buildTargetFramework = TestUtils.GetAssemblyTargetFramework();
+ _artifactsPivot = _buildConfiguration + "_" + _buildTargetFramework;
_output = output;
_type = output.GetType();
_testMember = _type.GetField("test", BindingFlags.Instance | BindingFlags.NonPublic);
@@ -38,25 +40,34 @@ public DeterministicBuild(ITestOutputHelper output)
private void CreateDeterministicTestPropsFile()
{
- var deterministicTestProps = new XDocument();
+ string propsFile = Path.Combine(_testProjectPath, PropsFileName);
+ File.Delete(propsFile);
+
+ XDocument deterministicTestProps = new();
deterministicTestProps.Add(
new XElement("Project",
new XElement("PropertyGroup",
new XElement("coverletMsbuildVersion", GetPackageVersion("*msbuild*.nupkg")),
new XElement("coverletCollectorsVersion", GetPackageVersion("*collector*.nupkg")))));
- _testProjectTfm = XElement.Load(Path.Combine(_testProjectPath, "coverlet.integration.determisticbuild.csproj"))!.
- Descendants("PropertyGroup")!.Single().Element("TargetFramework")!.Value;
+ _testProjectTfms = XElement.Load(Path.Combine(_testProjectPath, "coverlet.integration.determisticbuild.csproj"))!
+ .Descendants("PropertyGroup")!
+ .Single()
+ .Element("TargetFrameworks")!
+ .Value
+ .Split(';');
+
+ Assert.Contains(_buildTargetFramework, _testProjectTfms);
- deterministicTestProps.Save(Path.Combine(_testProjectPath, PropsFileName));
+ deterministicTestProps.Save(Path.Combine(propsFile));
}
- private protected void AssertCoverage(string standardOutput = "", bool checkDeterministicReport = true)
+ private protected void AssertCoverage(string standardOutput = "", string reportName = "", bool checkDeterministicReport = true)
{
if (_buildConfiguration == "Debug")
{
bool coverageChecked = false;
string reportFilePath = "";
- foreach (string coverageFile in Directory.GetFiles(GetReportPath(standardOutput), "coverage.json", SearchOption.AllDirectories))
+ foreach (string coverageFile in Directory.GetFiles(GetReportPath(standardOutput, reportName), reportName, SearchOption.AllDirectories))
{
Classes? document = JsonConvert.DeserializeObject(File.ReadAllText(coverageFile))?.Document("DeepThought.cs");
if (document != null)
@@ -74,8 +85,9 @@ private protected void AssertCoverage(string standardOutput = "", bool checkDete
if (checkDeterministicReport)
{
+ string newName = reportName.Replace("json", "cobertura.xml");
// Verify deterministic report
- foreach (string coverageFile in Directory.GetFiles(GetReportPath(standardOutput), "coverage.cobertura.xml", SearchOption.AllDirectories))
+ foreach (string coverageFile in Directory.GetFiles(GetReportPath(standardOutput, newName), newName, SearchOption.AllDirectories))
{
Assert.Contains("/_/test/coverlet.integration.determisticbuild/DeepThought.cs", File.ReadAllText(coverageFile));
File.Delete(coverageFile);
@@ -91,7 +103,7 @@ public void Msbuild()
string logFilename = $"{TestContext.Current.TestClass?.TestClassName}.{TestContext.Current.TestMethod?.MethodName}.binlog";
CreateDeterministicTestPropsFile();
- DotnetCli($"build -c {_buildConfiguration} -bl:build.{logFilename} /p:DeterministicSourcePaths=true", out string buildOutput, out string buildError, _testProjectPath);
+ DotnetCli($"build -c {_buildConfiguration} -f {_buildTargetFramework} -bl:build.{logFilename} /p:DeterministicSourcePaths=true", out string buildOutput, out string buildError, _testProjectPath);
if (!string.IsNullOrEmpty(buildError))
{
_output.WriteLine(buildError);
@@ -101,13 +113,12 @@ public void Msbuild()
_output.WriteLine(buildOutput);
}
Assert.Contains("Build succeeded.", buildOutput);
- string sourceRootMappingFilePath = Path.Combine(_testBinaryPath, _buildConfiguration.ToLowerInvariant(), "CoverletSourceRootsMapping_coverletsample.integration.determisticbuild");
+ string sourceRootMappingFilePath = Path.Combine(_testBinaryPath, _artifactsPivot.ToLowerInvariant(), "CoverletSourceRootsMapping_coverletsample.integration.determisticbuild");
Assert.True(File.Exists(sourceRootMappingFilePath), $"File not found: {sourceRootMappingFilePath}");
Assert.False(string.IsNullOrEmpty(File.ReadAllText(sourceRootMappingFilePath)));
Assert.Contains("=/_/", File.ReadAllText(sourceRootMappingFilePath));
- string testResultFile = Path.Join(testResultPath, "coverage.json");
- string cmdArgument = $"test -c {_buildConfiguration} --no-build /p:CollectCoverage=true /p:CoverletOutput=\"{testResultFile}\" /p:DeterministicReport=true /p:CoverletOutputFormat=\"cobertura%2cjson\" /p:Include=\"[coverletsample.integration.determisticbuild]*DeepThought\" /p:IncludeTestAssembly=true";
+ string cmdArgument = $"test -c {_buildConfiguration} -f {_buildTargetFramework} --no-build /p:CollectCoverage=true /p:DeterministicReport=true /p:CoverletOutputFormat=\"cobertura%2cjson\" /p:Include=\"[coverletsample.integration.determisticbuild]*DeepThought\" /p:IncludeTestAssembly=true --results-directory:{testResultPath}";
_output.WriteLine($"Command: dotnet {cmdArgument}");
int result = DotnetCli(cmdArgument, out string standardOutput, out string standardError, _testProjectPath);
if (!string.IsNullOrEmpty(standardError))
@@ -121,8 +132,9 @@ public void Msbuild()
Assert.Equal(0, result);
Assert.Contains("Passed!", standardOutput);
Assert.Contains("| coverletsample.integration.determisticbuild | 100% | 100% | 100% |", standardOutput);
- Assert.True(File.Exists(testResultFile));
- AssertCoverage(standardOutput);
+ string testResultFile = Path.Join(_testProjectPath, $"coverage.{_buildTargetFramework}.json");
+ Assert.True(File.Exists(testResultFile), $"File '{testResultFile}' does not exist");
+ AssertCoverage(standardOutput, $"coverage.{_buildTargetFramework}.json");
CleanupBuildOutput();
}
@@ -134,7 +146,7 @@ public void Msbuild_SourceLink()
string logFilename = $"{TestContext.Current.TestClass?.TestClassName}.{TestContext.Current.TestMethod?.MethodName}.binlog";
CreateDeterministicTestPropsFile();
- DotnetCli($"build -c {_buildConfiguration} -bl:build.{logFilename} --verbosity normal /p:DeterministicSourcePaths=true", out string buildOutput, out string buildError, _testProjectPath);
+ DotnetCli($"build -c {_buildConfiguration} -f {_buildTargetFramework} -bl:build.{logFilename} --verbosity normal /p:DeterministicSourcePaths=true", out string buildOutput, out string buildError, _testProjectPath);
if (!string.IsNullOrEmpty(buildError))
{
_output.WriteLine(buildError);
@@ -144,14 +156,13 @@ public void Msbuild_SourceLink()
_output.WriteLine(buildOutput);
}
Assert.Contains("Build succeeded.", buildOutput);
- string sourceRootMappingFilePath = Path.Combine(_testBinaryPath, _buildConfiguration.ToLowerInvariant(), "CoverletSourceRootsMapping_coverletsample.integration.determisticbuild");
+ string sourceRootMappingFilePath = Path.Combine(_testBinaryPath, _artifactsPivot.ToLowerInvariant(), "CoverletSourceRootsMapping_coverletsample.integration.determisticbuild");
Assert.True(File.Exists(sourceRootMappingFilePath), $"File not found: {sourceRootMappingFilePath}");
Assert.False(string.IsNullOrEmpty(File.ReadAllText(sourceRootMappingFilePath)));
Assert.Contains("=/_/", File.ReadAllText(sourceRootMappingFilePath));
- string testResultFile = Path.Join(testResultPath, "coverage.json");
- string cmdArgument = $"test -c {_buildConfiguration} --no-build /p:CollectCoverage=true /p:CoverletOutput=\"{testResultFile}\" /p:CoverletOutputFormat=\"cobertura%2cjson\" /p:UseSourceLink=true /p:Include=\"[coverletsample.integration.determisticbuild]*DeepThought\" /p:IncludeTestAssembly=true";
+ string cmdArgument = $"test -c {_buildConfiguration} -f {_buildTargetFramework} --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=\"cobertura%2cjson\" /p:UseSourceLink=true /p:Include=\"[coverletsample.integration.determisticbuild]*DeepThought\" /p:IncludeTestAssembly=true --results-directory:{testResultPath}";
_output.WriteLine($"Command: dotnet {cmdArgument}");
int result = DotnetCli(cmdArgument, out string standardOutput, out string standardError, _testProjectPath);
if (!string.IsNullOrEmpty(standardError))
@@ -165,9 +176,10 @@ public void Msbuild_SourceLink()
Assert.Equal(0, result);
Assert.Contains("Passed!", standardOutput);
Assert.Contains("| coverletsample.integration.determisticbuild | 100% | 100% | 100% |", standardOutput);
- Assert.True(File.Exists(testResultFile));
+ string testResultFile = Path.Join(_testProjectPath, $"coverage.{_buildTargetFramework}.json");
+ Assert.True(File.Exists(testResultFile), $"File '{testResultFile}' does not exist");
Assert.Contains("raw.githubusercontent.com", File.ReadAllText(testResultFile));
- AssertCoverage(standardOutput, checkDeterministicReport: false);
+ AssertCoverage(standardOutput, $"coverage.{_buildTargetFramework}.json", checkDeterministicReport: false);
CleanupBuildOutput();
}
@@ -183,7 +195,7 @@ public void Collectors()
DeleteLogFiles(testLogFilesPath);
DeleteCoverageFiles(testResultPath);
- DotnetCli($"build -c {_buildConfiguration} -bl:build.{logFilename} --verbosity normal /p:DeterministicSourcePaths=true", out string buildOutput, out string buildError, _testProjectPath);
+ DotnetCli($"build -c {_buildConfiguration} -f {_buildTargetFramework} -bl:build.{logFilename} --verbosity normal /p:DeterministicSourcePaths=true", out string buildOutput, out string buildError, _testProjectPath);
if (!string.IsNullOrEmpty(buildError))
{
_output.WriteLine(buildError);
@@ -193,14 +205,14 @@ public void Collectors()
_output.WriteLine(buildOutput);
}
Assert.Contains("Build succeeded.", buildOutput);
- string sourceRootMappingFilePath = Path.Combine(_testBinaryPath, _buildConfiguration.ToLowerInvariant(), "CoverletSourceRootsMapping_coverletsample.integration.determisticbuild");
+ string sourceRootMappingFilePath = Path.Combine(_testBinaryPath, _artifactsPivot.ToLowerInvariant(), "CoverletSourceRootsMapping_coverletsample.integration.determisticbuild");
Assert.True(File.Exists(sourceRootMappingFilePath), $"File not found: {sourceRootMappingFilePath}");
Assert.NotEmpty(File.ReadAllText(sourceRootMappingFilePath));
Assert.Contains("=/_/", File.ReadAllText(sourceRootMappingFilePath));
string runSettingsPath = AddCollectorRunsettingsFile(_testProjectPath, "[coverletsample.integration.determisticbuild]*DeepThought", deterministicReport: true);
- string cmdArgument = $"test -c {_buildConfiguration} --no-build --collect:\"XPlat Code Coverage\" --results-directory:\"{testResultPath}\" --settings \"{runSettingsPath}\" --diag:{Path.Combine(testLogFilesPath, "log.txt")}";
+ string cmdArgument = $"test -c {_buildConfiguration} -f {_buildTargetFramework} --no-build --collect:\"XPlat Code Coverage\" --results-directory:\"{testResultPath}\" --settings \"{runSettingsPath}\" --diag:{Path.Combine(testLogFilesPath, "log.txt")}";
_output.WriteLine($"Command: dotnet {cmdArgument}");
int result = DotnetCli(cmdArgument, out string standardOutput, out string standardError, _testProjectPath);
if (!string.IsNullOrEmpty(standardError))
@@ -213,7 +225,7 @@ public void Collectors()
}
Assert.Equal(0, result);
Assert.Contains("Passed!", standardOutput);
- AssertCoverage(standardOutput);
+ AssertCoverage(standardOutput, "coverage.json");
// delete irrelevant generated files
DeleteTestIntermediateFiles(testResultPath);
@@ -238,7 +250,7 @@ public void Collectors_SourceLink()
DeleteLogFiles(testLogFilesPath);
DeleteCoverageFiles(testResultPath);
- DotnetCli($"build -c {_buildConfiguration} -bl:build.{logFilename} --verbosity normal /p:DeterministicSourcePaths=true", out string buildOutput, out string buildError, _testProjectPath);
+ DotnetCli($"build -c {_buildConfiguration} -f {_buildTargetFramework} -bl:build.{logFilename} --verbosity normal /p:DeterministicSourcePaths=true", out string buildOutput, out string buildError, _testProjectPath);
if (!string.IsNullOrEmpty(buildError))
{
_output.WriteLine(buildError);
@@ -248,14 +260,14 @@ public void Collectors_SourceLink()
_output.WriteLine(buildOutput);
}
Assert.Contains("Build succeeded.", buildOutput);
- string sourceRootMappingFilePath = Path.Combine(_testBinaryPath, _buildConfiguration.ToLowerInvariant(), "CoverletSourceRootsMapping_coverletsample.integration.determisticbuild");
+ string sourceRootMappingFilePath = Path.Combine(_testBinaryPath, _artifactsPivot.ToLowerInvariant(), "CoverletSourceRootsMapping_coverletsample.integration.determisticbuild");
Assert.True(File.Exists(sourceRootMappingFilePath), $"File not found: {sourceRootMappingFilePath}");
Assert.NotEmpty(File.ReadAllText(sourceRootMappingFilePath));
Assert.Contains("=/_/", File.ReadAllText(sourceRootMappingFilePath));
string runSettingsPath = AddCollectorRunsettingsFile(_testProjectPath, "[coverletsample.integration.determisticbuild]*DeepThought", sourceLink: true);
- string cmdArgument = $"test -c {_buildConfiguration} --no-build --collect:\"XPlat Code Coverage\" --results-directory:\"{testResultPath}\" --settings \"{runSettingsPath}\" --diag:{Path.Combine(testLogFilesPath, "log.txt")}";
+ string cmdArgument = $"test -c {_buildConfiguration} -f {_buildTargetFramework} --no-build --collect:\"XPlat Code Coverage\" --results-directory:\"{testResultPath}\" --settings \"{runSettingsPath}\" --diag:{Path.Combine(testLogFilesPath, "log.txt")}";
_output.WriteLine($"Command: dotnet {cmdArgument}");
int result = DotnetCli(cmdArgument, out string standardOutput, out string standardError, _testProjectPath);
if (!string.IsNullOrEmpty(standardError))
@@ -268,7 +280,7 @@ public void Collectors_SourceLink()
}
Assert.Equal(0, result);
Assert.Contains("Passed!", standardOutput);
- AssertCoverage(standardOutput, checkDeterministicReport: false);
+ AssertCoverage(standardOutput, "coverage.json", checkDeterministicReport: false);
// delete irrelevant generated files
DeleteTestIntermediateFiles(testResultPath);
@@ -365,14 +377,14 @@ private static void DeleteCoverageFiles(string directory)
}
}
- private string GetReportPath(string standardOutput)
+ private string GetReportPath(string standardOutput, string reportFileName = "")
{
string reportPath = "";
- if (standardOutput.Contains("coverage.json"))
+ if (standardOutput.Contains(reportFileName))
{
- reportPath = standardOutput.Split('\n').FirstOrDefault(line => line.Contains("coverage.json"))!.TrimStart();
+ reportPath = standardOutput.Split('\n').FirstOrDefault(line => line.Contains(reportFileName))!.TrimStart();
reportPath = reportPath[reportPath.IndexOf(Directory.GetDirectoryRoot(_testProjectPath))..];
- reportPath = reportPath[..reportPath.IndexOf("coverage.json")];
+ reportPath = reportPath[..reportPath.IndexOf(reportFileName)];
}
return reportPath;
}
diff --git a/test/coverlet.integration.tests/DotnetTool.cs b/test/coverlet.integration.tests/DotnetTool.cs
index 91e989f02..c37e1156d 100644
--- a/test/coverlet.integration.tests/DotnetTool.cs
+++ b/test/coverlet.integration.tests/DotnetTool.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Toni Solarin-Sodara
+// Copyright (c) Toni Solarin-Sodara
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.IO;
diff --git a/test/coverlet.integration.tests/Msbuild.cs b/test/coverlet.integration.tests/Msbuild.cs
index abb784d10..86acea9fc 100644
--- a/test/coverlet.integration.tests/Msbuild.cs
+++ b/test/coverlet.integration.tests/Msbuild.cs
@@ -109,7 +109,7 @@ public void TestMsbuild_CoverletOutput_Folder_FileNameExtension()
public void TestMsbuild_CoverletOutput_Folder_FileNameExtension_SpecifyFramework()
{
using ClonedTemplateProject clonedTemplateProject = PrepareTemplateProject();
- string[] targetFrameworks = new string[] { "net6.0" };
+ string[] targetFrameworks = new string[] { "net8.0" };
UpdateProjectTargetFramework(clonedTemplateProject, targetFrameworks);
Assert.False(clonedTemplateProject.IsMultipleTargetFramework());
string framework = clonedTemplateProject.GetTargetFrameworks().Single();
@@ -152,7 +152,7 @@ public void TestMsbuild_CoverletOutput_Folder_FileNameWithDoubleExtension()
public void Test_MultipleTargetFrameworkReport_NoCoverletOutput()
{
using ClonedTemplateProject clonedTemplateProject = PrepareTemplateProject();
- string[] targetFrameworks = new string[] { "net6.0", "net8.0" };
+ string[] targetFrameworks = new string[] { "net9.0", "net8.0" };
UpdateProjectTargetFramework(clonedTemplateProject, targetFrameworks);
DotnetCli($"test -c {_buildConfiguration} \"{clonedTemplateProject.ProjectRootPath}\" /p:CollectCoverage=true /p:Include=\"[{ClonedTemplateProject.AssemblyName}]*DeepThought\" /p:IncludeTestAssembly=true", out string standardOutput, out string standardError, clonedTemplateProject.ProjectRootPath!);
if (!string.IsNullOrEmpty(standardError))
@@ -178,7 +178,7 @@ public void Test_MultipleTargetFrameworkReport_NoCoverletOutput()
public void Test_MultipleTargetFrameworkReport_CoverletOutput_Folder()
{
using ClonedTemplateProject clonedTemplateProject = PrepareTemplateProject();
- string[] targetFrameworks = new string[] { "net6.0", "net8.0" };
+ string[] targetFrameworks = new string[] { "net9.0", "net8.0" };
UpdateProjectTargetFramework(clonedTemplateProject, targetFrameworks);
int result = DotnetCli($"test -c {_buildConfiguration} \"{clonedTemplateProject.ProjectRootPath}\" /p:CollectCoverage=true /p:Include=\"[{ClonedTemplateProject.AssemblyName}]*DeepThought\" /p:IncludeTestAssembly=true /p:CoverletOutput=\"{clonedTemplateProject.ProjectRootPath}\"\\", out string standardOutput, out string standardError, clonedTemplateProject.ProjectRootPath!);
if (!string.IsNullOrEmpty(standardError))
@@ -206,7 +206,7 @@ public void Test_MultipleTargetFrameworkReport_CoverletOutput_Folder()
public void Test_MultipleTargetFrameworkReport_CoverletOutput_Folder_FileNameWithoutExtension()
{
using ClonedTemplateProject clonedTemplateProject = PrepareTemplateProject();
- string[] targetFrameworks = new string[] { "net6.0", "net8.0" };
+ string[] targetFrameworks = new string[] { "net9.0", "net8.0" };
UpdateProjectTargetFramework(clonedTemplateProject, targetFrameworks);
DotnetCli($"test -c {_buildConfiguration} \"{clonedTemplateProject.ProjectRootPath}\" /p:CollectCoverage=true /p:Include=\"[{ClonedTemplateProject.AssemblyName}]*DeepThought\" /p:IncludeTestAssembly=true /p:CoverletOutput=\"{clonedTemplateProject.ProjectRootPath}\"\\file", out string standardOutput, out string standardError, clonedTemplateProject.ProjectRootPath!);
if (!string.IsNullOrEmpty(standardError))
@@ -232,7 +232,7 @@ public void Test_MultipleTargetFrameworkReport_CoverletOutput_Folder_FileNameWit
public void Test_MultipleTargetFrameworkReport_CoverletOutput_Folder_FileNameWithExtension_SpecifyFramework()
{
using ClonedTemplateProject clonedTemplateProject = PrepareTemplateProject();
- string[] targetFrameworks = new string[] { "net6.0", "net8.0" };
+ string[] targetFrameworks = new string[] { "net9.0", "net8.0" };
UpdateProjectTargetFramework(clonedTemplateProject, targetFrameworks);
Assert.True(clonedTemplateProject.IsMultipleTargetFramework());
string[] frameworks = clonedTemplateProject.GetTargetFrameworks();
@@ -269,7 +269,7 @@ public void Test_MultipleTargetFrameworkReport_CoverletOutput_Folder_FileNameWit
public void Test_MultipleTargetFrameworkReport_CoverletOutput_Folder_FileNameWithExtension()
{
using ClonedTemplateProject clonedTemplateProject = PrepareTemplateProject();
- string[] targetFrameworks = new string[] { "net6.0", "net8.0" };
+ string[] targetFrameworks = new string[] { "net9.0", "net8.0" };
UpdateProjectTargetFramework(clonedTemplateProject, targetFrameworks);
DotnetCli($"test -c {_buildConfiguration} \"{clonedTemplateProject.ProjectRootPath}\" /p:CollectCoverage=true /p:Include=\"[{ClonedTemplateProject.AssemblyName}]*DeepThought\" /p:IncludeTestAssembly=true /p:CoverletOutput=\"{clonedTemplateProject.ProjectRootPath}\"\\file.ext", out string standardOutput, out string standardError, clonedTemplateProject.ProjectRootPath!);
if (!string.IsNullOrEmpty(standardError))
@@ -295,7 +295,7 @@ public void Test_MultipleTargetFrameworkReport_CoverletOutput_Folder_FileNameWit
public void Test_MultipleTargetFrameworkReport_CoverletOutput_Folder_FileNameWithDoubleExtension()
{
using ClonedTemplateProject clonedTemplateProject = PrepareTemplateProject();
- string[] targetFrameworks = new string[] { "net6.0", "net8.0" };
+ string[] targetFrameworks = new string[] { "net9.0", "net8.0" };
UpdateProjectTargetFramework(clonedTemplateProject, targetFrameworks);
DotnetCli($"test -c {_buildConfiguration} \"{clonedTemplateProject.ProjectRootPath}\" /p:CollectCoverage=true /p:Include=\"[{ClonedTemplateProject.AssemblyName}]*DeepThought\" /p:IncludeTestAssembly=true /p:CoverletOutput=\"{clonedTemplateProject.ProjectRootPath}\"\\file.ext1.ext2", out string standardOutput, out string standardError, clonedTemplateProject.ProjectRootPath!);
if (!string.IsNullOrEmpty(standardError))
diff --git a/test/coverlet.integration.tests/coverlet.integration.tests.csproj b/test/coverlet.integration.tests/coverlet.integration.tests.csproj
index 4c8cc9c50..5a1e8f02e 100644
--- a/test/coverlet.integration.tests/coverlet.integration.tests.csproj
+++ b/test/coverlet.integration.tests/coverlet.integration.tests.csproj
@@ -1,9 +1,8 @@
- net8.0
+ $(NetCurrent);$(NetMinimum)
Exe
true
- true
false
enable
false
@@ -17,13 +16,12 @@
+
all
runtime; build; native; contentfiles; analyzers
-
-
diff --git a/test/coverlet.msbuild.tasks.tests/coverlet.msbuild.tasks.tests.csproj b/test/coverlet.msbuild.tasks.tests/coverlet.msbuild.tasks.tests.csproj
index f363d52ac..1e77b344b 100644
--- a/test/coverlet.msbuild.tasks.tests/coverlet.msbuild.tasks.tests.csproj
+++ b/test/coverlet.msbuild.tasks.tests/coverlet.msbuild.tasks.tests.csproj
@@ -1,11 +1,9 @@
- net8.0
-
-
enable
true
false
@@ -20,7 +18,7 @@
-
+
@@ -38,6 +36,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
+
diff --git a/test/coverlet.tests.projectsample.aspmvcrazor/coverlet.tests.projectsample.aspmvcrazor.csproj b/test/coverlet.tests.projectsample.aspmvcrazor/coverlet.tests.projectsample.aspmvcrazor.csproj
index 6e46d7306..cf1079a1b 100644
--- a/test/coverlet.tests.projectsample.aspmvcrazor/coverlet.tests.projectsample.aspmvcrazor.csproj
+++ b/test/coverlet.tests.projectsample.aspmvcrazor/coverlet.tests.projectsample.aspmvcrazor.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net8.0
enable
false
false
diff --git a/test/coverlet.tests.utils/TestUtils.cs b/test/coverlet.tests.utils/TestUtils.cs
index f24f13399..8a89196ac 100644
--- a/test/coverlet.tests.utils/TestUtils.cs
+++ b/test/coverlet.tests.utils/TestUtils.cs
@@ -33,8 +33,8 @@ public static BuildConfiguration GetAssemblyBuildConfiguration()
public static string GetAssemblyTargetFramework()
{
-#if NET6_0
- return "net6.0";
+#if NET9_0
+ return "net9.0";
#endif
#if NET8_0
return "net8.0";
@@ -57,9 +57,9 @@ public static string GetPackagePath(string buildConfiguration)
return Path.Join(Path.GetFullPath(Path.Join(AppContext.BaseDirectory, s_rel3Parents)), "package", buildConfiguration);
}
- public static string GetTestResultsPath(string directoryName)
+ public static string GetTestResultsPath()
{
- return Path.Join(Path.GetFullPath(Path.Join(AppContext.BaseDirectory, s_rel3Parents)), "testresults", directoryName);
+ return Path.Join(Path.GetFullPath(Path.Join(AppContext.BaseDirectory, s_rel3Parents)), "reports");
}
}