From d4cea5f6243773f3f4e34d0ad2d3cee1ab212785 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 31 May 2024 16:44:38 +0100 Subject: [PATCH 01/91] [skip ci] Update release notes --- ReleaseNotes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 8cc0812e..d22db2e7 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 30) +# (Habu series release 31) + +# 8.8.74 (Habu series release 30) * [BUGFIX] Issue #222 - distinguish methods differing only in number of generic parameters (JSON and cobertura in particular, but with small changes for all all output formats) * [BUGFIX] Issue #223 - handle degenerate source paths for Cobertura output From 5bacc518348dc009a89ac8eb2cc58bc72f670732 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Wed, 12 Jun 2024 19:35:44 +0100 Subject: [PATCH 02/91] Get more coverlet output --- Build/coverletArgs.runsettings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Build/coverletArgs.runsettings b/Build/coverletArgs.runsettings index e2ae35f9..40c55517 100644 --- a/Build/coverletArgs.runsettings +++ b/Build/coverletArgs.runsettings @@ -4,7 +4,7 @@ - opencover + opencover,cobertura,teamcity [*]*Uncoverlet,[xunit*]*,[Sample*]*,[AltCover.Record*]M*,[NUnit*]*,[*]*UnitTestStub,[*]*ExpectoTestManifest,[AltCover.*]*StartupCode*SolutionRoot CompilerGenerated,TestSDKAutoGeneratedCode From ebb526f062af04db969b37f24ce48fada64e1360 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Wed, 12 Jun 2024 19:56:45 +0100 Subject: [PATCH 03/91] [skip ci] Tidy dead reference --- AltCover.sln | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AltCover.sln b/AltCover.sln index 9927e158..4e0d0485 100644 --- a/AltCover.sln +++ b/AltCover.sln @@ -59,7 +59,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Items", "Build Items" .github\workflows\main.yml = .github\workflows\main.yml Build\merge-coverage.ps1 = Build\merge-coverage.ps1 Build\msbuildtest.proj = Build\msbuildtest.proj - Build\NuPacker.xml = Build\NuPacker.xml OutputBuildProps.props = OutputBuildProps.props OutputBuildTargets.props = OutputBuildTargets.props Build\pester.ps1 = Build\pester.ps1 @@ -138,7 +137,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cecil", "Cecil", "{F56DE54A EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample0", "Samples\Sample0\Sample0.csproj", "{19CE63CE-3622-409A-974D-3EA01388317E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample32", "Samples\Sample32\Sample32.csproj", "{349B2983-FB15-4D72-B7F6-04FD36C81B90}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample32", "Samples\Sample32\Sample32.csproj", "{349B2983-FB15-4D72-B7F6-04FD36C81B90}" EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.RecorderModern", "AltCover.RecorderModern\AltCover.RecorderModern.fsproj", "{219B0218-3289-44DD-9C22-6C14A3D7B5A7}" EndProject From 727dde9305cacb00e58d3f52a86bb2cb660c32e1 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 13 Jun 2024 19:07:57 +0100 Subject: [PATCH 04/91] Split paths to facets --- AltCover.Engine/Cobertura.fs | 15 +++++++++++++++ AltCover.Tests/Runner.Tests.fs | 14 ++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/AltCover.Engine/Cobertura.fs b/AltCover.Engine/Cobertura.fs index 3f0f115d..7340fc81 100644 --- a/AltCover.Engine/Cobertura.fs +++ b/AltCover.Engine/Cobertura.fs @@ -30,6 +30,21 @@ module internal Cobertura = String.Format(CultureInfo.InvariantCulture, "{0:0.##}", ratio) ) + let splitPath path = + let rec facets path bits = + let npath = Path.GetDirectoryName path + let facet = if String.IsNullOrWhiteSpace npath then path else (Path.GetFileName path) + let wfacet = facet :: bits + if String.IsNullOrWhiteSpace npath then + wfacet + else + facets npath wfacet + + if String.IsNullOrWhiteSpace path then + [String.Empty] + else + facets path [] + [] + let PathsSplitOK () = + let cases = + [ + ("C:/Users/anon/OneDrive/Pictures/wallpaper.jpg", ["C:\\"; "Users"; "anon"; "OneDrive"; "Pictures"; "wallpaper.jpg"]) + ("/usr/home/anon/project/src/code.cs", [String([|Path.DirectorySeparatorChar|]); "usr"; "home"; "anon"; "project"; "src"; "code.cs"]) + ("partial/path/OK", ["partial"; "path"; "OK"]) + (String.Empty, [String.Empty]) + (null, [String.Empty]) + ] + + cases + |> List.iter (fun (case, expect) -> test <@ Cobertura.I.splitPath case = expect @>) + [] let DegenerateCasesShouldNotGenerateCobertura () = Runner.init () From d61e313834ce2a4c6f8b515f100b066522c2e113 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 13 Jun 2024 19:25:31 +0100 Subject: [PATCH 05/91] Getting tests to run --- AltCover.Engine/Cobertura.fs | 3 +++ AltCover.Tests/Expecto.fs | 2 ++ 2 files changed, 5 insertions(+) diff --git a/AltCover.Engine/Cobertura.fs b/AltCover.Engine/Cobertura.fs index 7340fc81..2a622225 100644 --- a/AltCover.Engine/Cobertura.fs +++ b/AltCover.Engine/Cobertura.fs @@ -30,6 +30,9 @@ module internal Cobertura = String.Format(CultureInfo.InvariantCulture, "{0:0.##}", ratio) ) + [] let splitPath path = let rec facets path bits = let npath = Path.GetDirectoryName path diff --git a/AltCover.Tests/Expecto.fs b/AltCover.Tests/Expecto.fs index b5a5191c..ca524a71 100644 --- a/AltCover.Tests/Expecto.fs +++ b/AltCover.Tests/Expecto.fs @@ -274,6 +274,8 @@ module ExpectoTestManifest = "Runner.NCoverWithOverloadsShouldGeneratePlausibleCobertura" Tests.AltCoverRunnerTests.NCoverShouldGenerateMorePlausibleCobertura, "Runner.NCoverShouldGenerateMorePlausibleCobertura" + Tests.AltCoverRunnerTests.PathsSplitOK, + "Runner.PathsSplitOK" Tests.AltCoverRunnerTests.DegenerateCasesShouldNotGenerateCobertura, "Runner.DegenerateCasesShouldNotGenerateCobertura" Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleCoberturaWithMissingFullName, From 313923f10ac1f78b6ec6fdbcf1d956c62e2a4f41 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 13 Jun 2024 19:40:33 +0100 Subject: [PATCH 06/91] First Linux case --- AltCover.Tests/Runner.Tests.fs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index 535b3a30..a3c971f0 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -6154,7 +6154,11 @@ module AltCoverRunnerTests = let PathsSplitOK () = let cases = [ +#if WINDOWS ("C:/Users/anon/OneDrive/Pictures/wallpaper.jpg", ["C:\\"; "Users"; "anon"; "OneDrive"; "Pictures"; "wallpaper.jpg"]) +#else + ("C:/Users/anon/OneDrive/Pictures/wallpaper.jpg", ["C:"; "Users"; "anon"; "OneDrive"; "Pictures"; "wallpaper.jpg"]) +#endif ("/usr/home/anon/project/src/code.cs", [String([|Path.DirectorySeparatorChar|]); "usr"; "home"; "anon"; "project"; "src"; "code.cs"]) ("partial/path/OK", ["partial"; "path"; "OK"]) (String.Empty, [String.Empty]) From e5694e645fcca6658daadc95e471e4e3a0dc20e1 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 13 Jun 2024 20:02:34 +0100 Subject: [PATCH 07/91] And back together again --- AltCover.Tests/Runner.Tests.fs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index a3c971f0..6c5bffdc 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -6166,7 +6166,10 @@ module AltCoverRunnerTests = ] cases - |> List.iter (fun (case, expect) -> test <@ Cobertura.I.splitPath case = expect @>) + |> List.iter (fun (case, expect) -> + test <@ Cobertura.I.splitPath case = expect @> + if case.IsNotNull then + test <@ case = (Path.Combine (List.toArray expect)).Replace ("\\", "/") @>) [] let DegenerateCasesShouldNotGenerateCobertura () = From 8d3e9f402bca5d65b3c8af9edf3e6de590b3b0b4 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 13 Jun 2024 20:17:19 +0100 Subject: [PATCH 08/91] And back together again --- AltCover.Engine/Cobertura.fs | 14 +++++++++--- AltCover.Tests/Expecto.fs | 3 +-- AltCover.Tests/Runner.Tests.fs | 39 +++++++++++++++++++++++++++------- Build/targets.fs | 4 ++++ 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/AltCover.Engine/Cobertura.fs b/AltCover.Engine/Cobertura.fs index 2a622225..b34fbfc8 100644 --- a/AltCover.Engine/Cobertura.fs +++ b/AltCover.Engine/Cobertura.fs @@ -32,19 +32,27 @@ module internal Cobertura = [] + Justification = + "Temporary to validate")>] let splitPath path = let rec facets path bits = let npath = Path.GetDirectoryName path - let facet = if String.IsNullOrWhiteSpace npath then path else (Path.GetFileName path) + + let facet = + if String.IsNullOrWhiteSpace npath then + path + else + (Path.GetFileName path) + let wfacet = facet :: bits + if String.IsNullOrWhiteSpace npath then wfacet else facets npath wfacet if String.IsNullOrWhiteSpace path then - [String.Empty] + [ String.Empty ] else facets path [] diff --git a/AltCover.Tests/Expecto.fs b/AltCover.Tests/Expecto.fs index ca524a71..2fdc58d8 100644 --- a/AltCover.Tests/Expecto.fs +++ b/AltCover.Tests/Expecto.fs @@ -274,8 +274,7 @@ module ExpectoTestManifest = "Runner.NCoverWithOverloadsShouldGeneratePlausibleCobertura" Tests.AltCoverRunnerTests.NCoverShouldGenerateMorePlausibleCobertura, "Runner.NCoverShouldGenerateMorePlausibleCobertura" - Tests.AltCoverRunnerTests.PathsSplitOK, - "Runner.PathsSplitOK" + Tests.AltCoverRunnerTests.PathsSplitOK, "Runner.PathsSplitOK" Tests.AltCoverRunnerTests.DegenerateCasesShouldNotGenerateCobertura, "Runner.DegenerateCasesShouldNotGenerateCobertura" Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleCoberturaWithMissingFullName, diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index 6c5bffdc..79bc0ed9 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -6155,21 +6155,44 @@ module AltCoverRunnerTests = let cases = [ #if WINDOWS - ("C:/Users/anon/OneDrive/Pictures/wallpaper.jpg", ["C:\\"; "Users"; "anon"; "OneDrive"; "Pictures"; "wallpaper.jpg"]) + ("C:/Users/anon/OneDrive/Pictures/wallpaper.jpg", + [ "C:\\" + "Users" + "anon" + "OneDrive" + "Pictures" + "wallpaper.jpg" ]) #else - ("C:/Users/anon/OneDrive/Pictures/wallpaper.jpg", ["C:"; "Users"; "anon"; "OneDrive"; "Pictures"; "wallpaper.jpg"]) + ("C:/Users/anon/OneDrive/Pictures/wallpaper.jpg", + [ "C:" + "Users" + "anon" + "OneDrive" + "Pictures" + "wallpaper.jpg" ]) #endif - ("/usr/home/anon/project/src/code.cs", [String([|Path.DirectorySeparatorChar|]); "usr"; "home"; "anon"; "project"; "src"; "code.cs"]) - ("partial/path/OK", ["partial"; "path"; "OK"]) - (String.Empty, [String.Empty]) - (null, [String.Empty]) - ] + ("/usr/home/anon/project/src/code.cs", + [ String([| Path.DirectorySeparatorChar |]) + "usr" + "home" + "anon" + "project" + "src" + "code.cs" ]) + ("partial/path/OK", [ "partial"; "path"; "OK" ]) + (String.Empty, [ String.Empty ]) + (null, [ String.Empty ]) ] cases |> List.iter (fun (case, expect) -> test <@ Cobertura.I.splitPath case = expect @> + if case.IsNotNull then - test <@ case = (Path.Combine (List.toArray expect)).Replace ("\\", "/") @>) + test + <@ + case = (Path.Combine(List.toArray expect)) + .Replace("\\", "/") + @>) [] let DegenerateCasesShouldNotGenerateCobertura () = diff --git a/Build/targets.fs b/Build/targets.fs index 6542dd25..cf217c75 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -8139,6 +8139,10 @@ module Targets = let cobertura2Files = xml + |> List.filter (fun (x, _) -> + Path + .GetFileName(x) + .Equals("coverage.cobertura.xml", StringComparison.Ordinal)) |> List.filter (fun x -> let root = (snd x).Root From 2dbd3c0bf1d91da67dfb50c659cbe0da275f2524 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 13 Jun 2024 20:19:21 +0100 Subject: [PATCH 09/91] Fix filter --- Build/targets.fs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Build/targets.fs b/Build/targets.fs index cf217c75..82bc8692 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -8142,7 +8142,8 @@ module Targets = |> List.filter (fun (x, _) -> Path .GetFileName(x) - .Equals("coverage.cobertura.xml", StringComparison.Ordinal)) + .Equals("coverage.cobertura.xml", StringComparison.Ordinal) + |> not) |> List.filter (fun x -> let root = (snd x).Root From 137c3bc85cadf0c036f76d468b73bf0d89c9503c Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 13 Jun 2024 20:53:59 +0100 Subject: [PATCH 10/91] Get the sources first --- AltCover.Engine/Cobertura.fs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/AltCover.Engine/Cobertura.fs b/AltCover.Engine/Cobertura.fs index b34fbfc8..f981266a 100644 --- a/AltCover.Engine/Cobertura.fs +++ b/AltCover.Engine/Cobertura.fs @@ -66,18 +66,26 @@ module internal Cobertura = (tag: string) (attribute: string) = - report.Descendants(tag.X) - |> Seq.map (fun s -> s.Attribute(attribute.X).Value) - |> Seq.filter (fun a -> a |> String.IsNullOrWhiteSpace |> not) - |> Seq.map Path.GetDirectoryName - |> Seq.filter (String.IsNullOrWhiteSpace >> not) - |> Seq.fold (fun s f -> s |> Set.add f) Set.empty - |> Seq.sort + let rawsources = + report.Descendants(tag.X) + |> Seq.map (fun s -> s.Attribute(attribute.X).Value) + |> Seq.filter (fun a -> a |> String.IsNullOrWhiteSpace |> not) + |> Seq.map Path.GetDirectoryName + |> Seq.filter (String.IsNullOrWhiteSpace >> not) + |> Seq.distinct + |> Seq.sort + + rawsources |> Seq.iter (fun f -> target.Descendants("sources".X) |> Seq.iter _.Add(XElement("source".X, XText(f)))) + rawsources + let internal nCover (report: XDocument) (packages: XElement) = + + let sources = addSources report packages.Parent "seqpnt" "document" + let processSeqPnts document (method: XElement) (lines: XElement) = method.Descendants("seqpnt".X) |> Seq.filter (fun s -> @@ -228,9 +236,10 @@ module internal Cobertura = p.Attribute("lines-valid".X).Value <- total.ToString(CultureInfo.InvariantCulture) p.Attribute("lines-covered".X).Value <- hits.ToString(CultureInfo.InvariantCulture) - addSources report packages.Parent "seqpnt" "document" - let internal openCover (report: XDocument) (packages: XElement) = + + let sources = addSources report packages.Parent "File" "fullPath" + let extract (owner: XElement) (target: XElement) = let summary = owner.Elements("Summary".X) |> Seq.head @@ -504,8 +513,6 @@ module internal Cobertura = |> Seq.head) packages.Parent - addSources report packages.Parent "File" "fullPath" - let internal convertReport (report: XDocument) (format: ReportFormat) = let rewrite = XDocument(XDeclaration("1.0", "utf-8", "no"), [||]) From 78bf65fffe418555a00a32427c99e08490e5e65c Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 14 Jun 2024 19:06:51 +0100 Subject: [PATCH 11/91] Do grouping --- AltCover.Engine/Cobertura.fs | 25 ++++++++++++++++++++++-- AltCover.Tests/Expecto.fs | 1 + AltCover.Tests/Runner.Tests.fs | 35 ++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/AltCover.Engine/Cobertura.fs b/AltCover.Engine/Cobertura.fs index f981266a..1b2f5c6e 100644 --- a/AltCover.Engine/Cobertura.fs +++ b/AltCover.Engine/Cobertura.fs @@ -56,6 +56,19 @@ module internal Cobertura = else facets path [] + [] + let grouping path = + match path with + | [ "\\" ] + | [ "/" ] -> "/" + | "\\" :: x :: _ + | "/" :: x :: _ -> "/" + x + | [] -> String.Empty + | _ -> path |> Seq.head + [ Seq.distinct |> Seq.sort + let groupable = + rawsources |> Seq.map (fun x -> (x, splitPath x)) + + let groups = + groupable |> Seq.groupBy (snd >> grouping) + rawsources |> Seq.iter (fun f -> target.Descendants("sources".X) @@ -84,7 +103,8 @@ module internal Cobertura = let internal nCover (report: XDocument) (packages: XElement) = - let sources = addSources report packages.Parent "seqpnt" "document" + let sources = + addSources report packages.Parent "seqpnt" "document" let processSeqPnts document (method: XElement) (lines: XElement) = method.Descendants("seqpnt".X) @@ -238,7 +258,8 @@ module internal Cobertura = let internal openCover (report: XDocument) (packages: XElement) = - let sources = addSources report packages.Parent "File" "fullPath" + let sources = + addSources report packages.Parent "File" "fullPath" let extract (owner: XElement) (target: XElement) = let summary = diff --git a/AltCover.Tests/Expecto.fs b/AltCover.Tests/Expecto.fs index 2fdc58d8..55add236 100644 --- a/AltCover.Tests/Expecto.fs +++ b/AltCover.Tests/Expecto.fs @@ -275,6 +275,7 @@ module ExpectoTestManifest = Tests.AltCoverRunnerTests.NCoverShouldGenerateMorePlausibleCobertura, "Runner.NCoverShouldGenerateMorePlausibleCobertura" Tests.AltCoverRunnerTests.PathsSplitOK, "Runner.PathsSplitOK" + Tests.AltCoverRunnerTests.PathsGroupOK, "Runner.PathsGroupOK" Tests.AltCoverRunnerTests.DegenerateCasesShouldNotGenerateCobertura, "Runner.DegenerateCasesShouldNotGenerateCobertura" Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleCoberturaWithMissingFullName, diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index 79bc0ed9..6884a0ad 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -6194,6 +6194,41 @@ module AltCoverRunnerTests = .Replace("\\", "/") @>) + [] + let PathsGroupOK () = + let cases = + [ ([ "C:\\" + "Users" + "anon" + "OneDrive" + "Pictures" + "wallpaper.jpg" ], + "C:\\") + ([ "/" + "usr" + "home" + "anon" + "project" + "src" + "code.cs" ], + "/usr") + ([ "\\" + "usr" + "home" + "anon" + "project" + "src" + "code.cs" ], + "/usr") + ([ "/" ], "/") + ([ "\\" ], "/") + ([ "partial"; "path"; "OK" ], "partial") + ([], String.Empty) + ([ String.Empty ], String.Empty) ] + + cases + |> List.iter (fun (case, expect) -> test <@ Cobertura.I.grouping case = expect @>) + [] let DegenerateCasesShouldNotGenerateCobertura () = Runner.init () From cda4e8e6f434c5a26bae19d07ec877cbe01e54dc Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 14 Jun 2024 19:49:04 +0100 Subject: [PATCH 12/91] Incremental partial implementation --- AltCover.Engine/Cobertura.fs | 18 ++++++++++++++++-- AltCover.Tests/NCoverWithPartials.cob.xml | 1 - AltCover.Tests/OpenCoverWithPartials.cob.xml | 1 - 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/AltCover.Engine/Cobertura.fs b/AltCover.Engine/Cobertura.fs index 1b2f5c6e..429e59d1 100644 --- a/AltCover.Engine/Cobertura.fs +++ b/AltCover.Engine/Cobertura.fs @@ -69,6 +69,15 @@ module internal Cobertura = | [] -> String.Empty | _ -> path |> Seq.head + let extractSource x = + let key = fst x + let values = snd x + + match Seq.length values with + | 1 -> (key, values |> Seq.head |> fst ) + | _ -> // extract longest common prefix + (key, values |> Seq.head |> fst ) // TODO + [ Seq.groupBy (snd >> grouping) - rawsources + let results = + groups + |> Seq.map extractSource + + results + |> Seq.map snd |> Seq.iter (fun f -> target.Descendants("sources".X) |> Seq.iter _.Add(XElement("source".X, XText(f)))) - rawsources + results let internal nCover (report: XDocument) (packages: XElement) = diff --git a/AltCover.Tests/NCoverWithPartials.cob.xml b/AltCover.Tests/NCoverWithPartials.cob.xml index b26e853b..1d74463d 100644 --- a/AltCover.Tests/NCoverWithPartials.cob.xml +++ b/AltCover.Tests/NCoverWithPartials.cob.xml @@ -3,7 +3,6 @@ C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.29.30133/include - C:/Users/steve/Documents/GitHub/altcover/Samples/Sample29/SimpleMix d:/a01/_work/5/s/src/vctools/crt/crtw32/msilcrt diff --git a/AltCover.Tests/OpenCoverWithPartials.cob.xml b/AltCover.Tests/OpenCoverWithPartials.cob.xml index 4a58f2d8..21cd3899 100644 --- a/AltCover.Tests/OpenCoverWithPartials.cob.xml +++ b/AltCover.Tests/OpenCoverWithPartials.cob.xml @@ -3,7 +3,6 @@ C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include - C:\Users\steve\Documents\GitHub\altcover\Samples\Sample29\SimpleMix d:\a01\_work\5\s\src\vctools\crt\crtw32\msilcrt From 25c06b988a497df1ba6742d7a31ce6e20412275b Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 15 Jun 2024 11:44:22 +0100 Subject: [PATCH 13/91] Extract sources --- AltCover.Engine/Cobertura.fs | 43 ++++++++++++++++---- AltCover.Tests/Expecto.fs | 1 + AltCover.Tests/NCoverWithPartials.cob.xml | 2 +- AltCover.Tests/OpenCoverWithPartials.cob.xml | 2 +- AltCover.Tests/Runner.Tests.fs | 18 ++++++++ 5 files changed, 55 insertions(+), 11 deletions(-) diff --git a/AltCover.Engine/Cobertura.fs b/AltCover.Engine/Cobertura.fs index 429e59d1..2cc2461a 100644 --- a/AltCover.Engine/Cobertura.fs +++ b/AltCover.Engine/Cobertura.fs @@ -69,14 +69,41 @@ module internal Cobertura = | [] -> String.Empty | _ -> path |> Seq.head - let extractSource x = - let key = fst x - let values = snd x - + let extractSource (values: (string * #(string seq)) seq) = match Seq.length values with - | 1 -> (key, values |> Seq.head |> fst ) + | 1 -> values |> Seq.head |> fst | _ -> // extract longest common prefix - (key, values |> Seq.head |> fst ) // TODO + let l = + values + |> Seq.map (fun (_, split) -> Seq.length split) + |> Seq.min + + let starter = values |> Seq.head + + let parts = + values + |> Seq.map (fun (_, split) -> split |> Seq.take l |> Seq.toArray) + + let tokens = + (snd starter) + |> Seq.mapi (fun i facet -> (i, facet)) + |> Seq.take l + + let prefix = + tokens + |> Seq.takeWhile (fun (i, facet) -> + parts + |> Seq.map (fun x -> x[i]) + |> Seq.forall (fun x -> x = facet)) + |> Seq.map snd + |> Seq.toArray + |> Path.Combine + + let trimmed = prefix.Length + let source = fst starter + + source.Substring(0, trimmed).Trim('\\') + + String([| Path.DirectorySeparatorChar |]) [ Seq.groupBy (snd >> grouping) let results = - groups - |> Seq.map extractSource + groups |> Seq.map (snd >> extractSource) results - |> Seq.map snd |> Seq.iter (fun f -> target.Descendants("sources".X) |> Seq.iter _.Add(XElement("source".X, XText(f)))) diff --git a/AltCover.Tests/Expecto.fs b/AltCover.Tests/Expecto.fs index 55add236..594fca6d 100644 --- a/AltCover.Tests/Expecto.fs +++ b/AltCover.Tests/Expecto.fs @@ -276,6 +276,7 @@ module ExpectoTestManifest = "Runner.NCoverShouldGenerateMorePlausibleCobertura" Tests.AltCoverRunnerTests.PathsSplitOK, "Runner.PathsSplitOK" Tests.AltCoverRunnerTests.PathsGroupOK, "Runner.PathsGroupOK" + Tests.AltCoverRunnerTests.ExtractSourcesOK, "Runner.ExtractSourcesOK" Tests.AltCoverRunnerTests.DegenerateCasesShouldNotGenerateCobertura, "Runner.DegenerateCasesShouldNotGenerateCobertura" Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleCoberturaWithMissingFullName, diff --git a/AltCover.Tests/NCoverWithPartials.cob.xml b/AltCover.Tests/NCoverWithPartials.cob.xml index 1d74463d..1fe7a350 100644 --- a/AltCover.Tests/NCoverWithPartials.cob.xml +++ b/AltCover.Tests/NCoverWithPartials.cob.xml @@ -2,7 +2,7 @@ - C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.29.30133/include + C:/ d:/a01/_work/5/s/src/vctools/crt/crtw32/msilcrt diff --git a/AltCover.Tests/OpenCoverWithPartials.cob.xml b/AltCover.Tests/OpenCoverWithPartials.cob.xml index 21cd3899..0edccb13 100644 --- a/AltCover.Tests/OpenCoverWithPartials.cob.xml +++ b/AltCover.Tests/OpenCoverWithPartials.cob.xml @@ -2,7 +2,7 @@ - C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include + C:\ d:\a01\_work\5\s\src\vctools\crt\crtw32\msilcrt diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index 6884a0ad..dbaf961c 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -6229,6 +6229,24 @@ module AltCoverRunnerTests = cases |> List.iter (fun (case, expect) -> test <@ Cobertura.I.grouping case = expect @>) + [] + let ExtractSourcesOK () = + let cases = + [ ([ "a" ], "a") + ([ "a/b/"; "a/b/c" ], "a/b") + ([ "a/b/x/y"; "a/c/d" ], "a") + ([ "c:\\b\\x\\y"; "c:\\b\\c\\d" ], "c:\\b") ] + |> List.map (fun (inputs, expect) -> + (inputs + |> Seq.map (fun x -> (x, Cobertura.I.splitPath x))), + expect) + + cases + |> Seq.iter (fun (case, expect) -> + test <@ Cobertura.I.extractSource case = expect.Replace('\\', '/') + "/" @>) + + () + [] let DegenerateCasesShouldNotGenerateCobertura () = Runner.init () From 75941d6b66290424648c63d5004ae2cb2a2045ed Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 15 Jun 2024 14:10:12 +0100 Subject: [PATCH 14/91] Fix filenames and then all the test data --- AltCover.Engine/Cobertura.fs | 43 ++++++++++++++++---- AltCover.Tests/Issue222.NCover.cobertura | 8 ++-- AltCover.Tests/Issue222.OpenCover.cobertura | 8 ++-- AltCover.Tests/NCover.ConvertTo.cobertura | 2 +- AltCover.Tests/NCover122.cobertura | 4 +- AltCover.Tests/NCoverBugFix.cobertura | 2 +- AltCover.Tests/NCoverWithPartials.cob.xml | 10 ++--- AltCover.Tests/OpenCover.ConvertTo.cobertura | 2 +- AltCover.Tests/OpenCoverWithPartials.cob.xml | 10 ++--- AltCover.Tests/Runner.Tests.fs | 19 +++++---- AltCover.Tests/Sample1WithNCover.cob.xml | 2 +- AltCover.Tests/Sample4FullTracking.cobertura | 12 +++--- AltCover.Tests/Sample5.native.cobertura | 8 ++-- AltCover.Tests/Sample5.ncover.cobertura | 26 ++++++------ AltCover.Tests/issue122.cobertura | 4 +- AltCover.sln | 2 + 16 files changed, 98 insertions(+), 64 deletions(-) diff --git a/AltCover.Engine/Cobertura.fs b/AltCover.Engine/Cobertura.fs index 2cc2461a..2b08fcdd 100644 --- a/AltCover.Engine/Cobertura.fs +++ b/AltCover.Engine/Cobertura.fs @@ -6,6 +6,7 @@ open System.Xml.Linq open System.Globalization open AltCover.Shared +open System.Diagnostics.CodeAnalysis // based on the sample file at https://raw.githubusercontent.com/jenkinsci/cobertura-plugin/master/src/test/resources/hudson/plugins/cobertura/coverage-with-data.xml [ String.Empty | _ -> path |> Seq.head + [] + [] let extractSource (values: (string * #(string seq)) seq) = + let starter = values |> Seq.head + match Seq.length values with - | 1 -> values |> Seq.head |> fst + | 1 -> starter |> fst | _ -> // extract longest common prefix let l = values |> Seq.map (fun (_, split) -> Seq.length split) |> Seq.min - let starter = values |> Seq.head - let parts = values |> Seq.map (fun (_, split) -> split |> Seq.take l |> Seq.toArray) @@ -94,7 +101,7 @@ module internal Cobertura = |> Seq.takeWhile (fun (i, facet) -> parts |> Seq.map (fun x -> x[i]) - |> Seq.forall (fun x -> x = facet)) + |> Seq.forall (fun x -> x.Equals(facet, StringComparison.Ordinal))) |> Seq.map snd |> Seq.toArray |> Path.Combine @@ -139,6 +146,7 @@ module internal Cobertura = |> Seq.iter _.Add(XElement("source".X, XText(f)))) results + |> Seq.map (fun p -> p.Replace('\\', '/').Trim('/')) let internal nCover (report: XDocument) (packages: XElement) = @@ -226,12 +234,24 @@ module internal Cobertura = |> LCov.sortByFirst |> Seq.fold (processMethod document methods) (0, 0) - let processClass (classes: XElement) (hits, total) ((name, document), method) = + let processClass + (classes: XElement) + (hits, total) + ((name, document: string), method) + = + let normalized = document.Replace('\\', '/') + + let filename = + sources + |> Seq.tryFind (fun s -> normalized.StartsWith(s, StringComparison.Ordinal)) + |> Option.map (fun start -> document.Substring(start.Length + 1)) + |> Option.defaultValue document + let ``class`` = XElement( "class".X, XAttribute("name".X, name), - XAttribute("filename".X, document) + XAttribute("filename".X, filename) ) classes.Add(``class``) @@ -485,18 +505,25 @@ module internal Cobertura = |> Seq.fold (processMethod fileid methods) (0, 0, 0, 0, 0, 0) let processClass - files + (files: Map) (classes: XElement) (cvcum, ccum) ((name, fileid), methodSet) = let document = files |> Map.find fileid + let normalized = document.Replace('\\', '/') + + let filename = + sources + |> Seq.tryFind (fun s -> normalized.StartsWith(s, StringComparison.Ordinal)) + |> Option.map (fun start -> document.Substring(start.Length + 1)) + |> Option.defaultValue document let ``class`` = XElement( "class".X, XAttribute("name".X, name), - XAttribute("filename".X, document) + XAttribute("filename".X, filename) ) classes.Add(``class``) diff --git a/AltCover.Tests/Issue222.NCover.cobertura b/AltCover.Tests/Issue222.NCover.cobertura index ff802844..5872c3d9 100644 --- a/AltCover.Tests/Issue222.NCover.cobertura +++ b/AltCover.Tests/Issue222.NCover.cobertura @@ -7,7 +7,7 @@ - + @@ -23,7 +23,7 @@ - + @@ -65,7 +65,7 @@ - + @@ -77,7 +77,7 @@ - + diff --git a/AltCover.Tests/Issue222.OpenCover.cobertura b/AltCover.Tests/Issue222.OpenCover.cobertura index 3b3da7a7..12b97481 100644 --- a/AltCover.Tests/Issue222.OpenCover.cobertura +++ b/AltCover.Tests/Issue222.OpenCover.cobertura @@ -7,7 +7,7 @@ - + @@ -23,7 +23,7 @@ - + @@ -65,7 +65,7 @@ - + @@ -77,7 +77,7 @@ - + diff --git a/AltCover.Tests/NCover.ConvertTo.cobertura b/AltCover.Tests/NCover.ConvertTo.cobertura index d63cde24..ffbab951 100644 --- a/AltCover.Tests/NCover.ConvertTo.cobertura +++ b/AltCover.Tests/NCover.ConvertTo.cobertura @@ -7,7 +7,7 @@ - + diff --git a/AltCover.Tests/NCover122.cobertura b/AltCover.Tests/NCover122.cobertura index 0c8b2b09..e24afa5b 100644 --- a/AltCover.Tests/NCover122.cobertura +++ b/AltCover.Tests/NCover122.cobertura @@ -7,7 +7,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/AltCover.Tests/NCoverBugFix.cobertura b/AltCover.Tests/NCoverBugFix.cobertura index 3c5f6b87..e60cfcf9 100644 --- a/AltCover.Tests/NCoverBugFix.cobertura +++ b/AltCover.Tests/NCoverBugFix.cobertura @@ -7,7 +7,7 @@ - + diff --git a/AltCover.Tests/NCoverWithPartials.cob.xml b/AltCover.Tests/NCoverWithPartials.cob.xml index 1fe7a350..9ef7e26c 100644 --- a/AltCover.Tests/NCoverWithPartials.cob.xml +++ b/AltCover.Tests/NCoverWithPartials.cob.xml @@ -8,7 +8,7 @@ - + @@ -24,7 +24,7 @@ - + @@ -48,7 +48,7 @@ - + @@ -76,7 +76,7 @@ - + @@ -92,7 +92,7 @@ - + diff --git a/AltCover.Tests/OpenCover.ConvertTo.cobertura b/AltCover.Tests/OpenCover.ConvertTo.cobertura index 17160f2e..50ec6b23 100644 --- a/AltCover.Tests/OpenCover.ConvertTo.cobertura +++ b/AltCover.Tests/OpenCover.ConvertTo.cobertura @@ -7,7 +7,7 @@ - + diff --git a/AltCover.Tests/OpenCoverWithPartials.cob.xml b/AltCover.Tests/OpenCoverWithPartials.cob.xml index 0edccb13..0febe683 100644 --- a/AltCover.Tests/OpenCoverWithPartials.cob.xml +++ b/AltCover.Tests/OpenCoverWithPartials.cob.xml @@ -8,7 +8,7 @@ - + @@ -32,7 +32,7 @@ - + @@ -64,7 +64,7 @@ - + @@ -92,7 +92,7 @@ - + @@ -116,7 +116,7 @@ - + diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index dbaf961c..15063c87 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -6231,21 +6231,26 @@ module AltCoverRunnerTests = [] let ExtractSourcesOK () = + let sep = + String([| Path.DirectorySeparatorChar |]) + let cases = [ ([ "a" ], "a") - ([ "a/b/"; "a/b/c" ], "a/b") - ([ "a/b/x/y"; "a/c/d" ], "a") - ([ "c:\\b\\x\\y"; "c:\\b\\c\\d" ], "c:\\b") ] + ([ "a/b/"; "a/b/c" ], "a/b" + sep) + ([ "a/b/x/y"; "a/c/d" ], "a" + sep) + ([ "c:\\b\\x\\y"; "c:\\b\\c\\d" ], "c:\\b" + sep) ] |> List.map (fun (inputs, expect) -> (inputs |> Seq.map (fun x -> (x, Cobertura.I.splitPath x))), expect) - cases - |> Seq.iter (fun (case, expect) -> - test <@ Cobertura.I.extractSource case = expect.Replace('\\', '/') + "/" @>) + Assert.Multiple(fun () -> + cases + |> Seq.iter (fun (case, expect) -> + test + <@ Cobertura.I.extractSource case = expect - () + @>)) [] let DegenerateCasesShouldNotGenerateCobertura () = diff --git a/AltCover.Tests/Sample1WithNCover.cob.xml b/AltCover.Tests/Sample1WithNCover.cob.xml index e22a5bac..98b989b3 100644 --- a/AltCover.Tests/Sample1WithNCover.cob.xml +++ b/AltCover.Tests/Sample1WithNCover.cob.xml @@ -7,7 +7,7 @@ - + diff --git a/AltCover.Tests/Sample4FullTracking.cobertura b/AltCover.Tests/Sample4FullTracking.cobertura index 892ed0ed..ff63beaa 100644 --- a/AltCover.Tests/Sample4FullTracking.cobertura +++ b/AltCover.Tests/Sample4FullTracking.cobertura @@ -7,7 +7,7 @@ - + @@ -51,7 +51,7 @@ - + @@ -65,7 +65,7 @@ - + @@ -101,7 +101,7 @@ - + @@ -129,7 +129,7 @@ - + @@ -141,7 +141,7 @@ - + diff --git a/AltCover.Tests/Sample5.native.cobertura b/AltCover.Tests/Sample5.native.cobertura index 69fde325..6c4382e6 100644 --- a/AltCover.Tests/Sample5.native.cobertura +++ b/AltCover.Tests/Sample5.native.cobertura @@ -7,7 +7,7 @@ - + @@ -45,7 +45,7 @@ - + @@ -89,7 +89,7 @@ - + @@ -203,7 +203,7 @@ - + diff --git a/AltCover.Tests/Sample5.ncover.cobertura b/AltCover.Tests/Sample5.ncover.cobertura index 86e32d1a..a3eb3922 100644 --- a/AltCover.Tests/Sample5.ncover.cobertura +++ b/AltCover.Tests/Sample5.ncover.cobertura @@ -7,7 +7,7 @@ - + @@ -45,7 +45,7 @@ - + @@ -61,7 +61,7 @@ - + @@ -79,7 +79,7 @@ - + @@ -107,7 +107,7 @@ - + @@ -127,7 +127,7 @@ - + @@ -205,7 +205,7 @@ - + @@ -221,7 +221,7 @@ - + @@ -239,7 +239,7 @@ - + @@ -269,7 +269,7 @@ - + @@ -289,7 +289,7 @@ - + @@ -341,7 +341,7 @@ - + @@ -355,7 +355,7 @@ - + diff --git a/AltCover.Tests/issue122.cobertura b/AltCover.Tests/issue122.cobertura index 820bc025..4e57690e 100644 --- a/AltCover.Tests/issue122.cobertura +++ b/AltCover.Tests/issue122.cobertura @@ -7,7 +7,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/AltCover.sln b/AltCover.sln index 4e0d0485..84010707 100644 --- a/AltCover.sln +++ b/AltCover.sln @@ -59,6 +59,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Items", "Build Items" .github\workflows\main.yml = .github\workflows\main.yml Build\merge-coverage.ps1 = Build\merge-coverage.ps1 Build\msbuildtest.proj = Build\msbuildtest.proj + AltCover.Tests\NCover.ConvertTo.cobertura = AltCover.Tests\NCover.ConvertTo.cobertura + AltCover.Tests\OpenCover.ConvertTo.cobertura = AltCover.Tests\OpenCover.ConvertTo.cobertura OutputBuildProps.props = OutputBuildProps.props OutputBuildTargets.props = OutputBuildTargets.props Build\pester.ps1 = Build\pester.ps1 From c645cf1ff0ce263205e7b7903f002d6092547645 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 15 Jun 2024 14:39:56 +0100 Subject: [PATCH 15/91] Fix linux case --- AltCover.Engine/Cobertura.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AltCover.Engine/Cobertura.fs b/AltCover.Engine/Cobertura.fs index 2b08fcdd..fc996e3a 100644 --- a/AltCover.Engine/Cobertura.fs +++ b/AltCover.Engine/Cobertura.fs @@ -55,7 +55,7 @@ module internal Cobertura = if String.IsNullOrWhiteSpace path then [ String.Empty ] else - facets path [] + facets (path.Replace('\\', '/')) [] [ Date: Thu, 27 Jun 2024 12:13:29 +0100 Subject: [PATCH 16/91] Update these refs --- AltCover.Recorder.sln | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/AltCover.Recorder.sln b/AltCover.Recorder.sln index 5086d2d6..7d9ffdb8 100644 --- a/AltCover.Recorder.sln +++ b/AltCover.Recorder.sln @@ -20,7 +20,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Items", "Build Items" nupkg\build\netstandard2.0\AltCover.props = nupkg\build\netstandard2.0\AltCover.props nupkg\build\netstandard2.0\AltCover.targets = nupkg\build\netstandard2.0\AltCover.targets Build\Apply-Xslt.ps1 = Build\Apply-Xslt.ps1 - Build\build.fsx = Build\build.fsx Build\common-rules.xml = Build\common-rules.xml Directory.Build.props = Directory.Build.props Directory.Build.targets = Directory.Build.targets @@ -38,8 +37,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Items", "Build Items" Build\Recorder.snk = Build\Recorder.snk ReleaseNotes.md = ReleaseNotes.md Build\SelfTest.snk = Build\SelfTest.snk - Build\setup.fsx = Build\setup.fsx - Build\targets.fsx = Build\targets.fsx + Build\setup.fs = Build\setup.fs + Build\targets.fs = Build\targets.fs EndProjectSection EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Sample25", "Samples\Sample25\Sample25.fsproj", "{54E57C76-339C-496E-B6EF-832534C7D545}" From deef884004ee67ac6648188d056dd313a7f4d438 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 27 Jun 2024 18:48:52 +0100 Subject: [PATCH 17/91] More updates --- AltCover.Recorder.sln | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AltCover.Recorder.sln b/AltCover.Recorder.sln index 7d9ffdb8..76a67589 100644 --- a/AltCover.Recorder.sln +++ b/AltCover.Recorder.sln @@ -17,8 +17,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Items", "Build Items" Build\actions.fsx = Build\actions.fsx Build\AddStrongName.fsx = Build\AddStrongName.fsx Build\AltCover.nuspec = Build\AltCover.nuspec - nupkg\build\netstandard2.0\AltCover.props = nupkg\build\netstandard2.0\AltCover.props - nupkg\build\netstandard2.0\AltCover.targets = nupkg\build\netstandard2.0\AltCover.targets + nupkg\build\AltCover.props = nupkg\build\AltCover.props + nupkg\build\AltCover.targets = nupkg\build\AltCover.targets Build\Apply-Xslt.ps1 = Build\Apply-Xslt.ps1 Build\common-rules.xml = Build\common-rules.xml Directory.Build.props = Directory.Build.props From 61de9805380494e34232fabbceca54db9d3bae74 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 28 Jun 2024 10:45:56 +0100 Subject: [PATCH 18/91] C# replacement - the easy step --- AltCover.Recorder.sln | 11 ++++---- Samples/Sample25/Library.fs | 43 -------------------------------- Samples/Sample25/Sample25.csproj | 18 +++++++++++++ Samples/Sample25/Sample25.fsproj | 32 ------------------------ Samples/Sample25/Say.cs | 11 ++++++++ 5 files changed, 35 insertions(+), 80 deletions(-) delete mode 100644 Samples/Sample25/Library.fs create mode 100644 Samples/Sample25/Sample25.csproj delete mode 100644 Samples/Sample25/Sample25.fsproj create mode 100644 Samples/Sample25/Say.cs diff --git a/AltCover.Recorder.sln b/AltCover.Recorder.sln index 76a67589..29490ab6 100644 --- a/AltCover.Recorder.sln +++ b/AltCover.Recorder.sln @@ -41,10 +41,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Items", "Build Items" Build\targets.fs = Build\targets.fs EndProjectSection EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Sample25", "Samples\Sample25\Sample25.fsproj", "{54E57C76-339C-496E-B6EF-832534C7D545}" -EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.Async", "AltCover.Async\AltCover.Async.fsproj", "{9E8E72B3-FA30-4B09-8577-B9A1BB4F3126}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample25", "D:\Github\altcover\Samples\Sample25\Sample25.csproj", "{16FCCC18-F3EE-4783-B548-50B011D03B5F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -61,13 +61,14 @@ Global {25BF9131-91CD-41CA-87F7-041E40426B5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {25BF9131-91CD-41CA-87F7-041E40426B5C}.Debug|Any CPU.Build.0 = Debug|Any CPU {25BF9131-91CD-41CA-87F7-041E40426B5C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {54E57C76-339C-496E-B6EF-832534C7D545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {54E57C76-339C-496E-B6EF-832534C7D545}.Debug|Any CPU.Build.0 = Debug|Any CPU - {54E57C76-339C-496E-B6EF-832534C7D545}.Release|Any CPU.ActiveCfg = Release|Any CPU {9E8E72B3-FA30-4B09-8577-B9A1BB4F3126}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9E8E72B3-FA30-4B09-8577-B9A1BB4F3126}.Debug|Any CPU.Build.0 = Debug|Any CPU {9E8E72B3-FA30-4B09-8577-B9A1BB4F3126}.Release|Any CPU.ActiveCfg = Release|Any CPU {9E8E72B3-FA30-4B09-8577-B9A1BB4F3126}.Release|Any CPU.Build.0 = Release|Any CPU + {16FCCC18-F3EE-4783-B548-50B011D03B5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {16FCCC18-F3EE-4783-B548-50B011D03B5F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {16FCCC18-F3EE-4783-B548-50B011D03B5F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {16FCCC18-F3EE-4783-B548-50B011D03B5F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Samples/Sample25/Library.fs b/Samples/Sample25/Library.fs deleted file mode 100644 index da873430..00000000 --- a/Samples/Sample25/Library.fs +++ /dev/null @@ -1,43 +0,0 @@ -namespace Sample25 - -module Say = - let hello name = printfn "Hello %s" name - -#if IDEMPOTENT_INSTRUMENT -[ + + Sample25 + False + net20 + + + 11.0 + True + + + + + + + + + \ No newline at end of file diff --git a/Samples/Sample25/Sample25.fsproj b/Samples/Sample25/Sample25.fsproj deleted file mode 100644 index 70a39c50..00000000 --- a/Samples/Sample25/Sample25.fsproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - net20 - Sample25 - Sample25 - --keyfile:$(InfrastructureKey) - - - - TRACE - - - - TRACE;DEBUG;CODE_ANALYSIS - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Samples/Sample25/Say.cs b/Samples/Sample25/Say.cs new file mode 100644 index 00000000..c112d60f --- /dev/null +++ b/Samples/Sample25/Say.cs @@ -0,0 +1,11 @@ +using System; + +namespace Sample25; + +public static class Say +{ + public static void Hello(string name) + { + Console.WriteLine("hello"); + } +} \ No newline at end of file From 8f1b244563ed81be294a5790301bc1f271bd35be Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 28 Jun 2024 12:05:03 +0100 Subject: [PATCH 19/91] This seems to work, but there's a system injected attribute that freaks Gendarme --- AltCover.Async/AltCover.Async.csproj | 29 ++++++++++++++ AltCover.Async/AltCover.Async.fsproj | 31 -------------- AltCover.Async/Instance.cs | 44 ++++++++++++++++++++ AltCover.Async/Library.fs | 60 ---------------------------- AltCover.Recorder.sln | 12 +++--- 5 files changed, 79 insertions(+), 97 deletions(-) create mode 100644 AltCover.Async/AltCover.Async.csproj delete mode 100644 AltCover.Async/AltCover.Async.fsproj create mode 100644 AltCover.Async/Instance.cs delete mode 100644 AltCover.Async/Library.fs diff --git a/AltCover.Async/AltCover.Async.csproj b/AltCover.Async/AltCover.Async.csproj new file mode 100644 index 00000000..5dcd7b23 --- /dev/null +++ b/AltCover.Async/AltCover.Async.csproj @@ -0,0 +1,29 @@ + + + AltCover.Async + False + net46 + false + false + false + + + 11.0 + True + + + + + + TRACE;DEBUG;CODE_ANALYSIS + CS1591 + + + TRACE + CS1591 + + + + + + \ No newline at end of file diff --git a/AltCover.Async/AltCover.Async.fsproj b/AltCover.Async/AltCover.Async.fsproj deleted file mode 100644 index 0d8e7e6e..00000000 --- a/AltCover.Async/AltCover.Async.fsproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - net46 - AltCover.Async - AltCover.Recorder - false - false - false - --keyfile:$(InfrastructureKey) - - - - TRACE - - - - - TRACE;DEBUG;CODE_ANALYSIS - - - - - - - - - - - - \ No newline at end of file diff --git a/AltCover.Async/Instance.cs b/AltCover.Async/Instance.cs new file mode 100644 index 00000000..a8ad72a5 --- /dev/null +++ b/AltCover.Async/Instance.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.Versioning; +using System.Threading; + +namespace AltCover.Recorder; + +internal static class _0024Library +{ + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + internal static readonly TargetFrameworkAttribute attr_004011; + + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + internal static readonly AsyncLocal> value_004014; + + static _0024Library() + { + TargetFrameworkAttribute attr = (attr_004011 = new TargetFrameworkAttribute(".NETFramework,Version=v4.6")); + AsyncLocal> asyncLocal = (value_004014 = new AsyncLocal>()); + } +} + +public static class Instance +{ + public static class I + { + internal static class CallTrack + { + internal static TargetFrameworkAttribute attr => _0024Library.attr_004011; + + internal static AsyncLocal> value => _0024Library.value_004014; + + internal static Stack instance() + { + if (value.Value == null) + { + value.Value = new Stack(); + } + return value.Value; + } + } + } +} \ No newline at end of file diff --git a/AltCover.Async/Library.fs b/AltCover.Async/Library.fs deleted file mode 100644 index 239e9991..00000000 --- a/AltCover.Async/Library.fs +++ /dev/null @@ -1,60 +0,0 @@ -namespace AltCover.Recorder - -open System.Collections.Generic -open System.Diagnostics.CodeAnalysis -open System.Threading - -module Instance = - module I = - module private CallTrack = - - let attr = - System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6") - - let value = AsyncLocal>() - - let instance () = - match value.Value with - | null -> value.Value <- Stack() - | _ -> () - - value.Value - -[] -[] -[] -[] -[] -[] -[] -[] -() \ No newline at end of file diff --git a/AltCover.Recorder.sln b/AltCover.Recorder.sln index 29490ab6..6116022f 100644 --- a/AltCover.Recorder.sln +++ b/AltCover.Recorder.sln @@ -41,10 +41,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Items", "Build Items" Build\targets.fs = Build\targets.fs EndProjectSection EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.Async", "AltCover.Async\AltCover.Async.fsproj", "{9E8E72B3-FA30-4B09-8577-B9A1BB4F3126}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample25", "D:\Github\altcover\Samples\Sample25\Sample25.csproj", "{16FCCC18-F3EE-4783-B548-50B011D03B5F}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AltCover.Async", "D:\Github\altcover\AltCover.Async\AltCover.Async.csproj", "{882812A5-4DA4-4B6D-8054-EC14979EE4A3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -61,14 +61,14 @@ Global {25BF9131-91CD-41CA-87F7-041E40426B5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {25BF9131-91CD-41CA-87F7-041E40426B5C}.Debug|Any CPU.Build.0 = Debug|Any CPU {25BF9131-91CD-41CA-87F7-041E40426B5C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9E8E72B3-FA30-4B09-8577-B9A1BB4F3126}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9E8E72B3-FA30-4B09-8577-B9A1BB4F3126}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9E8E72B3-FA30-4B09-8577-B9A1BB4F3126}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9E8E72B3-FA30-4B09-8577-B9A1BB4F3126}.Release|Any CPU.Build.0 = Release|Any CPU {16FCCC18-F3EE-4783-B548-50B011D03B5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {16FCCC18-F3EE-4783-B548-50B011D03B5F}.Debug|Any CPU.Build.0 = Debug|Any CPU {16FCCC18-F3EE-4783-B548-50B011D03B5F}.Release|Any CPU.ActiveCfg = Release|Any CPU {16FCCC18-F3EE-4783-B548-50B011D03B5F}.Release|Any CPU.Build.0 = Release|Any CPU + {882812A5-4DA4-4B6D-8054-EC14979EE4A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {882812A5-4DA4-4B6D-8054-EC14979EE4A3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {882812A5-4DA4-4B6D-8054-EC14979EE4A3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {882812A5-4DA4-4B6D-8054-EC14979EE4A3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 438b43a34f0800971d86b7f7017b7b52075f5e83 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 28 Jun 2024 15:31:28 +0100 Subject: [PATCH 20/91] Working but messy --- .config/dotnet-tools.json | 2 +- AltCover.Async/Instance.cs | 57 +++++++++++++++++-- .../AltCover.ValidateGendarmeEmulation.fsproj | 2 +- Directory.Packages.props | 2 +- 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 283c5ce9..68071073 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -17,7 +17,7 @@ "rollForward": false }, "altcode.gendarme-tool": { - "version": "2023.12.27.19054", + "version": "2024.6.28.12460", "commands": [ "gendarme" ], diff --git a/AltCover.Async/Instance.cs b/AltCover.Async/Instance.cs index a8ad72a5..f7cb476d 100644 --- a/AltCover.Async/Instance.cs +++ b/AltCover.Async/Instance.cs @@ -1,12 +1,57 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; +using System; +using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Threading; +[assembly: CLSCompliant(true)] +[assembly: ComVisible(false)] +[assembly: SuppressMessage("Gendarme.Rules.Performance", + "AvoidUncalledPrivateCodeRule", + Scope = "member", // MethodDefinition + Target = "AltCover.Recorder.Instance/I/CallTrack::get_attr()", + Justification = "stub assembly")] +[assembly: SuppressMessage("Gendarme.Rules.Performance", + "AvoidUncalledPrivateCodeRule", + Scope = "member", // MethodDefinition + Target = "AltCover.Recorder.Instance/I/CallTrack::instance()", + Justification = "stub assembly")] +[assembly: SuppressMessage("Gendarme.Rules.Naming", + "UseCorrectCasingRule", + Scope = "member", // MethodDefinition + Target = "AltCover.Recorder.Instance/I/CallTrack::get_attr()", + Justification = "stub assembly")] +[assembly: SuppressMessage("Gendarme.Rules.Naming", + "UseCorrectCasingRule", + Scope = "member", // MethodDefinition + Target = "AltCover.Recorder.Instance/I/CallTrack::get_value()", + Justification = "stub assembly")] +[assembly: SuppressMessage("Gendarme.Rules.Naming", + "UseCorrectCasingRule", + Scope = "member", // MethodDefinition + Target = "AltCover.Recorder.Instance/I/CallTrack::instance()", + Justification = "stub assembly")] +[assembly: SuppressMessage("Gendarme.Rules.Performance", + "AvoidRepetitiveCallsToPropertiesRule", + Scope = "member", // MethodDefinition + Target = "AltCover.Recorder.Instance/I/CallTrack::instance()", + Justification = "stub assembly")] +[assembly: SuppressMessage("Microsoft.Performance", + "CA1811:AvoidUncalledPrivateCode", + Scope = "member", + Target = "AltCover.Recorder.Instance+I+CallTrack.#instance()", + Justification = "stub assembly")] +[assembly: SuppressMessage("Microsoft.Performance", + "CA1810:InitializeReferenceTypeStaticFieldsInline", + Scope = "member", + Target = "AltCover.Recorder.LibraryHelper.#.cctor()", + Justification = "stub assembly")] + namespace AltCover.Recorder; -internal static class _0024Library +internal static class LibraryHelper { [DebuggerBrowsable(DebuggerBrowsableState.Never)] internal static readonly TargetFrameworkAttribute attr_004011; @@ -14,7 +59,7 @@ internal static class _0024Library [DebuggerBrowsable(DebuggerBrowsableState.Never)] internal static readonly AsyncLocal> value_004014; - static _0024Library() + static LibraryHelper() { TargetFrameworkAttribute attr = (attr_004011 = new TargetFrameworkAttribute(".NETFramework,Version=v4.6")); AsyncLocal> asyncLocal = (value_004014 = new AsyncLocal>()); @@ -27,9 +72,11 @@ public static class I { internal static class CallTrack { - internal static TargetFrameworkAttribute attr => _0024Library.attr_004011; + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "stub assembly")] + internal static TargetFrameworkAttribute attr => LibraryHelper.attr_004011; - internal static AsyncLocal> value => _0024Library.value_004014; + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "stub assembly")] + internal static AsyncLocal> value => LibraryHelper.value_004014; internal static Stack instance() { diff --git a/AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj b/AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj index 3e7f0419..b3ee7914 100644 --- a/AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj +++ b/AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj @@ -3,7 +3,7 @@ net8.0;net472 false - 2023.12.27.19054 + 2024.6.28.12460 ..\packages\altcode.gendarme\$(GendarmeVersion)\tools\ false AltCover.ValidateGendarmeEmulation diff --git a/Directory.Packages.props b/Directory.Packages.props index ad6edeef..e84700f2 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,7 +3,7 @@ - + From d211ed6fbe8dbe2e2279f7f2e7175664d7359da9 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 28 Jun 2024 18:27:45 +0100 Subject: [PATCH 21/91] Debug leakage (general use) --- AltCover.Tests/Runner.Tests.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index 15063c87..f256d725 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -5695,7 +5695,7 @@ module AltCoverRunnerTests = Assert.That(r, Is.EqualTo(0, 0, String.Empty)) let result = File.ReadAllText unique - printfn "%s" result + //printfn "%s" result let resource2 = Assembly @@ -5900,7 +5900,7 @@ module AltCoverRunnerTests = Assert.That(r, Is.EqualTo(0, 0, String.Empty)) let result = File.ReadAllText unique - printfn "%s" result + //printfn "%s" result let resource2 = Assembly From a54496d0c12fc64f39b4ee1bafda32a1d4471f6b Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Tue, 2 Jul 2024 12:16:58 +0100 Subject: [PATCH 22/91] First stake in the ground --- AltCover.Engine/AltCover.Engine.fsproj | 4 +- AltCover.Recorder.Tests/Adapter.cs | 0 ....fsproj => AltCover.Recorder.Tests.csproj} | 25 ++----- AltCover.Recorder.Tests/AssemblyInfo.cs | 5 ++ AltCover.Recorder.Tests/Program.cs | 19 ++++++ AltCover.Recorder.Tests/Recorder.Tests.cs | 38 +++++++++++ AltCover.Recorder.Tests/Tracer.Tests.cs | 0 ...corder.fsproj => AltCover.Recorder.csproj} | 33 +++++---- AltCover.Recorder/AssemblyInfo.cs | 6 ++ AltCover.Recorder/Base.cs | 0 AltCover.Recorder/InstrumentationAttribute.cs | 27 ++++++++ AltCover.Recorder/Recorder.cs | 21 ++++++ AltCover.Recorder/Tracer.cs | 0 ...fsproj => AltCover.Recorder2.Tests.csproj} | 20 +++--- .../AltCover.RecorderModern.Tests.fsproj | 55 --------------- .../AltCover.RecorderModern.fsproj | 56 ---------------- AltCover.Tests/AltCover.Tests.fsproj | 2 +- AltCover.sln | 67 +++++++++++++++---- Build/targets.fs | 16 ----- 19 files changed, 209 insertions(+), 185 deletions(-) create mode 100644 AltCover.Recorder.Tests/Adapter.cs rename AltCover.Recorder.Tests/{AltCover.Recorder.Tests.fsproj => AltCover.Recorder.Tests.csproj} (71%) create mode 100644 AltCover.Recorder.Tests/AssemblyInfo.cs create mode 100644 AltCover.Recorder.Tests/Program.cs create mode 100644 AltCover.Recorder.Tests/Recorder.Tests.cs create mode 100644 AltCover.Recorder.Tests/Tracer.Tests.cs rename AltCover.Recorder/{AltCover.Recorder.fsproj => AltCover.Recorder.csproj} (59%) create mode 100644 AltCover.Recorder/AssemblyInfo.cs create mode 100644 AltCover.Recorder/Base.cs create mode 100644 AltCover.Recorder/InstrumentationAttribute.cs create mode 100644 AltCover.Recorder/Recorder.cs create mode 100644 AltCover.Recorder/Tracer.cs rename AltCover.Recorder2.Tests/{AltCover.Recorder2.Tests.fsproj => AltCover.Recorder2.Tests.csproj} (73%) delete mode 100644 AltCover.RecorderModern.Tests/AltCover.RecorderModern.Tests.fsproj delete mode 100644 AltCover.RecorderModern/AltCover.RecorderModern.fsproj diff --git a/AltCover.Engine/AltCover.Engine.fsproj b/AltCover.Engine/AltCover.Engine.fsproj index cd9da938..ef15a522 100644 --- a/AltCover.Engine/AltCover.Engine.fsproj +++ b/AltCover.Engine/AltCover.Engine.fsproj @@ -67,10 +67,10 @@ Recorder.snk - + AltCover.Recorder.net20.dll - + AltCover.Async.net46.dll diff --git a/AltCover.Recorder.Tests/Adapter.cs b/AltCover.Recorder.Tests/Adapter.cs new file mode 100644 index 00000000..e69de29b diff --git a/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj b/AltCover.Recorder.Tests/AltCover.Recorder.Tests.csproj similarity index 71% rename from AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj rename to AltCover.Recorder.Tests/AltCover.Recorder.Tests.csproj index 2d1aac53..a3440c96 100644 --- a/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj +++ b/AltCover.Recorder.Tests/AltCover.Recorder.Tests.csproj @@ -6,7 +6,7 @@ AltCover.Recorder.Tests false - NU1702 + NU1702;CS1591 NU1702 --keyfile:$(InfrastructureKey) @@ -19,14 +19,10 @@ - - AssemblyVersion.fs + + AssemblyVersion.cs - - - - - + @@ -59,19 +55,10 @@ - - - - - - - contentfiles - - - + - + \ No newline at end of file diff --git a/AltCover.Recorder.Tests/AssemblyInfo.cs b/AltCover.Recorder.Tests/AssemblyInfo.cs new file mode 100644 index 00000000..b4e1d9f9 --- /dev/null +++ b/AltCover.Recorder.Tests/AssemblyInfo.cs @@ -0,0 +1,5 @@ +using System; +using System.Runtime.InteropServices; + +[assembly: CLSCompliant(true)] +[assembly: ComVisible(false)] \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Program.cs b/AltCover.Recorder.Tests/Program.cs new file mode 100644 index 00000000..d4c4501b --- /dev/null +++ b/AltCover.Recorder.Tests/Program.cs @@ -0,0 +1,19 @@ +#if !NET472 +#if NET20 +namespace Tests.Recorder.Clr2 +#else + +namespace Tests.Recorder.Core +#endif +#else +namespace Tests.Recorder.Clr4 +#endif +{ + internal static class UnitTestStub + { + private static int Main() + { + return 0; + } + } +} \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Recorder.Tests.cs b/AltCover.Recorder.Tests/Recorder.Tests.cs new file mode 100644 index 00000000..19ed2eea --- /dev/null +++ b/AltCover.Recorder.Tests/Recorder.Tests.cs @@ -0,0 +1,38 @@ +#if !NET472 +#if NET20 +namespace Tests.Recorder.Clr2 +#else + +namespace Tests.Recorder.Core +#endif +#else +namespace Tests.Recorder.Clr4 +#endif +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.IO.Compression; + using System.Reflection; + using System.Runtime.CompilerServices; + using System.Threading; + using System.Xml; + + using AltCover.Recorder; + using NUnit.Framework; + + public static class AltCoverTests + { + [Test] + public static void ShouldCoverTrivalClass() + { + var mark = new InstrumentationAttribute(); // Constructor has all the instrumented code + Assert.That(mark.Assembly, Is.EqualTo("AltCover.Recorder.g!")); + Assert.That(mark.Configuration, Is.EqualTo("Uninstrumented!!")); + mark.Assembly = String.Empty; + mark.Configuration = String.Empty; + Assert.True(String.IsNullOrEmpty(mark.Assembly)); + Assert.True(String.IsNullOrEmpty(mark.Configuration)); + } + } +} \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Tracer.Tests.cs b/AltCover.Recorder.Tests/Tracer.Tests.cs new file mode 100644 index 00000000..e69de29b diff --git a/AltCover.Recorder/AltCover.Recorder.fsproj b/AltCover.Recorder/AltCover.Recorder.csproj similarity index 59% rename from AltCover.Recorder/AltCover.Recorder.fsproj rename to AltCover.Recorder/AltCover.Recorder.csproj index 6addc561..5f52de81 100644 --- a/AltCover.Recorder/AltCover.Recorder.fsproj +++ b/AltCover.Recorder/AltCover.Recorder.csproj @@ -12,7 +12,7 @@ TRACE;$(DefineConstants) - --keyfile:$(InfrastructureKey) --standalone --staticlink:ICSharpCode.SharpZipLib + --keyfile:$(InfrastructureKey) --staticlink:ICSharpCode.SharpZipLib @@ -20,16 +20,27 @@ --keyfile:$(InfrastructureKey) + + CS1591 + + + + CS1591 + + + + CS1591 + + + + CS1591 + + - - - - - - - - - + + + + AltCover.Recorder.Strings.resources @@ -38,12 +49,10 @@ - all runtime; build; native; contentfiles; analyzers - diff --git a/AltCover.Recorder/AssemblyInfo.cs b/AltCover.Recorder/AssemblyInfo.cs new file mode 100644 index 00000000..d412f9a9 --- /dev/null +++ b/AltCover.Recorder/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using System; +using System.Runtime.InteropServices; + +[assembly: CLSCompliant(true)] +[assembly: ComVisible(false)] +[assembly: System.Resources.NeutralResourcesLanguageAttribute("en-GB")] \ No newline at end of file diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs new file mode 100644 index 00000000..e69de29b diff --git a/AltCover.Recorder/InstrumentationAttribute.cs b/AltCover.Recorder/InstrumentationAttribute.cs new file mode 100644 index 00000000..e3331054 --- /dev/null +++ b/AltCover.Recorder/InstrumentationAttribute.cs @@ -0,0 +1,27 @@ +namespace AltCover.Recorder +{ + using System; + + /// + /// An attribute to label an instrumented assembly by provenance + /// + [AttributeUsage(AttributeTargets.Assembly)] + public sealed class InstrumentationAttribute : Attribute + { + /// + /// SHA-256 hash of the original assembly + /// + public string Assembly { get; set; } + + /// + /// SHA-256 hash of instrumentation parameters + /// + public string Configuration { get; set; } + + public InstrumentationAttribute() + { + Assembly = "AltCover.Recorder.g!"; + Configuration = "Uninstrumented!!"; + } + } +} \ No newline at end of file diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs new file mode 100644 index 00000000..daebbc24 --- /dev/null +++ b/AltCover.Recorder/Recorder.cs @@ -0,0 +1,21 @@ +namespace AltCover.Recorder +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.IO; + using System.Reflection; + + using System.Resources; + using System.Runtime.CompilerServices; + +#if !NET20 +using System.Threading; +#endif + + //using AltCover.Shared; + + public static class Instance + { } +} \ No newline at end of file diff --git a/AltCover.Recorder/Tracer.cs b/AltCover.Recorder/Tracer.cs new file mode 100644 index 00000000..e69de29b diff --git a/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj b/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.csproj similarity index 73% rename from AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj rename to AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.csproj index f7444883..3bca1800 100644 --- a/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj +++ b/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.csproj @@ -5,7 +5,7 @@ false AltCover.Recorder2.Tests false - NU1702 + NU1702;CS1591 NU1702 --keyfile:$(InfrastructureKey) @@ -20,14 +20,14 @@ - - AssemblyVersion.fs + + AssemblyVersion.cs - - - - - + + + + + @@ -42,10 +42,6 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - contentfiles - - diff --git a/AltCover.RecorderModern.Tests/AltCover.RecorderModern.Tests.fsproj b/AltCover.RecorderModern.Tests/AltCover.RecorderModern.Tests.fsproj deleted file mode 100644 index 4e360438..00000000 --- a/AltCover.RecorderModern.Tests/AltCover.RecorderModern.Tests.fsproj +++ /dev/null @@ -1,55 +0,0 @@ - - - - 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 deleted file mode 100644 index a5819e90..00000000 --- a/AltCover.RecorderModern/AltCover.RecorderModern.fsproj +++ /dev/null @@ -1,56 +0,0 @@ - - - - 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/AltCover.Tests.fsproj b/AltCover.Tests/AltCover.Tests.fsproj index b58c4c44..8eaac112 100644 --- a/AltCover.Tests/AltCover.Tests.fsproj +++ b/AltCover.Tests/AltCover.Tests.fsproj @@ -105,7 +105,7 @@ - + AltCover.Recorder.net20.dll diff --git a/AltCover.sln b/AltCover.sln index 84010707..b832f0b2 100644 --- a/AltCover.sln +++ b/AltCover.sln @@ -3,6 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 15.0.26124.0 Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.Engine", "AltCover.Engine\AltCover.Engine.fsproj", "{26C01B27-9A3E-4460-BB43-5383C8E818FB}" + ProjectSection(ProjectDependencies) = postProject + {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC} = {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC} + EndProjectSection EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.PowerShell", "AltCover.PowerShell\AltCover.PowerShell.fsproj", "{208B8925-5626-4E5D-A00B-6A993D850524}" EndProject @@ -141,9 +144,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample0", "Samples\Sample0\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample32", "Samples\Sample32\Sample32.csproj", "{349B2983-FB15-4D72-B7F6-04FD36C81B90}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.RecorderModern", "AltCover.RecorderModern\AltCover.RecorderModern.fsproj", "{219B0218-3289-44DD-9C22-6C14A3D7B5A7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AltCover.Async", "AltCover.Async\AltCover.Async.csproj", "{A81EDA11-9C1A-4BFA-9CC6-511C5447B167}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample25", "Samples\Sample25\Sample25.csproj", "{3349AD8B-577C-471D-93E7-E99D88CB883D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AltCover.Recorder", "AltCover.Recorder\AltCover.Recorder.csproj", "{5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.RecorderModern.Tests", "AltCover.RecorderModern.Tests\AltCover.RecorderModern.Tests.fsproj", "{4B905582-3295-463B-A645-7FA6D0844035}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AltCover.Recorder.Tests", "AltCover.Recorder.Tests\AltCover.Recorder.Tests.csproj", "{6DCDCA5E-3174-4C0B-996A-F7E4E455F889}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AltCover.Recorder2.Tests", "AltCover.Recorder2.Tests\AltCover.Recorder2.Tests.csproj", "{2079F388-81AE-4A76-9428-3C8D7F86825B}" + ProjectSection(ProjectDependencies) = postProject + {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC} = {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -351,16 +363,46 @@ Global {349B2983-FB15-4D72-B7F6-04FD36C81B90}.Release|Any CPU.Build.0 = Release|Any CPU {349B2983-FB15-4D72-B7F6-04FD36C81B90}.Release|x86.ActiveCfg = Release|Any CPU {349B2983-FB15-4D72-B7F6-04FD36C81B90}.Release|x86.Build.0 = 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 + {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Debug|x86.ActiveCfg = Debug|Any CPU + {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Debug|x86.Build.0 = Debug|Any CPU + {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Release|Any CPU.Build.0 = Release|Any CPU + {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Release|x86.ActiveCfg = Release|Any CPU + {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Release|x86.Build.0 = Release|Any CPU + {3349AD8B-577C-471D-93E7-E99D88CB883D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3349AD8B-577C-471D-93E7-E99D88CB883D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3349AD8B-577C-471D-93E7-E99D88CB883D}.Debug|x86.ActiveCfg = Debug|Any CPU + {3349AD8B-577C-471D-93E7-E99D88CB883D}.Debug|x86.Build.0 = Debug|Any CPU + {3349AD8B-577C-471D-93E7-E99D88CB883D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3349AD8B-577C-471D-93E7-E99D88CB883D}.Release|Any CPU.Build.0 = Release|Any CPU + {3349AD8B-577C-471D-93E7-E99D88CB883D}.Release|x86.ActiveCfg = Release|Any CPU + {3349AD8B-577C-471D-93E7-E99D88CB883D}.Release|x86.Build.0 = Release|Any CPU + {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Debug|x86.ActiveCfg = Debug|Any CPU + {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Debug|x86.Build.0 = Debug|Any CPU + {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Release|Any CPU.Build.0 = Release|Any CPU + {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Release|x86.ActiveCfg = Release|Any CPU + {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Release|x86.Build.0 = Release|Any CPU + {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Debug|x86.ActiveCfg = Debug|Any CPU + {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Debug|x86.Build.0 = Debug|Any CPU + {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Release|Any CPU.Build.0 = Release|Any CPU + {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Release|x86.ActiveCfg = Release|Any CPU + {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Release|x86.Build.0 = Release|Any CPU + {2079F388-81AE-4A76-9428-3C8D7F86825B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2079F388-81AE-4A76-9428-3C8D7F86825B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2079F388-81AE-4A76-9428-3C8D7F86825B}.Debug|x86.ActiveCfg = Debug|Any CPU + {2079F388-81AE-4A76-9428-3C8D7F86825B}.Debug|x86.Build.0 = Debug|Any CPU + {2079F388-81AE-4A76-9428-3C8D7F86825B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2079F388-81AE-4A76-9428-3C8D7F86825B}.Release|Any CPU.Build.0 = Release|Any CPU + {2079F388-81AE-4A76-9428-3C8D7F86825B}.Release|x86.ActiveCfg = Release|Any CPU + {2079F388-81AE-4A76-9428-3C8D7F86825B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -389,6 +431,7 @@ Global {F56DE54A-ABD6-42F7-B61E-7BAFCCF2D787} = {97367D43-64EF-48E1-B6B4-D951C783E6E1} {19CE63CE-3622-409A-974D-3EA01388317E} = {2837CE07-B91F-4B8A-89B5-E7BE39A8F340} {349B2983-FB15-4D72-B7F6-04FD36C81B90} = {2837CE07-B91F-4B8A-89B5-E7BE39A8F340} + {3349AD8B-577C-471D-93E7-E99D88CB883D} = {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 82bc8692..8a5ef3f6 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -935,12 +935,6 @@ module Targets = printfn "%A" x reraise ()) - let BuildRecorder = - (fun () -> msbuildDebug MSBuildPath "./AltCover.Recorder.sln") - - let BuildReleaseRecorder = - (fun () -> msbuildRelease MSBuildPath "./AltCover.Recorder.sln") - let BuildDebug = (fun () -> Directory.ensure "./_SourceLink" @@ -954,11 +948,6 @@ module Targets = Shell.copyFile "/tmp/.AltCover_SourceLink/Sample14.SourceLink.Class3.cs") "./Samples/Sample14/Sample14/Class3.txt" - // net20 and such - [ msbuildDebug MSBuildPath - msbuildRelease MSBuildPath ] - |> List.iter (fun f -> f "./AltCover.Recorder.sln") - [ "./AltCover.sln" "./AltCover.Visualizer.sln" "./MCS.sln" @@ -8350,8 +8339,6 @@ module Targets = _Target "SetVersion" SetVersion _Target "Compilation" ignore _Target "BuildRelease" BuildRelease - _Target "BuildRecorder" BuildRecorder - _Target "BuildReleaseRecorder" BuildReleaseRecorder _Target "BuildDebug" BuildDebug _Target "BuildMonoSamples" BuildMonoSamples _Target "BuildSample31" BuildSample31 @@ -8443,9 +8430,6 @@ module Targets = "Preparation" ==> "BuildDebug" |> ignore - "BuildRecorder" ==> "JustRecorderUnitTest" - |> ignore - "BuildDebug" ==> "BuildRelease" ==> "Compilation" |> ignore From dde94a64cefc6a654bc53031c826b2d6f85a2d88 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Tue, 2 Jul 2024 12:42:12 +0100 Subject: [PATCH 23/91] One unit test at a time... --- AltCover.Recorder.Tests/Tracer.Tests.cs | 68 +++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/AltCover.Recorder.Tests/Tracer.Tests.cs b/AltCover.Recorder.Tests/Tracer.Tests.cs index e69de29b..558b75b0 100644 --- a/AltCover.Recorder.Tests/Tracer.Tests.cs +++ b/AltCover.Recorder.Tests/Tracer.Tests.cs @@ -0,0 +1,68 @@ +#if !NET472 +#if NET20 +namespace Tests.Recorder.Clr2 +#else + +namespace Tests.Recorder.Core +#endif +#else +namespace Tests.Recorder.Clr4 +#endif + +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.IO.Compression; + using System.Reflection; + using AltCover.Recorder; + using NUnit.Framework; + using NUnit.Framework.Constraints; + using static NUnit.Framework.Constraints.Tolerance; + + //[] + public static class AltCoverCoreTests + { + private static void maybeIOException(Action f) + { + try { f(); } + catch (IOException) + { } + } + + private static void maybeDeleteFile(string f) + { + if (File.Exists(f)) + { + File.Delete(f); + } + } + + private static void maybeReraise(Action f, Action g) + { + try { f(); } + catch (Exception) + { + g(); + throw; + } + } + + private static void ignore() + { } + + [Test] + public static void ExcerciseItAll() + { + var where = + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + + var unique = + Path.Combine(Path.Combine(where, Guid.NewGuid().ToString()), "nonesuch.txt"); + + maybeDeleteFile(unique); + maybeIOException(() => { maybeReraise(() => { File.Delete(unique); }, ignore); }); + maybeIOException(() => { maybeReraise(() => { throw new IOException(); }, ignore); }); + } + } +} \ No newline at end of file From 52d8143c83921188f7c66a5f08e1b6dae81f7c24 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Tue, 2 Jul 2024 13:21:58 +0100 Subject: [PATCH 24/91] Tracer Test "WillNotConnectSpontaneously" --- AltCover.Recorder.Tests/Tracer.Tests.cs | 21 +++++++ AltCover.Recorder/Tracer.cs | 83 +++++++++++++++++++++++++ Build/actions.fs | 5 +- 3 files changed, 106 insertions(+), 3 deletions(-) diff --git a/AltCover.Recorder.Tests/Tracer.Tests.cs b/AltCover.Recorder.Tests/Tracer.Tests.cs index 558b75b0..938f4473 100644 --- a/AltCover.Recorder.Tests/Tracer.Tests.cs +++ b/AltCover.Recorder.Tests/Tracer.Tests.cs @@ -12,9 +12,11 @@ namespace Tests.Recorder.Clr4 { using System; using System.Collections.Generic; + using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Reflection; + using System.Runtime.InteropServices; using AltCover.Recorder; using NUnit.Framework; using NUnit.Framework.Constraints; @@ -64,5 +66,24 @@ public static void ExcerciseItAll() maybeIOException(() => { maybeReraise(() => { File.Delete(unique); }, ignore); }); maybeIOException(() => { maybeReraise(() => { throw new IOException(); }, ignore); }); } + + public static void WillNotConnectSpontaneously() + { + var where = + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + + var unique = Path.Combine(where, Guid.NewGuid().ToString()); + + var client = Tracer.Create(unique); + Action close = (() => client.Close()); + + maybeReraise( + () => + { + client = client.OnStart(); + Assert.True(!client.IsConnected()); + close(); + }, close); + } } } \ No newline at end of file diff --git a/AltCover.Recorder/Tracer.cs b/AltCover.Recorder/Tracer.cs index e69de29b..76cf5796 100644 --- a/AltCover.Recorder/Tracer.cs +++ b/AltCover.Recorder/Tracer.cs @@ -0,0 +1,83 @@ +namespace AltCover.Recorder +{ + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Drawing; + using System.IO; + using System.IO.Compression; + using System.Runtime.Remoting.Contexts; + using System.Runtime.Serialization; + using System.Text.RegularExpressions; + + //using AltCover.Shared; + + internal enum Close + { + DomainUnload, + ProcessExit, + Pause, + Resume, + } + + internal struct Tracer + { + public string TracerName; + public bool Runner; + public bool Definitive; + public System.IO.Stream Stream; + public System.IO.BinaryWriter Formatter; + + private Tracer(string name) + { + TracerName = name; + Runner = false; + Definitive = false; + Stream = null; + Formatter = null; + } + + internal static Tracer Create(string name) + { + return new Tracer(name); + } + + internal void Close() + { + try + { + this.Stream.Flush(); + + this.Formatter.Close(); + } + catch (ObjectDisposedException) { } + catch (NullReferenceException) { } + } + + internal bool IsConnected() + { + return (this.Stream != null) && this.Runner; + } + + internal Tracer OnStart() + { + var running = this.Connect(); + running.Definitive = true; + return running; + } + + internal Tracer Connect() + { + if (File.Exists(this.TracerName)) + { + throw new NotImplementedException(); + // Seq.initInfinite (fun i -> Path.ChangeExtension(this.Tracer, sprintf ".%d.acv" i)) + //|> Seq.filter (File.Exists >> not) + //|> Seq.map this.MakeConnection + //|> Seq.head + } + else + { return this; } + } + } +} \ No newline at end of file diff --git a/Build/actions.fs b/Build/actions.fs index b62592e3..ff85ae9d 100644 --- a/Build/actions.fs +++ b/Build/actions.fs @@ -110,9 +110,6 @@ open System.Runtime.CompilerServices [] [] [] -[] -[] -[] [] #else [] @@ -128,6 +125,8 @@ using System.Runtime.CompilerServices; #if DEBUG [assembly: AssemblyConfiguration("Debug {0}")] [assembly: InternalsVisibleTo("AltCover.Monitor.Tests, PublicKey={1}")] +[assembly: InternalsVisibleTo("AltCover.Recorder.Tests, PublicKey={1}")] +[assembly: InternalsVisibleTo("AltCover.Recorder2.Tests, PublicKey={1}")] #else [assembly: AssemblyConfiguration("Release {0}")] #endif""" From bd9686add4aba44f1ca04c0398831575bddef33e Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Tue, 2 Jul 2024 14:02:08 +0100 Subject: [PATCH 25/91] Another test --- AltCover.Recorder.Tests/Tracer.Tests.cs | 23 +++++++++++++++++++++ AltCover.Recorder/Tracer.cs | 27 ++++++++++++++++++++----- AltCover.sln | 14 ------------- 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/AltCover.Recorder.Tests/Tracer.Tests.cs b/AltCover.Recorder.Tests/Tracer.Tests.cs index 938f4473..a09a4df9 100644 --- a/AltCover.Recorder.Tests/Tracer.Tests.cs +++ b/AltCover.Recorder.Tests/Tracer.Tests.cs @@ -67,6 +67,7 @@ public static void ExcerciseItAll() maybeIOException(() => { maybeReraise(() => { throw new IOException(); }, ignore); }); } + [Test] public static void WillNotConnectSpontaneously() { var where = @@ -85,5 +86,27 @@ public static void WillNotConnectSpontaneously() close(); }, close); } + + [Test] + public static void ValidTokenWillConnect() + { + var where = + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + + var unique = Path.Combine(where, Guid.NewGuid().ToString()); + + using (var stream = File.Create(unique)) + { } + + var client = Tracer.Create(unique); + + try + { + client = client.OnStart(); + Assert.True(client.IsConnected()); + } + finally + { client.Close(); } + } } } \ No newline at end of file diff --git a/AltCover.Recorder/Tracer.cs b/AltCover.Recorder/Tracer.cs index 76cf5796..696b36ae 100644 --- a/AltCover.Recorder/Tracer.cs +++ b/AltCover.Recorder/Tracer.cs @@ -66,15 +66,32 @@ internal Tracer OnStart() return running; } + private Tracer MakeConnection(string f) + { + var fs = File.OpenWrite(f); + + var s = + new DeflateStream(fs, CompressionMode.Compress); + + Stream = s; + Formatter = new BinaryWriter(s); + Runner = true; + + return this; + } + internal Tracer Connect() { if (File.Exists(this.TracerName)) { - throw new NotImplementedException(); - // Seq.initInfinite (fun i -> Path.ChangeExtension(this.Tracer, sprintf ".%d.acv" i)) - //|> Seq.filter (File.Exists >> not) - //|> Seq.map this.MakeConnection - //|> Seq.head + for (var i = 0; true; ++i) + { + var extension = i.ToString(System.Globalization.CultureInfo.InvariantCulture); + var path = Path.ChangeExtension(this.TracerName, "." + extension + ".acv"); + if (File.Exists(path)) { continue; } + MakeConnection(path); + return this; + } } else { return this; } diff --git a/AltCover.sln b/AltCover.sln index b832f0b2..c40b2bf4 100644 --- a/AltCover.sln +++ b/AltCover.sln @@ -358,51 +358,37 @@ Global {349B2983-FB15-4D72-B7F6-04FD36C81B90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {349B2983-FB15-4D72-B7F6-04FD36C81B90}.Debug|Any CPU.Build.0 = Debug|Any CPU {349B2983-FB15-4D72-B7F6-04FD36C81B90}.Debug|x86.ActiveCfg = Debug|Any CPU - {349B2983-FB15-4D72-B7F6-04FD36C81B90}.Debug|x86.Build.0 = Debug|Any CPU {349B2983-FB15-4D72-B7F6-04FD36C81B90}.Release|Any CPU.ActiveCfg = Release|Any CPU {349B2983-FB15-4D72-B7F6-04FD36C81B90}.Release|Any CPU.Build.0 = Release|Any CPU {349B2983-FB15-4D72-B7F6-04FD36C81B90}.Release|x86.ActiveCfg = Release|Any CPU - {349B2983-FB15-4D72-B7F6-04FD36C81B90}.Release|x86.Build.0 = Release|Any CPU {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Debug|Any CPU.Build.0 = Debug|Any CPU {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Debug|x86.ActiveCfg = Debug|Any CPU - {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Debug|x86.Build.0 = Debug|Any CPU {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Release|Any CPU.ActiveCfg = Release|Any CPU {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Release|Any CPU.Build.0 = Release|Any CPU {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Release|x86.ActiveCfg = Release|Any CPU - {A81EDA11-9C1A-4BFA-9CC6-511C5447B167}.Release|x86.Build.0 = Release|Any CPU {3349AD8B-577C-471D-93E7-E99D88CB883D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3349AD8B-577C-471D-93E7-E99D88CB883D}.Debug|Any CPU.Build.0 = Debug|Any CPU {3349AD8B-577C-471D-93E7-E99D88CB883D}.Debug|x86.ActiveCfg = Debug|Any CPU - {3349AD8B-577C-471D-93E7-E99D88CB883D}.Debug|x86.Build.0 = Debug|Any CPU {3349AD8B-577C-471D-93E7-E99D88CB883D}.Release|Any CPU.ActiveCfg = Release|Any CPU {3349AD8B-577C-471D-93E7-E99D88CB883D}.Release|Any CPU.Build.0 = Release|Any CPU {3349AD8B-577C-471D-93E7-E99D88CB883D}.Release|x86.ActiveCfg = Release|Any CPU - {3349AD8B-577C-471D-93E7-E99D88CB883D}.Release|x86.Build.0 = Release|Any CPU {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Debug|Any CPU.Build.0 = Debug|Any CPU {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Debug|x86.ActiveCfg = Debug|Any CPU - {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Debug|x86.Build.0 = Debug|Any CPU {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Release|Any CPU.ActiveCfg = Release|Any CPU {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Release|Any CPU.Build.0 = Release|Any CPU {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Release|x86.ActiveCfg = Release|Any CPU - {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}.Release|x86.Build.0 = Release|Any CPU {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Debug|Any CPU.Build.0 = Debug|Any CPU {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Debug|x86.ActiveCfg = Debug|Any CPU - {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Debug|x86.Build.0 = Debug|Any CPU {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Release|Any CPU.Build.0 = Release|Any CPU {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Release|x86.ActiveCfg = Release|Any CPU - {6DCDCA5E-3174-4C0B-996A-F7E4E455F889}.Release|x86.Build.0 = Release|Any CPU {2079F388-81AE-4A76-9428-3C8D7F86825B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2079F388-81AE-4A76-9428-3C8D7F86825B}.Debug|Any CPU.Build.0 = Debug|Any CPU {2079F388-81AE-4A76-9428-3C8D7F86825B}.Debug|x86.ActiveCfg = Debug|Any CPU - {2079F388-81AE-4A76-9428-3C8D7F86825B}.Debug|x86.Build.0 = Debug|Any CPU {2079F388-81AE-4A76-9428-3C8D7F86825B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2079F388-81AE-4A76-9428-3C8D7F86825B}.Release|Any CPU.Build.0 = Release|Any CPU {2079F388-81AE-4A76-9428-3C8D7F86825B}.Release|x86.ActiveCfg = Release|Any CPU - {2079F388-81AE-4A76-9428-3C8D7F86825B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 7c5dafb6c028636883d260e669e110015a775c33 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Tue, 2 Jul 2024 19:58:56 +0100 Subject: [PATCH 26/91] ILRepack and other build fixings --- AltCover.Engine/AltCover.Engine.fsproj | 4 +- AltCover.Recorder.Tests/Tracer.Tests.cs | 4 +- AltCover.Recorder/AltCover.Recorder.csproj | 20 +------ AltCover.Recorder/Tracer.cs | 14 ++++- AltCover.Tests/AltCover.Tests.fsproj | 2 +- Build/NuGet.csproj | 1 + Build/targets.fs | 67 ++++++++++++++++------ Directory.Packages.props | 1 + 8 files changed, 70 insertions(+), 43 deletions(-) diff --git a/AltCover.Engine/AltCover.Engine.fsproj b/AltCover.Engine/AltCover.Engine.fsproj index ef15a522..e919a766 100644 --- a/AltCover.Engine/AltCover.Engine.fsproj +++ b/AltCover.Engine/AltCover.Engine.fsproj @@ -67,10 +67,10 @@ Recorder.snk - + AltCover.Recorder.net20.dll - + AltCover.Async.net46.dll diff --git a/AltCover.Recorder.Tests/Tracer.Tests.cs b/AltCover.Recorder.Tests/Tracer.Tests.cs index a09a4df9..8b79b76e 100644 --- a/AltCover.Recorder.Tests/Tracer.Tests.cs +++ b/AltCover.Recorder.Tests/Tracer.Tests.cs @@ -82,7 +82,7 @@ public static void WillNotConnectSpontaneously() () => { client = client.OnStart(); - Assert.True(!client.IsConnected()); + Assert.True(!client.IsConnected); close(); }, close); } @@ -103,7 +103,7 @@ public static void ValidTokenWillConnect() try { client = client.OnStart(); - Assert.True(client.IsConnected()); + Assert.True(client.IsConnected); } finally { client.Close(); } diff --git a/AltCover.Recorder/AltCover.Recorder.csproj b/AltCover.Recorder/AltCover.Recorder.csproj index 5f52de81..dd036b0c 100644 --- a/AltCover.Recorder/AltCover.Recorder.csproj +++ b/AltCover.Recorder/AltCover.Recorder.csproj @@ -8,32 +8,16 @@ false false RECORDER + CS1591 + --keyfile:$(InfrastructureKey) TRACE;$(DefineConstants) - --keyfile:$(InfrastructureKey) --staticlink:ICSharpCode.SharpZipLib TRACE;DEBUG;CODE_ANALYSIS;$(DefineConstants) - --keyfile:$(InfrastructureKey) - - - - CS1591 - - - - CS1591 - - - - CS1591 - - - - CS1591 diff --git a/AltCover.Recorder/Tracer.cs b/AltCover.Recorder/Tracer.cs index 696b36ae..10d27d12 100644 --- a/AltCover.Recorder/Tracer.cs +++ b/AltCover.Recorder/Tracer.cs @@ -12,6 +12,7 @@ namespace AltCover.Recorder //using AltCover.Shared; + [Serializable] internal enum Close { DomainUnload, @@ -20,6 +21,9 @@ internal enum Close Resume, } + [SuppressMessage("Gendarme.Rules.Performance", + "OverrideValueTypeDefaultsRule", + Justification = "Not actually used/NoComparison")] internal struct Tracer { public string TracerName; @@ -54,9 +58,12 @@ internal void Close() catch (NullReferenceException) { } } - internal bool IsConnected() + internal bool IsConnected { - return (this.Stream != null) && this.Runner; + get + { + return (this.Stream != null) && this.Runner; + } } internal Tracer OnStart() @@ -66,6 +73,9 @@ internal Tracer OnStart() return running; } + [SuppressMessage("Gendarme.Rules.Correctness", + "EnsureLocalDisposalRule", + Justification = "s, fs : Closed as recording ends")] private Tracer MakeConnection(string f) { var fs = File.OpenWrite(f); diff --git a/AltCover.Tests/AltCover.Tests.fsproj b/AltCover.Tests/AltCover.Tests.fsproj index 8eaac112..cedbcb3a 100644 --- a/AltCover.Tests/AltCover.Tests.fsproj +++ b/AltCover.Tests/AltCover.Tests.fsproj @@ -105,7 +105,7 @@ - + AltCover.Recorder.net20.dll diff --git a/Build/NuGet.csproj b/Build/NuGet.csproj index baea8b2c..96bfa1fd 100644 --- a/Build/NuGet.csproj +++ b/Build/NuGet.csproj @@ -16,6 +16,7 @@ all runtime; build; native; contentfiles; analyzers + diff --git a/Build/targets.fs b/Build/targets.fs index 8a5ef3f6..8e81dfef 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -938,6 +938,13 @@ module Targets = let BuildDebug = (fun () -> Directory.ensure "./_SourceLink" + Directory.ensure "./_Repack" + + let repackdir = + ("./_Repack" |> Path.getFullName) + + Shell.cleanDir repackdir + Shell.copyFile "./_SourceLink/Class2.cs" "./Samples/Sample14/Sample14/Class2.txt" (if Environment.isWindows then @@ -948,6 +955,41 @@ module Targets = Shell.copyFile "/tmp/.AltCover_SourceLink/Sample14.SourceLink.Class3.cs") "./Samples/Sample14/Sample14/Class3.txt" + // net20 and such + dotnetBuildRelease "./AltCover.Recorder/AltCover.Recorder.csproj" + dotnetBuildRelease "./AltCover.Async/AltCover.Async.csproj" + + Shell.copyFile + (Path.Join(repackdir, "AltCover.Async.dll")) + ("./_Binaries/AltCover.Async/Release+AnyCPU/net46/AltCover.Async.dll" + |> Path.getFullName) + + let ilrepack = + ("./packages/" + + (packageVersion "ILRepack") + + "/tools/ILRepack.exe") + |> Path.getFullName + + let keyfile = + "./Build/Infrastructure.snk" |> Path.getFullName + + let cmd = + [ "/keyfile:" + keyfile + "/ver:" + + (String.Join(".", VersionTemplate.Split('.') |> Seq.take 2)) + + ".0.0" + "/target:library" + "/targetplatform:v2" + "/internalize" + "/out:" + + Path.Join(repackdir, "AltCover.Recorder.dll") + "./_Binaries/AltCover.Recorder/Release+AnyCPU/net20/AltCover.Recorder.dll" + |> Path.getFullName + "./_Binaries/AltCover.Recorder/Release+AnyCPU/net20/ICSharpCode.SharpZipLib.dll" + |> Path.getFullName ] + + Actions.Run (ilrepack, ".", cmd) "ILRepack failed" + [ "./AltCover.sln" "./AltCover.Visualizer.sln" "./MCS.sln" @@ -1745,13 +1787,6 @@ module Targets = :: p.Properties DoRestore = true } - let msbuildDebug = doMSBuild withTagDebug - msbuildDebug MSBuildPath "./AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj" - - msbuildDebug - MSBuildPath - "./AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj" - let buildIt = DotNet.build (fun p -> { p.WithCommon dotnetOptions with @@ -1760,7 +1795,9 @@ module Targets = |> (buildWithCLITaggedArguments "UnitTestDotNet")) !!(@"./*Test*/*Tests.fsproj") - |> Seq.filter (_.Contains("Recorder") >> not) // net20 + |> Seq.iter buildIt + + !!(@"./*Test*/*Tests.csproj") |> Seq.iter buildIt !!(@"./*.Valid*/*Valid*.fsproj") @@ -1802,16 +1839,10 @@ module Targets = :: p.Properties DoRestore = true } - let msbuildDebug = doMSBuild withTagDebug - - msbuildDebug MSBuildPath "./AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj" - - msbuildDebug - MSBuildPath - "./AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj" - [ Path.getFullName "./AltCover.Expecto.Tests/AltCover.Expecto.Tests.fsproj" Path.getFullName "./AltCover.Api.Tests/AltCover.Api.Tests.fsproj" + Path.getFullName "./AltCover.Recorder.Tests/AltCover.Recorder.Tests.csproj" + Path.getFullName "./AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.csproj" //Path.getFullName "./AltCover.Monitor.Tests/AltCover.Monitor.Tests.fsproj" Path.getFullName "./AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj" @@ -1833,8 +1864,8 @@ module Targets = [ Path.getFullName "./AltCover.Expecto.Tests/AltCover.Expecto.Tests.fsproj" Path.getFullName "./AltCover.Api.Tests/AltCover.Api.Tests.fsproj" //Path.getFullName "./AltCover.Monitor.Tests/AltCover.Monitor.Tests.fsproj" - Path.getFullName "./AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj" - Path.getFullName "./AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj" + Path.getFullName "./AltCover.Recorder.Tests/AltCover.Recorder.Tests.csproj" + Path.getFullName "./AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.csproj" Path.getFullName "./AltCover.Visualizer.Tests/AltCover.Visualizer.Tests.fsproj" Path.getFullName diff --git a/Directory.Packages.props b/Directory.Packages.props index e84700f2..b0fa08ea 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -46,6 +46,7 @@ + From 0e7d013a27ec8fd465f4659bd186d9942851f98f Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Wed, 3 Jul 2024 18:08:19 +0100 Subject: [PATCH 27/91] Incremental replacement of base --- AltCover.Base/AltCover.Base.csproj | 54 +++++++++++++++++++ AltCover.Base/AssemblyInfo.cs | 18 +++++++ AltCover.Engine/AltCover.Engine.fsproj | 6 ++- AltCover.Engine/Runner.fs | 4 +- AltCover.Recorder/Base.cs | 74 ++++++++++++++++++++++++++ AltCover.Recorder/Base.fs | 49 ----------------- AltCover.Tests/Runner.Tests.fs | 14 ++--- AltCover.sln | 9 ++++ Build/actions.fs | 1 + 9 files changed, 170 insertions(+), 59 deletions(-) create mode 100644 AltCover.Base/AltCover.Base.csproj create mode 100644 AltCover.Base/AssemblyInfo.cs diff --git a/AltCover.Base/AltCover.Base.csproj b/AltCover.Base/AltCover.Base.csproj new file mode 100644 index 00000000..aece210f --- /dev/null +++ b/AltCover.Base/AltCover.Base.csproj @@ -0,0 +1,54 @@ + + + + netstandard2.0 + AltCover + AltCover.Base + RUNNER + + + + TRACE;DEBUG;CODE_ANALYSIS;$(GlobalDefineConstants) + + + TRACE;$(GlobalDefineConstants) + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + ..\ThirdParty\cecil\Mono.Cecil.dll + + + ..\ThirdParty\cecil\Mono.Cecil.Rocks.dll + + + ..\ThirdParty\cecil\Mono.Cecil.Mdb.dll + + + ..\ThirdParty\cecil\Mono.Cecil.Pdb.dll + + + + + + + ..\ThirdParty\Manatee.Json.dll + + + + + + + + \ No newline at end of file diff --git a/AltCover.Base/AssemblyInfo.cs b/AltCover.Base/AssemblyInfo.cs new file mode 100644 index 00000000..e2e03c6f --- /dev/null +++ b/AltCover.Base/AssemblyInfo.cs @@ -0,0 +1,18 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: InternalsVisibleTo("AltCover.Engine, PublicKey=0024000004800000940000000602000000240000525341310004000001000100916443A2EE1D294E8CFA7666FB3F512D998D7CEAC4909E35EDB2AC1E104DE68890A93716D1D1931F7228AAC0523CACF50FD82CDB4CCF4FF4BF0DED95E3A383F4F371E3B82C45502CE74D7D572583495208C1905E0F1E8A3CCE66C4C75E4CA32E9A8F8DEE64E059C0DC0266E8D2CB6D7EBD464B47E062F80B63D390E389217FB7")] +[assembly: InternalsVisibleTo("AltCover.PowerShell, PublicKey=0024000004800000940000000602000000240000525341310004000001000100916443A2EE1D294E8CFA7666FB3F512D998D7CEAC4909E35EDB2AC1E104DE68890A93716D1D1931F7228AAC0523CACF50FD82CDB4CCF4FF4BF0DED95E3A383F4F371E3B82C45502CE74D7D572583495208C1905E0F1E8A3CCE66C4C75E4CA32E9A8F8DEE64E059C0DC0266E8D2CB6D7EBD464B47E062F80B63D390E389217FB7")] +[assembly: InternalsVisibleTo("AltCover.Toolkit, PublicKey=0024000004800000940000000602000000240000525341310004000001000100916443A2EE1D294E8CFA7666FB3F512D998D7CEAC4909E35EDB2AC1E104DE68890A93716D1D1931F7228AAC0523CACF50FD82CDB4CCF4FF4BF0DED95E3A383F4F371E3B82C45502CE74D7D572583495208C1905E0F1E8A3CCE66C4C75E4CA32E9A8F8DEE64E059C0DC0266E8D2CB6D7EBD464B47E062F80B63D390E389217FB7")] +[assembly: InternalsVisibleTo("AltCover, PublicKey=0024000004800000940000000602000000240000525341310004000001000100916443A2EE1D294E8CFA7666FB3F512D998D7CEAC4909E35EDB2AC1E104DE68890A93716D1D1931F7228AAC0523CACF50FD82CDB4CCF4FF4BF0DED95E3A383F4F371E3B82C45502CE74D7D572583495208C1905E0F1E8A3CCE66C4C75E4CA32E9A8F8DEE64E059C0DC0266E8D2CB6D7EBD464B47E062F80B63D390E389217FB7")] +#if DEBUG +// Self-test signing key +[assembly: InternalsVisibleTo("AltCover.Engine, PublicKey=002400000480000094000000060200000024000052534131000400000100010041C08339BC8FE3A8B847E3EC38CB1BB31A9B39855347761BAB7AC04E726FFB227B147DF92DE5C3D8BCE3B7CFC7C9AC8110AF2E22F5E35D9CB0EBF47C36890DF617BD83E211002A1979DAB26CC18743DE674CE6F34ABAC834F597364BC5598C133F192596FC2161A832A9BBD33835DBB44F3B924A6F736BE6217ECE42889ABBCF")] +[assembly: InternalsVisibleTo("AltCover.PowerShell, PublicKey=002400000480000094000000060200000024000052534131000400000100010041C08339BC8FE3A8B847E3EC38CB1BB31A9B39855347761BAB7AC04E726FFB227B147DF92DE5C3D8BCE3B7CFC7C9AC8110AF2E22F5E35D9CB0EBF47C36890DF617BD83E211002A1979DAB26CC18743DE674CE6F34ABAC834F597364BC5598C133F192596FC2161A832A9BBD33835DBB44F3B924A6F736BE6217ECE42889ABBCF")] +[assembly: InternalsVisibleTo("AltCover.Toolkit, PublicKey=002400000480000094000000060200000024000052534131000400000100010041C08339BC8FE3A8B847E3EC38CB1BB31A9B39855347761BAB7AC04E726FFB227B147DF92DE5C3D8BCE3B7CFC7C9AC8110AF2E22F5E35D9CB0EBF47C36890DF617BD83E211002A1979DAB26CC18743DE674CE6F34ABAC834F597364BC5598C133F192596FC2161A832A9BBD33835DBB44F3B924A6F736BE6217ECE42889ABBCF")] +[assembly: InternalsVisibleTo("AltCover, PublicKey=002400000480000094000000060200000024000052534131000400000100010041C08339BC8FE3A8B847E3EC38CB1BB31A9B39855347761BAB7AC04E726FFB227B147DF92DE5C3D8BCE3B7CFC7C9AC8110AF2E22F5E35D9CB0EBF47C36890DF617BD83E211002A1979DAB26CC18743DE674CE6F34ABAC834F597364BC5598C133F192596FC2161A832A9BBD33835DBB44F3B924A6F736BE6217ECE42889ABBCF")] +#endif +[assembly: CLSCompliant(true)] +[assembly: ComVisible(false)] +[assembly: System.Resources.NeutralResourcesLanguage("en-GB")] \ No newline at end of file diff --git a/AltCover.Engine/AltCover.Engine.fsproj b/AltCover.Engine/AltCover.Engine.fsproj index e919a766..6522d2a5 100644 --- a/AltCover.Engine/AltCover.Engine.fsproj +++ b/AltCover.Engine/AltCover.Engine.fsproj @@ -12,7 +12,7 @@ TRACE;$(GlobalDefineConstants) - + --staticlink:AltCover.Base @@ -121,6 +121,10 @@ + + + + diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 4632c595..7938810f 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1031,7 +1031,7 @@ module internal Runner = | Tag.Both -> let time = formatter.ReadInt64() let call = formatter.ReadInt32() - Both { Time = time; Call = call } + Both (Pair.Create(time, call)) | Tag.Table -> let t = Dictionary>() @@ -1075,7 +1075,7 @@ module internal Runner = pv.Tracks.Add( let time = formatter.ReadInt64() let call = formatter.ReadInt32() - Both { Time = time; Call = call } + Both (Pair.Create(time, call)) ) tracking () diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index e69de29b..272f4fa6 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -0,0 +1,74 @@ +#if RUNNER + +namespace AltCover +#else +namespace AltCover.Recorder +#endif +{ + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Globalization; + using System.IO; + using System.Xml; + +#if !RUNNER + using ICSharpCode.SharpZipLib.Zip; + + [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)] + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUninstantiatedInternalClassesRule", + Justification = "Looks like a bug, not detecting its use")] + internal sealed class ExcludeFromCodeCoverageAttribute : Attribute + {} +#endif + + [Flags] + [SuppressMessage("Gendarme.Rules.Design", + "FlagsShouldNotDefineAZeroValueRule", + Justification = "Zero is meaningful")] + [SuppressMessage("Gendarme.Rules.Naming", + "UsePluralNameInEnumFlagsRule", + Justification = "Not meaningful to do so")] + internal enum ReportFormat + { + NCover = 0, + OpenCover = 1, + NativeJson = 2, + TrackMask = 63, + WithTracking = 64, + ZipMask = 127, + Zipped = 128, + }; + + internal enum Sampling + { + All = 0, + Single = 1, + }; + + // TODO isolate where + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUninstantiatedInternalClassesRule", + Justification = "Used as pattern match and compiled away")] + internal enum Tag + { + Null = 0, + Time = 1, + Call = 2, + Both = 3, + Table = 4, + } + + [ExcludeFromCodeCoverage] + internal struct Pair + { + public long Time; + public int Call; + + public static Pair Create(long time, int call) + { + return new Pair { Time = time, Call = call }; + } + } +} \ No newline at end of file diff --git a/AltCover.Recorder/Base.fs b/AltCover.Recorder/Base.fs index 1335a70b..aea24469 100644 --- a/AltCover.Recorder/Base.fs +++ b/AltCover.Recorder/Base.fs @@ -11,55 +11,6 @@ open System.Globalization open System.IO open System.Xml -[] -[] -[] -type internal ReportFormat = - | NCover = 0 - | OpenCover = 1 - | NativeJson = 2 - | TrackMask = 63 - | WithTracking = 64 - | ZipMask = 127 - | Zipped = 128 - -#if !RUNNER -open ICSharpCode.SharpZipLib.Zip - -[] -[] -[] -type internal ExcludeFromCodeCoverageAttribute() = - inherit Attribute() -#endif - -type internal Sampling = - | All = 0 - | Single = 1 - -// TODO isolate where -#if RUNNER -[] -#endif -type internal Tag = - | Null = 0 - | Time = 1 - | Call = 2 - | Both = 3 - | Table = 4 - -[] -[] -type internal Pair = { Time: int64; Call: int } - [] [] type internal Track = diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index f256d725..ecbedeb9 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -2690,7 +2690,7 @@ module AltCoverRunnerTests = [| Null Call 0 Time t - Both { Time = t; Call = 0 } |] + Both (Pair.Create(t, 0)) |] let t0 = tracks 0L @@ -2988,7 +2988,7 @@ module AltCoverRunnerTests = [| Null Call 0 Time t - Both { Time = t; Call = 0 } |] + Both (Pair.Create(t, 0)) |] let t0 = tracks 0L @@ -3260,7 +3260,7 @@ module AltCoverRunnerTests = [| Null Call 0 Time t - Both { Time = t; Call = 0 } |] + Both (Pair.Create(t, 0)) |] let t0 = tracks 0L @@ -3578,7 +3578,7 @@ module AltCoverRunnerTests = [| Null Call 0 Time t - Both { Time = t; Call = 0 } |] + Both (Pair.Create(t, 0)) |] let t0 = tracks 0L @@ -3900,7 +3900,7 @@ module AltCoverRunnerTests = [ Null Call 17 Time 23L - Both { Time = 5L; Call = 42 } + Both (Pair.Create(5, 42)) Time 42L Call 5 ] @@ -4012,7 +4012,7 @@ module AltCoverRunnerTests = let d = Dictionary() - d.Add(4, (0L, [ Both { Time = 5L; Call = 42 } ])) + d.Add(4, (0L, [ Both (Pair.Create(5, 42)) ])) let e = Dictionary() @@ -4062,7 +4062,7 @@ module AltCoverRunnerTests = [ Null Call 17 Time 23L - Both { Time = 5L; Call = 42 } + Both (Pair.Create(5, 42)) Time 42L Time 5L ] diff --git a/AltCover.sln b/AltCover.sln index c40b2bf4..f695fe6c 100644 --- a/AltCover.sln +++ b/AltCover.sln @@ -5,6 +5,7 @@ MinimumVisualStudioVersion = 15.0.26124.0 Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.Engine", "AltCover.Engine\AltCover.Engine.fsproj", "{26C01B27-9A3E-4460-BB43-5383C8E818FB}" ProjectSection(ProjectDependencies) = postProject {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC} = {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC} + {79E50E5A-381F-4C9A-8F1D-3603CE9247BB} = {79E50E5A-381F-4C9A-8F1D-3603CE9247BB} EndProjectSection EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.PowerShell", "AltCover.PowerShell\AltCover.PowerShell.fsproj", "{208B8925-5626-4E5D-A00B-6A993D850524}" @@ -157,6 +158,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AltCover.Recorder2.Tests", {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC} = {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC} EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AltCover.Base", "AltCover.Base\AltCover.Base.csproj", "{79E50E5A-381F-4C9A-8F1D-3603CE9247BB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -389,6 +392,12 @@ Global {2079F388-81AE-4A76-9428-3C8D7F86825B}.Debug|x86.ActiveCfg = Debug|Any CPU {2079F388-81AE-4A76-9428-3C8D7F86825B}.Release|Any CPU.ActiveCfg = Release|Any CPU {2079F388-81AE-4A76-9428-3C8D7F86825B}.Release|x86.ActiveCfg = Release|Any CPU + {79E50E5A-381F-4C9A-8F1D-3603CE9247BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {79E50E5A-381F-4C9A-8F1D-3603CE9247BB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {79E50E5A-381F-4C9A-8F1D-3603CE9247BB}.Debug|x86.ActiveCfg = Debug|Any CPU + {79E50E5A-381F-4C9A-8F1D-3603CE9247BB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {79E50E5A-381F-4C9A-8F1D-3603CE9247BB}.Release|Any CPU.Build.0 = Release|Any CPU + {79E50E5A-381F-4C9A-8F1D-3603CE9247BB}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Build/actions.fs b/Build/actions.fs index ff85ae9d..c7e1c197 100644 --- a/Build/actions.fs +++ b/Build/actions.fs @@ -124,6 +124,7 @@ using System.Runtime.CompilerServices; #if DEBUG [assembly: AssemblyConfiguration("Debug {0}")] +[assembly: InternalsVisibleTo("AltCover.Tests, PublicKey={1}")] [assembly: InternalsVisibleTo("AltCover.Monitor.Tests, PublicKey={1}")] [assembly: InternalsVisibleTo("AltCover.Recorder.Tests, PublicKey={1}")] [assembly: InternalsVisibleTo("AltCover.Recorder2.Tests, PublicKey={1}")] From 6ad16def03f0b9490614aceca5646ce01199a1e6 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Wed, 3 Jul 2024 19:48:25 +0100 Subject: [PATCH 28/91] Start to replace Base.fs - Runner test TrackingPayloadShouldReportAsExpected loses Table serialization --- AltCover.Engine/PostProcess.fs | 4 +- AltCover.Engine/Runner.fs | 24 ++-- AltCover.Recorder/Base.cs | 217 +++++++++++++++++++++++++++++++++ AltCover.Recorder/Base.fs | 39 ++---- AltCover.Tests/Runner.Tests.fs | 131 ++++++++++---------- 5 files changed, 303 insertions(+), 112 deletions(-) diff --git a/AltCover.Engine/PostProcess.fs b/AltCover.Engine/PostProcess.fs index 3d9d4c6a..f6d02eec 100644 --- a/AltCover.Engine/PostProcess.fs +++ b/AltCover.Engine/PostProcess.fs @@ -181,7 +181,7 @@ module internal PostProcess = |> Seq.head let vc = - (lookUpVisitsByToken token dict).Total() + (lookUpVisitsByToken token dict).Total mp |> Seq.iter (fun m -> @@ -226,7 +226,7 @@ module internal PostProcess = tracks.[index].Tracks |> Seq.map (fun t -> match t with - | Time tx -> sprintf "%d" tx + | :? Time as tx -> sprintf "%d" tx.Value | _ -> String.Empty) // never happens |> Seq.filter (fun s -> s.Length > 0) diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 7938810f..d905c971 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1026,8 +1026,8 @@ module internal Runner = id, strike, match enum tag with - | Tag.Time -> Time <| formatter.ReadInt64() - | Tag.Call -> Call <| formatter.ReadInt32() + | Tag.Time -> (Time <| formatter.ReadInt64()) :> Track + | Tag.Call -> (Call <| formatter.ReadInt32()) :> Track | Tag.Both -> let time = formatter.ReadInt64() let call = formatter.ReadInt32() @@ -1057,7 +1057,7 @@ module internal Runner = if p |> t.[m].ContainsKey |> not then t.[m].Add(p, PointVisit.Create()) - let pv = t.[m].[p] + let mutable pv = t.[m].[p] pv.Count <- pv.Count + n // [] @@ -1090,7 +1090,7 @@ module internal Runner = ``module`` () Table t - | _ -> Null + | _ -> new Null() ) with :? EndOfStreamException -> None @@ -1190,11 +1190,11 @@ module internal Runner = let internal extractTracks tracks = tracks - |> Seq.map (fun t -> + |> Seq.map (fun (t:Track) -> match t with - | Time x -> (Some x, None) - | Both b -> (Some b.Time, Some b.Call) - | Call y -> (None, Some y) + | :? Time as x -> (Some x.Value, None) + | :? Both as b -> (Some b.Value.Time, Some b.Value.Call) + | :? Call as y -> (None, Some y.Value) | _ -> (None, None)) |> Seq.toList |> List.unzip @@ -1226,7 +1226,7 @@ module internal Runner = entrypoint.Tracks |> Seq.iter (fun t -> match t with - | Time tx -> tx |> NativeJson.fromTracking |> m.Entry.Add + | :? Time as tx -> tx.Value |> NativeJson.fromTracking |> m.Entry.Add | _ -> ()) let e3, exits = hits.TryGetValue Track.Exit @@ -1239,7 +1239,7 @@ module internal Runner = exitpoint.Tracks |> Seq.iter (fun t -> match t with - | Time tx -> tx |> NativeJson.fromTracking |> m.Exit.Add + | :? Time as tx -> tx.Value |> NativeJson.fromTracking |> m.Exit.Add | _ -> ()) let fillTracks tracks calls = @@ -1279,7 +1279,7 @@ module internal Runner = let calls = calls' |> Seq.choose id { sp with - VC = (int <| count.Total()) + Math.Max(0, sp.VC) + VC = (int <| count.Total) + Math.Max(0, sp.VC) Tracks = fillTracks sp.Tracks calls Times = fillTimes sp.Times times } else @@ -1303,7 +1303,7 @@ module internal Runner = let calls = calls' |> Seq.choose id { bp with - Hits = (int <| count.Total()) + Math.Max(0, bp.Hits) + Hits = (int <| count.Total) + Math.Max(0, bp.Hits) Tracks = fillTracks bp.Tracks calls Times = fillTimes bp.Times times } else diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 272f4fa6..96e27db7 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -1,5 +1,9 @@ #if RUNNER +using AltCover; +using System.Drawing; +using System; + namespace AltCover #else namespace AltCover.Recorder @@ -70,5 +74,218 @@ public static Pair Create(long time, int call) { return new Pair { Time = time, Call = call }; } + + public override string ToString() + { + return "AltCover.Pair(Time=" + Time.ToString(CultureInfo.InvariantCulture) + + ", Call=" + Call.ToString(CultureInfo.InvariantCulture) + ")"; + } + + public override bool Equals(object obj) + { + if (obj is Pair b) + { + return Call == b.Call + && Time == b.Time; + } + + return false; + } + + public override int GetHashCode() + { + return Call.GetHashCode() ^ Time.GetHashCode(); + } + } + + internal abstract class Track + { + internal static readonly string Entry = "\u2611"; // BALLOT BOX WITH CHECK + internal static readonly string Exit = "\u2612"; // BALLOT BOX WITH X + + public override bool Equals(object obj) + { + return (obj is Track); + } + + public override int GetHashCode() + { + return 0; + } + } + + internal class Null : Track + { + public override string ToString() + { + return "AltCover.Null"; + } + } + + internal class Time : Track + { + public readonly long Value; + + public Time(long time) + { + Value = time; + } + + public override bool Equals(object obj) + { + if (obj is Time) + { + return Value == ((Time)obj).Value; + } + + return false; + } + + public override int GetHashCode() + { + return Value.GetHashCode(); + } + + public override string ToString() + { + return "AltCover.Time : " + Value.ToString(CultureInfo.InvariantCulture); + } + } + + internal class Call : Track + { + public readonly int Value; + + public Call(int call) + { + Value = call; + } + + public override bool Equals(object obj) + { + if (obj is Call) + { + return Value == ((Call)obj).Value; + } + + return false; + } + + public override int GetHashCode() + { + return Value.GetHashCode(); + } + + public override string ToString() + { + return "AltCover.Call : " + Value.ToString(CultureInfo.InvariantCulture); + } + } + + internal class Both : Track + { + public readonly Pair Value; + + public Both(Pair both) + { + Value = both; + } + + public override bool Equals(object obj) + { + if (obj is Both b) + { + var ok = Value.Equals(b.Value); + return ok; + } + + return false; + } + + public override int GetHashCode() + { + return Value.GetHashCode(); + } + + public override string ToString() + { + return "AltCover.Both : " + Value.ToString(); + } + } + + internal class Table : Track + { + public readonly Dictionary> Value; + + public Table(Dictionary> table) + { + Value = table; + } + } + + internal class PointVisit + { + public long Count; + public readonly List Tracks; + + public override bool Equals(object obj) + { + if (obj is PointVisit b) + { + var ok = Count == b.Count && Tracks.Count == b.Tracks.Count; + for (var i = 0; ok && i < Tracks.Count; i++) + { + ok = ok && Tracks[i].Equals(b.Tracks[i]); + } + + return ok; + } + + return false; + } + + public override int GetHashCode() + { + return Count.GetHashCode(); + } + + public override string ToString() + { + var tracks = new string[Tracks.Count]; + for (int i = 0; i < Tracks.Count; ++i) + tracks[i] = Tracks[i].ToString(); + + return "AltCover.PointVisit : Count = " + Count.ToString(CultureInfo.InvariantCulture) + + "Tracks = " + String.Join("; ", tracks); + } + + private PointVisit(long count) + { + Count = count; + Tracks = new List(); + } + + internal static PointVisit Create() + { + return new PointVisit(0); + } + + internal void Step() + { + System.Threading.Interlocked.Increment(ref this.Count); + } + + internal void Track(Track something) + { + lock (this.Tracks) + { + this.Tracks.Add(something); + } + } + + internal long Total + { + get { return this.Count + this.Tracks.Count; } + } } } \ No newline at end of file diff --git a/AltCover.Recorder/Base.fs b/AltCover.Recorder/Base.fs index aea24469..d9f14d65 100644 --- a/AltCover.Recorder/Base.fs +++ b/AltCover.Recorder/Base.fs @@ -11,31 +11,6 @@ open System.Globalization open System.IO open System.Xml -[] -[] -type internal Track = - | Null - | Time of int64 - | Call of int - | Both of Pair - | Table of Dictionary> - static member internal Entry = "\u2611" // BALLOT BOX WITH CHECK - static member internal Exit = "\u2612" // BALLOT BOX WITH X - -and [] internal PointVisit = - { mutable Count: int64 - Tracks: List } - static member internal Create() = { Count = 0L; Tracks = List() } - - member internal self.Step() = - System.Threading.Interlocked.Increment(&self.Count) - |> ignore - - member internal self.Track something = - lock self.Tracks (fun () -> self.Tracks.Add something) - - member internal self.Total() = self.Count + int64 self.Tracks.Count - [] module internal Counter = type System.NotSupportedException with @@ -281,7 +256,7 @@ module internal Counter = |> snd // Treat -ve visit counts (an exemption added in analysis) as zero let count = moduleHits.[counter] - let visits = (max 0L vc) + count.Total() + let visits = (max 0L vc) + count.Total pt.SetAttribute(v, visits.ToString(CultureInfo.InvariantCulture)) pointProcess pt count.Tracks)) @@ -327,9 +302,9 @@ module internal Counter = here.Keys |> Seq.iter (fun p -> ensurePoint next p - let v = next.[p] + let mutable v = next.[p] let add = here.[p] - hitcount <- hitcount + add.Total() + hitcount <- hitcount + add.Total lock v (fun () -> v.Count <- v.Count + add.Count @@ -351,7 +326,7 @@ module internal Counter = (counts: Dictionary>) moduleId hitPointId - context + (context:Track) = if counts.ContainsKey moduleId then let next = counts.[moduleId] @@ -360,7 +335,7 @@ module internal Counter = let v = next.[hitPointId] match context with - | Null -> v.Step() + | :? Null -> v.Step() | something -> v.Track something #if RUNNER @@ -368,10 +343,10 @@ module internal Counter = (counts: Dictionary>) moduleId hitPointId - context + (context:Track) = match context with - | Table t -> I.addTable counts t + | :? Table as t -> I.addTable counts t.Value | _ -> addSingleVisit counts moduleId hitPointId context 1L diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index ecbedeb9..785ff6a3 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -105,7 +105,7 @@ module AltCoverRunnerTests = visits.Add(" ", Dictionary()) let key = " " - let v1 = Counter.addVisit visits key 23 Null + let v1 = Counter.addVisit visits key 23 (new Null()) Assert.That(v1, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) Assert.That(visits.[key].Count, Is.EqualTo 1) @@ -146,11 +146,11 @@ module AltCoverRunnerTests = visits.Add("key", Dictionary()) let key = " " - let v3 = Counter.addVisit visits key 23 Null + let v3 = Counter.addVisit visits key 23 (new Null()) Assert.That(v3, Is.EqualTo 1) let v4 = - Counter.addVisit visits "key" 42 Null + Counter.addVisit visits "key" 42 (new Null()) Assert.That(visits.Count, Is.EqualTo 2) Assert.That(v4, Is.EqualTo 1) @@ -165,9 +165,9 @@ module AltCoverRunnerTests = visits.Add(" ", Dictionary()) let key = " " - let v5 = Counter.addVisit visits key 23 Null + let v5 = Counter.addVisit visits key 23 (new Null()) Assert.That(v5, Is.EqualTo 1) - let v6 = Counter.addVisit visits key 42 Null + let v6 = Counter.addVisit visits key 42 (new Null()) Assert.That(v6, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) Assert.That(visits.[key].Count, Is.EqualTo 2) @@ -182,9 +182,9 @@ module AltCoverRunnerTests = visits.Add(" ", Dictionary()) let key = " " - let v7 = Counter.addVisit visits key 23 Null + let v7 = Counter.addVisit visits key 23 (new Null()) Assert.That(v7, Is.EqualTo 1) - let v8 = Counter.addVisit visits key 23 Null + let v8 = Counter.addVisit visits key 23 (new Null()) Assert.That(v8, Is.EqualTo 1) let x = visits.[key].[23] Assert.That(x.Count, Is.EqualTo 2) @@ -201,7 +201,7 @@ module AltCoverRunnerTests = let key = " " let payload = Time DateTime.UtcNow.Ticks - let v9 = Counter.addVisit visits key 23 Null + let v9 = Counter.addVisit visits key 23 (new Null()) Assert.That(v9, Is.EqualTo 1) let v10 = @@ -225,9 +225,8 @@ module AltCoverRunnerTests = |> Seq.find _.EndsWith("Sample1WithOpenCover.xml", StringComparison.Ordinal) let internal init n l = - let tmp = - { PointVisit.Create() with Count = n } - + let mutable tmp = PointVisit.Create() + tmp.Count <- n tmp.Tracks.AddRange l tmp @@ -2576,7 +2575,7 @@ module AltCoverRunnerTests = [ 0..9 ] |> Seq.iter (fun i -> for j = 1 to i + 1 do - hits.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, Null) + hits.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, new Null()) ignore j) let counts = @@ -2686,10 +2685,10 @@ module AltCoverRunnerTests = stream.CopyTo worker - let tracks t = - [| Null - Call 0 - Time t + let tracks t : Track array = + [| Null() :> Track + Call (0) :> Track + Time (t) :> Track Both (Pair.Create(t, 0)) |] let t0 = tracks 0L @@ -2823,7 +2822,7 @@ module AltCoverRunnerTests = [ 0..9 ] |> Seq.iter (fun i -> for j = 1 to i + 1 do - hits.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, Null) + hits.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, new Null()) ignore j) let counts = @@ -2984,10 +2983,10 @@ module AltCoverRunnerTests = Zip.save (stream.CopyTo) reportFile true // fsharplint:disable-line - let tracks t = - [| Null - Call 0 - Time t + let tracks t : Track array = + [| Null() :> Track + Call (0) :> Track + Time (t) :> Track Both (Pair.Create(t, 0)) |] let t0 = tracks 0L @@ -3142,7 +3141,7 @@ module AltCoverRunnerTests = [ 0..9 ] |> Seq.iter (fun i -> for j = 1 to i + 1 do - hits.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, Null) + hits.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, new Null()) ignore j) let counts = @@ -3256,10 +3255,10 @@ module AltCoverRunnerTests = stream.CopyTo worker - let tracks t = - [| Null - Call 0 - Time t + let tracks t : Track array = + [| Null() :> Track + Call (0) :> Track + Time (t) :> Track Both (Pair.Create(t, 0)) |] let t0 = tracks 0L @@ -3405,7 +3404,7 @@ module AltCoverRunnerTests = [ 0..9 ] |> Seq.iter (fun i -> for j = 1 to i + 1 do - hits.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, Null) + hits.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, new Null()) ignore j) let counts = @@ -3574,10 +3573,10 @@ module AltCoverRunnerTests = Zip.save (stream.CopyTo) reportFile true // fsharplint:disable-line - let tracks t = - [| Null - Call 0 - Time t + let tracks t : Track array = + [| Null() :> Track + Call (0) :> Track + Time (t) :> Track Both (Pair.Create(t, 0)) |] let t0 = tracks 0L @@ -3853,7 +3852,7 @@ module AltCoverRunnerTests = let formatter = System.Runtime.Serialization.DataContractSerializer( - typeof> + typeof> ) let r = @@ -3873,7 +3872,7 @@ module AltCoverRunnerTests = l |> List.mapi (fun i x -> - formatter.WriteObject(pipe, (x, i, Null, DateTime.UtcNow)) + formatter.WriteObject(pipe, (x, i, DateTime.UtcNow)) x) |> List.length) [ "a"; "b"; String.Empty; "c" ] @@ -3897,12 +3896,12 @@ module AltCoverRunnerTests = Path.Combine(where, Guid.NewGuid().ToString()) let payloads0 = - [ Null - Call 17 - Time 23L - Both (Pair.Create(5, 42)) - Time 42L - Call 5 ] + [ Null () :> Track + Call (17) :> Track + Time (23L) :> Track + Both (Pair.Create(5, 42)) :> Track + Time (42L) :> Track + Call (5) :> Track ] let pv = init 42L (payloads0 |> List.tail) @@ -3911,7 +3910,7 @@ module AltCoverRunnerTests = table.Add("Extra", Dictionary()) table.["Extra"].Add(3, pv) - let payloads = (Table table) :: payloads0 + let payloads = ((Table table) :> Track) :: payloads0 let inputs = [ String.Empty @@ -3942,44 +3941,44 @@ module AltCoverRunnerTests = formatter.Write i match y with - | Null -> formatter.Write(Tag.Null |> byte) - | Time t -> + | :? Null -> formatter.Write(Tag.Null |> byte) + | :? Time as t -> formatter.Write(Tag.Time |> byte) - formatter.Write(t) - | Call t -> + formatter.Write(t.Value) + | :? Call as t -> formatter.Write(Tag.Call |> byte) - formatter.Write(t) - | Both b -> + formatter.Write(t.Value) + | :? Both as b -> formatter.Write(Tag.Both |> byte) - formatter.Write(b.Time) - formatter.Write(b.Call) - | Table t -> + formatter.Write(b.Value.Time) + formatter.Write(b.Value.Call) + | :? Table as t -> formatter.Write(Tag.Table |> byte) - t.Keys + t.Value.Keys |> Seq.iter (fun m -> formatter.Write m - formatter.Write t.[m].Keys.Count + formatter.Write t.Value.[m].Keys.Count - t.[m].Keys + t.Value.[m].Keys |> Seq.iter (fun p -> formatter.Write p - let v = t.[m].[p] + let v = t.Value.[m].[p] formatter.Write v.Count v.Tracks |> Seq.iter (fun tx -> match tx with - | Time t -> + | :? Time as t -> formatter.Write(Tag.Time |> byte) - formatter.Write(t) - | Call t -> + formatter.Write(t.Value) + | :? Call as t -> formatter.Write(Tag.Call |> byte) - formatter.Write(t) - | Both b -> + formatter.Write(t.Value) + | :? Both as b -> formatter.Write(Tag.Both |> byte) - formatter.Write(b.Time) - formatter.Write(b.Call) + formatter.Write(b.Value.Time) + formatter.Write(b.Value.Call) //| _ -> tx |> (sprintf "%A") |> Assert.Fail ) @@ -4059,12 +4058,12 @@ module AltCoverRunnerTests = let root = x.DocumentElement let hits = - [ Null - Call 17 - Time 23L - Both (Pair.Create(5, 42)) - Time 42L - Time 5L ] + [ Null() :> Track + Call (17) :> Track + Time (23L) :> Track + Both (Pair.Create(5, 42)) :> Track + Time (42L) :> Track + Time (5L) :> Track ] Runner.J.pointProcess root hits From 60d33fa7e16549959ec1b4ddb0b050d232f3907a Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Wed, 3 Jul 2024 20:11:02 +0100 Subject: [PATCH 29/91] Fix that unit test --- 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 d905c971..7ec15ad3 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1105,7 +1105,7 @@ module internal Runner = || ((String.IsNullOrEmpty key) && hitPointId = 0 && visit.GetType().ToString() - == "AltCover.Track+Table") + == "AltCover.Table") // TODO better than this then if hits.ContainsKey key |> not From 112e4d9e03bcafbdbbb40343b9b7ea8ca619fbfe Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Wed, 3 Jul 2024 21:31:36 +0100 Subject: [PATCH 30/91] We can now write the type --- AltCover.Engine/Runner.fs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 7ec15ad3..83be1a0a 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1104,8 +1104,7 @@ module internal Runner = key |> String.IsNullOrWhiteSpace |> not || ((String.IsNullOrEmpty key) && hitPointId = 0 - && visit.GetType().ToString() - == "AltCover.Table") // TODO better than this + && visit.GetType()= typeof) then if hits.ContainsKey key |> not From e1a710e316f7fb222e35392579a48876432b1e3b Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Wed, 3 Jul 2024 21:49:07 +0100 Subject: [PATCH 31/91] A big bang --- AltCover.Engine/AltCover.Engine.fsproj | 2 +- AltCover.Recorder/Base.cs | 33 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/AltCover.Engine/AltCover.Engine.fsproj b/AltCover.Engine/AltCover.Engine.fsproj index 6522d2a5..935d5484 100644 --- a/AltCover.Engine/AltCover.Engine.fsproj +++ b/AltCover.Engine/AltCover.Engine.fsproj @@ -26,7 +26,7 @@ - + diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 96e27db7..445e74e2 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -288,4 +288,37 @@ internal long Total get { return this.Count + this.Tracks.Count; } } } + + internal static class Counter + { + // // + // // The time at which coverage run began + // // + internal static DateTime startTime = DateTime.UtcNow; + + // // + // // The finishing time taken of the coverage run + // // + internal static DateTime measureTime = DateTime.UtcNow; + + // // + // // The offset flag for branch counts + // // + internal const int branchFlag = unchecked((int)0x80000000); + + internal const int branchMask = unchecked((int)0x7FFFFFFF); + + internal static long totalVisits = 0; + + internal static long branchVisits = 0; + +#if DEBUG + + internal static class I +#else + static private class I +#endif + { + } + } } \ No newline at end of file From d0b5f4ee378f5bfb3f9dc61a388f0ab7ea58fb03 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 4 Jul 2024 09:39:06 +0100 Subject: [PATCH 32/91] Base is now API complete, failing 17 more unit tests in runner --- AltCover.Engine/Runner.fs | 16 +- AltCover.Recorder/Base.cs | 296 ++++++++++++++++++++++++++++++++- AltCover.Tests/Runner.Tests.fs | 61 +++---- Build/actions.fs | 1 + 4 files changed, 332 insertions(+), 42 deletions(-) diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 83be1a0a..bd0cb896 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1112,7 +1112,7 @@ module internal Runner = then hits.Add(key, Dictionary()) - Counter.addVisit hits key hitPointId visit + Counter.addVisit(hits, key, hitPointId, visit) else 0L @@ -1392,13 +1392,13 @@ module internal Runner = let result = AltCover.Counter.doFlushStream - (postProcess hits format) - pointProcess - true - hits - format - file - outputFile + ((postProcess hits format), + pointProcess, + true, + hits, + format, + file, + outputFile) match arg with | None -> () diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 445e74e2..bd81da83 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -11,10 +11,13 @@ namespace AltCover.Recorder { using System; using System.Collections.Generic; + using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; + using System.Text.RegularExpressions; using System.Xml; + using static System.Net.Mime.MediaTypeNames; #if !RUNNER using ICSharpCode.SharpZipLib.Zip; @@ -51,10 +54,6 @@ internal enum Sampling Single = 1, }; - // TODO isolate where - [SuppressMessage("Gendarme.Rules.Performance", - "AvoidUninstantiatedInternalClassesRule", - Justification = "Used as pattern match and compiled away")] internal enum Tag { Null = 0, @@ -319,6 +318,295 @@ internal static class I static private class I #endif { + // let internal openCoverXml = + // ("//Module", + // "hash", + // "Classes/Class/Methods/Method", + // [ ("SequencePoints/SequencePoint", 0) + // ("BranchPoints/BranchPoint", branchFlag) ], + // "vc") + + //let internal IEnumerable nCoverXml = + // ("//module", "moduleId", "method", [ ("seqpnt", 0)], "visitcount") + internal static readonly object openCoverXml = "//Module";//TODO + + internal static readonly object nCoverXml = "//module";//TODO + + internal static object xmlByFormat(ReportFormat format) + { + switch (format & ReportFormat.TrackMask) + { + case ReportFormat.OpenCover: return openCoverXml; + case ReportFormat.NCover: return nCoverXml; + default: throw new NotSupportedException(format.ToString()); + } + } + + internal static DateTime minTime(DateTime t1, DateTime t2) + { + return t1 < t2 ? t1 : t2; + } + + internal static DateTime maxTime(DateTime t1, DateTime t2) + { + return t1 > t2 ? t1 : t2; + } + + internal static int findIndexFromUspid(int flag, string uspid) + { + var f = Int32.TryParse( + uspid, + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out int c); + return f ? (c | flag) : -1; + } + + internal static void ensurePoint(Dictionary next, int hitPointId) + { } + + internal static long addTable( + Dictionary> counts, + Dictionary> t + ) + { + long hitcount = 0; + //let internal addTable + // (counts: Dictionary>) + // (t: Dictionary>) + // = + // let mutable hitcount = 0L + + // t.Keys + // |> Seq.iter (fun m -> + // if counts.ContainsKey m |> not then + // counts.Add(m, Dictionary()) + + // let next = counts.[m] + // let here = t.[m] + + // here.Keys + // |> Seq.iter (fun p -> + // ensurePoint next p + // let mutable v = next.[p] + // let add = here.[p] + // hitcount <- hitcount + add.Total + + // lock v (fun () -> + // v.Count <- v.Count + add.Count + // v.Tracks.AddRange(add.Tracks)))) + + return hitcount; + } + + public static DateTime updateReport( + Action postProcess, + /*Action>*/ object pointProcess, + bool own, + Dictionary> counts, + ReportFormat format, + Stream coverageFile, + Stream outputFile + ) + { + var flushStart = DateTime.UtcNow; + // let flushStart = + // updateReport postProcess pointProcess own counts format coverageFile outputFile + + // TimeSpan(DateTime.UtcNow.Ticks - flushStart.Ticks) + return flushStart; + } + + public static TimeSpan doFlush( + Action postProcess, + /*Action>*/ object pointProcess, + bool own, + Dictionary> counts, + ReportFormat format, + Stream coverageFile, + Stream outputFile + ) + { + var flushStart = + updateReport(postProcess, pointProcess, own, counts, format, coverageFile, outputFile); + + return new TimeSpan(DateTime.UtcNow.Ticks - flushStart.Ticks); + } + } + + // "Public" API + internal static void addSingleVisit( + Dictionary> counts, + string moduleId, + int hitPointId, + Track context + ) + { + if (counts.ContainsKey(moduleId)) + { + var next = counts[moduleId]; + I.ensurePoint(next, hitPointId); + var v = next[hitPointId]; + + if (context is Null n) + { v.Step(); } + else { v.Track(context); } + } + } + +#if RUNNER + + internal static long addVisit( + Dictionary> counts, + string moduleId, + int hitPointId, + Track context + ) + { + if (context is Table t) + { + return I.addTable(counts, t.Value); + } + + addSingleVisit(counts, moduleId, hitPointId, context); + return 1; + } + + [SuppressMessage("Gendarme.Rules.Smells", + "AvoidLongParameterListsRule", + Justification = "Most of this gets curried away")] + public static TimeSpan doFlushStream( + Action postProcess, + Action> pointProcess, + bool own, + Dictionary> counts, + ReportFormat format, + Stream coverageFile, + Stream outputFile + ) + { + return I.doFlush(postProcess, pointProcess, own, counts, format, coverageFile, outputFile); } + +#else + //[] + //[] + //let internal doFlushStream + // postProcess + // pointProcess + // own + // counts + // format + // coverageFile + // output + // = + // use target = + // match output with + // | None -> new MemoryStream() :> Stream + // | Some f -> + // new FileStream( + // f, + // FileMode.OpenOrCreate, + // FileAccess.Write, + // FileShare.None, + // 4096, + // FileOptions.SequentialScan + // ) + // :> Stream + + // let outputFile = + // if Option.isSome output then + // target + // else + // coverageFile :> Stream + + // I.doFlush postProcess pointProcess own counts format coverageFile outputFile + + //[] + //[] + //[] + //let internal doFlushFile postProcess pointProcess own counts format report output = + // let zipped = + // int (format &&& ReportFormat.Zipped) <> 0 + + // if not zipped then + // use coverageFile = + // new FileStream( + // report, + // FileMode.Open, + // FileAccess.ReadWrite, + // FileShare.None, + // 4096, + // FileOptions.SequentialScan + // ) + + // doFlushStream postProcess pointProcess own counts format coverageFile output + // else + // let container = + // new FileStream( + // report + ".zip", + // FileMode.Open, + // FileAccess.ReadWrite, + // FileShare.None, + // 4096, + // FileOptions.SequentialScan + // ) + + // use target = + // match output with + // | None -> new MemoryStream() :> Stream + // | Some f -> + // new FileStream( + // f, + // FileMode.OpenOrCreate, + // FileAccess.Write, + // FileShare.None, + // 4096, + // FileOptions.SequentialScan + // ) + // :> Stream + + // try + // ZipConstants.DefaultCodePage <- 65001 //UTF-8 as System.IO.Compression.ZipFile uses internally + // let zip = new ZipFile(container) + + // try + // let entryName = report |> Path.GetFileName + // let entry = zip.GetEntry(entryName) + + // let result = + // use reader = zip.GetInputStream(entry) + // I.doFlush postProcess pointProcess own counts format reader target + + // if output.IsNone then + // zip.BeginUpdate() + // zip.Delete entry + // target.Seek(0L, SeekOrigin.Begin) |> ignore + + // let source = + // { new IStaticDataSource with + // member self.GetSource() = target } + + // zip.Add(source, entryName) + // zip.CommitUpdate() + + // result + // finally + // zip.Close() + // with :? ZipException -> + // use reader = new MemoryStream() + // I.doFlush postProcess pointProcess own counts format reader target + +#endif // !RUNNER } } \ No newline at end of file diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index 785ff6a3..a110c4bb 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -16,6 +16,7 @@ open Microsoft.FSharp.Reflection open Mono.Options #nowarn "25" // partial pattern match +#nowarn "3559" // TODO module AltCoverUsage = let internal usageText = @@ -65,25 +66,25 @@ module AltCoverRunnerTests = let MaxTimeFirst () = let now = DateTime.Now let ago = now - TimeSpan(1, 0, 0, 0) - test <@ (Counter.I.maxTime now ago) = now @> + test <@ (Counter.I.maxTime (now, ago)) = now @> [] let MaxTimeLast () = let now = DateTime.Now let ago = now - TimeSpan(1, 0, 0, 0) - test <@ (Counter.I.maxTime ago now) = now @> + test <@ (Counter.I.maxTime (ago, now)) = now @> [] let MinTimeFirst () = let now = DateTime.Now let ago = now - TimeSpan(1, 0, 0, 0) - test <@ (Counter.I.minTime ago now) = ago @> + test <@ (Counter.I.minTime (ago, now)) = ago @> [] let MinTimeLast () = let now = DateTime.Now let ago = now - TimeSpan(1, 0, 0, 0) - test <@ (Counter.I.minTime now ago) = ago @> + test <@ (Counter.I.minTime (now, ago)) = ago @> [] let JunkUspidGivesNegativeIndex () = @@ -91,7 +92,7 @@ module AltCoverRunnerTests = let key = " " let index = - Counter.I.findIndexFromUspid 0 key + Counter.I.findIndexFromUspid(0, key) test <@ index < 0 @> @@ -105,7 +106,7 @@ module AltCoverRunnerTests = visits.Add(" ", Dictionary()) let key = " " - let v1 = Counter.addVisit visits key 23 (new Null()) + let v1 = Counter.addVisit(visits, key, 23, new Null()) Assert.That(v1, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) Assert.That(visits.[key].Count, Is.EqualTo 1) @@ -126,7 +127,7 @@ module AltCoverRunnerTests = let payload = Time DateTime.UtcNow.Ticks let v2 = - Counter.addVisit visits key 23 payload + Counter.addVisit(visits, key, 23, payload) Assert.That(v2, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) @@ -146,11 +147,11 @@ module AltCoverRunnerTests = visits.Add("key", Dictionary()) let key = " " - let v3 = Counter.addVisit visits key 23 (new Null()) + let v3 = Counter.addVisit (visits, key, 23, new Null()) Assert.That(v3, Is.EqualTo 1) let v4 = - Counter.addVisit visits "key" 42 (new Null()) + Counter.addVisit (visits, "key", 42, new Null()) Assert.That(visits.Count, Is.EqualTo 2) Assert.That(v4, Is.EqualTo 1) @@ -165,9 +166,9 @@ module AltCoverRunnerTests = visits.Add(" ", Dictionary()) let key = " " - let v5 = Counter.addVisit visits key 23 (new Null()) + let v5 = Counter.addVisit(visits, key, 23, new Null()) Assert.That(v5, Is.EqualTo 1) - let v6 = Counter.addVisit visits key 42 (new Null()) + let v6 = Counter.addVisit(visits, key, 42, new Null()) Assert.That(v6, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) Assert.That(visits.[key].Count, Is.EqualTo 2) @@ -182,9 +183,9 @@ module AltCoverRunnerTests = visits.Add(" ", Dictionary()) let key = " " - let v7 = Counter.addVisit visits key 23 (new Null()) + let v7 = Counter.addVisit(visits, key, 23, new Null()) Assert.That(v7, Is.EqualTo 1) - let v8 = Counter.addVisit visits key 23 (new Null()) + let v8 = Counter.addVisit(visits, key, 23, new Null()) Assert.That(v8, Is.EqualTo 1) let x = visits.[key].[23] Assert.That(x.Count, Is.EqualTo 2) @@ -201,11 +202,11 @@ module AltCoverRunnerTests = let key = " " let payload = Time DateTime.UtcNow.Ticks - let v9 = Counter.addVisit visits key 23 (new Null()) + let v9 = Counter.addVisit(visits, key, 23, new Null()) Assert.That(v9, Is.EqualTo 1) let v10 = - Counter.addVisit visits key 23 payload + Counter.addVisit(visits, key, 23, payload) Assert.That(v10, Is.EqualTo 1) let x = visits.[key].[23] @@ -263,13 +264,13 @@ module AltCoverRunnerTests = item.Add("7C-CD-66-29-A3-6C-6D-5F-A7-65-71-0E-22-7D-B2-61-B5-1F-65-9A", payload) Counter.I.updateReport - ignore - (fun _ _ -> ()) - true - item - ReportFormat.OpenCover - worker - worker2 + (ignore, + (fun _ _ -> ()), + true, + item, + ReportFormat.OpenCover, + worker, + worker2) |> ignore worker2.Position <- 0L @@ -2586,7 +2587,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit counts moduleId hitPointId hit + AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) |> ignore) // degenerate case @@ -2709,7 +2710,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit counts moduleId hitPointId hit + AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) |> ignore) let entries = Dictionary() @@ -2833,7 +2834,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit counts moduleId hitPointId hit + AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) |> ignore) // degenerate case 1 @@ -3007,7 +3008,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit counts moduleId hitPointId hit + AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) |> ignore) let entries = Dictionary() @@ -3152,7 +3153,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit counts moduleId hitPointId hit + AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) |> ignore) // degenerate case @@ -3279,7 +3280,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit counts moduleId hitPointId hit + AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) |> ignore) let entries = Dictionary() @@ -3415,7 +3416,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit counts moduleId hitPointId hit + AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) |> ignore) // degenerate case 1 @@ -3597,7 +3598,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit counts moduleId hitPointId hit + AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) |> ignore) let entries = Dictionary() diff --git a/Build/actions.fs b/Build/actions.fs index c7e1c197..92d37f5f 100644 --- a/Build/actions.fs +++ b/Build/actions.fs @@ -125,6 +125,7 @@ using System.Runtime.CompilerServices; #if DEBUG [assembly: AssemblyConfiguration("Debug {0}")] [assembly: InternalsVisibleTo("AltCover.Tests, PublicKey={1}")] +[assembly: InternalsVisibleTo("AltCover.Api.Tests, PublicKey={1}")] [assembly: InternalsVisibleTo("AltCover.Monitor.Tests, PublicKey={1}")] [assembly: InternalsVisibleTo("AltCover.Recorder.Tests, PublicKey={1}")] [assembly: InternalsVisibleTo("AltCover.Recorder2.Tests, PublicKey={1}")] From 9a6d34d7b3f868fd5d6a39031db91e3d4b32a070 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 4 Jul 2024 10:06:04 +0100 Subject: [PATCH 33/91] Formatting --- AltCover.Engine/Runner.fs | 17 +++--- AltCover.Tests/Runner.Tests.fs | 100 ++++++++++++++++++++------------- 2 files changed, 71 insertions(+), 46 deletions(-) diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index bd0cb896..83d19302 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1031,7 +1031,7 @@ module internal Runner = | Tag.Both -> let time = formatter.ReadInt64() let call = formatter.ReadInt32() - Both (Pair.Create(time, call)) + Both(Pair.Create(time, call)) | Tag.Table -> let t = Dictionary>() @@ -1075,7 +1075,7 @@ module internal Runner = pv.Tracks.Add( let time = formatter.ReadInt64() let call = formatter.ReadInt32() - Both (Pair.Create(time, call)) + Both(Pair.Create(time, call)) ) tracking () @@ -1104,7 +1104,7 @@ module internal Runner = key |> String.IsNullOrWhiteSpace |> not || ((String.IsNullOrEmpty key) && hitPointId = 0 - && visit.GetType()= typeof) + && visit.GetType() = typeof) then if hits.ContainsKey key |> not @@ -1112,7 +1112,7 @@ module internal Runner = then hits.Add(key, Dictionary()) - Counter.addVisit(hits, key, hitPointId, visit) + Counter.addVisit (hits, key, hitPointId, visit) else 0L @@ -1189,7 +1189,7 @@ module internal Runner = let internal extractTracks tracks = tracks - |> Seq.map (fun (t:Track) -> + |> Seq.map (fun (t: Track) -> match t with | :? Time as x -> (Some x.Value, None) | :? Both as b -> (Some b.Value.Time, Some b.Value.Call) @@ -1391,14 +1391,15 @@ module internal Runner = | _ -> new MemoryStream() :> Stream let result = - AltCover.Counter.doFlushStream - ((postProcess hits format), + AltCover.Counter.doFlushStream ( + (postProcess hits format), pointProcess, true, hits, format, file, - outputFile) + outputFile + ) match arg with | None -> () diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index a110c4bb..dceda16c 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -92,7 +92,7 @@ module AltCoverRunnerTests = let key = " " let index = - Counter.I.findIndexFromUspid(0, key) + Counter.I.findIndexFromUspid (0, key) test <@ index < 0 @> @@ -106,7 +106,10 @@ module AltCoverRunnerTests = visits.Add(" ", Dictionary()) let key = " " - let v1 = Counter.addVisit(visits, key, 23, new Null()) + + let v1 = + Counter.addVisit (visits, key, 23, new Null()) + Assert.That(v1, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) Assert.That(visits.[key].Count, Is.EqualTo 1) @@ -127,7 +130,7 @@ module AltCoverRunnerTests = let payload = Time DateTime.UtcNow.Ticks let v2 = - Counter.addVisit(visits, key, 23, payload) + Counter.addVisit (visits, key, 23, payload) Assert.That(v2, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) @@ -147,7 +150,10 @@ module AltCoverRunnerTests = visits.Add("key", Dictionary()) let key = " " - let v3 = Counter.addVisit (visits, key, 23, new Null()) + + let v3 = + Counter.addVisit (visits, key, 23, new Null()) + Assert.That(v3, Is.EqualTo 1) let v4 = @@ -166,9 +172,15 @@ module AltCoverRunnerTests = visits.Add(" ", Dictionary()) let key = " " - let v5 = Counter.addVisit(visits, key, 23, new Null()) + + let v5 = + Counter.addVisit (visits, key, 23, new Null()) + Assert.That(v5, Is.EqualTo 1) - let v6 = Counter.addVisit(visits, key, 42, new Null()) + + let v6 = + Counter.addVisit (visits, key, 42, new Null()) + Assert.That(v6, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) Assert.That(visits.[key].Count, Is.EqualTo 2) @@ -183,9 +195,15 @@ module AltCoverRunnerTests = visits.Add(" ", Dictionary()) let key = " " - let v7 = Counter.addVisit(visits, key, 23, new Null()) + + let v7 = + Counter.addVisit (visits, key, 23, new Null()) + Assert.That(v7, Is.EqualTo 1) - let v8 = Counter.addVisit(visits, key, 23, new Null()) + + let v8 = + Counter.addVisit (visits, key, 23, new Null()) + Assert.That(v8, Is.EqualTo 1) let x = visits.[key].[23] Assert.That(x.Count, Is.EqualTo 2) @@ -202,11 +220,14 @@ module AltCoverRunnerTests = let key = " " let payload = Time DateTime.UtcNow.Ticks - let v9 = Counter.addVisit(visits, key, 23, new Null()) + + let v9 = + Counter.addVisit (visits, key, 23, new Null()) + Assert.That(v9, Is.EqualTo 1) let v10 = - Counter.addVisit(visits, key, 23, payload) + Counter.addVisit (visits, key, 23, payload) Assert.That(v10, Is.EqualTo 1) let x = visits.[key].[23] @@ -263,14 +284,15 @@ module AltCoverRunnerTests = item.Add("7C-CD-66-29-A3-6C-6D-5F-A7-65-71-0E-22-7D-B2-61-B5-1F-65-9A", payload) - Counter.I.updateReport - (ignore, + Counter.I.updateReport ( + ignore, (fun _ _ -> ()), true, item, ReportFormat.OpenCover, worker, - worker2) + worker2 + ) |> ignore worker2.Position <- 0L @@ -2688,9 +2710,9 @@ module AltCoverRunnerTests = let tracks t : Track array = [| Null() :> Track - Call (0) :> Track - Time (t) :> Track - Both (Pair.Create(t, 0)) |] + Call(0) :> Track + Time(t) :> Track + Both(Pair.Create(t, 0)) |] let t0 = tracks 0L @@ -2986,9 +3008,9 @@ module AltCoverRunnerTests = let tracks t : Track array = [| Null() :> Track - Call (0) :> Track - Time (t) :> Track - Both (Pair.Create(t, 0)) |] + Call(0) :> Track + Time(t) :> Track + Both(Pair.Create(t, 0)) |] let t0 = tracks 0L @@ -3258,9 +3280,9 @@ module AltCoverRunnerTests = let tracks t : Track array = [| Null() :> Track - Call (0) :> Track - Time (t) :> Track - Both (Pair.Create(t, 0)) |] + Call(0) :> Track + Time(t) :> Track + Both(Pair.Create(t, 0)) |] let t0 = tracks 0L @@ -3576,9 +3598,9 @@ module AltCoverRunnerTests = let tracks t : Track array = [| Null() :> Track - Call (0) :> Track - Time (t) :> Track - Both (Pair.Create(t, 0)) |] + Call(0) :> Track + Time(t) :> Track + Both(Pair.Create(t, 0)) |] let t0 = tracks 0L @@ -3897,12 +3919,12 @@ module AltCoverRunnerTests = Path.Combine(where, Guid.NewGuid().ToString()) let payloads0 = - [ Null () :> Track - Call (17) :> Track - Time (23L) :> Track - Both (Pair.Create(5, 42)) :> Track - Time (42L) :> Track - Call (5) :> Track ] + [ Null() :> Track + Call(17) :> Track + Time(23L) :> Track + Both(Pair.Create(5, 42)) :> Track + Time(42L) :> Track + Call(5) :> Track ] let pv = init 42L (payloads0 |> List.tail) @@ -3911,7 +3933,9 @@ module AltCoverRunnerTests = table.Add("Extra", Dictionary()) table.["Extra"].Add(3, pv) - let payloads = ((Table table) :> Track) :: payloads0 + + let payloads = + ((Table table) :> Track) :: payloads0 let inputs = [ String.Empty @@ -4012,7 +4036,7 @@ module AltCoverRunnerTests = let d = Dictionary() - d.Add(4, (0L, [ Both (Pair.Create(5, 42)) ])) + d.Add(4, (0L, [ Both(Pair.Create(5, 42)) ])) let e = Dictionary() @@ -4060,11 +4084,11 @@ module AltCoverRunnerTests = let hits = [ Null() :> Track - Call (17) :> Track - Time (23L) :> Track - Both (Pair.Create(5, 42)) :> Track - Time (42L) :> Track - Time (5L) :> Track ] + Call(17) :> Track + Time(23L) :> Track + Both(Pair.Create(5, 42)) :> Track + Time(42L) :> Track + Time(5L) :> Track ] Runner.J.pointProcess root hits From 7eddb730a6e8e28d2923bab79541a58881ce558c Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 4 Jul 2024 10:06:33 +0100 Subject: [PATCH 34/91] Engage with static analysis for base --- Build/targets.fs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Build/targets.fs b/Build/targets.fs index 8e81dfef..293772c6 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -1140,7 +1140,8 @@ module Targets = Directory.ensure "./_Reports" [ ("./Build/common-rules.xml", - [ "_Binaries/AltCover.Engine/Debug+AnyCPU/netstandard2.0/AltCover.Engine.dll" ]) + [ "_Binaries/AltCover.Engine/Debug+AnyCPU/netstandard2.0/AltCover.Engine.dll" + "_Binaries/AltCover.Base/Debug+AnyCPU/netstandard2.0/AltCover.Base.dll" ]) ("./Build/build-rules.xml", [ "$Binaries/Setup/Debug+AnyCPU/net8.0/Setup.dll" "$Binaries/Build/Debug+AnyCPU/net8.0/Build.dll" ]) @@ -1406,7 +1407,8 @@ module Targets = defaultRules) (dixon, Option.get refdir, - [ "_Binaries/AltCover.Engine/Debug+AnyCPU/netstandard2.0/AltCover.Engine.dll" ], + [ "_Binaries/AltCover.Base/Debug+AnyCPU/netstandard2.0/AltCover.Base.dll" + "_Binaries/AltCover.Engine/Debug+AnyCPU/netstandard2.0/AltCover.Engine.dll" ], [], List.concat [ defaultRules @@ -1794,11 +1796,9 @@ module Targets = Framework = Some "net8.0" } |> (buildWithCLITaggedArguments "UnitTestDotNet")) - !!(@"./*Test*/*Tests.fsproj") - |> Seq.iter buildIt + !!(@"./*Test*/*Tests.fsproj") |> Seq.iter buildIt - !!(@"./*Test*/*Tests.csproj") - |> Seq.iter buildIt + !!(@"./*Test*/*Tests.csproj") |> Seq.iter buildIt !!(@"./*.Valid*/*Valid*.fsproj") |> Seq.iter buildIt) From fc40b18f88024e9a58de14cf4afd9c58607c6a9b Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 4 Jul 2024 12:27:33 +0100 Subject: [PATCH 35/91] That fixes a bunch of tests --- AltCover.Recorder/Base.cs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index bd81da83..be7dd5a8 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -362,8 +362,24 @@ internal static int findIndexFromUspid(int flag, string uspid) return f ? (c | flag) : -1; } - internal static void ensurePoint(Dictionary next, int hitPointId) - { } + internal static void ensurePoint(Dictionary counts, int hitPointId) + { + if (!counts.ContainsKey(hitPointId)) + { + lock (counts) + { + if (!counts.ContainsKey(hitPointId)) + { + System.Threading.Interlocked.Increment(ref Counter.totalVisits); + + if (hitPointId < 0) + { System.Threading.Interlocked.Increment(ref Counter.branchVisits); } + + counts.Add(hitPointId, PointVisit.Create()); + } + } + } + } internal static long addTable( Dictionary> counts, From 124fbb80745210d3c8cb885d4364b63dc9d49fa1 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 4 Jul 2024 12:47:14 +0100 Subject: [PATCH 36/91] Implementing that fixes more --- AltCover.Recorder/Base.cs | 46 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index be7dd5a8..095e66f2 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -387,31 +387,29 @@ Dictionary> t ) { long hitcount = 0; - //let internal addTable - // (counts: Dictionary>) - // (t: Dictionary>) - // = - // let mutable hitcount = 0L - - // t.Keys - // |> Seq.iter (fun m -> - // if counts.ContainsKey m |> not then - // counts.Add(m, Dictionary()) - - // let next = counts.[m] - // let here = t.[m] - - // here.Keys - // |> Seq.iter (fun p -> - // ensurePoint next p - // let mutable v = next.[p] - // let add = here.[p] - // hitcount <- hitcount + add.Total - - // lock v (fun () -> - // v.Count <- v.Count + add.Count - // v.Tracks.AddRange(add.Tracks)))) + foreach (var key in t.Keys) + { + if (!counts.ContainsKey(key)) + { + counts.Add(key, new Dictionary()); + var next = counts[key]; + var here = t[key]; + + foreach (var p in here.Keys) + { + ensurePoint(next, p); + var v = next[p]; + var add = here[p]; + hitcount += add.Total; + lock (v) + { + v.Count += add.Count; + v.Tracks.AddRange(add.Tracks); + } + } + } + } return hitcount; } From 493e976136e89ab9d40e99735023fe66a863874a Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 4 Jul 2024 13:50:37 +0100 Subject: [PATCH 37/91] A bit more reimplementation --- AltCover.Recorder/Base.cs | 211 +++++++++++++++++++++++++++++++++----- 1 file changed, 188 insertions(+), 23 deletions(-) diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 095e66f2..7fa5f796 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -318,21 +318,38 @@ internal static class I static private class I #endif { - // let internal openCoverXml = - // ("//Module", - // "hash", - // "Classes/Class/Methods/Method", - // [ ("SequencePoints/SequencePoint", 0) - // ("BranchPoints/BranchPoint", branchFlag) ], - // "vc") - - //let internal IEnumerable nCoverXml = - // ("//module", "moduleId", "method", [ ("seqpnt", 0)], "visitcount") - internal static readonly object openCoverXml = "//Module";//TODO - - internal static readonly object nCoverXml = "//module";//TODO + internal struct coverXml + { + internal string m; + internal string i; + internal string m2; + internal Dictionary s; + internal string v; + } - internal static object xmlByFormat(ReportFormat format) + internal static readonly coverXml openCoverXml = + new coverXml() + { + m = "//Module", + i = "hash", + m2 = "Classes/Class/Methods/Method", + s = new Dictionary { { "SequencePoints/SequencePoint", 0 }, + { "BranchPoints/BranchPoint", branchFlag } + }, + v = "vc" + }; + + internal static readonly coverXml nCoverXml = + new coverXml() + { + m = "//module", + i = "moduleId", + m2 = "method", + s = new Dictionary { { "seqpnt", 0 } }, + v = "visitcount" + }; + + internal static coverXml xmlByFormat(ReportFormat format) { switch (format & ReportFormat.TrackMask) { @@ -413,6 +430,46 @@ Dictionary> t return hitcount; } + // TODO inline in release if possible + internal static IEnumerable selectNodes(XmlNode node, string name) + { + var result = new List(); + foreach (var x in node.SelectNodes(name)) + result.Add(x as XmlElement); + return result; + } + + // // + // // Load the XDocument + // // + // // The XML file to load + // // Idiom to work with CA2202; we still double dispose the stream, but elude the rule. + // // If this is ever a problem, we will need mutability and two streams, with explicit + // // stream disposal if and only if the reader or writer doesn't take ownership + // // Approved way is ugly -- https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2202?view=vs-2019 + // // Also, this rule is deprecated + // // + private static XmlDocument readXDocument(Stream stream) + { + var doc = new XmlDocument(); + + try + { doc.Load(stream); } + catch (XmlException) + { doc.LoadXml(""); } + + return doc; + } + + // // + // // Write the XDocument + // // + // // The XML document to write + // // The XML file to write to + // // Idiom to work with CA2202 as above + private static void writeXDocument(XmlDocument coverageDocument, Stream stream) + { coverageDocument.Save(stream); } + public static DateTime updateReport( Action postProcess, /*Action>*/ object pointProcess, @@ -424,21 +481,129 @@ Stream outputFile ) { var flushStart = DateTime.UtcNow; - // let flushStart = - // updateReport postProcess pointProcess own counts format coverageFile outputFile + var xmlformat = xmlByFormat(format);// throw early on unsupported + //let (m, i, m', s, v) + + var coverageDocument = readXDocument(coverageFile); + + var root = coverageDocument.DocumentElement; + + var startTimeNode = root.GetAttributeNode("startTime"); + + if ((format == ReportFormat.NCover) && !Object.ReferenceEquals(startTimeNode, null)) + { + //then + // let startTimeAttr = startTimeNode.Value + + // let measureTimeAttr = + // root.GetAttribute("measureTime") + + // let oldStartTime = + // DateTime.ParseExact(startTimeAttr, "o", null) + + // let oldMeasureTime = + // DateTime.ParseExact(measureTimeAttr, "o", null) + + // let st = minTime startTime oldStartTime + // startTime <- st.ToUniversalTime() // Min + // let mt = maxTime measureTime oldMeasureTime + // measureTime <- mt.ToUniversalTime() // Max + + // root.SetAttribute( + // "startTime", + // startTime.ToString("o", System.Globalization.CultureInfo.InvariantCulture) + // ) + + // root.SetAttribute( + // "measureTime", + // measureTime.ToString("o", System.Globalization.CultureInfo.InvariantCulture) + // ) + + // root.SetAttribute( + // "driverVersion", + // "AltCover.Recorder " + // + System.Diagnostics.FileVersionInfo + // .GetVersionInfo( + // System.Reflection.Assembly + // .GetExecutingAssembly() + // .Location + // ) + // .FileVersion + // ) + } + + var moduleNodes = selectNodes(coverageDocument, xmlformat.m); + + //moduleNodes + //|> Seq.cast + //|> Seq.map (fun el -> el.GetAttribute(i), el) + //|> Seq.filter (fun (k, _) -> counts.ContainsKey k) + //|> Seq.iter (fun (k, affectedModule) -> + // let moduleHits = counts.[k] + // // Don't do this in one leap like -- + // // affectedModule.Descendants(XName.Get("seqpnt")) + // // Get the methods, then flip their + // // contents before concatenating + // let nn = selectNodes affectedModule m' + + // nn + // |> Seq.cast + // |> Seq.collect (fun (method: XmlElement) -> + // s + // |> Seq.collect (fun (name, flag) -> + // let nodes = selectNodes method name + + // nodes + // |> Seq.cast + // |> Seq.map (fun x -> (x, flag)) + // |> Seq.toList + // |> List.rev)) + // |> Seq.mapi (fun counter (pt, flag) -> + // ((match format &&& ReportFormat.TrackMask with + // | ReportFormat.OpenCover -> + // "uspid" + // |> pt.GetAttribute + // |> (findIndexFromUspid flag) + // | _ -> counter), + // pt)) + // |> Seq.filter (fst >> moduleHits.ContainsKey) + // |> Seq.iter (fun x -> + // let pt = snd x + // let counter = fst x + + // let vc = + // Int64.TryParse( + // pt.GetAttribute(v), + // System.Globalization.NumberStyles.Integer, + // System.Globalization.CultureInfo.InvariantCulture + // ) + // |> snd + // // Treat -ve visit counts (an exemption added in analysis) as zero + // let count = moduleHits.[counter] + // let visits = (max 0L vc) + count.Total + // pt.SetAttribute(v, visits.ToString(CultureInfo.InvariantCulture)) + // pointProcess pt count.Tracks)) + + postProcess(coverageDocument); + + // Save modified xml to a file + outputFile.Seek(0L, SeekOrigin.Begin); + outputFile.SetLength(0); + + if (own) + { writeXDocument(coverageDocument, outputFile); } - // TimeSpan(DateTime.UtcNow.Ticks - flushStart.Ticks) return flushStart; } public static TimeSpan doFlush( - Action postProcess, + Action postProcess, /*Action>*/ object pointProcess, - bool own, - Dictionary> counts, - ReportFormat format, - Stream coverageFile, - Stream outputFile + bool own, + Dictionary> counts, + ReportFormat format, + Stream coverageFile, + Stream outputFile ) { var flushStart = From 8020b2bfbd8160cdf1be55c19d551852bb073478 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 12 Jul 2024 17:56:38 +0100 Subject: [PATCH 38/91] Revert to F# tests, just not built at net20 - breaks as API isn't there yet --- ....csproj => AltCover.Recorder.Tests.fsproj} | 19 +++++++++----- AltCover.Recorder.Tests/Tracer.Tests.fs | 3 --- AltCover.Recorder/Recorder.cs | 25 +++++++++++++++++-- ...csproj => AltCover.Recorder2.Tests.fsproj} | 19 ++++++++------ AltCover.sln | 4 +-- 5 files changed, 49 insertions(+), 21 deletions(-) rename AltCover.Recorder.Tests/{AltCover.Recorder.Tests.csproj => AltCover.Recorder.Tests.fsproj} (78%) rename AltCover.Recorder2.Tests/{AltCover.Recorder2.Tests.csproj => AltCover.Recorder2.Tests.fsproj} (75%) diff --git a/AltCover.Recorder.Tests/AltCover.Recorder.Tests.csproj b/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj similarity index 78% rename from AltCover.Recorder.Tests/AltCover.Recorder.Tests.csproj rename to AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj index a3440c96..3ed9d505 100644 --- a/AltCover.Recorder.Tests/AltCover.Recorder.Tests.csproj +++ b/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj @@ -1,12 +1,12 @@  - net8.0;net472;net20 + net8.0;net472 false AltCover.Recorder.Tests false - NU1702;CS1591 + NU1702 NU1702 --keyfile:$(InfrastructureKey) @@ -19,10 +19,14 @@ - - AssemblyVersion.cs + + AssemblyVersion.fs - + + + + + @@ -58,7 +62,10 @@ - + + + contentfiles + \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Tracer.Tests.fs b/AltCover.Recorder.Tests/Tracer.Tests.fs index 920a9c4e..f4b2ea2d 100644 --- a/AltCover.Recorder.Tests/Tracer.Tests.fs +++ b/AltCover.Recorder.Tests/Tracer.Tests.fs @@ -399,9 +399,6 @@ module AltCoverCoreTests = Assert.That(Instance.I.trace.Equals expected, Is.False) Assert.True(Instance.I.trace.IsConnected, "connection failed") - let formatter = - System.Runtime.Serialization.Formatters.Binary.BinaryFormatter() - let (a, b, c) = expected |> Seq.head Adapter.tracePush (a, b, c) Instance.FlushFinish() diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index daebbc24..a6e29bee 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -11,11 +11,32 @@ namespace AltCover.Recorder using System.Runtime.CompilerServices; #if !NET20 -using System.Threading; + using System.Threading; #endif //using AltCover.Shared; public static class Instance - { } + { + // Public "fields" + + /// + /// Gets the location of coverage xml file + /// This property's IL code is modified to store the actual file location + /// + public static string ReportFile + { + [MethodImpl(MethodImplOptions.NoInlining)] + get { return "Coverage.Default.xml"; } + } + +#if DEBUG + + internal static class I +#else + private static class I +#endif + { + } + } } \ No newline at end of file diff --git a/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.csproj b/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj similarity index 75% rename from AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.csproj rename to AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj index 3bca1800..303ea2b2 100644 --- a/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.csproj +++ b/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj @@ -5,7 +5,7 @@ false AltCover.Recorder2.Tests false - NU1702;CS1591 + NU1702 NU1702 --keyfile:$(InfrastructureKey) @@ -20,14 +20,14 @@ - - AssemblyVersion.cs + + AssemblyVersion.fs - - - - - + + + + + @@ -42,6 +42,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + + contentfiles + diff --git a/AltCover.sln b/AltCover.sln index f695fe6c..07440fce 100644 --- a/AltCover.sln +++ b/AltCover.sln @@ -151,9 +151,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample25", "Samples\Sample2 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AltCover.Recorder", "AltCover.Recorder\AltCover.Recorder.csproj", "{5D4A7DFE-688D-4D1B-804C-A06743FFC4BC}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AltCover.Recorder.Tests", "AltCover.Recorder.Tests\AltCover.Recorder.Tests.csproj", "{6DCDCA5E-3174-4C0B-996A-F7E4E455F889}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.Recorder.Tests", "AltCover.Recorder.Tests\AltCover.Recorder.Tests.fsproj", "{6DCDCA5E-3174-4C0B-996A-F7E4E455F889}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AltCover.Recorder2.Tests", "AltCover.Recorder2.Tests\AltCover.Recorder2.Tests.csproj", "{2079F388-81AE-4A76-9428-3C8D7F86825B}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AltCover.Recorder2.Tests", "AltCover.Recorder2.Tests\AltCover.Recorder2.Tests.fsproj", "{2079F388-81AE-4A76-9428-3C8D7F86825B}" ProjectSection(ProjectDependencies) = postProject {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC} = {5D4A7DFE-688D-4D1B-804C-A06743FFC4BC} EndProjectSection From 66a10fa0d9566c69820af368b80e0f969ab6cda4 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 12 Jul 2024 18:20:22 +0100 Subject: [PATCH 39/91] Incremental API clearing --- AltCover.Recorder.Tests/Adapter.fs | 4 +- AltCover.Recorder/Recorder.cs | 513 +++++++++++++++++++++++++++++ 2 files changed, 515 insertions(+), 2 deletions(-) diff --git a/AltCover.Recorder.Tests/Adapter.fs b/AltCover.Recorder.Tests/Adapter.fs index eb3e7a9c..74d55116 100644 --- a/AltCover.Recorder.Tests/Adapter.fs +++ b/AltCover.Recorder.Tests/Adapter.fs @@ -37,8 +37,8 @@ module Adapter = Instance.I.visits.Add(name, entry) let internal init (n, l) = - let tmp = - { PointVisit.Create() with Count = n } + let tmp = PointVisit.Create() + tmp.Count <- n tmp.Tracks.AddRange l tmp diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index a6e29bee..3d85aed9 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -2,16 +2,23 @@ namespace AltCover.Recorder { using System; using System.Collections.Generic; + using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; + using System.Drawing; using System.IO; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.Remoting.Contexts; + using System.Security.Policy; + using System.Text.RegularExpressions; #if !NET20 using System.Threading; + using static System.Net.Mime.MediaTypeNames; #endif //using AltCover.Shared; @@ -30,6 +37,95 @@ public static string ReportFile get { return "Coverage.Default.xml"; } } + // let ReportFilePath = + // Path.Combine( + // Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), + // ReportFile + // ) + // |> AltCover.Canonical.canonicalPath + + // /// + // /// Gets whether to defer output until process exit + // /// This property's IL code is modified to store the actual value + // /// + // [< MethodImplAttribute(MethodImplOptions.NoInlining) >] + // let Defer = false + + // /// + // /// Gets the style of the associated report + // /// This property's IL code is modified to store the user chosen override if applicable + // /// + // [< MethodImplAttribute(MethodImplOptions.NoInlining) >] + // [< SuppressMessage("Gendarme.Rules.Performance", + // "AvoidUncalledPrivateCodeRule", + // Justification = "Unit test accessor") >] + // [< SuppressMessage("Gendarme.Rules.Naming", + // "UseCorrectCasingRule", + // Justification = "Code rewritten") >] + // let + //#if DEBUG + // mutable + //#endif + // internal CoverageFormat = // fsharplint:disable-line NonPublicValuesNames + // ReportFormat.NCover + + // /// + // /// Gets the frequency of time sampling + // /// This property's IL code is modified to store the user chosen override if applicable + // /// + // [< MethodImplAttribute(MethodImplOptions.NoInlining) >] + // let Timer = 0L + + // /// + // /// Gets the sampling strategy + // /// This property's IL code is modified to store the user chosen override if applicable + // /// + // [] + // let internal Sample = Sampling.All // fsharplint:disable-line NonPublicValuesNames + + // /// + // /// Gets the unique token for this instance + // /// This property's IL code is modified to store a GUID-based token + // /// + // [< MethodImplAttribute(MethodImplOptions.NoInlining) >] + // let Token = "AltCover" + + // /// + // /// Gets the indexed module tokens + // /// This property's IL code is modified to store instrumentation results + // /// + // [] + // [] + + internal static IEnumerable modules; + // [] + // let mutable internal modules = + // [| String.Empty |] + + // [] + // let mutable internal supervision = + // //Assembly.GetExecutingAssembly().GetName().Name = "AltCover.Recorder.g" && + // AppDomain.CurrentDomain.GetAssemblies() + // |> Seq.map(fun a -> a.GetName()) + // |> Seq.exists(fun n -> + // n.Name == "AltCover.DataCollector" + // && n.FullName.EndsWith("PublicKeyToken=c02b1a9f5b7cade8", StringComparison.Ordinal)) + // && Token<> "AltCover" + + internal abstract class Sampled + { } + + // type internal Sampled = + // | Visit of int + // | CallVisit of(int* int) + // | TimeVisit of(int* int64) + #if DEBUG internal static class I @@ -37,6 +133,423 @@ internal static class I private static class I #endif { + // let internal resources = + // ResourceManager("AltCover.Recorder.Strings", Assembly.GetExecutingAssembly()) + + // let internal getResource s = + // let cc = + // System.Globalization.CultureInfo.CurrentUICulture + + // [cc.Name; cc.Parent.Name; "en" ] + // |> Seq.map(fun l -> resources.GetString(s + "." + l)) + // |> Seq.tryFind(String.IsNullOrEmpty >> not) + + internal static Dictionary> makeVisits() + { + return default; + } + + // let private makeVisits() = + // [modules + // [| Track.Entry; Track.Exit |] ] + // |> Seq.concat + // |> Seq.fold + // (fun (d: Dictionary>) k -> + // d.Add(k, Dictionary()) + // d) + // (Dictionary>()) + + /// + /// Accumulation of visit records + /// + internal static Dictionary> visits = makeVisits(); + + internal static Dictionary> makeSamples() + { + return default; + } + + // let internal makeSamples() = + // modules + // |> Seq.fold + // (fun (d: Dictionary>) k -> + // d.Add(k, Dictionary()) + // d) + // (Dictionary>()) + + internal static Dictionary> samples = makeSamples(); + + internal static bool isRunner = false; + + // let internal synchronize = Object() + + //#if NET20 + // // class needed for "[ThreadStatic] static val mutable" + // [] + // type private AsyncLocal<'a>() = + // [] + // static val mutable private item: 'a + + // [] + // member this.Value + // with get () = AsyncLocal<'a>.item + // and set (value) = AsyncLocal<'a>.item <- value + //#endif + + // /// + // /// Gets or sets the current test method + // /// + // module private CallTrack = + // let value = AsyncLocal>() + + // // no race conditions here + // let instance() = + // match value.Value with + // | null -> value.Value<- Stack() + // | _ -> () + + // value.Value + + // let private look op = + // let i = instance() + + // match i.Count with + // | 0 -> None + // | _ -> Some(op i) + + // let peek () = look(fun i->i.Peek()) + + // let push x = instance().Push x + + // let pop () = look(fun i->i.Pop()) + + // let internal callerId() = CallTrack.peek() + // let internal push x = CallTrack.push x + // let internal pop() = CallTrack.pop() + + // /// + // /// Serialize access to the report file across AppDomains for the classic mode + // /// + // let internal mutex = + // new System.Threading.Mutex(false, Token + ".mutex") + + // let internal signalFile() = ReportFilePath + ".acv" + + // /// + // /// Reporting back to the mother-ship + // /// + // let mutable internal trace = + // Tracer.Create(signalFile ()) + + // let internal withMutex(f: bool -> 'a) = + // let own = mutex.WaitOne(1000) + + // try + // f (own) + // finally + // if own then + // mutex.ReleaseMutex() + + // let internal initialiseTrace(t: Tracer) = + // withMutex(fun _ -> + // trace<- t.OnStart() + // isRunner <- isRunner || trace.IsConnected) + + // let internal watcher = + // new FileSystemWatcher() + + // let mutable internal recording = true + + internal static void clear() + { } + + // let internal clear() = + // visits<- makeVisits () + // Counter.branchVisits<- 0L + // Counter.totalVisits<- 0L + + // /// + // /// This method flushes hit count buffers. + // /// + // let internal flushAll _ = + // let counts = visits + // clear() + + // trace.OnConnected(fun () -> trace.OnFinish counts) (fun () -> + // match counts.Values |> Seq.sumBy (fun x -> x.Count) with + // | 0 -> () + // | _ -> + // withMutex(fun own -> + // let delta = + // Counter.doFlushFile + // ignore + // (fun _ _ -> ()) + // own + // counts + // CoverageFormat + // ReportFilePath + // None + + // getResource "Coverage statistics flushing took {0:N} seconds" + // |> Option.iter(fun s -> Console.Out.WriteLine(s, delta.TotalSeconds)))) + + // let internal flushPause() = + // ("PauseHandler") + // |> getResource + // |> Option.iter Console.Out.WriteLine + + // recording<- false + // flushAll Pause + // trace<- signalFile () |> Tracer.Create + + // let internal flushResume() = + // ("ResumeHandler") + // |> getResource + // |> Option.iter Console.Out.WriteLine + + // let wasConnected = isRunner + // initialiseTrace trace + + // if (wasConnected<> isRunner) then + // samples<- makeSamples () + // clear () + + // recording <- true + + // let internal traceVisit moduleId hitPointId context = + // lock synchronize(fun () -> + // let counts = visits + + // if counts.Values |> Seq.sumBy (fun x -> x.Count) > 0 then + // clear() + + // trace.OnVisit counts moduleId hitPointId context) + + // [] + // let internal logException moduleId hitPointId context x = + // let text = + // [| sprintf "ModuleId = %A" moduleId + // sprintf "hitPointId = %A" hitPointId + // sprintf "context = %A" context + // sprintf "exception = %s" (x.ToString()) + // StackTrace().ToString() |] + + // let stamp = + // sprintf "%A" DateTime.UtcNow.Ticks + + // let filename = + // ReportFilePath + "." + stamp + ".exn" + + // use file = + // File.Open(filename, FileMode.OpenOrCreate, FileAccess.Write) + + // use writer = new StreamWriter(file) + + // text + // |> Seq.iter(fun line -> writer.WriteLine("{0}", line)) + + // [] + + // let + //#if !DEBUG + // inline + //#endif + // internal issue71Wrapper + // visits + // moduleId + // hitPointId + // context + // handler + // add + // = + // try + // add visits moduleId hitPointId context + // with x -> + // match x with + // | :? KeyNotFoundException + // | :? NullReferenceException + // | :? ArgumentNullException -> handler moduleId hitPointId context x + // | _ -> reraise() + + // let + //#if !DEBUG + // inline + //#endif + // internal curriedIssue71Wrapper + // visits + // moduleId + // hitPointId + // context + // add + // = + // issue71Wrapper visits moduleId hitPointId context logException add + + // let internal addVisit moduleId hitPointId context = + // curriedIssue71Wrapper visits moduleId hitPointId context Counter.addSingleVisit + + // type InvalidDataException with + // [< SuppressMessage("Gendarme.Rules.Design.Generic", + // "AvoidMethodWithUnusedGenericTypeRule", + // Justification = "Matches clause type") >] + // static member Throw<'T>(message: obj) : 'T = + // message.ToString() + // |> InvalidDataException + // |> raise + + // let internal takeSample strategy moduleId hitPointId(context: Track) = + // match strategy with + // | Sampling.All -> true + // | _ -> + // (match context with + // | Null -> [Visit hitPointId] + // | Time t -> + // [Visit hitPointId + // TimeVisit(hitPointId, t)] + // | Call c -> + // [Visit hitPointId + // CallVisit(hitPointId, c)] + // | Both b -> + // [Visit hitPointId + // TimeVisit(hitPointId, b.Time) + // CallVisit(hitPointId, b.Call)] + // | _ -> context |> InvalidDataException.Throw) + // |> Seq.map(fun hit -> + // if samples.ContainsKey(moduleId) then + // let next = samples.[moduleId] + + // let mutable hasPointKey = + // next.ContainsKey(hit) + + // if hasPointKey |> not then + // lock next(fun () -> + // hasPointKey<- next.ContainsKey(hit) + + // if hasPointKey |> not then + // next.Add(hit, true)) + + // not hasPointKey + // else + // false) + // |> Seq.fold(||) false // true if any are novel -- all must be evaluated + + // /// + // /// This method is executed from instrumented assemblies. + // /// + // /// Assembly being visited + // /// Sequence Point identifier + // let internal visitImpl moduleId hitPointId context = + // if + // (Sample = Sampling.All + // || takeSample Sample moduleId hitPointId context) + // then + // let adder = + // if Defer || supervision || (trace.IsConnected |> not) then + // addVisit + // else + // traceVisit + + // adder moduleId hitPointId context + + // let internal isTracking() = + // (int (CoverageFormat &&& ReportFormat.WithTracking) + // <> 0) + + // let internal isTrackingRunner() = isTracking() && isRunner + + // let internal granularity() = Timer + // let internal clock() = DateTime.UtcNow.Ticks + + // let internal payloadSelection clock frequency wantPayload = + // if wantPayload() then + // match(frequency (), callerId ()) with + // | (0L, None) -> Null + // | (t, None) -> Time(t* (clock () / t)) + // | (0L, n) -> Call n.Value + // | (t, n) -> + // Both + // { + // Time = t * (clock() / t) + // Call = n.Value } + // else + // Null + + // let internal payloadControl = + // payloadSelection clock + + // let internal payloadSelector enable = payloadControl granularity enable + + // let internal visitSelection track moduleId hitPointId = + // visitImpl moduleId hitPointId track + + // let internal flushCounter(finish: Close) _ = + // match finish with + // | Resume -> flushResume() + // | Pause -> flushPause() + // | _ -> + // recording<- false + + // if supervision |> not then + // flushAll finish + + // Register event handling + internal static FileSystemEventHandler doPause = default; + + //(FileSystemEventHandlerfun _ a -> flushCounter Pause a) + + internal static FileSystemEventHandler doResume = default; + //FileSystemEventHandler(fun _ a -> flushCounter Resume a) + + internal static EventHandler doUnload = default; + //EventHandler(fun _ a -> flushCounter DomainUnload a) + + internal static EventHandler doExit = default; + //EventHandler(fun _ a -> flushCounter ProcessExit a) + + // let internal startWatcher() = + // watcher.Path<- Path.GetDirectoryName<| signalFile () + // watcher.Filter<- Path.GetFileName<| signalFile () + // watcher.add_Created doResume + // watcher.add_Deleted doPause + // watcher.EnableRaisingEvents<- watcher.Path |> String.IsNullOrEmpty |> not + + //do + // AppDomain.CurrentDomain.add_DomainUnload doUnload + // AppDomain.CurrentDomain.add_ProcessExit doExit + // startWatcher () + // signalFile () |> Tracer.Create |> initialiseTrace } + + // // Public API + // let Visit moduleId hitPointId = + // if I.recording then + // I.visitSelection + // (if I.isTracking() then + // I.payloadSelector I.isTrackingRunner + // else + // Null) + // moduleId + // hitPointId + + //// The moduleId strings are not the hash or guids normally found there + //let Push caller = + // I.push caller + + // if I.isTrackingRunner() then + // I.visitSelection(Time DateTime.UtcNow.Ticks) Track.Entry caller + + //let Pop() = + // let caller = I.pop() + + // if I.isTrackingRunner() && caller.IsSome then + // I.visitSelection(Time DateTime.UtcNow.Ticks) Track.Exit caller.Value + + //// Used by the datacollector + //let FlushFinish () = I.flushAll ProcessExit } } \ No newline at end of file From 00be3b5ffadffd86ab4fbe5faa688d7f6e3bf997 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 12 Jul 2024 18:34:21 +0100 Subject: [PATCH 40/91] More API --- AltCover.Recorder.Tests/Adapter.fs | 18 +++++++++--------- AltCover.Recorder/Recorder.cs | 7 +++++++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/AltCover.Recorder.Tests/Adapter.fs b/AltCover.Recorder.Tests/Adapter.fs index 74d55116..d515bba0 100644 --- a/AltCover.Recorder.Tests/Adapter.fs +++ b/AltCover.Recorder.Tests/Adapter.fs @@ -56,8 +56,8 @@ module Adapter = let v2 = init ( (number + 1L), - [ Time 17L - Both { Time = 42L; Call = 23 } ] + [ Time(17L) + Both(Pair.Create(42L,23)) ] ) Instance.I.visits.[name].Add(line + 1, v2) @@ -71,29 +71,29 @@ module Adapter = let Lock = Instance.I.visits :> obj let VisitImplNone (moduleId, hitPointId) = - Instance.I.visitImpl moduleId hitPointId Track.Null + Instance.I.visitImpl(moduleId, hitPointId, Null()) let VisitImplMethod (moduleId, hitPointId, mId) = - Instance.I.visitImpl moduleId hitPointId (Call mId) + Instance.I.visitImpl (moduleId, hitPointId, (Call mId)) //let internal VisitImpl (a, b, c) = // Instance.I.visitImpl a b c let internal addSample (moduleId, hitPointId, context) = - Instance.I.takeSample Sampling.Single moduleId hitPointId context + Instance.I.takeSample(Sampling.Single, moduleId, hitPointId, context) let internal addSampleUnconditional (moduleId, hitPointId, context) = - Instance.I.takeSample Sampling.All moduleId hitPointId context + Instance.I.takeSample(Sampling.All, moduleId, hitPointId, context) - let internal newBoth (time, call) = Both { Time = time; Call = call } + let internal newBoth (time, call) = Both(Pair.Create(time, call)) let internal asCall track = Call track let internal time at = Time at - let internal untime at = + let internal untime (at:Track) = let r = List() match at with - | Time t -> r.Add(t) + | :? Time as t -> r.Add(t) | _ -> () r diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 3d85aed9..9c32238d 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -402,6 +402,9 @@ internal static void clear() // |> InvalidDataException // |> raise + internal static void takeSample(Sampling strategy, string moduleId, int hitPointId, Track context) + { } + // let internal takeSample strategy moduleId hitPointId(context: Track) = // match strategy with // | Sampling.All -> true @@ -443,6 +446,10 @@ internal static void clear() // /// // /// Assembly being visited // /// Sequence Point identifier + internal static void visitImpl(string moduleId, int hitPointId, Track context) + { + } + // let internal visitImpl moduleId hitPointId context = // if // (Sample = Sampling.All From 63e1dc558df54792083f80ceaf447334c9b1d259 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 12 Jul 2024 18:59:28 +0100 Subject: [PATCH 41/91] Getting to some functional bits now --- AltCover.Recorder.Tests/Adapter.fs | 48 +++--- AltCover.Recorder/Base.cs | 252 +++++++++++++++-------------- AltCover.Recorder/Recorder.cs | 17 ++ 3 files changed, 174 insertions(+), 143 deletions(-) diff --git a/AltCover.Recorder.Tests/Adapter.fs b/AltCover.Recorder.Tests/Adapter.fs index d515bba0..fd4ea6bc 100644 --- a/AltCover.Recorder.Tests/Adapter.fs +++ b/AltCover.Recorder.Tests/Adapter.fs @@ -93,7 +93,7 @@ module Adapter = let r = List() match at with - | :? Time as t -> r.Add(t) + | :? Time as t -> r.Add(t.Value) | _ -> () r @@ -104,8 +104,9 @@ module Adapter = let internal untable t = let r = List() - match t with - | (n, p, Table d) -> + let n, p, (t':Track) = t + match t' with + | :? Table as d -> r.Add(n) r.Add(p) r.Add(d) @@ -120,39 +121,36 @@ module Adapter = else Some output - Counter.doFlushFile ignore (fun _ _ -> ()) true visits format report output' + Counter.doFlushFile(ignore, (fun _ _ -> ()), true, visits, format, report, output') let internal updateReport (counts, format, coverageFile, outputFile) = Counter.I.updateReport - ignore - (fun _ _ -> ()) - true - counts - format - coverageFile - outputFile + (ignore, + (fun _ _ -> ()), + true, + counts, + format, + coverageFile, + outputFile); let internal payloadSelector x = Instance.I.payloadSelector (fun _ -> x) let internal payloadControl (x, y) = - Instance.I.payloadControl (fun _ -> x) (fun _ -> y) + Instance.I.payloadControl ((fun _ -> x), (fun _ -> y)) let internal payloadSelection (x, y, z) = - Instance.I.payloadSelection (fun _ -> x) (fun _ -> y) (fun _ -> z) + Instance.I.payloadSelection ((fun _ -> x), (fun _ -> y), (fun _ -> z)) let internal makeNullTrace name = - { Tracer = name - Stream = null - Formatter = null - Runner = false - Definitive = false } + Tracer.Create(name) let internal makeStreamTrace s1 = - { Tracer = null - Stream = new System.IO.MemoryStream() - Formatter = new System.IO.BinaryWriter(s1) - Runner = true - Definitive = false } + let mutable t = Tracer.Create(null) + t.Stream <- new System.IO.MemoryStream() + t.Formatter <- new System.IO.BinaryWriter(s1) + t.Runner <- true + t.Definitive <- false + t let internal invokeIssue71Wrapper<'T when 'T :> System.Exception> ((unique: string), (called: bool array)) @@ -175,7 +173,7 @@ module Adapter = | :? System.ArgumentNullException as ane -> ane.ParamName = unique | _ -> x.Message = unique - Instance.I.issue71Wrapper () () () () catcher pitcher + Instance.I.issue71Wrapper ((), (), (), (), catcher, pitcher) let internal invokeCurriedIssue71Wrapper<'T when 'T :> System.Exception> (unique: string) @@ -189,7 +187,7 @@ module Adapter = constructor.Invoke([| unique |]) :?> System.Exception |> raise - Instance.I.curriedIssue71Wrapper "a" "b" "c" "d" pitcher + Instance.I.curriedIssue71Wrapper ("a", "b", "c", "d", pitcher) let internal tracePush (a, b, c) = Instance.I.trace.Push a b c //let LogException (a, b, c, d) = Instance.I.logException a b c d diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 7fa5f796..7ca9983c 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -6,6 +6,7 @@ namespace AltCover #else + namespace AltCover.Recorder #endif { @@ -20,6 +21,7 @@ namespace AltCover.Recorder using static System.Net.Mime.MediaTypeNames; #if !RUNNER + using ICSharpCode.SharpZipLib.Zip; [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)] @@ -27,7 +29,8 @@ namespace AltCover.Recorder "AvoidUninstantiatedInternalClassesRule", Justification = "Looks like a bug, not detecting its use")] internal sealed class ExcludeFromCodeCoverageAttribute : Attribute - {} + { } + #endif [Flags] @@ -668,123 +671,136 @@ Stream outputFile } #else - //[] - //[] - //let internal doFlushStream - // postProcess - // pointProcess - // own - // counts - // format - // coverageFile - // output - // = - // use target = - // match output with - // | None -> new MemoryStream() :> Stream - // | Some f -> - // new FileStream( - // f, - // FileMode.OpenOrCreate, - // FileAccess.Write, - // FileShare.None, - // 4096, - // FileOptions.SequentialScan - // ) - // :> Stream - - // let outputFile = - // if Option.isSome output then - // target - // else - // coverageFile :> Stream - - // I.doFlush postProcess pointProcess own counts format coverageFile outputFile - - //[] - //[] - //[] - //let internal doFlushFile postProcess pointProcess own counts format report output = - // let zipped = - // int (format &&& ReportFormat.Zipped) <> 0 - - // if not zipped then - // use coverageFile = - // new FileStream( - // report, - // FileMode.Open, - // FileAccess.ReadWrite, - // FileShare.None, - // 4096, - // FileOptions.SequentialScan - // ) - - // doFlushStream postProcess pointProcess own counts format coverageFile output - // else - // let container = - // new FileStream( - // report + ".zip", - // FileMode.Open, - // FileAccess.ReadWrite, - // FileShare.None, - // 4096, - // FileOptions.SequentialScan - // ) - - // use target = - // match output with - // | None -> new MemoryStream() :> Stream - // | Some f -> - // new FileStream( - // f, - // FileMode.OpenOrCreate, - // FileAccess.Write, - // FileShare.None, - // 4096, - // FileOptions.SequentialScan - // ) - // :> Stream - - // try - // ZipConstants.DefaultCodePage <- 65001 //UTF-8 as System.IO.Compression.ZipFile uses internally - // let zip = new ZipFile(container) - - // try - // let entryName = report |> Path.GetFileName - // let entry = zip.GetEntry(entryName) - - // let result = - // use reader = zip.GetInputStream(entry) - // I.doFlush postProcess pointProcess own counts format reader target - - // if output.IsNone then - // zip.BeginUpdate() - // zip.Delete entry - // target.Seek(0L, SeekOrigin.Begin) |> ignore - - // let source = - // { new IStaticDataSource with - // member self.GetSource() = target } - - // zip.Add(source, entryName) - // zip.CommitUpdate() - - // result - // finally - // zip.Close() - // with :? ZipException -> - // use reader = new MemoryStream() - // I.doFlush postProcess pointProcess own counts format reader target + //[] + //[] + //let internal doFlushStream + // postProcess + // pointProcess + // own + // counts + // format + // coverageFile + // output + // = + // use target = + // match output with + // | None -> new MemoryStream() :> Stream + // | Some f -> + // new FileStream( + // f, + // FileMode.OpenOrCreate, + // FileAccess.Write, + // FileShare.None, + // 4096, + // FileOptions.SequentialScan + // ) + // :> Stream + + // let outputFile = + // if Option.isSome output then + // target + // else + // coverageFile :> Stream + + // I.doFlush postProcess pointProcess own counts format coverageFile outputFile + + //[] + //[] + //[] + + internal static void doFlushFile( + Action postProcess, + /*Action>*/ object pointProcess, + bool own, + Dictionary> counts, + ReportFormat format, + Stream report, + object output + ) + { + } + + //let internal doFlushFile postProcess pointProcess own counts format report output = + // let zipped = + // int (format &&& ReportFormat.Zipped) <> 0 + + // if not zipped then + // use coverageFile = + // new FileStream( + // report, + // FileMode.Open, + // FileAccess.ReadWrite, + // FileShare.None, + // 4096, + // FileOptions.SequentialScan + // ) + + // doFlushStream postProcess pointProcess own counts format coverageFile output + // else + // let container = + // new FileStream( + // report + ".zip", + // FileMode.Open, + // FileAccess.ReadWrite, + // FileShare.None, + // 4096, + // FileOptions.SequentialScan + // ) + + // use target = + // match output with + // | None -> new MemoryStream() :> Stream + // | Some f -> + // new FileStream( + // f, + // FileMode.OpenOrCreate, + // FileAccess.Write, + // FileShare.None, + // 4096, + // FileOptions.SequentialScan + // ) + // :> Stream + + // try + // ZipConstants.DefaultCodePage <- 65001 //UTF-8 as System.IO.Compression.ZipFile uses internally + // let zip = new ZipFile(container) + + // try + // let entryName = report |> Path.GetFileName + // let entry = zip.GetEntry(entryName) + + // let result = + // use reader = zip.GetInputStream(entry) + // I.doFlush postProcess pointProcess own counts format reader target + + // if output.IsNone then + // zip.BeginUpdate() + // zip.Delete entry + // target.Seek(0L, SeekOrigin.Begin) |> ignore + + // let source = + // { new IStaticDataSource with + // member self.GetSource() = target } + + // zip.Add(source, entryName) + // zip.CommitUpdate() + + // result + // finally + // zip.Close() + // with :? ZipException -> + // use reader = new MemoryStream() + // I.doFlush postProcess pointProcess own counts format reader target #endif // !RUNNER } diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 9c32238d..9bfb65e8 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -356,6 +356,10 @@ internal static void clear() // "AvoidLongParameterListsRule", // Justification = "Self-contained internal decorator")>] + internal static void issue71Wrapper(object visits, string moduleId, int hitPointId, + Track context, object handler, object add) + { } + // let //#if !DEBUG // inline @@ -377,6 +381,10 @@ internal static void clear() // | :? ArgumentNullException -> handler moduleId hitPointId context x // | _ -> reraise() + internal static void curriedIssue71Wrapper(object visits, string moduleId, int hitPointId, + Track context, object add) + { } + // let //#if !DEBUG // inline @@ -472,6 +480,9 @@ internal static void visitImpl(string moduleId, int hitPointId, Track context) // let internal granularity() = Timer // let internal clock() = DateTime.UtcNow.Ticks + internal static Track payloadSelection(object clock, object frquency, object wantPayload) + { return default; } + // let internal payloadSelection clock frequency wantPayload = // if wantPayload() then // match(frequency (), callerId ()) with @@ -486,9 +497,15 @@ internal static void visitImpl(string moduleId, int hitPointId, Track context) // else // Null + internal static Track payloadControl(object frquency, object wantPayload) + { return default; } + // let internal payloadControl = // payloadSelection clock + internal static Track payloadSelector(object enable) + { return default; } + // let internal payloadSelector enable = payloadControl granularity enable // let internal visitSelection track moduleId hitPointId = From 213ab3d02939ebda5767f4b84f4a1c8d83224760 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 13 Jul 2024 14:01:59 +0100 Subject: [PATCH 42/91] Getting closer, but it now lies to me about the availability of Mutex at net20! --- AltCover.Recorder.Tests/Adapter.fs | 6 +- AltCover.Recorder.Tests/Recorder.Tests.fs | 31 +- AltCover.Recorder.Tests/Tracer.Tests.fs | 7 +- AltCover.Recorder/Base.cs | 10 + AltCover.Recorder/Recorder.cs | 350 ++++++++++++++-------- AltCover.Recorder/Tracer.cs | 96 ++++-- 6 files changed, 327 insertions(+), 173 deletions(-) diff --git a/AltCover.Recorder.Tests/Adapter.fs b/AltCover.Recorder.Tests/Adapter.fs index fd4ea6bc..83c0cde0 100644 --- a/AltCover.Recorder.Tests/Adapter.fs +++ b/AltCover.Recorder.Tests/Adapter.fs @@ -98,8 +98,8 @@ module Adapter = r - let internal asNull () = Null - let internal table t = Table t + let internal asNull () = new Null() :> Track + let internal table t = Table t :> Track let internal untable t = let r = List() @@ -189,7 +189,7 @@ module Adapter = Instance.I.curriedIssue71Wrapper ("a", "b", "c", "d", pitcher) - let internal tracePush (a, b, c) = Instance.I.trace.Push a b c + let internal tracePush (a, b, c) = Instance.I.trace.Push (a, b, c) //let LogException (a, b, c, d) = Instance.I.logException a b c d //let FindIndexFromUspid (a,b) = Counter.I.findIndexFromUspid a b #endif \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index d9143889..06923957 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -82,7 +82,7 @@ module AltCoverTests = let v1 = DateTime.UtcNow.Ticks let probe = Instance.I.clock () let v2 = DateTime.UtcNow.Ticks - Assert.True(Instance.I.granularity () = 0L) + Assert.True(Instance.I.granularity = 0L) Assert.True(probe >= v1) Assert.True(probe <= v2) @@ -111,31 +111,32 @@ module AltCoverTests = lock Adapter.Lock (fun () -> try Adapter.ModuleReset [| "module"; "newmodule" |] + let n = Null() :> Track - Assert.True(Adapter.addSample ("module", 23, Null), "Test 1") - Assert.True(Adapter.addSample ("module", 24, Null), "Test 2") - Assert.True(Adapter.addSample ("newmodule", 23, Null), "Test 3") - Assert.True(Adapter.addSample ("module", 23, Null) |> not, "Test 4") - Assert.True(Adapter.addSampleUnconditional ("module", 23, Null), "Test 5") + Assert.True(Adapter.addSample ("module", 23, n), "Test 1") + Assert.True(Adapter.addSample ("module", 24, n), "Test 2") + Assert.True(Adapter.addSample ("newmodule", 23, n), "Test 3") + Assert.True(Adapter.addSample ("module", 23, n) |> not, "Test 4") + Assert.True(Adapter.addSampleUnconditional ("module", 23, n), "Test 5") Assert.True(Adapter.addSample ("module", 23, Call 1), "Test 6") Assert.True(Adapter.addSample ("module", 23, Time 0L), "Test 7") Assert.True( - Adapter.addSample ("module", 24, Both { Call = 1; Time = 0L }), + Adapter.addSample ("module", 24, new Both(Pair.Create(1,0))), "Test 8" ) Assert.True( - Adapter.addSample ("module", 25, Both { Call = 1; Time = 0L }), + Adapter.addSample ("module", 25, new Both(Pair.Create(1,0))), "Test 9" ) Assert.True(Adapter.addSample ("module", 25, Call 1) |> not, "Test 10") Assert.True(Adapter.addSample ("module", 25, Call 1) |> not, "Test 11") - Assert.True(Adapter.addSample ("module", 25, Null) |> not, "Test 12") + Assert.True(Adapter.addSample ("module", 25, n) |> not, "Test 12") // out of band example - Assert.True(Adapter.addSample ("nonesuch", 25, Null) |> not, "Test 12a") + Assert.True(Adapter.addSample ("nonesuch", 25, n) |> not, "Test 12a") Assert.Throws(fun () -> Adapter.addSample ("module", 23, Table null) @@ -159,16 +160,16 @@ module AltCoverTests = Instance.I.trace <- Adapter.makeNullTrace null Instance.I.recording <- false - Instance.Visit "key" 17 + Instance.Visit ("key", 17) Instance.I.recording <- true Instance.CoverageFormat <- ReportFormat.NCover - Instance.Visit key -23 + Instance.Visit (key, -23) Instance.CoverageFormat <- ReportFormat.OpenCover ||| ReportFormat.WithTracking - Instance.Visit key -23 + Instance.Visit (key, -23) let vs = Adapter.VisitsSeq() Assert.True(vs |> Seq.length = 3, sprintf "Adapter.VisitsSeq() = %A" vs) @@ -196,7 +197,7 @@ module AltCoverTests = let key = " " let index = - Counter.I.findIndexFromUspid 0 key + Counter.I.findIndexFromUspid (0, key) Assert.True(index < 0) @@ -571,7 +572,7 @@ module AltCoverTests = let before = Directory.GetFiles(where, "*.exn") - Instance.I.visitImpl key 23 (Adapter.asNull ()) + Instance.I.visitImpl (key, 23, Adapter.asNull ()) let after = Directory.GetFiles(where, "*.exn") diff --git a/AltCover.Recorder.Tests/Tracer.Tests.fs b/AltCover.Recorder.Tests/Tracer.Tests.fs index f4b2ea2d..14ab93aa 100644 --- a/AltCover.Recorder.Tests/Tracer.Tests.fs +++ b/AltCover.Recorder.Tests/Tracer.Tests.fs @@ -107,7 +107,7 @@ module AltCoverCoreTests = strike, match enum tag with //| Tag.Time -> Adapter.Time <| formatter.ReadInt64() - | Tag.Call -> Adapter.asCall <| formatter.ReadInt32() + | Tag.Call -> (Adapter.asCall <| formatter.ReadInt32()) :> Track //| Tag.Both -> Adapter.NewBoth((formatter.ReadInt64()), (formatter.ReadInt32())) | Tag.Table -> Assert.True((id = String.Empty)) @@ -250,10 +250,11 @@ module AltCoverCoreTests = let expect23 = [ Adapter.asCall 17; Adapter.asCall 42 ] + |> Seq.cast let expect24 = - [ Adapter.time 17L - Adapter.newBoth (42L, 23) ] + [ (Adapter.time 17L) :> Track + (Adapter.newBoth (42L, 23)) :> Track ] t.["name"].[23] <- Adapter.init (1L, expect23) t.["name"].[24] <- Adapter.init (2L, expect24) diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 7ca9983c..56e53606 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -122,6 +122,16 @@ public override string ToString() { return "AltCover.Null"; } + + public override bool Equals(object obj) + { + return obj is Null n; + } + + public override int GetHashCode() + { + return string.Empty.GetHashCode(); + } } internal class Time : Track diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 9bfb65e8..91e9dec0 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -31,77 +31,99 @@ public static class Instance /// Gets the location of coverage xml file /// This property's IL code is modified to store the actual file location /// - public static string ReportFile + internal static string ReportFile { [MethodImpl(MethodImplOptions.NoInlining)] get { return "Coverage.Default.xml"; } } - // let ReportFilePath = - // Path.Combine( - // Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), - // ReportFile - // ) - // |> AltCover.Canonical.canonicalPath + internal static string ReportFilePath + { + get + { + return canonicalPath(Path.Combine( + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), + ReportFile)); + } + } - // /// - // /// Gets whether to defer output until process exit - // /// This property's IL code is modified to store the actual value - // /// - // [< MethodImplAttribute(MethodImplOptions.NoInlining) >] - // let Defer = false + internal static string canonicalPath(string path) + // Mono+Linux barfs at a path of "/_" without the "file://" prefix + { + var u = new Uri("file://" + Path.GetFullPath(path), UriKind.Absolute); + return u.LocalPath; + } - // /// - // /// Gets the style of the associated report - // /// This property's IL code is modified to store the user chosen override if applicable - // /// - // [< MethodImplAttribute(MethodImplOptions.NoInlining) >] - // [< SuppressMessage("Gendarme.Rules.Performance", - // "AvoidUncalledPrivateCodeRule", - // Justification = "Unit test accessor") >] - // [< SuppressMessage("Gendarme.Rules.Naming", - // "UseCorrectCasingRule", - // Justification = "Code rewritten") >] - // let - //#if DEBUG - // mutable - //#endif - // internal CoverageFormat = // fsharplint:disable-line NonPublicValuesNames - // ReportFormat.NCover + /// + /// Gets whether to defer output until process exit + /// This property's IL code is modified to store the actual value + /// + internal static bool Defer + { + [MethodImpl(MethodImplOptions.NoInlining)] + get { return false; } + } - // /// - // /// Gets the frequency of time sampling - // /// This property's IL code is modified to store the user chosen override if applicable - // /// - // [< MethodImplAttribute(MethodImplOptions.NoInlining) >] - // let Timer = 0L + /// + /// Gets the style of the associated report + /// This property's IL code is modified to store the user chosen override if applicable + /// + private static ReportFormat __coverageFormat = ReportFormat.NCover; - // /// - // /// Gets the sampling strategy - // /// This property's IL code is modified to store the user chosen override if applicable - // /// - // [] - // let internal Sample = Sampling.All // fsharplint:disable-line NonPublicValuesNames + internal static ReportFormat CoverageFormat + { +#if DEBUG + set { __coverageFormat = value; } +#endif + [MethodImpl(MethodImplOptions.NoInlining)] + get { return __coverageFormat; } + } + + /// + /// Gets the frequency of time sampling + /// This property's IL code is modified to store the user chosen override if applicable + /// + public static long Timer + { + [MethodImpl(MethodImplOptions.NoInlining)] + get { return 0; } + } - // /// - // /// Gets the unique token for this instance - // /// This property's IL code is modified to store a GUID-based token - // /// - // [< MethodImplAttribute(MethodImplOptions.NoInlining) >] - // let Token = "AltCover" + /// + /// Gets the sampling strategy + /// This property's IL code is modified to store the user chosen override if applicable + /// + internal static Sampling Sample + { + [MethodImpl(MethodImplOptions.NoInlining)] + get { return Sampling.All; } + } + + /// + /// Gets the unique token for this instance + /// This property's IL code is modified to store a GUID-based token + /// + internal static string Token + { + [MethodImpl(MethodImplOptions.NoInlining)] + get { return "AltCover"; } + } // /// // /// Gets the indexed module tokens // /// This property's IL code is modified to store instrumentation results // /// - // [] - // [] + private static IEnumerable __modules = new string[] { string.Empty }; + + internal static IEnumerable modules + { +#if DEBUG + set { __modules = value; } +#endif + [MethodImpl(MethodImplOptions.NoInlining)] + get { return __modules; } + } - internal static IEnumerable modules; // [] // let mutable internal modules = // [| String.Empty |] @@ -181,7 +203,7 @@ internal static Dictionary> makeSamples() internal static bool isRunner = false; - // let internal synchronize = Object() + internal static readonly object synchronize = new Object(); //#if NET20 // // class needed for "[ThreadStatic] static val mutable" @@ -225,24 +247,48 @@ internal static Dictionary> makeSamples() // let pop () = look(fun i->i.Pop()) - // let internal callerId() = CallTrack.peek() + internal static int callerID + { + get { return default; } //CallTrack.peek() + } + + internal static void push(int i) + { } + // let internal push x = CallTrack.push x + + internal static int pop() + { return default; } + // let internal pop() = CallTrack.pop() - // /// - // /// Serialize access to the report file across AppDomains for the classic mode - // /// - // let internal mutex = - // new System.Threading.Mutex(false, Token + ".mutex") + /// + /// Serialize access to the report file across AppDomains for the classic mode + /// + internal static readonly Mutex mutex = new System.Threading.Mutex(false, Token + ".mutex"); - // let internal signalFile() = ReportFilePath + ".acv" + internal static string signalFile + { + get { return ReportFilePath + ".acv"; } + } - // /// - // /// Reporting back to the mother-ship - // /// + /// + /// Reporting back to the mother-ship + /// // let mutable internal trace = // Tracer.Create(signalFile ()) + private static Tracer __trace = Tracer.Create(signalFile); + + internal static Tracer trace + { +#if DEBUG + set { __trace = value; } +#endif + [MethodImpl(MethodImplOptions.NoInlining)] + get { return __trace; } + } + // let internal withMutex(f: bool -> 'a) = // let own = mutex.WaitOne(1000) @@ -260,7 +306,16 @@ internal static Dictionary> makeSamples() // let internal watcher = // new FileSystemWatcher() - // let mutable internal recording = true + private static bool __recording = true; + + internal static bool recording + { +#if DEBUG + set { __recording = value; } +#endif + [MethodImpl(MethodImplOptions.NoInlining)] + get { return __recording; } + } internal static void clear() { } @@ -270,30 +325,33 @@ internal static void clear() // Counter.branchVisits<- 0L // Counter.totalVisits<- 0L - // /// - // /// This method flushes hit count buffers. - // /// - // let internal flushAll _ = - // let counts = visits - // clear() - - // trace.OnConnected(fun () -> trace.OnFinish counts) (fun () -> - // match counts.Values |> Seq.sumBy (fun x -> x.Count) with - // | 0 -> () - // | _ -> - // withMutex(fun own -> - // let delta = - // Counter.doFlushFile - // ignore - // (fun _ _ -> ()) - // own - // counts - // CoverageFormat - // ReportFilePath - // None - - // getResource "Coverage statistics flushing took {0:N} seconds" - // |> Option.iter(fun s -> Console.Out.WriteLine(s, delta.TotalSeconds)))) + /// + /// This method flushes hit count buffers. + /// + internal static void flushAll(Close _) + { + // let internal flushAll _ = + // let counts = visits + // clear() + + // trace.OnConnected(fun () -> trace.OnFinish counts) (fun () -> + // match counts.Values |> Seq.sumBy (fun x -> x.Count) with + // | 0 -> () + // | _ -> + // withMutex(fun own -> + // let delta = + // Counter.doFlushFile + // ignore + // (fun _ _ -> ()) + // own + // counts + // CoverageFormat + // ReportFilePath + // None + + // getResource "Coverage statistics flushing took {0:N} seconds" + // |> Option.iter(fun s -> Console.Out.WriteLine(s, delta.TotalSeconds)))) + } // let internal flushPause() = // ("PauseHandler") @@ -410,8 +468,10 @@ internal static void curriedIssue71Wrapper(object visits, string moduleId, int h // |> InvalidDataException // |> raise - internal static void takeSample(Sampling strategy, string moduleId, int hitPointId, Track context) - { } + internal static bool takeSample(Sampling strategy, string moduleId, int hitPointId, Track context) + { + return false; + } // let internal takeSample strategy moduleId hitPointId(context: Track) = // match strategy with @@ -478,30 +538,42 @@ internal static void visitImpl(string moduleId, int hitPointId, Track context) // let internal isTrackingRunner() = isTracking() && isRunner // let internal granularity() = Timer - // let internal clock() = DateTime.UtcNow.Ticks + internal static long granularity + { + get { return Timer; } + } - internal static Track payloadSelection(object clock, object frquency, object wantPayload) - { return default; } + internal static long clock() + { return DateTime.UtcNow.Ticks; } - // let internal payloadSelection clock frequency wantPayload = - // if wantPayload() then - // match(frequency (), callerId ()) with - // | (0L, None) -> Null - // | (t, None) -> Time(t* (clock () / t)) - // | (0L, n) -> Call n.Value - // | (t, n) -> - // Both - // { - // Time = t * (clock() / t) - // Call = n.Value } - // else - // Null - - internal static Track payloadControl(object frquency, object wantPayload) - { return default; } + internal delegate long ClockProvider(); + + internal delegate long FrequencyProvider(); + + internal delegate bool PayloadProvider(); - // let internal payloadControl = - // payloadSelection clock + internal static Track payloadSelection(ClockProvider clock, + FrequencyProvider frequency, PayloadProvider wantPayload) + { + if (wantPayload()) + { + // match(frequency (), callerId ()) with + // | (0L, None) -> Null + // | (t, None) -> Time(t* (clock () / t)) + // | (0L, n) -> Call n.Value + // | (t, n) -> + // Both + // { + // Time = t * (clock() / t) + // Call = n.Value } + } + return new Null(); + } + + internal static Track payloadControl(FrequencyProvider frequency, PayloadProvider wantPayload) + { + return payloadSelection(clock, frequency, wantPayload); + } internal static Track payloadSelector(object enable) { return default; } @@ -549,31 +621,43 @@ internal static Track payloadSelector(object enable) // signalFile () |> Tracer.Create |> initialiseTrace } - // // Public API - // let Visit moduleId hitPointId = - // if I.recording then - // I.visitSelection - // (if I.isTracking() then - // I.payloadSelector I.isTrackingRunner - // else - // Null) - // moduleId - // hitPointId + // Public API + public static void Visit(string moduleId, int hitPointId) + { + // let Visit moduleId hitPointId = + // if I.recording then + // I.visitSelection + // (if I.isTracking() then + // I.payloadSelector I.isTrackingRunner + // else + // Null) + // moduleId + // hitPointId + } //// The moduleId strings are not the hash or guids normally found there - //let Push caller = - // I.push caller + public static void Push(Action caller) + { + //let Push caller = + // I.push caller - // if I.isTrackingRunner() then - // I.visitSelection(Time DateTime.UtcNow.Ticks) Track.Entry caller + // if I.isTrackingRunner() then + // I.visitSelection(Time DateTime.UtcNow.Ticks) Track.Entry caller + } - //let Pop() = - // let caller = I.pop() + public static void Pop() + { + //let Pop() = + // let caller = I.pop() - // if I.isTrackingRunner() && caller.IsSome then - // I.visitSelection(Time DateTime.UtcNow.Ticks) Track.Exit caller.Value + // if I.isTrackingRunner() && caller.IsSome then + // I.visitSelection(Time DateTime.UtcNow.Ticks) Track.Exit caller.Value + } //// Used by the datacollector - //let FlushFinish () = I.flushAll ProcessExit + internal static void FlushFinish() + { + I.flushAll(Close.ProcessExit); + } } } \ No newline at end of file diff --git a/AltCover.Recorder/Tracer.cs b/AltCover.Recorder/Tracer.cs index 10d27d12..6e05646d 100644 --- a/AltCover.Recorder/Tracer.cs +++ b/AltCover.Recorder/Tracer.cs @@ -46,18 +46,6 @@ internal static Tracer Create(string name) return new Tracer(name); } - internal void Close() - { - try - { - this.Stream.Flush(); - - this.Formatter.Close(); - } - catch (ObjectDisposedException) { } - catch (NullReferenceException) { } - } - internal bool IsConnected { get @@ -66,13 +54,6 @@ internal bool IsConnected } } - internal Tracer OnStart() - { - var running = this.Connect(); - running.Definitive = true; - return running; - } - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", Justification = "s, fs : Closed as recording ends")] @@ -106,5 +87,82 @@ internal Tracer Connect() else { return this; } } + + internal void Close() + { + try + { + this.Stream.Flush(); + + this.Formatter.Close(); + } + catch (ObjectDisposedException) { } + catch (NullReferenceException) { } + } + + private void PushContext(Track context) + { + //member private this.PushContext context = + // match context with + // | Null -> this.Formatter.Write(Tag.Null |> byte) + // | Time t -> + // this.Formatter.Write(Tag.Time |> byte) + // this.Formatter.Write(t) + // | Call t -> + // this.Formatter.Write(Tag.Call |> byte) + // this.Formatter.Write(t) + // | Both b -> + // this.Formatter.Write(Tag.Both |> byte) + // this.Formatter.Write(b.Time) + // this.Formatter.Write(b.Call) + // | Table t -> + // this.Formatter.Write(Tag.Table |> byte) + + // t.Keys + // |> Seq.filter (fun k -> t.[k].Count > 0) + // |> Seq.iter (fun m -> + // this.Formatter.Write m + // this.Formatter.Write t.[m].Count + + // t.[m].Keys + // |> Seq.iter (fun p -> + // this.Formatter.Write p + // let v = t.[m].[p] + // this.Formatter.Write v.Count + // v.Tracks |> Seq.iter this.PushContext + // this.PushContext Null)) + + // this.Formatter.Write String.Empty + } + + internal void Push(string moduleId, int hitPointId, Track context) + { + this.Formatter.Write(moduleId); + this.Formatter.Write(hitPointId); + this.PushContext(context); + } + + //member internal this.CatchUp(visits: Dictionary>) = + // if visits.Values |> Seq.sumBy (fun x -> x.Count) > 0 then + // visits |> Table |> this.Push String.Empty 0 + + internal Tracer OnStart() + { + var running = this.Connect(); + running.Definitive = true; + return running; + } + + //member internal this.OnConnected f g = if this.IsConnected then f () else g () + + //member internal this.OnFinish visits = + // this.CatchUp visits + // this.Close() + + //member internal this.OnVisit visits moduleId hitPointId context = + // this.CatchUp visits + // this.Push moduleId hitPointId context + // this.Formatter.Flush() + // this.Stream.Flush() } } \ No newline at end of file From c1c503aa25bdc93e460608c18a836f9d9f5b66ce Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 13 Jul 2024 14:11:15 +0100 Subject: [PATCH 43/91] Mutex resolved. 42 compile errors to go. --- AltCover.Recorder/Recorder.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 91e9dec0..1672888b 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -15,13 +15,8 @@ namespace AltCover.Recorder using System.Runtime.Remoting.Contexts; using System.Security.Policy; using System.Text.RegularExpressions; - -#if !NET20 using System.Threading; using static System.Net.Mime.MediaTypeNames; -#endif - - //using AltCover.Shared; public static class Instance { @@ -265,7 +260,7 @@ internal static int pop() /// /// Serialize access to the report file across AppDomains for the classic mode /// - internal static readonly Mutex mutex = new System.Threading.Mutex(false, Token + ".mutex"); + internal static readonly Mutex mutex = new Mutex(false, Token + ".mutex"); internal static string signalFile { From f99cccebe2fb0872149817afa0536fa2aa0c9a07 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 10:35:16 +0100 Subject: [PATCH 44/91] Compiles cleanly. Now the work begins --- AltCover.Api.Tests/AltCover.Api.Tests.fsproj | 1 + AltCover.Recorder.Tests/Adapter.fs | 8 ++-- AltCover.Recorder.Tests/Recorder.Tests.fs | 47 ++++++++++--------- AltCover.Recorder/Base.cs | 14 +++--- AltCover.Recorder/Recorder.cs | 38 +++++++++++---- .../AltCover.ValidateGendarmeEmulation.fsproj | 1 + 6 files changed, 69 insertions(+), 40 deletions(-) diff --git a/AltCover.Api.Tests/AltCover.Api.Tests.fsproj b/AltCover.Api.Tests/AltCover.Api.Tests.fsproj index a4ac8592..23af45cd 100644 --- a/AltCover.Api.Tests/AltCover.Api.Tests.fsproj +++ b/AltCover.Api.Tests/AltCover.Api.Tests.fsproj @@ -9,6 +9,7 @@ Library $(AssemblySearchPaths);{GAC} DEBUG;TRACE + MSB3277 diff --git a/AltCover.Recorder.Tests/Adapter.fs b/AltCover.Recorder.Tests/Adapter.fs index 83c0cde0..7e314cae 100644 --- a/AltCover.Recorder.Tests/Adapter.fs +++ b/AltCover.Recorder.Tests/Adapter.fs @@ -117,9 +117,9 @@ module Adapter = let internal doFlush (visits, format, report, output) = let output' = if System.String.IsNullOrEmpty output then - None + null else - Some output + output Counter.doFlushFile(ignore, (fun _ _ -> ()), true, visits, format, report, output') @@ -173,7 +173,7 @@ module Adapter = | :? System.ArgumentNullException as ane -> ane.ParamName = unique | _ -> x.Message = unique - Instance.I.issue71Wrapper ((), (), (), (), catcher, pitcher) + Instance.I.issue71Wrapper ((), (), (), (), catcher, pitcher) |> ignore let internal invokeCurriedIssue71Wrapper<'T when 'T :> System.Exception> (unique: string) @@ -187,7 +187,7 @@ module Adapter = constructor.Invoke([| unique |]) :?> System.Exception |> raise - Instance.I.curriedIssue71Wrapper ("a", "b", "c", "d", pitcher) + Instance.I.curriedIssue71Wrapper ("a", "b", "c", "d", pitcher) |> ignore let internal tracePush (a, b, c) = Instance.I.trace.Push (a, b, c) //let LogException (a, b, c, d) = Instance.I.logException a b c d diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index 06923957..febe2606 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -210,7 +210,7 @@ module AltCoverTests = ReportFormat.OpenCover ||| ReportFormat.WithTracking - Assert.True(Instance.I.callerId () |> Option.isNone) + Assert.False(Instance.I.callerId.HasValue) Assert.True(Adapter.payloadSelector false = Adapter.asNull ()) Assert.True(Adapter.payloadSelector true = Adapter.asNull ()) Instance.Push 4321 @@ -256,9 +256,9 @@ module AltCoverTests = Assert.True(probe % 1000L = 0L) Assert.True(probe <= v2) Assert.True(probe >= (1000L * (v1 / 1000L))) - Assert.True(Instance.I.callerId () |> Option.isNone) + Assert.True(Instance.I.callerId.HasValue |> not) Instance.Pop() - Assert.True(Instance.I.callerId () |> Option.isNone) + Assert.True(Instance.I.callerId.HasValue |> not) [] let PayloadWithEntryExitGeneratedIsAsExpected () = @@ -273,7 +273,7 @@ module AltCoverTests = Adapter.VisitsClear() - Assert.True(Instance.I.callerId () |> Option.isNone) + Assert.True(Instance.I.callerId.HasValue |> not) Assert.True(Adapter.payloadSelector false = Adapter.asNull ()) Assert.True(Adapter.payloadSelector true = Adapter.asNull ()) Instance.Push 4321 @@ -320,9 +320,9 @@ module AltCoverTests = Assert.True(probe % 1000L = 0L) Assert.True(probe <= v2) Assert.True(probe >= (1000L * (v1 / 1000L))) - Assert.True(Instance.I.callerId () |> Option.isNone) + Assert.True(Instance.I.callerId.HasValue |> not) Instance.Pop() - Assert.True(Instance.I.callerId () |> Option.isNone) + Assert.True(Instance.I.callerId.HasValue |> not) Assert.That(Instance.I.visits.Keys, Is.EquivalentTo [ Track.Entry; Track.Exit ]) @@ -385,7 +385,7 @@ module AltCoverTests = try Instance.I.trace <- Adapter.makeNullTrace null - Instance.I.visitSelection (Adapter.asNull ()) key 23 + Instance.I.visitSelection (Adapter.asNull (), key, 23) Assert.That( Instance.I.visits.Keys, @@ -435,7 +435,7 @@ module AltCoverTests = let before = Directory.GetFiles(where, "*.exn") - Instance.I.logException "a" "b" "c" "ex" + Instance.I.logException ("a", "b", "c", "ex") let after = Directory.GetFiles(where, "*.exn") @@ -615,8 +615,8 @@ module AltCoverTests = try let key = " " Adapter.ModuleReset [| key; "key" |] - Instance.I.visitImpl key 23 (Adapter.asNull ()) - Instance.I.visitImpl "key" 42 (Adapter.asNull ()) + Instance.I.visitImpl ( key, 23, Adapter.asNull ()) + Instance.I.visitImpl ("key", 42, Adapter.asNull ()) Assert.That( Instance.I.visits.Keys, @@ -635,8 +635,8 @@ module AltCoverTests = try let key = " " Adapter.ModuleReset [| key |] - Instance.I.visitImpl key 23 (Adapter.asNull ()) - Instance.I.visitImpl key 42 (Adapter.asNull ()) + Instance.I.visitImpl (key, 23, Adapter.asNull ()) + Instance.I.visitImpl (key, 42, Adapter.asNull ()) Assert.That( Instance.I.visits.Keys, @@ -658,8 +658,8 @@ module AltCoverTests = Adapter.ModuleReset [| key |] try - Instance.I.visitImpl key 23 (Adapter.asNull ()) - Instance.I.visitImpl key 23 (Adapter.asNull ()) + Instance.I.visitImpl (key, 23, Adapter.asNull ()) + Instance.I.visitImpl (key, 23, Adapter.asNull ()) Assert.That(Instance.I.visits.[key].[23].Count, Is.EqualTo 2) Assert.That(Instance.I.visits.[key].[23].Tracks, Is.Empty) finally @@ -679,8 +679,8 @@ module AltCoverTests = let payload = Adapter.time DateTime.UtcNow.Ticks - Instance.I.visitImpl key 23 (Adapter.asNull ()) - Instance.I.visitImpl key 23 payload + Instance.I.visitImpl (key, 23, Adapter.asNull ()) + Instance.I.visitImpl (key, 23, payload) Assert.That(Instance.I.visits.[key].[23].Count, Is.EqualTo 1) Assert.That(Instance.I.visits.[key].[23].Tracks, Is.EquivalentTo [ payload ]) finally @@ -1269,7 +1269,8 @@ module AltCoverTests = (int64 (i + 1)) )) - Adapter.DoPause().Invoke(null, null) + let NullObj:obj = null + Adapter.DoPause().Invoke(NullObj, null) Adapter.VisitsSeq() |> Seq.cast>> @@ -1369,7 +1370,8 @@ module AltCoverTests = [ 0..9 ] |> Seq.iter (fun i -> Adapter.VisitsAdd(key, i, (int64 (i + 1)))) - Adapter.DoResume().Invoke(null, null) + let NullObj:obj = null + Adapter.DoResume().Invoke(NullObj, null) Adapter.VisitsSeq() |> Seq.cast>> @@ -1474,7 +1476,8 @@ module AltCoverTests = (int64 (i + 1)) )) - Adapter.DoExit().Invoke(null, null) + let NullObj:obj = null + Adapter.DoExit().Invoke(NullObj, null) let head = "Coverage statistics flushing took " @@ -1580,7 +1583,8 @@ module AltCoverTests = (int64 (i + 1)) )) - Adapter.DoUnload().Invoke(null, null) + let NullObj:obj = null + Adapter.DoUnload().Invoke(NullObj, null) let head = "Coverage statistics flushing took " @@ -2083,7 +2087,8 @@ module AltCoverTests = (int64 (i + 1)) )) - Adapter.DoExit().Invoke(null, null) + let NullObj:obj = null + Adapter.DoExit().Invoke(NullObj, null) let head = "Coverage statistics flushing took " diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 56e53606..7b180329 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -303,6 +303,8 @@ internal long Total internal static class Counter { + public delegate void PointProcessor(XmlElement doc, IEnumerable tracking); + // // // // The time at which coverage run began // // @@ -485,7 +487,7 @@ private static void writeXDocument(XmlDocument coverageDocument, Stream stream) public static DateTime updateReport( Action postProcess, - /*Action>*/ object pointProcess, + PointProcessor pointProcess, bool own, Dictionary> counts, ReportFormat format, @@ -611,7 +613,7 @@ Stream outputFile public static TimeSpan doFlush( Action postProcess, - /*Action>*/ object pointProcess, + PointProcessor pointProcess, bool own, Dictionary> counts, ReportFormat format, @@ -669,7 +671,7 @@ Track context Justification = "Most of this gets curried away")] public static TimeSpan doFlushStream( Action postProcess, - Action> pointProcess, + PointProcessor pointProcess, bool own, Dictionary> counts, ReportFormat format, @@ -730,12 +732,12 @@ Stream outputFile internal static void doFlushFile( Action postProcess, - /*Action>*/ object pointProcess, + PointProcessor pointProcess, bool own, Dictionary> counts, ReportFormat format, - Stream report, - object output + string report, + string output // option ) { } diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 1672888b..bf964942 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -16,6 +16,7 @@ namespace AltCover.Recorder using System.Security.Policy; using System.Text.RegularExpressions; using System.Threading; + using static AltCover.Recorder.Instance.I; using static System.Net.Mime.MediaTypeNames; public static class Instance @@ -126,6 +127,8 @@ internal static IEnumerable modules // [] + + internal static bool supervision; // let mutable internal supervision = // //Assembly.GetExecutingAssembly().GetName().Name = "AltCover.Recorder.g" && // AppDomain.CurrentDomain.GetAssemblies() @@ -242,7 +245,7 @@ internal static Dictionary> makeSamples() // let pop () = look(fun i->i.Pop()) - internal static int callerID + internal static Nullable callerId { get { return default; } //CallTrack.peek() } @@ -383,6 +386,9 @@ internal static void flushAll(Close _) // [] + internal static void logException(T1 moduleId, T2 hitPointId, T3 context, T4 x) + { } + // let internal logException moduleId hitPointId context x = // let text = // [| sprintf "ModuleId = %A" moduleId @@ -409,9 +415,15 @@ internal static void flushAll(Close _) // "AvoidLongParameterListsRule", // Justification = "Self-contained internal decorator")>] - internal static void issue71Wrapper(object visits, string moduleId, int hitPointId, - Track context, object handler, object add) - { } + internal delegate T HandlerFunction(T1 a, T2 b, T3 c, Exception x); + + internal delegate T Adder(T1 a, T2 b, T3 c, T4 d); + + internal static T issue71Wrapper(T1 visits, T2 moduleId, T3 hitPointId, + T4 context, HandlerFunction handler, Adder add) + { + return default; + } // let //#if !DEBUG @@ -434,9 +446,12 @@ internal static void issue71Wrapper(object visits, string moduleId, int hitPoint // | :? ArgumentNullException -> handler moduleId hitPointId context x // | _ -> reraise() - internal static void curriedIssue71Wrapper(object visits, string moduleId, int hitPointId, - Track context, object add) - { } + internal static T curriedIssue71Wrapper(T1 visits, T2 moduleId, + T3 hitPointId, + T4 context, Adder add) + { + return default; + } // let //#if !DEBUG @@ -570,11 +585,16 @@ internal static Track payloadControl(FrequencyProvider frequency, PayloadProvide return payloadSelection(clock, frequency, wantPayload); } - internal static Track payloadSelector(object enable) + internal delegate T PayloadEnabler(); + + internal static Track payloadSelector(PayloadEnabler enable) { return default; } // let internal payloadSelector enable = payloadControl granularity enable + internal static void visitSelection(T track, string moduleId, int hitPointId) + { } + // let internal visitSelection track moduleId hitPointId = // visitImpl moduleId hitPointId track @@ -631,7 +651,7 @@ public static void Visit(string moduleId, int hitPointId) } //// The moduleId strings are not the hash or guids normally found there - public static void Push(Action caller) + public static void Push(int caller) { //let Push caller = // I.push caller diff --git a/AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj b/AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj index b3ee7914..22282ba3 100644 --- a/AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj +++ b/AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj @@ -9,6 +9,7 @@ AltCover.ValidateGendarmeEmulation false + MSB3277 From 730f0f9f054932b54f8e29d41974122e02baea46 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 10:49:07 +0100 Subject: [PATCH 45/91] Tidy, note 44 failing unit tests now --- AltCover.Recorder/Recorder.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index bf964942..68a8ca7a 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -16,8 +16,6 @@ namespace AltCover.Recorder using System.Security.Policy; using System.Text.RegularExpressions; using System.Threading; - using static AltCover.Recorder.Instance.I; - using static System.Net.Mime.MediaTypeNames; public static class Instance { From 0fbe24c6d15098318228b88f89ec79847d8fec64 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 11:52:03 +0100 Subject: [PATCH 46/91] Transcribing this much brings us to 34 tests failing --- AltCover.Recorder.Tests/Adapter.fs | 4 +- AltCover.Recorder/Recorder.cs | 129 +++++++++++++++++------------ AltCover.Recorder/Tracer.cs | 29 +++++-- 3 files changed, 97 insertions(+), 65 deletions(-) diff --git a/AltCover.Recorder.Tests/Adapter.fs b/AltCover.Recorder.Tests/Adapter.fs index 7e314cae..dd41bd6a 100644 --- a/AltCover.Recorder.Tests/Adapter.fs +++ b/AltCover.Recorder.Tests/Adapter.fs @@ -187,9 +187,7 @@ module Adapter = constructor.Invoke([| unique |]) :?> System.Exception |> raise - Instance.I.curriedIssue71Wrapper ("a", "b", "c", "d", pitcher) |> ignore + Instance.I.curriedIssue71Wrapper ("a", "b", "c", "d", pitcher) |> ignore let internal tracePush (a, b, c) = Instance.I.trace.Push (a, b, c) -//let LogException (a, b, c, d) = Instance.I.logException a b c d -//let FindIndexFromUspid (a,b) = Counter.I.findIndexFromUspid a b #endif \ No newline at end of file diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 68a8ca7a..4177bf84 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -162,21 +162,20 @@ private static class I // |> Seq.map(fun l -> resources.GetString(s + "." + l)) // |> Seq.tryFind(String.IsNullOrEmpty >> not) - internal static Dictionary> makeVisits() + private static Dictionary> makeVisits() { - return default; + var d = new Dictionary> + { + { Track.Entry, new Dictionary() }, + { Track.Exit, new Dictionary() } + }; + foreach (var item in modules) + { + d.Add(item, new Dictionary()); + } + return d; } - // let private makeVisits() = - // [modules - // [| Track.Entry; Track.Exit |] ] - // |> Seq.concat - // |> Seq.fold - // (fun (d: Dictionary>) k -> - // d.Add(k, Dictionary()) - // d) - // (Dictionary>()) - /// /// Accumulation of visit records /// @@ -184,17 +183,14 @@ internal static Dictionary> makeVisits() internal static Dictionary> makeSamples() { - return default; + var d = new Dictionary>(); + foreach (var item in modules) + { + d.Add(item, new Dictionary()); + } + return d; } - // let internal makeSamples() = - // modules - // |> Seq.fold - // (fun (d: Dictionary>) k -> - // d.Add(k, Dictionary()) - // d) - // (Dictionary>()) - internal static Dictionary> samples = makeSamples(); internal static bool isRunner = false; @@ -314,12 +310,11 @@ internal static bool recording } internal static void clear() - { } - - // let internal clear() = - // visits<- makeVisits () - // Counter.branchVisits<- 0L - // Counter.totalVisits<- 0L + { + visits = makeVisits(); + Counter.branchVisits = 0; + Counter.totalVisits = 0; + } /// /// This method flushes hit count buffers. @@ -372,14 +367,24 @@ internal static void flushAll(Close _) // recording <- true - // let internal traceVisit moduleId hitPointId context = - // lock synchronize(fun () -> - // let counts = visits - - // if counts.Values |> Seq.sumBy (fun x -> x.Count) > 0 then - // clear() - - // trace.OnVisit counts moduleId hitPointId context) + internal static void traceVisit(string moduleId, int hitPointId, Track context) + { + lock (synchronize) + { + var counts = visits; + //if counts.Values |> Seq.sumBy (fun x -> x.Count) > 0 then + foreach (var item in counts.Values) + { + if (item.Count > 0) + { + clear(); + break; + } + } + + trace.OnVisit(counts, moduleId, hitPointId, context); + } + } // [(T1 moduleId, T2 hitPointId, T3 internal delegate T HandlerFunction(T1 a, T2 b, T3 c, Exception x); - internal delegate T Adder(T1 a, T2 b, T3 c, T4 d); + internal delegate void Adder(T1 a, T2 b, T3 c, T4 d); internal static T issue71Wrapper(T1 visits, T2 moduleId, T3 hitPointId, - T4 context, HandlerFunction handler, Adder add) + T4 context, HandlerFunction handler, Adder add) { return default; } @@ -444,11 +449,11 @@ internal static T issue71Wrapper(T1 visits, T2 moduleId, T3 h // | :? ArgumentNullException -> handler moduleId hitPointId context x // | _ -> reraise() - internal static T curriedIssue71Wrapper(T1 visits, T2 moduleId, + internal static void curriedIssue71Wrapper(T1 visits, T2 moduleId, T3 hitPointId, - T4 context, Adder add) + T4 context, Adder add) { - return default; + return; } // let @@ -464,6 +469,11 @@ internal static T curriedIssue71Wrapper(T1 visits, T2 moduleI // = // issue71Wrapper visits moduleId hitPointId context logException add + internal static void addVisit(string moduleId, int hitPointId, Track context) + { + curriedIssue71Wrapper(visits, moduleId, hitPointId, context, Counter.addSingleVisit); + } + // let internal addVisit moduleId hitPointId context = // curriedIssue71Wrapper visits moduleId hitPointId context Counter.addSingleVisit @@ -524,20 +534,33 @@ internal static bool takeSample(Sampling strategy, string moduleId, int hitPoint // /// Sequence Point identifier internal static void visitImpl(string moduleId, int hitPointId, Track context) { - } - - // let internal visitImpl moduleId hitPointId context = - // if - // (Sample = Sampling.All - // || takeSample Sample moduleId hitPointId context) - // then - // let adder = - // if Defer || supervision || (trace.IsConnected |> not) then - // addVisit - // else - // traceVisit + if + (Sample == Sampling.All + || takeSample(Sample, moduleId, hitPointId, context)) + { + if (Defer || supervision || !trace.IsConnected) + { + addVisit(moduleId, hitPointId, context); + } + else + { + traceVisit(moduleId, hitPointId, context); + } + } - // adder moduleId hitPointId context + // let internal visitImpl moduleId hitPointId context = + // if + // (Sample = Sampling.All + // || takeSample Sample moduleId hitPointId context) + // then + // let adder = + // if Defer || supervision || (trace.IsConnected |> not) then + // addVisit + // else + // traceVisit + + // adder moduleId hitPointId context + } // let internal isTracking() = // (int (CoverageFormat &&& ReportFormat.WithTracking) diff --git a/AltCover.Recorder/Tracer.cs b/AltCover.Recorder/Tracer.cs index 6e05646d..57c5efef 100644 --- a/AltCover.Recorder/Tracer.cs +++ b/AltCover.Recorder/Tracer.cs @@ -142,13 +142,21 @@ internal void Push(string moduleId, int hitPointId, Track context) this.PushContext(context); } - //member internal this.CatchUp(visits: Dictionary>) = - // if visits.Values |> Seq.sumBy (fun x -> x.Count) > 0 then - // visits |> Table |> this.Push String.Empty 0 + internal void CatchUp(Dictionary> visits) + { + foreach (var item in visits.Values) + { + if (item.Count > 0) + { + Push(String.Empty, 0, new Table(visits)); + return; + } + } + } internal Tracer OnStart() { - var running = this.Connect(); + var running = Connect(); running.Definitive = true; return running; } @@ -159,10 +167,13 @@ internal Tracer OnStart() // this.CatchUp visits // this.Close() - //member internal this.OnVisit visits moduleId hitPointId context = - // this.CatchUp visits - // this.Push moduleId hitPointId context - // this.Formatter.Flush() - // this.Stream.Flush() + internal void OnVisit(Dictionary> visits, + string moduleId, int hitPointId, Track context) + { + CatchUp(visits); + Push(moduleId, hitPointId, context); + Formatter.Flush(); + Stream.Flush(); + } } } \ No newline at end of file From 3b32fca36e3821facdb0aaf6ae3ee78bc1ca5654 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 12:01:49 +0100 Subject: [PATCH 47/91] Down to 27 failing --- AltCover.Recorder/Recorder.cs | 58 ++++++++++------------------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 4177bf84..85928b74 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -418,65 +418,39 @@ internal static void logException(T1 moduleId, T2 hitPointId, T3 // "AvoidLongParameterListsRule", // Justification = "Self-contained internal decorator")>] - internal delegate T HandlerFunction(T1 a, T2 b, T3 c, Exception x); + internal delegate void HandlerFunction(T1 a, T2 b, T3 c, Exception x); internal delegate void Adder(T1 a, T2 b, T3 c, T4 d); - internal static T issue71Wrapper(T1 visits, T2 moduleId, T3 hitPointId, - T4 context, HandlerFunction handler, Adder add) + internal static void issue71Wrapper(T1 visits, T2 moduleId, T3 hitPointId, + T4 context, HandlerFunction handler, Adder add) { - return default; + try + { + add(visits, moduleId, hitPointId, context); + } + catch (Exception x) + { + if (x is KeyNotFoundException || x is NullReferenceException || x is ArgumentNullException) + { + handler(moduleId, hitPointId, context, x); + } + else throw; + } } - // let - //#if !DEBUG - // inline - //#endif - // internal issue71Wrapper - // visits - // moduleId - // hitPointId - // context - // handler - // add - // = - // try - // add visits moduleId hitPointId context - // with x -> - // match x with - // | :? KeyNotFoundException - // | :? NullReferenceException - // | :? ArgumentNullException -> handler moduleId hitPointId context x - // | _ -> reraise() - internal static void curriedIssue71Wrapper(T1 visits, T2 moduleId, T3 hitPointId, T4 context, Adder add) { - return; + issue71Wrapper(visits, moduleId, hitPointId, context, logException, add); } - // let - //#if !DEBUG - // inline - //#endif - // internal curriedIssue71Wrapper - // visits - // moduleId - // hitPointId - // context - // add - // = - // issue71Wrapper visits moduleId hitPointId context logException add - internal static void addVisit(string moduleId, int hitPointId, Track context) { curriedIssue71Wrapper(visits, moduleId, hitPointId, context, Counter.addSingleVisit); } - // let internal addVisit moduleId hitPointId context = - // curriedIssue71Wrapper visits moduleId hitPointId context Counter.addSingleVisit - // type InvalidDataException with // [< SuppressMessage("Gendarme.Rules.Design.Generic", // "AvoidMethodWithUnusedGenericTypeRule", From 74d8ab2f0bd9eb6cc6c9d167a8e5d63edfe6a043 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 12:18:16 +0100 Subject: [PATCH 48/91] 26 tests to go --- AltCover.Recorder.Tests/Recorder.Tests.fs | 6 ++-- AltCover.Recorder/Recorder.cs | 43 +++++++++-------------- 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index febe2606..ce296d1a 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -452,9 +452,9 @@ module AltCoverTests = lines |> Seq.take 4 |> Seq.zip - [ "ModuleId = \"a\"" - "hitPointId = \"b\"" - "context = \"c\"" + [ "ModuleId = a" + "hitPointId = b" + "context = c" "exception = ex" ] |> Seq.iter (fun (a, b) -> Assert.That(a, Is.EqualTo b)) diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 85928b74..ccef4482 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -390,33 +390,24 @@ internal static void traceVisit(string moduleId, int hitPointId, Track context) // "CA2202:DisposeObjectsBeforeLosingScope", // Justification = "Damned if you do, damned if you don't Dispose()")>] internal static void logException(T1 moduleId, T2 hitPointId, T3 context, T4 x) - { } - - // let internal logException moduleId hitPointId context x = - // let text = - // [| sprintf "ModuleId = %A" moduleId - // sprintf "hitPointId = %A" hitPointId - // sprintf "context = %A" context - // sprintf "exception = %s" (x.ToString()) - // StackTrace().ToString() |] - - // let stamp = - // sprintf "%A" DateTime.UtcNow.Ticks - - // let filename = - // ReportFilePath + "." + stamp + ".exn" - - // use file = - // File.Open(filename, FileMode.OpenOrCreate, FileAccess.Write) - - // use writer = new StreamWriter(file) - - // text - // |> Seq.iter(fun line -> writer.WriteLine("{0}", line)) + { + var text = new string[] { + String.Format("ModuleId = {0}", moduleId), + String.Format("hitPointId = {0}", hitPointId), + String.Format("context = {0}", context), + String.Format("exception = {0}", x.ToString()), + (new StackTrace()).ToString() + }; - // [] + var stamp = DateTime.UtcNow.Ticks.ToString(); + var filename = ReportFilePath + "." + stamp + ".exn"; + using (var file = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Write)) + using (var writer = new StreamWriter(file)) + { + foreach (var line in text) + writer.WriteLine(line); + } + } internal delegate void HandlerFunction(T1 a, T2 b, T3 c, Exception x); From 72369cd8369943f6739fcbd49370c175994645db Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 13:33:55 +0100 Subject: [PATCH 49/91] 24 tests to go --- AltCover.Recorder/Recorder.cs | 89 +++++++++++++++++++---------------- AltCover.Recorder/Tracer.cs | 86 ++++++++++++++++++++------------- 2 files changed, 101 insertions(+), 74 deletions(-) diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index ccef4482..2ad4cb7f 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -197,62 +197,71 @@ internal static Dictionary> makeSamples() internal static readonly object synchronize = new Object(); - //#if NET20 - // // class needed for "[ThreadStatic] static val mutable" - // [] - // type private AsyncLocal<'a>() = - // [] - // static val mutable private item: 'a +#if NET20 - // [] - // member this.Value - // with get () = AsyncLocal<'a>.item - // and set (value) = AsyncLocal<'a>.item <- value - //#endif + // class needed for "[ThreadStatic] static val mutable" + private sealed class AsyncLocal + { + private static T item; + + public T Value + { + get { return item; } + set { item = value; } + } + } - // /// - // /// Gets or sets the current test method - // /// - // module private CallTrack = - // let value = AsyncLocal>() +#endif - // // no race conditions here - // let instance() = - // match value.Value with - // | null -> value.Value<- Stack() - // | _ -> () + /// + /// Gets or sets the current test method + /// + private static class CallTrack + { + private static AsyncLocal> value = new AsyncLocal>(); - // value.Value + // module private CallTrack = + // let value = AsyncLocal>() - // let private look op = - // let i = instance() + // no race conditions here + private static Stack instance() + { + if (value.Value == null) + value.Value = new Stack(); - // match i.Count with - // | 0 -> None - // | _ -> Some(op i) + return value.Value; + } - // let peek () = look(fun i->i.Peek()) + public static Nullable peek() + { + var i = instance(); + return (i.Count > 0) ? (Nullable)i.Peek() : null; + } - // let push x = instance().Push x + public static void push(int x) + { + instance().Push(x); + } - // let pop () = look(fun i->i.Pop()) + public static Nullable pop() + { + var i = instance(); + return (i.Count > 0) ? (Nullable)i.Pop() : null; + } + } internal static Nullable callerId { - get { return default; } //CallTrack.peek() + get { return CallTrack.peek(); } } internal static void push(int i) - { } - - // let internal push x = CallTrack.push x - - internal static int pop() - { return default; } + { + CallTrack.push(i); + } - // let internal pop() = CallTrack.pop() + internal static Nullable pop() + { return CallTrack.pop(); } /// /// Serialize access to the report file across AppDomains for the classic mode diff --git a/AltCover.Recorder/Tracer.cs b/AltCover.Recorder/Tracer.cs index 57c5efef..f225b990 100644 --- a/AltCover.Recorder/Tracer.cs +++ b/AltCover.Recorder/Tracer.cs @@ -102,37 +102,47 @@ internal void Close() private void PushContext(Track context) { - //member private this.PushContext context = - // match context with - // | Null -> this.Formatter.Write(Tag.Null |> byte) - // | Time t -> - // this.Formatter.Write(Tag.Time |> byte) - // this.Formatter.Write(t) - // | Call t -> - // this.Formatter.Write(Tag.Call |> byte) - // this.Formatter.Write(t) - // | Both b -> - // this.Formatter.Write(Tag.Both |> byte) - // this.Formatter.Write(b.Time) - // this.Formatter.Write(b.Call) - // | Table t -> - // this.Formatter.Write(Tag.Table |> byte) - - // t.Keys - // |> Seq.filter (fun k -> t.[k].Count > 0) - // |> Seq.iter (fun m -> - // this.Formatter.Write m - // this.Formatter.Write t.[m].Count - - // t.[m].Keys - // |> Seq.iter (fun p -> - // this.Formatter.Write p - // let v = t.[m].[p] - // this.Formatter.Write v.Count - // v.Tracks |> Seq.iter this.PushContext - // this.PushContext Null)) - - // this.Formatter.Write String.Empty + if (context is Null) + Formatter.Write((byte)Tag.Null); + else if (context is Time) + { + var t = (Time)context; + Formatter.Write((byte)Tag.Time); + Formatter.Write(t.Value); + } + else if (context is Call) + { + var c = (Call)context; + Formatter.Write((byte)Tag.Call); + Formatter.Write(c.Value); + } + else if (context is Both) + { + var b = (Both)context; + Formatter.Write((byte)Tag.Both); + Formatter.Write(b.Value.Time); + Formatter.Write(b.Value.Call); + } + else + { + var t = (Table)context; + Formatter.Write((byte)Tag.Table); + // t.Keys + // |> Seq.filter (fun k -> t.[k].Count > 0) + // |> Seq.iter (fun m -> + // this.Formatter.Write m + // this.Formatter.Write t.[m].Count + + // t.[m].Keys + // |> Seq.iter (fun p -> + // this.Formatter.Write p + // let v = t.[m].[p] + // this.Formatter.Write v.Count + // v.Tracks |> Seq.iter this.PushContext + // this.PushContext Null)) + } + + Formatter.Write(String.Empty); } internal void Push(string moduleId, int hitPointId, Track context) @@ -161,11 +171,19 @@ internal Tracer OnStart() return running; } + public delegate void Act(); + //member internal this.OnConnected f g = if this.IsConnected then f () else g () + internal void OnConnected(Act f, Act g) + { + if (IsConnected) f(); else g(); + } - //member internal this.OnFinish visits = - // this.CatchUp visits - // this.Close() + internal void OnFinish(Dictionary> visits) + { + CatchUp(visits); + Close(); + } internal void OnVisit(Dictionary> visits, string moduleId, int hitPointId, Track context) From f18d07635081727b98b368ede8d98a12b934da1d Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 13:46:02 +0100 Subject: [PATCH 50/91] Tracer now transcribed, needs debugging --- AltCover.Recorder.Tests/Tracer.Tests.fs | 2 +- AltCover.Recorder/Tracer.cs | 32 ++++++++++++++----------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/AltCover.Recorder.Tests/Tracer.Tests.fs b/AltCover.Recorder.Tests/Tracer.Tests.fs index 14ab93aa..e8225eb3 100644 --- a/AltCover.Recorder.Tests/Tracer.Tests.fs +++ b/AltCover.Recorder.Tests/Tracer.Tests.fs @@ -323,7 +323,7 @@ module AltCoverCoreTests = let p = p' :?> int let d = - d' :?> Dictionary> + (d' :?> Table).Value Assert.True(n |> Seq.isEmpty) Assert.True((p = 0)) diff --git a/AltCover.Recorder/Tracer.cs b/AltCover.Recorder/Tracer.cs index f225b990..45fb47cc 100644 --- a/AltCover.Recorder/Tracer.cs +++ b/AltCover.Recorder/Tracer.cs @@ -125,21 +125,25 @@ private void PushContext(Track context) } else { - var t = (Table)context; + var t = ((Table)context).Value; Formatter.Write((byte)Tag.Table); - // t.Keys - // |> Seq.filter (fun k -> t.[k].Count > 0) - // |> Seq.iter (fun m -> - // this.Formatter.Write m - // this.Formatter.Write t.[m].Count - - // t.[m].Keys - // |> Seq.iter (fun p -> - // this.Formatter.Write p - // let v = t.[m].[p] - // this.Formatter.Write v.Count - // v.Tracks |> Seq.iter this.PushContext - // this.PushContext Null)) + foreach (var key in t.Keys) + { + if (t[key].Count == 0) + continue; + Formatter.Write(key); + Formatter.Write(t[key].Count); + + foreach (var p in t[key].Keys) + { + Formatter.Write(p); + var v = t[key][p]; + Formatter.Write(v.Count); + foreach (var x in v.Tracks) + PushContext(x); + PushContext(new Null()); + } + } } Formatter.Write(String.Empty); From d63862168a673641bba6e871132866bc1fafc9d4 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 17:48:23 +0100 Subject: [PATCH 51/91] Fix delimiter write, 23 tests to go --- AltCover.Recorder/Tracer.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AltCover.Recorder/Tracer.cs b/AltCover.Recorder/Tracer.cs index 45fb47cc..d9c1f4dd 100644 --- a/AltCover.Recorder/Tracer.cs +++ b/AltCover.Recorder/Tracer.cs @@ -144,9 +144,8 @@ private void PushContext(Track context) PushContext(new Null()); } } + Formatter.Write(String.Empty); } - - Formatter.Write(String.Empty); } internal void Push(string moduleId, int hitPointId, Track context) From 67f150822d661df3dc0879812e9f93e062dd00c2 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 17:55:07 +0100 Subject: [PATCH 52/91] Transcribe the time attribute code, down to 19 failing tests --- AltCover.Recorder/Base.cs | 69 ++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 7b180329..65e87945 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -507,44 +507,37 @@ Stream outputFile if ((format == ReportFormat.NCover) && !Object.ReferenceEquals(startTimeNode, null)) { - //then - // let startTimeAttr = startTimeNode.Value - - // let measureTimeAttr = - // root.GetAttribute("measureTime") - - // let oldStartTime = - // DateTime.ParseExact(startTimeAttr, "o", null) - - // let oldMeasureTime = - // DateTime.ParseExact(measureTimeAttr, "o", null) - - // let st = minTime startTime oldStartTime - // startTime <- st.ToUniversalTime() // Min - // let mt = maxTime measureTime oldMeasureTime - // measureTime <- mt.ToUniversalTime() // Max - - // root.SetAttribute( - // "startTime", - // startTime.ToString("o", System.Globalization.CultureInfo.InvariantCulture) - // ) - - // root.SetAttribute( - // "measureTime", - // measureTime.ToString("o", System.Globalization.CultureInfo.InvariantCulture) - // ) - - // root.SetAttribute( - // "driverVersion", - // "AltCover.Recorder " - // + System.Diagnostics.FileVersionInfo - // .GetVersionInfo( - // System.Reflection.Assembly - // .GetExecutingAssembly() - // .Location - // ) - // .FileVersion - // ) + var startTimeAttr = startTimeNode.Value; + var measureTimeAttr = root.GetAttribute("measureTime"); + var oldStartTime = DateTime.ParseExact(startTimeAttr, "o", null); + var oldMeasureTime = DateTime.ParseExact(measureTimeAttr, "o", null); + + var st = minTime(startTime, oldStartTime); + startTime = st.ToUniversalTime(); // Min + var mt = maxTime(measureTime, oldMeasureTime); + measureTime = mt.ToUniversalTime(); // Max + + root.SetAttribute( + "startTime", + startTime.ToString("o", System.Globalization.CultureInfo.InvariantCulture) + ); + + root.SetAttribute( + "measureTime", + measureTime.ToString("o", System.Globalization.CultureInfo.InvariantCulture) + ); + + root.SetAttribute( + "driverVersion", + "AltCover.Recorder " + + System.Diagnostics.FileVersionInfo + .GetVersionInfo( + System.Reflection.Assembly + .GetExecutingAssembly() + .Location + ) + .FileVersion + ); } var moduleNodes = selectNodes(coverageDocument, xmlformat.m); From 13312b0702338dfbdd184e42eace78e74d803755 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 18:31:38 +0100 Subject: [PATCH 53/91] Transcribe the rest of UpdateReport - 12 failing tests now --- AltCover.Recorder/Base.cs | 157 +++++++++++++++++++------------------- 1 file changed, 79 insertions(+), 78 deletions(-) diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 65e87945..d38cb274 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -25,9 +25,6 @@ namespace AltCover.Recorder using ICSharpCode.SharpZipLib.Zip; [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)] - [SuppressMessage("Gendarme.Rules.Performance", - "AvoidUninstantiatedInternalClassesRule", - Justification = "Looks like a bug, not detecting its use")] internal sealed class ExcludeFromCodeCoverageAttribute : Attribute { } @@ -305,19 +302,19 @@ internal static class Counter { public delegate void PointProcessor(XmlElement doc, IEnumerable tracking); - // // - // // The time at which coverage run began - // // + // + // The time at which coverage run began + // internal static DateTime startTime = DateTime.UtcNow; - // // - // // The finishing time taken of the coverage run - // // + // + // The finishing time taken of the coverage run + // internal static DateTime measureTime = DateTime.UtcNow; - // // - // // The offset flag for branch counts - // // + // + // The offset flag for branch counts + // internal const int branchFlag = unchecked((int)0x80000000); internal const int branchMask = unchecked((int)0x7FFFFFFF); @@ -454,16 +451,16 @@ internal static IEnumerable selectNodes(XmlNode node, string name) return result; } - // // - // // Load the XDocument - // // - // // The XML file to load - // // Idiom to work with CA2202; we still double dispose the stream, but elude the rule. - // // If this is ever a problem, we will need mutability and two streams, with explicit - // // stream disposal if and only if the reader or writer doesn't take ownership - // // Approved way is ugly -- https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2202?view=vs-2019 - // // Also, this rule is deprecated - // // + // + // Load the XDocument + // + // The XML file to load + // Idiom to work with CA2202; we still double dispose the stream, but elude the rule. + // If this is ever a problem, we will need mutability and two streams, with explicit + // stream disposal if and only if the reader or writer doesn't take ownership + // Approved way is ugly -- https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2202?view=vs-2019 + // Also, this rule is deprecated + // private static XmlDocument readXDocument(Stream stream) { var doc = new XmlDocument(); @@ -476,12 +473,12 @@ private static XmlDocument readXDocument(Stream stream) return doc; } - // // - // // Write the XDocument - // // - // // The XML document to write - // // The XML file to write to - // // Idiom to work with CA2202 as above + // + // Write the XDocument + // + // The XML document to write + // The XML file to write to + // Idiom to work with CA2202 as above private static void writeXDocument(XmlDocument coverageDocument, Stream stream) { coverageDocument.Save(stream); } @@ -497,7 +494,6 @@ Stream outputFile { var flushStart = DateTime.UtcNow; var xmlformat = xmlByFormat(format);// throw early on unsupported - //let (m, i, m', s, v) var coverageDocument = readXDocument(coverageFile); @@ -542,55 +538,60 @@ Stream outputFile var moduleNodes = selectNodes(coverageDocument, xmlformat.m); - //moduleNodes - //|> Seq.cast - //|> Seq.map (fun el -> el.GetAttribute(i), el) - //|> Seq.filter (fun (k, _) -> counts.ContainsKey k) - //|> Seq.iter (fun (k, affectedModule) -> - // let moduleHits = counts.[k] - // // Don't do this in one leap like -- - // // affectedModule.Descendants(XName.Get("seqpnt")) - // // Get the methods, then flip their - // // contents before concatenating - // let nn = selectNodes affectedModule m' - - // nn - // |> Seq.cast - // |> Seq.collect (fun (method: XmlElement) -> - // s - // |> Seq.collect (fun (name, flag) -> - // let nodes = selectNodes method name - - // nodes - // |> Seq.cast - // |> Seq.map (fun x -> (x, flag)) - // |> Seq.toList - // |> List.rev)) - // |> Seq.mapi (fun counter (pt, flag) -> - // ((match format &&& ReportFormat.TrackMask with - // | ReportFormat.OpenCover -> - // "uspid" - // |> pt.GetAttribute - // |> (findIndexFromUspid flag) - // | _ -> counter), - // pt)) - // |> Seq.filter (fst >> moduleHits.ContainsKey) - // |> Seq.iter (fun x -> - // let pt = snd x - // let counter = fst x - - // let vc = - // Int64.TryParse( - // pt.GetAttribute(v), - // System.Globalization.NumberStyles.Integer, - // System.Globalization.CultureInfo.InvariantCulture - // ) - // |> snd - // // Treat -ve visit counts (an exemption added in analysis) as zero - // let count = moduleHits.[counter] - // let visits = (max 0L vc) + count.Total - // pt.SetAttribute(v, visits.ToString(CultureInfo.InvariantCulture)) - // pointProcess pt count.Tracks)) + foreach (var el in moduleNodes) + { + var k = el.GetAttribute(xmlformat.i); + if (!counts.ContainsKey(k)) continue; + + var moduleHits = counts[k]; + + // Don't do this in one leap like -- + // affectedModule.Descendants(XName.Get("seqpnt")) + // Get the methods, then flip their + // contents before concatenating + var nn = selectNodes(el, xmlformat.m2); + foreach (var method in nn) + { + var nodes = new List>(); + foreach (var nameflag in xmlformat.s) + { + foreach (var node in selectNodes(method, nameflag.Key)) + { + nodes.Insert(0, new KeyValuePair(node, nameflag.Value)); + } + } + + int counter = -1; + foreach (var node in nodes) + { + ++counter; + var index = counter; + if ((format & ReportFormat.TrackMask) == + ReportFormat.OpenCover) + { + index = findIndexFromUspid(node.Value, node.Key.GetAttribute("uspid")); + } + + if (!moduleHits.ContainsKey(index)) + continue; + + var pt = node.Key; + + Int64.TryParse( + pt.GetAttribute(xmlformat.v), + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out var vc + ); + + // Treat -ve visit counts (an exemption added in analysis) as zero + var count = moduleHits[index]; + var visits = Math.Max(vc, 0) + count.Total; + pt.SetAttribute(xmlformat.v, visits.ToString(CultureInfo.InvariantCulture)); + pointProcess(pt, count.Tracks); + } + } + } postProcess(coverageDocument); From a92d2e58fb771f98cf01a8301e5b0ae59aacc67d Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 18:38:00 +0100 Subject: [PATCH 54/91] fantomas --- AltCover.Recorder.Tests/Adapter.fs | 39 ++++++++++++++--------- AltCover.Recorder.Tests/Recorder.Tests.fs | 22 ++++++------- AltCover.Recorder.Tests/Tracer.Tests.fs | 3 +- AltCover.Recorder/Base.fs | 4 +-- 4 files changed, 38 insertions(+), 30 deletions(-) diff --git a/AltCover.Recorder.Tests/Adapter.fs b/AltCover.Recorder.Tests/Adapter.fs index dd41bd6a..a02774ce 100644 --- a/AltCover.Recorder.Tests/Adapter.fs +++ b/AltCover.Recorder.Tests/Adapter.fs @@ -57,7 +57,7 @@ module Adapter = init ( (number + 1L), [ Time(17L) - Both(Pair.Create(42L,23)) ] + Both(Pair.Create(42L, 23)) ] ) Instance.I.visits.[name].Add(line + 1, v2) @@ -71,7 +71,7 @@ module Adapter = let Lock = Instance.I.visits :> obj let VisitImplNone (moduleId, hitPointId) = - Instance.I.visitImpl(moduleId, hitPointId, Null()) + Instance.I.visitImpl (moduleId, hitPointId, Null()) let VisitImplMethod (moduleId, hitPointId, mId) = Instance.I.visitImpl (moduleId, hitPointId, (Call mId)) @@ -79,17 +79,17 @@ module Adapter = // Instance.I.visitImpl a b c let internal addSample (moduleId, hitPointId, context) = - Instance.I.takeSample(Sampling.Single, moduleId, hitPointId, context) + Instance.I.takeSample (Sampling.Single, moduleId, hitPointId, context) let internal addSampleUnconditional (moduleId, hitPointId, context) = - Instance.I.takeSample(Sampling.All, moduleId, hitPointId, context) + Instance.I.takeSample (Sampling.All, moduleId, hitPointId, context) let internal newBoth (time, call) = Both(Pair.Create(time, call)) let internal asCall track = Call track let internal time at = Time at - let internal untime (at:Track) = + let internal untime (at: Track) = let r = List() match at with @@ -104,7 +104,8 @@ module Adapter = let internal untable t = let r = List() - let n, p, (t':Track) = t + let n, p, (t': Track) = t + match t' with | :? Table as d -> r.Add(n) @@ -121,17 +122,18 @@ module Adapter = else output - Counter.doFlushFile(ignore, (fun _ _ -> ()), true, visits, format, report, output') + Counter.doFlushFile (ignore, (fun _ _ -> ()), true, visits, format, report, output') let internal updateReport (counts, format, coverageFile, outputFile) = - Counter.I.updateReport - (ignore, + Counter.I.updateReport ( + ignore, (fun _ _ -> ()), true, counts, format, coverageFile, - outputFile); + outputFile + ) let internal payloadSelector x = Instance.I.payloadSelector (fun _ -> x) @@ -141,8 +143,7 @@ module Adapter = let internal payloadSelection (x, y, z) = Instance.I.payloadSelection ((fun _ -> x), (fun _ -> y), (fun _ -> z)) - let internal makeNullTrace name = - Tracer.Create(name) + let internal makeNullTrace name = Tracer.Create(name) let internal makeStreamTrace s1 = let mutable t = Tracer.Create(null) @@ -173,7 +174,8 @@ module Adapter = | :? System.ArgumentNullException as ane -> ane.ParamName = unique | _ -> x.Message = unique - Instance.I.issue71Wrapper ((), (), (), (), catcher, pitcher) |> ignore + Instance.I.issue71Wrapper ((), (), (), (), catcher, pitcher) + |> ignore let internal invokeCurriedIssue71Wrapper<'T when 'T :> System.Exception> (unique: string) @@ -187,7 +189,14 @@ module Adapter = constructor.Invoke([| unique |]) :?> System.Exception |> raise - Instance.I.curriedIssue71Wrapper ("a", "b", "c", "d", pitcher) |> ignore + Instance.I.curriedIssue71Wrapper ( + "a", + "b", + "c", + "d", + pitcher + ) + |> ignore - let internal tracePush (a, b, c) = Instance.I.trace.Push (a, b, c) + let internal tracePush (a, b, c) = Instance.I.trace.Push(a, b, c) #endif \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index ce296d1a..80714bc2 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -122,12 +122,12 @@ module AltCoverTests = Assert.True(Adapter.addSample ("module", 23, Time 0L), "Test 7") Assert.True( - Adapter.addSample ("module", 24, new Both(Pair.Create(1,0))), + Adapter.addSample ("module", 24, new Both(Pair.Create(1, 0))), "Test 8" ) Assert.True( - Adapter.addSample ("module", 25, new Both(Pair.Create(1,0))), + Adapter.addSample ("module", 25, new Both(Pair.Create(1, 0))), "Test 9" ) @@ -160,16 +160,16 @@ module AltCoverTests = Instance.I.trace <- Adapter.makeNullTrace null Instance.I.recording <- false - Instance.Visit ("key", 17) + Instance.Visit("key", 17) Instance.I.recording <- true Instance.CoverageFormat <- ReportFormat.NCover - Instance.Visit (key, -23) + Instance.Visit(key, -23) Instance.CoverageFormat <- ReportFormat.OpenCover ||| ReportFormat.WithTracking - Instance.Visit (key, -23) + Instance.Visit(key, -23) let vs = Adapter.VisitsSeq() Assert.True(vs |> Seq.length = 3, sprintf "Adapter.VisitsSeq() = %A" vs) @@ -615,7 +615,7 @@ module AltCoverTests = try let key = " " Adapter.ModuleReset [| key; "key" |] - Instance.I.visitImpl ( key, 23, Adapter.asNull ()) + Instance.I.visitImpl (key, 23, Adapter.asNull ()) Instance.I.visitImpl ("key", 42, Adapter.asNull ()) Assert.That( @@ -1269,7 +1269,7 @@ module AltCoverTests = (int64 (i + 1)) )) - let NullObj:obj = null + let NullObj: obj = null Adapter.DoPause().Invoke(NullObj, null) Adapter.VisitsSeq() @@ -1370,7 +1370,7 @@ module AltCoverTests = [ 0..9 ] |> Seq.iter (fun i -> Adapter.VisitsAdd(key, i, (int64 (i + 1)))) - let NullObj:obj = null + let NullObj: obj = null Adapter.DoResume().Invoke(NullObj, null) Adapter.VisitsSeq() @@ -1476,7 +1476,7 @@ module AltCoverTests = (int64 (i + 1)) )) - let NullObj:obj = null + let NullObj: obj = null Adapter.DoExit().Invoke(NullObj, null) let head = @@ -1583,7 +1583,7 @@ module AltCoverTests = (int64 (i + 1)) )) - let NullObj:obj = null + let NullObj: obj = null Adapter.DoUnload().Invoke(NullObj, null) let head = @@ -2087,7 +2087,7 @@ module AltCoverTests = (int64 (i + 1)) )) - let NullObj:obj = null + let NullObj: obj = null Adapter.DoExit().Invoke(NullObj, null) let head = diff --git a/AltCover.Recorder.Tests/Tracer.Tests.fs b/AltCover.Recorder.Tests/Tracer.Tests.fs index e8225eb3..105f7c88 100644 --- a/AltCover.Recorder.Tests/Tracer.Tests.fs +++ b/AltCover.Recorder.Tests/Tracer.Tests.fs @@ -322,8 +322,7 @@ module AltCoverCoreTests = let n = n' :?> String let p = p' :?> int - let d = - (d' :?> Table).Value + let d = (d' :?> Table).Value Assert.True(n |> Seq.isEmpty) Assert.True((p = 0)) diff --git a/AltCover.Recorder/Base.fs b/AltCover.Recorder/Base.fs index d9f14d65..2180d94e 100644 --- a/AltCover.Recorder/Base.fs +++ b/AltCover.Recorder/Base.fs @@ -326,7 +326,7 @@ module internal Counter = (counts: Dictionary>) moduleId hitPointId - (context:Track) + (context: Track) = if counts.ContainsKey moduleId then let next = counts.[moduleId] @@ -343,7 +343,7 @@ module internal Counter = (counts: Dictionary>) moduleId hitPointId - (context:Track) + (context: Track) = match context with | :? Table as t -> I.addTable counts t.Value From 1c903559165f8cc4c0ab52c406385cb300b9bc47 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 18:51:11 +0100 Subject: [PATCH 55/91] Transcribe some more - 10 failing tests --- AltCover.Recorder/Base.cs | 85 ++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 46 deletions(-) diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index d38cb274..54c907f0 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -677,52 +677,32 @@ Stream outputFile } #else - //[] - //[] - //let internal doFlushStream - // postProcess - // pointProcess - // own - // counts - // format - // coverageFile - // output - // = - // use target = - // match output with - // | None -> new MemoryStream() :> Stream - // | Some f -> - // new FileStream( - // f, - // FileMode.OpenOrCreate, - // FileAccess.Write, - // FileShare.None, - // 4096, - // FileOptions.SequentialScan - // ) - // :> Stream - - // let outputFile = - // if Option.isSome output then - // target - // else - // coverageFile :> Stream - - // I.doFlush postProcess pointProcess own counts format coverageFile outputFile - - //[] - //[] - //[] + + internal static void doFlushStream( + Action postProcess, + PointProcessor pointProcess, + bool own, + Dictionary> counts, + ReportFormat format, + Stream coverageFile, + string output) // option + { + using (var target = string.IsNullOrEmpty(output) ? + new MemoryStream() as Stream : + new FileStream( + output, + FileMode.OpenOrCreate, + FileAccess.Write, + FileShare.None, + 4096, + FileOptions.SequentialScan + )) + { + var outputFile = string.IsNullOrEmpty(output) ? + coverageFile : target; + I.doFlush(postProcess, pointProcess, own, counts, format, coverageFile, outputFile); + } + } internal static void doFlushFile( Action postProcess, @@ -734,6 +714,19 @@ internal static void doFlushFile( string output // option ) { + var zipped = (format & ReportFormat.Zipped) != 0; + if (!zipped) + { + using (var coverageFile = new FileStream( + report, + FileMode.Open, + FileAccess.ReadWrite, + FileShare.None, + 4096, + FileOptions.SequentialScan + )) + doFlushStream(postProcess, pointProcess, own, counts, format, coverageFile, output); + } } //let internal doFlushFile postProcess pointProcess own counts format report output = From f2abf5611ec1e37fec468631c8de9e7bb74c67a5 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 19:19:18 +0100 Subject: [PATCH 56/91] The rest of Base - 8 failing tests --- AltCover.Recorder/Base.cs | 153 +++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 75 deletions(-) diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 54c907f0..dc8bb663 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -678,7 +678,7 @@ Stream outputFile #else - internal static void doFlushStream( + internal static TimeSpan doFlushStream( Action postProcess, PointProcessor pointProcess, bool own, @@ -700,11 +700,11 @@ internal static void doFlushStream( { var outputFile = string.IsNullOrEmpty(output) ? coverageFile : target; - I.doFlush(postProcess, pointProcess, own, counts, format, coverageFile, outputFile); + return I.doFlush(postProcess, pointProcess, own, counts, format, coverageFile, outputFile); } } - internal static void doFlushFile( + internal static TimeSpan doFlushFile( Action postProcess, PointProcessor pointProcess, bool own, @@ -725,81 +725,84 @@ string output // option 4096, FileOptions.SequentialScan )) - doFlushStream(postProcess, pointProcess, own, counts, format, coverageFile, output); + return doFlushStream(postProcess, pointProcess, own, counts, format, coverageFile, output); + } + else + { + var container = + new FileStream( + report + ".zip", + FileMode.Open, + FileAccess.ReadWrite, + FileShare.None, + 4096, + FileOptions.SequentialScan + ); + using (var target = string.IsNullOrEmpty(output) ? + new MemoryStream() as Stream : + new FileStream( + output, + FileMode.OpenOrCreate, + FileAccess.Write, + FileShare.None, + 4096, + FileOptions.SequentialScan + )) + { + try + { + ZipConstants.DefaultCodePage = 65001; //UTF-8 as System.IO.Compression.ZipFile uses internally + var zip = new ZipFile(container); + + try + { + var entryName = Path.GetFileName(report); + var entry = zip.GetEntry(entryName); + + var result = new TimeSpan(0); + using (var reader = zip.GetInputStream(entry)) + { + result = I.doFlush(postProcess, pointProcess, own, counts, format, reader, target); + } + + if (string.IsNullOrEmpty(output)) + { + zip.BeginUpdate(); + zip.Delete(entry); + target.Seek(0L, SeekOrigin.Begin); //|> ignore + + zip.Add(new Source(target), entryName); + zip.CommitUpdate(); + } + return result; + } + finally { zip.Close(); } + } + catch (ZipException) + { + using (var reader = new MemoryStream()) + { return I.doFlush(postProcess, pointProcess, own, counts, format, reader, target); } + } + } } } - //let internal doFlushFile postProcess pointProcess own counts format report output = - // let zipped = - // int (format &&& ReportFormat.Zipped) <> 0 - - // if not zipped then - // use coverageFile = - // new FileStream( - // report, - // FileMode.Open, - // FileAccess.ReadWrite, - // FileShare.None, - // 4096, - // FileOptions.SequentialScan - // ) - - // doFlushStream postProcess pointProcess own counts format coverageFile output - // else - // let container = - // new FileStream( - // report + ".zip", - // FileMode.Open, - // FileAccess.ReadWrite, - // FileShare.None, - // 4096, - // FileOptions.SequentialScan - // ) - - // use target = - // match output with - // | None -> new MemoryStream() :> Stream - // | Some f -> - // new FileStream( - // f, - // FileMode.OpenOrCreate, - // FileAccess.Write, - // FileShare.None, - // 4096, - // FileOptions.SequentialScan - // ) - // :> Stream - - // try - // ZipConstants.DefaultCodePage <- 65001 //UTF-8 as System.IO.Compression.ZipFile uses internally - // let zip = new ZipFile(container) - - // try - // let entryName = report |> Path.GetFileName - // let entry = zip.GetEntry(entryName) - - // let result = - // use reader = zip.GetInputStream(entry) - // I.doFlush postProcess pointProcess own counts format reader target - - // if output.IsNone then - // zip.BeginUpdate() - // zip.Delete entry - // target.Seek(0L, SeekOrigin.Begin) |> ignore - - // let source = - // { new IStaticDataSource with - // member self.GetSource() = target } - - // zip.Add(source, entryName) - // zip.CommitUpdate() - - // result - // finally - // zip.Close() - // with :? ZipException -> - // use reader = new MemoryStream() - // I.doFlush postProcess pointProcess own counts format reader target +#if !RUNNER + + internal class Source : IStaticDataSource + { + private readonly Stream _target; + + public Source(Stream t) + { + _target = t; + } + + public Stream GetSource() + { return _target; } + } + +#endif #endif // !RUNNER } From 8808f15018ed6477d16c062f5bcc0fd197217c95 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 19:21:05 +0100 Subject: [PATCH 57/91] Format change - 7 tests to go --- AltCover.Recorder.Tests/Recorder.Tests.fs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index 80714bc2..b0ee9589 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -493,9 +493,9 @@ module AltCoverTests = lines |> Seq.take 4 |> Seq.zip - [ "ModuleId = \"b\"" - "hitPointId = \"c\"" - "context = \"d\"" + [ "ModuleId = b" + "hitPointId = c" + "context = d" "exception = System.NullReferenceException: " + unique ] |> Seq.iter (fun (a, b) -> Assert.That(b, Is.EqualTo a)) From 95fe8bf3eb919fd940e2f37d9254cb88613ea3f8 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 19:30:22 +0100 Subject: [PATCH 58/91] Another formatting fix - 6 to go --- AltCover.Recorder.Tests/Recorder.Tests.fs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index b0ee9589..34b93a41 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -590,11 +590,11 @@ module AltCoverTests = lines |> Seq.take 4 |> Seq.zip - [ "ModuleId = \" \"" + [ "ModuleId = " "hitPointId = 23" - "context = Null" + "context = AltCover.Null" "exception = System.NullReferenceException: Object reference not set to an instance of an object." ] - |> Seq.iter (fun (a, b) -> Assert.True((a = b))) + |> Seq.iter (fun (a, b) -> Assert.That(a, Is.EqualTo(b))) let third = Directory.GetFiles(where, "*.exn") From 0fd9a77616300e885029e1ae7d43d3b9f5af2b66 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 20:03:21 +0100 Subject: [PATCH 59/91] Five tests to go --- AltCover.Recorder/Recorder.cs | 154 ++++++++++++++++++---------------- 1 file changed, 82 insertions(+), 72 deletions(-) diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 2ad4cb7f..ca54970d 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -118,31 +118,59 @@ internal static IEnumerable modules get { return __modules; } } - // [] - // let mutable internal modules = - // [| String.Empty |] + private static bool IsSupervised() + { + bool maybe = false; + foreach (var a in AppDomain.CurrentDomain.GetAssemblies()) + { + var n = a.GetName(); + maybe = maybe || + n.Name == "AltCover.DataCollector" + && n.FullName.EndsWith("PublicKeyToken=c02b1a9f5b7cade8", StringComparison.Ordinal); + } - // [] + return maybe && !Token.Equals("AltCover", StringComparison.Ordinal); + } - internal static bool supervision; - // let mutable internal supervision = + internal static bool supervision = IsSupervised(); // //Assembly.GetExecutingAssembly().GetName().Name = "AltCover.Recorder.g" && - // AppDomain.CurrentDomain.GetAssemblies() - // |> Seq.map(fun a -> a.GetName()) - // |> Seq.exists(fun n -> - // n.Name == "AltCover.DataCollector" - // && n.FullName.EndsWith("PublicKeyToken=c02b1a9f5b7cade8", StringComparison.Ordinal)) - // && Token<> "AltCover" internal abstract class Sampled - { } + { + protected Sampled(int visit) + { + this.visit = visit; + } + + public readonly int visit; + } + + internal class SimpleVisit : Sampled + { + public SimpleVisit(int visit) : base(visit) + { + } + } + + internal class CallVisit : Sampled + { + public readonly int call; - // type internal Sampled = - // | Visit of int - // | CallVisit of(int* int) - // | TimeVisit of(int* int64) + public CallVisit(int visit, int call) : base(visit) + { + this.call = call; + } + } + + internal class TimeVisit : Sampled + { + public readonly long time; + + public TimeVisit(int visit, long time) : base(visit) + { + this.time = time; + } + } #if DEBUG @@ -151,8 +179,8 @@ internal static class I private static class I #endif { - // let internal resources = - // ResourceManager("AltCover.Recorder.Strings", Assembly.GetExecutingAssembly()) + internal static readonly ResourceManager resources = + new ResourceManager("AltCover.Recorder.Strings", Assembly.GetExecutingAssembly()); // let internal getResource s = // let cc = @@ -220,9 +248,6 @@ private static class CallTrack { private static AsyncLocal> value = new AsyncLocal>(); - // module private CallTrack = - // let value = AsyncLocal>() - // no race conditions here private static Stack instance() { @@ -276,9 +301,6 @@ internal static string signalFile /// /// Reporting back to the mother-ship /// - // let mutable internal trace = - // Tracer.Create(signalFile ()) - private static Tracer __trace = Tracer.Create(signalFile); internal static Tracer trace @@ -462,6 +484,8 @@ internal static void addVisit(string moduleId, int hitPointId, Track context) internal static bool takeSample(Sampling strategy, string moduleId, int hitPointId, Track context) { + if (strategy == Sampling.All) + return true; return false; } @@ -501,11 +525,12 @@ internal static bool takeSample(Sampling strategy, string moduleId, int hitPoint // false) // |> Seq.fold(||) false // true if any are novel -- all must be evaluated - // /// - // /// This method is executed from instrumented assemblies. - // /// - // /// Assembly being visited - // /// Sequence Point identifier + /// + /// This method is executed from instrumented assemblies. + /// + /// Assembly being visited + /// Sequence Point identifier + /// What sort of visit internal static void visitImpl(string moduleId, int hitPointId, Track context) { if @@ -521,28 +546,18 @@ internal static void visitImpl(string moduleId, int hitPointId, Track context) traceVisit(moduleId, hitPointId, context); } } - - // let internal visitImpl moduleId hitPointId context = - // if - // (Sample = Sampling.All - // || takeSample Sample moduleId hitPointId context) - // then - // let adder = - // if Defer || supervision || (trace.IsConnected |> not) then - // addVisit - // else - // traceVisit - - // adder moduleId hitPointId context } - // let internal isTracking() = - // (int (CoverageFormat &&& ReportFormat.WithTracking) - // <> 0) + internal static bool isTracking + { + get { return (CoverageFormat & ReportFormat.WithTracking) != 0; } + } - // let internal isTrackingRunner() = isTracking() && isRunner + internal static bool isTrackingRunner() + { + return isTracking && isRunner; + } - // let internal granularity() = Timer internal static long granularity { get { return Timer; } @@ -587,11 +602,10 @@ internal static Track payloadSelector(PayloadEnabler enable) // let internal payloadSelector enable = payloadControl granularity enable - internal static void visitSelection(T track, string moduleId, int hitPointId) - { } - - // let internal visitSelection track moduleId hitPointId = - // visitImpl moduleId hitPointId track + internal static void visitSelection(Track track, string moduleId, int hitPointId) + { + visitImpl(moduleId, hitPointId, track); + } // let internal flushCounter(finish: Close) _ = // match finish with @@ -634,34 +648,30 @@ internal static void visitSelection(T track, string moduleId, int hitPointId) // Public API public static void Visit(string moduleId, int hitPointId) { - // let Visit moduleId hitPointId = - // if I.recording then - // I.visitSelection - // (if I.isTracking() then - // I.payloadSelector I.isTrackingRunner - // else - // Null) - // moduleId - // hitPointId + if (I.recording) + { + var track = I.isTracking ? + I.payloadSelector(I.isTrackingRunner) : + new Null(); + I.visitSelection(track, moduleId, hitPointId); + } } //// The moduleId strings are not the hash or guids normally found there public static void Push(int caller) { - //let Push caller = - // I.push caller + I.push(caller); - // if I.isTrackingRunner() then - // I.visitSelection(Time DateTime.UtcNow.Ticks) Track.Entry caller + if (I.isTrackingRunner()) + I.visitSelection(new Time(DateTime.UtcNow.Ticks), Track.Entry, caller); } public static void Pop() { - //let Pop() = - // let caller = I.pop() + var caller = I.pop(); - // if I.isTrackingRunner() && caller.IsSome then - // I.visitSelection(Time DateTime.UtcNow.Ticks) Track.Exit caller.Value + if (I.isTrackingRunner() && caller.HasValue) + I.visitSelection(new Time(DateTime.UtcNow.Ticks), Track.Exit, caller.Value); } //// Used by the datacollector From 5b0ea861b5cec25427cd8a1e6689af5d06679938 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 20:12:52 +0100 Subject: [PATCH 60/91] Four tests to go --- AltCover.Recorder.Tests/Recorder.Tests.fs | 12 ++++++------ AltCover.Recorder/Recorder.cs | 14 ++++++-------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index 34b93a41..647bfb09 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -82,7 +82,7 @@ module AltCoverTests = let v1 = DateTime.UtcNow.Ticks let probe = Instance.I.clock () let v2 = DateTime.UtcNow.Ticks - Assert.True(Instance.I.granularity = 0L) + Assert.True(Instance.I.granularity () = 0L) Assert.True(probe >= v1) Assert.True(probe <= v2) @@ -181,7 +181,7 @@ module AltCoverTests = sprintf "Adapter.VisitsEntrySeq %A = %A" key vesk ) - Assert.True(Adapter.VisitCount(key, -23) = 2L) + Assert.That(Adapter.VisitCount(key, -23), Is.EqualTo 2L) Assert.That(Counter.totalVisits, Is.EqualTo 1L) Assert.That(Counter.branchVisits, Is.EqualTo 1L) finally @@ -274,11 +274,11 @@ module AltCoverTests = Adapter.VisitsClear() Assert.True(Instance.I.callerId.HasValue |> not) - Assert.True(Adapter.payloadSelector false = Adapter.asNull ()) - Assert.True(Adapter.payloadSelector true = Adapter.asNull ()) + Assert.That(Adapter.payloadSelector false, Is.EqualTo <| Adapter.asNull ()) + Assert.That(Adapter.payloadSelector true, Is.EqualTo <| Adapter.asNull ()) Instance.Push 4321 - Assert.True(Adapter.payloadSelector false = Adapter.asNull ()) - Assert.True(Adapter.payloadSelector true = (Adapter.asCall 4321)) + Assert.That(Adapter.payloadSelector false, Is.EqualTo <| Adapter.asNull ()) + Assert.That(Adapter.payloadSelector true, Is.EqualTo(Adapter.asCall 4321)) try Instance.Push 6789 diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index ca54970d..b2b09c56 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -558,9 +558,9 @@ internal static bool isTrackingRunner() return isTracking && isRunner; } - internal static long granularity + internal static long granularity() { - get { return Timer; } + return Timer; } internal static long clock() @@ -595,12 +595,10 @@ internal static Track payloadControl(FrequencyProvider frequency, PayloadProvide return payloadSelection(clock, frequency, wantPayload); } - internal delegate T PayloadEnabler(); - - internal static Track payloadSelector(PayloadEnabler enable) - { return default; } - - // let internal payloadSelector enable = payloadControl granularity enable + internal static Track payloadSelector(PayloadProvider enable) + { + return payloadControl(granularity, enable); + } internal static void visitSelection(Track track, string moduleId, int hitPointId) { From 2e50519512db02212b0d31b8c0c0d1851d3541ed Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 20:17:35 +0100 Subject: [PATCH 61/91] Improve failre reports - payloadSelector is next to transcribe --- AltCover.Recorder.Tests/Recorder.Tests.fs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index 647bfb09..29c6f3fd 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -211,11 +211,11 @@ module AltCoverTests = ||| ReportFormat.WithTracking Assert.False(Instance.I.callerId.HasValue) - Assert.True(Adapter.payloadSelector false = Adapter.asNull ()) - Assert.True(Adapter.payloadSelector true = Adapter.asNull ()) + Assert.That(Adapter.payloadSelector false, Is.EqualTo <| Adapter.asNull ()) + Assert.That(Adapter.payloadSelector true, Is.EqualTo <| Adapter.asNull ()) Instance.Push 4321 - Assert.True(Adapter.payloadSelector false = Adapter.asNull ()) - Assert.True(Adapter.payloadSelector true = (Adapter.asCall 4321)) + Assert.That(Adapter.payloadSelector false, Is.EqualTo <| Adapter.asNull ()) + Assert.That(Adapter.payloadSelector true, Is.EqualTo <| (Adapter.asCall 4321)) try Instance.Push 6789 @@ -230,7 +230,7 @@ module AltCoverTests = finally Instance.Pop() - Assert.True((Adapter.payloadSelector true = (Adapter.asCall 4321))) + Assert.That(Adapter.payloadSelector true, Is.EqualTo(Adapter.asCall 4321)) finally Instance.Pop() Instance.CoverageFormat <- ReportFormat.NCover @@ -293,7 +293,7 @@ module AltCoverTests = finally Instance.Pop() - Assert.True((Adapter.payloadSelector true = (Adapter.asCall 4321))) + Assert.That(Adapter.payloadSelector true, Is.EqualTo(Adapter.asCall 4321)) finally Instance.Pop() Instance.I.isRunner <- false From 4166be23453b623e71691beabb406fbebfe2a2c6 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 21:02:22 +0100 Subject: [PATCH 62/91] Payload selector & Minor tidying - 2 tests to go --- AltCover.Recorder.Tests/Recorder.Tests.fs | 6 ++-- AltCover.Recorder/Recorder.cs | 34 +++++++++-------------- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index 29c6f3fd..c98b580b 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -97,11 +97,9 @@ module AltCoverTests = 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 "<=" [] diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index b2b09c56..8a126790 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -417,9 +417,6 @@ internal static void traceVisit(string moduleId, int hitPointId, Track context) } } - // [] internal static void logException(T1 moduleId, T2 hitPointId, T3 context, T4 x) { var text = new string[] { @@ -473,15 +470,6 @@ internal static void addVisit(string moduleId, int hitPointId, Track context) curriedIssue71Wrapper(visits, moduleId, hitPointId, context, Counter.addSingleVisit); } - // type InvalidDataException with - // [< SuppressMessage("Gendarme.Rules.Design.Generic", - // "AvoidMethodWithUnusedGenericTypeRule", - // Justification = "Matches clause type") >] - // static member Throw<'T>(message: obj) : 'T = - // message.ToString() - // |> InvalidDataException - // |> raise - internal static bool takeSample(Sampling strategy, string moduleId, int hitPointId, Track context) { if (strategy == Sampling.All) @@ -577,15 +565,19 @@ internal static Track payloadSelection(ClockProvider clock, { if (wantPayload()) { - // match(frequency (), callerId ()) with - // | (0L, None) -> Null - // | (t, None) -> Time(t* (clock () / t)) - // | (0L, n) -> Call n.Value - // | (t, n) -> - // Both - // { - // Time = t * (clock() / t) - // Call = n.Value } + var f = frequency(); + var id = callerId; + if (f == 0) + { + return id.HasValue ? + (Track)new Call(id.Value) : + new Null(); + } + + var t = f * (clock() / f); + return id.HasValue ? + (Track)new Both(Pair.Create(t, id.Value)) : + new Time(t); } return new Null(); } From 34f21593cb512eb218b9d06150c59732f16e2613 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 15 Jul 2024 21:39:22 +0100 Subject: [PATCH 63/91] Transcribe more, and make the stubs fail hard - 4 tests now fail --- AltCover.Recorder/Recorder.cs | 267 ++++++++++++++++++++-------------- 1 file changed, 154 insertions(+), 113 deletions(-) diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 8a126790..d7e0b6f3 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -2,19 +2,12 @@ namespace AltCover.Recorder { using System; using System.Collections.Generic; - using System.ComponentModel; using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.Drawing; using System.IO; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; - using System.Runtime.Remoting.Contexts; - using System.Security.Policy; - using System.Text.RegularExpressions; using System.Threading; public static class Instance @@ -103,10 +96,10 @@ internal static string Token get { return "AltCover"; } } - // /// - // /// Gets the indexed module tokens - // /// This property's IL code is modified to store instrumentation results - // /// + /// + /// Gets the indexed module tokens + /// This property's IL code is modified to store instrumentation results + /// private static IEnumerable __modules = new string[] { string.Empty }; internal static IEnumerable modules @@ -132,8 +125,8 @@ private static bool IsSupervised() return maybe && !Token.Equals("AltCover", StringComparison.Ordinal); } + //Assembly.GetExecutingAssembly().GetName().Name = "AltCover.Recorder.g" && internal static bool supervision = IsSupervised(); - // //Assembly.GetExecutingAssembly().GetName().Name = "AltCover.Recorder.g" && internal abstract class Sampled { @@ -182,13 +175,16 @@ private static class I internal static readonly ResourceManager resources = new ResourceManager("AltCover.Recorder.Strings", Assembly.GetExecutingAssembly()); - // let internal getResource s = - // let cc = - // System.Globalization.CultureInfo.CurrentUICulture + internal static string getResource(string s) + { + throw new NotImplementedException("getResource"); + // let cc = + // System.Globalization.CultureInfo.CurrentUICulture - // [cc.Name; cc.Parent.Name; "en" ] - // |> Seq.map(fun l -> resources.GetString(s + "." + l)) - // |> Seq.tryFind(String.IsNullOrEmpty >> not) + // [cc.Name; cc.Parent.Name; "en" ] + // |> Seq.map(fun l -> resources.GetString(s + "." + l)) + // |> Seq.tryFind(String.IsNullOrEmpty >> not) + } private static Dictionary> makeVisits() { @@ -312,22 +308,35 @@ internal static Tracer trace get { return __trace; } } - // let internal withMutex(f: bool -> 'a) = - // let own = mutex.WaitOne(1000) + internal delegate T MutexHandler(bool own); + + internal static T withMutex(MutexHandler f) + { + var own = mutex.WaitOne(1000); - // try - // f (own) - // finally - // if own then - // mutex.ReleaseMutex() + try + { + return f(own); + } + finally + { + if (own) mutex.ReleaseMutex(); + } + } - // let internal initialiseTrace(t: Tracer) = - // withMutex(fun _ -> - // trace<- t.OnStart() - // isRunner <- isRunner || trace.IsConnected) + internal static void initialiseTrace(Tracer t) + { + withMutex( + x => + { + trace = t.OnStart(); + isRunner = isRunner || trace.IsConnected; + return true; // dummy + } + ); + } - // let internal watcher = - // new FileSystemWatcher() + internal static FileSystemWatcher watcher = new FileSystemWatcher(); private static bool __recording = true; @@ -352,6 +361,8 @@ internal static void clear() /// internal static void flushAll(Close _) { + throw new NotImplementedException("flushAll"); + // let internal flushAll _ = // let counts = visits // clear() @@ -375,28 +386,34 @@ internal static void flushAll(Close _) // |> Option.iter(fun s -> Console.Out.WriteLine(s, delta.TotalSeconds)))) } - // let internal flushPause() = - // ("PauseHandler") - // |> getResource - // |> Option.iter Console.Out.WriteLine + internal static void flushPause() + { + throw new NotImplementedException("flushPause"); + // ("PauseHandler") + // |> getResource + // |> Option.iter Console.Out.WriteLine - // recording<- false - // flushAll Pause - // trace<- signalFile () |> Tracer.Create + // recording<- false + // flushAll Pause + // trace<- signalFile () |> Tracer.Create + } - // let internal flushResume() = - // ("ResumeHandler") - // |> getResource - // |> Option.iter Console.Out.WriteLine + internal static void flushResume() + { + throw new NotImplementedException("flushResume"); + // ("ResumeHandler") + // |> getResource + // |> Option.iter Console.Out.WriteLine - // let wasConnected = isRunner - // initialiseTrace trace + // let wasConnected = isRunner + // initialiseTrace trace - // if (wasConnected<> isRunner) then - // samples<- makeSamples () - // clear () + // if (wasConnected<> isRunner) then + // samples<- makeSamples () + // clear () - // recording <- true + // recording <- true + } internal static void traceVisit(string moduleId, int hitPointId, Track context) { @@ -474,44 +491,44 @@ internal static bool takeSample(Sampling strategy, string moduleId, int hitPoint { if (strategy == Sampling.All) return true; - return false; - } - - // let internal takeSample strategy moduleId hitPointId(context: Track) = - // match strategy with - // | Sampling.All -> true - // | _ -> - // (match context with - // | Null -> [Visit hitPointId] - // | Time t -> - // [Visit hitPointId - // TimeVisit(hitPointId, t)] - // | Call c -> - // [Visit hitPointId - // CallVisit(hitPointId, c)] - // | Both b -> - // [Visit hitPointId - // TimeVisit(hitPointId, b.Time) - // CallVisit(hitPointId, b.Call)] - // | _ -> context |> InvalidDataException.Throw) - // |> Seq.map(fun hit -> - // if samples.ContainsKey(moduleId) then - // let next = samples.[moduleId] - - // let mutable hasPointKey = - // next.ContainsKey(hit) - - // if hasPointKey |> not then - // lock next(fun () -> - // hasPointKey<- next.ContainsKey(hit) - - // if hasPointKey |> not then - // next.Add(hit, true)) - - // not hasPointKey - // else - // false) - // |> Seq.fold(||) false // true if any are novel -- all must be evaluated + throw new NotImplementedException("takeSample"); + + // let internal takeSample strategy moduleId hitPointId(context: Track) = + // match strategy with + // | Sampling.All -> true + // | _ -> + // (match context with + // | Null -> [Visit hitPointId] + // | Time t -> + // [Visit hitPointId + // TimeVisit(hitPointId, t)] + // | Call c -> + // [Visit hitPointId + // CallVisit(hitPointId, c)] + // | Both b -> + // [Visit hitPointId + // TimeVisit(hitPointId, b.Time) + // CallVisit(hitPointId, b.Call)] + // | _ -> context |> InvalidDataException.Throw) + // |> Seq.map(fun hit -> + // if samples.ContainsKey(moduleId) then + // let next = samples.[moduleId] + + // let mutable hasPointKey = + // next.ContainsKey(hit) + + // if hasPointKey |> not then + // lock next(fun () -> + // hasPointKey<- next.ContainsKey(hit) + + // if hasPointKey |> not then + // next.Add(hit, true)) + + // not hasPointKey + // else + // false) + // |> Seq.fold(||) false // true if any are novel -- all must be evaluated + } /// /// This method is executed from instrumented assemblies. @@ -597,42 +614,66 @@ internal static void visitSelection(Track track, string moduleId, int hitPointId visitImpl(moduleId, hitPointId, track); } - // let internal flushCounter(finish: Close) _ = - // match finish with - // | Resume -> flushResume() - // | Pause -> flushPause() - // | _ -> - // recording<- false + internal static void flushCounter(Close finish, EventArgs _) + { + throw new NotImplementedException("flushCounter"); + // match finish with + // | Resume -> flushResume() + // | Pause -> flushPause() + // | _ -> + // recording<- false - // if supervision |> not then - // flushAll finish + // if supervision |> not then + // flushAll finish + } // Register event handling - internal static FileSystemEventHandler doPause = default; + internal static FileSystemEventHandler doPause = PauseHandler; - //(FileSystemEventHandlerfun _ a -> flushCounter Pause a) + internal static void PauseHandler(object sender, FileSystemEventArgs e) + { + flushCounter(Close.Pause, e); + } - internal static FileSystemEventHandler doResume = default; - //FileSystemEventHandler(fun _ a -> flushCounter Resume a) + internal static FileSystemEventHandler doResume = ResumeHandler; - internal static EventHandler doUnload = default; - //EventHandler(fun _ a -> flushCounter DomainUnload a) + internal static void ResumeHandler(object sender, FileSystemEventArgs e) + { + flushCounter(Close.Resume, e); + } - internal static EventHandler doExit = default; - //EventHandler(fun _ a -> flushCounter ProcessExit a) + internal static EventHandler doUnload = UnloadHandler; - // let internal startWatcher() = - // watcher.Path<- Path.GetDirectoryName<| signalFile () - // watcher.Filter<- Path.GetFileName<| signalFile () - // watcher.add_Created doResume - // watcher.add_Deleted doPause - // watcher.EnableRaisingEvents<- watcher.Path |> String.IsNullOrEmpty |> not + internal static void UnloadHandler(object sender, EventArgs e) + { + flushCounter(Close.DomainUnload, e); + } - //do - // AppDomain.CurrentDomain.add_DomainUnload doUnload - // AppDomain.CurrentDomain.add_ProcessExit doExit - // startWatcher () - // signalFile () |> Tracer.Create |> initialiseTrace + internal static EventHandler doExit = ExitHandler; + + internal static void ExitHandler(object sender, EventArgs e) + { + flushCounter(Close.ProcessExit, e); + } + + internal static void startWatcher() + { + watcher.Path = Path.GetDirectoryName(signalFile); + watcher.Filter = Path.GetFileName(signalFile); + watcher.Created += doResume; + watcher.Deleted += doPause; + watcher.EnableRaisingEvents = !String.IsNullOrEmpty(watcher.Path); + } + + static I() + { + AppDomain.CurrentDomain.DomainUnload += doUnload; + AppDomain.CurrentDomain.ProcessExit += doExit; + startWatcher(); + initialiseTrace( + Tracer.Create(signalFile) + ); + } } // Public API From 784ca41e05bfefddf771f41e723cc5756ba4ff18 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Tue, 16 Jul 2024 09:16:38 +0100 Subject: [PATCH 64/91] Implement on the flush side, clear 2 tests --- AltCover.Recorder/Recorder.cs | 134 +++++++++++++++++++--------------- 1 file changed, 77 insertions(+), 57 deletions(-) diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index d7e0b6f3..a49dd2cd 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -177,13 +177,16 @@ private static class I internal static string getResource(string s) { - throw new NotImplementedException("getResource"); - // let cc = - // System.Globalization.CultureInfo.CurrentUICulture + var cc = System.Globalization.CultureInfo.CurrentUICulture; + var names = new string[] { cc.Name, cc.Parent.Name, "en" }; + foreach (var name in names) + { + var result = resources.GetString(s + "." + name); + if (!string.IsNullOrEmpty(result)) + return result; + } - // [cc.Name; cc.Parent.Name; "en" ] - // |> Seq.map(fun l -> resources.GetString(s + "." + l)) - // |> Seq.tryFind(String.IsNullOrEmpty >> not) + return null; } private static Dictionary> makeVisits() @@ -308,15 +311,15 @@ internal static Tracer trace get { return __trace; } } - internal delegate T MutexHandler(bool own); + internal delegate void MutexHandler(bool own); - internal static T withMutex(MutexHandler f) + internal static void withMutex(MutexHandler f) { var own = mutex.WaitOne(1000); try { - return f(own); + f(own); } finally { @@ -331,7 +334,6 @@ internal static void initialiseTrace(Tracer t) { trace = t.OnStart(); isRunner = isRunner || trace.IsConnected; - return true; // dummy } ); } @@ -361,58 +363,73 @@ internal static void clear() /// internal static void flushAll(Close _) { - throw new NotImplementedException("flushAll"); + var counts = visits; + clear(); - // let internal flushAll _ = - // let counts = visits - // clear() - - // trace.OnConnected(fun () -> trace.OnFinish counts) (fun () -> - // match counts.Values |> Seq.sumBy (fun x -> x.Count) with - // | 0 -> () - // | _ -> - // withMutex(fun own -> - // let delta = - // Counter.doFlushFile - // ignore - // (fun _ _ -> ()) - // own - // counts - // CoverageFormat - // ReportFilePath - // None + trace.OnConnected( + () => trace.OnFinish(counts), + () => + { + var any = false; + foreach (var n in counts.Values) + { + if (n.Count > 0) + { + any = true; + break; + } + } - // getResource "Coverage statistics flushing took {0:N} seconds" - // |> Option.iter(fun s -> Console.Out.WriteLine(s, delta.TotalSeconds)))) + if (!any) return; + + withMutex(own => + { + var delta = + Counter.doFlushFile( + x => { return; }, + (x, y) => { return; }, + own, + counts, + CoverageFormat, + ReportFilePath, + null + ); + + var message = getResource("Coverage statistics flushing took {0:N} seconds"); + if (!string.IsNullOrEmpty(message)) + Console.Out.WriteLine(message, delta.TotalSeconds); + }); + } + ); } internal static void flushPause() { - throw new NotImplementedException("flushPause"); - // ("PauseHandler") - // |> getResource - // |> Option.iter Console.Out.WriteLine + var message = getResource("PauseHandler"); + if (!string.IsNullOrEmpty(message)) + Console.Out.WriteLine(message); - // recording<- false - // flushAll Pause - // trace<- signalFile () |> Tracer.Create + recording = false; + flushAll(Close.Pause); + trace = Tracer.Create(signalFile); } internal static void flushResume() { - throw new NotImplementedException("flushResume"); - // ("ResumeHandler") - // |> getResource - // |> Option.iter Console.Out.WriteLine + var message = getResource("ResumeHandler"); + if (!string.IsNullOrEmpty(message)) + Console.Out.WriteLine(message); - // let wasConnected = isRunner - // initialiseTrace trace + var wasConnected = isRunner; + initialiseTrace(trace); - // if (wasConnected<> isRunner) then - // samples<- makeSamples () - // clear () + if (wasConnected != isRunner) + { + samples = makeSamples(); + clear(); + } - // recording <- true + recording = true; } internal static void traceVisit(string moduleId, int hitPointId, Track context) @@ -616,15 +633,18 @@ internal static void visitSelection(Track track, string moduleId, int hitPointId internal static void flushCounter(Close finish, EventArgs _) { - throw new NotImplementedException("flushCounter"); - // match finish with - // | Resume -> flushResume() - // | Pause -> flushPause() - // | _ -> - // recording<- false - - // if supervision |> not then - // flushAll finish + switch (finish) + { + case Close.Resume: + flushResume(); break; + case Close.Pause: + flushPause(); break; + default: + recording = false; + if (!supervision) + flushAll(finish); + break; + } } // Register event handling From 1e9a86d6b98774c59b2d76aba3ebea053ccb7b3a Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Tue, 16 Jul 2024 09:48:49 +0100 Subject: [PATCH 65/91] Last recorder test, transcription errors --- AltCover.Recorder.Tests/Recorder.Tests.fs | 4 +- AltCover.Recorder/Recorder.cs | 128 +++++++++++++++------- 2 files changed, 88 insertions(+), 44 deletions(-) diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index c98b580b..d3d1cc7c 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -120,12 +120,12 @@ module AltCoverTests = Assert.True(Adapter.addSample ("module", 23, Time 0L), "Test 7") Assert.True( - Adapter.addSample ("module", 24, new Both(Pair.Create(1, 0))), + Adapter.addSample ("module", 24, new Both(Pair.Create(0, 1))), "Test 8" ) Assert.True( - Adapter.addSample ("module", 25, new Both(Pair.Create(1, 0))), + Adapter.addSample ("module", 25, new Both(Pair.Create(0, 1))), "Test 9" ) diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index a49dd2cd..9edc5f93 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -143,6 +143,20 @@ internal class SimpleVisit : Sampled public SimpleVisit(int visit) : base(visit) { } + + public override bool Equals(object obj) + { + if (obj is SimpleVisit visit1) + { + return visit == visit1.visit; + } + return false; + } + + public override int GetHashCode() + { + return visit.GetHashCode(); + } } internal class CallVisit : Sampled @@ -153,6 +167,20 @@ public CallVisit(int visit, int call) : base(visit) { this.call = call; } + + public override bool Equals(object obj) + { + if (obj is CallVisit visit1) + { + return (visit == visit1.visit) && (call == visit1.call); + } + return false; + } + + public override int GetHashCode() + { + return visit.GetHashCode() ^ call.GetHashCode(); + } } internal class TimeVisit : Sampled @@ -163,13 +191,28 @@ public TimeVisit(int visit, long time) : base(visit) { this.time = time; } + + public override bool Equals(object obj) + { + if (obj is TimeVisit visit1) + { + return (visit == visit1.visit) && (time == visit1.time); + } + return false; + } + + public override int GetHashCode() + { + return visit.GetHashCode() ^ time.GetHashCode(); + } } #if DEBUG internal static class I #else - private static class I + + private static class I #endif { internal static readonly ResourceManager resources = @@ -304,9 +347,7 @@ internal static string signalFile internal static Tracer trace { -#if DEBUG set { __trace = value; } -#endif [MethodImpl(MethodImplOptions.NoInlining)] get { return __trace; } } @@ -344,9 +385,7 @@ internal static void initialiseTrace(Tracer t) internal static bool recording { -#if DEBUG set { __recording = value; } -#endif [MethodImpl(MethodImplOptions.NoInlining)] get { return __recording; } } @@ -508,43 +547,48 @@ internal static bool takeSample(Sampling strategy, string moduleId, int hitPoint { if (strategy == Sampling.All) return true; - throw new NotImplementedException("takeSample"); - - // let internal takeSample strategy moduleId hitPointId(context: Track) = - // match strategy with - // | Sampling.All -> true - // | _ -> - // (match context with - // | Null -> [Visit hitPointId] - // | Time t -> - // [Visit hitPointId - // TimeVisit(hitPointId, t)] - // | Call c -> - // [Visit hitPointId - // CallVisit(hitPointId, c)] - // | Both b -> - // [Visit hitPointId - // TimeVisit(hitPointId, b.Time) - // CallVisit(hitPointId, b.Call)] - // | _ -> context |> InvalidDataException.Throw) - // |> Seq.map(fun hit -> - // if samples.ContainsKey(moduleId) then - // let next = samples.[moduleId] - - // let mutable hasPointKey = - // next.ContainsKey(hit) - - // if hasPointKey |> not then - // lock next(fun () -> - // hasPointKey<- next.ContainsKey(hit) - - // if hasPointKey |> not then - // next.Add(hit, true)) - - // not hasPointKey - // else - // false) - // |> Seq.fold(||) false // true if any are novel -- all must be evaluated + + Sampled[] sampleds = null; + if (context is Null) + sampleds = new Sampled[] { new SimpleVisit(hitPointId) }; + else if (context is Time) + sampleds = new Sampled[] { new SimpleVisit(hitPointId), + new TimeVisit(hitPointId, ((Time)context).Value) }; + else if (context is Call) + sampleds = new Sampled[] { new SimpleVisit(hitPointId), + new CallVisit(hitPointId, ((Call)context).Value) }; + else if (context is Both) + { + var b = (Both)context; + sampleds = new Sampled[] { new SimpleVisit(hitPointId), + new TimeVisit(hitPointId, b.Value.Time), + new CallVisit(hitPointId, b.Value.Call)}; + } + else throw new InvalidDataException(context.ToString()); + + var wanted = false; + foreach (var sample in sampleds) + { + if (!samples.ContainsKey(moduleId)) + continue; + var next = samples[moduleId]; + var hasPointKey = next.ContainsKey(sample); + if (!hasPointKey) + { + lock (next) + { + hasPointKey = next.ContainsKey(sample); + if (!hasPointKey) + { + next.Add(sample, true); + } + } + + wanted = wanted || !hasPointKey; + } + } + + return wanted; } /// From 3c60ccc27758cd5e21413f977d6090b51524efb5 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Tue, 16 Jul 2024 10:25:04 +0100 Subject: [PATCH 66/91] Static analysis cruft --- AltCover.Base/AltCover.Base.csproj | 3 +- AltCover.Recorder/Base.cs | 87 +++++++++++++++++++++++++----- 2 files changed, 76 insertions(+), 14 deletions(-) diff --git a/AltCover.Base/AltCover.Base.csproj b/AltCover.Base/AltCover.Base.csproj index aece210f..273f0def 100644 --- a/AltCover.Base/AltCover.Base.csproj +++ b/AltCover.Base/AltCover.Base.csproj @@ -4,7 +4,7 @@ netstandard2.0 AltCover AltCover.Base - RUNNER + RUNNER;LITEVERSION @@ -15,6 +15,7 @@ + diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index dc8bb663..eb2bfa9a 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -48,12 +48,24 @@ internal enum ReportFormat Zipped = 128, }; + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUncalledPrivateCodeRule", + Justification = "Internals Visible To")] + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUninstantiatedInternalClassesRule", + Justification = "Internals Visible To")] internal enum Sampling { All = 0, Single = 1, }; + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUncalledPrivateCodeRule", + Justification = "Internals Visible To")] + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUninstantiatedInternalClassesRule", + Justification = "Internals Visible To")] internal enum Tag { Null = 0, @@ -64,11 +76,23 @@ internal enum Tag } [ExcludeFromCodeCoverage] + [SuppressMessage("Gendarme.Rules.Performance", + "ImplementEqualsTypeRule", + Justification = "No use case")] + [SuppressMessage("Gendarme.Rules.Design", + "OperatorEqualsShouldBeOverloadedRule", + Justification = "No use case")] internal struct Pair { public long Time; public int Call; + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUncalledPrivateCodeRule", + Justification = "Internals Visible To")] + [SuppressMessage("Gendarme.Rules.Performance", + "OverrideValueTypeDefaultsRule", + Justification = "You what, mate?")] public static Pair Create(long time, int call) { return new Pair { Time = time, Call = call }; @@ -97,10 +121,13 @@ public override int GetHashCode() } } + [SuppressMessage("Gendarme.Rules.Performance", + "ImplementEqualsTypeRule", + Justification = "abstract type, No use case")] internal abstract class Track { - internal static readonly string Entry = "\u2611"; // BALLOT BOX WITH CHECK - internal static readonly string Exit = "\u2612"; // BALLOT BOX WITH X + internal const string Entry = "\u2611"; // BALLOT BOX WITH CHECK + internal const string Exit = "\u2612"; // BALLOT BOX WITH X public override bool Equals(object obj) { @@ -113,6 +140,9 @@ public override int GetHashCode() } } + [SuppressMessage("Gendarme.Rules.Performance", + "ImplementEqualsTypeRule", + Justification = "No use case")] internal class Null : Track { public override string ToString() @@ -131,6 +161,9 @@ public override int GetHashCode() } } + [SuppressMessage("Gendarme.Rules.Performance", + "ImplementEqualsTypeRule", + Justification = "No use case")] internal class Time : Track { public readonly long Value; @@ -142,9 +175,9 @@ public Time(long time) public override bool Equals(object obj) { - if (obj is Time) + if (obj is Time t) { - return Value == ((Time)obj).Value; + return Value == t.Value; } return false; @@ -161,7 +194,10 @@ public override string ToString() } } - internal class Call : Track + [SuppressMessage("Gendarme.Rules.Performance", + "ImplementEqualsTypeRule", + Justification = "No use case")] + internal sealed class Call : Track { public readonly int Value; @@ -172,9 +208,9 @@ public Call(int call) public override bool Equals(object obj) { - if (obj is Call) + if (obj is Call c) { - return Value == ((Call)obj).Value; + return Value == c.Value; } return false; @@ -191,7 +227,10 @@ public override string ToString() } } - internal class Both : Track + [SuppressMessage("Gendarme.Rules.Performance", + "ImplementEqualsTypeRule", + Justification = "No use case")] + internal sealed class Both : Track { public readonly Pair Value; @@ -222,7 +261,7 @@ public override string ToString() } } - internal class Table : Track + internal sealed class Table : Track { public readonly Dictionary> Value; @@ -232,7 +271,10 @@ public Table(Dictionary> table) } } - internal class PointVisit + [SuppressMessage("Gendarme.Rules.Performance", + "ImplementEqualsTypeRule", + Justification = "No use case")] + internal sealed class PointVisit { public long Count; public readonly List Tracks; @@ -300,6 +342,9 @@ internal long Total internal static class Counter { + [SuppressMessage("Gendarme.Rules.Design.Generic", + "AvoidDeclaringCustomDelegatesRule", + Justification = "Net Framework 2.0")] public delegate void PointProcessor(XmlElement doc, IEnumerable tracking); // @@ -327,7 +372,8 @@ internal static class Counter internal static class I #else - static private class I + + private static class I #endif { internal struct coverXml @@ -482,6 +528,12 @@ private static XmlDocument readXDocument(Stream stream) private static void writeXDocument(XmlDocument coverageDocument, Stream stream) { coverageDocument.Save(stream); } + [SuppressMessage("Gendarme.Rules.Smells", + "AvoidLongMethodsRule", + Justification = "Well tested code")] + [SuppressMessage("Gendarme.Rules.Smells", + "AvoidLongParameterListsRule", + Justification = "Stable code")] public static DateTime updateReport( Action postProcess, PointProcessor pointProcess, @@ -605,6 +657,9 @@ out var vc return flushStart; } + [SuppressMessage("Gendarme.Rules.Smells", + "AvoidLongParameterListsRule", + Justification = "Stable code")] public static TimeSpan doFlush( Action postProcess, PointProcessor pointProcess, @@ -644,6 +699,9 @@ Track context #if RUNNER + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUncalledPrivateCodeRule", + Justification = "Internals Visible To")] internal static long addVisit( Dictionary> counts, string moduleId, @@ -660,9 +718,12 @@ Track context return 1; } + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUncalledPrivateCodeRule", + Justification = "Internals Visible To")] [SuppressMessage("Gendarme.Rules.Smells", - "AvoidLongParameterListsRule", - Justification = "Most of this gets curried away")] + "AvoidLongParameterListsRule", + Justification = "Stable code")] public static TimeSpan doFlushStream( Action postProcess, PointProcessor pointProcess, From 8567bcc8337617859039f4d7438b9b573384c267 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Tue, 16 Jul 2024 19:17:56 +0100 Subject: [PATCH 67/91] Gendarme clean --- AltCover.Engine/Runner.fs | 4 +- AltCover.Recorder.Tests/Adapter.fs | 34 +-- AltCover.Recorder.Tests/Recorder.Tests.fs | 92 +++--- AltCover.Recorder.Tests/Tracer.Tests.fs | 38 +-- AltCover.Recorder/Base.cs | 125 ++++---- AltCover.Recorder/Recorder.cs | 339 ++++++++++++++-------- AltCover.Recorder/Tracer.cs | 27 +- AltCover.Tests/Runner.Tests.fs | 50 ++-- 8 files changed, 413 insertions(+), 296 deletions(-) diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 83d19302..930efdcc 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1112,7 +1112,7 @@ module internal Runner = then hits.Add(key, Dictionary()) - Counter.addVisit (hits, key, hitPointId, visit) + Counter.AddVisit (hits, key, hitPointId, visit) else 0L @@ -1391,7 +1391,7 @@ module internal Runner = | _ -> new MemoryStream() :> Stream let result = - AltCover.Counter.doFlushStream ( + AltCover.Counter.DoFlushStream ( (postProcess hits format), pointProcess, true, diff --git a/AltCover.Recorder.Tests/Adapter.fs b/AltCover.Recorder.Tests/Adapter.fs index a02774ce..e47c8f0c 100644 --- a/AltCover.Recorder.Tests/Adapter.fs +++ b/AltCover.Recorder.Tests/Adapter.fs @@ -11,12 +11,12 @@ module Adapter = let DoExit () = Instance.I.doExit let VisitsClear () = - Instance.I.clear () + Instance.I.Clear () Counter.branchVisits <- 0L Counter.totalVisits <- 0L let SamplesClear () = - Instance.I.samples <- Instance.I.makeSamples () + Instance.I.samples <- Instance.I.MakeSamples () let private reset () = Instance.I.isRunner <- false @@ -24,11 +24,11 @@ module Adapter = SamplesClear() let ModuleReset (m: string array) = - Instance.modules <- m + Instance.Modules <- m reset () let HardReset () = - Instance.modules <- [| System.String.Empty |] + Instance.Modules <- [| System.String.Empty |] reset () let internal prepareName name = @@ -71,18 +71,16 @@ module Adapter = let Lock = Instance.I.visits :> obj let VisitImplNone (moduleId, hitPointId) = - Instance.I.visitImpl (moduleId, hitPointId, Null()) + Instance.I.VisitImpl (moduleId, hitPointId, Null()) let VisitImplMethod (moduleId, hitPointId, mId) = - Instance.I.visitImpl (moduleId, hitPointId, (Call mId)) - //let internal VisitImpl (a, b, c) = - // Instance.I.visitImpl a b c + Instance.I.VisitImpl (moduleId, hitPointId, (Call mId)) let internal addSample (moduleId, hitPointId, context) = - Instance.I.takeSample (Sampling.Single, moduleId, hitPointId, context) + Instance.I.TakeSample (Sampling.Single, moduleId, hitPointId, context) let internal addSampleUnconditional (moduleId, hitPointId, context) = - Instance.I.takeSample (Sampling.All, moduleId, hitPointId, context) + Instance.I.TakeSample (Sampling.All, moduleId, hitPointId, context) let internal newBoth (time, call) = Both(Pair.Create(time, call)) @@ -122,10 +120,10 @@ module Adapter = else output - Counter.doFlushFile (ignore, (fun _ _ -> ()), true, visits, format, report, output') + Counter.DoFlushFile (ignore, (fun _ _ -> ()), true, visits, format, report, output') let internal updateReport (counts, format, coverageFile, outputFile) = - Counter.I.updateReport ( + Counter.I.UpdateReport ( ignore, (fun _ _ -> ()), true, @@ -135,13 +133,13 @@ module Adapter = outputFile ) - let internal payloadSelector x = Instance.I.payloadSelector (fun _ -> x) + let internal payloadSelector x = Instance.I.PayloadSelector (fun _ -> x) let internal payloadControl (x, y) = - Instance.I.payloadControl ((fun _ -> x), (fun _ -> y)) + Instance.I.PayloadControl ((fun _ -> x), (fun _ -> y)) let internal payloadSelection (x, y, z) = - Instance.I.payloadSelection ((fun _ -> x), (fun _ -> y), (fun _ -> z)) + Instance.I.PayloadSelection ((fun _ -> x), (fun _ -> y), (fun _ -> z)) let internal makeNullTrace name = Tracer.Create(name) @@ -174,7 +172,7 @@ module Adapter = | :? System.ArgumentNullException as ane -> ane.ParamName = unique | _ -> x.Message = unique - Instance.I.issue71Wrapper ((), (), (), (), catcher, pitcher) + Instance.I.Issue71Wrapper ((), (), (), (), catcher, pitcher) |> ignore let internal invokeCurriedIssue71Wrapper<'T when 'T :> System.Exception> @@ -189,7 +187,7 @@ module Adapter = constructor.Invoke([| unique |]) :?> System.Exception |> raise - Instance.I.curriedIssue71Wrapper ( + Instance.I.CurriedIssue71Wrapper ( "a", "b", "c", @@ -198,5 +196,5 @@ module Adapter = ) |> ignore - let internal tracePush (a, b, c) = Instance.I.trace.Push(a, b, c) + let internal tracePush (a, b, c) = Instance.I.Trace.Push(a, b, c) #endif \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index d3d1cc7c..853a9fee 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -69,7 +69,7 @@ module AltCoverTests = let ShouldFailXmlDataForNativeJson () = Assert.Throws(fun () -> ReportFormat.NativeJson - |> Counter.I.xmlByFormat + |> Counter.I.XmlByFormat |> ignore) |> ignore @@ -80,9 +80,9 @@ module AltCoverTests = [] let DefaultAccessorsBehaveAsExpected () = let v1 = DateTime.UtcNow.Ticks - let probe = Instance.I.clock () + let probe = Instance.I.Clock () let v2 = DateTime.UtcNow.Ticks - Assert.True(Instance.I.granularity () = 0L) + Assert.True(Instance.I.Granularity () = 0L) Assert.True(probe >= v1) Assert.True(probe <= v2) @@ -150,16 +150,16 @@ module AltCoverTests = getMyMethodName "=>" lock Adapter.Lock (fun () -> - let save = Instance.I.trace + let save = Instance.I.Trace try let key = " " Adapter.ModuleReset [| key |] - Instance.I.trace <- Adapter.makeNullTrace null + Instance.I.Trace <- Adapter.makeNullTrace null - Instance.I.recording <- false + Instance.I.Recording <- false Instance.Visit("key", 17) - Instance.I.recording <- true + Instance.I.Recording <- true Instance.CoverageFormat <- ReportFormat.NCover Instance.Visit(key, -23) @@ -184,9 +184,9 @@ module AltCoverTests = Assert.That(Counter.branchVisits, Is.EqualTo 1L) finally Instance.CoverageFormat <- ReportFormat.NCover - Instance.I.recording <- true + Instance.I.Recording <- true Adapter.HardReset() - Instance.I.trace <- save) + Instance.I.Trace <- save) getMyMethodName "<=" @@ -195,7 +195,7 @@ module AltCoverTests = let key = " " let index = - Counter.I.findIndexFromUspid (0, key) + Counter.I.FindIndexFromUspid (0, key) Assert.True(index < 0) @@ -208,7 +208,7 @@ module AltCoverTests = ReportFormat.OpenCover ||| ReportFormat.WithTracking - Assert.False(Instance.I.callerId.HasValue) + Assert.False(Instance.I.CallerId.HasValue) Assert.That(Adapter.payloadSelector false, Is.EqualTo <| Adapter.asNull ()) Assert.That(Adapter.payloadSelector true, Is.EqualTo <| Adapter.asNull ()) Instance.Push 4321 @@ -254,9 +254,9 @@ module AltCoverTests = Assert.True(probe % 1000L = 0L) Assert.True(probe <= v2) Assert.True(probe >= (1000L * (v1 / 1000L))) - Assert.True(Instance.I.callerId.HasValue |> not) + Assert.True(Instance.I.CallerId.HasValue |> not) Instance.Pop() - Assert.True(Instance.I.callerId.HasValue |> not) + Assert.True(Instance.I.CallerId.HasValue |> not) [] let PayloadWithEntryExitGeneratedIsAsExpected () = @@ -271,7 +271,7 @@ module AltCoverTests = Adapter.VisitsClear() - Assert.True(Instance.I.callerId.HasValue |> not) + Assert.True(Instance.I.CallerId.HasValue |> not) Assert.That(Adapter.payloadSelector false, Is.EqualTo <| Adapter.asNull ()) Assert.That(Adapter.payloadSelector true, Is.EqualTo <| Adapter.asNull ()) Instance.Push 4321 @@ -318,9 +318,9 @@ module AltCoverTests = Assert.True(probe % 1000L = 0L) Assert.True(probe <= v2) Assert.True(probe >= (1000L * (v1 / 1000L))) - Assert.True(Instance.I.callerId.HasValue |> not) + Assert.True(Instance.I.CallerId.HasValue |> not) Instance.Pop() - Assert.True(Instance.I.callerId.HasValue |> not) + Assert.True(Instance.I.CallerId.HasValue |> not) Assert.That(Instance.I.visits.Keys, Is.EquivalentTo [ Track.Entry; Track.Exit ]) @@ -376,14 +376,14 @@ module AltCoverTests = getMyMethodName "=>" lock Instance.I.visits (fun () -> - let save = Instance.I.trace + let save = Instance.I.Trace let key = " " Adapter.ModuleReset [| key |] try - Instance.I.trace <- Adapter.makeNullTrace null + Instance.I.Trace <- Adapter.makeNullTrace null - Instance.I.visitSelection (Adapter.asNull (), key, 23) + Instance.I.VisitSelection (Adapter.asNull (), key, 23) Assert.That( Instance.I.visits.Keys, @@ -401,7 +401,7 @@ module AltCoverTests = Assert.That(Instance.I.visits.[key].[23].Tracks, Is.Empty) finally Adapter.HardReset() - Instance.I.trace <- save) + Instance.I.Trace <- save) getMyMethodName "<=" @@ -433,7 +433,7 @@ module AltCoverTests = let before = Directory.GetFiles(where, "*.exn") - Instance.I.logException ("a", "b", "c", "ex") + Instance.I.LogException ("a", "b", "c", "ex") let after = Directory.GetFiles(where, "*.exn") @@ -570,7 +570,7 @@ module AltCoverTests = let before = Directory.GetFiles(where, "*.exn") - Instance.I.visitImpl (key, 23, Adapter.asNull ()) + Instance.I.VisitImpl (key, 23, Adapter.asNull ()) let after = Directory.GetFiles(where, "*.exn") @@ -613,8 +613,8 @@ module AltCoverTests = try let key = " " Adapter.ModuleReset [| key; "key" |] - Instance.I.visitImpl (key, 23, Adapter.asNull ()) - Instance.I.visitImpl ("key", 42, Adapter.asNull ()) + Instance.I.VisitImpl (key, 23, Adapter.asNull ()) + Instance.I.VisitImpl ("key", 42, Adapter.asNull ()) Assert.That( Instance.I.visits.Keys, @@ -633,8 +633,8 @@ module AltCoverTests = try let key = " " Adapter.ModuleReset [| key |] - Instance.I.visitImpl (key, 23, Adapter.asNull ()) - Instance.I.visitImpl (key, 42, Adapter.asNull ()) + Instance.I.VisitImpl (key, 23, Adapter.asNull ()) + Instance.I.VisitImpl (key, 42, Adapter.asNull ()) Assert.That( Instance.I.visits.Keys, @@ -656,8 +656,8 @@ module AltCoverTests = Adapter.ModuleReset [| key |] try - Instance.I.visitImpl (key, 23, Adapter.asNull ()) - Instance.I.visitImpl (key, 23, Adapter.asNull ()) + Instance.I.VisitImpl (key, 23, Adapter.asNull ()) + Instance.I.VisitImpl (key, 23, Adapter.asNull ()) Assert.That(Instance.I.visits.[key].[23].Count, Is.EqualTo 2) Assert.That(Instance.I.visits.[key].[23].Tracks, Is.Empty) finally @@ -677,8 +677,8 @@ module AltCoverTests = let payload = Adapter.time DateTime.UtcNow.Ticks - Instance.I.visitImpl (key, 23, Adapter.asNull ()) - Instance.I.visitImpl (key, 23, payload) + Instance.I.VisitImpl (key, 23, Adapter.asNull ()) + Instance.I.VisitImpl (key, 23, payload) Assert.That(Instance.I.visits.[key].[23].Count, Is.EqualTo 1) Assert.That(Instance.I.visits.[key].[23].Tracks, Is.EquivalentTo [ payload ]) finally @@ -1223,13 +1223,13 @@ module AltCoverTests = let unique = Path.Combine(where, Guid.NewGuid().ToString()) - let save = Instance.I.trace + let save = Instance.I.Trace use s = new MemoryStream() let s1 = new Compression.DeflateStream(s, CompressionMode.Compress) - Instance.I.trace <- Adapter.makeStreamTrace s1 + Instance.I.Trace <- Adapter.makeStreamTrace s1 try Instance.I.isRunner <- true @@ -1301,7 +1301,7 @@ module AltCoverTests = "-1" ] ) finally - Instance.I.trace <- save + Instance.I.Trace <- save AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath Adapter.VisitsClear() Instance.I.isRunner <- false @@ -1327,7 +1327,7 @@ module AltCoverTests = let unique = Path.Combine(where, Guid.NewGuid().ToString()) - let save = Instance.I.trace + let save = Instance.I.Trace let tag = unique + ".xml.acv" do @@ -1339,7 +1339,7 @@ module AltCoverTests = "f6e3edb3-fb20-44b3-817d-f69d1a22fc2f" Adapter.ModuleReset [| key |] - Instance.I.trace <- Tracer.Create(tag) + Instance.I.Trace <- Tracer.Create(tag) use stdout = new StringWriter() Console.SetOut stdout @@ -1377,7 +1377,7 @@ module AltCoverTests = Assert.That(v.Value, Is.Empty, sprintf "Visits should be cleared %A" v)) Assert.That( - Object.ReferenceEquals(Instance.I.trace, save), + Object.ReferenceEquals(Instance.I.Trace, save), Is.False, "trace should be replaced" ) @@ -1409,7 +1409,7 @@ module AltCoverTests = ) finally Adapter.HardReset() - Instance.I.trace <- save + Instance.I.Trace <- save AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath Adapter.VisitsClear() Console.SetOut saved @@ -1437,8 +1437,8 @@ module AltCoverTests = 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() @@ -1517,7 +1517,7 @@ module AltCoverTests = "1" ] ) finally - Instance.I.trace <- save + Instance.I.Trace <- save AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath Adapter.VisitsClear() Console.SetOut saved @@ -1542,8 +1542,8 @@ module AltCoverTests = 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 Instance.supervision <- true @@ -1617,7 +1617,7 @@ module AltCoverTests = "-1" ] ) finally - Instance.I.trace <- save + Instance.I.Trace <- save Instance.supervision <- false AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath Adapter.VisitsClear() @@ -2040,8 +2040,8 @@ module AltCoverTests = 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() @@ -2134,7 +2134,7 @@ module AltCoverTests = "1" ] ) finally - Instance.I.trace <- save + Instance.I.Trace <- save AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath AltCoverCoreTests.maybeDeleteFile (Instance.ReportFilePath + ".zip") Adapter.VisitsClear() diff --git a/AltCover.Recorder.Tests/Tracer.Tests.fs b/AltCover.Recorder.Tests/Tracer.Tests.fs index 105f7c88..3b0cd7ea 100644 --- a/AltCover.Recorder.Tests/Tracer.Tests.fs +++ b/AltCover.Recorder.Tests/Tracer.Tests.fs @@ -175,7 +175,7 @@ module AltCoverCoreTests = [] let VisitShouldSignal () = - let save = Instance.I.trace + let save = Instance.I.Trace let where = Assembly.GetExecutingAssembly().Location @@ -198,15 +198,15 @@ module AltCoverCoreTests = try Adapter.HardReset() - Instance.I.trace <- client.OnStart() - Assert.True(Instance.I.trace.IsConnected, "connection failed") + Instance.I.Trace <- client.OnStart() + Assert.True(Instance.I.Trace.IsConnected, "connection failed") Instance.I.isRunner <- true Adapter.VisitImplNone("name", 23) finally - Instance.I.trace.Close() - Instance.I.trace.Close() - Instance.I.trace.Close() - Instance.I.trace <- save + Instance.I.Trace.Close() + Instance.I.Trace.Close() + Instance.I.Trace.Close() + Instance.I.Trace <- save use stream = // fsharplint:disable-next-line RedundantNewKeyword new DeflateStream(File.OpenRead(unique + ".0.acv"), CompressionMode.Decompress) @@ -232,7 +232,7 @@ module AltCoverCoreTests = [] let VisitShouldSignalTrack () = - let save = Instance.I.trace + let save = Instance.I.Trace let where = Assembly.GetExecutingAssembly().Location @@ -271,8 +271,8 @@ module AltCoverCoreTests = let mutable client = Tracer.Create tag try - Instance.I.trace <- client.OnStart() - Assert.True(Instance.I.trace.IsConnected, "connection failed") + Instance.I.Trace <- client.OnStart() + Assert.True(Instance.I.Trace.IsConnected, "connection failed") Instance.I.isRunner <- true Adapter.HardReset() @@ -280,8 +280,8 @@ module AltCoverCoreTests = Adapter.VisitImplMethod("name", 23, 5) finally Instance.I.isRunner <- false - Instance.I.trace.Close() - Instance.I.trace <- save + Instance.I.Trace.Close() + Instance.I.Trace <- save use stream = // fsharplint:disable-next-line RedundantNewKeyword new DeflateStream(File.OpenRead(unique + ".0.acv"), CompressionMode.Decompress) @@ -371,7 +371,7 @@ module AltCoverCoreTests = [] let FlushShouldTidyUp () = // also throw a bone to OpenCover 615 - let save = Instance.I.trace + let save = Instance.I.Trace let where = Assembly.GetExecutingAssembly().Location @@ -394,18 +394,18 @@ module AltCoverCoreTests = try Adapter.HardReset() - Instance.I.trace <- client.OnStart() - Assert.That(Instance.I.trace.Equals client, Is.False) - Assert.That(Instance.I.trace.Equals expected, Is.False) - Assert.True(Instance.I.trace.IsConnected, "connection failed") + Instance.I.Trace <- client.OnStart() + Assert.That(Instance.I.Trace.Equals client, Is.False) + Assert.That(Instance.I.Trace.Equals expected, Is.False) + Assert.True(Instance.I.Trace.IsConnected, "connection failed") let (a, b, c) = expected |> Seq.head Adapter.tracePush (a, b, c) Instance.FlushFinish() finally - Instance.I.trace.Close() + Instance.I.Trace.Close() System.Threading.Thread.Sleep 100 - Instance.I.trace <- save + Instance.I.Trace <- save use stream = // fsharplint:disable-next-line RedundantNewKeyword new DeflateStream(File.OpenRead(root + ".0.acv"), CompressionMode.Decompress) diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index eb2bfa9a..77ec6ffc 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -1,24 +1,16 @@ #if RUNNER -using AltCover; -using System.Drawing; -using System; - namespace AltCover #else - namespace AltCover.Recorder #endif { using System; using System.Collections.Generic; - using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; - using System.Text.RegularExpressions; using System.Xml; - using static System.Net.Mime.MediaTypeNames; #if !RUNNER @@ -37,6 +29,7 @@ internal sealed class ExcludeFromCodeCoverageAttribute : Attribute [SuppressMessage("Gendarme.Rules.Naming", "UsePluralNameInEnumFlagsRule", Justification = "Not meaningful to do so")] + [Serializable] internal enum ReportFormat { NCover = 0, @@ -54,6 +47,7 @@ internal enum ReportFormat [SuppressMessage("Gendarme.Rules.Performance", "AvoidUninstantiatedInternalClassesRule", Justification = "Internals Visible To")] + [Serializable] internal enum Sampling { All = 0, @@ -66,6 +60,7 @@ internal enum Sampling [SuppressMessage("Gendarme.Rules.Performance", "AvoidUninstantiatedInternalClassesRule", Justification = "Internals Visible To")] + [Serializable] internal enum Tag { Null = 0, @@ -82,6 +77,9 @@ internal enum Tag [SuppressMessage("Gendarme.Rules.Design", "OperatorEqualsShouldBeOverloadedRule", Justification = "No use case")] + [SuppressMessage("Gendarme.Rules.Performance", + "OverrideValueTypeDefaultsRule", + Justification = "You what, mate?")] internal struct Pair { public long Time; @@ -90,9 +88,6 @@ internal struct Pair [SuppressMessage("Gendarme.Rules.Performance", "AvoidUncalledPrivateCodeRule", Justification = "Internals Visible To")] - [SuppressMessage("Gendarme.Rules.Performance", - "OverrideValueTypeDefaultsRule", - Justification = "You what, mate?")] public static Pair Create(long time, int call) { return new Pair { Time = time, Call = call }; @@ -143,7 +138,7 @@ public override int GetHashCode() [SuppressMessage("Gendarme.Rules.Performance", "ImplementEqualsTypeRule", Justification = "No use case")] - internal class Null : Track + internal sealed class Null : Track { public override string ToString() { @@ -164,7 +159,7 @@ public override int GetHashCode() [SuppressMessage("Gendarme.Rules.Performance", "ImplementEqualsTypeRule", Justification = "No use case")] - internal class Time : Track + internal sealed class Time : Track { public readonly long Value; @@ -340,6 +335,9 @@ internal long Total } } + [SuppressMessage("Gendarme.Rules.Smells", + "AvoidLongParameterListsRule", + Justification = "Stable code")] internal static class Counter { [SuppressMessage("Gendarme.Rules.Design.Generic", @@ -376,7 +374,13 @@ internal static class I private static class I #endif { - internal struct coverXml + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidLargeStructureRule", + Justification = "No premature work")] + [SuppressMessage("Gendarme.Rules.Performance", + "OverrideValueTypeDefaultsRule", + Justification = "You what, mate?")] + internal struct CoverXml { internal string m; internal string i; @@ -385,8 +389,8 @@ internal struct coverXml internal string v; } - internal static readonly coverXml openCoverXml = - new coverXml() + internal static readonly CoverXml openCoverXml = + new CoverXml() { m = "//Module", i = "hash", @@ -397,8 +401,8 @@ internal struct coverXml v = "vc" }; - internal static readonly coverXml nCoverXml = - new coverXml() + internal static readonly CoverXml nCoverXml = + new CoverXml() { m = "//module", i = "moduleId", @@ -407,7 +411,7 @@ internal struct coverXml v = "visitcount" }; - internal static coverXml xmlByFormat(ReportFormat format) + internal static CoverXml XmlByFormat(ReportFormat format) { switch (format & ReportFormat.TrackMask) { @@ -417,17 +421,17 @@ internal static coverXml xmlByFormat(ReportFormat format) } } - internal static DateTime minTime(DateTime t1, DateTime t2) + internal static DateTime MinTime(DateTime t1, DateTime t2) { return t1 < t2 ? t1 : t2; } - internal static DateTime maxTime(DateTime t1, DateTime t2) + internal static DateTime MaxTime(DateTime t1, DateTime t2) { return t1 > t2 ? t1 : t2; } - internal static int findIndexFromUspid(int flag, string uspid) + internal static int FindIndexFromUspid(int flag, string uspid) { var f = Int32.TryParse( uspid, @@ -437,7 +441,7 @@ internal static int findIndexFromUspid(int flag, string uspid) return f ? (c | flag) : -1; } - internal static void ensurePoint(Dictionary counts, int hitPointId) + internal static void EnsurePoint(Dictionary counts, int hitPointId) { if (!counts.ContainsKey(hitPointId)) { @@ -456,7 +460,10 @@ internal static void ensurePoint(Dictionary counts, int hitPoin } } - internal static long addTable( + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUncalledPrivateCodeRule", + Justification = "Internals Visible To")] + internal static long AddTable( Dictionary> counts, Dictionary> t ) @@ -473,7 +480,7 @@ Dictionary> t foreach (var p in here.Keys) { - ensurePoint(next, p); + EnsurePoint(next, p); var v = next[p]; var add = here[p]; hitcount += add.Total; @@ -489,7 +496,7 @@ Dictionary> t } // TODO inline in release if possible - internal static IEnumerable selectNodes(XmlNode node, string name) + internal static IEnumerable SelectNodes(XmlNode node, string name) { var result = new List(); foreach (var x in node.SelectNodes(name)) @@ -507,7 +514,7 @@ internal static IEnumerable selectNodes(XmlNode node, string name) // Approved way is ugly -- https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2202?view=vs-2019 // Also, this rule is deprecated // - private static XmlDocument readXDocument(Stream stream) + private static XmlDocument ReadXDocument(Stream stream) { var doc = new XmlDocument(); @@ -525,7 +532,7 @@ private static XmlDocument readXDocument(Stream stream) // The XML document to write // The XML file to write to // Idiom to work with CA2202 as above - private static void writeXDocument(XmlDocument coverageDocument, Stream stream) + private static void WriteXDocument(XmlDocument coverageDocument, Stream stream) { coverageDocument.Save(stream); } [SuppressMessage("Gendarme.Rules.Smells", @@ -534,7 +541,7 @@ private static void writeXDocument(XmlDocument coverageDocument, Stream stream) [SuppressMessage("Gendarme.Rules.Smells", "AvoidLongParameterListsRule", Justification = "Stable code")] - public static DateTime updateReport( + public static DateTime UpdateReport( Action postProcess, PointProcessor pointProcess, bool own, @@ -545,9 +552,9 @@ Stream outputFile ) { var flushStart = DateTime.UtcNow; - var xmlformat = xmlByFormat(format);// throw early on unsupported + var xmlformat = XmlByFormat(format);// throw early on unsupported - var coverageDocument = readXDocument(coverageFile); + var coverageDocument = ReadXDocument(coverageFile); var root = coverageDocument.DocumentElement; @@ -560,9 +567,9 @@ Stream outputFile var oldStartTime = DateTime.ParseExact(startTimeAttr, "o", null); var oldMeasureTime = DateTime.ParseExact(measureTimeAttr, "o", null); - var st = minTime(startTime, oldStartTime); + var st = MinTime(startTime, oldStartTime); startTime = st.ToUniversalTime(); // Min - var mt = maxTime(measureTime, oldMeasureTime); + var mt = MaxTime(measureTime, oldMeasureTime); measureTime = mt.ToUniversalTime(); // Max root.SetAttribute( @@ -588,7 +595,7 @@ Stream outputFile ); } - var moduleNodes = selectNodes(coverageDocument, xmlformat.m); + var moduleNodes = SelectNodes(coverageDocument, xmlformat.m); foreach (var el in moduleNodes) { @@ -601,13 +608,13 @@ Stream outputFile // affectedModule.Descendants(XName.Get("seqpnt")) // Get the methods, then flip their // contents before concatenating - var nn = selectNodes(el, xmlformat.m2); + var nn = SelectNodes(el, xmlformat.m2); foreach (var method in nn) { var nodes = new List>(); foreach (var nameflag in xmlformat.s) { - foreach (var node in selectNodes(method, nameflag.Key)) + foreach (var node in SelectNodes(method, nameflag.Key)) { nodes.Insert(0, new KeyValuePair(node, nameflag.Value)); } @@ -621,7 +628,7 @@ Stream outputFile if ((format & ReportFormat.TrackMask) == ReportFormat.OpenCover) { - index = findIndexFromUspid(node.Value, node.Key.GetAttribute("uspid")); + index = FindIndexFromUspid(node.Value, node.Key.GetAttribute("uspid")); } if (!moduleHits.ContainsKey(index)) @@ -652,7 +659,7 @@ out var vc outputFile.SetLength(0); if (own) - { writeXDocument(coverageDocument, outputFile); } + { WriteXDocument(coverageDocument, outputFile); } return flushStart; } @@ -660,7 +667,7 @@ out var vc [SuppressMessage("Gendarme.Rules.Smells", "AvoidLongParameterListsRule", Justification = "Stable code")] - public static TimeSpan doFlush( + public static TimeSpan DoFlush( Action postProcess, PointProcessor pointProcess, bool own, @@ -671,14 +678,14 @@ Stream outputFile ) { var flushStart = - updateReport(postProcess, pointProcess, own, counts, format, coverageFile, outputFile); + UpdateReport(postProcess, pointProcess, own, counts, format, coverageFile, outputFile); return new TimeSpan(DateTime.UtcNow.Ticks - flushStart.Ticks); } } // "Public" API - internal static void addSingleVisit( + internal static void AddSingleVisit( Dictionary> counts, string moduleId, int hitPointId, @@ -688,7 +695,7 @@ Track context if (counts.ContainsKey(moduleId)) { var next = counts[moduleId]; - I.ensurePoint(next, hitPointId); + I.EnsurePoint(next, hitPointId); var v = next[hitPointId]; if (context is Null n) @@ -702,7 +709,7 @@ Track context [SuppressMessage("Gendarme.Rules.Performance", "AvoidUncalledPrivateCodeRule", Justification = "Internals Visible To")] - internal static long addVisit( + internal static long AddVisit( Dictionary> counts, string moduleId, int hitPointId, @@ -711,10 +718,10 @@ Track context { if (context is Table t) { - return I.addTable(counts, t.Value); + return I.AddTable(counts, t.Value); } - addSingleVisit(counts, moduleId, hitPointId, context); + AddSingleVisit(counts, moduleId, hitPointId, context); return 1; } @@ -724,7 +731,7 @@ Track context [SuppressMessage("Gendarme.Rules.Smells", "AvoidLongParameterListsRule", Justification = "Stable code")] - public static TimeSpan doFlushStream( + public static TimeSpan DoFlushStream( Action postProcess, PointProcessor pointProcess, bool own, @@ -734,12 +741,12 @@ public static TimeSpan doFlushStream( Stream outputFile ) { - return I.doFlush(postProcess, pointProcess, own, counts, format, coverageFile, outputFile); + return I.DoFlush(postProcess, pointProcess, own, counts, format, coverageFile, outputFile); } #else - internal static TimeSpan doFlushStream( + internal static TimeSpan DoFlushStream( Action postProcess, PointProcessor pointProcess, bool own, @@ -761,11 +768,14 @@ internal static TimeSpan doFlushStream( { var outputFile = string.IsNullOrEmpty(output) ? coverageFile : target; - return I.doFlush(postProcess, pointProcess, own, counts, format, coverageFile, outputFile); + return I.DoFlush(postProcess, pointProcess, own, counts, format, coverageFile, outputFile); } } - internal static TimeSpan doFlushFile( + [SuppressMessage("Gendarme.Rules.Correctness", + "EnsureLocalDisposalRule", + Justification = "'zip' owns 'container' and is 'Close()'d")] + internal static TimeSpan DoFlushFile( Action postProcess, PointProcessor pointProcess, bool own, @@ -786,7 +796,7 @@ string output // option 4096, FileOptions.SequentialScan )) - return doFlushStream(postProcess, pointProcess, own, counts, format, coverageFile, output); + return DoFlushStream(postProcess, pointProcess, own, counts, format, coverageFile, output); } else { @@ -823,7 +833,7 @@ string output // option var result = new TimeSpan(0); using (var reader = zip.GetInputStream(entry)) { - result = I.doFlush(postProcess, pointProcess, own, counts, format, reader, target); + result = I.DoFlush(postProcess, pointProcess, own, counts, format, reader, target); } if (string.IsNullOrEmpty(output)) @@ -842,7 +852,7 @@ string output // option catch (ZipException) { using (var reader = new MemoryStream()) - { return I.doFlush(postProcess, pointProcess, own, counts, format, reader, target); } + { return I.DoFlush(postProcess, pointProcess, own, counts, format, reader, target); } } } } @@ -850,7 +860,7 @@ string output // option #if !RUNNER - internal class Source : IStaticDataSource + internal sealed class Source : IStaticDataSource { private readonly Stream _target; @@ -859,8 +869,13 @@ public Source(Stream t) _target = t; } + [SuppressMessage("Gendarme.Rules.Design", + "ConsiderConvertingMethodToPropertyRule", + Justification = "Third party interface")] public Stream GetSource() - { return _target; } + { + return _target; + } } #endif diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 9edc5f93..27083a65 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -1,3 +1,11 @@ +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Gendarme.Rules.Performance", + "AvoidUnneededFieldInitializationRule", + Scope = "member", // MethodDefinition + Target = "AltCover.Recorder.Instance::.cctor()", + Justification = "Compiler generated")] + namespace AltCover.Recorder { using System; @@ -28,13 +36,13 @@ internal static string ReportFilePath { get { - return canonicalPath(Path.Combine( + return CanonicalPath(Path.Combine( Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), ReportFile)); } } - internal static string canonicalPath(string path) + internal static string CanonicalPath(string path) // Mono+Linux barfs at a path of "/_" without the "file://" prefix { var u = new Uri("file://" + Path.GetFullPath(path), UriKind.Absolute); @@ -60,6 +68,9 @@ internal static bool Defer internal static ReportFormat CoverageFormat { #if DEBUG + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUncalledPrivateCodeRule", + Justification = "Test interface")] set { __coverageFormat = value; } #endif [MethodImpl(MethodImplOptions.NoInlining)] @@ -102,15 +113,21 @@ internal static string Token /// private static IEnumerable __modules = new string[] { string.Empty }; - internal static IEnumerable modules + internal static IEnumerable Modules { #if DEBUG + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUncalledPrivateCodeRule", + Justification = "Test interface")] set { __modules = value; } #endif [MethodImpl(MethodImplOptions.NoInlining)] get { return __modules; } } + [SuppressMessage("Gendarme.Rules.Design", + "ConsiderConvertingMethodToPropertyRule", + Justification = "A bit big for that")] private static bool IsSupervised() { bool maybe = false; @@ -128,8 +145,14 @@ private static bool IsSupervised() //Assembly.GetExecutingAssembly().GetName().Name = "AltCover.Recorder.g" && internal static bool supervision = IsSupervised(); + [SuppressMessage("Gendarme.Rules.Smells", + "AvoidCodeDuplicatedInSiblingClassesRule", + Justification = "Too trivial")] internal abstract class Sampled { + [SuppressMessage("Gendarme.Rules.Maintainability", + "VariableNamesShouldNotMatchFieldNamesRule", + Justification = "too trivial")] protected Sampled(int visit) { this.visit = visit; @@ -138,7 +161,10 @@ protected Sampled(int visit) public readonly int visit; } - internal class SimpleVisit : Sampled + [SuppressMessage("Gendarme.Rules.Performance", + "ImplementEqualsTypeRule", + Justification = "No use case")] + internal sealed class SimpleVisit : Sampled { public SimpleVisit(int visit) : base(visit) { @@ -159,10 +185,16 @@ public override int GetHashCode() } } - internal class CallVisit : Sampled + [SuppressMessage("Gendarme.Rules.Performance", + "ImplementEqualsTypeRule", + Justification = "No use case")] + internal sealed class CallVisit : Sampled { public readonly int call; + [SuppressMessage("Gendarme.Rules.Maintainability", + "VariableNamesShouldNotMatchFieldNamesRule", + Justification = "too trivial")] public CallVisit(int visit, int call) : base(visit) { this.call = call; @@ -183,10 +215,16 @@ public override int GetHashCode() } } - internal class TimeVisit : Sampled + [SuppressMessage("Gendarme.Rules.Performance", + "ImplementEqualsTypeRule", + Justification = "No use case")] + internal sealed class TimeVisit : Sampled { public readonly long time; + [SuppressMessage("Gendarme.Rules.Maintainability", + "VariableNamesShouldNotMatchFieldNamesRule", + Justification = "too trivial")] public TimeVisit(int visit, long time) : base(visit) { this.time = time; @@ -209,6 +247,12 @@ public override int GetHashCode() #if DEBUG + [SuppressMessage("Gendarme.Rules.Smells", + "AvoidLargeClassesRule", + Justification = "No. Go away.")] + [SuppressMessage("Gendarme.Rules.Smells", + "AvoidLongParameterListsRule", + Justification = "Stable code")] internal static class I #else @@ -218,7 +262,7 @@ private static class I internal static readonly ResourceManager resources = new ResourceManager("AltCover.Recorder.Strings", Assembly.GetExecutingAssembly()); - internal static string getResource(string s) + internal static string GetResource(string s) { var cc = System.Globalization.CultureInfo.CurrentUICulture; var names = new string[] { cc.Name, cc.Parent.Name, "en" }; @@ -232,14 +276,14 @@ internal static string getResource(string s) return null; } - private static Dictionary> makeVisits() + private static Dictionary> MakeVisits() { var d = new Dictionary> { { Track.Entry, new Dictionary() }, { Track.Exit, new Dictionary() } }; - foreach (var item in modules) + foreach (var item in Modules) { d.Add(item, new Dictionary()); } @@ -249,19 +293,19 @@ private static Dictionary> makeVisits() /// /// Accumulation of visit records /// - internal static Dictionary> visits = makeVisits(); + internal static Dictionary> visits = MakeVisits(); - internal static Dictionary> makeSamples() + internal static Dictionary> MakeSamples() { var d = new Dictionary>(); - foreach (var item in modules) + foreach (var item in Modules) { d.Add(item, new Dictionary()); } return d; } - internal static Dictionary> samples = makeSamples(); + internal static Dictionary> samples = MakeSamples(); internal static bool isRunner = false; @@ -276,7 +320,16 @@ private sealed class AsyncLocal public T Value { + [SuppressMessage("Gendarme.Rules.Correctness", + "MethodCanBeMadeStaticRule", + Justification = "Whole point of the exercise")] get { return item; } + [SuppressMessage("Gendarme.Rules.Correctness", + "MethodCanBeMadeStaticRule", + Justification = "Whole point of the exercise")] + [SuppressMessage("Gendarme.Rules.Concurrency", + "WriteStaticFieldFromInstanceMethodRule", + Justification = "Whole point of the exercise")] set { item = value; } } } @@ -299,43 +352,43 @@ private static Stack instance() return value.Value; } - public static Nullable peek() + public static Nullable Peek() { var i = instance(); return (i.Count > 0) ? (Nullable)i.Peek() : null; } - public static void push(int x) + public static void Push(int x) { instance().Push(x); } - public static Nullable pop() + public static Nullable Pop() { var i = instance(); return (i.Count > 0) ? (Nullable)i.Pop() : null; } } - internal static Nullable callerId + internal static Nullable CallerId { - get { return CallTrack.peek(); } + get { return CallTrack.Peek(); } } - internal static void push(int i) + internal static void Push(int i) { - CallTrack.push(i); + CallTrack.Push(i); } - internal static Nullable pop() - { return CallTrack.pop(); } + internal static Nullable Pop() + { return CallTrack.Pop(); } /// /// Serialize access to the report file across AppDomains for the classic mode /// internal static readonly Mutex mutex = new Mutex(false, Token + ".mutex"); - internal static string signalFile + internal static string SignalFile { get { return ReportFilePath + ".acv"; } } @@ -343,18 +396,21 @@ internal static string signalFile /// /// Reporting back to the mother-ship /// - private static Tracer __trace = Tracer.Create(signalFile); + private static Tracer __trace = Tracer.Create(SignalFile); - internal static Tracer trace + internal static Tracer Trace { set { __trace = value; } [MethodImpl(MethodImplOptions.NoInlining)] get { return __trace; } } + [SuppressMessage("Gendarme.Rules.Design.Generic", + "AvoidDeclaringCustomDelegatesRule", + Justification = "Net Framework 2.0")] internal delegate void MutexHandler(bool own); - internal static void withMutex(MutexHandler f) + internal static void WithMutex(MutexHandler f) { var own = mutex.WaitOne(1000); @@ -368,13 +424,13 @@ internal static void withMutex(MutexHandler f) } } - internal static void initialiseTrace(Tracer t) + internal static void InitialiseTrace(Tracer t) { - withMutex( + WithMutex( x => { - trace = t.OnStart(); - isRunner = isRunner || trace.IsConnected; + Trace = t.OnStart(); + isRunner = isRunner || Trace.IsConnected; } ); } @@ -383,16 +439,16 @@ internal static void initialiseTrace(Tracer t) private static bool __recording = true; - internal static bool recording + internal static bool Recording { set { __recording = value; } [MethodImpl(MethodImplOptions.NoInlining)] get { return __recording; } } - internal static void clear() + internal static void Clear() { - visits = makeVisits(); + visits = MakeVisits(); Counter.branchVisits = 0; Counter.totalVisits = 0; } @@ -400,13 +456,16 @@ internal static void clear() /// /// This method flushes hit count buffers. /// - internal static void flushAll(Close _) + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUnusedParametersRule", + Justification = "Tidying later perhaps")] + internal static void FlushAll(Close _) { var counts = visits; - clear(); + Clear(); - trace.OnConnected( - () => trace.OnFinish(counts), + Trace.OnConnected( + () => Trace.OnFinish(counts), () => { var any = false; @@ -421,10 +480,10 @@ internal static void flushAll(Close _) if (!any) return; - withMutex(own => + WithMutex(own => { var delta = - Counter.doFlushFile( + Counter.DoFlushFile( x => { return; }, (x, y) => { return; }, own, @@ -434,7 +493,7 @@ internal static void flushAll(Close _) null ); - var message = getResource("Coverage statistics flushing took {0:N} seconds"); + var message = GetResource("Coverage statistics flushing took {0:N} seconds"); if (!string.IsNullOrEmpty(message)) Console.Out.WriteLine(message, delta.TotalSeconds); }); @@ -442,36 +501,36 @@ internal static void flushAll(Close _) ); } - internal static void flushPause() + internal static void FlushPause() { - var message = getResource("PauseHandler"); + var message = GetResource("PauseHandler"); if (!string.IsNullOrEmpty(message)) Console.Out.WriteLine(message); - recording = false; - flushAll(Close.Pause); - trace = Tracer.Create(signalFile); + Recording = false; + FlushAll(Close.Pause); + Trace = Tracer.Create(SignalFile); } - internal static void flushResume() + internal static void FlushResume() { - var message = getResource("ResumeHandler"); + var message = GetResource("ResumeHandler"); if (!string.IsNullOrEmpty(message)) Console.Out.WriteLine(message); var wasConnected = isRunner; - initialiseTrace(trace); + InitialiseTrace(Trace); if (wasConnected != isRunner) { - samples = makeSamples(); - clear(); + samples = MakeSamples(); + Clear(); } - recording = true; + Recording = true; } - internal static void traceVisit(string moduleId, int hitPointId, Track context) + internal static void TraceVisit(string moduleId, int hitPointId, Track context) { lock (synchronize) { @@ -481,16 +540,19 @@ internal static void traceVisit(string moduleId, int hitPointId, Track context) { if (item.Count > 0) { - clear(); + Clear(); break; } } - trace.OnVisit(counts, moduleId, hitPointId, context); + Trace.OnVisit(counts, moduleId, hitPointId, context); } } - internal static void logException(T1 moduleId, T2 hitPointId, T3 context, T4 x) + [SuppressMessage("Gendarme.Rules.Globalization", + "PreferIFormatProviderOverrideRule", + Justification = "later, perhaps")] + internal static void LogException(T1 moduleId, T2 hitPointId, T3 context, T4 x) { var text = new string[] { String.Format("ModuleId = {0}", moduleId), @@ -510,16 +572,22 @@ internal static void logException(T1 moduleId, T2 hitPointId, T3 } } + [SuppressMessage("Gendarme.Rules.Design.Generic", + "AvoidDeclaringCustomDelegatesRule", + Justification = "Net Framework 2.0")] internal delegate void HandlerFunction(T1 a, T2 b, T3 c, Exception x); + [SuppressMessage("Gendarme.Rules.Design.Generic", + "AvoidDeclaringCustomDelegatesRule", + Justification = "Net Framework 2.0")] internal delegate void Adder(T1 a, T2 b, T3 c, T4 d); - internal static void issue71Wrapper(T1 visits, T2 moduleId, T3 hitPointId, + internal static void Issue71Wrapper(T1 visitsIn, T2 moduleId, T3 hitPointId, T4 context, HandlerFunction handler, Adder add) { try { - add(visits, moduleId, hitPointId, context); + add(visitsIn, moduleId, hitPointId, context); } catch (Exception x) { @@ -531,19 +599,19 @@ internal static void issue71Wrapper(T1 visits, T2 moduleId, T3 h } } - internal static void curriedIssue71Wrapper(T1 visits, T2 moduleId, + internal static void CurriedIssue71Wrapper(T1 visitsIn, T2 moduleId, T3 hitPointId, T4 context, Adder add) { - issue71Wrapper(visits, moduleId, hitPointId, context, logException, add); + Issue71Wrapper(visitsIn, moduleId, hitPointId, context, LogException, add); } - internal static void addVisit(string moduleId, int hitPointId, Track context) + internal static void AddVisit(string moduleId, int hitPointId, Track context) { - curriedIssue71Wrapper(visits, moduleId, hitPointId, context, Counter.addSingleVisit); + CurriedIssue71Wrapper(visits, moduleId, hitPointId, context, Counter.AddSingleVisit); } - internal static bool takeSample(Sampling strategy, string moduleId, int hitPointId, Track context) + internal static bool TakeSample(Sampling strategy, string moduleId, int hitPointId, Track context) { if (strategy == Sampling.All) return true; @@ -551,15 +619,14 @@ internal static bool takeSample(Sampling strategy, string moduleId, int hitPoint Sampled[] sampleds = null; if (context is Null) sampleds = new Sampled[] { new SimpleVisit(hitPointId) }; - else if (context is Time) + else if (context is Time t) sampleds = new Sampled[] { new SimpleVisit(hitPointId), - new TimeVisit(hitPointId, ((Time)context).Value) }; - else if (context is Call) + new TimeVisit(hitPointId, t.Value)}; + else if (context is Call c) sampleds = new Sampled[] { new SimpleVisit(hitPointId), - new CallVisit(hitPointId, ((Call)context).Value) }; - else if (context is Both) + new CallVisit(hitPointId, c.Value)}; + else if (context is Both b) { - var b = (Both)context; sampleds = new Sampled[] { new SimpleVisit(hitPointId), new TimeVisit(hitPointId, b.Value.Time), new CallVisit(hitPointId, b.Value.Call)}; @@ -597,96 +664,115 @@ internal static bool takeSample(Sampling strategy, string moduleId, int hitPoint /// Assembly being visited /// Sequence Point identifier /// What sort of visit - internal static void visitImpl(string moduleId, int hitPointId, Track context) + internal static void VisitImpl(string moduleId, int hitPointId, Track context) { if (Sample == Sampling.All - || takeSample(Sample, moduleId, hitPointId, context)) + || TakeSample(Sample, moduleId, hitPointId, context)) { - if (Defer || supervision || !trace.IsConnected) + if (Defer || supervision || !Trace.IsConnected) { - addVisit(moduleId, hitPointId, context); + AddVisit(moduleId, hitPointId, context); } else { - traceVisit(moduleId, hitPointId, context); + TraceVisit(moduleId, hitPointId, context); } } } - internal static bool isTracking + internal static bool IsTracking { get { return (CoverageFormat & ReportFormat.WithTracking) != 0; } } - internal static bool isTrackingRunner() + [SuppressMessage("Gendarme.Rules.Design", + "ConsiderConvertingMethodToPropertyRule", + Justification = "No use case")] + internal static bool IsTrackingRunner() { - return isTracking && isRunner; + return IsTracking && isRunner; } - internal static long granularity() + internal static long Granularity() { return Timer; } - internal static long clock() - { return DateTime.UtcNow.Ticks; } + internal static long Clock() + { + return DateTime.UtcNow.Ticks; + } + [SuppressMessage("Gendarme.Rules.Design.Generic", + "AvoidDeclaringCustomDelegatesRule", + Justification = "Net Framework 2.0")] internal delegate long ClockProvider(); + [SuppressMessage("Gendarme.Rules.Design.Generic", + "AvoidDeclaringCustomDelegatesRule", + Justification = "Net Framework 2.0")] internal delegate long FrequencyProvider(); + [SuppressMessage("Gendarme.Rules.Design.Generic", + "AvoidDeclaringCustomDelegatesRule", + Justification = "Net Framework 2.0")] internal delegate bool PayloadProvider(); - internal static Track payloadSelection(ClockProvider clock, + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidRepetitiveCallsToPropertiesRule", + Justification = "Separate branches")] + internal static Track PayloadSelection(ClockProvider clock, FrequencyProvider frequency, PayloadProvider wantPayload) { if (wantPayload()) { var f = frequency(); - var id = callerId; + var id = CallerId; if (f == 0) { return id.HasValue ? (Track)new Call(id.Value) : new Null(); } - - var t = f * (clock() / f); - return id.HasValue ? - (Track)new Both(Pair.Create(t, id.Value)) : - new Time(t); + else + { + var t = f * (clock() / f); + return id.HasValue ? + (Track)new Both(Pair.Create(t, id.Value)) : + new Time(t); + } } return new Null(); } - internal static Track payloadControl(FrequencyProvider frequency, PayloadProvider wantPayload) + internal static Track PayloadControl(FrequencyProvider frequency, PayloadProvider wantPayload) { - return payloadSelection(clock, frequency, wantPayload); + return PayloadSelection(Clock, frequency, wantPayload); } - internal static Track payloadSelector(PayloadProvider enable) + internal static Track PayloadSelector(PayloadProvider enable) { - return payloadControl(granularity, enable); + return PayloadControl(Granularity, enable); } - internal static void visitSelection(Track track, string moduleId, int hitPointId) + internal static void VisitSelection(Track track, string moduleId, int hitPointId) { - visitImpl(moduleId, hitPointId, track); + VisitImpl(moduleId, hitPointId, track); } - internal static void flushCounter(Close finish, EventArgs _) + internal static void FlushCounter(Close finish, EventArgs _) { switch (finish) { case Close.Resume: - flushResume(); break; + FlushResume(); break; case Close.Pause: - flushPause(); break; + FlushPause(); break; default: - recording = false; + Recording = false; if (!supervision) - flushAll(finish); + FlushAll(finish); break; } } @@ -696,46 +782,59 @@ internal static void flushCounter(Close finish, EventArgs _) internal static void PauseHandler(object sender, FileSystemEventArgs e) { - flushCounter(Close.Pause, e); + FlushCounter(Close.Pause, e); } internal static FileSystemEventHandler doResume = ResumeHandler; internal static void ResumeHandler(object sender, FileSystemEventArgs e) { - flushCounter(Close.Resume, e); + FlushCounter(Close.Resume, e); } + [SuppressMessage("Gendarme.Rules.Correctness", + "DeclareEventsExplicitlyRule", + Justification = "Wrong use case")] internal static EventHandler doUnload = UnloadHandler; internal static void UnloadHandler(object sender, EventArgs e) { - flushCounter(Close.DomainUnload, e); + FlushCounter(Close.DomainUnload, e); } + [SuppressMessage("Gendarme.Rules.Correctness", + "DeclareEventsExplicitlyRule", + Justification = "Wrong use case")] internal static EventHandler doExit = ExitHandler; internal static void ExitHandler(object sender, EventArgs e) { - flushCounter(Close.ProcessExit, e); + FlushCounter(Close.ProcessExit, e); } - internal static void startWatcher() + internal static void StartWatcher() { - watcher.Path = Path.GetDirectoryName(signalFile); - watcher.Filter = Path.GetFileName(signalFile); + var s = SignalFile; + watcher.Path = Path.GetDirectoryName(s); + watcher.Filter = Path.GetFileName(s); watcher.Created += doResume; watcher.Deleted += doPause; watcher.EnableRaisingEvents = !String.IsNullOrEmpty(watcher.Path); } + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUnneededFieldInitializationRule", + Justification = "Simpler this way")] + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidRepetitiveCallsToPropertiesRule", + Justification = "You what, mate?")] static I() { AppDomain.CurrentDomain.DomainUnload += doUnload; AppDomain.CurrentDomain.ProcessExit += doExit; - startWatcher(); - initialiseTrace( - Tracer.Create(signalFile) + StartWatcher(); + InitialiseTrace( + Tracer.Create(SignalFile) ); } } @@ -743,36 +842,38 @@ static I() // Public API public static void Visit(string moduleId, int hitPointId) { - if (I.recording) + if (I.Recording) { - var track = I.isTracking ? - I.payloadSelector(I.isTrackingRunner) : + var track = I.IsTracking ? + I.PayloadSelector(I.IsTrackingRunner) : new Null(); - I.visitSelection(track, moduleId, hitPointId); + I.VisitSelection(track, moduleId, hitPointId); } } //// The moduleId strings are not the hash or guids normally found there public static void Push(int caller) { - I.push(caller); + I.Push(caller); - if (I.isTrackingRunner()) - I.visitSelection(new Time(DateTime.UtcNow.Ticks), Track.Entry, caller); + if (I.IsTrackingRunner()) + I.VisitSelection(new Time(DateTime.UtcNow.Ticks), Track.Entry, caller); } public static void Pop() { - var caller = I.pop(); + var caller = I.Pop(); - if (I.isTrackingRunner() && caller.HasValue) - I.visitSelection(new Time(DateTime.UtcNow.Ticks), Track.Exit, caller.Value); + if (I.IsTrackingRunner() && caller.HasValue) + I.VisitSelection(new Time(DateTime.UtcNow.Ticks), Track.Exit, caller.Value); } - //// Used by the datacollector + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUncalledPrivateCodeRule", + Justification = "Internals Visible To")] internal static void FlushFinish() { - I.flushAll(Close.ProcessExit); + I.FlushAll(Close.ProcessExit); } } } \ No newline at end of file diff --git a/AltCover.Recorder/Tracer.cs b/AltCover.Recorder/Tracer.cs index d9c1f4dd..aa071dd0 100644 --- a/AltCover.Recorder/Tracer.cs +++ b/AltCover.Recorder/Tracer.cs @@ -100,44 +100,44 @@ internal void Close() catch (NullReferenceException) { } } + [SuppressMessage("Gendarme.Rules.Smells", + "AvoidLongMethodsRule", + Justification = "Well tested code")] private void PushContext(Track context) { if (context is Null) Formatter.Write((byte)Tag.Null); - else if (context is Time) + else if (context is Time t) { - var t = (Time)context; Formatter.Write((byte)Tag.Time); Formatter.Write(t.Value); } - else if (context is Call) + else if (context is Call c) { - var c = (Call)context; Formatter.Write((byte)Tag.Call); Formatter.Write(c.Value); } - else if (context is Both) + else if (context is Both b) { - var b = (Both)context; Formatter.Write((byte)Tag.Both); Formatter.Write(b.Value.Time); Formatter.Write(b.Value.Call); } else { - var t = ((Table)context).Value; + var tx = ((Table)context).Value; Formatter.Write((byte)Tag.Table); - foreach (var key in t.Keys) + foreach (var key in tx.Keys) { - if (t[key].Count == 0) + if (tx[key].Count == 0) continue; Formatter.Write(key); - Formatter.Write(t[key].Count); + Formatter.Write(tx[key].Count); - foreach (var p in t[key].Keys) + foreach (var p in tx[key].Keys) { Formatter.Write(p); - var v = t[key][p]; + var v = tx[key][p]; Formatter.Write(v.Count); foreach (var x in v.Tracks) PushContext(x); @@ -174,6 +174,9 @@ internal Tracer OnStart() return running; } + [SuppressMessage("Gendarme.Rules.Design.Generic", + "AvoidDeclaringCustomDelegatesRule", + Justification = "Net Framework 2.0")] public delegate void Act(); //member internal this.OnConnected f g = if this.IsConnected then f () else g () diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index dceda16c..10c9330e 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -59,32 +59,32 @@ module AltCoverRunnerTests = [] let ShouldFailXmlDataForNativeJson () = Assert.Throws(fun () -> - ignore (ReportFormat.NativeJson |> Counter.I.xmlByFormat)) + ignore (ReportFormat.NativeJson |> Counter.I.XmlByFormat)) |> ignore [] let MaxTimeFirst () = let now = DateTime.Now let ago = now - TimeSpan(1, 0, 0, 0) - test <@ (Counter.I.maxTime (now, ago)) = now @> + test <@ (Counter.I.MaxTime (now, ago)) = now @> [] let MaxTimeLast () = let now = DateTime.Now let ago = now - TimeSpan(1, 0, 0, 0) - test <@ (Counter.I.maxTime (ago, now)) = now @> + test <@ (Counter.I.MaxTime (ago, now)) = now @> [] let MinTimeFirst () = let now = DateTime.Now let ago = now - TimeSpan(1, 0, 0, 0) - test <@ (Counter.I.minTime (ago, now)) = ago @> + test <@ (Counter.I.MinTime (ago, now)) = ago @> [] let MinTimeLast () = let now = DateTime.Now let ago = now - TimeSpan(1, 0, 0, 0) - test <@ (Counter.I.minTime (now, ago)) = ago @> + test <@ (Counter.I.MinTime (now, ago)) = ago @> [] let JunkUspidGivesNegativeIndex () = @@ -92,7 +92,7 @@ module AltCoverRunnerTests = let key = " " let index = - Counter.I.findIndexFromUspid (0, key) + Counter.I.FindIndexFromUspid (0, key) test <@ index < 0 @> @@ -108,7 +108,7 @@ module AltCoverRunnerTests = let key = " " let v1 = - Counter.addVisit (visits, key, 23, new Null()) + Counter.AddVisit (visits, key, 23, new Null()) Assert.That(v1, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) @@ -130,7 +130,7 @@ module AltCoverRunnerTests = let payload = Time DateTime.UtcNow.Ticks let v2 = - Counter.addVisit (visits, key, 23, payload) + Counter.AddVisit (visits, key, 23, payload) Assert.That(v2, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) @@ -152,12 +152,12 @@ module AltCoverRunnerTests = let key = " " let v3 = - Counter.addVisit (visits, key, 23, new Null()) + Counter.AddVisit (visits, key, 23, new Null()) Assert.That(v3, Is.EqualTo 1) let v4 = - Counter.addVisit (visits, "key", 42, new Null()) + Counter.AddVisit (visits, "key", 42, new Null()) Assert.That(visits.Count, Is.EqualTo 2) Assert.That(v4, Is.EqualTo 1) @@ -174,12 +174,12 @@ module AltCoverRunnerTests = let key = " " let v5 = - Counter.addVisit (visits, key, 23, new Null()) + Counter.AddVisit (visits, key, 23, new Null()) Assert.That(v5, Is.EqualTo 1) let v6 = - Counter.addVisit (visits, key, 42, new Null()) + Counter.AddVisit (visits, key, 42, new Null()) Assert.That(v6, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) @@ -197,12 +197,12 @@ module AltCoverRunnerTests = let key = " " let v7 = - Counter.addVisit (visits, key, 23, new Null()) + Counter.AddVisit (visits, key, 23, new Null()) Assert.That(v7, Is.EqualTo 1) let v8 = - Counter.addVisit (visits, key, 23, new Null()) + Counter.AddVisit (visits, key, 23, new Null()) Assert.That(v8, Is.EqualTo 1) let x = visits.[key].[23] @@ -222,12 +222,12 @@ module AltCoverRunnerTests = let payload = Time DateTime.UtcNow.Ticks let v9 = - Counter.addVisit (visits, key, 23, new Null()) + Counter.AddVisit (visits, key, 23, new Null()) Assert.That(v9, Is.EqualTo 1) let v10 = - Counter.addVisit (visits, key, 23, payload) + Counter.AddVisit (visits, key, 23, payload) Assert.That(v10, Is.EqualTo 1) let x = visits.[key].[23] @@ -284,7 +284,7 @@ module AltCoverRunnerTests = item.Add("7C-CD-66-29-A3-6C-6D-5F-A7-65-71-0E-22-7D-B2-61-B5-1F-65-9A", payload) - Counter.I.updateReport ( + Counter.I.UpdateReport ( ignore, (fun _ _ -> ()), true, @@ -2609,7 +2609,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) |> ignore) // degenerate case @@ -2732,7 +2732,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) |> ignore) let entries = Dictionary() @@ -2856,7 +2856,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) |> ignore) // degenerate case 1 @@ -3030,7 +3030,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) |> ignore) let entries = Dictionary() @@ -3175,7 +3175,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) |> ignore) // degenerate case @@ -3302,7 +3302,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) |> ignore) let entries = Dictionary() @@ -3438,7 +3438,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) |> ignore) // degenerate case 1 @@ -3620,7 +3620,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.addVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) |> ignore) let entries = Dictionary() From 0e3e26ccfac4a64f9e9de5269a36f7f1ed249883 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Tue, 16 Jul 2024 19:33:44 +0100 Subject: [PATCH 68/91] FxCop too --- AltCover.Recorder/Base.cs | 9 +++++++++ AltCover.Recorder/Recorder.cs | 6 ++++++ AltCover.Recorder/Tracer.cs | 3 +++ 3 files changed, 18 insertions(+) diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 77ec6ffc..41dc9548 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -541,6 +541,9 @@ private static void WriteXDocument(XmlDocument coverageDocument, Stream stream) [SuppressMessage("Gendarme.Rules.Smells", "AvoidLongParameterListsRule", Justification = "Stable code")] + [SuppressMessage("Microsoft.Usage", + "CA1806:DoNotIgnoreMethodResults", + Justification = "TryParse fails safe")] public static DateTime UpdateReport( Action postProcess, PointProcessor pointProcess, @@ -746,6 +749,9 @@ Stream outputFile #else + [SuppressMessage("Microsoft.Reliability", + "CA2000:Dispose objects before losing scope", + Justification="MemoryStream is 'use'd if created")] internal static TimeSpan DoFlushStream( Action postProcess, PointProcessor pointProcess, @@ -775,6 +781,9 @@ internal static TimeSpan DoFlushStream( [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", Justification = "'zip' owns 'container' and is 'Close()'d")] + [SuppressMessage("Microsoft.Reliability", + "CA2000:Dispose objects before losing scope", + Justification = "'zip' owns 'container' and is 'Close()'d")] internal static TimeSpan DoFlushFile( Action postProcess, PointProcessor pointProcess, diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 27083a65..6cb5f034 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -552,6 +552,9 @@ internal static void TraceVisit(string moduleId, int hitPointId, Track context) [SuppressMessage("Gendarme.Rules.Globalization", "PreferIFormatProviderOverrideRule", Justification = "later, perhaps")] + [SuppressMessage("Microsoft.Globalization", + "CA1305:SpecifyIFormatProvider", + Justification = "later, perhaps")] internal static void LogException(T1 moduleId, T2 hitPointId, T3 context, T4 x) { var text = new string[] { @@ -828,6 +831,9 @@ internal static void StartWatcher() [SuppressMessage("Gendarme.Rules.Performance", "AvoidRepetitiveCallsToPropertiesRule", Justification = "You what, mate?")] + [SuppressMessage("Microsoft.Performance", + "CA1810:InitializeReferenceTypeStaticFieldsInline", + Justification = "Simpler this way")] static I() { AppDomain.CurrentDomain.DomainUnload += doUnload; diff --git a/AltCover.Recorder/Tracer.cs b/AltCover.Recorder/Tracer.cs index aa071dd0..2ff0b415 100644 --- a/AltCover.Recorder/Tracer.cs +++ b/AltCover.Recorder/Tracer.cs @@ -57,6 +57,9 @@ internal bool IsConnected [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", Justification = "s, fs : Closed as recording ends")] + [SuppressMessage("Microsoft.Reliability", + "CA2000:Dispose objects before losing scope", + Justification = "s, fs : Closed as recording ends")] private Tracer MakeConnection(string f) { var fs = File.OpenWrite(f); From b3f68c7acaaa8ee67f22fa04bbfa67282feaafa9 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Tue, 16 Jul 2024 20:16:33 +0100 Subject: [PATCH 69/91] Align Async with the recorder code, ready to start work on that last unit test --- AltCover.Async/Instance.cs | 89 +++++++++-------------------------- AltCover.Async/Library.fs | 60 +++++++++++++++++++++++ AltCover.Recorder/Recorder.cs | 12 ++--- 3 files changed, 88 insertions(+), 73 deletions(-) create mode 100644 AltCover.Async/Library.fs diff --git a/AltCover.Async/Instance.cs b/AltCover.Async/Instance.cs index f7cb476d..5af218b7 100644 --- a/AltCover.Async/Instance.cs +++ b/AltCover.Async/Instance.cs @@ -1,89 +1,44 @@ using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System; using System.Runtime.InteropServices; -using System.Runtime.Versioning; using System.Threading; +using System.Runtime.Versioning; +using System.Diagnostics.CodeAnalysis; [assembly: CLSCompliant(true)] [assembly: ComVisible(false)] -[assembly: SuppressMessage("Gendarme.Rules.Performance", - "AvoidUncalledPrivateCodeRule", - Scope = "member", // MethodDefinition - Target = "AltCover.Recorder.Instance/I/CallTrack::get_attr()", - Justification = "stub assembly")] -[assembly: SuppressMessage("Gendarme.Rules.Performance", - "AvoidUncalledPrivateCodeRule", - Scope = "member", // MethodDefinition - Target = "AltCover.Recorder.Instance/I/CallTrack::instance()", - Justification = "stub assembly")] -[assembly: SuppressMessage("Gendarme.Rules.Naming", - "UseCorrectCasingRule", - Scope = "member", // MethodDefinition - Target = "AltCover.Recorder.Instance/I/CallTrack::get_attr()", - Justification = "stub assembly")] -[assembly: SuppressMessage("Gendarme.Rules.Naming", - "UseCorrectCasingRule", - Scope = "member", // MethodDefinition - Target = "AltCover.Recorder.Instance/I/CallTrack::get_value()", - Justification = "stub assembly")] -[assembly: SuppressMessage("Gendarme.Rules.Naming", - "UseCorrectCasingRule", - Scope = "member", // MethodDefinition - Target = "AltCover.Recorder.Instance/I/CallTrack::instance()", - Justification = "stub assembly")] -[assembly: SuppressMessage("Gendarme.Rules.Performance", - "AvoidRepetitiveCallsToPropertiesRule", - Scope = "member", // MethodDefinition - Target = "AltCover.Recorder.Instance/I/CallTrack::instance()", - Justification = "stub assembly")] -[assembly: SuppressMessage("Microsoft.Performance", - "CA1811:AvoidUncalledPrivateCode", - Scope = "member", - Target = "AltCover.Recorder.Instance+I+CallTrack.#instance()", - Justification = "stub assembly")] -[assembly: SuppressMessage("Microsoft.Performance", - "CA1810:InitializeReferenceTypeStaticFieldsInline", - Scope = "member", - Target = "AltCover.Recorder.LibraryHelper.#.cctor()", - Justification = "stub assembly")] namespace AltCover.Recorder; -internal static class LibraryHelper -{ - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - internal static readonly TargetFrameworkAttribute attr_004011; - - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - internal static readonly AsyncLocal> value_004014; - - static LibraryHelper() - { - TargetFrameworkAttribute attr = (attr_004011 = new TargetFrameworkAttribute(".NETFramework,Version=v4.6")); - AsyncLocal> asyncLocal = (value_004014 = new AsyncLocal>()); - } -} - public static class Instance { public static class I { internal static class CallTrack { - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "stub assembly")] - internal static TargetFrameworkAttribute attr => LibraryHelper.attr_004011; - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "stub assembly")] - internal static AsyncLocal> value => LibraryHelper.value_004014; - - internal static Stack instance() + [SuppressMessage("Microsoft.Performance", + "CA1823:AvoidUnusedPrivateFields", + Justification = "Template code only")] + private static readonly TargetFrameworkAttribute attr = + new TargetFrameworkAttribute(".NETFramework,Version=v4.6"); + + private static readonly AsyncLocal> value = new AsyncLocal>(); + + // no race conditions here + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidUncalledPrivateCodeRule", + Justification = "Template code only")] + [SuppressMessage("Microsoft.Performance", + "CA1811:AvoidUncalledPrivateCode", + Justification = "Template code only")] + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidRepetitiveCallsToPropertiesRule", + Justification = "Initialization")] + private static Stack Instance() { if (value.Value == null) - { value.Value = new Stack(); - } + return value.Value; } } diff --git a/AltCover.Async/Library.fs b/AltCover.Async/Library.fs new file mode 100644 index 00000000..239e9991 --- /dev/null +++ b/AltCover.Async/Library.fs @@ -0,0 +1,60 @@ +namespace AltCover.Recorder + +open System.Collections.Generic +open System.Diagnostics.CodeAnalysis +open System.Threading + +module Instance = + module I = + module private CallTrack = + + let attr = + System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6") + + let value = AsyncLocal>() + + let instance () = + match value.Value with + | null -> value.Value <- Stack() + | _ -> () + + value.Value + +[] +[] +[] +[] +[] +[] +[] +[] +() \ No newline at end of file diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 6cb5f034..64d6849d 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -98,7 +98,7 @@ internal static Sampling Sample } /// - /// Gets the unique token for this instance + /// Gets the unique token for this Instance /// This property's IL code is modified to store a GUID-based token /// internal static string Token @@ -341,10 +341,10 @@ public T Value /// private static class CallTrack { - private static AsyncLocal> value = new AsyncLocal>(); + private static readonly AsyncLocal> value = new AsyncLocal>(); // no race conditions here - private static Stack instance() + private static Stack Instance() { if (value.Value == null) value.Value = new Stack(); @@ -354,18 +354,18 @@ private static Stack instance() public static Nullable Peek() { - var i = instance(); + var i = Instance(); return (i.Count > 0) ? (Nullable)i.Peek() : null; } public static void Push(int x) { - instance().Push(x); + Instance().Push(x); } public static Nullable Pop() { - var i = instance(); + var i = Instance(); return (i.Count > 0) ? (Nullable)i.Pop() : null; } } From e35607fbcd307f5d5bfafabcbf8852098183a388 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 18 Jul 2024 13:09:46 +0100 Subject: [PATCH 70/91] Finally, that elusive last test. --- AltCover.Async/Instance.cs | 16 +- AltCover.Engine/Instrument.fs | 6 +- AltCover.Engine/Runner.fs | 4 +- AltCover.Recorder.Tests/Adapter.fs | 28 ++- AltCover.Recorder.Tests/Recorder.Tests.fs | 49 ++-- AltCover.Recorder/Recorder.cs | 13 +- AltCover.Tests/Runner.Tests.fs | 48 ++-- AltCover.Tests/XTests.fs | 4 +- Samples/Sample3/Class1.cs | 280 +++++++++++----------- 9 files changed, 231 insertions(+), 217 deletions(-) diff --git a/AltCover.Async/Instance.cs b/AltCover.Async/Instance.cs index 5af218b7..74aec14b 100644 --- a/AltCover.Async/Instance.cs +++ b/AltCover.Async/Instance.cs @@ -22,7 +22,15 @@ internal static class CallTrack private static readonly TargetFrameworkAttribute attr = new TargetFrameworkAttribute(".NETFramework,Version=v4.6"); - private static readonly AsyncLocal> value = new AsyncLocal>(); + private static readonly AsyncLocal> __value = new AsyncLocal>(); + + private static AsyncLocal> Value + { + [SuppressMessage("Microsoft.Performance", + "CA1811:AvoidUncalledPrivateCode", + Justification = "Template code only")] + get { return __value; } + } // no race conditions here [SuppressMessage("Gendarme.Rules.Performance", @@ -36,10 +44,10 @@ internal static class CallTrack Justification = "Initialization")] private static Stack Instance() { - if (value.Value == null) - value.Value = new Stack(); + if (Value.Value == null) + Value.Value = new Stack(); - return value.Value; + return Value.Value; } } } diff --git a/AltCover.Engine/Instrument.fs b/AltCover.Engine/Instrument.fs index 17685ed7..f6a85a45 100644 --- a/AltCover.Engine/Instrument.fs +++ b/AltCover.Engine/Instrument.fs @@ -1209,7 +1209,7 @@ module internal Instrument = let value = calltrack.Properties - |> Seq.find (fun m -> m.Name == "value") + |> Seq.find (fun m -> m.Name == "Value") let getValue = value.GetMethod @@ -1222,7 +1222,7 @@ module internal Instrument = GetValue = getValue Instance = calltrack.Methods - |> Seq.find (fun m -> m.Name == "instance") + |> Seq.find (fun m -> m.Name == "Instance") Field = field FieldType = field.FieldType :?> GenericInstanceType Maker = @@ -1336,7 +1336,7 @@ module internal Instrument = let getterDef = recorder.MainModule.GetTypes() |> Seq.collect _.Methods - |> Seq.filter (fun m -> m.Name == "get_modules") + |> Seq.filter (fun m -> m.Name == "get_Modules") |> Seq.head let body = getterDef.Body diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 930efdcc..99c5018e 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1112,7 +1112,7 @@ module internal Runner = then hits.Add(key, Dictionary()) - Counter.AddVisit (hits, key, hitPointId, visit) + Counter.AddVisit(hits, key, hitPointId, visit) else 0L @@ -1391,7 +1391,7 @@ module internal Runner = | _ -> new MemoryStream() :> Stream let result = - AltCover.Counter.DoFlushStream ( + AltCover.Counter.DoFlushStream( (postProcess hits format), pointProcess, true, diff --git a/AltCover.Recorder.Tests/Adapter.fs b/AltCover.Recorder.Tests/Adapter.fs index e47c8f0c..750cd110 100644 --- a/AltCover.Recorder.Tests/Adapter.fs +++ b/AltCover.Recorder.Tests/Adapter.fs @@ -11,12 +11,12 @@ module Adapter = let DoExit () = Instance.I.doExit let VisitsClear () = - Instance.I.Clear () + Instance.I.Clear() Counter.branchVisits <- 0L Counter.totalVisits <- 0L let SamplesClear () = - Instance.I.samples <- Instance.I.MakeSamples () + Instance.I.samples <- Instance.I.MakeSamples() let private reset () = Instance.I.isRunner <- false @@ -71,16 +71,16 @@ module Adapter = let Lock = Instance.I.visits :> obj let VisitImplNone (moduleId, hitPointId) = - Instance.I.VisitImpl (moduleId, hitPointId, Null()) + Instance.I.VisitImpl(moduleId, hitPointId, Null()) let VisitImplMethod (moduleId, hitPointId, mId) = - Instance.I.VisitImpl (moduleId, hitPointId, (Call mId)) + Instance.I.VisitImpl(moduleId, hitPointId, (Call mId)) let internal addSample (moduleId, hitPointId, context) = - Instance.I.TakeSample (Sampling.Single, moduleId, hitPointId, context) + Instance.I.TakeSample(Sampling.Single, moduleId, hitPointId, context) let internal addSampleUnconditional (moduleId, hitPointId, context) = - Instance.I.TakeSample (Sampling.All, moduleId, hitPointId, context) + Instance.I.TakeSample(Sampling.All, moduleId, hitPointId, context) let internal newBoth (time, call) = Both(Pair.Create(time, call)) @@ -120,10 +120,10 @@ module Adapter = else output - Counter.DoFlushFile (ignore, (fun _ _ -> ()), true, visits, format, report, output') + Counter.DoFlushFile(ignore, (fun _ _ -> ()), true, visits, format, report, output') let internal updateReport (counts, format, coverageFile, outputFile) = - Counter.I.UpdateReport ( + Counter.I.UpdateReport( ignore, (fun _ _ -> ()), true, @@ -133,19 +133,21 @@ module Adapter = outputFile ) - let internal payloadSelector x = Instance.I.PayloadSelector (fun _ -> x) + let internal payloadSelector x = Instance.I.PayloadSelector(fun _ -> x) let internal payloadControl (x, y) = - Instance.I.PayloadControl ((fun _ -> x), (fun _ -> y)) + Instance.I.PayloadControl((fun _ -> x), (fun _ -> y)) let internal payloadSelection (x, y, z) = - Instance.I.PayloadSelection ((fun _ -> x), (fun _ -> y), (fun _ -> z)) + Instance.I.PayloadSelection((fun _ -> x), (fun _ -> y), (fun _ -> z)) let internal makeNullTrace name = Tracer.Create(name) let internal makeStreamTrace s1 = let mutable t = Tracer.Create(null) + // fsharplint:disable-next-line RedundantNewKeyword t.Stream <- new System.IO.MemoryStream() + // fsharplint:disable-next-line RedundantNewKeyword t.Formatter <- new System.IO.BinaryWriter(s1) t.Runner <- true t.Definitive <- false @@ -172,7 +174,7 @@ module Adapter = | :? System.ArgumentNullException as ane -> ane.ParamName = unique | _ -> x.Message = unique - Instance.I.Issue71Wrapper ((), (), (), (), catcher, pitcher) + Instance.I.Issue71Wrapper((), (), (), (), catcher, pitcher) |> ignore let internal invokeCurriedIssue71Wrapper<'T when 'T :> System.Exception> @@ -187,7 +189,7 @@ module Adapter = constructor.Invoke([| unique |]) :?> System.Exception |> raise - Instance.I.CurriedIssue71Wrapper ( + Instance.I.CurriedIssue71Wrapper( "a", "b", "c", diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index 853a9fee..894ed251 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -16,7 +16,6 @@ open System.IO open System.IO.Compression open System.Reflection open System.Runtime.CompilerServices -open System.Threading open System.Xml open AltCover.Recorder @@ -80,9 +79,9 @@ module AltCoverTests = [] let DefaultAccessorsBehaveAsExpected () = let v1 = DateTime.UtcNow.Ticks - let probe = Instance.I.Clock () + let probe = Instance.I.Clock() let v2 = DateTime.UtcNow.Ticks - Assert.True(Instance.I.Granularity () = 0L) + Assert.True(Instance.I.Granularity() = 0L) Assert.True(probe >= v1) Assert.True(probe <= v2) @@ -195,7 +194,7 @@ module AltCoverTests = let key = " " let index = - Counter.I.FindIndexFromUspid (0, key) + Counter.I.FindIndexFromUspid(0, key) Assert.True(index < 0) @@ -383,7 +382,7 @@ module AltCoverTests = try Instance.I.Trace <- Adapter.makeNullTrace null - Instance.I.VisitSelection (Adapter.asNull (), key, 23) + Instance.I.VisitSelection(Adapter.asNull (), key, 23) Assert.That( Instance.I.visits.Keys, @@ -433,7 +432,7 @@ module AltCoverTests = let before = Directory.GetFiles(where, "*.exn") - Instance.I.LogException ("a", "b", "c", "ex") + Instance.I.LogException("a", "b", "c", "ex") let after = Directory.GetFiles(where, "*.exn") @@ -570,7 +569,7 @@ module AltCoverTests = let before = Directory.GetFiles(where, "*.exn") - Instance.I.VisitImpl (key, 23, Adapter.asNull ()) + Instance.I.VisitImpl(key, 23, Adapter.asNull ()) let after = Directory.GetFiles(where, "*.exn") @@ -613,8 +612,8 @@ module AltCoverTests = try let key = " " Adapter.ModuleReset [| key; "key" |] - Instance.I.VisitImpl (key, 23, Adapter.asNull ()) - Instance.I.VisitImpl ("key", 42, Adapter.asNull ()) + Instance.I.VisitImpl(key, 23, Adapter.asNull ()) + Instance.I.VisitImpl("key", 42, Adapter.asNull ()) Assert.That( Instance.I.visits.Keys, @@ -633,8 +632,8 @@ module AltCoverTests = try let key = " " Adapter.ModuleReset [| key |] - Instance.I.VisitImpl (key, 23, Adapter.asNull ()) - Instance.I.VisitImpl (key, 42, Adapter.asNull ()) + Instance.I.VisitImpl(key, 23, Adapter.asNull ()) + Instance.I.VisitImpl(key, 42, Adapter.asNull ()) Assert.That( Instance.I.visits.Keys, @@ -656,8 +655,8 @@ module AltCoverTests = Adapter.ModuleReset [| key |] try - Instance.I.VisitImpl (key, 23, Adapter.asNull ()) - Instance.I.VisitImpl (key, 23, Adapter.asNull ()) + Instance.I.VisitImpl(key, 23, Adapter.asNull ()) + Instance.I.VisitImpl(key, 23, Adapter.asNull ()) Assert.That(Instance.I.visits.[key].[23].Count, Is.EqualTo 2) Assert.That(Instance.I.visits.[key].[23].Tracks, Is.Empty) finally @@ -677,8 +676,8 @@ module AltCoverTests = let payload = Adapter.time DateTime.UtcNow.Ticks - Instance.I.VisitImpl (key, 23, Adapter.asNull ()) - Instance.I.VisitImpl (key, 23, payload) + Instance.I.VisitImpl(key, 23, Adapter.asNull ()) + Instance.I.VisitImpl(key, 23, payload) Assert.That(Instance.I.visits.[key].[23].Count, Is.EqualTo 1) Assert.That(Instance.I.visits.[key].[23].Tracks, Is.EquivalentTo [ payload ]) finally @@ -1267,8 +1266,8 @@ module AltCoverTests = (int64 (i + 1)) )) - let NullObj: obj = null - Adapter.DoPause().Invoke(NullObj, null) + let nullObj: obj = null + Adapter.DoPause().Invoke(nullObj, null) Adapter.VisitsSeq() |> Seq.cast>> @@ -1368,8 +1367,8 @@ module AltCoverTests = [ 0..9 ] |> Seq.iter (fun i -> Adapter.VisitsAdd(key, i, (int64 (i + 1)))) - let NullObj: obj = null - Adapter.DoResume().Invoke(NullObj, null) + let nullObj: obj = null + Adapter.DoResume().Invoke(nullObj, null) Adapter.VisitsSeq() |> Seq.cast>> @@ -1474,8 +1473,8 @@ module AltCoverTests = (int64 (i + 1)) )) - let NullObj: obj = null - Adapter.DoExit().Invoke(NullObj, null) + let nullObj: obj = null + Adapter.DoExit().Invoke(nullObj, null) let head = "Coverage statistics flushing took " @@ -1581,8 +1580,8 @@ module AltCoverTests = (int64 (i + 1)) )) - let NullObj: obj = null - Adapter.DoUnload().Invoke(NullObj, null) + let nullObj: obj = null + Adapter.DoUnload().Invoke(nullObj, null) let head = "Coverage statistics flushing took " @@ -2085,8 +2084,8 @@ module AltCoverTests = (int64 (i + 1)) )) - let NullObj: obj = null - Adapter.DoExit().Invoke(NullObj, null) + let nullObj: obj = null + Adapter.DoExit().Invoke(nullObj, null) let head = "Coverage statistics flushing took " diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 64d6849d..117f8a18 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -341,15 +341,20 @@ public T Value /// private static class CallTrack { - private static readonly AsyncLocal> value = new AsyncLocal>(); + private static readonly AsyncLocal> __value = new AsyncLocal>(); + + private static AsyncLocal> Value + { + get { return __value; } + } // no race conditions here private static Stack Instance() { - if (value.Value == null) - value.Value = new Stack(); + if (Value.Value == null) + Value.Value = new Stack(); - return value.Value; + return Value.Value; } public static Nullable Peek() diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index 10c9330e..70541acd 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -66,25 +66,25 @@ module AltCoverRunnerTests = let MaxTimeFirst () = let now = DateTime.Now let ago = now - TimeSpan(1, 0, 0, 0) - test <@ (Counter.I.MaxTime (now, ago)) = now @> + test <@ (Counter.I.MaxTime(now, ago)) = now @> [] let MaxTimeLast () = let now = DateTime.Now let ago = now - TimeSpan(1, 0, 0, 0) - test <@ (Counter.I.MaxTime (ago, now)) = now @> + test <@ (Counter.I.MaxTime(ago, now)) = now @> [] let MinTimeFirst () = let now = DateTime.Now let ago = now - TimeSpan(1, 0, 0, 0) - test <@ (Counter.I.MinTime (ago, now)) = ago @> + test <@ (Counter.I.MinTime(ago, now)) = ago @> [] let MinTimeLast () = let now = DateTime.Now let ago = now - TimeSpan(1, 0, 0, 0) - test <@ (Counter.I.MinTime (now, ago)) = ago @> + test <@ (Counter.I.MinTime(now, ago)) = ago @> [] let JunkUspidGivesNegativeIndex () = @@ -92,7 +92,7 @@ module AltCoverRunnerTests = let key = " " let index = - Counter.I.FindIndexFromUspid (0, key) + Counter.I.FindIndexFromUspid(0, key) test <@ index < 0 @> @@ -108,7 +108,7 @@ module AltCoverRunnerTests = let key = " " let v1 = - Counter.AddVisit (visits, key, 23, new Null()) + Counter.AddVisit(visits, key, 23, new Null()) Assert.That(v1, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) @@ -130,7 +130,7 @@ module AltCoverRunnerTests = let payload = Time DateTime.UtcNow.Ticks let v2 = - Counter.AddVisit (visits, key, 23, payload) + Counter.AddVisit(visits, key, 23, payload) Assert.That(v2, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) @@ -152,12 +152,12 @@ module AltCoverRunnerTests = let key = " " let v3 = - Counter.AddVisit (visits, key, 23, new Null()) + Counter.AddVisit(visits, key, 23, new Null()) Assert.That(v3, Is.EqualTo 1) let v4 = - Counter.AddVisit (visits, "key", 42, new Null()) + Counter.AddVisit(visits, "key", 42, new Null()) Assert.That(visits.Count, Is.EqualTo 2) Assert.That(v4, Is.EqualTo 1) @@ -174,12 +174,12 @@ module AltCoverRunnerTests = let key = " " let v5 = - Counter.AddVisit (visits, key, 23, new Null()) + Counter.AddVisit(visits, key, 23, new Null()) Assert.That(v5, Is.EqualTo 1) let v6 = - Counter.AddVisit (visits, key, 42, new Null()) + Counter.AddVisit(visits, key, 42, new Null()) Assert.That(v6, Is.EqualTo 1) Assert.That(visits.Count, Is.EqualTo 1) @@ -197,12 +197,12 @@ module AltCoverRunnerTests = let key = " " let v7 = - Counter.AddVisit (visits, key, 23, new Null()) + Counter.AddVisit(visits, key, 23, new Null()) Assert.That(v7, Is.EqualTo 1) let v8 = - Counter.AddVisit (visits, key, 23, new Null()) + Counter.AddVisit(visits, key, 23, new Null()) Assert.That(v8, Is.EqualTo 1) let x = visits.[key].[23] @@ -222,12 +222,12 @@ module AltCoverRunnerTests = let payload = Time DateTime.UtcNow.Ticks let v9 = - Counter.AddVisit (visits, key, 23, new Null()) + Counter.AddVisit(visits, key, 23, new Null()) Assert.That(v9, Is.EqualTo 1) let v10 = - Counter.AddVisit (visits, key, 23, payload) + Counter.AddVisit(visits, key, 23, payload) Assert.That(v10, Is.EqualTo 1) let x = visits.[key].[23] @@ -284,7 +284,7 @@ module AltCoverRunnerTests = item.Add("7C-CD-66-29-A3-6C-6D-5F-A7-65-71-0E-22-7D-B2-61-B5-1F-65-9A", payload) - Counter.I.UpdateReport ( + Counter.I.UpdateReport( ignore, (fun _ _ -> ()), true, @@ -2609,7 +2609,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit(counts, moduleId, hitPointId, hit) |> ignore) // degenerate case @@ -2732,7 +2732,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit(counts, moduleId, hitPointId, hit) |> ignore) let entries = Dictionary() @@ -2856,7 +2856,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit(counts, moduleId, hitPointId, hit) |> ignore) // degenerate case 1 @@ -3030,7 +3030,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit(counts, moduleId, hitPointId, hit) |> ignore) let entries = Dictionary() @@ -3175,7 +3175,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit(counts, moduleId, hitPointId, hit) |> ignore) // degenerate case @@ -3302,7 +3302,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit(counts, moduleId, hitPointId, hit) |> ignore) let entries = Dictionary() @@ -3438,7 +3438,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit(counts, moduleId, hitPointId, hit) |> ignore) // degenerate case 1 @@ -3620,7 +3620,7 @@ module AltCoverRunnerTests = if counts.ContainsKey moduleId |> not then counts.Add(moduleId, Dictionary()) - AltCover.Counter.AddVisit (counts, moduleId, hitPointId, hit) + AltCover.Counter.AddVisit(counts, moduleId, hitPointId, hit) |> ignore) let entries = Dictionary() diff --git a/AltCover.Tests/XTests.fs b/AltCover.Tests/XTests.fs index 2bc99d5d..b740966f 100644 --- a/AltCover.Tests/XTests.fs +++ b/AltCover.Tests/XTests.fs @@ -1427,7 +1427,7 @@ module AltCoverXTests = t1.GetNestedType("CallTrack", BindingFlags.NonPublic) let p = - t2.GetProperty("value", BindingFlags.NonPublic ||| BindingFlags.Static) + t2.GetProperty("Value", BindingFlags.NonPublic ||| BindingFlags.Static) let v = p.GetValue(nullObject) @@ -1435,7 +1435,7 @@ module AltCoverXTests = test <@ v.GetType() = typeof>> @> let m = - t2.GetMethod("instance", BindingFlags.NonPublic ||| BindingFlags.Static) + t2.GetMethod("Instance", BindingFlags.NonPublic ||| BindingFlags.Static) let v2 = m.Invoke(nullObject, [||]) diff --git a/Samples/Sample3/Class1.cs b/Samples/Sample3/Class1.cs index fae74766..6547b79a 100644 --- a/Samples/Sample3/Class1.cs +++ b/Samples/Sample3/Class1.cs @@ -6,169 +6,169 @@ // cheat to allow init-property namespace System.Runtime.CompilerServices { - internal static class IsExternalInit - { } + internal static class IsExternalInit + { } } namespace AltCover.Sample3 { - public class Class1 - { - public int Property { get; set; } + public class Class1 + { + public int Property { get; set; } #if !MONO - public int Property2 { get; init; } + public int Property2 { get; init; } #endif - } + } - public class Class2 - { - private int _Property; + public class Class2 + { + private int _Property; - public int Property - { get { return _Property; } set { _Property = value > 0 ? value : 0; } } - } + public int Property + { get { return _Property; } set { _Property = value > 0 ? value : 0; } } + } - public class Class3 + public class Class3 + { + public class Class4 { - public class Class4 - { - public Class1 Property { get; set; } - - public List ToList(T item) - { - try - { - return new List { item }; - } - catch (NullReferenceException) - { - return Enumerable.Empty().ToList(); - } - } - - public string ReportFile { get; set; } - public string Token { get; set; } - public int CoverageFormat { get; set; } - public int Sample { get; set; } - public Int64 Timer { get; set; } - public bool Defer { get; set; } - public static string[] modules { get; set; } - } + public Class1 Property { get; set; } - private static List> log = new List>(); - - public List> Visits + public List ToList(T item) + { + try { - get - { - return log; - } + return new List { item }; } - - public static void Log(string id, int num) + catch (NullReferenceException) { - log.Add(Tuple.Create(id, num)); + return Enumerable.Empty().ToList(); } + } + + public string ReportFile { get; set; } + public string Token { get; set; } + public int CoverageFormat { get; set; } + public int Sample { get; set; } + public Int64 Timer { get; set; } + public bool Defer { get; set; } + public static string[] Modules { get; set; } + } - public static int GetOperandType(Instruction self) - { - int i = 0; - switch (self.OpCode.Code) - { - case Code.Ldarg_0: - case Code.Ldarg_1: - case Code.Ldarg_2: - case Code.Ldarg_3: - case Code.Ldarg: - case Code.Ldarg_S: - case Code.Ldarga: - case Code.Ldarga_S: - case Code.Starg: - case Code.Starg_S: - i = 1; - Console.WriteLine("arguments"); - break; - - case Code.Conv_R4: - case Code.Ldc_R4: - case Code.Ldelem_R4: - case Code.Ldind_R4: - case Code.Stelem_R4: - case Code.Stind_R4: - i = 2; - Console.WriteLine("singles"); - break; - - case Code.Conv_R8: - case Code.Ldc_R8: - case Code.Ldelem_R8: - case Code.Ldind_R8: - case Code.Stelem_R8: - i = 3; - Console.WriteLine("doubles"); - break; - - case Code.Ldloc_0: - case Code.Ldloc_1: - case Code.Ldloc_2: - case Code.Ldloc_3: - case Code.Ldloc: - case Code.Ldloc_S: - case Code.Ldloca: - case Code.Ldloca_S: - case Code.Stloc_0: - case Code.Stloc_1: - case Code.Stloc_2: - case Code.Stloc_3: - case Code.Stloc: - case Code.Stloc_S: - i = 4; - Console.WriteLine("locals"); - break; - - case Code.Ldfld: - case Code.Ldflda: - case Code.Ldsfld: - case Code.Ldsflda: - case Code.Stfld: - case Code.Stsfld: - i = 5; - Console.WriteLine("fields"); - break; - - case Code.Call: - case Code.Callvirt: - case Code.Newobj: - i = 6; - Console.WriteLine("calls"); - break; - - default: - i = 7; - Console.WriteLine("default"); - break; - } - Console.WriteLine("end"); - return i; - } + private static List> log = new List>(); + + public List> Visits + { + get + { + return log; + } + } + + public static void Log(string id, int num) + { + log.Add(Tuple.Create(id, num)); } + + public static int GetOperandType(Instruction self) + { + int i = 0; + switch (self.OpCode.Code) + { + case Code.Ldarg_0: + case Code.Ldarg_1: + case Code.Ldarg_2: + case Code.Ldarg_3: + case Code.Ldarg: + case Code.Ldarg_S: + case Code.Ldarga: + case Code.Ldarga_S: + case Code.Starg: + case Code.Starg_S: + i = 1; + Console.WriteLine("arguments"); + break; + + case Code.Conv_R4: + case Code.Ldc_R4: + case Code.Ldelem_R4: + case Code.Ldind_R4: + case Code.Stelem_R4: + case Code.Stind_R4: + i = 2; + Console.WriteLine("singles"); + break; + + case Code.Conv_R8: + case Code.Ldc_R8: + case Code.Ldelem_R8: + case Code.Ldind_R8: + case Code.Stelem_R8: + i = 3; + Console.WriteLine("doubles"); + break; + + case Code.Ldloc_0: + case Code.Ldloc_1: + case Code.Ldloc_2: + case Code.Ldloc_3: + case Code.Ldloc: + case Code.Ldloc_S: + case Code.Ldloca: + case Code.Ldloca_S: + case Code.Stloc_0: + case Code.Stloc_1: + case Code.Stloc_2: + case Code.Stloc_3: + case Code.Stloc: + case Code.Stloc_S: + i = 4; + Console.WriteLine("locals"); + break; + + case Code.Ldfld: + case Code.Ldflda: + case Code.Ldsfld: + case Code.Ldsflda: + case Code.Stfld: + case Code.Stsfld: + i = 5; + Console.WriteLine("fields"); + break; + + case Code.Call: + case Code.Callvirt: + case Code.Newobj: + i = 6; + Console.WriteLine("calls"); + break; + + default: + i = 7; + Console.WriteLine("default"); + break; + } + Console.WriteLine("end"); + return i; + } + } } // AltCover.Recorder.InstrumentationAttribute namespace AltCover.Recorder { - [Serializable] - [AttributeUsage(AttributeTargets.Assembly)] - public sealed class InstrumentationAttribute : Attribute - { - public string Assembly { get; set; } + [Serializable] + [AttributeUsage(AttributeTargets.Assembly)] + public sealed class InstrumentationAttribute : Attribute + { + public string Assembly { get; set; } - public string Configuration { get; set; } + public string Configuration { get; set; } - public InstrumentationAttribute() - { - Assembly = "Sample3 test assembly!"; - Configuration = "Unit testing only!!"; - } + public InstrumentationAttribute() + { + Assembly = "Sample3 test assembly!"; + Configuration = "Unit testing only!!"; } + } } \ No newline at end of file From 120e865e0d4e4ef6f878ecc904c393c709f05574 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 18 Jul 2024 14:15:17 +0100 Subject: [PATCH 71/91] Starting to work! --- AltCover.Async/Instance.cs | 5 +++++ AltCover.Engine/Instrument.fs | 4 +++- AltCover.Recorder/Recorder.cs | 7 +++++-- AltCover.Tests/Tests.fs | 8 ++++---- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/AltCover.Async/Instance.cs b/AltCover.Async/Instance.cs index 74aec14b..3177ac51 100644 --- a/AltCover.Async/Instance.cs +++ b/AltCover.Async/Instance.cs @@ -12,6 +12,11 @@ namespace AltCover.Recorder; public static class Instance { + //internal static IEnumerable Modules + //{ + // get { return new string[] { "a", "b", "c", "d" }; } + //} + public static class I { internal static class CallTrack diff --git a/AltCover.Engine/Instrument.fs b/AltCover.Engine/Instrument.fs index f6a85a45..915762d9 100644 --- a/AltCover.Engine/Instrument.fs +++ b/AltCover.Engine/Instrument.fs @@ -1363,7 +1363,7 @@ module internal Instrument = [ worker.Create(OpCodes.Dup) worker.Create(OpCodes.Ldc_I4, i) worker.Create(OpCodes.Ldstr, k) - worker.Create(OpCodes.Stelem_Any, stringtype) ] + worker.Create(OpCodes.Stelem_Ref) ] bulkInsertBefore worker head addElement true |> ignore) @@ -1372,6 +1372,8 @@ module internal Instrument = [ worker.Create(OpCodes.Stsfld, head.Operand :?> FieldReference) ] bulkInsertBefore worker head store true |> ignore + let re = [ worker.Create OpCodes.Ret ] + bulkInsertBefore worker head re true |> ignore let recorderFileName = (extractName state.RecordingAssembly) + ".dll" diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 117f8a18..2ac21073 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -111,9 +111,12 @@ internal static string Token /// Gets the indexed module tokens /// This property's IL code is modified to store instrumentation results /// - private static IEnumerable __modules = new string[] { string.Empty }; + private static string[] __modules = new string[] { string.Empty }; - internal static IEnumerable Modules + [SuppressMessage("Gendarme.Rules.Performance", + "AvoidReturningArraysOnPropertiesRule", + Justification = "Controlled use")] + internal static string[] Modules { #if DEBUG [SuppressMessage("Gendarme.Rules.Performance", diff --git a/AltCover.Tests/Tests.fs b/AltCover.Tests/Tests.fs index ed73bf73..24e4e463 100644 --- a/AltCover.Tests/Tests.fs +++ b/AltCover.Tests/Tests.fs @@ -3346,8 +3346,8 @@ module AltCoverTests = "set_CoverageFormat" "get_Sample" "set_Sample" - "get_modules" - "set_modules" + "get_Modules" + "set_Modules" "ToList" "#ctor" "#ctor" @@ -3401,8 +3401,8 @@ module AltCoverTests = "System.Void AltCover.Sample3.Class3+Class4.set_CoverageFormat(System.Int32)" "System.Int32 AltCover.Sample3.Class3+Class4.get_Sample()" "System.Void AltCover.Sample3.Class3+Class4.set_Sample(System.Int32)" - "System.String[] AltCover.Sample3.Class3+Class4.get_modules()" - "System.Void AltCover.Sample3.Class3+Class4.set_modules(System.String[])" + "System.String[] AltCover.Sample3.Class3+Class4.get_Modules()" + "System.Void AltCover.Sample3.Class3+Class4.set_Modules(System.String[])" "System.Collections.Generic.List`1 AltCover.Sample3.Class3+Class4.ToList(T)" "System.Void AltCover.Sample3.Class3+Class4.#ctor()" "System.String AltCover.Recorder.InstrumentationAttribute.get_Assembly()" From 8ec649c95ff7fc69ed5b9c7c6c6ddc08388e0d37 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Thu, 18 Jul 2024 18:27:43 +0100 Subject: [PATCH 72/91] Need to cover explicit code that F# simply implied --- .../AltCover.Recorder.Tests.fsproj | 3 +- AltCover.Recorder.Tests/Base.Tests.fs | 65 +++++++++++++++++++ AltCover.Recorder.Tests/Recorder.Tests.fs | 2 + AltCover.Recorder/Base.cs | 17 ++--- AltCover.Recorder/Recorder.cs | 7 +- .../AltCover.Recorder2.Tests.fsproj | 2 +- AltCover.Tests/AltCover.Tests.fsproj | 4 +- AltCover.Tests/Expecto.fs | 4 ++ Build/targets.fs | 8 +-- 9 files changed, 90 insertions(+), 22 deletions(-) create mode 100644 AltCover.Recorder.Tests/Base.Tests.fs diff --git a/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj b/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj index 3ed9d505..ad49c9ee 100644 --- a/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj +++ b/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj @@ -24,6 +24,7 @@ + @@ -63,7 +64,7 @@ - + contentfiles diff --git a/AltCover.Recorder.Tests/Base.Tests.fs b/AltCover.Recorder.Tests/Base.Tests.fs new file mode 100644 index 00000000..a33bfe85 --- /dev/null +++ b/AltCover.Recorder.Tests/Base.Tests.fs @@ -0,0 +1,65 @@ +#if RUNNER_TESTS +namespace Tests +#else +#if !NET472 +#if NET20 +namespace Tests.Recorder.Clr2 +#else +namespace Tests.Recorder.Core +#endif +#else +namespace Tests.Recorder.Clr4 +#endif +#endif + +open System + +#if RUNNER_TESTS +open AltCover +#else +open AltCover.Recorder +open NUnit.Framework +#endif + +module BaseTests = + [] + let ExerciseBoth () = + let b = Both(Pair.Create(0L, 0)) + let b1 = Both(Pair.Create(0L, 0)) + let b2 = Both(Pair.Create(1L, 2)) + Assert.That(b1.Equals(b)) + Assert.That(not <| b2.Equals(b)) + Assert.That(not <| b2.Equals(String.Empty)) + Assert.That(b.GetHashCode(), Is.EqualTo <| b1.GetHashCode()) + Assert.That(b.ToString(), Is.EqualTo("AltCover.Both : AltCover.Pair(Time=0, Call=0)")) + + [] + let ExerciseCall () = + let b = Call(0) + let b1 = Call(0) + let b2 = Call(2) + Assert.That(b1.Equals(b)) + Assert.That(not <| b2.Equals(b)) + Assert.That(not <| b2.Equals(String.Empty)) + Assert.That(b.GetHashCode(), Is.EqualTo <| b1.GetHashCode()) + Assert.That(b.ToString(), Is.EqualTo("AltCover.Call : 0")) + + [] + let ExerciseTime () = + let b = Time(0l) + let b1 = Time(0l) + let b2 = Time(2l) + Assert.That(b1.Equals(b)) + Assert.That(not <| b2.Equals(b)) + Assert.That(not <| b2.Equals(String.Empty)) + Assert.That(b.GetHashCode(), Is.EqualTo <| b1.GetHashCode()) + Assert.That(b.ToString(), Is.EqualTo("AltCover.Time : 0")) + + [] + let ExerciseNull () = + let b = Null() + let b1 = Null() + Assert.That(b1.Equals(b)) + Assert.That(not <| b.Equals(String.Empty)) + Assert.That(b.GetHashCode(), Is.EqualTo <| b1.GetHashCode()) + Assert.That(b.ToString(), Is.EqualTo("AltCover.Null")) \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index 894ed251..89e19433 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -117,6 +117,8 @@ module AltCoverTests = Assert.True(Adapter.addSampleUnconditional ("module", 23, n), "Test 5") Assert.True(Adapter.addSample ("module", 23, Call 1), "Test 6") Assert.True(Adapter.addSample ("module", 23, Time 0L), "Test 7") + Assert.True(Adapter.addSample ("module", 23, Time 1L), "Test 7a") + Assert.True(Adapter.addSample ("module", 23, Time 0L) |> not, "Test 7b") Assert.True( Adapter.addSample ("module", 24, new Both(Pair.Create(0, 1))), diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 41dc9548..19c8b621 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -2,6 +2,7 @@ namespace AltCover #else + namespace AltCover.Recorder #endif { @@ -123,16 +124,6 @@ internal abstract class Track { internal const string Entry = "\u2611"; // BALLOT BOX WITH CHECK internal const string Exit = "\u2612"; // BALLOT BOX WITH X - - public override bool Equals(object obj) - { - return (obj is Track); - } - - public override int GetHashCode() - { - return 0; - } } [SuppressMessage("Gendarme.Rules.Performance", @@ -460,6 +451,7 @@ internal static void EnsurePoint(Dictionary counts, int hitPoin } } +#if RUNNER [SuppressMessage("Gendarme.Rules.Performance", "AvoidUncalledPrivateCodeRule", Justification = "Internals Visible To")] @@ -494,6 +486,7 @@ Dictionary> t } return hitcount; } +#endif // TODO inline in release if possible internal static IEnumerable SelectNodes(XmlNode node, string name) @@ -751,7 +744,7 @@ Stream outputFile [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", - Justification="MemoryStream is 'use'd if created")] + Justification = "MemoryStream is 'use'd if created")] internal static TimeSpan DoFlushStream( Action postProcess, PointProcessor pointProcess, @@ -883,7 +876,7 @@ public Source(Stream t) Justification = "Third party interface")] public Stream GetSource() { - return _target; + return _target; } } diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 2ac21073..ce21c695 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -269,14 +269,15 @@ internal static string GetResource(string s) { var cc = System.Globalization.CultureInfo.CurrentUICulture; var names = new string[] { cc.Name, cc.Parent.Name, "en" }; + string result = null; foreach (var name in names) { - var result = resources.GetString(s + "." + name); + result = resources.GetString(s + "." + name); if (!string.IsNullOrEmpty(result)) - return result; + break; } - return null; + return result; } private static Dictionary> MakeVisits() diff --git a/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj b/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj index 303ea2b2..967218ee 100644 --- a/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj +++ b/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj @@ -25,11 +25,11 @@ + - diff --git a/AltCover.Tests/AltCover.Tests.fsproj b/AltCover.Tests/AltCover.Tests.fsproj index cedbcb3a..fe2611d7 100644 --- a/AltCover.Tests/AltCover.Tests.fsproj +++ b/AltCover.Tests/AltCover.Tests.fsproj @@ -6,7 +6,7 @@ AltCover.Tests MONO WINDOWS - TRACE;$(ExtraDefines) + TRACE;RUNNER_TESTS;$(ExtraDefines) @@ -27,6 +27,7 @@ + @@ -111,6 +112,7 @@ + diff --git a/AltCover.Tests/Expecto.fs b/AltCover.Tests/Expecto.fs index 594fca6d..d2a252f9 100644 --- a/AltCover.Tests/Expecto.fs +++ b/AltCover.Tests/Expecto.fs @@ -12,6 +12,10 @@ module ExpectoTestManifest = let simpleTests () = [| #endif + Tests.BaseTests.ExerciseBoth, "BaseTests.ExerciseBoth" + Tests.BaseTests.ExerciseTime, "BaseTests.ExerciseTime" + Tests.BaseTests.ExerciseCall, "BaseTests.ExerciseCall" + Tests.BaseTests.ExerciseNull, "BaseTests.ExerciseNull" Tests.TestCommonTests.TestMultiple, "Tests.TestCommonTests.TestMultiple" Tests.TestCommonTests.TestIgnoredTests, "TestCommonTests.TestIgnoredTests" Tests.TestCommonTests.ExerciseItAll, "TestCommonTests.ExerciseItAll" diff --git a/Build/targets.fs b/Build/targets.fs index 293772c6..3ca6ee51 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -1841,8 +1841,8 @@ module Targets = [ Path.getFullName "./AltCover.Expecto.Tests/AltCover.Expecto.Tests.fsproj" Path.getFullName "./AltCover.Api.Tests/AltCover.Api.Tests.fsproj" - Path.getFullName "./AltCover.Recorder.Tests/AltCover.Recorder.Tests.csproj" - Path.getFullName "./AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.csproj" + Path.getFullName "./AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj" + Path.getFullName "./AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj" //Path.getFullName "./AltCover.Monitor.Tests/AltCover.Monitor.Tests.fsproj" Path.getFullName "./AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj" @@ -1864,8 +1864,8 @@ module Targets = [ Path.getFullName "./AltCover.Expecto.Tests/AltCover.Expecto.Tests.fsproj" Path.getFullName "./AltCover.Api.Tests/AltCover.Api.Tests.fsproj" //Path.getFullName "./AltCover.Monitor.Tests/AltCover.Monitor.Tests.fsproj" - Path.getFullName "./AltCover.Recorder.Tests/AltCover.Recorder.Tests.csproj" - Path.getFullName "./AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.csproj" + Path.getFullName "./AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj" + Path.getFullName "./AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj" Path.getFullName "./AltCover.Visualizer.Tests/AltCover.Visualizer.Tests.fsproj" Path.getFullName From 4b302628aff67fb66b04c49494a705fcf35329d1 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 19 Jul 2024 15:05:29 +0100 Subject: [PATCH 73/91] 100% line coverage, all tests pass. Not to start debugging. --- AltCover.Recorder.Tests/Base.Tests.fs | 26 ++++++++++++++++++- AltCover.Recorder/Base.cs | 36 +++++++++++++-------------- AltCover.Tests/Expecto.fs | 1 + 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/AltCover.Recorder.Tests/Base.Tests.fs b/AltCover.Recorder.Tests/Base.Tests.fs index a33bfe85..9e845497 100644 --- a/AltCover.Recorder.Tests/Base.Tests.fs +++ b/AltCover.Recorder.Tests/Base.Tests.fs @@ -62,4 +62,28 @@ module BaseTests = Assert.That(b1.Equals(b)) Assert.That(not <| b.Equals(String.Empty)) Assert.That(b.GetHashCode(), Is.EqualTo <| b1.GetHashCode()) - Assert.That(b.ToString(), Is.EqualTo("AltCover.Null")) \ No newline at end of file + Assert.That(b.ToString(), Is.EqualTo("AltCover.Null")) + + [] + let ExercisePointVisit () = + let p = PointVisit.Create(); + let p1 = PointVisit.Create(); + Assert.That (p1.Equals(p)) + Assert.That(not <| p.Equals(String.Empty)) + Assert.That(p.GetHashCode(), Is.EqualTo <| p1.GetHashCode()) + Assert.That(p.ToString(), Is.EqualTo("AltCover.PointVisit : Count = 0 Tracks = ''")) + p.Track(Null()) + p1.Track(Null()) + Assert.That (p1.Equals(p)) + Assert.That(p.GetHashCode(), Is.EqualTo <| p1.GetHashCode()) + Assert.That(p.ToString(), Is.EqualTo("AltCover.PointVisit : Count = 0 Tracks = 'AltCover.Null'")) + p.Step() + Assert.That (p1.Equals(p) |> not) + p1.Step() + Assert.That (p1.Equals(p)) + Assert.That(p.GetHashCode(), Is.EqualTo <| p1.GetHashCode()) + p.Track(Both(Pair.Create(1L, 2))) + Assert.That (p1.Equals(p) |> not) + Assert.That(p.ToString(), Is.EqualTo("AltCover.PointVisit : Count = 1 Tracks = 'AltCover.Null; AltCover.Both : AltCover.Pair(Time=1, Call=2)'")) + p1.Track(Time(2l)) + Assert.That (p1.Equals(p) |> not) \ No newline at end of file diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 19c8b621..31451825 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -293,7 +293,7 @@ public override string ToString() tracks[i] = Tracks[i].ToString(); return "AltCover.PointVisit : Count = " + Count.ToString(CultureInfo.InvariantCulture) + - "Tracks = " + String.Join("; ", tracks); + " Tracks = '" + String.Join("; ", tracks) + "'"; } private PointVisit(long count) @@ -627,23 +627,23 @@ Stream outputFile index = FindIndexFromUspid(node.Value, node.Key.GetAttribute("uspid")); } - if (!moduleHits.ContainsKey(index)) - continue; - - var pt = node.Key; - - Int64.TryParse( - pt.GetAttribute(xmlformat.v), - NumberStyles.Integer, - CultureInfo.InvariantCulture, - out var vc - ); - - // Treat -ve visit counts (an exemption added in analysis) as zero - var count = moduleHits[index]; - var visits = Math.Max(vc, 0) + count.Total; - pt.SetAttribute(xmlformat.v, visits.ToString(CultureInfo.InvariantCulture)); - pointProcess(pt, count.Tracks); + if (moduleHits.ContainsKey(index)) + { + var pt = node.Key; + + Int64.TryParse( + pt.GetAttribute(xmlformat.v), + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out var vc + ); + + // Treat -ve visit counts (an exemption added in analysis) as zero + var count = moduleHits[index]; + var visits = Math.Max(vc, 0) + count.Total; + pt.SetAttribute(xmlformat.v, visits.ToString(CultureInfo.InvariantCulture)); + pointProcess(pt, count.Tracks); + } } } } diff --git a/AltCover.Tests/Expecto.fs b/AltCover.Tests/Expecto.fs index d2a252f9..79b726e9 100644 --- a/AltCover.Tests/Expecto.fs +++ b/AltCover.Tests/Expecto.fs @@ -16,6 +16,7 @@ module ExpectoTestManifest = Tests.BaseTests.ExerciseTime, "BaseTests.ExerciseTime" Tests.BaseTests.ExerciseCall, "BaseTests.ExerciseCall" Tests.BaseTests.ExerciseNull, "BaseTests.ExerciseNull" + Tests.BaseTests.ExercisePointVisit, "BaseTests.ExercisePointVisit" Tests.TestCommonTests.TestMultiple, "Tests.TestCommonTests.TestMultiple" Tests.TestCommonTests.TestIgnoredTests, "TestCommonTests.TestIgnoredTests" Tests.TestCommonTests.ExerciseItAll, "TestCommonTests.ExerciseItAll" From f1cca687f007476dd266a5efea865d2cfd27f56a Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 19 Jul 2024 15:43:40 +0100 Subject: [PATCH 74/91] Static analysis --- AltCover.Engine/Runner.fs | 2 +- AltCover.Recorder/Base.cs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 99c5018e..1d5dc1ce 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -1090,7 +1090,7 @@ module internal Runner = ``module`` () Table t - | _ -> new Null() + | _ -> Null() ) with :? EndOfStreamException -> None diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 31451825..6d446591 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -120,6 +120,9 @@ public override int GetHashCode() [SuppressMessage("Gendarme.Rules.Performance", "ImplementEqualsTypeRule", Justification = "abstract type, No use case")] + [SuppressMessage("Gendarme.Rules.Design", + "ConsiderUsingStaticTypeRule", + Justification = "Base class of union")] internal abstract class Track { internal const string Entry = "\u2611"; // BALLOT BOX WITH CHECK From a117eb70dbddc7036e30e823a59cf32c6345fb7a Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 19 Jul 2024 15:44:08 +0100 Subject: [PATCH 75/91] Fix confused IL generation --- AltCover.Engine/Instrument.fs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/AltCover.Engine/Instrument.fs b/AltCover.Engine/Instrument.fs index 915762d9..c2171319 100644 --- a/AltCover.Engine/Instrument.fs +++ b/AltCover.Engine/Instrument.fs @@ -1368,12 +1368,8 @@ module internal Instrument = bulkInsertBefore worker head addElement true |> ignore) - let store = - [ worker.Create(OpCodes.Stsfld, head.Operand :?> FieldReference) ] - - bulkInsertBefore worker head store true |> ignore - let re = [ worker.Create OpCodes.Ret ] - bulkInsertBefore worker head re true |> ignore + let ret = [ worker.Create OpCodes.Ret ] + bulkInsertBefore worker head ret true |> ignore let recorderFileName = (extractName state.RecordingAssembly) + ".dll" From c20f201b3b17f585d5bea1e2935c78bd4eba3dc7 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 19 Jul 2024 16:59:02 +0100 Subject: [PATCH 76/91] AltCoverRunner and Coverlet both give 100% line coverage - but where we record line coverage detail we get operational test failures --- AltCover.Recorder.Tests/Base.Tests.fs | 33 +++++++--- Build/targets.fs | 31 --------- rework failure list.txt | 91 +++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 41 deletions(-) create mode 100644 rework failure list.txt diff --git a/AltCover.Recorder.Tests/Base.Tests.fs b/AltCover.Recorder.Tests/Base.Tests.fs index 9e845497..f3303259 100644 --- a/AltCover.Recorder.Tests/Base.Tests.fs +++ b/AltCover.Recorder.Tests/Base.Tests.fs @@ -30,6 +30,7 @@ module BaseTests = Assert.That(b1.Equals(b)) Assert.That(not <| b2.Equals(b)) Assert.That(not <| b2.Equals(String.Empty)) + Assert.That(not <| b2.Value.Equals(String.Empty)) Assert.That(b.GetHashCode(), Is.EqualTo <| b1.GetHashCode()) Assert.That(b.ToString(), Is.EqualTo("AltCover.Both : AltCover.Pair(Time=0, Call=0)")) @@ -66,24 +67,36 @@ module BaseTests = [] let ExercisePointVisit () = - let p = PointVisit.Create(); - let p1 = PointVisit.Create(); - Assert.That (p1.Equals(p)) + let p = PointVisit.Create() + let p1 = PointVisit.Create() + Assert.That(p1.Equals(p)) Assert.That(not <| p.Equals(String.Empty)) Assert.That(p.GetHashCode(), Is.EqualTo <| p1.GetHashCode()) Assert.That(p.ToString(), Is.EqualTo("AltCover.PointVisit : Count = 0 Tracks = ''")) p.Track(Null()) p1.Track(Null()) - Assert.That (p1.Equals(p)) + Assert.That(p1.Equals(p)) Assert.That(p.GetHashCode(), Is.EqualTo <| p1.GetHashCode()) - Assert.That(p.ToString(), Is.EqualTo("AltCover.PointVisit : Count = 0 Tracks = 'AltCover.Null'")) + + Assert.That( + p.ToString(), + Is.EqualTo("AltCover.PointVisit : Count = 0 Tracks = 'AltCover.Null'") + ) + p.Step() - Assert.That (p1.Equals(p) |> not) + Assert.That(p1.Equals(p) |> not) p1.Step() - Assert.That (p1.Equals(p)) + Assert.That(p1.Equals(p)) Assert.That(p.GetHashCode(), Is.EqualTo <| p1.GetHashCode()) p.Track(Both(Pair.Create(1L, 2))) - Assert.That (p1.Equals(p) |> not) - Assert.That(p.ToString(), Is.EqualTo("AltCover.PointVisit : Count = 1 Tracks = 'AltCover.Null; AltCover.Both : AltCover.Pair(Time=1, Call=2)'")) + Assert.That(p1.Equals(p) |> not) + + Assert.That( + p.ToString(), + Is.EqualTo( + "AltCover.PointVisit : Count = 1 Tracks = 'AltCover.Null; AltCover.Both : AltCover.Pair(Time=1, Call=2)'" + ) + ) + p1.Track(Time(2l)) - Assert.That (p1.Equals(p) |> not) \ No newline at end of file + Assert.That(p1.Equals(p) |> not) \ No newline at end of file diff --git a/Build/targets.fs b/Build/targets.fs index 3ca6ee51..b78a2935 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -1723,15 +1723,6 @@ module Targets = Actions.Run (nunitConsole, ".", recArgs) "Recorder NUnit failed" - let rec2Args = - [ "--noheader" - "--work=." - "--result=./_Reports/JustRecorder2UnitTestReport.xml" - Path.getFullName - "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net20/AltCover.Recorder.Tests.dll" ] - - Actions.Run (nunitConsole, ".", rec2Args) "Recorder NUnit failed" - with x -> printfn "%A" x reraise ()) @@ -1766,15 +1757,6 @@ module Targets = Actions.Run (nunitConsole, ".", recArgs) "Recorder NUnit failed" - let rec2Args = - [ "--noheader" - "--work=." - "--result=./_Reports/Recorder2UnitTestReport.xml" - Path.getFullName - "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net20/AltCover.Recorder.Tests.dll" ] - - Actions.Run (nunitConsole, ".", rec2Args) "Recorder NUnit failed" - with x -> printfn "%A" x reraise ()) @@ -2365,19 +2347,6 @@ module Targets = [ Path.getFullName "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net472/__RecorderTestWithAltCoverRunner/AltCover.Recorder.Tests.dll" ], baseFilter, - shadowkeyfile) - (Path.getFullName "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net20", - "./__RecorderTest2WithAltCoverRunner", - "RecorderTest2WithAltCoverRunner.xml", - "./_Reports/RecorderTest2WithAltCoverRunnerReport.xml", - [ Path.getFullName - "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net20/__RecorderTest2WithAltCoverRunner/AltCover.Recorder.Tests.dll" ], - baseFilter - >> (fun p -> - { p with - AttributeFilter = - [ TypeSafe.Raw "EntryPoint" ] - |> p.AttributeFilter.Join }), shadowkeyfile) ] tests diff --git a/rework failure list.txt b/rework failure list.txt new file mode 100644 index 00000000..aaa78c6a --- /dev/null +++ b/rework failure list.txt @@ -0,0 +1,91 @@ +FSharpTypesDotNetCollecter 00:00:11.3171337 ( Bad visit list ["0"; "0"; "0"; "1"; "1"; "0"; "0"; "0"; "1"; "1"; "1"; "1"; "1"; "0"; "0"; "0"; + "0"; "1"; "0"; "0"] +Assert.That(, ) + String lengths are both 39. Strings differ at index 2. + Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" + But was: "0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0" + -------------^ +) +FSharpTypesDotNetRunner 00:00:07.0583183 ( Bad visit list ["0"; "0"; "0"; "1"; "1"; "0"; "0"; "0"; "1"; "1"; "1"; "1"; "1"; "0"; "0"; "0"; + "0"; "1"; "0"; "0"] +Assert.That(, ) + String lengths are both 39. Strings differ at index 2. + Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" + But was: "0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0" + -------------^ +) +ReplayJsonReporting 00:00:05.1513692 ( Bad tracked visit list ["2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"] +Assert.That(, ) + String lengths are both 25. Strings differ at index 0. + Expected: "1 1 1 1 1 1 1 1 2 2 2 2 2" + But was: "2 2 2 2 2 2 2 2 2 2 2 2 2" + -----------^ +) +Unhandled exception. Fake.Core.BuildFailedException: Target 'ReplayReleaseXUnitFSharpTypesDotNetFullRunner' failed. + ---> System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.) + ---> System.NullReferenceException: Object reference not set to an instance of an object. + at AltCover.Actions.Pipe #1 stage #1 at line 674@674.Invoke(XElement m) in C:\Users\email\Documents\Github\altcover\Build\actions.fs:line 675 +DotnetGlobalIntegration +Issue114 +(Issue20 - Net6.0 EOL) +ReplayIssue72 00:00:12.0468419 ( + +(found, "first") = (["1"; "4"; "3"; "1"; "2"; "1"; "1"; "1"; "5"; "5"], "first") +(["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"], "first") = (["1"; "4"; "3"; "1"; "2"; "1"; "1"; "1"; "5"; "5"], "first") +false +) +ReplayDotnetTestIntegration 00:00:18.0391875 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; + "0"; "0"; "0"; "0"] in C:\Users\email\Documents\Github\altcover\_DotnetTest\coverage.net8.0.xml +Assert.That(, ) + String lengths are both 39. Strings differ at index 2. + Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" + But was: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" + -------------^ +Cake2Test - System.IO.IOException: The process cannot access the file 'C:\Users\email\Documents\Github\.nuget\packages\microsoft.testplatform.testhost\17.9.0\build\netcoreapp3.1\x64\testhost.dll' because it is being used by another process. + at System.IO.FileSystem.CopyFile(String sourceFullPath, String destFullPath, Boolean overwrite) + at .$Tasks.Execute@528.Invoke(String x) in /_//AltCover.Engine/Tasks.fs + :line 528 + + +ReplayApiUse 00:00:16.4179594 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; + "0"; "0"; "0"; "0"] in C:\Users\email\Documents\Github\altcover\_ApiUse\_DotnetTest\coverage.net8.0.xml +Assert.That(, ) + String lengths are both 39. Strings differ at index 2. + Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" + But was: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" + -------------^ +) +ReplayMSBuildTest 00:00:09.6313753 ( Assert.That(, ) + Expected: equivalent to < "", "", "", "", "", "", "", "", "", ""... > + But was: < "", "", "", "", "", "", "", "", "", ""... > + Missing (1): < "" > + Extra (1): < "" > +) +ReplayReleaseXUnitFSharpTypesShowVisualized 00:00:07.0424524 ( expect [ 0; 1; 2 ] +Assert.That(, ) + Expected and actual are both +) +ReplayReleaseFSharpTypesDotNetRunner 00:00:04.2638439 ( Bad visit list ["0"; "0"; "0"; "1"; "1"; "0"; "0"; "0"; "1"; "1"; "1"; "1"; "1"; "0"; "0"; "0"; + "0"; "1"; "0"; "0"] +Assert.That(, ) + String lengths are both 39. Strings differ at index 2. + Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" + But was: "0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0" + -------------^ +) +ReplayReleaseXUnitFSharpTypesDotNetRunner 00:00:04.5455546 ( Bad visit list ["0"; "0"; "0"; "1"; "1"; "0"; "0"; "0"; "1"; "1"; "1"; "1"; "1"; "0"; "0"; "0"; + "0"; "1"; "0"; "0"] +Assert.That(, ) + String lengths are both 39. Strings differ at index 2. + Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" + But was: "0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0" + -------------^ +) +WindowsPowerShell [-] Invoke-Altcover.instruments and collects 4.56s (4.55s|5ms) + Expected strings to be the same, but they were different. + String lengths are both 39. + Strings differ at index 2. + Expected: '0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1' + But was: '0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0' + --^ + at $result | Should -Be "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1", C:\Users\email\Documents\Github\altcover\Build\Pester.Tests.ps1:76 \ No newline at end of file From 270f0593ad362d48e6cffc2f35964992549d7d05 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 19 Jul 2024 18:21:28 +0100 Subject: [PATCH 77/91] F# fields that are actually properties become C# fields --- AltCover.DataCollector/DataCollector.cs | 7 +------ AltCover.Monitor/Monitor.cs | 8 ++++---- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/AltCover.DataCollector/DataCollector.cs b/AltCover.DataCollector/DataCollector.cs index cf0841db..09bfa0e6 100644 --- a/AltCover.DataCollector/DataCollector.cs +++ b/AltCover.DataCollector/DataCollector.cs @@ -67,7 +67,7 @@ private void Supervise() RecorderInstance.ToList().ForEach( i => { - var supervision = i.GetProperty("supervision", + var supervision = i.GetField("supervision", BindingFlags.Static | BindingFlags.NonPublic); if (supervision == null) { @@ -98,11 +98,6 @@ public void TestCaseEnd(TestCaseEndArgs testCaseEndArgs) testCaseEndArgs?.DataCollectionContext?.TestCase?.FullyQualifiedName, testCaseEndArgs?.TestOutcome); - //Console.Error.WriteLine( - // "Console.Error.WriteLine TestCaseEnd {0} => {1}", - // testCaseEndArgs.DataCollectionContext.TestCase.FullyQualifiedName, - // testCaseEndArgs.TestOutcome); - if (EqtTrace.IsInfoEnabled) { EqtTrace.Info("TestCaseEnd {0}", testCaseEndArgs); diff --git a/AltCover.Monitor/Monitor.cs b/AltCover.Monitor/Monitor.cs index 47a81563..bbf4bc0e 100644 --- a/AltCover.Monitor/Monitor.cs +++ b/AltCover.Monitor/Monitor.cs @@ -222,16 +222,16 @@ public static bool TryGetVisitTotals(out PointCount totals) var found = false; foreach (var t in counter) { - var temp = (Int64)t.GetProperty("branchVisits", + var temp = (Int64)t.GetField("branchVisits", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | - System.Reflection.BindingFlags.Static).GetValue(null, Type.EmptyTypes); + System.Reflection.BindingFlags.Static).GetValue(null); totals.Branch = (int)temp; - temp = (Int64)t.GetProperty("totalVisits", + temp = (Int64)t.GetField("totalVisits", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | - System.Reflection.BindingFlags.Static).GetValue(null, Type.EmptyTypes); + System.Reflection.BindingFlags.Static).GetValue(null); totals.Code = (int)temp - totals.Branch; found = true; From ad049d228dba48b157cc573de7f009a826721b0a Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Fri, 19 Jul 2024 21:09:03 +0100 Subject: [PATCH 78/91] Simplifications, and data to make a new unit test --- AltCover.Recorder/Base.cs | 102 ++++++++++++++++++++++------------ AltCover.Recorder/Recorder.cs | 2 +- rework failure list.txt | 89 +++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 36 deletions(-) diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index 6d446591..db0d878b 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -141,7 +141,7 @@ public override string ToString() public override bool Equals(object obj) { - return obj is Null n; + return obj is Null; } public override int GetHashCode() @@ -559,7 +559,7 @@ Stream outputFile var startTimeNode = root.GetAttributeNode("startTime"); - if ((format == ReportFormat.NCover) && !Object.ReferenceEquals(startTimeNode, null)) + if ((format == ReportFormat.NCover) && startTimeNode is object) { var startTimeAttr = startTimeNode.Value; var measureTimeAttr = root.GetAttribute("measureTime"); @@ -594,59 +594,86 @@ Stream outputFile ); } + //let moduleNodes = + // selectNodes coverageDocument m var moduleNodes = SelectNodes(coverageDocument, xmlformat.m); + //moduleNodes + //|> Seq.cast < XmlElement > foreach (var el in moduleNodes) { + //|> Seq.map(fun el->el.GetAttribute(i), el) var k = el.GetAttribute(xmlformat.i); + + // |> Seq.filter(fun(k, _)->counts.ContainsKey k) if (!counts.ContainsKey(k)) continue; + // let moduleHits = counts.[k] var moduleHits = counts[k]; // Don't do this in one leap like -- // affectedModule.Descendants(XName.Get("seqpnt")) // Get the methods, then flip their // contents before concatenating + // let nn = selectNodes affectedModule m' var nn = SelectNodes(el, xmlformat.m2); + + //nn + //|> Seq.cast < XmlElement > + //|> Seq.collect(fun(method: XmlElement)-> + var nodes = new List>(); foreach (var method in nn) { - var nodes = new List>(); + // s + //|> Seq.collect(fun(name, flag)-> foreach (var nameflag in xmlformat.s) { + // let nodes = selectNodes method name + + // nodes + // |> Seq.cast + var nodes1 = new List>(); foreach (var node in SelectNodes(method, nameflag.Key)) { - nodes.Insert(0, new KeyValuePair(node, nameflag.Value)); + // |> Seq.map(fun x-> (x, flag)) + nodes1.Insert(0, new KeyValuePair(node, nameflag.Value)); } + + nodes1.Reverse(); + // |> Seq.toList + // |> List.rev)) + + nodes.AddRange(nodes); } + } - int counter = -1; - foreach (var node in nodes) + int counter = -1; + foreach (var node in nodes) + { + ++counter; + var index = counter; + if ((format & ReportFormat.TrackMask) == + ReportFormat.OpenCover) { - ++counter; - var index = counter; - if ((format & ReportFormat.TrackMask) == - ReportFormat.OpenCover) - { - index = FindIndexFromUspid(node.Value, node.Key.GetAttribute("uspid")); - } + index = FindIndexFromUspid(node.Value, node.Key.GetAttribute("uspid")); + } - if (moduleHits.ContainsKey(index)) - { - var pt = node.Key; - - Int64.TryParse( - pt.GetAttribute(xmlformat.v), - NumberStyles.Integer, - CultureInfo.InvariantCulture, - out var vc - ); - - // Treat -ve visit counts (an exemption added in analysis) as zero - var count = moduleHits[index]; - var visits = Math.Max(vc, 0) + count.Total; - pt.SetAttribute(xmlformat.v, visits.ToString(CultureInfo.InvariantCulture)); - pointProcess(pt, count.Tracks); - } + if (moduleHits.TryGetValue(index, out PointVisit value)) + { + var pt = node.Key; + + Int64.TryParse( + pt.GetAttribute(xmlformat.v), + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out var vc + ); + + // Treat -ve visit counts (an exemption added in analysis) as zero + var count = value; + var visits = Math.Max(vc, 0) + count.Total; + pt.SetAttribute(xmlformat.v, visits.ToString(CultureInfo.InvariantCulture)); + pointProcess(pt, count.Tracks); } } } @@ -658,7 +685,10 @@ out var vc outputFile.SetLength(0); if (own) - { WriteXDocument(coverageDocument, outputFile); } + + { + WriteXDocument(coverageDocument, outputFile); + } return flushStart; } @@ -684,6 +714,9 @@ Stream outputFile } // "Public" API + [SuppressMessage("Gendarme.Rules.Maintainability", + "AvoidUnnecessarySpecializationRule", + Justification = "No speculative generalization")] internal static void AddSingleVisit( Dictionary> counts, string moduleId, @@ -691,13 +724,12 @@ internal static void AddSingleVisit( Track context ) { - if (counts.ContainsKey(moduleId)) + if (counts.TryGetValue(moduleId, out Dictionary value)) { - var next = counts[moduleId]; + var next = value; I.EnsurePoint(next, hitPointId); var v = next[hitPointId]; - - if (context is Null n) + if (context is Null) { v.Step(); } else { v.Track(context); } } diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index ce21c695..f8b17f46 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -628,7 +628,7 @@ internal static bool TakeSample(Sampling strategy, string moduleId, int hitPoint if (strategy == Sampling.All) return true; - Sampled[] sampleds = null; + Sampled[] sampleds; if (context is Null) sampleds = new Sampled[] { new SimpleVisit(hitPointId) }; else if (context is Time t) diff --git a/rework failure list.txt b/rework failure list.txt index aaa78c6a..13a96048 100644 --- a/rework failure list.txt +++ b/rework failure list.txt @@ -6,6 +6,95 @@ Assert.That(, ) But was: "0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0" -------------^ ) + +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 5, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 1, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId -2147483648, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 4, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 2, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId -2147483646, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 3, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 13, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 12, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId -2147483643, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 11, track AltCover.Null + +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 18, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 16, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId -2147483640, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 17, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 16, track AltCover.Null +moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 19, track AltCover.Null + +hitpoint 5 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint 1 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint -2147483648 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint 4 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint 2 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint -2147483646 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint 3 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint 13 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint 12 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint -2147483643 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint 11 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint 18 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint 16 hits AltCover.PointVisit : Count = 2 Tracks = '' +hitpoint -2147483640 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint 17 hits AltCover.PointVisit : Count = 1 Tracks = '' +hitpoint 19 hits AltCover.PointVisit : Count = 1 Tracks = '' + +--------------------------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------------------------- + + + + FSharpTypesDotNetRunner 00:00:07.0583183 ( Bad visit list ["0"; "0"; "0"; "1"; "1"; "0"; "0"; "0"; "1"; "1"; "1"; "1"; "1"; "0"; "0"; "0"; "0"; "1"; "0"; "0"] Assert.That(, ) From a6bc71c501942fe4a4d251f6c19e3c9c8e55a83c Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 20 Jul 2024 15:06:49 +0100 Subject: [PATCH 79/91] Unit test made it simpler to find the first promlem --- .../AltCover.Recorder.Tests.fsproj | 4 +- AltCover.Recorder.Tests/Recorder.Tests.fs | 78 +++++++++++++++++-- AltCover.Recorder.Tests/Sample2NCoverage.xml | 46 +++++++++++ AltCover.Recorder/Base.cs | 10 +-- .../AltCover.Recorder2.Tests.fsproj | 1 + 5 files changed, 125 insertions(+), 14 deletions(-) create mode 100644 AltCover.Recorder.Tests/Sample2NCoverage.xml diff --git a/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj b/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj index ad49c9ee..8c73f001 100644 --- a/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj +++ b/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj @@ -32,9 +32,7 @@ - - - + diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index 89e19433..a5d9410a 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -41,12 +41,6 @@ module AltCoverTests = .GetManifestResourceNames() |> Seq.find (fun n -> n.EndsWith("SimpleCoverage.xml", StringComparison.Ordinal)) - let private updateReport a b = - Adapter.updateReport (a, ReportFormat.NCover, b, b) - |> ignore - - let private pointVisitInit a b = Adapter.init (a, b) - let resource2 = Assembly .GetExecutingAssembly() @@ -54,6 +48,18 @@ module AltCoverTests = |> Seq.find (fun n -> n.EndsWith("Sample1WithModifiedOpenCover.xml", StringComparison.Ordinal)) + let resource3 = + Assembly + .GetExecutingAssembly() + .GetManifestResourceNames() + |> Seq.find (fun n -> n.EndsWith("Sample2NCoverage.xml", StringComparison.Ordinal)) + + let private updateReport a b = + Adapter.updateReport (a, ReportFormat.NCover, b, b) + |> ignore + + let private pointVisitInit a b = Adapter.init (a, b) + [] let ShouldCoverTrivalClass () = let mark = InstrumentationAttribute() // Constructor has all the instrumented code @@ -1088,6 +1094,66 @@ module AltCoverTests = getMyMethodName "<=" + [] + let KnownModuleWithPayloadMakesExpectedComplexChange () = + getMyMethodName "=>" + + lock Instance.I.visits (fun () -> + Counter.measureTime <- + DateTime.ParseExact("2017-12-29T16:33:40.9564026+00:00", "o", null) + + use stream = + Assembly + .GetExecutingAssembly() + .GetManifestResourceStream(resource3) + + let size = int stream.Length + let buffer = Array.create size 0uy + Assert.That(stream.Read(buffer, 0, size), Is.EqualTo size) + use worker = new MemoryStream() + worker.Write(buffer, 0, size) + worker.Position <- 0L + let payload = Dictionary() + + payload.[5] <- pointVisitInit 1L [] + payload.[1] <- pointVisitInit 1L [] + payload.[-2147483648] <- pointVisitInit 1L [] + payload.[4] <- pointVisitInit 1L [] + payload.[2] <- pointVisitInit 1L [] + payload.[-2147483646] <- pointVisitInit 1L [] + payload.[3] <- pointVisitInit 1L [] + payload.[13] <- pointVisitInit 1L [] + payload.[12] <- pointVisitInit 1L [] + payload.[-2147483643] <- pointVisitInit 1L [] + payload.[11] <- pointVisitInit 1L [] + payload.[18] <- pointVisitInit 1L [] + payload.[16] <- pointVisitInit 2L [] + payload.[-2147483640] <- pointVisitInit 1L [] + payload.[17] <- pointVisitInit 1L [] + payload.[19] <- pointVisitInit 1L [] + + let item = + Dictionary>() + + item.Add("f7f80a77-e131-f5c7-da33-cd3b6036778a", payload) + updateReport item worker + worker.Position <- 0L + let after = XmlDocument() + after.Load worker + + let join (x: string seq) = String.Join(" ", x) + + Assert.That( + after.SelectNodes("//seqpnt") + |> Seq.cast + |> Seq.map (fun x -> x.GetAttribute("visitcount")) + |> join, + Is.EqualTo "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" + + )) + + getMyMethodName "<=" + [] let KnownModuleWithPayloadMakesExpectedChangeInOpenCover () = getMyMethodName "=>" diff --git a/AltCover.Recorder.Tests/Sample2NCoverage.xml b/AltCover.Recorder.Tests/Sample2NCoverage.xml new file mode 100644 index 00000000..5e7da433 --- /dev/null +++ b/AltCover.Recorder.Tests/Sample2NCoverage.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AltCover.Recorder/Base.cs b/AltCover.Recorder/Base.cs index db0d878b..881b5393 100644 --- a/AltCover.Recorder/Base.cs +++ b/AltCover.Recorder/Base.cs @@ -455,6 +455,7 @@ internal static void EnsurePoint(Dictionary counts, int hitPoin } #if RUNNER + [SuppressMessage("Gendarme.Rules.Performance", "AvoidUncalledPrivateCodeRule", Justification = "Internals Visible To")] @@ -489,6 +490,7 @@ Dictionary> t } return hitcount; } + #endif // TODO inline in release if possible @@ -636,14 +638,12 @@ Stream outputFile foreach (var node in SelectNodes(method, nameflag.Key)) { // |> Seq.map(fun x-> (x, flag)) + // |> Seq.toList + // |> List.rev)) nodes1.Insert(0, new KeyValuePair(node, nameflag.Value)); } - nodes1.Reverse(); - // |> Seq.toList - // |> List.rev)) - - nodes.AddRange(nodes); + nodes.AddRange(nodes1); } } diff --git a/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj b/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj index 967218ee..3d2b83ee 100644 --- a/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj +++ b/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj @@ -19,6 +19,7 @@ + AssemblyVersion.fs From aca5f85e6eb10f94b9dd4137b32bcacd76e62e91 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 20 Jul 2024 15:08:02 +0100 Subject: [PATCH 80/91] Tidy a bit --- Build/targets.fs | 7 +- rework failure list.txt | 151 +++++++++++----------------------------- 2 files changed, 41 insertions(+), 117 deletions(-) diff --git a/Build/targets.fs b/Build/targets.fs index b78a2935..86fd7dc2 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -5881,10 +5881,8 @@ module Targets = sprintf "Bad tracked method list %A" trackedFormat ) - //let trackedTimes = methods |> List.filter _.Value.TId.HasValue - // |> List.collect (fun m -> let first = m.Value.Entry |> List.iter (fun m -> let first = m.Value.Entry @@ -5903,10 +5901,7 @@ module Targets = test <@ from <= first @> test <@ first <= second @> test <@ second <= Actions.ticksNow () @>) - // [first; second]) - // Assert.That - // (x.ToString().Replace("\r\n", "\n"), - // Is.EqualTo <| tracked.Replace("\r\n", "\n"))) ??? + printfn "Tracked OK" let trackedVisits = diff --git a/rework failure list.txt b/rework failure list.txt index 13a96048..601e0d72 100644 --- a/rework failure list.txt +++ b/rework failure list.txt @@ -1,108 +1,3 @@ -FSharpTypesDotNetCollecter 00:00:11.3171337 ( Bad visit list ["0"; "0"; "0"; "1"; "1"; "0"; "0"; "0"; "1"; "1"; "1"; "1"; "1"; "0"; "0"; "0"; - "0"; "1"; "0"; "0"] -Assert.That(, ) - String lengths are both 39. Strings differ at index 2. - Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" - But was: "0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0" - -------------^ -) - -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 5, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 1, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId -2147483648, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 4, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 2, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId -2147483646, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 3, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 13, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 12, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId -2147483643, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 11, track AltCover.Null - -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 18, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 16, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId -2147483640, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 17, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 16, track AltCover.Null -moduleId f7f80a77-e131-f5c7-da33-cd3b6036778a, hitPointId 19, track AltCover.Null - -hitpoint 5 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint 1 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint -2147483648 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint 4 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint 2 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint -2147483646 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint 3 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint 13 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint 12 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint -2147483643 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint 11 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint 18 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint 16 hits AltCover.PointVisit : Count = 2 Tracks = '' -hitpoint -2147483640 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint 17 hits AltCover.PointVisit : Count = 1 Tracks = '' -hitpoint 19 hits AltCover.PointVisit : Count = 1 Tracks = '' - ---------------------------------------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------------------------- - - - - -FSharpTypesDotNetRunner 00:00:07.0583183 ( Bad visit list ["0"; "0"; "0"; "1"; "1"; "0"; "0"; "0"; "1"; "1"; "1"; "1"; "1"; "0"; "0"; "0"; - "0"; "1"; "0"; "0"] -Assert.That(, ) - String lengths are both 39. Strings differ at index 2. - Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" - But was: "0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0" - -------------^ -) ReplayJsonReporting 00:00:05.1513692 ( Bad tracked visit list ["2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"] Assert.That(, ) String lengths are both 25. Strings differ at index 0. @@ -110,26 +5,60 @@ Assert.That(, ) But was: "2 2 2 2 2 2 2 2 2 2 2 2 2" -----------^ ) -Unhandled exception. Fake.Core.BuildFailedException: Target 'ReplayReleaseXUnitFSharpTypesDotNetFullRunner' failed. - ---> System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.) +Unhandled exception. Fake.Core.BuildFailedException: Target 'JsonReporting' failed. + ---> System.AggregateException: One or more errors occurred. (The input sequence was empty. (Parameter 'source')) + ---> System.ArgumentException: The input sequence was empty. (Parameter 'source') + at Microsoft.FSharp.Collections.SeqModule.Head[T](IEnumerable`1 source) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 1693 + at AltCover.Targets.checkSample4Visits@5836.Invoke(Int64 from, String path) in C:\Users\email\Documents\Github\altcover\Build\targets.fs:line 5898 + at AltCover.Targets.JsonReporting() in C:\Users\email\Documents\Github\altcover\Build\targets.fs:line 59 + +ReleaseXUnitFSharpTypesDotNetFullRunner +DotnetGlobalIntegration +System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.) ---> System.NullReferenceException: Object reference not set to an instance of an object. at AltCover.Actions.Pipe #1 stage #1 at line 674@674.Invoke(XElement m) in C:\Users\email\Documents\Github\altcover\Build\actions.fs:line 675 -DotnetGlobalIntegration -Issue114 + (Issue20 - Net6.0 EOL) -ReplayIssue72 00:00:12.0468419 ( + +Issue72 00:00:11.7880238 ( (found, "first") = (["1"; "4"; "3"; "1"; "2"; "1"; "1"; "1"; "5"; "5"], "first") (["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"], "first") = (["1"; "4"; "3"; "1"; "2"; "1"; "1"; "1"; "5"; "5"], "first") false ) -ReplayDotnetTestIntegration 00:00:18.0391875 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; + +DotnetTestIntegration 00:00:17.9539171 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"] in C:\Users\email\Documents\Github\altcover\_DotnetTest\coverage.net8.0.xml Assert.That(, ) String lengths are both 39. Strings differ at index 2. Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" But was: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" -------------^ +) + at AltCover.Targets.DotnetTestIntegration() in C:\Users\email\Documents\Github\altcover\Build\targets.fs:line 6458 + + +ApiUse 00:00:00 (skipped) +MSBuildTest 00:00:00 (skipped) +ReleaseXUnitFSharpTypesShowVisualized 00:00:00 (skipped) +ReleaseFSharpTypesDotNetRunner 00:00:00 (skipped) +ReleaseDotNetWithFramework 00:00:00 (skipped) +ReleaseDotNetWithDotNet 00:00:00 (skipped) +ReleaseMonoWithDotNet 00:00:00 (skipped) +SimpleMonoReleaseTest 00:00:00 (skipped) +SimpleZipReleaseTest 00:00:00 (skipped) +SimpleReleaseTest 00:00:00 (skipped) +OpenCoverForPester 00:00:00 (skipped) +ReleaseXUnitFSharpTypesDotNetRunner 00:00:00 (skipped) +WindowsPowerShell 00:00:00 (skipped) +Pester 00:00:00 (skipped) +Deployment 00:00:00 (skipped) +UnitTestWithAltCoverCoreRunner 00:00:00 (skipped) +UnitTest 00:00:00 (skipped) +BulkReport 00:00:00 (skipped) +All 00:00:00 (skipped) +R + Cake2Test - System.IO.IOException: The process cannot access the file 'C:\Users\email\Documents\Github\.nuget\packages\microsoft.testplatform.testhost\17.9.0\build\netcoreapp3.1\x64\testhost.dll' because it is being used by another process. at System.IO.FileSystem.CopyFile(String sourceFullPath, String destFullPath, Boolean overwrite) at .$Tasks.Execute@528.Invoke(String x) in /_//AltCover.Engine/Tasks.fs From ad1c7afadbc0549ea4ce0581984d95091b137b9c Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 20 Jul 2024 15:16:58 +0100 Subject: [PATCH 81/91] net6.0 EOL mid-November --- RegressionTesting/issue20/xunit-tests/xunit-tests.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RegressionTesting/issue20/xunit-tests/xunit-tests.xml b/RegressionTesting/issue20/xunit-tests/xunit-tests.xml index 400fbdbe..e77e31f5 100644 --- a/RegressionTesting/issue20/xunit-tests/xunit-tests.xml +++ b/RegressionTesting/issue20/xunit-tests/xunit-tests.xml @@ -1,7 +1,7 @@ - net6.0 + net8.0 xunit_tests Major false From 471971c1f3f0b0bdd3cd5123af9ed5636649fcab Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 20 Jul 2024 16:12:04 +0100 Subject: [PATCH 82/91] Update state of play --- rework failure list.txt | 134 +++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 79 deletions(-) diff --git a/rework failure list.txt b/rework failure list.txt index 601e0d72..94762a61 100644 --- a/rework failure list.txt +++ b/rework failure list.txt @@ -1,33 +1,30 @@ -ReplayJsonReporting 00:00:05.1513692 ( Bad tracked visit list ["2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"; "2"] -Assert.That(, ) - String lengths are both 25. Strings differ at index 0. - Expected: "1 1 1 1 1 1 1 1 2 2 2 2 2" - But was: "2 2 2 2 2 2 2 2 2 2 2 2 2" - -----------^ -) -Unhandled exception. Fake.Core.BuildFailedException: Target 'JsonReporting' failed. - ---> System.AggregateException: One or more errors occurred. (The input sequence was empty. (Parameter 'source')) - ---> System.ArgumentException: The input sequence was empty. (Parameter 'source') - at Microsoft.FSharp.Collections.SeqModule.Head[T](IEnumerable`1 source) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 1693 - at AltCover.Targets.checkSample4Visits@5836.Invoke(Int64 from, String path) in C:\Users\email\Documents\Github\altcover\Build\targets.fs:line 5898 - at AltCover.Targets.JsonReporting() in C:\Users\email\Documents\Github\altcover\Build\targets.fs:line 59 +JsonReporting 00:00:05.4703791 (The input sequence was empty. (Parameter 'source')) +- Exit event not logged. -ReleaseXUnitFSharpTypesDotNetFullRunner -DotnetGlobalIntegration -System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.) - ---> System.NullReferenceException: Object reference not set to an instance of an object. - at AltCover.Actions.Pipe #1 stage #1 at line 674@674.Invoke(XElement m) in C:\Users\email\Documents\Github\altcover\Build\actions.fs:line 675 +ReplayReleaseXUnitFSharpTypesDotNetFullRunner 00:00:04.5343187 ( Assert.That(, ) + Expected: equivalent to < "", "", "", "", "", "", "", "", "", ""... > + But was: < "", "", "", "", "", "", "", "", "", ""... > + Missing (5): < "", "", "", "", "" > + Extra (5): < "", "", "", "", "" > +) +- tracked method IDs -(Issue20 - Net6.0 EOL) +ReplayDotnetGlobalIntegration 00:00:11.9794665 ( Assert.That(, ) + Expected: equivalent to < "", "", "", "", "", "", "", "", "", ""... > + But was: < "", "", "", "", "", "", "", "", "", ""... > + Missing (4): < "", "", "", "" > + Extra (4): < "", "", "", "" > +) +-- ditto -Issue72 00:00:11.7880238 ( +Issue72 00:00:08.1871717 ( (found, "first") = (["1"; "4"; "3"; "1"; "2"; "1"; "1"; "1"; "5"; "5"], "first") (["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"], "first") = (["1"; "4"; "3"; "1"; "2"; "1"; "1"; "1"; "5"; "5"], "first") false ) -DotnetTestIntegration 00:00:17.9539171 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; +DotnetTestIntegration 00:00:17.4145571 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"] in C:\Users\email\Documents\Github\altcover\_DotnetTest\coverage.net8.0.xml Assert.That(, ) String lengths are both 39. Strings differ at index 2. @@ -35,37 +32,26 @@ Assert.That(, ) But was: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" -------------^ ) - at AltCover.Targets.DotnetTestIntegration() in C:\Users\email\Documents\Github\altcover\Build\targets.fs:line 6458 -ApiUse 00:00:00 (skipped) -MSBuildTest 00:00:00 (skipped) -ReleaseXUnitFSharpTypesShowVisualized 00:00:00 (skipped) -ReleaseFSharpTypesDotNetRunner 00:00:00 (skipped) -ReleaseDotNetWithFramework 00:00:00 (skipped) -ReleaseDotNetWithDotNet 00:00:00 (skipped) -ReleaseMonoWithDotNet 00:00:00 (skipped) -SimpleMonoReleaseTest 00:00:00 (skipped) -SimpleZipReleaseTest 00:00:00 (skipped) -SimpleReleaseTest 00:00:00 (skipped) -OpenCoverForPester 00:00:00 (skipped) -ReleaseXUnitFSharpTypesDotNetRunner 00:00:00 (skipped) -WindowsPowerShell 00:00:00 (skipped) -Pester 00:00:00 (skipped) -Deployment 00:00:00 (skipped) -UnitTestWithAltCoverCoreRunner 00:00:00 (skipped) -UnitTest 00:00:00 (skipped) -BulkReport 00:00:00 (skipped) -All 00:00:00 (skipped) -R - -Cake2Test - System.IO.IOException: The process cannot access the file 'C:\Users\email\Documents\Github\.nuget\packages\microsoft.testplatform.testhost\17.9.0\build\netcoreapp3.1\x64\testhost.dll' because it is being used by another process. +Cake2Test 00:00:43.1579842 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; + "0"; "0"; "0"; "0"] in C:\Users\email\Documents\Github\altcover\_Cake\_DotnetTest\coverage.build.cake.--version 2.0.0.net8.0.xml +Assert.That(, ) + String lengths are both 39. Strings differ at index 2. + Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" + But was: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" + -------------^ +) System.IO.IOException: The process cannot access the file 'C:\Users\email\Documents\Github\.nuget\packa + ges\microsoft.testplatform.testhost\17.9.0\build\netcoreapp3.1\x64\testhost.exe' because it is being us + ed by another process. at System.IO.FileSystem.CopyFile(String sourceFullPath, String destFullPath, Boolean overwrite) at .$Tasks.Execute@528.Invoke(String x) in /_//AltCover.Engine/Tasks.fs :line 528 + at AltCover.CommandLine.I.doRetry[a,b](FSharpFunc`2 action, FSharpFunc`2 log, Int32 limit, Int32 res + t, Int32 depth, a f) in /_//AltCover.Engine/CommandLine.fs:line 215 -ReplayApiUse 00:00:16.4179594 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; +ApiUse 00:00:15.8093949 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"] in C:\Users\email\Documents\Github\altcover\_ApiUse\_DotnetTest\coverage.net8.0.xml Assert.That(, ) String lengths are both 39. Strings differ at index 2. @@ -73,37 +59,27 @@ Assert.That(, ) But was: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" -------------^ ) -ReplayMSBuildTest 00:00:09.6313753 ( Assert.That(, ) - Expected: equivalent to < "", "", "", "", "", "", "", "", "", ""... > - But was: < "", "", "", "", "", "", "", "", "", ""... > - Missing (1): < "" > - Extra (1): < "" > -) -ReplayReleaseXUnitFSharpTypesShowVisualized 00:00:07.0424524 ( expect [ 0; 1; 2 ] -Assert.That(, ) - Expected and actual are both -) -ReplayReleaseFSharpTypesDotNetRunner 00:00:04.2638439 ( Bad visit list ["0"; "0"; "0"; "1"; "1"; "0"; "0"; "0"; "1"; "1"; "1"; "1"; "1"; "0"; "0"; "0"; - "0"; "1"; "0"; "0"] -Assert.That(, ) - String lengths are both 39. Strings differ at index 2. - Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" - But was: "0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0" - -------------^ -) -ReplayReleaseXUnitFSharpTypesDotNetRunner 00:00:04.5455546 ( Bad visit list ["0"; "0"; "0"; "1"; "1"; "0"; "0"; "0"; "1"; "1"; "1"; "1"; "1"; "0"; "0"; "0"; - "0"; "1"; "0"; "0"] -Assert.That(, ) - String lengths are both 39. Strings differ at index 2. - Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" - But was: "0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0" - -------------^ -) -WindowsPowerShell [-] Invoke-Altcover.instruments and collects 4.56s (4.55s|5ms) - Expected strings to be the same, but they were different. - String lengths are both 39. - Strings differ at index 2. - Expected: '0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1' - But was: '0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0' - --^ - at $result | Should -Be "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1", C:\Users\email\Documents\Github\altcover\Build\Pester.Tests.ps1:76 \ No newline at end of file + +yMSBuildTest 00:00:08.6849914 (Object reference not set to an instance of an object.) + at AltCover.Actions.Pipe #1 stage #1 at line 674@674.Invoke(XElement m) in C:\Users\email\Documents\Github\altcover\Build\actions.fs:line 675 + at AltCover.Actions.Check4Visits@670-3.Invoke(XElement x) in C:\Users\email\Documents\Github\altcover\Build\actions.fs:line 690 + at AltCover.Actions.Check4Visits(String path, Int64 before, XDocument coverageDocument) in C:\Users\email\Documents\Github\altcover\Build\actions.fs:line 670 + + +WindowsPowerShell +missing methods +Void AltCover.LCov.convertReport +XDocument AltCover.Cobertura.convertReport +Void AltCover.CoverageParameters.set_theReportFormat +Void AltCover.PostProcess.action +String AltCover.Json.xmlToJson + +Pester - ditto + +UnitTestWithAltCoverCoreRunner + Failed AltCoverMonitorTests.MonitorTests.ShouldRecordPointTotals [417 ms] + Error Message: + Object reference not set to an instance of an object. + Stack Trace: + at AltCover.Local.Monitor.TryGetPointTotals(PointCount& totals) in C:\Users\email\Documents\Github\altcover\AltCover.Monitor\Monitor.cs:line 161 + var xml = i.GetProperty("ReportFile").GetValue(null, Type.EmptyTypes).ToString(); From 20fd71cfc91a55fd9b0af5f069a21e585a99566c Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 20 Jul 2024 17:39:37 +0100 Subject: [PATCH 83/91] Remember to keep the call tracker [ThreadStatic] in net20 mode --- AltCover.Recorder/Recorder.cs | 6 ++++++ rework failure list.txt | 37 ++--------------------------------- 2 files changed, 8 insertions(+), 35 deletions(-) diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index f8b17f46..97c1e90a 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -320,8 +320,14 @@ internal static Dictionary> MakeSamples() // class needed for "[ThreadStatic] static val mutable" private sealed class AsyncLocal { + [ThreadStatic] private static T item; + static AsyncLocal() + { + item = default(T); + } + public T Value { [SuppressMessage("Gendarme.Rules.Correctness", diff --git a/rework failure list.txt b/rework failure list.txt index 94762a61..66d35c53 100644 --- a/rework failure list.txt +++ b/rework failure list.txt @@ -1,22 +1,3 @@ -JsonReporting 00:00:05.4703791 (The input sequence was empty. (Parameter 'source')) -- Exit event not logged. - -ReplayReleaseXUnitFSharpTypesDotNetFullRunner 00:00:04.5343187 ( Assert.That(, ) - Expected: equivalent to < "", "", "", "", "", "", "", "", "", ""... > - But was: < "", "", "", "", "", "", "", "", "", ""... > - Missing (5): < "", "", "", "", "" > - Extra (5): < "", "", "", "", "" > -) -- tracked method IDs - -ReplayDotnetGlobalIntegration 00:00:11.9794665 ( Assert.That(, ) - Expected: equivalent to < "", "", "", "", "", "", "", "", "", ""... > - But was: < "", "", "", "", "", "", "", "", "", ""... > - Missing (4): < "", "", "", "" > - Extra (4): < "", "", "", "" > -) --- ditto - Issue72 00:00:08.1871717 ( (found, "first") = (["1"; "4"; "3"; "1"; "2"; "1"; "1"; "1"; "5"; "5"], "first") @@ -33,7 +14,6 @@ Assert.That(, ) -------------^ ) - Cake2Test 00:00:43.1579842 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"] in C:\Users\email\Documents\Github\altcover\_Cake\_DotnetTest\coverage.build.cake.--version 2.0.0.net8.0.xml Assert.That(, ) @@ -41,16 +21,9 @@ Assert.That(, ) Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" But was: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" -------------^ -) System.IO.IOException: The process cannot access the file 'C:\Users\email\Documents\Github\.nuget\packa - ges\microsoft.testplatform.testhost\17.9.0\build\netcoreapp3.1\x64\testhost.exe' because it is being us - ed by another process. - at System.IO.FileSystem.CopyFile(String sourceFullPath, String destFullPath, Boolean overwrite) - at .$Tasks.Execute@528.Invoke(String x) in /_//AltCover.Engine/Tasks.fs - :line 528 - at AltCover.CommandLine.I.doRetry[a,b](FSharpFunc`2 action, FSharpFunc`2 log, Int32 limit, Int32 res - t, Int32 depth, a f) in /_//AltCover.Engine/CommandLine.fs:line 215 - +) + ApiUse 00:00:15.8093949 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"] in C:\Users\email\Documents\Github\altcover\_ApiUse\_DotnetTest\coverage.net8.0.xml Assert.That(, ) @@ -60,12 +33,6 @@ Assert.That(, ) -------------^ ) -yMSBuildTest 00:00:08.6849914 (Object reference not set to an instance of an object.) - at AltCover.Actions.Pipe #1 stage #1 at line 674@674.Invoke(XElement m) in C:\Users\email\Documents\Github\altcover\Build\actions.fs:line 675 - at AltCover.Actions.Check4Visits@670-3.Invoke(XElement x) in C:\Users\email\Documents\Github\altcover\Build\actions.fs:line 690 - at AltCover.Actions.Check4Visits(String path, Int64 before, XDocument coverageDocument) in C:\Users\email\Documents\Github\altcover\Build\actions.fs:line 670 - - WindowsPowerShell missing methods Void AltCover.LCov.convertReport From b2cab65d51453c2cf83283560765d392356d762d Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sat, 20 Jul 2024 21:34:17 +0100 Subject: [PATCH 84/91] Make public some APIs that had been auto-internalized. Two more glitches to fix --- AltCover.Recorder/Recorder.cs | 10 +++--- rework failure list.txt | 64 +++++++++++------------------------ 2 files changed, 25 insertions(+), 49 deletions(-) diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index 97c1e90a..f8c8c0a9 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -26,13 +26,13 @@ public static class Instance /// Gets the location of coverage xml file /// This property's IL code is modified to store the actual file location /// - internal static string ReportFile + public static string ReportFile { [MethodImpl(MethodImplOptions.NoInlining)] get { return "Coverage.Default.xml"; } } - internal static string ReportFilePath + public static string ReportFilePath { get { @@ -53,7 +53,7 @@ internal static string CanonicalPath(string path) /// Gets whether to defer output until process exit /// This property's IL code is modified to store the actual value /// - internal static bool Defer + public static bool Defer { [MethodImpl(MethodImplOptions.NoInlining)] get { return false; } @@ -101,7 +101,7 @@ internal static Sampling Sample /// Gets the unique token for this Instance /// This property's IL code is modified to store a GUID-based token /// - internal static string Token + public static string Token { [MethodImpl(MethodImplOptions.NoInlining)] get { return "AltCover"; } @@ -892,7 +892,7 @@ public static void Pop() [SuppressMessage("Gendarme.Rules.Performance", "AvoidUncalledPrivateCodeRule", Justification = "Internals Visible To")] - internal static void FlushFinish() + public static void FlushFinish() { I.FlushAll(Close.ProcessExit); } diff --git a/rework failure list.txt b/rework failure list.txt index 66d35c53..7ecc9b04 100644 --- a/rework failure list.txt +++ b/rework failure list.txt @@ -1,39 +1,4 @@ -Issue72 00:00:08.1871717 ( - -(found, "first") = (["1"; "4"; "3"; "1"; "2"; "1"; "1"; "1"; "5"; "5"], "first") -(["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"], "first") = (["1"; "4"; "3"; "1"; "2"; "1"; "1"; "1"; "5"; "5"], "first") -false -) - -DotnetTestIntegration 00:00:17.4145571 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; - "0"; "0"; "0"; "0"] in C:\Users\email\Documents\Github\altcover\_DotnetTest\coverage.net8.0.xml -Assert.That(, ) - String lengths are both 39. Strings differ at index 2. - Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" - But was: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" - -------------^ -) - -Cake2Test 00:00:43.1579842 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; - "0"; "0"; "0"; "0"] in C:\Users\email\Documents\Github\altcover\_Cake\_DotnetTest\coverage.build.cake.--version 2.0.0.net8.0.xml -Assert.That(, ) - String lengths are both 39. Strings differ at index 2. - Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" - But was: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" - -------------^ -) - - -ApiUse 00:00:15.8093949 ( Bad visit list ["0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; - "0"; "0"; "0"; "0"] in C:\Users\email\Documents\Github\altcover\_ApiUse\_DotnetTest\coverage.net8.0.xml -Assert.That(, ) - String lengths are both 39. Strings differ at index 2. - Expected: "0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 2 1 1 1" - But was: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" - -------------^ -) - -WindowsPowerShell +WindowsPowerShell, Pester missing methods Void AltCover.LCov.convertReport XDocument AltCover.Cobertura.convertReport @@ -41,12 +6,23 @@ Void AltCover.CoverageParameters.set_theReportFormat Void AltCover.PostProcess.action String AltCover.Json.xmlToJson -Pester - ditto - UnitTestWithAltCoverCoreRunner - Failed AltCoverMonitorTests.MonitorTests.ShouldRecordPointTotals [417 ms] - Error Message: - Object reference not set to an instance of an object. - Stack Trace: - at AltCover.Local.Monitor.TryGetPointTotals(PointCount& totals) in C:\Users\email\Documents\Github\altcover\AltCover.Monitor\Monitor.cs:line 161 - var xml = i.GetProperty("ReportFile").GetValue(null, Type.EmptyTypes).ToString(); + AltCover.Recorder -> C:\Users\email\Documents\Github\altcover\_Binaries\UnitTestWithCoreRunner_AltCover + .Recorder\Debug+AnyCPU\net46\AltCover.Recorder.dll +C:\Program Files\dotnet\sdk\8.0.303\FSharp\Microsoft.FSharp.Targets(332,9): error MSB6004: The specified +task executable location "C:\Program Files\dotnet\sdk\8.0.303\FSharp\fsc.exe" is invalid. [C:\Users\email +\Documents\Github\altcover\__AltCover.Recorder.Tests\AltCover.Recorder.Tests.fsproj::TargetFramework=net4 +72] +C:\Program Files\dotnet\sdk\8.0.303\FSharp\Microsoft.FSharp.Targets(332,9): error MSB6004: The specified +task executable location "C:\Program Files\dotnet\sdk\8.0.303\FSharp\fsc.exe" is invalid. [C:\Users\email +\Documents\Github\altcover\__AltCover.Recorder.Tests\AltCover.Recorder.Tests.fsproj::TargetFramework=net8 +.0] +Finished (Failed) 'ReplayUnitTestWithAltCoverCoreRunner' in 00:01:55.4040158 + + +Pester 00:00:00 (skipped) +Deployment 00:00:00 (skipped) +UnitTestWithAltCoverCoreRunner 00:00:00 (skipped) +UnitTest 00:00:00 (skipped) +BulkReport 00:00:00 (skipped) +All 00:00:00 (skipped) From 38df3af5cd5f904d716940474dba9d553b1c54cf Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sun, 21 Jul 2024 14:00:08 +0100 Subject: [PATCH 85/91] Tidy up some --- AltCover.Recorder/Recorder.cs | 2 +- Build/targets.fs | 90 ++--------------------------------- 2 files changed, 6 insertions(+), 86 deletions(-) diff --git a/AltCover.Recorder/Recorder.cs b/AltCover.Recorder/Recorder.cs index f8c8c0a9..d7c35a4d 100644 --- a/AltCover.Recorder/Recorder.cs +++ b/AltCover.Recorder/Recorder.cs @@ -325,7 +325,7 @@ private sealed class AsyncLocal static AsyncLocal() { - item = default(T); + item = default; } public T Value diff --git a/Build/targets.fs b/Build/targets.fs index 86fd7dc2..4af96453 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -1949,9 +1949,6 @@ module Targets = let recorder4Files = !!(@"_Binaries/*Tests/Debug+AnyCPU/net472/*Recorder.Tests.dll") - let recorderFiles = - !!(@"_Binaries/*Tests/Debug+AnyCPU/net20/AltCover*Test*.dll") - let visualizerFiles = !!(@"_Binaries/AltCover.Visualizer.Tests/Debug+AnyCPU/net472/AltCover.Test*.dll") @@ -2006,24 +2003,6 @@ module Targets = (String.Join(" ", testFiles) + " --result=./_Reports/UnitTestWithOpenCoverReport.xml") - OpenCover.run - (fun p -> - { p with - WorkingDir = "." - ExePath = openCoverConsole - TestRunnerExePath = nunitConsole // OK, not on Linux - Filter = - "+[AltCover.Recorder]* +[AltCover.Recorder.Tests]* -[*]ICSharpCode.* -[*]System.* -[AltCover.*]*StartupCode*SolutionRoot" - MergeByHash = true - ReturnTargetCode = - Fake.DotNet.Testing.OpenCover.ReturnTargetCodeType.Yes - OptionalArguments = - "-excludebyattribute:*ExcludeFromCodeCoverageAttribute;*ProgIdAttribute" - Register = OpenCover.RegisterType.RegisterUser // Path64 doesn't work on my machine - Output = scoverage }) - (String.Join(" ", recorderFiles) - + " --result=./_Reports/RecorderTestWithOpenCoverReport.xml") - OpenCover.run (fun p -> { p with @@ -2128,7 +2107,7 @@ module Targets = OutputDirectories = [| "./__UnitTestWithAltCover" weakDir - @@ "__ValidateGendarmeEmulationWithAltCover" + @@ "__VGEWithAltCover" recorder4Dir @@ "__RecorderTestWithAltCover" apiDir @@ "__ApiTestWithAltCover" (*visDir @@ "__VisualizerTestWithAltCover"; monitorDir @@ "__MonitorTestWithAltCover"*) |] @@ -2166,7 +2145,7 @@ module Targets = Path.getFullName "_Binaries/AltCover.Api.Tests/Debug+AnyCPU/net472/__ApiTestWithAltCover/AltCover.Api.Tests.dll" Path.getFullName - "_Binaries/AltCover.ValidateGendarmeEmulation/Debug+AnyCPU/net472/__ValidateGendarmeEmulationWithAltCover/AltCover.ValidateGendarmeEmulation.dll" + "_Binaries/AltCover.ValidateGendarmeEmulation/Debug+AnyCPU/net472/__VGEWithAltCover/AltCover.ValidateGendarmeEmulation.dll" //Path.getFullName "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net472/__RecorderTestWithAltCover/AltCover.Recorder.Tests.dll" Path.getFullName "_Binaries/AltCover.Tests/Debug+AnyCPU/net472/__UnitTestWithAltCover/Sample2.dll" ] @@ -2176,52 +2155,6 @@ module Targets = printfn "UnitTestWithAltCover caught %A" x reraise () - printfn "Instrument the net20 Recorder tests" - - let recorderDir = - Path.getFullName "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net20" - - let recorderReport = - reports @@ "RecorderTestWithAltCover.xml" - - let prep = - AltCover.PrepareOptions.Primitive( - { Primitive.PrepareOptions.Create() with - Report = recorderReport - OutputDirectories = [| "./__RecorderTestWithAltCover" |] - StrongNameKey = shadowkeyfile - ReportFormat = "NCover" - InPlace = false - Save = false } - |> AltCoverFilter - ) - |> AltCoverCommand.Prepare - - { AltCoverCommand.Options.Create prep with - ToolPath = altcover - ToolType = frameworkAltcover - WorkingDirectory = recorderDir } - |> AltCoverCommand.run - - printfn "Execute the net20 Recorder tests" - - // !!("_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net20/__RecorderTestWithAltCover/Alt*.Test*.dll") - // |> NUnitRetry - // (fun p -> - // { p with - // ToolPath = nunitConsole - // WorkingDir = "." }) - // "./_Reports/RecorderTestWithAltCoverReport.xml" - - let recArgs = - [ "--noheader" - "--work=." - "--result=./_Reports/RecorderTestWithAltCoverReport.xml" - Path.getFullName - "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net20/__RecorderTestWithAltCover/AltCover.Recorder.Tests.dll" ] - - Actions.Run (nunitConsole, ".", recArgs) "Recorder net20 NUnit failed" - printfn "Instrument the net472 Recorder tests" let recorder472Dir = @@ -2269,7 +2202,6 @@ module Targets = ReportGenerator.ReportType.XmlSummary ] TargetDir = "_Reports/_UnitTestWithAltCover" }) [ altReport - recorderReport recorder472Report ] uncovered @"_Reports/_UnitTestWithAltCover/Summary.xml" @@ -2332,11 +2264,11 @@ module Targets = keyfile) (Path.getFullName "_Binaries/AltCover.ValidateGendarmeEmulation/Debug+AnyCPU/net472", - "./__ValidateGendarmeEmulationWithAltCoverRunner", + "./__VGEWithAltCoverRunner", "ValidateGendarmeEmulationWithAltCoverRunner.xml", "./_Reports/ValidateGendarmeEmulationWithAltCoverRunnerReport.xml", [ Path.getFullName - "_Binaries/AltCover.ValidateGendarmeEmulation/Debug+AnyCPU/net472/__ValidateGendarmeEmulationWithAltCoverRunner/AltCover.ValidateGendarmeEmulation.dll" ], + "_Binaries/AltCover.ValidateGendarmeEmulation/Debug+AnyCPU/net472/__VGEWithAltCoverRunner/AltCover.ValidateGendarmeEmulation.dll" ], // only use // (* >> (fun x -> { x with AssemblyExcludeFilter = TypeSafe.Filters [] }) *), AltCoverFilterXTypeSafe, keyfile) @@ -2721,23 +2653,11 @@ module Targets = AltCover.CollectOptions.Primitive <| Primitive.CollectOptions.Create() - if proj.Contains("Recorder") then - doMSBuild - (withDebug - >> fun p -> - { p with - Properties = - ("AltCoverTag", "UnitTestWithCoreRunner_") - :: p.Properties - Verbosity = Some MSBuildVerbosity.Minimal }) - MSBuildPath - newproj - DotNet.test (fun to' -> { to'.WithCommon(withWorkingDirectoryVM testdir) with Framework = Some "net8.0" - NoBuild = proj.Contains("Recorder") } + NoBuild = false } .WithAltCoverOptions prep coll From b5fafb3316144cea067cb1d617bbd3bedb23a0e4 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sun, 21 Jul 2024 15:25:29 +0100 Subject: [PATCH 86/91] Streamline base altcover self-test --- Build/targets.fs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Build/targets.fs b/Build/targets.fs index 4af96453..40deb939 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -2106,8 +2106,7 @@ module Targets = apiDir (*; visDir ; monitorDir*) |] OutputDirectories = [| "./__UnitTestWithAltCover" - weakDir - @@ "__VGEWithAltCover" + weakDir @@ "__VGEWithAltCover" recorder4Dir @@ "__RecorderTestWithAltCover" apiDir @@ "__ApiTestWithAltCover" (*visDir @@ "__VisualizerTestWithAltCover"; monitorDir @@ "__MonitorTestWithAltCover"*) |] @@ -2146,7 +2145,8 @@ module Targets = "_Binaries/AltCover.Api.Tests/Debug+AnyCPU/net472/__ApiTestWithAltCover/AltCover.Api.Tests.dll" Path.getFullName "_Binaries/AltCover.ValidateGendarmeEmulation/Debug+AnyCPU/net472/__VGEWithAltCover/AltCover.ValidateGendarmeEmulation.dll" - //Path.getFullName "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net472/__RecorderTestWithAltCover/AltCover.Recorder.Tests.dll" + Path.getFullName + "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net472/__RecorderTestWithAltCover/AltCover.Recorder.Tests.dll" Path.getFullName "_Binaries/AltCover.Tests/Debug+AnyCPU/net472/__UnitTestWithAltCover/Sample2.dll" ] @@ -2167,7 +2167,7 @@ module Targets = AltCover.PrepareOptions.Primitive( { Primitive.PrepareOptions.Create() with Report = recorder472Report - OutputDirectories = [| "./__Recorder472TestWithAltCover" |] + OutputDirectories = [| "./__RecorderTestWithAltCover" |] StrongNameKey = shadowkeyfile ReportFormat = "NCover" InPlace = false @@ -2189,7 +2189,7 @@ module Targets = "--work=." "--result=./_Reports/Recorder4TestWithAltCoverReport.xml" Path.getFullName - "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net472/__Recorder472TestWithAltCover/AltCover.Recorder.Tests.dll" ] + "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net472/__RecorderTestWithAltCover/AltCover.Recorder.Tests.dll" ] Actions.Run (nunitConsole, ".", rec4Args) "Recorder net472 NUnit failed" @@ -2201,8 +2201,7 @@ module Targets = [ ReportGenerator.ReportType.Html ReportGenerator.ReportType.XmlSummary ] TargetDir = "_Reports/_UnitTestWithAltCover" }) - [ altReport - recorder472Report ] + [ altReport; recorder472Report ] uncovered @"_Reports/_UnitTestWithAltCover/Summary.xml" |> List.map fst From 292dd833f637cdc0978d9a8b928c9b6f85683197 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sun, 21 Jul 2024 15:26:20 +0100 Subject: [PATCH 87/91] Delete the obsolete --- Build/targets.fs | 40 +--------------------------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/Build/targets.fs b/Build/targets.fs index 40deb939..e1f1fad2 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -2155,44 +2155,6 @@ module Targets = printfn "UnitTestWithAltCover caught %A" x reraise () - printfn "Instrument the net472 Recorder tests" - - let recorder472Dir = - Path.getFullName "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net472" - - let recorder472Report = - reports @@ "Recorder472TestWithAltCover.xml" - - let prep = - AltCover.PrepareOptions.Primitive( - { Primitive.PrepareOptions.Create() with - Report = recorder472Report - OutputDirectories = [| "./__RecorderTestWithAltCover" |] - StrongNameKey = shadowkeyfile - ReportFormat = "NCover" - InPlace = false - Save = false } - |> AltCoverFilter - ) - |> AltCoverCommand.Prepare - - { AltCoverCommand.Options.Create prep with - ToolPath = altcover - ToolType = frameworkAltcover - WorkingDirectory = recorder472Dir } - |> AltCoverCommand.run - - printfn "Execute the net472 Recorder tests" - - let rec4Args = - [ "--noheader" - "--work=." - "--result=./_Reports/Recorder4TestWithAltCoverReport.xml" - Path.getFullName - "_Binaries/AltCover.Recorder.Tests/Debug+AnyCPU/net472/__RecorderTestWithAltCover/AltCover.Recorder.Tests.dll" ] - - Actions.Run (nunitConsole, ".", rec4Args) "Recorder net472 NUnit failed" - ReportGenerator.generateReports (fun p -> { p with @@ -2201,7 +2163,7 @@ module Targets = [ ReportGenerator.ReportType.Html ReportGenerator.ReportType.XmlSummary ] TargetDir = "_Reports/_UnitTestWithAltCover" }) - [ altReport; recorder472Report ] + [ altReport ] uncovered @"_Reports/_UnitTestWithAltCover/Summary.xml" |> List.map fst From 47f7ffaf9676011035eabcdeffc6f6a4f9a6dc8e Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Sun, 21 Jul 2024 17:25:08 +0100 Subject: [PATCH 88/91] Static linking base is not worth the hassle after all. --- AltCover.Engine/AltCover.Engine.fsproj | 1 - Build/targets.fs | 9 ++++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/AltCover.Engine/AltCover.Engine.fsproj b/AltCover.Engine/AltCover.Engine.fsproj index 935d5484..978b48a9 100644 --- a/AltCover.Engine/AltCover.Engine.fsproj +++ b/AltCover.Engine/AltCover.Engine.fsproj @@ -12,7 +12,6 @@ TRACE;$(GlobalDefineConstants) - --staticlink:AltCover.Base diff --git a/Build/targets.fs b/Build/targets.fs index e1f1fad2..9054eca1 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -3839,6 +3839,9 @@ module Targets = let altCover = Path.getFullName "_Binaries/AltCover/Release+AnyCPU/net472/AltCover.exe" + let abase = + Path.getFullName "_Binaries/AltCover/Release+AnyCPU/net472/AltCover.Base.dll" + let engine = Path.getFullName "_Binaries/AltCover/Release+AnyCPU/net472/AltCover.Engine.dll" @@ -3899,6 +3902,7 @@ module Targets = let applicationFiles = [ (altCover, Some "tools/net472", None) + (abase, Some "tools/net472", None) (engine, Some "tools/net472", None) (config, Some "tools/net472", None) (monitor, Some "lib/net20", None) @@ -3913,6 +3917,7 @@ module Targets = let apiFiles = [ (altCover, Some "lib/net472", None) + (abase, Some "lib/net472", None) (engine, Some "lib/net472", None) (config, Some "lib/net472", None) (monitor, Some "lib/net472", None) @@ -4483,7 +4488,8 @@ module Targets = ((packageVersionPart "PowerShellStandard.Library") + "System.Management.Automation.dll") - [ "AltCover.Cake" + [ "AltCover.Base" + "AltCover.Cake" "AltCover.DotNet" "AltCover.Engine" // beware static linkage -- maybe copy from debug? "AltCover.Monitor" @@ -4570,6 +4576,7 @@ module Targets = "AltCover.Monitor" "AltCover.Fake" "AltCover.Cake" + "AltCover.Base" "Recorder" "Mono" "DataCollector" From ac9b30e4872625d2c0bf1e60946783a5d220007a Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 22 Jul 2024 09:33:55 +0100 Subject: [PATCH 89/91] Back-port a lot of goodness --- .config/dotnet-tools.json | 4 +- AltCover.Avalonia/AltCover.Avalonia.fsproj | 1 + ...tCover.Fake.DotNet.Testing.AltCover.fsproj | 2 +- AltCover.Fake/AltCover.Fake.fsproj | 2 +- AltCover.Recorder.Tests/Adapter.cs | 0 AltCover.Recorder.Tests/Adapter.fs | 202 --------- .../AltCover.Recorder.Tests.fsproj | 4 +- AltCover.Recorder.Tests/AssemblyInfo.cs | 5 - AltCover.Recorder.Tests/Program.cs | 19 - AltCover.Recorder.Tests/Recorder.Tests.cs | 38 -- AltCover.Recorder.Tests/Recorder.Tests.fs | 412 +++++++++++------- AltCover.Recorder.Tests/Tracer.Tests.cs | 112 ----- AltCover.Recorder.Tests/Tracer.Tests.fs | 187 +++++--- AltCover.Recorder.sln | 1 + .../AltCover.Recorder2.Tests.fsproj | 7 +- .../AltCover.Visualizer.Tests.fsproj | 2 +- Build/Build.fsproj | 4 + Build/DriveApi.fsproj | 2 +- Build/Setup.fsproj | 4 + Samples/Sample18/Sample18.fsproj | 2 +- fullbuild.ps1 | 3 + 21 files changed, 402 insertions(+), 611 deletions(-) delete mode 100644 AltCover.Recorder.Tests/Adapter.cs delete mode 100644 AltCover.Recorder.Tests/Adapter.fs delete mode 100644 AltCover.Recorder.Tests/AssemblyInfo.cs delete mode 100644 AltCover.Recorder.Tests/Program.cs delete mode 100644 AltCover.Recorder.Tests/Recorder.Tests.cs delete mode 100644 AltCover.Recorder.Tests/Tracer.Tests.cs create mode 100644 fullbuild.ps1 diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 68071073..33cc1ae3 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "dotnet-reportgenerator-globaltool": { - "version": "5.3.0", + "version": "5.3.6", "commands": [ "reportgenerator" ], @@ -38,7 +38,7 @@ "rollForward": false }, "nbgv": { - "version": "3.6.133", + "version": "3.6.139", "commands": [ "nbgv" ], diff --git a/AltCover.Avalonia/AltCover.Avalonia.fsproj b/AltCover.Avalonia/AltCover.Avalonia.fsproj index f879efc9..2575da3b 100644 --- a/AltCover.Avalonia/AltCover.Avalonia.fsproj +++ b/AltCover.Avalonia/AltCover.Avalonia.fsproj @@ -10,6 +10,7 @@ AVALONIA;$(TOGGLE) True $(ProjectDir)../AltCover.Visualizer/Resource.res + NU1902,NU1903,NU1904 diff --git a/AltCover.Fake.DotNet.Testing.AltCover/AltCover.Fake.DotNet.Testing.AltCover.fsproj b/AltCover.Fake.DotNet.Testing.AltCover/AltCover.Fake.DotNet.Testing.AltCover.fsproj index 31bbe700..9bc58f23 100644 --- a/AltCover.Fake.DotNet.Testing.AltCover/AltCover.Fake.DotNet.Testing.AltCover.fsproj +++ b/AltCover.Fake.DotNet.Testing.AltCover/AltCover.Fake.DotNet.Testing.AltCover.fsproj @@ -7,7 +7,7 @@ NoCanonicalDirectories;FAKEAPI MSB3277;MSB3245 - NU1701;NU1605 + NU1701;NU1605;NU1902,NU1903,NU1904 diff --git a/AltCover.Fake/AltCover.Fake.fsproj b/AltCover.Fake/AltCover.Fake.fsproj index 6f2aba8e..f5f6e1ed 100644 --- a/AltCover.Fake/AltCover.Fake.fsproj +++ b/AltCover.Fake/AltCover.Fake.fsproj @@ -5,7 +5,7 @@ AltCover.Fake AltCover.Fake RUNNER - NU1701;NU1605 + NU1701;NU1605;NU1902,NU1903,NU1904 diff --git a/AltCover.Recorder.Tests/Adapter.cs b/AltCover.Recorder.Tests/Adapter.cs deleted file mode 100644 index e69de29b..00000000 diff --git a/AltCover.Recorder.Tests/Adapter.fs b/AltCover.Recorder.Tests/Adapter.fs deleted file mode 100644 index 750cd110..00000000 --- a/AltCover.Recorder.Tests/Adapter.fs +++ /dev/null @@ -1,202 +0,0 @@ -namespace AltCover.Recorder - -open System.Collections.Generic - -#if DEBUG -[] -module Adapter = - let DoPause () = Instance.I.doPause - let DoResume () = Instance.I.doResume - let DoUnload () = Instance.I.doUnload - let DoExit () = Instance.I.doExit - - let VisitsClear () = - Instance.I.Clear() - Counter.branchVisits <- 0L - Counter.totalVisits <- 0L - - let SamplesClear () = - Instance.I.samples <- Instance.I.MakeSamples() - - let private reset () = - Instance.I.isRunner <- false - VisitsClear() - SamplesClear() - - let ModuleReset (m: string array) = - Instance.Modules <- m - reset () - - let HardReset () = - Instance.Modules <- [| System.String.Empty |] - reset () - - let internal prepareName name = - if name |> Instance.I.visits.ContainsKey |> not then - let entry = Dictionary() - Instance.I.visits.Add(name, entry) - - let internal init (n, l) = - let tmp = PointVisit.Create() - tmp.Count <- n - - tmp.Tracks.AddRange l - tmp - - let VisitsAdd (name, line, number) = - prepareName name - let v = init (number, []) - Instance.I.visits.[name].Add(line, v) - - let VisitsAddTrack (name, line, number) = - prepareName name - let v1 = init (number, [ Call 17; Call 42 ]) - Instance.I.visits.[name].Add(line, v1) - - let v2 = - init ( - (number + 1L), - [ Time(17L) - Both(Pair.Create(42L, 23)) ] - ) - - Instance.I.visits.[name].Add(line + 1, v2) - - let VisitsSeq () = Instance.I.visits |> Seq.cast - - let VisitsEntrySeq key = - Instance.I.visits.[key] |> Seq.cast - - let VisitCount (key, key2) = (Instance.I.visits.[key].[key2]).Count - let Lock = Instance.I.visits :> obj - - let VisitImplNone (moduleId, hitPointId) = - Instance.I.VisitImpl(moduleId, hitPointId, Null()) - - let VisitImplMethod (moduleId, hitPointId, mId) = - Instance.I.VisitImpl(moduleId, hitPointId, (Call mId)) - - let internal addSample (moduleId, hitPointId, context) = - Instance.I.TakeSample(Sampling.Single, moduleId, hitPointId, context) - - let internal addSampleUnconditional (moduleId, hitPointId, context) = - Instance.I.TakeSample(Sampling.All, moduleId, hitPointId, context) - - let internal newBoth (time, call) = Both(Pair.Create(time, call)) - - let internal asCall track = Call track - let internal time at = Time at - - let internal untime (at: Track) = - let r = List() - - match at with - | :? Time as t -> r.Add(t.Value) - | _ -> () - - r - - let internal asNull () = new Null() :> Track - let internal table t = Table t :> Track - - let internal untable t = - let r = List() - - let n, p, (t': Track) = t - - match t' with - | :? Table as d -> - r.Add(n) - r.Add(p) - r.Add(d) - | _ -> () - - r - - let internal doFlush (visits, format, report, output) = - let output' = - if System.String.IsNullOrEmpty output then - null - else - output - - Counter.DoFlushFile(ignore, (fun _ _ -> ()), true, visits, format, report, output') - - let internal updateReport (counts, format, coverageFile, outputFile) = - Counter.I.UpdateReport( - ignore, - (fun _ _ -> ()), - true, - counts, - format, - coverageFile, - outputFile - ) - - let internal payloadSelector x = Instance.I.PayloadSelector(fun _ -> x) - - let internal payloadControl (x, y) = - Instance.I.PayloadControl((fun _ -> x), (fun _ -> y)) - - let internal payloadSelection (x, y, z) = - Instance.I.PayloadSelection((fun _ -> x), (fun _ -> y), (fun _ -> z)) - - let internal makeNullTrace name = Tracer.Create(name) - - let internal makeStreamTrace s1 = - let mutable t = Tracer.Create(null) - // fsharplint:disable-next-line RedundantNewKeyword - t.Stream <- new System.IO.MemoryStream() - // fsharplint:disable-next-line RedundantNewKeyword - t.Formatter <- new System.IO.BinaryWriter(s1) - t.Runner <- true - t.Definitive <- false - t - - let internal invokeIssue71Wrapper<'T when 'T :> System.Exception> - ((unique: string), (called: bool array)) - = - let constructor = - typeof<'T> - .GetConstructor([| typeof |]) - - let pitcher = - fun _ _ _ _ -> - constructor.Invoke([| unique |]) :?> System.Exception - |> raise - - let catcher = - fun _ _ _ (x: System.Exception) -> - called.[0] <- true - - called.[1] <- - match x with - | :? System.ArgumentNullException as ane -> ane.ParamName = unique - | _ -> x.Message = unique - - Instance.I.Issue71Wrapper((), (), (), (), catcher, pitcher) - |> ignore - - let internal invokeCurriedIssue71Wrapper<'T when 'T :> System.Exception> - (unique: string) - = - let constructor = - typeof<'T> - .GetConstructor([| typeof |]) - - let pitcher = - fun _ _ _ _ -> - constructor.Invoke([| unique |]) :?> System.Exception - |> raise - - Instance.I.CurriedIssue71Wrapper( - "a", - "b", - "c", - "d", - pitcher - ) - |> ignore - - let internal tracePush (a, b, c) = Instance.I.Trace.Push(a, b, c) -#endif \ No newline at end of file diff --git a/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj b/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj index 8c73f001..3a8a34a7 100644 --- a/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj +++ b/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj @@ -23,11 +23,11 @@ AssemblyVersion.fs - - + + diff --git a/AltCover.Recorder.Tests/AssemblyInfo.cs b/AltCover.Recorder.Tests/AssemblyInfo.cs deleted file mode 100644 index b4e1d9f9..00000000 --- a/AltCover.Recorder.Tests/AssemblyInfo.cs +++ /dev/null @@ -1,5 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -[assembly: CLSCompliant(true)] -[assembly: ComVisible(false)] \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Program.cs b/AltCover.Recorder.Tests/Program.cs deleted file mode 100644 index d4c4501b..00000000 --- a/AltCover.Recorder.Tests/Program.cs +++ /dev/null @@ -1,19 +0,0 @@ -#if !NET472 -#if NET20 -namespace Tests.Recorder.Clr2 -#else - -namespace Tests.Recorder.Core -#endif -#else -namespace Tests.Recorder.Clr4 -#endif -{ - internal static class UnitTestStub - { - private static int Main() - { - return 0; - } - } -} \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Recorder.Tests.cs b/AltCover.Recorder.Tests/Recorder.Tests.cs deleted file mode 100644 index 19ed2eea..00000000 --- a/AltCover.Recorder.Tests/Recorder.Tests.cs +++ /dev/null @@ -1,38 +0,0 @@ -#if !NET472 -#if NET20 -namespace Tests.Recorder.Clr2 -#else - -namespace Tests.Recorder.Core -#endif -#else -namespace Tests.Recorder.Clr4 -#endif -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.IO.Compression; - using System.Reflection; - using System.Runtime.CompilerServices; - using System.Threading; - using System.Xml; - - using AltCover.Recorder; - using NUnit.Framework; - - public static class AltCoverTests - { - [Test] - public static void ShouldCoverTrivalClass() - { - var mark = new InstrumentationAttribute(); // Constructor has all the instrumented code - Assert.That(mark.Assembly, Is.EqualTo("AltCover.Recorder.g!")); - Assert.That(mark.Configuration, Is.EqualTo("Uninstrumented!!")); - mark.Assembly = String.Empty; - mark.Configuration = String.Empty; - Assert.True(String.IsNullOrEmpty(mark.Assembly)); - Assert.True(String.IsNullOrEmpty(mark.Configuration)); - } - } -} \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index a5d9410a..78d49a1e 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -35,30 +35,42 @@ module AltCoverTests = // printfn "%s %s" tag //#endif +#if RECORDER2 let resource = - Assembly - .GetExecutingAssembly() - .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("SimpleCoverage.xml", StringComparison.Ordinal)) + "AltCover.Recorder2.Tests.SimpleCoverage.xml" let resource2 = - Assembly - .GetExecutingAssembly() - .GetManifestResourceNames() - |> Seq.find (fun n -> - n.EndsWith("Sample1WithModifiedOpenCover.xml", StringComparison.Ordinal)) + "AltCover.Recorder2.Tests.Sample1WithModifiedOpenCover.xml" let resource3 = - Assembly - .GetExecutingAssembly() - .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("Sample2NCoverage.xml", StringComparison.Ordinal)) + "AltCover.Recorder2.Tests.Sample2NCoverage.xml" +#else + let resource = + "AltCover.Recorder.Tests.SimpleCoverage.xml" + + let resource2 = + "AltCover.Recorder.Tests.Sample1WithModifiedOpenCover.xml" + + let resource3 = + "AltCover.Recorder.Tests.Sample2NCoverage.xml" +#endif + + let internal updateReport0 (counts, format, coverageFile, outputFile) = + Counter.I.UpdateReport( + ignore, + (fun _ _ -> ()), + true, + counts, + format, + coverageFile, + outputFile + ) let private updateReport a b = - Adapter.updateReport (a, ReportFormat.NCover, b, b) + updateReport0 (a, ReportFormat.NCover, b, b) |> ignore - let private pointVisitInit a b = Adapter.init (a, b) + let private pointVisitInit a b = AltCoverCoreTests.init (a, b) [] let ShouldCoverTrivalClass () = @@ -95,8 +107,7 @@ module AltCoverTests = let ShouldBeLinkingTheCorrectCopyOfThisCode () = getMyMethodName "=>" - let tracer = - Adapter.makeNullTrace String.Empty + let tracer = Tracer.Create String.Empty // whitelist test not recorder.g @@ -107,62 +118,67 @@ module AltCoverTests = getMyMethodName "<=" + let internal addSample (moduleId, hitPointId, context) = + Instance.I.TakeSample(Sampling.Single, moduleId, hitPointId, context) + + let internal addSampleUnconditional (moduleId, hitPointId, context) = + Instance.I.TakeSample(Sampling.All, moduleId, hitPointId, context) + [] let OnlyNewIdPairShouldBeSampled () = getMyMethodName "=>" - lock Adapter.Lock (fun () -> + lock Instance.I.visits (fun () -> try - Adapter.ModuleReset [| "module"; "newmodule" |] + AltCoverCoreTests.ModuleReset [| "module"; "newmodule" |] let n = Null() :> Track - Assert.True(Adapter.addSample ("module", 23, n), "Test 1") - Assert.True(Adapter.addSample ("module", 24, n), "Test 2") - Assert.True(Adapter.addSample ("newmodule", 23, n), "Test 3") - Assert.True(Adapter.addSample ("module", 23, n) |> not, "Test 4") - Assert.True(Adapter.addSampleUnconditional ("module", 23, n), "Test 5") - Assert.True(Adapter.addSample ("module", 23, Call 1), "Test 6") - Assert.True(Adapter.addSample ("module", 23, Time 0L), "Test 7") - Assert.True(Adapter.addSample ("module", 23, Time 1L), "Test 7a") - Assert.True(Adapter.addSample ("module", 23, Time 0L) |> not, "Test 7b") + Assert.True(addSample ("module", 23, n), "Test 1") + Assert.True(addSample ("module", 24, n), "Test 2") + Assert.True(addSample ("newmodule", 23, n), "Test 3") + Assert.True(addSample ("module", 23, n) |> not, "Test 4") + Assert.True(addSampleUnconditional ("module", 23, n), "Test 5") + Assert.True(addSample ("module", 23, Call 1), "Test 6") + Assert.True(addSample ("module", 23, Time 0L), "Test 7") + Assert.True(addSample ("module", 23, Time 1L), "Test 7a") + Assert.True(addSample ("module", 23, Time 0L) |> not, "Test 7b") - Assert.True( - Adapter.addSample ("module", 24, new Both(Pair.Create(0, 1))), - "Test 8" - ) + Assert.True(addSample ("module", 24, new Both(Pair.Create(0, 1))), "Test 8") - Assert.True( - Adapter.addSample ("module", 25, new Both(Pair.Create(0, 1))), - "Test 9" - ) + Assert.True(addSample ("module", 25, new Both(Pair.Create(0, 1))), "Test 9") - Assert.True(Adapter.addSample ("module", 25, Call 1) |> not, "Test 10") - Assert.True(Adapter.addSample ("module", 25, Call 1) |> not, "Test 11") - Assert.True(Adapter.addSample ("module", 25, n) |> not, "Test 12") + Assert.True(addSample ("module", 25, Call 1) |> not, "Test 10") + Assert.True(addSample ("module", 25, Call 1) |> not, "Test 11") + Assert.True(addSample ("module", 25, n) |> not, "Test 12") // out of band example - Assert.True(Adapter.addSample ("nonesuch", 25, n) |> not, "Test 12a") + Assert.True(addSample ("nonesuch", 25, n) |> not, "Test 12a") Assert.Throws(fun () -> - Adapter.addSample ("module", 23, Table null) - |> ignore) + addSample ("module", 23, Table null) |> ignore) |> ignore finally - Adapter.HardReset()) + AltCoverCoreTests.HardReset()) getMyMethodName "<=" + let VisitsEntrySeq key = + Instance.I.visits.[key] + |> Seq.cast> + + let VisitCount (key, key2) = (Instance.I.visits.[key].[key2]).Count + [] let RealIdShouldIncrementCount () = getMyMethodName "=>" - lock Adapter.Lock (fun () -> + lock Instance.I.visits (fun () -> let save = Instance.I.Trace try let key = " " - Adapter.ModuleReset [| key |] - Instance.I.Trace <- Adapter.makeNullTrace null + AltCoverCoreTests.ModuleReset [| key |] + Instance.I.Trace <- Tracer.Create null Instance.I.Recording <- false Instance.Visit("key", 17) @@ -176,27 +192,41 @@ module AltCoverTests = Instance.Visit(key, -23) - let vs = Adapter.VisitsSeq() - Assert.True(vs |> Seq.length = 3, sprintf "Adapter.VisitsSeq() = %A" vs) - - let vesk = Adapter.VisitsEntrySeq key + let vs = AltCoverCoreTests.VisitsSeq() Assert.True( - vesk |> Seq.length = 1, - sprintf "Adapter.VisitsEntrySeq %A = %A" key vesk + vs |> Seq.length = 3, + sprintf "AltCoverCoreTests.VisitsSeq() = %A" vs ) - Assert.That(Adapter.VisitCount(key, -23), Is.EqualTo 2L) + let vesk = VisitsEntrySeq key + + Assert.True(vesk |> Seq.length = 1, sprintf "VisitsEntrySeq %A = %A" key vesk) + + Assert.That(VisitCount(key, -23), Is.EqualTo 2L) Assert.That(Counter.totalVisits, Is.EqualTo 1L) Assert.That(Counter.branchVisits, Is.EqualTo 1L) finally Instance.CoverageFormat <- ReportFormat.NCover Instance.I.Recording <- true - Adapter.HardReset() + AltCoverCoreTests.HardReset() Instance.I.Trace <- save) getMyMethodName "<=" + let internal payloadSelector x = Instance.I.PayloadSelector(fun _ -> x) + + let internal payloadControl (x, y) = + Instance.I.PayloadControl((fun _ -> x), (fun _ -> y)) + + let internal payloadSelection (x, y, z) = + Instance.I.PayloadSelection((fun _ -> x), (fun _ -> y), (fun _ -> z)) + + let internal untime (at: Track) = + match at with + | :? Time as t -> Some t.Value + | _ -> None + [] let JunkUspidGivesNegativeIndex () = let key = " " @@ -216,47 +246,44 @@ module AltCoverTests = ||| ReportFormat.WithTracking Assert.False(Instance.I.CallerId.HasValue) - Assert.That(Adapter.payloadSelector false, Is.EqualTo <| Adapter.asNull ()) - Assert.That(Adapter.payloadSelector true, Is.EqualTo <| Adapter.asNull ()) + Assert.That(payloadSelector false, Is.EqualTo <| Null()) + Assert.That(payloadSelector true, Is.EqualTo <| Null()) Instance.Push 4321 - Assert.That(Adapter.payloadSelector false, Is.EqualTo <| Adapter.asNull ()) - Assert.That(Adapter.payloadSelector true, Is.EqualTo <| (Adapter.asCall 4321)) + Assert.That(payloadSelector false, Is.EqualTo <| Null()) + Assert.That(payloadSelector true, Is.EqualTo <| (Call 4321)) try Instance.Push 6789 // 0x1234123412341234 == 1311693406324658740 let result = - Adapter.payloadSelection (1311693406324658740L, 1000L, true) + payloadSelection (1311693406324658740L, 1000L, true) let expected = - Adapter.newBoth (1311693406324658000L, 6789) + AltCoverCoreTests.newBoth (1311693406324658000L, 6789) Assert.True((result = expected)) finally Instance.Pop() - Assert.That(Adapter.payloadSelector true, Is.EqualTo(Adapter.asCall 4321)) + Assert.That(payloadSelector true, Is.EqualTo(Call 4321)) finally Instance.Pop() Instance.CoverageFormat <- ReportFormat.NCover let result2 = - Adapter.payloadSelection (1311693406324658740L, 1000L, true) + payloadSelection (1311693406324658740L, 1000L, true) - let expected2 = - Adapter.time 1311693406324658000L + let expected2 = Time 1311693406324658000L Assert.True((result2 = expected2)) let v1 = DateTime.UtcNow.Ticks - let probed = - Adapter.payloadControl (1000L, true) + let probed = payloadControl (1000L, true) let v2 = DateTime.UtcNow.Ticks - Assert.True(Adapter.asNull () |> Adapter.untime |> Seq.isEmpty) + Assert.True(Null() |> untime |> Option.isNone) - let [ probe ] = - Adapter.untime probed |> Seq.toList + let probe = (untime probed).Value Assert.True(probe % 1000L = 0L) Assert.True(probe <= v2) @@ -267,7 +294,7 @@ module AltCoverTests = [] let PayloadWithEntryExitGeneratedIsAsExpected () = - Adapter.ModuleReset [||] + AltCoverCoreTests.ModuleReset [||] try Instance.I.isRunner <- true @@ -276,51 +303,48 @@ module AltCoverTests = ReportFormat.OpenCover ||| ReportFormat.WithTracking - Adapter.VisitsClear() + AltCoverCoreTests.VisitsClear() Assert.True(Instance.I.CallerId.HasValue |> not) - Assert.That(Adapter.payloadSelector false, Is.EqualTo <| Adapter.asNull ()) - Assert.That(Adapter.payloadSelector true, Is.EqualTo <| Adapter.asNull ()) + Assert.That(payloadSelector false, Is.EqualTo <| Null()) + Assert.That(payloadSelector true, Is.EqualTo <| Null()) Instance.Push 4321 - Assert.That(Adapter.payloadSelector false, Is.EqualTo <| Adapter.asNull ()) - Assert.That(Adapter.payloadSelector true, Is.EqualTo(Adapter.asCall 4321)) + Assert.That(payloadSelector false, Is.EqualTo <| Null()) + Assert.That(payloadSelector true, Is.EqualTo(Call 4321)) try Instance.Push 6789 // 0x1234123412341234 == 1311693406324658740 let result = - Adapter.payloadSelection (1311693406324658740L, 1000L, true) + payloadSelection (1311693406324658740L, 1000L, true) let expected = - Adapter.newBoth (1311693406324658000L, 6789) + AltCoverCoreTests.newBoth (1311693406324658000L, 6789) Assert.True((result = expected)) finally Instance.Pop() - Assert.That(Adapter.payloadSelector true, Is.EqualTo(Adapter.asCall 4321)) + Assert.That(payloadSelector true, Is.EqualTo(Call 4321)) finally Instance.Pop() Instance.I.isRunner <- false Instance.CoverageFormat <- ReportFormat.NCover let result2 = - Adapter.payloadSelection (1311693406324658740L, 1000L, true) + payloadSelection (1311693406324658740L, 1000L, true) - let expected2 = - Adapter.time 1311693406324658000L + let expected2 = Time 1311693406324658000L Assert.True((result2 = expected2)) let v1 = DateTime.UtcNow.Ticks - let probed = - Adapter.payloadControl (1000L, true) + let probed = payloadControl (1000L, true) let v2 = DateTime.UtcNow.Ticks - Assert.True(Adapter.asNull () |> Adapter.untime |> Seq.isEmpty) + Assert.True(Null() |> untime |> Option.isNone) - let [ probe ] = - Adapter.untime probed |> Seq.toList + let probe = (untime probed).Value Assert.True(probe % 1000L = 0L) Assert.True(probe <= v2) @@ -359,24 +383,24 @@ module AltCoverTests = Assert.That(d.Tracks |> Seq.length, Is.EqualTo 1) let a2 = - a.Tracks |> Seq.head |> Adapter.untime |> Seq.head + (a.Tracks |> Seq.head |> untime).Value let b2 = - b.Tracks |> Seq.head |> Adapter.untime |> Seq.head + (b.Tracks |> Seq.head |> untime).Value Assert.That(b2 >= a2) let c2 = - c.Tracks |> Seq.head |> Adapter.untime |> Seq.head + (c.Tracks |> Seq.head |> untime).Value Assert.That(c2 >= b2) let d2 = - d.Tracks |> Seq.head |> Adapter.untime |> Seq.head + (d.Tracks |> Seq.head |> untime).Value Assert.That(d2 >= c2, sprintf "%A >= %A" d2 c2) - Adapter.HardReset() + AltCoverCoreTests.HardReset() [] let RealIdShouldIncrementCountSynchronously () = @@ -385,12 +409,12 @@ module AltCoverTests = lock Instance.I.visits (fun () -> let save = Instance.I.Trace let key = " " - Adapter.ModuleReset [| key |] + AltCoverCoreTests.ModuleReset [| key |] try - Instance.I.Trace <- Adapter.makeNullTrace null + Instance.I.Trace <- Tracer.Create null - Instance.I.VisitSelection(Adapter.asNull (), key, 23) + Instance.I.VisitSelection(Null(), key, 23) Assert.That( Instance.I.visits.Keys, @@ -407,7 +431,7 @@ module AltCoverTests = Assert.That(Instance.I.visits.[key].[23].Count, Is.EqualTo 1) Assert.That(Instance.I.visits.[key].[23].Tracks, Is.Empty) finally - Adapter.HardReset() + AltCoverCoreTests.HardReset() Instance.I.Trace <- save) getMyMethodName "<=" @@ -418,6 +442,51 @@ module AltCoverTests = Assert.That(all.Contains x) all.Remove x |> ignore) + let internal invokeCurriedIssue71Wrapper<'T when 'T :> System.Exception> + (unique: string) + = + let constructor = + typeof<'T> + .GetConstructor([| typeof |]) + + let pitcher = + fun _ _ _ _ -> + constructor.Invoke([| unique |]) :?> System.Exception + |> raise + + Instance.I.CurriedIssue71Wrapper( + "a", + "b", + "c", + "d", + pitcher + ) + |> ignore + + let internal invokeIssue71Wrapper<'T when 'T :> System.Exception> + ((unique: string), (called: bool array)) + = + let constructor = + typeof<'T> + .GetConstructor([| typeof |]) + + let pitcher = + fun _ _ _ _ -> + constructor.Invoke([| unique |]) :?> System.Exception + |> raise + + let catcher = + fun _ _ _ (x: System.Exception) -> + called.[0] <- true + + called.[1] <- + match x with + | :? System.ArgumentNullException as ane -> ane.ParamName = unique + | _ -> x.Message = unique + + Instance.I.Issue71Wrapper((), (), (), (), catcher, pitcher) + |> ignore + [] let StripWorks () = let b1 = [ "1" ] @@ -481,7 +550,7 @@ module AltCoverTests = let unique = System.Guid.NewGuid().ToString() - Adapter.invokeCurriedIssue71Wrapper unique + invokeCurriedIssue71Wrapper unique let after = Directory.GetFiles(where, "*.exn") @@ -517,7 +586,7 @@ module AltCoverTests = let unique = System.Guid.NewGuid().ToString() - Adapter.invokeIssue71Wrapper (unique, pair) + invokeIssue71Wrapper (unique, pair) Assert.That(pair |> Seq.head, Is.True) Assert.That(pair |> Seq.last, Is.True) @@ -528,7 +597,7 @@ module AltCoverTests = let unique = System.Guid.NewGuid().ToString() - Adapter.invokeIssue71Wrapper (unique, pair) + invokeIssue71Wrapper (unique, pair) Assert.That(pair |> Seq.head, Is.True) Assert.That(pair |> Seq.last, Is.True) @@ -539,7 +608,7 @@ module AltCoverTests = let unique = System.Guid.NewGuid().ToString() - Adapter.invokeIssue71Wrapper (unique, pair) + invokeIssue71Wrapper (unique, pair) Assert.That(pair |> Seq.head, Is.True) Assert.That(pair |> Seq.last, Is.True) @@ -552,7 +621,7 @@ module AltCoverTests = let exn = Assert.Throws(fun () -> - Adapter.invokeIssue71Wrapper (unique, pair)) + invokeIssue71Wrapper (unique, pair)) Assert.That(pair |> Seq.head, Is.False) Assert.That(pair |> Seq.last, Is.False) @@ -577,7 +646,7 @@ module AltCoverTests = let before = Directory.GetFiles(where, "*.exn") - Instance.I.VisitImpl(key, 23, Adapter.asNull ()) + Instance.I.VisitImpl(key, 23, Null()) let after = Directory.GetFiles(where, "*.exn") @@ -619,16 +688,16 @@ module AltCoverTests = lock Instance.I.visits (fun () -> try let key = " " - Adapter.ModuleReset [| key; "key" |] - Instance.I.VisitImpl(key, 23, Adapter.asNull ()) - Instance.I.VisitImpl("key", 42, Adapter.asNull ()) + AltCoverCoreTests.ModuleReset [| key; "key" |] + Instance.I.VisitImpl(key, 23, Null()) + Instance.I.VisitImpl("key", 42, Null()) Assert.That( Instance.I.visits.Keys, Is.EquivalentTo [ key; "key"; Track.Entry; Track.Exit ] ) finally - Adapter.HardReset()) + AltCoverCoreTests.HardReset()) getMyMethodName "<=" @@ -639,9 +708,9 @@ module AltCoverTests = lock Instance.I.visits (fun () -> try let key = " " - Adapter.ModuleReset [| key |] - Instance.I.VisitImpl(key, 23, Adapter.asNull ()) - Instance.I.VisitImpl(key, 42, Adapter.asNull ()) + AltCoverCoreTests.ModuleReset [| key |] + Instance.I.VisitImpl(key, 23, Null()) + Instance.I.VisitImpl(key, 42, Null()) Assert.That( Instance.I.visits.Keys, @@ -650,7 +719,7 @@ module AltCoverTests = Assert.That(Instance.I.visits.[key].Count, Is.EqualTo 2) finally - Adapter.HardReset()) + AltCoverCoreTests.HardReset()) getMyMethodName "<=" @@ -660,15 +729,15 @@ module AltCoverTests = lock Instance.I.visits (fun () -> let key = " " - Adapter.ModuleReset [| key |] + AltCoverCoreTests.ModuleReset [| key |] try - Instance.I.VisitImpl(key, 23, Adapter.asNull ()) - Instance.I.VisitImpl(key, 23, Adapter.asNull ()) + Instance.I.VisitImpl(key, 23, Null()) + Instance.I.VisitImpl(key, 23, Null()) Assert.That(Instance.I.visits.[key].[23].Count, Is.EqualTo 2) Assert.That(Instance.I.visits.[key].[23].Tracks, Is.Empty) finally - Adapter.HardReset()) + AltCoverCoreTests.HardReset()) getMyMethodName "<=" @@ -678,18 +747,17 @@ module AltCoverTests = lock Instance.I.visits (fun () -> let key = " " - Adapter.ModuleReset [| key |] + AltCoverCoreTests.ModuleReset [| key |] try - let payload = - Adapter.time DateTime.UtcNow.Ticks + let payload = Time DateTime.UtcNow.Ticks - Instance.I.VisitImpl(key, 23, Adapter.asNull ()) + Instance.I.VisitImpl(key, 23, Null()) Instance.I.VisitImpl(key, 23, payload) Assert.That(Instance.I.visits.[key].[23].Count, Is.EqualTo 1) Assert.That(Instance.I.visits.[key].[23].Tracks, Is.EquivalentTo [ payload ]) finally - Adapter.HardReset()) + AltCoverCoreTests.HardReset()) getMyMethodName "<=" @@ -1187,7 +1255,7 @@ module AltCoverTests = item.Add("7C-CD-66-29-A3-6C-6D-5F-A7-65-71-0E-22-7D-B2-61-B5-1F-65-9A", payload) - Adapter.updateReport (item, ReportFormat.OpenCover, worker, worker) + updateReport0 (item, ReportFormat.OpenCover, worker, worker) |> ignore worker.Position <- 0L @@ -1224,17 +1292,17 @@ module AltCoverTests = let EmptyFlushLeavesNoTrace () = getMyMethodName "=>" - lock Adapter.Lock (fun () -> + lock Instance.I.visits (fun () -> let saved = Console.Out try - Adapter.VisitsClear() + AltCoverCoreTests.VisitsClear() use stdout = new StringWriter() Console.SetOut stdout Instance.FlushFinish() Assert.That(stdout.ToString(), Is.Empty) finally - Adapter.VisitsClear() + AltCoverCoreTests.VisitsClear() Console.SetOut saved) getMyMethodName "<=" @@ -1274,11 +1342,21 @@ module AltCoverTests = trywithrelease (fun () -> InvalidOperationException() |> raise) + let internal makeStreamTrace s1 = + let mutable t = Tracer.Create(null) + // fsharplint:disable-next-line RedundantNewKeyword + t.Stream <- new System.IO.MemoryStream() + // fsharplint:disable-next-line RedundantNewKeyword + t.Formatter <- new System.IO.BinaryWriter(s1) + t.Runner <- true + t.Definitive <- false + t + [] let PauseLeavesExpectedTraces () = getMyMethodName "=>" - lock Adapter.Lock (fun () -> + lock Instance.I.visits (fun () -> trywithrelease (fun () -> let saved = Console.Out let here = Directory.GetCurrentDirectory() @@ -1296,11 +1374,11 @@ module AltCoverTests = let s1 = new Compression.DeflateStream(s, CompressionMode.Compress) - Instance.I.Trace <- Adapter.makeStreamTrace s1 + Instance.I.Trace <- makeStreamTrace s1 try Instance.I.isRunner <- true - Adapter.VisitsClear() + AltCoverCoreTests.VisitsClear() use stdout = new StringWriter() Console.SetOut stdout @@ -1328,17 +1406,16 @@ module AltCoverTests = [ 0..9 ] |> Seq.iter (fun i -> - Adapter.VisitsAdd( + AltCoverCoreTests.VisitsAdd( "f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, (int64 (i + 1)) )) let nullObj: obj = null - Adapter.DoPause().Invoke(nullObj, null) + Instance.I.doPause.Invoke(nullObj, null) - Adapter.VisitsSeq() - |> Seq.cast>> + AltCoverCoreTests.VisitsSeq() |> Seq.iter (fun v -> Assert.That(v.Value, Is.Empty, sprintf "Unexpected write %A" v)) @@ -1370,7 +1447,7 @@ module AltCoverTests = finally Instance.I.Trace <- save AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath - Adapter.VisitsClear() + AltCoverCoreTests.VisitsClear() Instance.I.isRunner <- false Console.SetOut saved Directory.SetCurrentDirectory(here) @@ -1382,7 +1459,7 @@ module AltCoverTests = let ResumeLeavesExpectedTraces () = getMyMethodName "=>" - lock Adapter.Lock (fun () -> + lock Instance.I.visits (fun () -> trywithrelease (fun () -> let saved = Console.Out let here = Directory.GetCurrentDirectory() @@ -1405,7 +1482,7 @@ module AltCoverTests = let key = "f6e3edb3-fb20-44b3-817d-f69d1a22fc2f" - Adapter.ModuleReset [| key |] + AltCoverCoreTests.ModuleReset [| key |] Instance.I.Trace <- Tracer.Create(tag) use stdout = new StringWriter() @@ -1433,13 +1510,12 @@ module AltCoverTests = () [ 0..9 ] - |> Seq.iter (fun i -> Adapter.VisitsAdd(key, i, (int64 (i + 1)))) + |> Seq.iter (fun i -> AltCoverCoreTests.VisitsAdd(key, i, (int64 (i + 1)))) let nullObj: obj = null - Adapter.DoResume().Invoke(nullObj, null) + Instance.I.doResume.Invoke(nullObj, null) - Adapter.VisitsSeq() - |> Seq.cast>> + AltCoverCoreTests.VisitsSeq() |> Seq.iter (fun v -> Assert.That(v.Value, Is.Empty, sprintf "Visits should be cleared %A" v)) @@ -1475,10 +1551,10 @@ module AltCoverTests = "-1" ] ) finally - Adapter.HardReset() + AltCoverCoreTests.HardReset() Instance.I.Trace <- save AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath - Adapter.VisitsClear() + AltCoverCoreTests.VisitsClear() Console.SetOut saved Directory.SetCurrentDirectory(here) File.Delete tag @@ -1490,7 +1566,7 @@ module AltCoverTests = let FlushLeavesExpectedTraces () = getMyMethodName "=>" - lock Adapter.Lock (fun () -> + lock Instance.I.visits (fun () -> Instance.I.isRunner <- false trywithrelease (fun () -> @@ -1505,10 +1581,10 @@ module AltCoverTests = Path.Combine(where, Guid.NewGuid().ToString()) let save = Instance.I.Trace - Instance.I.Trace <- Adapter.makeNullTrace null + Instance.I.Trace <- Tracer.Create null try - Adapter.VisitsClear() + AltCoverCoreTests.VisitsClear() use stdout = new StringWriter() Console.SetOut stdout Directory.CreateDirectory(unique) |> ignore @@ -1535,14 +1611,14 @@ module AltCoverTests = [ 0..9 ] |> Seq.iter (fun i -> - Adapter.VisitsAdd( + AltCoverCoreTests.VisitsAdd( "f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, (int64 (i + 1)) )) let nullObj: obj = null - Adapter.DoExit().Invoke(nullObj, null) + Instance.I.doExit.Invoke(nullObj, null) let head = "Coverage statistics flushing took " @@ -1586,7 +1662,7 @@ module AltCoverTests = finally Instance.I.Trace <- save AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath - Adapter.VisitsClear() + AltCoverCoreTests.VisitsClear() Console.SetOut saved Directory.SetCurrentDirectory(here) AltCoverCoreTests.maybeIOException (fun () -> Directory.Delete(unique)))) @@ -1597,7 +1673,7 @@ module AltCoverTests = let SupervisedFlushLeavesExpectedTraces () = getMyMethodName "=>" - lock Adapter.Lock (fun () -> + lock Instance.I.visits (fun () -> trywithrelease (fun () -> let saved = Console.Out let here = Directory.GetCurrentDirectory() @@ -1610,12 +1686,12 @@ module AltCoverTests = Path.Combine(where, Guid.NewGuid().ToString()) let save = Instance.I.Trace - Instance.I.Trace <- Adapter.makeNullTrace null + Instance.I.Trace <- Tracer.Create null Instance.supervision <- true try - Adapter.VisitsClear() + AltCoverCoreTests.VisitsClear() use stdout = new StringWriter() Console.SetOut stdout Directory.CreateDirectory(unique) |> ignore @@ -1642,14 +1718,14 @@ module AltCoverTests = [ 0..9 ] |> Seq.iter (fun i -> - Adapter.VisitsAdd( + AltCoverCoreTests.VisitsAdd( "f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, (int64 (i + 1)) )) let nullObj: obj = null - Adapter.DoUnload().Invoke(nullObj, null) + Instance.I.doUnload.Invoke(nullObj, null) let head = "Coverage statistics flushing took " @@ -1687,13 +1763,22 @@ module AltCoverTests = Instance.I.Trace <- save Instance.supervision <- false AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath - Adapter.VisitsClear() + AltCoverCoreTests.VisitsClear() Console.SetOut saved Directory.SetCurrentDirectory(here) AltCoverCoreTests.maybeIOException (fun () -> Directory.Delete(unique)))) getMyMethodName "<=" + let internal doFlush (visits, format, report, output) = + let output' = + if System.String.IsNullOrEmpty output then + null + else + output + + Counter.DoFlushFile(ignore, (fun _ _ -> ()), true, visits, format, report, output') + [] let FlushLeavesExpectedTracesWhenDiverted () = let saved = Console.Out @@ -1747,7 +1832,7 @@ module AltCoverTests = visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - Adapter.doFlush (visits, ReportFormat.NCover, reportFile, outputFile) + doFlush (visits, ReportFormat.NCover, reportFile, outputFile) |> ignore use worker' = @@ -1831,7 +1916,7 @@ module AltCoverTests = visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - Adapter.doFlush (visits, ReportFormat.NCover, reportFile, outputFile) + doFlush (visits, ReportFormat.NCover, reportFile, outputFile) |> ignore use worker' = @@ -1906,7 +1991,7 @@ module AltCoverTests = visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - Adapter.doFlush ( + doFlush ( visits, ReportFormat.NCover ||| ReportFormat.Zipped, reportFile, @@ -1997,7 +2082,7 @@ module AltCoverTests = visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - Adapter.doFlush ( + doFlush ( visits, ReportFormat.NCover ||| ReportFormat.Zipped, reportFile, @@ -2070,12 +2155,7 @@ module AltCoverTests = visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - Adapter.doFlush ( - visits, - ReportFormat.NCover ||| ReportFormat.Zipped, - reportFile, - null - ) + doFlush (visits, ReportFormat.NCover ||| ReportFormat.Zipped, reportFile, null) |> ignore Assert.That(reportFile |> File.Exists |> not) @@ -2092,7 +2172,7 @@ module AltCoverTests = let ZipFlushLeavesExpectedTraces () = getMyMethodName "=>" - lock Adapter.Lock (fun () -> + lock Instance.I.visits (fun () -> Instance.I.isRunner <- false Instance.CoverageFormat <- ReportFormat.NCover ||| ReportFormat.Zipped @@ -2108,10 +2188,10 @@ module AltCoverTests = Path.Combine(where, Guid.NewGuid().ToString()) let save = Instance.I.Trace - Instance.I.Trace <- Adapter.makeNullTrace null + Instance.I.Trace <- Tracer.Create null try - Adapter.VisitsClear() + AltCoverCoreTests.VisitsClear() use stdout = new StringWriter() Console.SetOut stdout Directory.CreateDirectory(unique) |> ignore @@ -2146,14 +2226,14 @@ module AltCoverTests = [ 0..9 ] |> Seq.iter (fun i -> - Adapter.VisitsAdd( + AltCoverCoreTests.VisitsAdd( "f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", i, (int64 (i + 1)) )) let nullObj: obj = null - Adapter.DoExit().Invoke(nullObj, null) + Instance.I.doExit.Invoke(nullObj, null) let head = "Coverage statistics flushing took " @@ -2204,7 +2284,7 @@ module AltCoverTests = Instance.I.Trace <- save AltCoverCoreTests.maybeDeleteFile Instance.ReportFilePath AltCoverCoreTests.maybeDeleteFile (Instance.ReportFilePath + ".zip") - Adapter.VisitsClear() + AltCoverCoreTests.VisitsClear() Console.SetOut saved Directory.SetCurrentDirectory(here) AltCoverCoreTests.maybeIOException (fun () -> Directory.Delete(unique)))) diff --git a/AltCover.Recorder.Tests/Tracer.Tests.cs b/AltCover.Recorder.Tests/Tracer.Tests.cs deleted file mode 100644 index 8b79b76e..00000000 --- a/AltCover.Recorder.Tests/Tracer.Tests.cs +++ /dev/null @@ -1,112 +0,0 @@ -#if !NET472 -#if NET20 -namespace Tests.Recorder.Clr2 -#else - -namespace Tests.Recorder.Core -#endif -#else -namespace Tests.Recorder.Clr4 -#endif - -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.IO; - using System.IO.Compression; - using System.Reflection; - using System.Runtime.InteropServices; - using AltCover.Recorder; - using NUnit.Framework; - using NUnit.Framework.Constraints; - using static NUnit.Framework.Constraints.Tolerance; - - //[] - public static class AltCoverCoreTests - { - private static void maybeIOException(Action f) - { - try { f(); } - catch (IOException) - { } - } - - private static void maybeDeleteFile(string f) - { - if (File.Exists(f)) - { - File.Delete(f); - } - } - - private static void maybeReraise(Action f, Action g) - { - try { f(); } - catch (Exception) - { - g(); - throw; - } - } - - private static void ignore() - { } - - [Test] - public static void ExcerciseItAll() - { - var where = - Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - - var unique = - Path.Combine(Path.Combine(where, Guid.NewGuid().ToString()), "nonesuch.txt"); - - maybeDeleteFile(unique); - maybeIOException(() => { maybeReraise(() => { File.Delete(unique); }, ignore); }); - maybeIOException(() => { maybeReraise(() => { throw new IOException(); }, ignore); }); - } - - [Test] - public static void WillNotConnectSpontaneously() - { - var where = - Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - - var unique = Path.Combine(where, Guid.NewGuid().ToString()); - - var client = Tracer.Create(unique); - Action close = (() => client.Close()); - - maybeReraise( - () => - { - client = client.OnStart(); - Assert.True(!client.IsConnected); - close(); - }, close); - } - - [Test] - public static void ValidTokenWillConnect() - { - var where = - Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - - var unique = Path.Combine(where, Guid.NewGuid().ToString()); - - using (var stream = File.Create(unique)) - { } - - var client = Tracer.Create(unique); - - try - { - client = client.OnStart(); - Assert.True(client.IsConnected); - } - finally - { client.Close(); } - } - } -} \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Tracer.Tests.fs b/AltCover.Recorder.Tests/Tracer.Tests.fs index 3b0cd7ea..97b572fa 100644 --- a/AltCover.Recorder.Tests/Tracer.Tests.fs +++ b/AltCover.Recorder.Tests/Tracer.Tests.fs @@ -37,6 +37,89 @@ module AltCoverCoreTests = g () reraise () + let internal init (n, l) = + let tmp = PointVisit.Create() + tmp.Count <- n + + tmp.Tracks.AddRange l + tmp + + let internal newBoth (time, call) = Both(Pair.Create(time, call)) + + let VisitsClear () = + Instance.I.Clear() + Counter.branchVisits <- 0L + Counter.totalVisits <- 0L + + let SamplesClear () = + Instance.I.samples <- Instance.I.MakeSamples() + + let private reset () = + Instance.I.isRunner <- false + VisitsClear() + SamplesClear() + + let ModuleReset (m: string array) = + Instance.Modules <- m + reset () + + let HardReset () = + Instance.Modules <- [| System.String.Empty |] + reset () + + let VisitsSeq () = + Instance.I.visits + |> Seq.cast>> + + let VisitImplMethod (moduleId, hitPointId, mId) = + Instance.I.VisitImpl(moduleId, hitPointId, (Call mId)) + + let internal prepareName name = + if name |> Instance.I.visits.ContainsKey |> not then + let entry = Dictionary() + Instance.I.visits.Add(name, entry) + + let VisitsAdd (name, line, number) = + prepareName name + let v = init (number, []) + Instance.I.visits.[name].Add(line, v) + + let VisitsAddTrack (name, line, number) = + prepareName name + let v1 = init (number, [ Call 17; Call 42 ]) + Instance.I.visits.[name].Add(line, v1) + + let v2 = + init ( + (number + 1L), + [ Time(17L) + Both(Pair.Create(42L, 23)) ] + ) + + Instance.I.visits.[name].Add(line + 1, v2) + + type Untable = + | Name of string + | Place of int + | Token of Track + + let internal untable t = + let r = List() + //let r = System.Collections.ArrayList() + + let n, p, (t': Track) = t + + match t' with + | :? Table as d -> + r.Add(Untable.Name n) |> ignore + r.Add(Untable.Place p) |> ignore + r.Add(Untable.Token d) |> ignore + | _ -> () + + r + + //======================================= + [] let ExcerciseItAll () = let where = @@ -106,9 +189,7 @@ module AltCoverCoreTests = (id, strike, match enum tag with - //| Tag.Time -> Adapter.Time <| formatter.ReadInt64() - | Tag.Call -> (Adapter.asCall <| formatter.ReadInt32()) :> Track - //| Tag.Both -> Adapter.NewBoth((formatter.ReadInt64()), (formatter.ReadInt32())) + | Tag.Call -> (Call <| formatter.ReadInt32()) :> Track | Tag.Table -> Assert.True((id = String.Empty)) Assert.True((strike = 0)) @@ -131,7 +212,7 @@ module AltCoverCoreTests = if pts > 0 then let p = formatter.ReadInt32() let n = formatter.ReadInt64() - let pv = Adapter.init (n, []) + let pv = init (n, []) t.[m].Add(p, pv) // [] @@ -140,17 +221,14 @@ module AltCoverCoreTests = match enum track with | Tag.Time -> - pv.Tracks.Add(Adapter.time <| formatter.ReadInt64()) + pv.Tracks.Add(Time <| formatter.ReadInt64()) tracking () | Tag.Call -> - pv.Tracks.Add(Adapter.asCall <| formatter.ReadInt32()) + pv.Tracks.Add(Call <| formatter.ReadInt32()) tracking () | Tag.Both -> pv.Tracks.Add( - Adapter.newBoth ( - (formatter.ReadInt64()), - (formatter.ReadInt32()) - ) + newBoth ((formatter.ReadInt64()), (formatter.ReadInt32())) ) tracking () @@ -164,8 +242,8 @@ module AltCoverCoreTests = sequencePoint points ``module`` () - Adapter.table t - | _ -> Adapter.asNull ()) + Table t + | _ -> Null()) |> hits.Add sink ()) @@ -187,7 +265,7 @@ module AltCoverCoreTests = let tag = unique + ".acv" let expected = - [ ("name", 23, Adapter.asNull ()) ] + [ ("name", 23, Null() :> Track) ] do use stream = File.Create tag @@ -197,11 +275,11 @@ module AltCoverCoreTests = let mutable client = Tracer.Create tag try - Adapter.HardReset() + HardReset() Instance.I.Trace <- client.OnStart() Assert.True(Instance.I.Trace.IsConnected, "connection failed") Instance.I.isRunner <- true - Adapter.VisitImplNone("name", 23) + Instance.I.VisitImpl("name", 23, Null()) finally Instance.I.Trace.Close() Instance.I.Trace.Close() @@ -214,21 +292,19 @@ module AltCoverCoreTests = let results = readResults stream |> Seq.toList - Adapter.VisitsSeq() - |> Seq.cast>> + VisitsSeq() |> Seq.iter (fun v -> Assert.That(v.Value, Is.Empty, sprintf "Unexpected local write %A" v)) Assert.That( - Adapter.VisitsSeq() |> Seq.length, + VisitsSeq() |> Seq.length, Is.EqualTo 3, - sprintf "unexpected local write %A" - <| Adapter.VisitsSeq() + sprintf "unexpected local write %A" <| VisitsSeq() ) Assert.True((results = expected), sprintf "unexpected result %A" results) finally - Adapter.HardReset() + HardReset() [] let VisitShouldSignalTrack () = @@ -249,19 +325,18 @@ module AltCoverCoreTests = t.["name"] <- Dictionary() let expect23 = - [ Adapter.asCall 17; Adapter.asCall 42 ] - |> Seq.cast + [ Call 17; Call 42 ] |> Seq.cast let expect24 = - [ (Adapter.time 17L) :> Track - (Adapter.newBoth (42L, 23)) :> Track ] + [ (Time 17L) :> Track + (newBoth (42L, 23)) :> Track ] - t.["name"].[23] <- Adapter.init (1L, expect23) - t.["name"].[24] <- Adapter.init (2L, expect24) + t.["name"].[23] <- init (1L, expect23) + t.["name"].[24] <- init (2L, expect24) let expected = - [ (String.Empty, 0, Adapter.table t) - ("name", 23, Adapter.asCall 5) ] + [ (String.Empty, 0, (Table t) :> Track) + ("name", 23, Call 5) ] do use stream = File.Create tag @@ -275,9 +350,9 @@ module AltCoverCoreTests = Assert.True(Instance.I.Trace.IsConnected, "connection failed") Instance.I.isRunner <- true - Adapter.HardReset() - Adapter.VisitsAddTrack("name", 23, 1L) - Adapter.VisitImplMethod("name", 23, 5) + HardReset() + VisitsAddTrack("name", 23, 1L) + VisitImplMethod("name", 23, 5) finally Instance.I.isRunner <- false Instance.I.Trace.Close() @@ -288,22 +363,17 @@ module AltCoverCoreTests = let results = readResults stream - Assert.True( - ("no", 0, Adapter.asNull ()) - |> Adapter.untable - |> Seq.isEmpty - ) + Assert.True(("no", 0, Null()) |> untable |> Seq.isEmpty) - Adapter.VisitsSeq() + VisitsSeq() |> Seq.cast>> |> Seq.iter (fun v -> Assert.That(v.Value, Is.Empty, sprintf "Unexpected local write %A" v)) Assert.That( - Adapter.VisitsSeq() |> Seq.length, + VisitsSeq() |> Seq.length, Is.EqualTo 3, - sprintf "unexpected local write %A" - <| Adapter.VisitsSeq() + sprintf "unexpected local write %A" <| VisitsSeq() ) Assert.True(results.Count = 2) @@ -314,15 +384,19 @@ module AltCoverCoreTests = ) let [ n'; p'; d' ] = - results - |> Seq.head - |> Adapter.untable - |> Seq.toList + results |> Seq.head |> untable |> Seq.toList + + let n = + match n' with + | Untable.Name x -> x - let n = n' :?> String - let p = p' :?> int + let p = + match p' with + | Untable.Place x -> x - let d = (d' :?> Table).Value + let d = + match d' with + | Untable.Token x -> (x :?> Table).Value Assert.True(n |> Seq.isEmpty) Assert.True((p = 0)) @@ -367,7 +441,7 @@ module AltCoverCoreTests = Assert.True((left2 = right2)) finally - Adapter.HardReset() + HardReset() [] let FlushShouldTidyUp () = // also throw a bone to OpenCover 615 @@ -390,17 +464,17 @@ module AltCoverCoreTests = let client = Tracer.Create unique let expected = - [ ("name", client.GetHashCode(), Adapter.asNull ()) ] + [ ("name", client.GetHashCode(), Null() :> Track) ] try - Adapter.HardReset() + HardReset() Instance.I.Trace <- client.OnStart() Assert.That(Instance.I.Trace.Equals client, Is.False) Assert.That(Instance.I.Trace.Equals expected, Is.False) Assert.True(Instance.I.Trace.IsConnected, "connection failed") let (a, b, c) = expected |> Seq.head - Adapter.tracePush (a, b, c) + Instance.I.Trace.Push(a, b, c) Instance.FlushFinish() finally Instance.I.Trace.Close() @@ -413,18 +487,17 @@ module AltCoverCoreTests = let results = stream |> readResults |> Seq.toList - Adapter.VisitsSeq() + VisitsSeq() |> Seq.cast>> |> Seq.iter (fun v -> Assert.That(v.Value, Is.Empty, sprintf "Unexpected local write %A" v)) Assert.That( - Adapter.VisitsSeq() |> Seq.length, + VisitsSeq() |> Seq.length, Is.EqualTo 3, - sprintf "unexpected local write %A" - <| Adapter.VisitsSeq() + sprintf "unexpected local write %A" <| VisitsSeq() ) Assert.True((results = expected), sprintf "unexpected result %A" results) finally - Adapter.VisitsClear() \ No newline at end of file + VisitsClear() \ No newline at end of file diff --git a/AltCover.Recorder.sln b/AltCover.Recorder.sln index 6116022f..d6ea40bd 100644 --- a/AltCover.Recorder.sln +++ b/AltCover.Recorder.sln @@ -28,6 +28,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Items", "Build Items" Build\get-token.fsx = Build\get-token.fsx global.json = global.json Build\Infrastructure.snk = Build\Infrastructure.snk + Build\merge-coverage.ps1 = Build\merge-coverage.ps1 Build\msbuildtest.proj = Build\msbuildtest.proj OutputBuildProps.props = OutputBuildProps.props OutputBuildTargets.props = OutputBuildTargets.props diff --git a/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj b/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj index 3d2b83ee..425492cf 100644 --- a/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj +++ b/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj @@ -11,7 +11,7 @@ - TRACE;DEBUG;ALTCOVER_TEST;$(ExtraDefines) + TRACE;DEBUG;ALTCOVER_TEST;RECORDER2;$(ExtraDefines) TRACE;RELEASE;ALTCOVER_TEST;$(ExtraDefines) @@ -25,11 +25,12 @@ AssemblyVersion.fs - - + + + diff --git a/AltCover.Visualizer.Tests/AltCover.Visualizer.Tests.fsproj b/AltCover.Visualizer.Tests/AltCover.Visualizer.Tests.fsproj index 7e9837aa..f650d406 100644 --- a/AltCover.Visualizer.Tests/AltCover.Visualizer.Tests.fsproj +++ b/AltCover.Visualizer.Tests/AltCover.Visualizer.Tests.fsproj @@ -14,7 +14,7 @@ TRACE;$(GlobalDefineConstants) - + 988 diff --git a/Build/Build.fsproj b/Build/Build.fsproj index c06e4853..37e13afd 100644 --- a/Build/Build.fsproj +++ b/Build/Build.fsproj @@ -1,4 +1,8 @@  + + + NU1902,NU1903,NU1904 + diff --git a/Build/DriveApi.fsproj b/Build/DriveApi.fsproj index 1269bde1..f31ff180 100644 --- a/Build/DriveApi.fsproj +++ b/Build/DriveApi.fsproj @@ -3,7 +3,7 @@ Exe net8.0 - MSB3243 + MSB3243;NU1902,NU1903,NU1904 diff --git a/Build/Setup.fsproj b/Build/Setup.fsproj index 108a81cf..38fc25bf 100644 --- a/Build/Setup.fsproj +++ b/Build/Setup.fsproj @@ -1,5 +1,9 @@  + + NU1902,NU1903,NU1904 + + diff --git a/Samples/Sample18/Sample18.fsproj b/Samples/Sample18/Sample18.fsproj index b2b15268..9c6249cd 100644 --- a/Samples/Sample18/Sample18.fsproj +++ b/Samples/Sample18/Sample18.fsproj @@ -7,7 +7,7 @@ portable - + 988 diff --git a/fullbuild.ps1 b/fullbuild.ps1 new file mode 100644 index 00000000..11b86892 --- /dev/null +++ b/fullbuild.ps1 @@ -0,0 +1,3 @@ +dotnet tool restore +dotnet run --project .\Build\setup.fsproj +dotnet run --project .\Build\build.fsproj \ No newline at end of file From ef56594a65ea5c7126092ea83cf4403a30fa9c81 Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 22 Jul 2024 10:07:36 +0100 Subject: [PATCH 90/91] This can now be omitted as default is at least this good. --- Samples/Sample21/Sample21.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/Samples/Sample21/Sample21.csproj b/Samples/Sample21/Sample21.csproj index 02cf9157..b37d6c9d 100644 --- a/Samples/Sample21/Sample21.csproj +++ b/Samples/Sample21/Sample21.csproj @@ -3,7 +3,6 @@ net8.0;net472 - 8.0 false From 7c78865f93d393763f3cf292986efbfe35b489cb Mon Sep 17 00:00:00 2001 From: SteveGilham Date: Mon, 22 Jul 2024 10:43:42 +0100 Subject: [PATCH 91/91] [skip ci] Update release notes --- ReleaseNotes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index d22db2e7..57404968 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 31) +* [ADVISORY] the Fake.build related assemblies (in the `altcover.api` and `altcover.fake` packages), and the Avalonia 0.10-based visualizer, rely on components with known vulnerabilities. The Fake.build project appears nigh-moribund so has not released an update, whereas Avalonia 11 completely rewrites all the earlier APIs and has not documented anything to assist in the rewrite of the application. +* [BUGFIX] Issue #197 - correctly split file paths in the Cobertura output +* [NET9 preparation] Recode the recorder into C# as compiler/build target changes in F#9 make maintaing net2.0 compatibility in F# too much bother. # 8.8.74 (Habu series release 30) * [BUGFIX] Issue #222 - distinguish methods differing only in number of generic parameters (JSON and cobertura in particular, but with small changes for all all output formats)