From c5cd774650116cf1da3d93416758f50f8fed8488 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Apr 2024 11:46:23 +0100 Subject: [PATCH 01/33] [skip ci] Update release notes --- ReleaseNotes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 045a62fa..16245b8a 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -3,7 +3,9 @@ A. Start with the Quick Start guide : https://github.com/SteveGilham/altcover/wiki/QuickStart-Guide and read the FAQ : https://github.com/SteveGilham/altcover/wiki/FAQ -# (Habu series release 28) +# (Habu series release 29) + +# 8.8.21 (Habu series release 28) * [BREAKING; BUGFIX] Issue #206 : Update to net6+ for `dotnet test` integration and respect the `$(IsTestProject)` setting from the `Microsoft.NET.Test.Sdk` package. * Simplify the use of the AltCover MSBuild tasks via the associated package-level `.targets` file by not even including the `VSTest` integration unless both `'$(AltCover)' == 'true' AND '$(IsTestProject)' == 'true'`. * Mitigate instances of `System.IO.IOException: The process cannot access the file '[coverage report]' because it is being used by another process.` From 6535a4df747265bf2810ff89f1035fd735b816f6 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sun, 28 Apr 2024 11:37:03 +0100 Subject: [PATCH 02/33] Exercise the separate output file option. --- Build/targets.fs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Build/targets.fs b/Build/targets.fs index e2ac8ef4..7f606960 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -2376,7 +2376,7 @@ module Targets = let prep = AltCover.PrepareOptions.TypeSafe( { TypeSafe.PrepareOptions.Create() with - Report = TypeSafe.FilePath altReport + Report = TypeSafe.FilePath (testDirectory @@ coverageReport) OutputDirectories = TypeSafe.DirectoryPaths [| TypeSafe.DirectoryPath outputDirectory |] StrongNameKey = TypeSafe.FilePath signingKey @@ -2409,6 +2409,7 @@ module Targets = AltCover.CollectOptions.TypeSafe { TypeSafe.CollectOptions.Create() with Executable = TypeSafe.FilePath nunitConsole + OutputFile = TypeSafe.FilePath altReport RecorderDirectory = TypeSafe.DirectoryPath(testDirectory @@ outputDirectory) CommandLine = From 5922d7d7071f2e5e80dd4748c2c1fcbe07d732a6 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sun, 28 Apr 2024 16:06:47 +0100 Subject: [PATCH 03/33] Work around a Defender false positive with the instrumented plain net2.0 binary --- AltCover.Tests/Tests.fs | 2 +- Build/actions.fs | 5 +++-- Build/targets.fs | 12 +++++++----- Samples/Sample1/Sample1.csproj | 6 +++++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/AltCover.Tests/Tests.fs b/AltCover.Tests/Tests.fs index cb6a4af3..f13508df 100644 --- a/AltCover.Tests/Tests.fs +++ b/AltCover.Tests/Tests.fs @@ -82,7 +82,7 @@ module AltCoverTests = Path.Combine(SolutionDir(), "_Mono/Sample1/Sample1.exe") let sample1path = - Path.Combine(SolutionDir(), "_Binaries/Sample1/Debug+AnyCPU/net20/Sample1.exe") + Path.Combine(SolutionDir(), "_Binaries/Sample1/Debug+AnyCPU/net472/Sample1.exe") #if !NET472 let sample4path = diff --git a/Build/actions.fs b/Build/actions.fs index 1f20ad33..df46871d 100644 --- a/Build/actions.fs +++ b/Build/actions.fs @@ -304,6 +304,7 @@ using System.Runtime.CompilerServices; let recorded = coverageDocument.Descendants(XName.Get("seqpnt")) + |> Seq.filter (fun x -> x.Attribute(XName.Get("excluded")).Value <> "true") |> Seq.toList let zero = @@ -420,7 +421,7 @@ using System.Runtime.CompilerServices; AltCover.PrepareOptions.Primitive { Primitive.PrepareOptions.Create() with // Verbosity = System.Diagnostics.TraceLevel.Verbose - TypeFilter = [ """System\.""" ] + TypeFilter = [ """System\.""" ; "Foo" ] Report = simpleReport OutputDirectories = [| "./" + instrumented |] ReportFormat = "NCover" @@ -475,7 +476,7 @@ using System.Runtime.CompilerServices; let prep = AltCover.PrepareOptions.Primitive { Primitive.PrepareOptions.Create() with - TypeFilter = [ """System\.""" ] + TypeFilter = [ """System\.""" ; "Foo" ] Report = simpleReport OutputDirectories = [| "./" + instrumented |] ReportFormat = "NCover" diff --git a/Build/targets.fs b/Build/targets.fs index 7f606960..7ae0cd6b 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -3385,7 +3385,7 @@ module Targets = Report = x OutputDirectories = [ o ] InputDirectories = [ i ] - TypeFilter = [ "System\\." ] + TypeFilter = [ "System\\."; "Foo" ] InPlace = false ReportFormat = "NCover" Save = false } @@ -3423,7 +3423,7 @@ module Targets = Report = x OutputDirectories = [ o ] InputDirectories = [ i ] - TypeFilter = [ "System\\." ] + TypeFilter = [ "System\\."; "Foo" ] InPlace = false ReportFormat = "NCover" Save = false } @@ -3468,7 +3468,7 @@ module Targets = { Primitive.PrepareOptions.Create() with Report = simpleReport OutputDirectories = [| instrumented |] - TypeFilter = [ "System\\."; "Microsoft\\." ] + TypeFilter = [ "System\\."; "Microsoft\\."; "Foo" ] InPlace = false ReportFormat = "NCover" Save = false } @@ -4741,7 +4741,7 @@ module Targets = let prep = AltCover.PrepareOptions.Primitive { Primitive.PrepareOptions.Create() with - TypeFilter = [ """System\.""" ] + TypeFilter = [ """System\."""; "Foo" ] Report = simpleReport OutputDirectories = [| "./" + instrumented |] ReportFormat = "NCover" @@ -4817,7 +4817,7 @@ module Targets = { Primitive.PrepareOptions.Create() with Report = simpleReport OutputDirectories = [ instrumented ] - TypeFilter = [ "System\\."; "Microsoft\\." ] + TypeFilter = [ "System\\."; "Microsoft\\."; "Foo" ] InPlace = false ReportFormat = "NCover" Save = false } @@ -4863,6 +4863,7 @@ module Targets = Report = x OutputDirectories = [ o ] InputDirectories = [ i ] + TypeFilter = [ "System\\."; "Microsoft\\."; "Foo" ] InPlace = false ReportFormat = "NCover" Save = false } @@ -4903,6 +4904,7 @@ module Targets = Report = x OutputDirectories = [ o ] InputDirectories = [ i ] + TypeFilter = [ "System\\."; "Microsoft\\."; "Foo" ] InPlace = false ReportFormat = "NCover" Save = false } diff --git a/Samples/Sample1/Sample1.csproj b/Samples/Sample1/Sample1.csproj index 5ce37ea5..5a3e75bc 100644 --- a/Samples/Sample1/Sample1.csproj +++ b/Samples/Sample1/Sample1.csproj @@ -2,7 +2,7 @@ Exe - net8.0;net20 + net8.0;net20;net472 Sample1 false @@ -10,4 +10,8 @@ + + + + \ No newline at end of file From fe11f4630b5d2d925fb7b276faf4e52fc82d7f92 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sun, 28 Apr 2024 18:03:42 +0100 Subject: [PATCH 04/33] Revert "Work around a Defender false positive with the instrumented plain net2.0 binary" This reverts commit 5922d7d7071f2e5e80dd4748c2c1fcbe07d732a6. --- AltCover.Tests/Tests.fs | 2 +- Build/actions.fs | 5 ++--- Build/targets.fs | 12 +++++------- Samples/Sample1/Sample1.csproj | 6 +----- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/AltCover.Tests/Tests.fs b/AltCover.Tests/Tests.fs index f13508df..cb6a4af3 100644 --- a/AltCover.Tests/Tests.fs +++ b/AltCover.Tests/Tests.fs @@ -82,7 +82,7 @@ module AltCoverTests = Path.Combine(SolutionDir(), "_Mono/Sample1/Sample1.exe") let sample1path = - Path.Combine(SolutionDir(), "_Binaries/Sample1/Debug+AnyCPU/net472/Sample1.exe") + Path.Combine(SolutionDir(), "_Binaries/Sample1/Debug+AnyCPU/net20/Sample1.exe") #if !NET472 let sample4path = diff --git a/Build/actions.fs b/Build/actions.fs index df46871d..1f20ad33 100644 --- a/Build/actions.fs +++ b/Build/actions.fs @@ -304,7 +304,6 @@ using System.Runtime.CompilerServices; let recorded = coverageDocument.Descendants(XName.Get("seqpnt")) - |> Seq.filter (fun x -> x.Attribute(XName.Get("excluded")).Value <> "true") |> Seq.toList let zero = @@ -421,7 +420,7 @@ using System.Runtime.CompilerServices; AltCover.PrepareOptions.Primitive { Primitive.PrepareOptions.Create() with // Verbosity = System.Diagnostics.TraceLevel.Verbose - TypeFilter = [ """System\.""" ; "Foo" ] + TypeFilter = [ """System\.""" ] Report = simpleReport OutputDirectories = [| "./" + instrumented |] ReportFormat = "NCover" @@ -476,7 +475,7 @@ using System.Runtime.CompilerServices; let prep = AltCover.PrepareOptions.Primitive { Primitive.PrepareOptions.Create() with - TypeFilter = [ """System\.""" ; "Foo" ] + TypeFilter = [ """System\.""" ] Report = simpleReport OutputDirectories = [| "./" + instrumented |] ReportFormat = "NCover" diff --git a/Build/targets.fs b/Build/targets.fs index 7ae0cd6b..7f606960 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -3385,7 +3385,7 @@ module Targets = Report = x OutputDirectories = [ o ] InputDirectories = [ i ] - TypeFilter = [ "System\\."; "Foo" ] + TypeFilter = [ "System\\." ] InPlace = false ReportFormat = "NCover" Save = false } @@ -3423,7 +3423,7 @@ module Targets = Report = x OutputDirectories = [ o ] InputDirectories = [ i ] - TypeFilter = [ "System\\."; "Foo" ] + TypeFilter = [ "System\\." ] InPlace = false ReportFormat = "NCover" Save = false } @@ -3468,7 +3468,7 @@ module Targets = { Primitive.PrepareOptions.Create() with Report = simpleReport OutputDirectories = [| instrumented |] - TypeFilter = [ "System\\."; "Microsoft\\."; "Foo" ] + TypeFilter = [ "System\\."; "Microsoft\\." ] InPlace = false ReportFormat = "NCover" Save = false } @@ -4741,7 +4741,7 @@ module Targets = let prep = AltCover.PrepareOptions.Primitive { Primitive.PrepareOptions.Create() with - TypeFilter = [ """System\."""; "Foo" ] + TypeFilter = [ """System\.""" ] Report = simpleReport OutputDirectories = [| "./" + instrumented |] ReportFormat = "NCover" @@ -4817,7 +4817,7 @@ module Targets = { Primitive.PrepareOptions.Create() with Report = simpleReport OutputDirectories = [ instrumented ] - TypeFilter = [ "System\\."; "Microsoft\\."; "Foo" ] + TypeFilter = [ "System\\."; "Microsoft\\." ] InPlace = false ReportFormat = "NCover" Save = false } @@ -4863,7 +4863,6 @@ module Targets = Report = x OutputDirectories = [ o ] InputDirectories = [ i ] - TypeFilter = [ "System\\."; "Microsoft\\."; "Foo" ] InPlace = false ReportFormat = "NCover" Save = false } @@ -4904,7 +4903,6 @@ module Targets = Report = x OutputDirectories = [ o ] InputDirectories = [ i ] - TypeFilter = [ "System\\."; "Microsoft\\."; "Foo" ] InPlace = false ReportFormat = "NCover" Save = false } diff --git a/Samples/Sample1/Sample1.csproj b/Samples/Sample1/Sample1.csproj index 5a3e75bc..5ce37ea5 100644 --- a/Samples/Sample1/Sample1.csproj +++ b/Samples/Sample1/Sample1.csproj @@ -2,7 +2,7 @@ Exe - net8.0;net20;net472 + net8.0;net20 Sample1 false @@ -10,8 +10,4 @@ - - - - \ No newline at end of file From 05302fdaa50f8d536a0d1711f1e7c1211a347d79 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sun, 28 Apr 2024 19:29:01 +0100 Subject: [PATCH 05/33] Instrumented sample1 is not a trojan, ffs --- AltCover.Tests/Runner.Tests.fs | 6 +++--- AltCover.Tests/Tests3.fs | 4 ++-- Samples/Sample1/Program.cs | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index 7eb938a9..85031643 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -771,7 +771,7 @@ module AltCoverRunnerTests = + args + "\'" + Environment.NewLine - + "Where is my rocket pack? " + + "Now " + Environment.NewLine Assert.That(result, Is.EqualTo(expected)) @@ -2501,7 +2501,7 @@ module AltCoverRunnerTests = + String.Join(" ", args.Tail) + "'" + Environment.NewLine - + "Where is my rocket pack? " + + "Now " + u1 + "*" + u2 @@ -2721,7 +2721,7 @@ module AltCoverRunnerTests = + String.Join(" ", args.Tail) + "'" + Environment.NewLine - + "Where is my rocket pack? " + + "Now " + u1 + "*" + u2 diff --git a/AltCover.Tests/Tests3.fs b/AltCover.Tests/Tests3.fs index 565810e8..4ef17f1b 100644 --- a/AltCover.Tests/Tests3.fs +++ b/AltCover.Tests/Tests3.fs @@ -83,7 +83,7 @@ module AltCoverTests3 = + args + "\'" + Environment.NewLine - + "Where is my rocket pack? " + + "Now " + Environment.NewLine Assert.That(result, Is.EqualTo(expected)) @@ -3538,7 +3538,7 @@ module AltCoverTests3 = + String.Join(" ", args.Tail) + "'" + Environment.NewLine - + "Where is my rocket pack? " + + "Now " + u1 + "*" + u2 diff --git a/Samples/Sample1/Program.cs b/Samples/Sample1/Program.cs index 6f323cfd..79521115 100644 --- a/Samples/Sample1/Program.cs +++ b/Samples/Sample1/Program.cs @@ -10,13 +10,13 @@ internal class Program private static void Main(string[] args) { var now = DateTime.Now; - if (now.Year > 2000) + if (now.Year > 2023) { - Console.WriteLine("Where is my rocket pack? " + String.Join("*", args)); + Console.WriteLine("Now " + String.Join("*", args)); } else { - Console.WriteLine("Twentieth Century, boy!"); + Console.WriteLine("Th" + "en"); } } } From afa719ec11a4d920107aaba4f229eabbb951a0b7 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sun, 28 Apr 2024 19:29:14 +0100 Subject: [PATCH 06/33] fantomas --- Build/targets.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Build/targets.fs b/Build/targets.fs index 7f606960..6f109b98 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -2376,7 +2376,7 @@ module Targets = let prep = AltCover.PrepareOptions.TypeSafe( { TypeSafe.PrepareOptions.Create() with - Report = TypeSafe.FilePath (testDirectory @@ coverageReport) + Report = TypeSafe.FilePath(testDirectory @@ coverageReport) OutputDirectories = TypeSafe.DirectoryPaths [| TypeSafe.DirectoryPath outputDirectory |] StrongNameKey = TypeSafe.FilePath signingKey From 6c71308f874f623e9efa8b8a63e23ead0542dbdd Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sun, 28 Apr 2024 20:12:48 +0100 Subject: [PATCH 07/33] Revert "Instrumented sample1 is not a trojan, ffs" This reverts commit 05302fdaa50f8d536a0d1711f1e7c1211a347d79. (cherry picked from commit 4757b4e0236e57976b0011e693dbf240777f6382) --- AltCover.Tests/Runner.Tests.fs | 6 +++--- AltCover.Tests/Tests3.fs | 4 ++-- Samples/Sample1/Program.cs | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index 85031643..7eb938a9 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -771,7 +771,7 @@ module AltCoverRunnerTests = + args + "\'" + Environment.NewLine - + "Now " + + "Where is my rocket pack? " + Environment.NewLine Assert.That(result, Is.EqualTo(expected)) @@ -2501,7 +2501,7 @@ module AltCoverRunnerTests = + String.Join(" ", args.Tail) + "'" + Environment.NewLine - + "Now " + + "Where is my rocket pack? " + u1 + "*" + u2 @@ -2721,7 +2721,7 @@ module AltCoverRunnerTests = + String.Join(" ", args.Tail) + "'" + Environment.NewLine - + "Now " + + "Where is my rocket pack? " + u1 + "*" + u2 diff --git a/AltCover.Tests/Tests3.fs b/AltCover.Tests/Tests3.fs index 4ef17f1b..565810e8 100644 --- a/AltCover.Tests/Tests3.fs +++ b/AltCover.Tests/Tests3.fs @@ -83,7 +83,7 @@ module AltCoverTests3 = + args + "\'" + Environment.NewLine - + "Now " + + "Where is my rocket pack? " + Environment.NewLine Assert.That(result, Is.EqualTo(expected)) @@ -3538,7 +3538,7 @@ module AltCoverTests3 = + String.Join(" ", args.Tail) + "'" + Environment.NewLine - + "Now " + + "Where is my rocket pack? " + u1 + "*" + u2 diff --git a/Samples/Sample1/Program.cs b/Samples/Sample1/Program.cs index 79521115..6f323cfd 100644 --- a/Samples/Sample1/Program.cs +++ b/Samples/Sample1/Program.cs @@ -10,13 +10,13 @@ internal class Program private static void Main(string[] args) { var now = DateTime.Now; - if (now.Year > 2023) + if (now.Year > 2000) { - Console.WriteLine("Now " + String.Join("*", args)); + Console.WriteLine("Where is my rocket pack? " + String.Join("*", args)); } else { - Console.WriteLine("Th" + "en"); + Console.WriteLine("Twentieth Century, boy!"); } } } From cf6816f4de2ae171fe4d9b9469fc288acedf8de2 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sun, 28 Apr 2024 20:42:06 +0100 Subject: [PATCH 08/33] Fix one, stop one --- Build/targets.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Build/targets.fs b/Build/targets.fs index 6f109b98..caef806d 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -4730,7 +4730,7 @@ module Targets = let binRoot = Path.getFullName binaryPath let sampleRoot = - Path.getFullName "_Binaries/Sample1/Debug+AnyCPU/net20" + Path.getFullName "_Mono/Sample1" let instrumented = "__Instrumented." + reportSigil @@ -8284,7 +8284,7 @@ module Targets = _Target "FSAsyncTests" FSAsyncTests _Target "FSharpTypesDotNetRunner" FSharpTypesDotNetRunner _Target "FSharpTypesDotNetCollecter" FSharpTypesDotNetCollecter - _Target "BasicCSharp" BasicCSharp + _Target "BasicCSharp" ignore // virus false +ve // BasicCSharp _Target "BasicCSharpMono" BasicCSharpMono _Target "BasicCSharpUnderMono" BasicCSharpUnderMono _Target "BasicCSharpMonoUnderMono" BasicCSharpMonoUnderMono From 9150719c37e9d10d8582d1278663c198b647c817 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sun, 28 Apr 2024 20:43:15 +0100 Subject: [PATCH 09/33] Convenience --- AltCover.sln | 1 + 1 file changed, 1 insertion(+) diff --git a/AltCover.sln b/AltCover.sln index 222e0b98..3f1d2dd1 100644 --- a/AltCover.sln +++ b/AltCover.sln @@ -35,6 +35,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Items", "Build Items", "{97367D43-64EF-48E1-B6B4-D951C783E6E1}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig + .fantomasignore = .fantomasignore Build\actions.fs = Build\actions.fs Build\AddStrongName.fsx = Build\AddStrongName.fsx Build\AltCover.nuspec = Build\AltCover.nuspec From 89baebc14cf75e54021177d34b0c7fe60a5ff6d1 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sun, 28 Apr 2024 21:38:13 +0100 Subject: [PATCH 10/33] Minimum net20 proof of concept replacement --- AltCover.sln | 8 +++ Build/targets.fs | 89 +++++++++++++++++++++++++++++++++- Samples/Sample0/Program.cs | 2 + Samples/Sample0/Sample0.csproj | 9 ++++ 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 Samples/Sample0/Program.cs create mode 100644 Samples/Sample0/Sample0.csproj diff --git a/AltCover.sln b/AltCover.sln index 3f1d2dd1..29f131e7 100644 --- a/AltCover.sln +++ b/AltCover.sln @@ -136,6 +136,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cecil", "Cecil", "{F56DE54A ThirdParty\cecil\Mono.Cecil.Rocks.pdb = ThirdParty\cecil\Mono.Cecil.Rocks.pdb EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample0", "Samples\Sample0\Sample0.csproj", "{19CE63CE-3622-409A-974D-3EA01388317E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -330,6 +332,11 @@ Global {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Debug|x86.Build.0 = Debug|Any CPU {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Release|Any CPU.ActiveCfg = Release|Any CPU {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Release|x86.ActiveCfg = Release|Any CPU + {19CE63CE-3622-409A-974D-3EA01388317E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19CE63CE-3622-409A-974D-3EA01388317E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19CE63CE-3622-409A-974D-3EA01388317E}.Debug|x86.ActiveCfg = Debug|Any CPU + {19CE63CE-3622-409A-974D-3EA01388317E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19CE63CE-3622-409A-974D-3EA01388317E}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -356,6 +363,7 @@ Global {10FB27A2-9C4D-474D-A3B9-1C554038AA7E} = {2837CE07-B91F-4B8A-89B5-E7BE39A8F340} {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881} = {2837CE07-B91F-4B8A-89B5-E7BE39A8F340} {F56DE54A-ABD6-42F7-B61E-7BAFCCF2D787} = {97367D43-64EF-48E1-B6B4-D951C783E6E1} + {19CE63CE-3622-409A-974D-3EA01388317E} = {2837CE07-B91F-4B8A-89B5-E7BE39A8F340} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C31111CF-68A2-403F-9B06-9625FCBD48E3} diff --git a/Build/targets.fs b/Build/targets.fs index caef806d..4e75be90 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -3334,6 +3334,93 @@ module Targets = Actions.ValidateFSharpTypesCoverage simpleReport2) + let BasicCSharp0 = + (fun () -> + let samplePath = + "_Binaries/Sample0/Debug+AnyCPU/net20" + + let binaryPath = + "_Binaries/AltCover/Release+AnyCPU/net472" + + let reportSigil = "BasicCSharp0" + + printfn "Instrument and run a simple executable" + Directory.ensure "./_Reports" + + let simpleReport = + (Path.getFullName "./_Reports") + @@ (reportSigil + ".xml") + + let binRoot = Path.getFullName binaryPath + let sampleRoot = Path.getFullName samplePath + + let instrumented = + "__Instrumented." + reportSigil + + let framework = + Fake.DotNet.ToolType.CreateFullFramework() + + let prep = + AltCover.PrepareOptions.Primitive + { Primitive.PrepareOptions.Create() with + // Verbosity = System.Diagnostics.TraceLevel.Verbose + TypeFilter = [ """System\.""" ] + Report = simpleReport + OutputDirectories = [| "./" + instrumented |] + ReportFormat = "NCover" + InPlace = false + Save = false } + |> AltCoverCommand.Prepare + + let parameters = + { AltCoverCommand.Options.Create prep with + ToolPath = binRoot @@ "AltCover.exe" + ToolType = framework + WorkingDirectory = sampleRoot } + + AltCoverCommand.run parameters + System.Threading.Thread.Sleep(1000) + + Actions.Run + (sampleRoot @@ (instrumented + "/Sample0.exe"), (sampleRoot @@ instrumented), []) + "Instrumented .exe failed" + + System.Threading.Thread.Sleep(1000) + + use coverageFile = // fsharplint:disable-next-line RedundantNewKeyword + new FileStream( + simpleReport, + FileMode.Open, + FileAccess.Read, + FileShare.None, + 4096, + FileOptions.SequentialScan + ) + + use reader = XmlReader.Create(coverageFile) + + let coverageDocument = + XDocument.Load(reader) + + let recorded = + coverageDocument.Descendants(XName.Get("seqpnt")) + |> Seq.toList + + Assert.That( + List.length recorded, + Is.EqualTo 1, + "unexpected points in " + reportSigil + ) + + let ones = + recorded + |> Seq.filter (fun x -> x.Attribute(XName.Get("visitcount")).Value = "1") + |> Seq.map _.Attribute(XName.Get("line")).Value + |> Seq.sort + |> Seq.toList + + Assert.That(List.length ones, Is.EqualTo 1, "unexpected visits in " + reportSigil)) + let BasicCSharp = (fun () -> Actions.SimpleInstrumentingRun @@ -8284,7 +8371,7 @@ module Targets = _Target "FSAsyncTests" FSAsyncTests _Target "FSharpTypesDotNetRunner" FSharpTypesDotNetRunner _Target "FSharpTypesDotNetCollecter" FSharpTypesDotNetCollecter - _Target "BasicCSharp" ignore // virus false +ve // BasicCSharp + _Target "BasicCSharp" BasicCSharp0 // virus false +ve // BasicCSharp _Target "BasicCSharpMono" BasicCSharpMono _Target "BasicCSharpUnderMono" BasicCSharpUnderMono _Target "BasicCSharpMonoUnderMono" BasicCSharpMonoUnderMono diff --git a/Samples/Sample0/Program.cs b/Samples/Sample0/Program.cs new file mode 100644 index 00000000..194e1bfc --- /dev/null +++ b/Samples/Sample0/Program.cs @@ -0,0 +1,2 @@ +// See https://aka.ms/new-console-template for more information +System.Console.WriteLine("Hello, World!"); \ No newline at end of file diff --git a/Samples/Sample0/Sample0.csproj b/Samples/Sample0/Sample0.csproj new file mode 100644 index 00000000..0a89fbea --- /dev/null +++ b/Samples/Sample0/Sample0.csproj @@ -0,0 +1,9 @@ + + + + Exe + net20 + 9.0 + + + From 29e492d41e5642116d0f2bf7207c0c1ce0973c70 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 29 Apr 2024 07:49:21 +0100 Subject: [PATCH 11/33] Summarise the output document correctly --- AltCover.Engine/Runner.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 4a7dc9e9..9c9021b5 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1514,7 +1514,7 @@ module internal Runner = |> Seq.iter File.Delete let document = - DocumentType.LoadReport format report + DocumentType.LoadReport format (Option.defaultValue report output) J.doSummaries document format result) 255 From ce4855dc2fb6d0a4b6ce0934874b4e1f0cbd70b2 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 29 Apr 2024 08:41:20 +0100 Subject: [PATCH 12/33] Fantomas convenience --- .fantomasignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.fantomasignore b/.fantomasignore index 01a3035b..ea4b0bf9 100644 --- a/.fantomasignore +++ b/.fantomasignore @@ -1,3 +1,4 @@ # Ignore interfaces (documentation annotations) *.fsi -Abstract.fs \ No newline at end of file +Abstract.fs +Recorder.fs \ No newline at end of file From fb92eee9ff504c3f1243f9fea01f7694736abd75 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 29 Apr 2024 09:30:14 +0100 Subject: [PATCH 13/33] Shuffle dependency resolution order nuget > gac > dotnet shared --- AltCover.Engine/CecilEx.fs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/AltCover.Engine/CecilEx.fs b/AltCover.Engine/CecilEx.fs index fb7927fb..0ce9f502 100644 --- a/AltCover.Engine/CecilEx.fs +++ b/AltCover.Engine/CecilEx.fs @@ -140,21 +140,21 @@ type internal AssemblyResolver() as self = let sources = [ AssemblyConstants.packageEnv - [ Environment.GetEnvironmentVariable "ProgramFiles" - |> Option.ofObj - |> Option.map (fun p -> Path.Combine(p, dotnetShared)) - Some <| Path.Combine(share, dotnetShared) - Some <| Path.Combine(shareLocal, dotnetShared) - AssemblyConstants.dotnetDir - |> Option.map (fun p -> Path.Combine(p, "shared")) - Some AssemblyConstants.nugetCache + [ Some AssemblyConstants.nugetCache Some <| Path.Combine("usr", monogac) Environment.GetEnvironmentVariable "WinDir" |> Option.ofObj |> Option.map (fun p -> Path.Combine(p, wingac)) Environment.GetEnvironmentVariable "MONO_GAC_PREFIX" |> Option.ofObj - |> Option.map (fun p -> Path.Combine(p, monogac)) ] + |> Option.map (fun p -> Path.Combine(p, monogac)) + Environment.GetEnvironmentVariable "ProgramFiles" + |> Option.ofObj + |> Option.map (fun p -> Path.Combine(p, dotnetShared)) + Some <| Path.Combine(share, dotnetShared) + Some <| Path.Combine(shareLocal, dotnetShared) + AssemblyConstants.dotnetDir + |> Option.map (fun p -> Path.Combine(p, "shared")) ] |> List.choose id ] |> List.concat |> List.filter Directory.Exists From 1d8661e59ea280bf2df87634efa8d73289b92976 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 29 Apr 2024 14:10:06 +0100 Subject: [PATCH 14/33] Passes unit tests and current optests with complete cover --- AltCover.Engine/CommandLine.fs | 8 +++++++- AltCover.Engine/NativeJson.fs | 31 ++++++++++++++++++++++++------- AltCover.Engine/Runner.fs | 2 +- AltCover.Tests/Runner.Tests.fs | 4 +++- AltCover.Tests/XTests.fs | 6 ++++-- 5 files changed, 39 insertions(+), 12 deletions(-) diff --git a/AltCover.Engine/CommandLine.fs b/AltCover.Engine/CommandLine.fs index ac31ac2d..5b3693d1 100644 --- a/AltCover.Engine/CommandLine.fs +++ b/AltCover.Engine/CommandLine.fs @@ -100,6 +100,12 @@ module internal Zip = else (null, new MemoryStream() :> Stream) + let internal openUpdateReport format (report: string) = + let container, stream = openUpdate report + use _ = container + use _ = stream + DocumentType.LoadReportStream format stream + type internal StringSink = Action module internal CommandLine = @@ -496,6 +502,6 @@ module internal CommandLine = "InstantiateArgumentExceptionCorrectlyRule", Scope = "member", // MethodDefinition Target = - "AltCover.CommandLine/I/transform@288::Invoke(System.String[])", + "AltCover.CommandLine/I/transform@294::Invoke(System.String[])", Justification = "Inlined library code")>] () \ No newline at end of file diff --git a/AltCover.Engine/NativeJson.fs b/AltCover.Engine/NativeJson.fs index b13a3479..6f024306 100644 --- a/AltCover.Engine/NativeJson.fs +++ b/AltCover.Engine/NativeJson.fs @@ -1235,10 +1235,15 @@ module x #endif - let internal fileToJson filename = +#if GUI + let fileToJson filename = filename |> File.ReadAllText |> fromJsonText - +#else // RUNNER + let internal streamToJson (stream:Stream) = + use r = new StreamReader(stream) + r.ReadToEnd() |> fromJsonText #endif +#endif // GUI || RUNNER #if RUNNER // Instrumentation --------------------------------------------------------- @@ -1421,17 +1426,29 @@ type internal DocumentType = | XML of XDocument | JSON of NativeJson.Modules | Unknown - static member internal LoadReport format report = - if File.Exists report then + //static member internal LoadReport format report = + // if File.Exists report then + // if + // format = ReportFormat.NativeJson + // || format = ReportFormat.NativeJsonWithTracking + // then + // report |> NativeJson.fileToJson |> JSON + // else + // report |> XDocument.Load |> XML + // else + // Unknown + + static member internal LoadReportStream format (report:Stream) = + if report.Length > 0 then if format = ReportFormat.NativeJson || format = ReportFormat.NativeJsonWithTracking then - report |> NativeJson.fileToJson |> JSON + report |> NativeJson.streamToJson |> JSON else report |> XDocument.Load |> XML - else - Unknown + else Unknown + #endif #if GUI || RUNNER diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 9c9021b5..4796665f 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1514,7 +1514,7 @@ module internal Runner = |> Seq.iter File.Delete let document = - DocumentType.LoadReport format (Option.defaultValue report output) + Zip.openUpdateReport format (Option.defaultValue report output) J.doSummaries document format result) 255 diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index 7eb938a9..62ec1c09 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -3407,8 +3407,10 @@ module AltCoverRunnerTests = Assert.That(r, Is.EqualTo 0) Assert.That(File.Exists(unique + ".acv") |> not) + use stream = new MemoryStream() + let doc = - DocumentType.LoadReport ReportFormat.OpenCover (unique + ".acv") + DocumentType.LoadReportStream ReportFormat.OpenCover stream Assert.That(doc, Is.EqualTo DocumentType.Unknown) Assert.That(counts, Is.Empty) diff --git a/AltCover.Tests/XTests.fs b/AltCover.Tests/XTests.fs index 9aa20b0b..4ade9197 100644 --- a/AltCover.Tests/XTests.fs +++ b/AltCover.Tests/XTests.fs @@ -909,7 +909,8 @@ module AltCoverXTests = test <@ String.Join("; ", actualFiles) = String.Join("; ", theFiles) @> let recordedJson = - match DocumentType.LoadReport CoverageParameters.theReportFormat.Value report with + use stream = File.OpenRead report + match DocumentType.LoadReportStream CoverageParameters.theReportFormat.Value stream with | JSON j -> j test <@ recordedJson.Keys |> Seq.toList = [ "Sample4.dll" ] @> @@ -1155,7 +1156,8 @@ module AltCoverXTests = XDocument.Load(new StringReader(expectedText)) let recordedXml = - match DocumentType.LoadReport ReportFormat.OpenCover report with + use stream = File.OpenRead report + match DocumentType.LoadReportStream ReportFormat.OpenCover stream with | XML x -> x RecursiveValidate (recordedXml.Elements()) (expectedXml.Elements()) 0 true From 1d815a696596f715c15a9123691dfd7d68e09c10 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 29 Apr 2024 14:16:47 +0100 Subject: [PATCH 15/33] More mono GAC --- AltCover.Engine/CecilEx.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/AltCover.Engine/CecilEx.fs b/AltCover.Engine/CecilEx.fs index 0ce9f502..5b6804ff 100644 --- a/AltCover.Engine/CecilEx.fs +++ b/AltCover.Engine/CecilEx.fs @@ -145,6 +145,7 @@ type internal AssemblyResolver() as self = Environment.GetEnvironmentVariable "WinDir" |> Option.ofObj |> Option.map (fun p -> Path.Combine(p, wingac)) + Some <| Path.Combine("usr", monogac) Environment.GetEnvironmentVariable "MONO_GAC_PREFIX" |> Option.ofObj |> Option.map (fun p -> Path.Combine(p, monogac)) From 881bc48657d4e4a97bb04cf4049d87d1163ca18f Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 9 May 2024 16:21:37 +0100 Subject: [PATCH 16/33] Report format to flags - tests pass but 7 uncovered lines --- AltCover.Engine/CecilEx.fs | 2 +- AltCover.Engine/Main.fs | 7 +- AltCover.Engine/NativeJson.fs | 12 +- AltCover.Engine/PostProcess.fs | 5 +- AltCover.Engine/Runner.fs | 5 +- AltCover.Engine/Visitor.fs | 32 ++- AltCover.Recorder.Tests/Recorder.Tests.fs | 237 ++++++++++-------- AltCover.Recorder/Base.fs | 26 +- AltCover.Recorder/Recorder.fs | 14 +- .../AltCover.RecorderModern.Tests.fsproj | 55 ++++ .../AltCover.RecorderModern.fsproj | 56 +++++ AltCover.Tests/Tests.fs | 15 +- AltCover.Tests/Tests2.fs | 13 +- AltCover.Tests/XTests.fs | 6 +- AltCover.sln | 17 +- Build/actions.fs | 1 + 16 files changed, 340 insertions(+), 163 deletions(-) create mode 100644 AltCover.RecorderModern.Tests/AltCover.RecorderModern.Tests.fsproj create mode 100644 AltCover.RecorderModern/AltCover.RecorderModern.fsproj diff --git a/AltCover.Engine/CecilEx.fs b/AltCover.Engine/CecilEx.fs index 5b6804ff..e2b8e1bd 100644 --- a/AltCover.Engine/CecilEx.fs +++ b/AltCover.Engine/CecilEx.fs @@ -145,7 +145,7 @@ type internal AssemblyResolver() as self = Environment.GetEnvironmentVariable "WinDir" |> Option.ofObj |> Option.map (fun p -> Path.Combine(p, wingac)) - Some <| Path.Combine("usr", monogac) + Some <| Path.Combine("usr", monogac) Environment.GetEnvironmentVariable "MONO_GAC_PREFIX" |> Option.ofObj |> Option.map (fun p -> Path.Combine(p, monogac)) diff --git a/AltCover.Engine/Main.fs b/AltCover.Engine/Main.fs index f73120a8..3aeb370e 100644 --- a/AltCover.Engine/Main.fs +++ b/AltCover.Engine/Main.fs @@ -703,10 +703,11 @@ module internal Main = |> Option.defaultValue false let internal selectReportGenerator () = - match CoverageParameters.reportKind () with - | ReportFormat.OpenCoverWithTracking + match + CoverageParameters.reportKind () + &&& ReportFormat.TrackMask + with | ReportFormat.OpenCover -> OpenCover.reportGenerator () - | ReportFormat.NativeJsonWithTracking | ReportFormat.NativeJson -> NativeJson.reportGenerator () | _ -> Report.reportGenerator () diff --git a/AltCover.Engine/NativeJson.fs b/AltCover.Engine/NativeJson.fs index 6f024306..6dd69ed7 100644 --- a/AltCover.Engine/NativeJson.fs +++ b/AltCover.Engine/NativeJson.fs @@ -1239,7 +1239,7 @@ module let fileToJson filename = filename |> File.ReadAllText |> fromJsonText #else // RUNNER - let internal streamToJson (stream:Stream) = + let internal streamToJson (stream: Stream) = use r = new StreamReader(stream) r.ReadToEnd() |> fromJsonText #endif @@ -1438,16 +1438,14 @@ type internal DocumentType = // else // Unknown - static member internal LoadReportStream format (report:Stream) = + static member internal LoadReportStream format (report: Stream) = if report.Length > 0 then - if - format = ReportFormat.NativeJson - || format = ReportFormat.NativeJsonWithTracking - then + if format &&& ReportFormat.TrackMask = ReportFormat.NativeJson then report |> NativeJson.streamToJson |> JSON else report |> XDocument.Load |> XML - else Unknown + else + Unknown #endif diff --git a/AltCover.Engine/PostProcess.fs b/AltCover.Engine/PostProcess.fs index 1fd26f53..3d9d4c6a 100644 --- a/AltCover.Engine/PostProcess.fs +++ b/AltCover.Engine/PostProcess.fs @@ -241,8 +241,7 @@ module internal PostProcess = format (document: XmlAbstraction) = - match format with - | ReportFormat.OpenCoverWithTracking + match format &&& ReportFormat.TrackMask with | ReportFormat.OpenCover -> if counts.ContainsKey Track.Entry then fillTrackedVisits document counts.[Track.Entry] "entry" @@ -514,6 +513,6 @@ module internal PostProcess = "PreferStringComparisonOverrideRule", Scope = "member", Target = - "AltCover.PostProcess/Pipe #2 stage #1 at line 331@332-1::Invoke(AltCover.XmlElementAbstraction)", + "AltCover.PostProcess/Pipe #2 stage #1 at line 330@331-1::Invoke(AltCover.XmlElementAbstraction)", Justification = "Compiler generated")>] () \ No newline at end of file diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 4796665f..a476caf0 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1385,10 +1385,7 @@ module internal Runner = Zip.openUpdate report try - if - format = ReportFormat.NativeJson - || format = ReportFormat.NativeJsonWithTracking - then + if format &&& ReportFormat.TrackMask = ReportFormat.NativeJson then writeNativeJsonReport hits format file arg else AltCover.Counter.doFlushStream diff --git a/AltCover.Engine/Visitor.fs b/AltCover.Engine/Visitor.fs index 136f501e..ce11fddf 100644 --- a/AltCover.Engine/Visitor.fs +++ b/AltCover.Engine/Visitor.fs @@ -412,27 +412,35 @@ module internal CoverageParameters = else path - let internal reportFormat () = + let internal reportFormat0 () = let fmt = reportKind () if fmt = ReportFormat.OpenCover && (trackingNames.Any() || interval () > 0) then - ReportFormat.OpenCoverWithTracking + ReportFormat.OpenCover + ||| ReportFormat.WithTracking else if fmt = ReportFormat.NativeJson && (trackingNames.Any() || interval () > 0) then - ReportFormat.NativeJsonWithTracking + ReportFormat.NativeJson + ||| ReportFormat.WithTracking else fmt + let internal reportFormat () = + let raw = reportFormat0 () + + if zipReport.Value then + raw ||| ReportFormat.Zipped + else + raw + let internal isTracking () = - match reportFormat () with - | ReportFormat.OpenCoverWithTracking - | ReportFormat.NativeJsonWithTracking -> true - | _ -> false + int (reportFormat () &&& ReportFormat.WithTracking) + <> 0 let withBranches () = reportFormat () <> ReportFormat.NCover @@ -1674,30 +1682,30 @@ module internal Visitor = "AvoidMessageChainsRule", Scope = "member", Target = - "AltCover.Visitor/I/generated@1403::Invoke(Mono.Cecil.Cil.Instruction)", + "AltCover.Visitor/I/generated@1411::Invoke(Mono.Cecil.Cil.Instruction)", Justification = "No direct call available")>] [,Microsoft.FSharp.Collections.FSharpList`1)", + "AltCover.Visitor/I/start@1257::Invoke(Microsoft.FSharp.Core.FSharpFunc`2,Microsoft.FSharp.Collections.FSharpList`1)", Justification = "Inlined library code")>] [,Microsoft.FSharp.Collections.FSharpList`1)", + "AltCover.Visitor/I/finish@1260::Invoke(Microsoft.FSharp.Core.FSharpFunc`2,Microsoft.FSharp.Collections.FSharpList`1)", Justification = "Inlined library code")>] [] [] () \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index d56832d1..5897519e 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -93,7 +93,15 @@ module AltCoverTests = let tracer = Adapter.makeNullTrace String.Empty - Assert.True(tracer.GetType().Assembly.GetName().Name = "AltCover.Recorder") + // whitelist test not recorder.g + + let n = + tracer.GetType().Assembly.GetName().Name +#if RECORDERMODERN + Assert.That(n, Is.EqualTo "AltCover.RecorderModern") +#else + Assert.That(n, Is.EqualTo "AltCover.Recorder") +#endif getMyMethodName "<=" [] @@ -154,7 +162,11 @@ module AltCoverTests = Instance.I.recording <- true Instance.CoverageFormat <- ReportFormat.NCover Instance.Visit key -23 - Instance.CoverageFormat <- ReportFormat.OpenCoverWithTracking + + Instance.CoverageFormat <- + ReportFormat.OpenCover + ||| ReportFormat.WithTracking + Instance.Visit key -23 let vs = Adapter.VisitsSeq() @@ -191,7 +203,11 @@ module AltCoverTests = let PayloadGeneratedIsAsExpected () = try Instance.I.isRunner <- false - Instance.CoverageFormat <- ReportFormat.OpenCoverWithTracking + + Instance.CoverageFormat <- + ReportFormat.OpenCover + ||| ReportFormat.WithTracking + Assert.True(Instance.I.callerId () |> Option.isNone) Assert.True(Adapter.payloadSelector false = Adapter.asNull ()) Assert.True(Adapter.payloadSelector true = Adapter.asNull ()) @@ -248,7 +264,11 @@ module AltCoverTests = try Instance.I.isRunner <- true - Instance.CoverageFormat <- ReportFormat.OpenCoverWithTracking + + Instance.CoverageFormat <- + ReportFormat.OpenCover + ||| ReportFormat.WithTracking + Adapter.VisitsClear() Assert.True(Instance.I.callerId () |> Option.isNone) @@ -1644,12 +1664,7 @@ module AltCoverTests = visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - Adapter.doFlush ( - visits, - AltCover.Recorder.ReportFormat.NCover, - reportFile, - outputFile - ) + Adapter.doFlush (visits, ReportFormat.NCover, reportFile, outputFile) |> ignore use worker' = @@ -1733,12 +1748,7 @@ module AltCoverTests = visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - Adapter.doFlush ( - visits, - AltCover.Recorder.ReportFormat.NCover, - reportFile, - outputFile - ) + Adapter.doFlush (visits, ReportFormat.NCover, reportFile, outputFile) |> ignore use worker' = @@ -1815,7 +1825,7 @@ module AltCoverTests = Adapter.doFlush ( visits, - AltCover.Recorder.ReportFormat.NCover, + ReportFormat.NCover ||| ReportFormat.Zipped, reportFile, outputFile ) @@ -1905,7 +1915,7 @@ module AltCoverTests = Adapter.doFlush ( visits, - AltCover.Recorder.ReportFormat.NCover, + ReportFormat.NCover ||| ReportFormat.Zipped, reportFile, outputFile ) @@ -1976,7 +1986,12 @@ module AltCoverTests = visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - Adapter.doFlush (visits, AltCover.Recorder.ReportFormat.NCover, reportFile, null) + Adapter.doFlush ( + visits, + ReportFormat.NCover ||| ReportFormat.Zipped, + reportFile, + null + ) |> ignore Assert.That(reportFile |> File.Exists |> not) @@ -1991,117 +2006,123 @@ module AltCoverTests = let ZipFlushLeavesExpectedTraces () = getMyMethodName "=>" - lock Adapter.Lock (fun () -> - Instance.I.isRunner <- false + lock + Adapter.Lock + (fun () -> + Instance.I.isRunner <- false - trywithrelease (fun () -> - let saved = Console.Out - let here = Directory.GetCurrentDirectory() + trywith (fun () -> + let saved = Console.Out + let here = Directory.GetCurrentDirectory() - let where = - Assembly.GetExecutingAssembly().Location - |> Path.GetDirectoryName + let where = + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName - let unique = - Path.Combine(where, Guid.NewGuid().ToString()) + let unique = + Path.Combine(where, Guid.NewGuid().ToString()) - let save = Instance.I.trace - Instance.I.trace <- Adapter.makeNullTrace null + let save = Instance.I.trace + Instance.I.trace <- Adapter.makeNullTrace null - try - Adapter.VisitsClear() - use stdout = new StringWriter() - Console.SetOut stdout - Directory.CreateDirectory(unique) |> ignore - Directory.SetCurrentDirectory(unique) + try + Adapter.VisitsClear() + use stdout = new StringWriter() + Console.SetOut stdout + Directory.CreateDirectory(unique) |> ignore + Directory.SetCurrentDirectory(unique) - Counter.measureTime <- - DateTime.ParseExact("2017-12-29T16:33:40.9564026+00:00", "o", null) + Counter.measureTime <- + DateTime.ParseExact("2017-12-29T16:33:40.9564026+00:00", "o", null) - use stream = - Assembly - .GetExecutingAssembly() - .GetManifestResourceStream(resource) + use stream = + Assembly + .GetExecutingAssembly() + .GetManifestResourceStream(resource) - let size = int stream.Length - let buffer = Array.create size 0uy - Assert.That(stream.Read(buffer, 0, size), Is.EqualTo size) + let size = int stream.Length + let buffer = Array.create size 0uy + Assert.That(stream.Read(buffer, 0, size), Is.EqualTo size) - do - use archive = - ZipFile.Open(Instance.ReportFilePath + ".zip", ZipArchiveMode.Create) + do + AltCoverCoreTests.maybeDeleteFile (Instance.ReportFilePath + ".zip") - let entry = - Instance.ReportFilePath - |> Path.GetFileName - |> archive.CreateEntry + use archive = + ZipFile.Open(Instance.ReportFilePath + ".zip", ZipArchiveMode.Create) - use sink = entry.Open() - sink.Write(buffer, 0, size) - () + let entry = + Instance.ReportFilePath + |> Path.GetFileName + |> archive.CreateEntry - [ 0..9 ] - |> Seq.iter (fun i -> - Adapter.VisitsAdd( - "f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", - i, - (int64 (i + 1)) - )) + use sink = entry.Open() + sink.Write(buffer, 0, size) + () - Adapter.DoExit().Invoke(null, null) - - let head = - "Coverage statistics flushing took " + [ 0..9 ] + |> Seq.iter (fun i -> + Adapter.VisitsAdd( + "f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", + i, + (int64 (i + 1)) + )) - let tail = " seconds\n" + Adapter.DoExit().Invoke(null, null) - let recorded = - stdout.ToString().Replace("\r\n", "\n") + let head = + "Coverage statistics flushing took " - let index1 = - recorded.IndexOf(head, StringComparison.Ordinal) + let tail = " seconds\n" - let index2 = - recorded.IndexOf(tail, StringComparison.Ordinal) + let recorded = + stdout.ToString().Replace("\r\n", "\n") - Assert.That(index1, Is.GreaterThanOrEqualTo 0, recorded) - Assert.That(index2, Is.GreaterThan index1, recorded) + let index1 = + recorded.IndexOf(head, StringComparison.Ordinal) - use zip = - ZipFile.Open(Instance.ReportFilePath + ".zip", ZipArchiveMode.Update) + let index2 = + recorded.IndexOf(tail, StringComparison.Ordinal) - let entry = - Instance.ReportFilePath - |> Path.GetFileName - |> zip.GetEntry + Assert.That(index1, Is.GreaterThanOrEqualTo 0, recorded) + Assert.That(index2, Is.GreaterThan index1, recorded) - use worker' = entry.Open() - let after = XmlDocument() - after.Load worker' + use zip = + ZipFile.Open(Instance.ReportFilePath + ".zip", ZipArchiveMode.Update) - Assert.That( - after.SelectNodes("//seqpnt") - |> Seq.cast - |> Seq.map (fun x -> x.GetAttribute("visitcount")), - Is.EquivalentTo - [ "11" - "10" - "9" - "8" - "7" - "6" - "4" - "3" - "2" - "1" ] - ) - finally - Instance.I.trace <- save - AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath - Adapter.VisitsClear() - Console.SetOut saved - Directory.SetCurrentDirectory(here) - AltCoverCoreTests.maybeIOException (fun () -> Directory.Delete(unique)))) + let entry = + Instance.ReportFilePath + |> Path.GetFileName + |> zip.GetEntry + + use worker' = entry.Open() + let after = XmlDocument() + after.Load worker' + + Assert.That( + after.SelectNodes("//seqpnt") + |> Seq.cast + |> Seq.map (fun x -> x.GetAttribute("visitcount")), + Is.EquivalentTo + [ "11" + "10" + "9" + "8" + "7" + "6" + "4" + "3" + "2" + "1" ] + ) + finally + Instance.I.trace <- save + AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath + AltCoverCoreTests.maybeDeleteFile (Instance.ReportFilePath + ".zip") + Adapter.VisitsClear() + Console.SetOut saved + Directory.SetCurrentDirectory(here) + AltCoverCoreTests.maybeIOException (fun () -> Directory.Delete(unique)))) + ignore getMyMethodName "<=" #endif diff --git a/AltCover.Recorder/Base.fs b/AltCover.Recorder/Base.fs index 5aae9a34..269b1ec3 100644 --- a/AltCover.Recorder/Base.fs +++ b/AltCover.Recorder/Base.fs @@ -11,12 +11,21 @@ open System.Globalization open System.IO open System.Xml +[] +[] +[] type internal ReportFormat = | NCover = 0 | OpenCover = 1 - | OpenCoverWithTracking = 2 - | NativeJson = 3 - | NativeJsonWithTracking = 4 + | NativeJson = 2 + | TrackMask = 63 + | WithTracking = 64 + | ZipMask = 127 + | Zipped = 128 #if !RUNNER open ICSharpCode.SharpZipLib.Zip @@ -174,8 +183,7 @@ module internal Counter = ("//module", "moduleId", "method", [ ("seqpnt", 0) ], "visitcount") let internal xmlByFormat format = - match format with - | ReportFormat.OpenCoverWithTracking + match format &&& ReportFormat.TrackMask with | ReportFormat.OpenCover -> openCoverXml | ReportFormat.NCover -> nCoverXml | _ -> @@ -301,8 +309,7 @@ module internal Counter = |> Seq.toList |> List.rev)) |> Seq.mapi (fun counter (pt, flag) -> - ((match format with - | ReportFormat.OpenCoverWithTracking + ((match format &&& ReportFormat.TrackMask with | ReportFormat.OpenCover -> "uspid" |> pt.GetAttribute @@ -467,7 +474,10 @@ module internal Counter = "CA2000:DisposeObjectsBeforeLosingScope", Justification = "ald also 'target' is disposed")>] let internal doFlushFile postProcess pointProcess own counts format report output = - if File.Exists report then + let zipped = + int (format &&& ReportFormat.Zipped) <> 0 + + if not zipped then use coverageFile = new FileStream( report, diff --git a/AltCover.Recorder/Recorder.fs b/AltCover.Recorder/Recorder.fs index 782c3753..88d97573 100644 --- a/AltCover.Recorder/Recorder.fs +++ b/AltCover.Recorder/Recorder.fs @@ -430,10 +430,11 @@ module Instance = adder moduleId hitPointId context - let internal isTrackingRunner () = - (CoverageFormat = ReportFormat.OpenCoverWithTracking - || CoverageFormat = ReportFormat.NativeJsonWithTracking) - && isRunner + let internal isTracking () = + (int (CoverageFormat &&& ReportFormat.WithTracking) + <> 0) + + let internal isTrackingRunner () = isTracking () && isRunner let internal granularity () = Timer let internal clock () = DateTime.UtcNow.Ticks @@ -499,10 +500,7 @@ module Instance = let Visit moduleId hitPointId = if I.recording then I.visitSelection - (if - (CoverageFormat = ReportFormat.OpenCoverWithTracking - || CoverageFormat = ReportFormat.NativeJsonWithTracking) - then + (if I.isTracking () then I.payloadSelector I.isTrackingRunner else Null) diff --git a/AltCover.RecorderModern.Tests/AltCover.RecorderModern.Tests.fsproj b/AltCover.RecorderModern.Tests/AltCover.RecorderModern.Tests.fsproj new file mode 100644 index 00000000..4e360438 --- /dev/null +++ b/AltCover.RecorderModern.Tests/AltCover.RecorderModern.Tests.fsproj @@ -0,0 +1,55 @@ + + + + net472 + false + AltCover.RecorderModern.Tests + false + NU1702, 3559 + NU1702 + --keyfile:$(InfrastructureKey) + RECORDERMODERN + + + + TRACE;DEBUG;ALTCOVER_TEST;$(ExtraDefines) + + + TRACE;RELEASE;ALTCOVER_TEST;$(ExtraDefines) + + + + + + + AssemblyVersion.fs + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + contentfiles + + + + + + + + + \ No newline at end of file diff --git a/AltCover.RecorderModern/AltCover.RecorderModern.fsproj b/AltCover.RecorderModern/AltCover.RecorderModern.fsproj new file mode 100644 index 00000000..a5819e90 --- /dev/null +++ b/AltCover.RecorderModern/AltCover.RecorderModern.fsproj @@ -0,0 +1,56 @@ + + + + net472 + AltCover.RecorderModern + AltCover.Recorder + false + false + false + RECORDER + + + + TRACE;$(DefineConstants) + --keyfile:$(InfrastructureKey) + + + + TRACE;DEBUG;CODE_ANALYSIS;$(DefineConstants) + --keyfile:$(InfrastructureKey) + + + + + + + + + + + + + + + AltCover.Recorder.Strings.resources + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + contentfiles + + + + + + ..\ThirdParty\ziplib.net20\ICSharpCode.SharpZipLib.dll + + + + \ No newline at end of file diff --git a/AltCover.Tests/Tests.fs b/AltCover.Tests/Tests.fs index cb6a4af3..343c31ae 100644 --- a/AltCover.Tests/Tests.fs +++ b/AltCover.Tests/Tests.fs @@ -3754,7 +3754,10 @@ module AltCoverTests = Assert.That( CoverageParameters.reportFormat (), - Is.EqualTo ReportFormat.NativeJsonWithTracking + Is.EqualTo( + ReportFormat.NativeJson + ||| ReportFormat.WithTracking + ) ) let result = makeJson document @@ -5477,7 +5480,10 @@ module AltCoverTests = Assert.That( CoverageParameters.reportFormat (), - Is.EqualTo ReportFormat.OpenCoverWithTracking + Is.EqualTo( + ReportFormat.OpenCover + ||| ReportFormat.WithTracking + ) ) "Program" @@ -5624,7 +5630,10 @@ module AltCoverTests = Assert.That( CoverageParameters.reportFormat (), - Is.EqualTo ReportFormat.OpenCoverWithTracking + Is.EqualTo( + ReportFormat.OpenCover + ||| ReportFormat.WithTracking + ) ) "Main" diff --git a/AltCover.Tests/Tests2.fs b/AltCover.Tests/Tests2.fs index 651af837..da6fb1a3 100644 --- a/AltCover.Tests/Tests2.fs +++ b/AltCover.Tests/Tests2.fs @@ -608,7 +608,10 @@ module AltCoverTests2 = Assert.That( CoverageParameters.reportFormat (), - Is.EqualTo AltCover.ReportFormat.OpenCoverWithTracking + Is.EqualTo( + AltCover.ReportFormat.OpenCover + ||| ReportFormat.WithTracking + ) ) CoverageParameters.theInterval <- None @@ -616,7 +619,10 @@ module AltCoverTests2 = Assert.That( CoverageParameters.reportFormat (), - Is.EqualTo AltCover.ReportFormat.OpenCoverWithTracking + Is.EqualTo( + AltCover.ReportFormat.OpenCover + ||| ReportFormat.WithTracking + ) ) CoverageParameters.trackingNames.Clear() @@ -794,7 +800,8 @@ module AltCoverTests2 = Assert.That( report2, - AltCover.ReportFormat.OpenCoverWithTracking + (AltCover.ReportFormat.OpenCover + ||| ReportFormat.WithTracking) |> int |> Is.EqualTo, "wrong tracking format" diff --git a/AltCover.Tests/XTests.fs b/AltCover.Tests/XTests.fs index 4ade9197..c2825453 100644 --- a/AltCover.Tests/XTests.fs +++ b/AltCover.Tests/XTests.fs @@ -910,7 +910,10 @@ module AltCoverXTests = let recordedJson = use stream = File.OpenRead report - match DocumentType.LoadReportStream CoverageParameters.theReportFormat.Value stream with + + match + DocumentType.LoadReportStream CoverageParameters.theReportFormat.Value stream + with | JSON j -> j test <@ recordedJson.Keys |> Seq.toList = [ "Sample4.dll" ] @> @@ -1157,6 +1160,7 @@ module AltCoverXTests = let recordedXml = use stream = File.OpenRead report + match DocumentType.LoadReportStream ReportFormat.OpenCover stream with | XML x -> x diff --git a/AltCover.sln b/AltCover.sln index 29f131e7..3d25d661 100644 --- a/AltCover.sln +++ b/AltCover.sln @@ -136,7 +136,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cecil", "Cecil", "{F56DE54A ThirdParty\cecil\Mono.Cecil.Rocks.pdb = ThirdParty\cecil\Mono.Cecil.Rocks.pdb EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample0", "Samples\Sample0\Sample0.csproj", "{19CE63CE-3622-409A-974D-3EA01388317E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample0", "Samples\Sample0\Sample0.csproj", "{19CE63CE-3622-409A-974D-3EA01388317E}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.RecorderModern", "AltCover.RecorderModern\AltCover.RecorderModern.fsproj", "{219B0218-3289-44DD-9C22-6C14A3D7B5A7}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.RecorderModern.Tests", "AltCover.RecorderModern.Tests\AltCover.RecorderModern.Tests.fsproj", "{4B905582-3295-463B-A645-7FA6D0844035}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -329,7 +333,6 @@ Global {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Debug|Any CPU.Build.0 = Debug|Any CPU {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Debug|x86.ActiveCfg = Debug|Any CPU - {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Debug|x86.Build.0 = Debug|Any CPU {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Release|Any CPU.ActiveCfg = Release|Any CPU {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Release|x86.ActiveCfg = Release|Any CPU {19CE63CE-3622-409A-974D-3EA01388317E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -337,6 +340,16 @@ Global {19CE63CE-3622-409A-974D-3EA01388317E}.Debug|x86.ActiveCfg = Debug|Any CPU {19CE63CE-3622-409A-974D-3EA01388317E}.Release|Any CPU.ActiveCfg = Release|Any CPU {19CE63CE-3622-409A-974D-3EA01388317E}.Release|x86.ActiveCfg = Release|Any CPU + {219B0218-3289-44DD-9C22-6C14A3D7B5A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {219B0218-3289-44DD-9C22-6C14A3D7B5A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {219B0218-3289-44DD-9C22-6C14A3D7B5A7}.Debug|x86.ActiveCfg = Debug|Any CPU + {219B0218-3289-44DD-9C22-6C14A3D7B5A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {219B0218-3289-44DD-9C22-6C14A3D7B5A7}.Release|x86.ActiveCfg = Release|Any CPU + {4B905582-3295-463B-A645-7FA6D0844035}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4B905582-3295-463B-A645-7FA6D0844035}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4B905582-3295-463B-A645-7FA6D0844035}.Debug|x86.ActiveCfg = Debug|Any CPU + {4B905582-3295-463B-A645-7FA6D0844035}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4B905582-3295-463B-A645-7FA6D0844035}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Build/actions.fs b/Build/actions.fs index 1f20ad33..b62592e3 100644 --- a/Build/actions.fs +++ b/Build/actions.fs @@ -112,6 +112,7 @@ open System.Runtime.CompilerServices [] [] [] +[] [] #else [] From 66cc13cce7847ee79e65ed9d55d5cace53355ed0 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 9 May 2024 16:59:42 +0100 Subject: [PATCH 17/33] Verify that the Zip bit is written too --- AltCover.Tests/Tests2.fs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/AltCover.Tests/Tests2.fs b/AltCover.Tests/Tests2.fs index da6fb1a3..68851ec9 100644 --- a/AltCover.Tests/Tests2.fs +++ b/AltCover.Tests/Tests2.fs @@ -596,6 +596,7 @@ module AltCoverTests2 = [] let ShouldGetTrackingStyleIfSet () = + Main.init() let save2 = CoverageParameters.theReportFormat @@ -722,6 +723,7 @@ module AltCoverTests2 = CoverageParameters.theReportFormat <- Some AltCover.ReportFormat.OpenCover CoverageParameters.theInterval <- Some 1234567890 CoverageParameters.single <- true + CoverageParameters.zipReport.Value <- true Assert.That( CoverageParameters.sampling (), @@ -801,7 +803,8 @@ module AltCoverTests2 = Assert.That( report2, (AltCover.ReportFormat.OpenCover - ||| ReportFormat.WithTracking) + ||| ReportFormat.WithTracking + ||| ReportFormat.Zipped) |> int |> Is.EqualTo, "wrong tracking format" From 0c35a9cd8c6301ed9e28e43fc68a99cbc868e547 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 9 May 2024 19:42:03 +0100 Subject: [PATCH 18/33] Make a testable build of the recorder --- AltCover.Engine/CecilEx.fs | 2 +- AltCover.Recorder.Tests/Recorder.Tests.fs | 18 +++++- .../AltCover.RecorderModern.Tests.fsproj | 55 ++++++++++++++++++ .../AltCover.RecorderModern.fsproj | 56 +++++++++++++++++++ AltCover.sln | 17 +++++- Build/actions.fs | 1 + 6 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 AltCover.RecorderModern.Tests/AltCover.RecorderModern.Tests.fsproj create mode 100644 AltCover.RecorderModern/AltCover.RecorderModern.fsproj diff --git a/AltCover.Engine/CecilEx.fs b/AltCover.Engine/CecilEx.fs index 5b6804ff..e2b8e1bd 100644 --- a/AltCover.Engine/CecilEx.fs +++ b/AltCover.Engine/CecilEx.fs @@ -145,7 +145,7 @@ type internal AssemblyResolver() as self = Environment.GetEnvironmentVariable "WinDir" |> Option.ofObj |> Option.map (fun p -> Path.Combine(p, wingac)) - Some <| Path.Combine("usr", monogac) + Some <| Path.Combine("usr", monogac) Environment.GetEnvironmentVariable "MONO_GAC_PREFIX" |> Option.ofObj |> Option.map (fun p -> Path.Combine(p, monogac)) diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index d56832d1..026e1e73 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -93,7 +93,15 @@ module AltCoverTests = let tracer = Adapter.makeNullTrace String.Empty - Assert.True(tracer.GetType().Assembly.GetName().Name = "AltCover.Recorder") + // whitelist test not recorder.g + + let n = + tracer.GetType().Assembly.GetName().Name +#if RECORDERMODERN + Assert.That(n, Is.EqualTo "AltCover.RecorderModern") +#else + Assert.That(n, Is.EqualTo "AltCover.Recorder") +#endif getMyMethodName "<=" [] @@ -1994,7 +2002,13 @@ module AltCoverTests = lock Adapter.Lock (fun () -> Instance.I.isRunner <- false +#if RECORDERMODERN + let run f = f () + + run (fun () -> +#else trywithrelease (fun () -> +#endif let saved = Console.Out let here = Directory.GetCurrentDirectory() @@ -2028,6 +2042,7 @@ module AltCoverTests = Assert.That(stream.Read(buffer, 0, size), Is.EqualTo size) do + AltCoverCoreTests.maybeDeleteFile (Instance.ReportFilePath + ".zip") use archive = ZipFile.Open(Instance.ReportFilePath + ".zip", ZipArchiveMode.Create) @@ -2098,6 +2113,7 @@ module AltCoverTests = finally Instance.I.trace <- save AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath + AltCoverCoreTests.maybeDeleteFile (Instance.ReportFilePath + ".zip") Adapter.VisitsClear() Console.SetOut saved Directory.SetCurrentDirectory(here) diff --git a/AltCover.RecorderModern.Tests/AltCover.RecorderModern.Tests.fsproj b/AltCover.RecorderModern.Tests/AltCover.RecorderModern.Tests.fsproj new file mode 100644 index 00000000..4e360438 --- /dev/null +++ b/AltCover.RecorderModern.Tests/AltCover.RecorderModern.Tests.fsproj @@ -0,0 +1,55 @@ + + + + net472 + false + AltCover.RecorderModern.Tests + false + NU1702, 3559 + NU1702 + --keyfile:$(InfrastructureKey) + RECORDERMODERN + + + + TRACE;DEBUG;ALTCOVER_TEST;$(ExtraDefines) + + + TRACE;RELEASE;ALTCOVER_TEST;$(ExtraDefines) + + + + + + + AssemblyVersion.fs + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + contentfiles + + + + + + + + + \ No newline at end of file diff --git a/AltCover.RecorderModern/AltCover.RecorderModern.fsproj b/AltCover.RecorderModern/AltCover.RecorderModern.fsproj new file mode 100644 index 00000000..a5819e90 --- /dev/null +++ b/AltCover.RecorderModern/AltCover.RecorderModern.fsproj @@ -0,0 +1,56 @@ + + + + net472 + AltCover.RecorderModern + AltCover.Recorder + false + false + false + RECORDER + + + + TRACE;$(DefineConstants) + --keyfile:$(InfrastructureKey) + + + + TRACE;DEBUG;CODE_ANALYSIS;$(DefineConstants) + --keyfile:$(InfrastructureKey) + + + + + + + + + + + + + + + AltCover.Recorder.Strings.resources + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + contentfiles + + + + + + ..\ThirdParty\ziplib.net20\ICSharpCode.SharpZipLib.dll + + + + \ No newline at end of file diff --git a/AltCover.sln b/AltCover.sln index 29f131e7..3d25d661 100644 --- a/AltCover.sln +++ b/AltCover.sln @@ -136,7 +136,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cecil", "Cecil", "{F56DE54A ThirdParty\cecil\Mono.Cecil.Rocks.pdb = ThirdParty\cecil\Mono.Cecil.Rocks.pdb EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample0", "Samples\Sample0\Sample0.csproj", "{19CE63CE-3622-409A-974D-3EA01388317E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample0", "Samples\Sample0\Sample0.csproj", "{19CE63CE-3622-409A-974D-3EA01388317E}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.RecorderModern", "AltCover.RecorderModern\AltCover.RecorderModern.fsproj", "{219B0218-3289-44DD-9C22-6C14A3D7B5A7}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.RecorderModern.Tests", "AltCover.RecorderModern.Tests\AltCover.RecorderModern.Tests.fsproj", "{4B905582-3295-463B-A645-7FA6D0844035}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -329,7 +333,6 @@ Global {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Debug|Any CPU.Build.0 = Debug|Any CPU {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Debug|x86.ActiveCfg = Debug|Any CPU - {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Debug|x86.Build.0 = Debug|Any CPU {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Release|Any CPU.ActiveCfg = Release|Any CPU {B42E9FBA-BDE8-4B15-B7E7-DDF237CA7881}.Release|x86.ActiveCfg = Release|Any CPU {19CE63CE-3622-409A-974D-3EA01388317E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -337,6 +340,16 @@ Global {19CE63CE-3622-409A-974D-3EA01388317E}.Debug|x86.ActiveCfg = Debug|Any CPU {19CE63CE-3622-409A-974D-3EA01388317E}.Release|Any CPU.ActiveCfg = Release|Any CPU {19CE63CE-3622-409A-974D-3EA01388317E}.Release|x86.ActiveCfg = Release|Any CPU + {219B0218-3289-44DD-9C22-6C14A3D7B5A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {219B0218-3289-44DD-9C22-6C14A3D7B5A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {219B0218-3289-44DD-9C22-6C14A3D7B5A7}.Debug|x86.ActiveCfg = Debug|Any CPU + {219B0218-3289-44DD-9C22-6C14A3D7B5A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {219B0218-3289-44DD-9C22-6C14A3D7B5A7}.Release|x86.ActiveCfg = Release|Any CPU + {4B905582-3295-463B-A645-7FA6D0844035}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4B905582-3295-463B-A645-7FA6D0844035}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4B905582-3295-463B-A645-7FA6D0844035}.Debug|x86.ActiveCfg = Debug|Any CPU + {4B905582-3295-463B-A645-7FA6D0844035}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4B905582-3295-463B-A645-7FA6D0844035}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Build/actions.fs b/Build/actions.fs index 1f20ad33..b62592e3 100644 --- a/Build/actions.fs +++ b/Build/actions.fs @@ -112,6 +112,7 @@ open System.Runtime.CompilerServices [] [] [] +[] [] #else [] From 0539bb7b68cabae6b9e4d94c5094be86669c320f Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 11 May 2024 09:08:27 +0100 Subject: [PATCH 19/33] Revert needless change --- AltCover.Recorder.Tests/Recorder.Tests.fs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index 026e1e73..9c963f86 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -2002,13 +2002,7 @@ module AltCoverTests = lock Adapter.Lock (fun () -> Instance.I.isRunner <- false -#if RECORDERMODERN - let run f = f () - - run (fun () -> -#else trywithrelease (fun () -> -#endif let saved = Console.Out let here = Directory.GetCurrentDirectory() From 60716e78801cbc7db4731a30d65893dfd44ff371 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 11 May 2024 09:24:30 +0100 Subject: [PATCH 20/33] Fix trywithrelease --- AltCover.Recorder.Tests/Recorder.Tests.fs | 198 +++++++++++----------- AltCover.Tests/Tests2.fs | 3 +- 2 files changed, 104 insertions(+), 97 deletions(-) diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index 5897519e..acf5a048 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -1178,7 +1178,13 @@ module AltCoverTests = with :? 'a -> g () - let trywithrelease<'a when 'a :> exn> f = trywith f Instance.I.mutex.ReleaseMutex + let failsaferelease () = + try + Instance.I.mutex.ReleaseMutex() + with :? ApplicationException -> + () + + let trywithrelease<'a when 'a :> exn> f = trywith f failsaferelease [] let CanTryWith () = @@ -1193,6 +1199,9 @@ module AltCoverTests = Assert.That(flag, Is.True) + trywithrelease (fun () -> + InvalidOperationException() |> raise) + Instance.I.mutex.WaitOne(1000) |> ignore trywithrelease (fun () -> @@ -2006,123 +2015,120 @@ module AltCoverTests = let ZipFlushLeavesExpectedTraces () = getMyMethodName "=>" - lock - Adapter.Lock - (fun () -> - Instance.I.isRunner <- false + lock Adapter.Lock (fun () -> + Instance.I.isRunner <- false + + trywithrelease (fun () -> + let saved = Console.Out + let here = Directory.GetCurrentDirectory() + + let where = + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName - trywith (fun () -> - let saved = Console.Out - let here = Directory.GetCurrentDirectory() + let unique = + Path.Combine(where, Guid.NewGuid().ToString()) - let where = - Assembly.GetExecutingAssembly().Location - |> Path.GetDirectoryName + let save = Instance.I.trace + Instance.I.trace <- Adapter.makeNullTrace null - let unique = - Path.Combine(where, Guid.NewGuid().ToString()) + try + Adapter.VisitsClear() + use stdout = new StringWriter() + Console.SetOut stdout + Directory.CreateDirectory(unique) |> ignore + Directory.SetCurrentDirectory(unique) - let save = Instance.I.trace - Instance.I.trace <- Adapter.makeNullTrace null + Counter.measureTime <- + DateTime.ParseExact("2017-12-29T16:33:40.9564026+00:00", "o", null) - try - Adapter.VisitsClear() - use stdout = new StringWriter() - Console.SetOut stdout - Directory.CreateDirectory(unique) |> ignore - Directory.SetCurrentDirectory(unique) + use stream = + Assembly + .GetExecutingAssembly() + .GetManifestResourceStream(resource) - Counter.measureTime <- - DateTime.ParseExact("2017-12-29T16:33:40.9564026+00:00", "o", null) + let size = int stream.Length + let buffer = Array.create size 0uy + Assert.That(stream.Read(buffer, 0, size), Is.EqualTo size) - use stream = - Assembly - .GetExecutingAssembly() - .GetManifestResourceStream(resource) + do + AltCoverCoreTests.maybeDeleteFile (Instance.ReportFilePath + ".zip") - let size = int stream.Length - let buffer = Array.create size 0uy - Assert.That(stream.Read(buffer, 0, size), Is.EqualTo size) + use archive = + ZipFile.Open(Instance.ReportFilePath + ".zip", ZipArchiveMode.Create) - do - AltCoverCoreTests.maybeDeleteFile (Instance.ReportFilePath + ".zip") + let entry = + Instance.ReportFilePath + |> Path.GetFileName + |> archive.CreateEntry - use archive = - ZipFile.Open(Instance.ReportFilePath + ".zip", ZipArchiveMode.Create) + use sink = entry.Open() + sink.Write(buffer, 0, size) + () - let entry = - Instance.ReportFilePath - |> Path.GetFileName - |> archive.CreateEntry + [ 0..9 ] + |> Seq.iter (fun i -> + Adapter.VisitsAdd( + "f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", + i, + (int64 (i + 1)) + )) - use sink = entry.Open() - sink.Write(buffer, 0, size) - () + Adapter.DoExit().Invoke(null, null) - [ 0..9 ] - |> Seq.iter (fun i -> - Adapter.VisitsAdd( - "f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", - i, - (int64 (i + 1)) - )) + let head = + "Coverage statistics flushing took " - Adapter.DoExit().Invoke(null, null) + let tail = " seconds\n" - let head = - "Coverage statistics flushing took " + let recorded = + stdout.ToString().Replace("\r\n", "\n") - let tail = " seconds\n" + let index1 = + recorded.IndexOf(head, StringComparison.Ordinal) - let recorded = - stdout.ToString().Replace("\r\n", "\n") + let index2 = + recorded.IndexOf(tail, StringComparison.Ordinal) - let index1 = - recorded.IndexOf(head, StringComparison.Ordinal) + Assert.That(index1, Is.GreaterThanOrEqualTo 0, recorded) + Assert.That(index2, Is.GreaterThan index1, recorded) - let index2 = - recorded.IndexOf(tail, StringComparison.Ordinal) + use zip = + ZipFile.Open(Instance.ReportFilePath + ".zip", ZipArchiveMode.Update) - Assert.That(index1, Is.GreaterThanOrEqualTo 0, recorded) - Assert.That(index2, Is.GreaterThan index1, recorded) + let entry = + Instance.ReportFilePath + |> Path.GetFileName + |> zip.GetEntry - use zip = - ZipFile.Open(Instance.ReportFilePath + ".zip", ZipArchiveMode.Update) + use worker' = entry.Open() + let after = XmlDocument() + after.Load worker' - let entry = - Instance.ReportFilePath - |> Path.GetFileName - |> zip.GetEntry - - use worker' = entry.Open() - let after = XmlDocument() - after.Load worker' - - Assert.That( - after.SelectNodes("//seqpnt") - |> Seq.cast - |> Seq.map (fun x -> x.GetAttribute("visitcount")), - Is.EquivalentTo - [ "11" - "10" - "9" - "8" - "7" - "6" - "4" - "3" - "2" - "1" ] - ) - finally - Instance.I.trace <- save - AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath - AltCoverCoreTests.maybeDeleteFile (Instance.ReportFilePath + ".zip") - Adapter.VisitsClear() - Console.SetOut saved - Directory.SetCurrentDirectory(here) - AltCoverCoreTests.maybeIOException (fun () -> Directory.Delete(unique)))) - ignore + Assert.That( + after.SelectNodes("//seqpnt") + |> Seq.cast + |> Seq.map (fun x -> x.GetAttribute("visitcount")), + Is.EquivalentTo + [ "11" + "10" + "9" + "8" + "7" + "6" + "4" + "3" + "2" + "1" ] + ) + finally + Instance.I.trace <- save + AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath + AltCoverCoreTests.maybeDeleteFile (Instance.ReportFilePath + ".zip") + Adapter.VisitsClear() + Console.SetOut saved + Directory.SetCurrentDirectory(here) + AltCoverCoreTests.maybeIOException (fun () -> Directory.Delete(unique)))) getMyMethodName "<=" #endif diff --git a/AltCover.Tests/Tests2.fs b/AltCover.Tests/Tests2.fs index 68851ec9..6f3dc66e 100644 --- a/AltCover.Tests/Tests2.fs +++ b/AltCover.Tests/Tests2.fs @@ -596,7 +596,8 @@ module AltCoverTests2 = [] let ShouldGetTrackingStyleIfSet () = - Main.init() + Main.init () + let save2 = CoverageParameters.theReportFormat From 14a8460c3d4940117cec11c3ba071a59ff72968e Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 11 May 2024 10:33:40 +0100 Subject: [PATCH 21/33] Fix unit test and coverage, remove obsolete test handling --- AltCover.Recorder.Tests/Recorder.Tests.fs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index acf5a048..5b7eaaa4 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -146,6 +146,7 @@ module AltCoverTests = getMyMethodName "<=" + [] let RealIdShouldIncrementCount () = getMyMethodName "=>" @@ -1207,6 +1208,7 @@ module AltCoverTests = trywithrelease (fun () -> InvalidOperationException() |> raise) + [] let PauseLeavesExpectedTraces () = getMyMethodName "=>" @@ -1309,6 +1311,7 @@ module AltCoverTests = getMyMethodName "<=" + [] let ResumeLeavesExpectedTraces () = getMyMethodName "=>" @@ -1415,6 +1418,7 @@ module AltCoverTests = getMyMethodName "<=" + [] let FlushLeavesExpectedTraces () = getMyMethodName "=>" @@ -2012,11 +2016,17 @@ module AltCoverTests = Directory.SetCurrentDirectory(here) AltCoverCoreTests.maybeIOException (fun () -> Directory.Delete(unique)) +#if !NET20 + [] +#endif let ZipFlushLeavesExpectedTraces () = getMyMethodName "=>" lock Adapter.Lock (fun () -> Instance.I.isRunner <- false + Instance.CoverageFormat <- + ReportFormat.NCover + ||| ReportFormat.Zipped trywithrelease (fun () -> let saved = Console.Out @@ -2133,18 +2143,9 @@ module AltCoverTests = getMyMethodName "<=" #endif - // Dead simple sequential operation - // run only once in Framework mode to avoid contention [] - let MailboxFunctionsAsExpected () = + let ShouldCreateDummyAttribute () = let dummy = AltCover.Recorder.ExcludeFromCodeCoverageAttribute() - Assert.That(dummy, Is.Not.Null) - RealIdShouldIncrementCount() - PauseLeavesExpectedTraces() - ResumeLeavesExpectedTraces() -#if !NET20 - ZipFlushLeavesExpectedTraces() -#endif - FlushLeavesExpectedTraces() \ No newline at end of file + Assert.That(dummy, Is.Not.Null) \ No newline at end of file From f967545d0a2e75be98340d2fdfa4bc8afc9cb579 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 11 May 2024 10:35:50 +0100 Subject: [PATCH 22/33] fantomas --- AltCover.Recorder.Tests/Recorder.Tests.fs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index 5b7eaaa4..494b5af9 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -2024,9 +2024,7 @@ module AltCoverTests = lock Adapter.Lock (fun () -> Instance.I.isRunner <- false - Instance.CoverageFormat <- - ReportFormat.NCover - ||| ReportFormat.Zipped + Instance.CoverageFormat <- ReportFormat.NCover ||| ReportFormat.Zipped trywithrelease (fun () -> let saved = Console.Out From 5b5ddc7d1a7c0ffdc2347c3712e93759ca080ec4 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 11 May 2024 11:08:34 +0100 Subject: [PATCH 23/33] fix and auto-"fix" --- AltCover.Recorder.Tests/Recorder.Tests.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index 494b5af9..eda014cf 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -1871,6 +1871,7 @@ module AltCoverTests = Console.SetOut saved Directory.SetCurrentDirectory(here) AltCoverCoreTests.maybeIOException (fun () -> Directory.Delete(unique)) +#endif [] let ZipFlushLeavesExpectedTracesWhenBroken () = @@ -2139,7 +2140,6 @@ module AltCoverTests = AltCoverCoreTests.maybeIOException (fun () -> Directory.Delete(unique)))) getMyMethodName "<=" -#endif [] let ShouldCreateDummyAttribute () = From d04f0d01ce67587d57f4cd9630eb64beab8503ae Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 11 May 2024 12:46:08 +0100 Subject: [PATCH 24/33] Red unit tests for the new regime --- AltCover.Engine/CommandLine.fs | 14 +- AltCover.Engine/Runner.fs | 10 +- AltCover.Tests/Runner.Tests.fs | 628 ++++++++++++++++++++++++++++++++- 3 files changed, 628 insertions(+), 24 deletions(-) diff --git a/AltCover.Engine/CommandLine.fs b/AltCover.Engine/CommandLine.fs index 5b3693d1..33328f3b 100644 --- a/AltCover.Engine/CommandLine.fs +++ b/AltCover.Engine/CommandLine.fs @@ -70,8 +70,8 @@ module internal Zip = [] - let internal openUpdate (report: string) = - if File.Exists(report + ".zip") then + let internal openUpdate (report: string) (zipped: bool) = + if zipped then let zip = ZipFile.Open(report + ".zip", ZipArchiveMode.Update) @@ -85,7 +85,7 @@ module internal Zip = new MemoryStream() :> Stream (zip, stream) - else if File.Exists report then + else let stream = new FileStream( report, @@ -97,11 +97,11 @@ module internal Zip = ) (null, stream :> Stream) - else - (null, new MemoryStream() :> Stream) - let internal openUpdateReport format (report: string) = - let container, stream = openUpdate report + let internal openUpdateReport format (report: string) (zipped: bool) = + let container, stream = + openUpdate report zipped + use _ = container use _ = stream DocumentType.LoadReportStream format stream diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index a476caf0..9e790b00 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1381,8 +1381,11 @@ module internal Runner = report = let reporter (arg: string option) = + let zipped = + int (format &&& ReportFormat.Zipped) <> 0 + let (container, file) = - Zip.openUpdate report + Zip.openUpdate report zipped try if format &&& ReportFormat.TrackMask = ReportFormat.NativeJson then @@ -1510,8 +1513,11 @@ module internal Runner = ) |> Seq.iter File.Delete + let zipped = + int (format &&& ReportFormat.Zipped) <> 0 + let document = - Zip.openUpdateReport format (Option.defaultValue report output) + Zip.openUpdateReport format (Option.defaultValue report output) zipped J.doSummaries document format result) 255 diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index 62ec1c09..a1c3af47 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -2802,10 +2802,10 @@ module AltCoverRunnerTests = junkworker.Write([||], 0, 0) () - Runner.J.doReport counts AltCover.ReportFormat.NCover junkfile None + Runner.J.doReport counts AltCover.ReportFormat.NCover junkfile None // WriteLeavesExpectedTraces |> ignore - let (c0, w0) = Zip.openUpdate junkfile + let (c0, w0) = Zip.openUpdate junkfile false try Assert.That(c0 |> isNull) @@ -2814,7 +2814,7 @@ module AltCoverRunnerTests = finally w0.Dispose() - Runner.J.doReport counts AltCover.ReportFormat.NCover reportFile None + Runner.J.doReport counts AltCover.ReportFormat.NCover reportFile None // WriteLeavesExpectedTraces |> ignore use worker' = @@ -2930,12 +2930,12 @@ module AltCoverRunnerTests = exits.Add(2, pv) counts.Add(Track.Exit, exits) - Runner.J.doReport counts AltCover.ReportFormat.NativeJson reportFile (Some junkFile) + Runner.J.doReport counts AltCover.ReportFormat.NativeJson reportFile None // WriteJsonLeavesExpectedTraces |> ignore let jsonText = use worker' = - new FileStream(junkFile, FileMode.Open) + new FileStream(reportFile, FileMode.Open) use reader = new StreamReader(worker') reader.ReadToEnd() @@ -2994,6 +2994,8 @@ module AltCoverRunnerTests = let reportFile = Path.Combine(unique, "FlushLeavesExpectedTraces.xml") + let reportZip = reportFile + ".zip" + let junkfile = (reportFile + "." + (Path.GetFileName unique)) @@ -3037,7 +3039,7 @@ module AltCoverRunnerTests = // degenerate case 1 Assert.That(junkfile |> File.Exists |> not) - let (c0, w0) = Zip.openUpdate junkfile + let (c0, w0) = Zip.openUpdate junkfile true try Assert.That(c0 |> isNull) @@ -3061,7 +3063,7 @@ module AltCoverRunnerTests = sink.Write([| 0uy |], 0, 1) () - let (c0, w0) = Zip.openUpdate junkfile + let (c0, w0) = Zip.openUpdate junkfile true try Assert.That(c0.IsNotNull) @@ -3074,11 +3076,15 @@ module AltCoverRunnerTests = // degenerate case 2 Assert.That(junkfile2 |> File.Exists |> not) - Runner.J.doReport counts AltCover.ReportFormat.NCover junkfile2 None + Runner.J.doReport + counts + (ReportFormat.NCover ||| ReportFormat.Zipped) + junkfile2 + None // ZipWriteLeavesExpectedTraces |> ignore Assert.That(junkfile2 |> File.Exists |> not) - let (c1, w1) = Zip.openUpdate junkfile2 + let (c1, w1) = Zip.openUpdate junkfile2 true try Assert.That(c1 |> isNull) @@ -3088,11 +3094,15 @@ module AltCoverRunnerTests = w0.Dispose() Assert.That(junkfile2 |> File.Exists |> not) - Runner.J.doReport counts AltCover.ReportFormat.NCover reportFile None + Runner.J.doReport + counts + (ReportFormat.NCover ||| ReportFormat.Zipped) + reportFile + None // ZipWriteLeavesExpectedTraces |> ignore let (container, worker) = - Zip.openUpdate reportFile + Zip.openUpdate reportFile true use worker' = worker use container' = container @@ -3116,9 +3126,10 @@ module AltCoverRunnerTests = "1" ] ) finally + Assert.That(reportFile |> File.Exists |> not) Assert.That(junkfile |> File.Exists |> not) Assert.That(junkfile2 |> File.Exists |> not) - maybeDeleteFile reportFile + maybeDeleteFile reportZip Console.SetOut saved Directory.SetCurrentDirectory(here) maybeIOException (fun () -> Directory.Delete(unique)) @@ -3139,6 +3150,8 @@ module AltCoverRunnerTests = let reportFile = Path.Combine(unique, "WriteJsonLeavesExpectedTraces.json") + let reportZip = reportFile + ".zip" + let junkfile = (reportFile + "." + (Path.GetFileName unique)) @@ -3207,7 +3220,7 @@ module AltCoverRunnerTests = // degenerate case 1 Assert.That(junkfile |> File.Exists |> not) - let (c0, w0) = Zip.openUpdate junkfile + let (c0, w0) = Zip.openUpdate junkfile true try Assert.That(c0 |> isNull) @@ -3216,11 +3229,15 @@ module AltCoverRunnerTests = finally w0.Dispose() - Runner.J.doReport counts AltCover.ReportFormat.NativeJson reportFile None + Runner.J.doReport + counts + (ReportFormat.NativeJson ||| ReportFormat.Zipped) + reportFile + None // ZipWriteJsonLeavesExpectedTraces |> ignore let (container, worker) = - Zip.openUpdate reportFile + Zip.openUpdate reportFile true use container' = container @@ -3260,9 +3277,590 @@ module AltCoverRunnerTests = Is.EqualTo expected ) finally + Assert.That(reportFile |> File.Exists |> not) Assert.That(junkfile |> File.Exists |> not) Assert.That(junkfile2 |> File.Exists |> not) + maybeDeleteFile reportZip + Console.SetOut saved + Directory.SetCurrentDirectory(here) + maybeIOException (fun () -> Directory.Delete(unique)) + + [] + let DivertedWriteLeavesExpectedTraces () = + Runner.init () + let saved = Console.Out + let here = Directory.GetCurrentDirectory() + + let where = + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName + + let unique = + Path.Combine(where, Guid.NewGuid().ToString()) + + let reportFile = + Path.Combine(unique, "FlushLeavesExpectedTraces.xml") + + let outputFile = + Path.Combine(unique, "DivertedFlushLeavesExpectedTraces.xml") + + let junkfile = + (reportFile + "." + (Path.GetFileName unique)) + + try + use stdout = new StringWriter() + Console.SetOut stdout + Directory.CreateDirectory(unique) |> ignore + Directory.SetCurrentDirectory(unique) + + Counter.measureTime <- + DateTime.ParseExact("2017-12-29T16:33:40.9564026+00:00", "o", null) + + use stream = + Assembly + .GetExecutingAssembly() + .GetManifestResourceStream(resource) + + do + use worker = + new FileStream(reportFile, FileMode.CreateNew) + + stream.CopyTo worker + + let hits = List() + + [ 0..9 ] + |> Seq.iter (fun i -> + for j = 1 to i + 1 do + hits.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, Null) + ignore j) + + let counts = + Dictionary>() + + hits + |> Seq.iter (fun (moduleId, hitPointId, hit) -> + if counts.ContainsKey moduleId |> not then + counts.Add(moduleId, Dictionary()) + + AltCover.Counter.addVisit counts moduleId hitPointId hit + |> ignore) + + // degenerate case + Assert.That(junkfile |> File.Exists |> not) + + do + use junkworker = + new FileStream(junkfile, FileMode.CreateNew) + + junkworker.Write([||], 0, 0) + () + + Runner.J.doReport counts AltCover.ReportFormat.NCover junkfile None // DivertedWriteLeavesExpectedTraces + |> ignore + + let (c0, w0) = Zip.openUpdate junkfile false + + try + Assert.That(c0 |> isNull) + Assert.That(w0, Is.InstanceOf()) + Assert.That(w0.Length, Is.EqualTo 8L) + finally + w0.Dispose() + + Runner.J.doReport counts AltCover.ReportFormat.NCover reportFile (Some outputFile) // DivertedWriteLeavesExpectedTraces + |> ignore + + use worker' = + new FileStream(outputFile, FileMode.Open) + + let after = XmlDocument() + after.Load worker' + + Assert.That( + after.SelectNodes("//seqpnt") + |> Seq.cast + |> Seq.map _.GetAttribute("visitcount"), + Is.EquivalentTo + [ "11" + "10" + "9" + "8" + "7" + "6" + "4" + "3" + "2" + "1" ] + ) + finally + maybeDeleteFile outputFile + maybeDeleteFile reportFile + maybeDeleteFile junkfile + Console.SetOut saved + Directory.SetCurrentDirectory(here) + maybeIOException (fun () -> Directory.Delete(unique)) + + [] + let DivertedWriteJsonLeavesExpectedTraces () = + Runner.init () + let saved = Console.Out + let here = Directory.GetCurrentDirectory() + + let where = + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName + + let unique = + Path.Combine(where, Guid.NewGuid().ToString()) + + let reportFile = + Path.Combine(unique, "WriteJsonLeavesExpectedTraces.json") + + let outputFile = + Path.Combine(unique, "DivertedWriteJsonLeavesExpectedTraces.json") + + let junkFile = + (reportFile + "." + (Path.GetFileName unique)) + + try + use stdout = new StringWriter() + Console.SetOut stdout + Directory.CreateDirectory(unique) |> ignore + Directory.SetCurrentDirectory(unique) + + let nativeJson = + Assembly + .GetExecutingAssembly() + .GetManifestResourceNames() + |> Seq.find _.EndsWith("Sample4.native.json", StringComparison.Ordinal) + + use stream = + Assembly + .GetExecutingAssembly() + .GetManifestResourceStream(nativeJson) + + do + use worker = + new FileStream(reportFile, FileMode.CreateNew) + + stream.CopyTo worker + + let tracks t = + [| Null + Call 0 + Time t + Both { Time = t; Call = 0 } |] + + let t0 = tracks 0L + + let hits = List() + + [ 0..9 ] + |> Seq.iter (fun i -> + for j = 1 to i + 1 do + hits.Add("Sample4.dll", i ||| (Counter.branchFlag * (i % 2)), t0.[i % 4]) + ignore j) + + let counts = + Dictionary>() + + hits + |> Seq.iter (fun (moduleId, hitPointId, hit) -> + if counts.ContainsKey moduleId |> not then + counts.Add(moduleId, Dictionary()) + + AltCover.Counter.addVisit counts moduleId hitPointId hit + |> ignore) + + let entries = Dictionary() + let pv = PointVisit.Create() + pv.Track(Time 512L) + tracks (1L) |> Seq.iter pv.Track + entries.Add(1, pv) + counts.Add(Track.Entry, entries) + + let exits = Dictionary() + let pv = PointVisit.Create() + tracks (2L) |> Seq.iter pv.Track + pv.Track(Time 1024L) + exits.Add(1, pv) + exits.Add(2, pv) + counts.Add(Track.Exit, exits) + + Runner.J.doReport + counts + AltCover.ReportFormat.NativeJson + reportFile + (Some outputFile) // DivertedWriteJsonLeavesExpectedTraces + |> ignore + + let jsonText = + use worker' = + new FileStream(outputFile, FileMode.Open) + + use reader = new StreamReader(worker') + reader.ReadToEnd() + // saved.WriteLine jsonText // NOT printfn "%s" jsonText + + let visitedJson = + Assembly + .GetExecutingAssembly() + .GetManifestResourceNames() + |> Seq.find + _.EndsWith("Sample4.syntheticvisits.native.json", StringComparison.Ordinal) + + use stream = + Assembly + .GetExecutingAssembly() + .GetManifestResourceStream(visitedJson) + + use reader = new StreamReader(stream) + + let expected = + reader + .ReadToEnd() + .Replace('\r', '\u00FF') + .Replace('\n', '\u00FF') + .Replace("\u00FF\u00FF", "\u00FF") + .Trim([| '\u00FF' |]) + + Assert.That( + jsonText + .Replace('\r', '\u00FF') + .Replace('\n', '\u00FF') + .Replace("\u00FF\u00FF", "\u00FF") + .Trim([| '\u00FF' |]), + Is.EqualTo expected + ) + finally maybeDeleteFile reportFile + maybeDeleteFile outputFile + maybeDeleteFile junkFile + Console.SetOut saved + Directory.SetCurrentDirectory(here) + maybeIOException (fun () -> Directory.Delete(unique)) + + [] + let DivertedZipWriteLeavesExpectedTraces () = + Runner.init () + let saved = Console.Out + let here = Directory.GetCurrentDirectory() + + let where = + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName + + let unique = + Path.Combine(where, Guid.NewGuid().ToString()) + + let reportFile = + Path.Combine(unique, "FlushLeavesExpectedTraces.xml") + + let reportZip = reportFile + ".zip" + + let outputFile = + Path.Combine(unique, "DivertedFlushLeavesExpectedTraces.xml") + + let outputZip = outputFile + ".zip" + + let junkfile = + (reportFile + "." + (Path.GetFileName unique)) + + let junkfile2 = junkfile + ".xml" + + let junkfile3 = junkfile + ".3.xml" + + try + use stdout = new StringWriter() + Console.SetOut stdout + Directory.CreateDirectory(unique) |> ignore + Directory.SetCurrentDirectory(unique) + + Counter.measureTime <- + DateTime.ParseExact("2017-12-29T16:33:40.9564026+00:00", "o", null) + + use stream = + Assembly + .GetExecutingAssembly() + .GetManifestResourceStream(resource) + + let doc = XDocument.Load stream + Zip.save (fun s -> doc.Save s) reportFile true // fsharplint:disable-line + + let hits = List() + + [ 0..9 ] + |> Seq.iter (fun i -> + for j = 1 to i + 1 do + hits.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, Null) + ignore j) + + let counts = + Dictionary>() + + hits + |> Seq.iter (fun (moduleId, hitPointId, hit) -> + if counts.ContainsKey moduleId |> not then + counts.Add(moduleId, Dictionary()) + + AltCover.Counter.addVisit counts moduleId hitPointId hit + |> ignore) + + // degenerate case 1 + Assert.That(junkfile |> File.Exists |> not) + let (c0, w0) = Zip.openUpdate junkfile true + + try + Assert.That(c0 |> isNull) + Assert.That(w0, Is.InstanceOf()) + Assert.That(w0.Length, Is.EqualTo 0L) + finally + w0.Dispose() + + // degenerate case 1a + let junkzip = junkfile + ".zip" + Assert.That(junkzip |> File.Exists |> not) + + do + use archive = + ZipFile.Open(junkzip, ZipArchiveMode.Create) + + let entry = + Guid.NewGuid().ToString() |> archive.CreateEntry + + use sink = entry.Open() + sink.Write([| 0uy |], 0, 1) + () + + let (c0, w0) = Zip.openUpdate junkfile true + + try + Assert.That(c0.IsNotNull) + Assert.That(w0, Is.InstanceOf()) + Assert.That(w0.Length, Is.EqualTo 0L) + finally + c0.Dispose() + w0.Dispose() + + // degenerate case 2 + Assert.That(junkfile2 |> File.Exists |> not) + + Runner.J.doReport + counts + (ReportFormat.NCover ||| ReportFormat.Zipped) + junkfile2 + (Some junkfile3) + |> ignore + + Assert.That(junkfile2 |> File.Exists |> not) + let (c1, w1) = Zip.openUpdate junkfile2 true + + try + Assert.That(c1 |> isNull) + Assert.That(w1, Is.InstanceOf()) + Assert.That(w1.Length, Is.EqualTo 0L) + finally + w0.Dispose() + Assert.That(junkfile2 |> File.Exists |> not) + + Runner.J.doReport + counts + (ReportFormat.NCover ||| ReportFormat.Zipped) + reportFile + (Some outputFile) + |> ignore + + let (container, worker) = + Zip.openUpdate reportFile true + + use worker' = worker + use container' = container + let after = XmlDocument() + after.Load worker' + + Assert.That( + after.SelectNodes("//seqpnt") + |> Seq.cast + |> Seq.map _.GetAttribute("visitcount"), + Is.EquivalentTo + [ "11" + "10" + "9" + "8" + "7" + "6" + "4" + "3" + "2" + "1" ] + ) + finally + Assert.That(reportFile |> File.Exists |> not, "unexpected reportfile") + Assert.That(outputFile |> File.Exists |> not, "unexpected outputfile") + Assert.That(junkfile |> File.Exists |> not, "unexpected junkfile") + Assert.That(junkfile2 |> File.Exists |> not, "unexpected junkfile2") + Assert.That(junkfile3 |> File.Exists |> not, "unexpected junkfile3") + maybeDeleteFile reportZip + maybeDeleteFile outputZip + Console.SetOut saved + Directory.SetCurrentDirectory(here) + maybeIOException (fun () -> Directory.Delete(unique)) + + [] + let DivertedZipWriteJsonLeavesExpectedTraces () = + Runner.init () + let saved = Console.Out + let here = Directory.GetCurrentDirectory() + + let where = + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName + + let unique = + Path.Combine(where, Guid.NewGuid().ToString()) + + let reportFile = + Path.Combine(unique, "WriteJsonLeavesExpectedTraces.json") + + let reportZip = reportFile + ".zip" + + let outputFile = + Path.Combine(unique, "DivertedWriteJsonLeavesExpectedTraces.json") + + let outputZip = outputFile + ".zip" + + let junkfile = + (reportFile + "." + (Path.GetFileName unique)) + + let junkfile2 = junkfile + ".json" + + try + use stdout = new StringWriter() + Console.SetOut stdout + Directory.CreateDirectory(unique) |> ignore + Directory.SetCurrentDirectory(unique) + + let nativeJson = + Assembly + .GetExecutingAssembly() + .GetManifestResourceNames() + |> Seq.find _.EndsWith("Sample4.native.json", StringComparison.Ordinal) + + use stream = + Assembly + .GetExecutingAssembly() + .GetManifestResourceStream(nativeJson) + + Zip.save (stream.CopyTo) reportFile true // fsharplint:disable-line + + let tracks t = + [| Null + Call 0 + Time t + Both { Time = t; Call = 0 } |] + + let t0 = tracks 0L + + let hits = List() + + [ 0..9 ] + |> Seq.iter (fun i -> + for j = 1 to i + 1 do + hits.Add("Sample4.dll", i ||| (Counter.branchFlag * (i % 2)), t0.[i % 4]) + ignore j) + + let counts = + Dictionary>() + + hits + |> Seq.iter (fun (moduleId, hitPointId, hit) -> + if counts.ContainsKey moduleId |> not then + counts.Add(moduleId, Dictionary()) + + AltCover.Counter.addVisit counts moduleId hitPointId hit + |> ignore) + + let entries = Dictionary() + let pv = PointVisit.Create() + pv.Track(Time 512L) + tracks (1L) |> Seq.iter pv.Track + entries.Add(1, pv) + entries.Add(2, pv) + counts.Add(Track.Entry, entries) + + let exits = Dictionary() + let pv = PointVisit.Create() + tracks (2L) |> Seq.iter pv.Track + pv.Track(Time 1024L) + exits.Add(1, pv) + counts.Add(Track.Exit, exits) + + // degenerate case 1 + Assert.That(junkfile |> File.Exists |> not) + let (c0, w0) = Zip.openUpdate junkfile true + + try + Assert.That(c0 |> isNull) + Assert.That(w0, Is.InstanceOf()) + Assert.That(w0.Length, Is.EqualTo 0L) + finally + w0.Dispose() + + Runner.J.doReport + counts + (ReportFormat.NativeJson ||| ReportFormat.Zipped) + reportFile + (Some outputFile) // DivertedZipWriteJsonLeavesExpectedTraces + |> ignore + + let (container, worker) = + Zip.openUpdate outputFile true + + use container' = container + + let jsonText = + use worker' = worker + use reader = new StreamReader(worker') + reader.ReadToEnd() + + let visitedJson = + Assembly + .GetExecutingAssembly() + .GetManifestResourceNames() + |> Seq.find + _.EndsWith("Sample4.syntheticvisits.native.json", StringComparison.Ordinal) + + use stream = + Assembly + .GetExecutingAssembly() + .GetManifestResourceStream(visitedJson) + + use reader = new StreamReader(stream) + + let expected = + reader + .ReadToEnd() + .Replace('\r', '\u00FF') + .Replace('\n', '\u00FF') + .Replace("\u00FF\u00FF", "\u00FF") + .Trim([| '\u00FF' |]) + + Assert.That( + jsonText + .Replace('\r', '\u00FF') + .Replace('\n', '\u00FF') + .Replace("\u00FF\u00FF", "\u00FF") + .Trim([| '\u00FF' |]), + Is.EqualTo expected + ) + finally + Assert.That(reportFile |> File.Exists |> not, "unexpected report file") + Assert.That(outputFile |> File.Exists |> not, "unexpected outputfile") + Assert.That(junkfile |> File.Exists |> not, "unexpected junk file") + Assert.That(junkfile2 |> File.Exists |> not, "unexpected junk2 file") + maybeDeleteFile reportZip + maybeDeleteFile outputZip Console.SetOut saved Directory.SetCurrentDirectory(here) maybeIOException (fun () -> Directory.Delete(unique)) From 58c490a682c103c218096684310fe3f688dae10e Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 11 May 2024 12:54:33 +0100 Subject: [PATCH 25/33] Fix some flakiness --- AltCover.Tests/XTests.fs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/AltCover.Tests/XTests.fs b/AltCover.Tests/XTests.fs index c2825453..17436ab9 100644 --- a/AltCover.Tests/XTests.fs +++ b/AltCover.Tests/XTests.fs @@ -220,6 +220,8 @@ module AltCoverXTests = [] let TypeSafeCollectOptionsCanBeValidated () = + CommandLine.error <- [] + let here = Assembly.GetExecutingAssembly().Location @@ -311,6 +313,8 @@ module AltCoverXTests = [] let TypeSafeCollectOptionsCanBeValidatedWithErrors () = + CommandLine.error <- [] + let subject = TypeSafe.CollectOptions.Create() @@ -347,6 +351,8 @@ module AltCoverXTests = [] let TypeSafeCollectOptionsCanBePositivelyValidatedWithErrors () = + CommandLine.error <- [] + let test = { TypeSafe.CollectOptions.Create() with RecorderDirectory = From 9b7df3f0c17d8c82d2cf3e05cf0c2f4170b046c6 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 11 May 2024 13:33:06 +0100 Subject: [PATCH 26/33] Fix another flake --- AltCover.Tests/XTests.fs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/AltCover.Tests/XTests.fs b/AltCover.Tests/XTests.fs index 17436ab9..2bc99d5d 100644 --- a/AltCover.Tests/XTests.fs +++ b/AltCover.Tests/XTests.fs @@ -1516,6 +1516,15 @@ module AltCoverXTests = = test' <@ report = codedreport @> "should be default coverage file" test <@ output = Some alternate @> + + use stream = + Assembly + .GetExecutingAssembly() + .GetManifestResourceStream("AltCover.Tests.GenuineNCover158.Xml") + + use fs = File.Create(alternate) + stream.CopyTo fs + test <@ hits |> Seq.isEmpty @> TimeSpan.Zero From c417a89e6064b2df6665f49eb794c5b1c600fb13 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 11 May 2024 13:50:35 +0100 Subject: [PATCH 27/33] Fix the simplest zip case --- AltCover.Tests/Runner.Tests.fs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index a1c3af47..b96aee20 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -2999,6 +2999,8 @@ module AltCoverRunnerTests = let junkfile = (reportFile + "." + (Path.GetFileName unique)) + let junkfile1 = junkfile + ".1" + let junkfile2 = junkfile + ".xml" try @@ -3042,19 +3044,22 @@ module AltCoverRunnerTests = let (c0, w0) = Zip.openUpdate junkfile true try - Assert.That(c0 |> isNull) + Assert.That(c0.IsNotNull) Assert.That(w0, Is.InstanceOf()) Assert.That(w0.Length, Is.EqualTo 0L) finally w0.Dispose() + c0.Dispose() // degenerate case 1a let junkzip = junkfile + ".zip" - Assert.That(junkzip |> File.Exists |> not) + Assert.That(junkzip |> File.Exists) + + let junk1zip = junkfile1 + ".zip" do use archive = - ZipFile.Open(junkzip, ZipArchiveMode.Create) + ZipFile.Open(junk1zip, ZipArchiveMode.Create) let entry = Guid.NewGuid().ToString() |> archive.CreateEntry @@ -3063,7 +3068,7 @@ module AltCoverRunnerTests = sink.Write([| 0uy |], 0, 1) () - let (c0, w0) = Zip.openUpdate junkfile true + let (c0, w0) = Zip.openUpdate junkfile1 true try Assert.That(c0.IsNotNull) @@ -3087,11 +3092,12 @@ module AltCoverRunnerTests = let (c1, w1) = Zip.openUpdate junkfile2 true try - Assert.That(c1 |> isNull) + Assert.That(c1.IsNotNull) Assert.That(w1, Is.InstanceOf()) Assert.That(w1.Length, Is.EqualTo 0L) finally - w0.Dispose() + w1.Dispose() + c1.Dispose() Assert.That(junkfile2 |> File.Exists |> not) Runner.J.doReport @@ -3128,8 +3134,12 @@ module AltCoverRunnerTests = finally Assert.That(reportFile |> File.Exists |> not) Assert.That(junkfile |> File.Exists |> not) + Assert.That(junkfile1 |> File.Exists |> not) Assert.That(junkfile2 |> File.Exists |> not) maybeDeleteFile reportZip + maybeDeleteFile (junkfile + ".zip") + maybeDeleteFile (junkfile1 + ".zip") + maybeDeleteFile (junkfile2 + ".zip") Console.SetOut saved Directory.SetCurrentDirectory(here) maybeIOException (fun () -> Directory.Delete(unique)) From 5d5fd7d875307538eb0f469cb5ea37578cce3ccf Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 13 May 2024 09:26:57 +0100 Subject: [PATCH 28/33] Fix next case --- AltCover.Tests/Runner.Tests.fs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index b96aee20..e29a07be 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -3233,11 +3233,12 @@ module AltCoverRunnerTests = let (c0, w0) = Zip.openUpdate junkfile true try - Assert.That(c0 |> isNull) + Assert.That(c0.IsNotNull) Assert.That(w0, Is.InstanceOf()) Assert.That(w0.Length, Is.EqualTo 0L) finally w0.Dispose() + c0.Dispose() Runner.J.doReport counts @@ -3291,6 +3292,7 @@ module AltCoverRunnerTests = Assert.That(junkfile |> File.Exists |> not) Assert.That(junkfile2 |> File.Exists |> not) maybeDeleteFile reportZip + maybeDeleteFile (junkfile + ".zip") Console.SetOut saved Directory.SetCurrentDirectory(here) maybeIOException (fun () -> Directory.Delete(unique)) From 3c27bb09ad660f55b8f0d124bd13f638167fb841 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 13 May 2024 09:44:32 +0100 Subject: [PATCH 29/33] Fix up the slightly obsolete corner case tests - leaves the real divert-to-zip as a TODO --- AltCover.Tests/Runner.Tests.fs | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index e29a07be..522f9b33 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -3579,6 +3579,8 @@ module AltCoverRunnerTests = let junkfile = (reportFile + "." + (Path.GetFileName unique)) + let junkfile1 = junkfile + ".1" + let junkfile2 = junkfile + ".xml" let junkfile3 = junkfile + ".3.xml" @@ -3624,14 +3626,15 @@ module AltCoverRunnerTests = let (c0, w0) = Zip.openUpdate junkfile true try - Assert.That(c0 |> isNull) + Assert.That(c0.IsNotNull) Assert.That(w0, Is.InstanceOf()) Assert.That(w0.Length, Is.EqualTo 0L) finally w0.Dispose() + c0.Dispose() // degenerate case 1a - let junkzip = junkfile + ".zip" + let junkzip = junkfile1 + ".zip" Assert.That(junkzip |> File.Exists |> not) do @@ -3645,7 +3648,7 @@ module AltCoverRunnerTests = sink.Write([| 0uy |], 0, 1) () - let (c0, w0) = Zip.openUpdate junkfile true + let (c0, w0) = Zip.openUpdate junkfile1 true try Assert.That(c0.IsNotNull) @@ -3669,12 +3672,14 @@ module AltCoverRunnerTests = let (c1, w1) = Zip.openUpdate junkfile2 true try - Assert.That(c1 |> isNull) + Assert.That(c1.IsNotNull) Assert.That(w1, Is.InstanceOf()) Assert.That(w1.Length, Is.EqualTo 0L) finally - w0.Dispose() - Assert.That(junkfile2 |> File.Exists |> not) + w1.Dispose() + c1.Dispose() + + Assert.That(junkfile2 |> File.Exists |> not) Runner.J.doReport counts @@ -3684,7 +3689,7 @@ module AltCoverRunnerTests = |> ignore let (container, worker) = - Zip.openUpdate reportFile true + Zip.openUpdate outputFile true use worker' = worker use container' = container @@ -3711,10 +3716,15 @@ module AltCoverRunnerTests = Assert.That(reportFile |> File.Exists |> not, "unexpected reportfile") Assert.That(outputFile |> File.Exists |> not, "unexpected outputfile") Assert.That(junkfile |> File.Exists |> not, "unexpected junkfile") + Assert.That(junkfile1 |> File.Exists |> not, "unexpected junkfile1") Assert.That(junkfile2 |> File.Exists |> not, "unexpected junkfile2") Assert.That(junkfile3 |> File.Exists |> not, "unexpected junkfile3") maybeDeleteFile reportZip maybeDeleteFile outputZip + maybeDeleteFile (junkfile + ".zip") + maybeDeleteFile (junkfile1 + ".zip") + maybeDeleteFile (junkfile2 + ".zip") + maybeDeleteFile (junkfile3 + ".zip") Console.SetOut saved Directory.SetCurrentDirectory(here) maybeIOException (fun () -> Directory.Delete(unique)) @@ -3813,11 +3823,12 @@ module AltCoverRunnerTests = let (c0, w0) = Zip.openUpdate junkfile true try - Assert.That(c0 |> isNull) + Assert.That(c0.IsNotNull) Assert.That(w0, Is.InstanceOf()) Assert.That(w0.Length, Is.EqualTo 0L) finally w0.Dispose() + c0.Dispose() Runner.J.doReport counts @@ -3873,6 +3884,7 @@ module AltCoverRunnerTests = Assert.That(junkfile2 |> File.Exists |> not, "unexpected junk2 file") maybeDeleteFile reportZip maybeDeleteFile outputZip + maybeDeleteFile (junkfile + ".zip") Console.SetOut saved Directory.SetCurrentDirectory(here) maybeIOException (fun () -> Directory.Delete(unique)) From a41c74eedfb8498ca1ffe4073486d6396a15c9ca Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 13 May 2024 09:57:38 +0100 Subject: [PATCH 30/33] Fixes diverted JSON --- AltCover.Engine/Runner.fs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 9e790b00..1f6f8e4b 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1328,11 +1328,13 @@ module internal Runner = Justification = "meets an interface")>] let writeNativeJsonReport (hits: Dictionary>) - unusedCannotBeUnderscore + format (file: Stream) output = - ignore unusedCannotBeUnderscore + let zipped = + int (format &&& ReportFormat.Zipped) <> 0 + let flushStart = DateTime.UtcNow // do work here let jsonText = @@ -1357,17 +1359,8 @@ module internal Runner = NativeJson.serializeToUtf8Bytes json if Option.isSome output then - use outputFile = - new FileStream( - output.Value, - FileMode.OpenOrCreate, - FileAccess.Write, - FileShare.None, - 4096, - FileOptions.SequentialScan - ) - - outputFile.Write(encoded, 0, encoded.Length) + Zip.save (fun s -> s.Write(encoded, 0, encoded.Length)) output.Value zipped + else file.Seek(0L, SeekOrigin.Begin) |> ignore file.SetLength 0L From e7c304021c296d6f5a221980ae66b98806304d1c Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 13 May 2024 18:24:19 +0100 Subject: [PATCH 31/33] Finally sort out the maybe zip/json vs xml/maybe redirect combos. --- AltCover.Engine/Runner.fs | 29 ++- AltCover.Recorder.Tests/Recorder.Tests.fs | 2 +- AltCover.Recorder/Base.fs | 9 +- AltCover.Tests/Expecto.fs | 12 +- AltCover.Tests/Runner.Tests.fs | 206 +--------------------- 5 files changed, 38 insertions(+), 220 deletions(-) diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 1f6f8e4b..4632c595 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1380,10 +1380,18 @@ module internal Runner = let (container, file) = Zip.openUpdate report zipped - try - if format &&& ReportFormat.TrackMask = ReportFormat.NativeJson then - writeNativeJsonReport hits format file arg - else + use container' = container + use file' = file + + if format &&& ReportFormat.TrackMask = ReportFormat.NativeJson then + writeNativeJsonReport hits format file arg + else + use outputFile = + match arg with + | None -> file + | _ -> new MemoryStream() :> Stream + + let result = AltCover.Counter.doFlushStream (postProcess hits format) pointProcess @@ -1391,12 +1399,15 @@ module internal Runner = hits format file - arg - finally - file.Dispose() + outputFile + + match arg with + | None -> () + | Some x -> + outputFile.Position <- 0l + Zip.save (outputFile.CopyTo) x zipped - if container.IsNotNull then - container.Dispose() + result reporter diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index eda014cf..d9143889 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -2019,7 +2019,6 @@ module AltCoverTests = #if !NET20 [] -#endif let ZipFlushLeavesExpectedTraces () = getMyMethodName "=>" @@ -2140,6 +2139,7 @@ module AltCoverTests = AltCoverCoreTests.maybeIOException (fun () -> Directory.Delete(unique)))) getMyMethodName "<=" +#endif [] let ShouldCreateDummyAttribute () = diff --git a/AltCover.Recorder/Base.fs b/AltCover.Recorder/Base.fs index 269b1ec3..1335a70b 100644 --- a/AltCover.Recorder/Base.fs +++ b/AltCover.Recorder/Base.fs @@ -424,8 +424,14 @@ module internal Counter = | _ -> addSingleVisit counts moduleId hitPointId context 1L -#endif + [] + let doFlushStream postProcess pointProcess own counts format coverageFile outputFile = + I.doFlush postProcess pointProcess own counts format coverageFile outputFile + +#else [] @@ -463,7 +469,6 @@ module internal Counter = I.doFlush postProcess pointProcess own counts format coverageFile outputFile -#if !RUNNER [] diff --git a/AltCover.Tests/Expecto.fs b/AltCover.Tests/Expecto.fs index 42f052b7..e0881028 100644 --- a/AltCover.Tests/Expecto.fs +++ b/AltCover.Tests/Expecto.fs @@ -38,10 +38,14 @@ module ExpectoTestManifest = "Runner.RepeatVisitsShouldIncrementTotal" Tests.AltCoverRunnerTests.KnownModuleWithPayloadMakesExpectedChangeInOpenCover, "Runner.KnownModuleWithPayloadMakesExpectedChangeInOpenCover" - Tests.AltCoverRunnerTests.FlushLeavesExpectedTraces, - "Runner.FlushLeavesExpectedTraces" - Tests.AltCoverRunnerTests.FlushLeavesExpectedTracesWhenDiverted, - "Runner.FlushLeavesExpectedTracesWhenDiverted" + Tests.AltCoverRunnerTests.DivertedWriteLeavesExpectedTraces, + "Runner.DivertedWriteLeavesExpectedTraces" + Tests.AltCoverRunnerTests.DivertedWriteJsonLeavesExpectedTraces, + "Runner.DivertedWriteJsonLeavesExpectedTraces" + Tests.AltCoverRunnerTests.DivertedZipWriteLeavesExpectedTraces, + "Runner.DivertedZipWriteLeavesExpectedTraces" + Tests.AltCoverRunnerTests.DivertedZipWriteJsonLeavesExpectedTraces, + "Runner.DivertedZipWriteJsonLeavesExpectedTraces" Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleJson, "Runner.NCoverShouldGeneratePlausibleJson" Tests.AltCoverRunnerTests.OpenCoverShouldGeneratePlausibleJson, diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index 522f9b33..b31d616c 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -301,208 +301,6 @@ module AltCoverRunnerTests = Is.EquivalentTo [ "2"; "2" ] ) - [] - let FlushLeavesExpectedTraces () = - Runner.init () - let saved = Console.Out - let here = Directory.GetCurrentDirectory() - - let where = - Assembly.GetExecutingAssembly().Location - |> Path.GetDirectoryName - - let unique = - Path.Combine(where, Guid.NewGuid().ToString()) - - let reportFile = - Path.Combine(unique, "FlushLeavesExpectedTraces.xml") - - try - let visits = - new Dictionary>() - - use stdout = new StringWriter() - Console.SetOut stdout - Directory.CreateDirectory(unique) |> ignore - Directory.SetCurrentDirectory(unique) - - Counter.measureTime <- - DateTime.ParseExact("2017-12-29T16:33:40.9564026+00:00", "o", null) - - use stream = - Assembly - .GetExecutingAssembly() - .GetManifestResourceStream(resource) - - let size = int stream.Length - let buffer = Array.create size 0uy - Assert.That(stream.Read(buffer, 0, size), Is.EqualTo size) - - do - use worker = - new FileStream(reportFile, FileMode.CreateNew) - - worker.Write(buffer, 0, size) - () - - let payload = Dictionary() - - [ 0..9 ] - |> Seq.iter (fun i -> payload.[i] <- init (int64 (i + 1)) []) - - visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - - do - use coverageFile = - new FileStream( - reportFile, - FileMode.Open, - FileAccess.ReadWrite, - FileShare.None, - 4096, - FileOptions.SequentialScan - ) - - Counter.doFlushStream - ignore - (fun _ _ -> ()) - true - visits - AltCover.ReportFormat.NCover - coverageFile - None - |> ignore - - use worker' = - new FileStream(reportFile, FileMode.Open) - - let after = XmlDocument() - after.Load worker' - - Assert.That( - after.SelectNodes("//seqpnt") - |> Seq.cast - |> Seq.map _.GetAttribute("visitcount"), - Is.EquivalentTo - [ "11" - "10" - "9" - "8" - "7" - "6" - "4" - "3" - "2" - "1" ] - ) - finally - maybeDeleteFile reportFile - Console.SetOut saved - Directory.SetCurrentDirectory(here) - maybeIOException (fun () -> Directory.Delete(unique)) - - [] - let FlushLeavesExpectedTracesWhenDiverted () = - Runner.init () - let saved = Console.Out - let here = Directory.GetCurrentDirectory() - - let where = - Assembly.GetExecutingAssembly().Location - |> Path.GetDirectoryName - - let unique = - Path.Combine(where, Guid.NewGuid().ToString()) - - let reportFile = - Path.Combine(unique, "FlushLeavesExpectedTraces.xml") - - let outputFile = - Path.Combine(unique, "FlushLeavesExpectedTracesWhenDiverted.xml") - - try - let visits = - new Dictionary>() - - use stdout = new StringWriter() - Console.SetOut stdout - Directory.CreateDirectory(unique) |> ignore - Directory.SetCurrentDirectory(unique) - - Counter.measureTime <- - DateTime.ParseExact("2017-12-29T16:33:40.9564026+00:00", "o", null) - - use stream = - Assembly - .GetExecutingAssembly() - .GetManifestResourceStream(resource) - - let size = int stream.Length - let buffer = Array.create size 0uy - Assert.That(stream.Read(buffer, 0, size), Is.EqualTo size) - - do - use worker = - new FileStream(reportFile, FileMode.CreateNew) - - worker.Write(buffer, 0, size) - () - - let payload = Dictionary() - - [ 0..9 ] - |> Seq.iter (fun i -> payload.[i] <- init (int64 (i + 1)) []) - - visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - - use coverageFile = - new FileStream( - reportFile, - FileMode.Open, - FileAccess.ReadWrite, - FileShare.None, - 4096, - FileOptions.SequentialScan - ) - - Counter.doFlushStream - ignore - (fun _ _ -> ()) - true - visits - AltCover.ReportFormat.NCover - coverageFile - (Some outputFile) - |> ignore - - use worker' = - new FileStream(outputFile, FileMode.Open) - - let after = XmlDocument() - after.Load worker' - - Assert.That( - after.SelectNodes("//seqpnt") - |> Seq.cast - |> Seq.map _.GetAttribute("visitcount"), - Is.EquivalentTo - [ "11" - "10" - "9" - "8" - "7" - "6" - "4" - "3" - "2" - "1" ] - ) - finally - maybeDeleteFile reportFile - Console.SetOut saved - Directory.SetCurrentDirectory(here) - maybeIOException (fun () -> Directory.Delete(unique)) - //Json.fs [] let NCoverShouldGeneratePlausibleJson () = @@ -3383,11 +3181,11 @@ module AltCoverRunnerTests = Runner.J.doReport counts AltCover.ReportFormat.NCover reportFile (Some outputFile) // DivertedWriteLeavesExpectedTraces |> ignore - use worker' = + use worker2 = new FileStream(outputFile, FileMode.Open) let after = XmlDocument() - after.Load worker' + after.Load worker2 Assert.That( after.SelectNodes("//seqpnt") From 0db76a2b399a1f994eee6a679db28f9369ceae75 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 13 May 2024 20:26:47 +0100 Subject: [PATCH 32/33] Update release notes --- ReleaseNotes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 16245b8a..b458c60f 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -4,6 +4,9 @@ A. Start with the Quick Start guide : https://github.com/SteveGilham/altcover/wi read the FAQ : https://github.com/SteveGilham/altcover/wiki/FAQ # (Habu series release 29) +* [BUGFIX] Fix summary data for `--outputFile` option +* [BUGFIX] Fix interection of `--zipFile` prepare option and `--outputFile` collect option +* [BUGFIX] Issue #220 - improve dependency resolution to the GAC # 8.8.21 (Habu series release 28) * [BREAKING; BUGFIX] Issue #206 : Update to net6+ for `dotnet test` integration and respect the `$(IsTestProject)` setting from the `Microsoft.NET.Test.Sdk` package. From e4b1779715c3dfd91bb3e273cacaa601ac0446f1 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 13 May 2024 20:28:33 +0100 Subject: [PATCH 33/33] [skip ci] Typo --- ReleaseNotes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index b458c60f..1552a523 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -5,7 +5,7 @@ read the FAQ : https://github.com/SteveGilham/altcover/wiki/FAQ # (Habu series release 29) * [BUGFIX] Fix summary data for `--outputFile` option -* [BUGFIX] Fix interection of `--zipFile` prepare option and `--outputFile` collect option +* [BUGFIX] Fix interaction of `--zipFile` prepare option and `--outputFile` collect option * [BUGFIX] Issue #220 - improve dependency resolution to the GAC # 8.8.21 (Habu series release 28)