diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 490aff5fb..590a70919 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "dotnet-reportgenerator-globaltool": { - "version": "4.8.13", + "version": "5.0.0", "commands": [ "reportgenerator" ] @@ -27,7 +27,7 @@ ] }, "dotnet-fsharplint": { - "version": "0.20.2", + "version": "0.21.0", "commands": [ "dotnet-fsharplint" ] diff --git a/AltCover.Api.Tests/AltCover.Api.Tests.fsproj b/AltCover.Api.Tests/AltCover.Api.Tests.fsproj index b1561e51e..f7e4049ba 100644 --- a/AltCover.Api.Tests/AltCover.Api.Tests.fsproj +++ b/AltCover.Api.Tests/AltCover.Api.Tests.fsproj @@ -7,13 +7,8 @@ false Exe Library - $(AssemblySearchPaths);{GAC} - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk DEBUG;TRACE - Major @@ -72,7 +67,7 @@ - + diff --git a/AltCover.Api.Tests/FSApiTests.fs b/AltCover.Api.Tests/FSApiTests.fs index 177b616c6..a134c7207 100644 --- a/AltCover.Api.Tests/FSApiTests.fs +++ b/AltCover.Api.Tests/FSApiTests.fs @@ -161,7 +161,10 @@ module FSApiTests = let doc = XDocument.Load(stream) use stream2 = new MemoryStream() CoverageFormats.ConvertToLcov doc stream2 - use stream2a = new MemoryStream(stream2.GetBuffer(), 0, int stream2.Length) + + use stream2a = + new MemoryStream(stream2.GetBuffer(), 0, int stream2.Length) + use rdr = new StreamReader(stream2a) let result = @@ -190,7 +193,10 @@ module FSApiTests = let doc = XDocument.Load(stream) use stream2 = new MemoryStream() CoverageFormats.ConvertToLcov doc stream2 - use stream2a = new MemoryStream(stream2.GetBuffer(), 0, int stream2.Length) + + use stream2a = + new MemoryStream(stream2.GetBuffer(), 0, int stream2.Length) + use rdr = new StreamReader(stream2a) let result = @@ -252,8 +258,8 @@ module FSApiTests = .Replace('\r', '\u00FF') .Replace('\n', '\u00FF') .Replace("\u00FF\u00FF", "\u00FF") - .Replace("8.12", "8.13") // CRAP score rounding - .Replace("4.12", "4.13") // CRAP score rounding + .Replace("8.12", "8.13") // CRAP score rounding + .Replace("4.12", "4.13") // CRAP score rounding .Trim([| '\u00FF' |]) = expected .Replace('\r', '\u00FF') .Replace('\n', '\u00FF') @@ -309,7 +315,7 @@ module FSApiTests = .Trim([| '\u00FF' |]) @> [] - let JsonFromCoverletShouldHaveBranchExitValuesOK() = + let JsonFromCoverletShouldHaveBranchExitValuesOK () = use stream = Assembly .GetExecutingAssembly() @@ -319,8 +325,9 @@ module FSApiTests = use reader = new StreamReader(stream) reader.ReadToEnd() - let result = "\u00FF" + - (OpenCover.JsonToXml doc).ToString() + let result = + "\u00FF" + + (OpenCover.JsonToXml doc).ToString() use stream3 = Assembly @@ -613,8 +620,10 @@ module FSApiTests = use rdr = new StreamReader(mstream2) let result = - rdr.ReadToEnd().Replace("\r", String.Empty) - .Replace("ID0ES", "ID0ET") // flakiness in label autogenerator + rdr + .ReadToEnd() + .Replace("\r", String.Empty) + .Replace("ID0ES", "ID0ET") // flakiness in label autogenerator use stream2 = Assembly @@ -687,6 +696,7 @@ module FSApiTests = // fix up file path let exe = Path.Combine(SolutionRoot.location, "AltCover.Tests/SimpleMix.exe") + doc.Descendants("ModulePath".X) |> Seq.iter (fun x -> x.Value <- exe |> Canonical.canonicalPath) @@ -735,6 +745,9 @@ module FSApiTests = Visitor.visit visitors [ { AssemblyPath = sample + Identity = + { Assembly = String.Empty + Configuration = String.Empty } Destinations = [] } ] let document = @@ -758,12 +771,12 @@ module FSApiTests = let exe = Path.Combine(SolutionRoot.location, "AltCover.Tests/SimpleMix.exe") - let document = - XDocument.Load stream + let document = XDocument.Load stream let now = DateTime.UtcNow.ToLongDateString() let rewrite = CoverageFormats.ConvertFromNCover document [ exe ] + rewrite.Descendants("ModuleTime".X) |> Seq.iter (fun x -> x.Value <- now) @@ -781,12 +794,16 @@ module FSApiTests = use stream2 = Assembly .GetExecutingAssembly() - .GetManifestResourceStream("AltCover.Api.Tests.OpenCoverFromNCoverWithPartials.xml") + .GetManifestResourceStream( + "AltCover.Api.Tests.OpenCoverFromNCoverWithPartials.xml" + ) use rdr2 = new StreamReader(stream2) let doc2 = XDocument.Load rdr2 + doc2.Descendants("ModulePath".X) |> Seq.iter (fun x -> x.Value <- exe |> Canonical.canonicalPath) + doc2.Descendants("ModuleTime".X) |> Seq.iter (fun x -> x.Value <- now) @@ -797,9 +814,7 @@ module FSApiTests = use rdr3 = new StreamReader(stream3) let expected = - rdr3 - .ReadToEnd() - .Replace("\r", String.Empty) + rdr3.ReadToEnd().Replace("\r", String.Empty) //printfn "%A" result NUnit.Framework.Assert.That(result, NUnit.Framework.Is.EqualTo expected) @@ -903,7 +918,10 @@ module FSApiTests = let cob = CoverageFormats.ConvertToCobertura doc use stream2 = new MemoryStream() cob.Save stream2 - use stream2a = new MemoryStream(stream2.GetBuffer(), 0, int stream2.Length) + + use stream2a = + new MemoryStream(stream2.GetBuffer(), 0, int stream2.Length) + use rdr = new StreamReader(stream2a) let result = @@ -953,13 +971,17 @@ module FSApiTests = let cob = CoverageFormats.ConvertToCobertura doc use stream2 = new MemoryStream() cob.Save stream2 - use stream2a = new MemoryStream(stream2.GetBuffer(), 0, int stream2.Length) + + use stream2a = + new MemoryStream(stream2.GetBuffer(), 0, int stream2.Length) + use rdr = new StreamReader(stream2a) let result = - rdr.ReadToEnd() - .Replace("\r", String.Empty) - .Replace("\\", "/") + rdr + .ReadToEnd() + .Replace("\r", String.Empty) + .Replace("\\", "/") //printfn "FSApi.NCoverToCobertura\r\n%s" result @@ -1346,7 +1368,12 @@ module FSApiTests = let doc2 = XDocument.Load stream2 - let merge = AltCover.OpenCover.Merge [ doc1; doc2; doc1; doc2 ] + let merge = + AltCover.OpenCover.Merge [ doc1 + doc2 + doc1 + doc2 ] + let summary = merge.Root.Element(XName.Get "Summary") //printfn "%A" merge diff --git a/AltCover.Api.Tests/Program.fs b/AltCover.Api.Tests/Program.fs index d29c4a97c..b634d1397 100644 --- a/AltCover.Api.Tests/Program.fs +++ b/AltCover.Api.Tests/Program.fs @@ -13,23 +13,30 @@ module ExpectoMain = Tests.FSApiTests.PostprocessShouldRestoreBranchOnlyOpenCoverState, "FSApiTests.PostprocessShouldRestoreBranchOnlyOpenCoverState" Tests.FSApiTests.JsonToOpenCover, "FSApiTests.JsonToOpenCover" - Tests.FSApiTests.JsonWithPartialsToOpenCover, "FSApiTests.JsonWithPartialsToOpenCover" - Tests.FSApiTests.JsonFromCoverletShouldHaveBranchExitValuesOK, "FSApiTests.JsonFromCoverletShouldHaveBranchExitValuesOK" + Tests.FSApiTests.JsonWithPartialsToOpenCover, + "FSApiTests.JsonWithPartialsToOpenCover" + Tests.FSApiTests.JsonFromCoverletShouldHaveBranchExitValuesOK, + "FSApiTests.JsonFromCoverletShouldHaveBranchExitValuesOK" Tests.FSApiTests.OpenCoverToJson, "FSApiTests.OpenCoverToJson" - Tests.FSApiTests.OpenCoverWithPartialsToJson, "FSApiTests.OpenCoverWithPartialsToJson" + Tests.FSApiTests.OpenCoverWithPartialsToJson, + "FSApiTests.OpenCoverWithPartialsToJson" Tests.FSApiTests.OpenCoverToLcov, "FSApiTests.OpenCoverToLcov" - Tests.FSApiTests.OpenCoverWithPartialsToLcov, "FSApiTests.OpenCoverWithPartialsToLcov" + Tests.FSApiTests.OpenCoverWithPartialsToLcov, + "FSApiTests.OpenCoverWithPartialsToLcov" Tests.FSApiTests.OpenCoverToBarChart, "FSApiTests.OpenCoverToBarChart" Tests.FSApiTests.OpenCoverToNCover, "FSApiTests.OpenCoverToNCover" - Tests.FSApiTests.OpenCoverWithPartialsToNCover, "FSApiTests.OpenCoverWithPartialsToNCover" + Tests.FSApiTests.OpenCoverWithPartialsToNCover, + "FSApiTests.OpenCoverWithPartialsToNCover" Tests.FSApiTests.OpenCoverFromNCover, "FSApiTests.OpenCoverFromNCover" - Tests.FSApiTests.OpenCoverFromNCoverWithPartials, "FSApiTests.OpenCoverFromNCoverWithPartials" + Tests.FSApiTests.OpenCoverFromNCoverWithPartials, + "FSApiTests.OpenCoverFromNCoverWithPartials" Tests.FSApiTests.FormatsConvertToXmlDocument, "FSApiTests.FormatsConvertToXmlDocument" Tests.FSApiTests.FormatsConvertToXDocument, "FSApiTests.FormatsConvertToXDocument" Tests.FSApiTests.FormatsRoundTripSimply, "FSApiTests.FormatsRoundTripSimply" Tests.FSApiTests.NCoverToCobertura, "FSApiTests.NCoverToCobertura" - Tests.FSApiTests.NCoverWithPartialsToCobertura, "FSApiTests.NCoverWithPartialsToCobertura" + Tests.FSApiTests.NCoverWithPartialsToCobertura, + "FSApiTests.NCoverWithPartialsToCobertura" Tests.FSApiTests.NCoverToJson, "FSApiTests.NCoverToJson" Tests.FSApiTests.NCoverWithPartialsToJson, "FSApiTests.NCoverWithPartialsToJson" Tests.FSApiTests.NCoverToJsonWithEmbeds, "FSApiTests.NCoverToJsonWithEmbeds" diff --git a/AltCover.Avalonia.FuncUI/AltCover.Avalonia.FuncUI.fsproj b/AltCover.Avalonia.FuncUI/AltCover.Avalonia.FuncUI.fsproj index c1eeeb210..1bbbb7494 100644 --- a/AltCover.Avalonia.FuncUI/AltCover.Avalonia.FuncUI.fsproj +++ b/AltCover.Avalonia.FuncUI/AltCover.Avalonia.FuncUI.fsproj @@ -8,34 +8,13 @@ false True altcover.visualizer - true AVALONIA - $(ProjectDir)..\_Binaries/$(AssemblyName).FuncUI/$(Configuration)+$(Platform)/ - $(ProjectDir)..\_Intermediate/$(AssemblyName).FuncUI/$(Configuration)+$(Platform)/ - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk - Major - false - - - - false - false - - - true - true TRACE;DEBUG;CODE_ANALYSIS;$(GlobalDefineConstants) - true - 5 - true - - 52 - true TRACE;$(GlobalDefineConstants) diff --git a/AltCover.Avalonia/AltCover.Avalonia.fsproj b/AltCover.Avalonia/AltCover.Avalonia.fsproj index 41da1f31c..9602c37df 100644 --- a/AltCover.Avalonia/AltCover.Avalonia.fsproj +++ b/AltCover.Avalonia/AltCover.Avalonia.fsproj @@ -5,39 +5,17 @@ netcoreapp2.1 AltCover.Visualizer AltCover.Visualizer - false True altcover.visualizer - true - AVALONIA - $(ProjectDir)..\_Binaries/$(AssemblyName).Avalonia/$(Configuration)+$(Platform)/ - $(ProjectDir)..\_Intermediate/$(AssemblyName).Avalonia/$(Configuration)+$(Platform)/ - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk + AVALONIA;$(TOGGLE) True $(ProjectDir)../AltCover.Visualizer/Resource.res - Major - false - - - - false - false - - - true - true TRACE;DEBUG;CODE_ANALYSIS;$(GlobalDefineConstants) - true - 5 - true - - 52 - true TRACE;$(GlobalDefineConstants) diff --git a/AltCover.Avalonia/MainWindow.fs b/AltCover.Avalonia/MainWindow.fs index 1542db99b..a0a5a26d2 100644 --- a/AltCover.Avalonia/MainWindow.fs +++ b/AltCover.Avalonia/MainWindow.fs @@ -23,7 +23,7 @@ type MainWindow() as this = inherit Window() let mutable armed = false let mutable justOpened = String.Empty - let mutable coverageFiles : string list = [] + let mutable coverageFiles: string list = [] let ofd = OpenFileDialog() let iconMaker (x: Stream) = new Bitmap(x) let icons = Icons(iconMaker) @@ -41,15 +41,34 @@ type MainWindow() as this = let notVisited = SolidColorBrush.Parse "#DC143C" // "#F5F5F5"// Crimson on White Smoke let excluded = SolidColorBrush.Parse "#87CEEB" // "#F5F5F5" // Sky Blue on White Smoke - let makeTreeNode leaf name icon = + let makeTreeNode pc leaf name icon = let tree = Image() - tree.Source <- if leaf - then icons.Blank.Force() - else icons.TreeExpand.Force() + + tree.Source <- + if leaf then + icons.Blank.Force() + else + icons.TreeExpand.Force() + tree.Margin <- Thickness.Parse("2") let text = TextBlock() text.Text <- name text.Margin <- Thickness.Parse("2") +#if !VIS_PERCENT + pc |> ignore +#else + let note = TextBlock() + note.Text <- pc + note.HorizontalAlignment <- Avalonia.Layout.HorizontalAlignment.Right + note.VerticalAlignment <- Avalonia.Layout.VerticalAlignment.Bottom + text.VerticalAlignment <- Avalonia.Layout.VerticalAlignment.Bottom + note.Margin <- Thickness.Parse("2") + + let logfont = + LogFont.TryParse(Persistence.readFont ()) |> snd + + note.FontFamily <- FontFamily(logfont.faceName) +#endif let image = Image() image.Source <- icon image.Margin <- Thickness.Parse("2") @@ -57,6 +76,9 @@ type MainWindow() as this = display.Orientation <- Avalonia.Layout.Orientation.Horizontal display.Children.Add tree display.Children.Add image +#if VIS_PERCENT + display.Children.Add note +#endif display.Children.Add text display.Tag <- name display @@ -312,7 +334,8 @@ type MainWindow() as this = } |> Async.Start - with x -> + with + | x -> let caption = Resource.GetResourceString "LoadError" this.ShowMessageBox MessageType.Error caption x.Message @@ -489,7 +512,7 @@ type MainWindow() as this = this.FindControl("Refresh").Click |> Event.map (fun _ -> 0) - let makeNewRow leaf name (anIcon: Lazy) = + let makeNewRow note leaf name (anIcon: Lazy) = let row = TreeViewItem() row.HorizontalAlignment <- Avalonia.Layout.HorizontalAlignment.Left @@ -511,29 +534,30 @@ type MainWindow() as this = row.Tapped |> Event.add - (fun evt -> - row.IsExpanded <- not row.IsExpanded - if not leaf - then - let items = (row.Header :?> StackPanel).Children - items.RemoveAt(0) - let mark = Image() - - mark.Source <- - if row.Items.OfType().Any() then - if row.IsExpanded then - icons.TreeCollapse.Force() - else - icons.TreeExpand.Force() - else - icons.Blank.Force() - - mark.Margin <- Thickness.Parse("2") - items.Insert(0, mark) - evt.Handled <- true) + (fun evt -> + row.IsExpanded <- not row.IsExpanded + + if not leaf then + let items = (row.Header :?> StackPanel).Children + items.RemoveAt(0) + let mark = Image() + + mark.Source <- + if row.Items.OfType().Any() then + if row.IsExpanded then + icons.TreeCollapse.Force() + else + icons.TreeExpand.Force() + else + icons.Blank.Force() + + mark.Margin <- Thickness.Parse("2") + items.Insert(0, mark) + + evt.Handled <- true) row.Items <- List() - row.Header <- makeTreeNode leaf name <| anIcon.Force() + row.Header <- makeTreeNode note leaf name <| anIcon.Force() row select @@ -546,15 +570,18 @@ type MainWindow() as this = let mutable auxModel = { Model = List() Row = null } + let addNode = - fun leaf (context:CoverageTreeContext, TreeViewItem>) icon name (tip : string option) -> - let newrow = makeNewRow leaf name icon - (context.Row.Items :?> List).Add newrow - tip - |> Option.iter(fun text -> - ToolTip.SetTip(newrow, text)) - { context with - Row = newrow } + fun leaf (context: CoverageTreeContext, TreeViewItem>) icon pc name (tip: string option) -> + let newrow = makeNewRow pc leaf name icon + + (context.Row.Items :?> List) + .Add newrow + + tip + |> Option.iter (fun text -> ToolTip.SetTip(newrow, text)) + + { context with Row = newrow } let environment = { Icons = icons @@ -595,20 +622,22 @@ type MainWindow() as this = tree.Items <- auxModel.Model this.UpdateMRU info.FullName true SetXmlNode = - fun name icon tip -> + fun pc name icon tip -> let model = auxModel.Model - let row = makeNewRow false name icon + let row = makeNewRow pc false name icon model.Add row - if tip |> String.IsNullOrWhiteSpace |> not - then ToolTip.SetTip(row, tip) - { Model = model - Row = row } + + if tip |> String.IsNullOrWhiteSpace |> not then + ToolTip.SetTip(row, tip) + + { Model = model; Row = row } AddNode = (addNode false) AddLeafNode = (addNode true) Map = this.PrepareDoubleTap } Dispatcher.UIThread.Post (fun _ -> CoverageFileTree.DoSelected environment index)) + this.FindControl("Program").Text <- "AltCover.Visualizer " + AssemblyVersionInformation.AssemblyFileVersion @@ -633,6 +662,7 @@ type MainWindow() as this = (fun _ -> Avalonia.Dialogs.AboutAvaloniaDialog.OpenBrowser "http://www.github.com/SteveGilham/altcover") + this.FindControl("AboutDetails").Header <- Resource.GetResourceString "AboutDialog.About" diff --git a/AltCover.Cake/AltCover.Cake.csproj b/AltCover.Cake/AltCover.Cake.csproj index f19907017..19ec0b994 100644 --- a/AltCover.Cake/AltCover.Cake.csproj +++ b/AltCover.Cake/AltCover.Cake.csproj @@ -6,32 +6,14 @@ false AltCover.Cake AltCover.Cake - true - $(ProjectDir)../ - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - true - true - - - - false - false - - - true - true + + false TRACE;DEBUG;CODE_ANALYSIS - true - - - true TRACE diff --git a/AltCover.DataCollector/AltCover.DataCollector.csproj b/AltCover.DataCollector/AltCover.DataCollector.csproj index 17777ff52..f5b10dcae 100644 --- a/AltCover.DataCollector/AltCover.DataCollector.csproj +++ b/AltCover.DataCollector/AltCover.DataCollector.csproj @@ -5,25 +5,8 @@ netstandard2.0 AltCover AltCover.DataCollector - false - true - $(ProjectDir)../ - true - $(SolutionDir)\Build\Infrastructure.snk 1701;1702;NU1603 - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - true - true - - - - false - false - - - true - true + diff --git a/AltCover.DotNet/AltCover.DotNet.fsproj b/AltCover.DotNet/AltCover.DotNet.fsproj index 4620d3c94..2d5d75ce7 100644 --- a/AltCover.DotNet/AltCover.DotNet.fsproj +++ b/AltCover.DotNet/AltCover.DotNet.fsproj @@ -5,34 +5,13 @@ netstandard2.0 AltCover.DotNet AltCover.DotNet - false - true RUNNER - $(ProjectDir)../ - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk - - - - false - false - - - true - true TRACE;DEBUG;CODE_ANALYSIS;$(GlobalDefineConstants) - 4 - true - - true - true TRACE;$(GlobalDefineConstants) diff --git a/AltCover.DotNet/DotNet.fs b/AltCover.DotNet/DotNet.fs index d91d3f7a8..52a1084c3 100644 --- a/AltCover.DotNet/DotNet.fs +++ b/AltCover.DotNet/DotNet.fs @@ -12,9 +12,9 @@ open System.Linq module DotNet = type ICLIOptions = interface - abstract member ForceDelete : bool - abstract member FailFast : bool - abstract member ShowSummary : String + abstract member ForceDelete: bool + abstract member FailFast: bool + abstract member ShowSummary: String end [ String.Empty | Abstract a -> a.ShowSummary | Many s -> - match s - |> Seq.map (fun f -> f.ShowSummary) - |> Seq.filter (String.IsNullOrWhiteSpace >> not) - |> Seq.tryHead with - | Some x -> x - | _ -> String.Empty + match s + |> Seq.map (fun f -> f.ShowSummary) + |> Seq.filter (String.IsNullOrWhiteSpace >> not) + |> Seq.tryHead + with + | Some x -> x + | _ -> String.Empty interface ICLIOptions with member self.FailFast = self.FailFast diff --git a/AltCover.Engine/Abstraction.fs b/AltCover.Engine/Abstraction.fs index 4fbc165eb..9b5b1c7af 100644 --- a/AltCover.Engine/Abstraction.fs +++ b/AltCover.Engine/Abstraction.fs @@ -4,6 +4,5 @@ module Abstraction = // abstract away selection based on OS dependencies and other environment constants - let Maybe predicate (result: 'TResult) (alternate: 'TResult) = if predicate - then result - else alternate \ No newline at end of file + let Maybe predicate (result: 'TResult) (alternate: 'TResult) = + if predicate then result else alternate \ No newline at end of file diff --git a/AltCover.Engine/AltCover.Engine.fsproj b/AltCover.Engine/AltCover.Engine.fsproj index 9dc5e3c57..f3620309b 100644 --- a/AltCover.Engine/AltCover.Engine.fsproj +++ b/AltCover.Engine/AltCover.Engine.fsproj @@ -5,32 +5,16 @@ netstandard2.0 AltCover AltCover.Engine - false RUNNER - true - $(ProjectDir)../ - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - --keyfile:$(SolutionDir)Build\Infrastructure.snk - false - false TRACE;DEBUG;CODE_ANALYSIS;$(GlobalDefineConstants) - 4 - true - - 52 - true - true - true TRACE;$(GlobalDefineConstants) @@ -85,10 +69,10 @@ Recorder.snk - + AltCover.Recorder.net20.dll - + AltCover.Recorder.net46.dll diff --git a/AltCover.Engine/Canonical.fs b/AltCover.Engine/Canonical.fs index d80e25254..8ed0d9422 100644 --- a/AltCover.Engine/Canonical.fs +++ b/AltCover.Engine/Canonical.fs @@ -10,15 +10,23 @@ open System.IO [] module internal Canonical = - let canonicalPath (path:string) = + let canonicalPath (path: string) = // Mono+Linux barfs at a path of "/_" without the "file://" prefix - Uri("file://" + (Path.GetFullPath path), UriKind.Absolute).LocalPath + Uri( + "file://" + (Path.GetFullPath path), + UriKind.Absolute + ) + .LocalPath #if !FAKE && !NoCanonicalDirectories - let canonicalDirectory (path:string) = + let canonicalDirectory (path: string) = let last = path |> Seq.last - canonicalPath (if last = Path.DirectorySeparatorChar || - last = Path.AltDirectorySeparatorChar - then path - else path + Path.DirectorySeparatorChar.ToString()) + + canonicalPath ( + if last = Path.DirectorySeparatorChar + || last = Path.AltDirectorySeparatorChar then + path + else + path + Path.DirectorySeparatorChar.ToString() + ) #endif \ No newline at end of file diff --git a/AltCover.Engine/CecilEx.fs b/AltCover.Engine/CecilEx.fs index cadc94a02..b2accd9a9 100644 --- a/AltCover.Engine/CecilEx.fs +++ b/AltCover.Engine/CecilEx.fs @@ -12,16 +12,17 @@ open Mono.Cecil.Cil [] module internal CecilExtension = // workround for old MCS + Cecil 0.11.4 - let pruneLocalScopes(m:MethodDefinition) = - let rec pruneScope (scope:ScopeDebugInformation) = - if scope.IsNotNull - then + let pruneLocalScopes (m: MethodDefinition) = + let rec pruneScope (scope: ScopeDebugInformation) = + if scope.IsNotNull then let scopes = scope.Scopes - if scopes.IsNotNull - then + + if scopes.IsNotNull then scopes - |> Seq.filter(fun subScope -> pruneScope subScope - subScope.Start.IsEndOfMethod) + |> Seq.filter + (fun subScope -> + pruneScope subScope + subScope.Start.IsEndOfMethod) |> Seq.toList |> List.iter (scopes.Remove >> ignore) @@ -61,20 +62,20 @@ module internal CecilExtension = match instruction.OpCode.OperandType with | OperandType.InlineBrTarget | OperandType.ShortInlineBrTarget -> - if instruction.Operand = (oldValue :> Object) then - instruction.Operand <- newValue + if instruction.Operand = (oldValue :> Object) then + instruction.Operand <- newValue // At this point instruction.Operand will be either Operand != oldOperand // or instruction.Operand will be of type Instruction[] // (in other words - it will be a switch operator's operand) | OperandType.InlineSwitch -> - let operands = - instruction.Operand :?> Instruction array - - operands - |> Array.iteri - (fun i x -> - if x = oldValue then - Array.set operands i newValue) + let operands = + instruction.Operand :?> Instruction array + + operands + |> Array.iteri + (fun i x -> + if x = oldValue then + Array.set operands i newValue) | _ -> () let replaceInstructionReferences diff --git a/AltCover.Engine/Cobertura.fs b/AltCover.Engine/Cobertura.fs index a7eed27c5..2e105fd13 100644 --- a/AltCover.Engine/Cobertura.fs +++ b/AltCover.Engine/Cobertura.fs @@ -10,7 +10,7 @@ open System.Globalization "CA1704", Justification = "'Cobertura' is jargon")>] module internal Cobertura = - let internal path : Option ref = ref None + let internal path: Option ref = ref None module internal I = @@ -51,8 +51,10 @@ module internal Cobertura = let internal nCover (report: XDocument) (packages: XElement) = let processSeqPnts document (method: XElement) (lines: XElement) = method.Descendants("seqpnt".X) - |> Seq.filter (fun s -> s.Attribute("excluded".X).Value <> "true" - && s.Attribute("document".X).Value = document) + |> Seq.filter + (fun s -> + s.Attribute("excluded".X).Value <> "true" + && s.Attribute("document".X).Value = document) |> Seq.fold (fun (h, t) s -> let vc = s.Attribute("visitcount".X) @@ -71,7 +73,12 @@ module internal Cobertura = (h + (if vx = "0" then 0 else 1), t + 1)) (0, 0) - let processMethod document (methods: XElement) (hits, total) (key, (signature, method)) = + let processMethod + document + (methods: XElement) + (hits, total) + (key, (signature, method)) + = let mtx = XElement( "method".X, @@ -138,19 +145,23 @@ module internal Cobertura = let extractClasses (``module``: XElement) classes = ``module``.Descendants("method".X) - |> Seq.filter (fun m -> m.Attribute("excluded".X).Value <> "true" - && m.Descendants("seqpnt".X) |> Seq.isEmpty |> not) - - |> Seq.collect (fun method -> - let cname = method.Attribute("class".X).Value - method.Descendants("seqpnt".X) - |> Seq.map (fun s -> s.Attribute("document".X).Value) - |> Seq.distinct - |> Seq.sort - |> Seq.map (fun d -> (cname, d), method)) + |> Seq.filter + (fun m -> + m.Attribute("excluded".X).Value <> "true" + && m.Descendants("seqpnt".X) |> Seq.isEmpty |> not) + + |> Seq.collect + (fun method -> + let cname = method.Attribute("class".X).Value + + method.Descendants("seqpnt".X) + |> Seq.map (fun s -> s.Attribute("document".X).Value) + |> Seq.distinct + |> Seq.sort + |> Seq.map (fun d -> (cname, d), method)) |> Seq.groupBy fst - |> Seq.map (fun (k,s) -> k, s |> Seq.map (fun (k,m) -> m)) - |> Seq.sortBy (fun ((c,d), _) -> c + "\u0000" + d) // short classes sort first + |> Seq.map (fun (k, s) -> k, s |> Seq.map (fun (k, m) -> m)) + |> Seq.sortBy (fun ((c, d), _) -> c + "\u0000" + d) // short classes sort first |> Seq.fold (processClass classes) (0, 0) let processModule (hits, total) (``module``: XElement) = @@ -192,8 +203,12 @@ module internal Cobertura = let branches = owner.Descendants("BranchPoint".X) let b = branches |> Seq.length - let bv = branches |> Seq.filter (fun x -> x.Attribute("vc".X).Value <> "0") - |> Seq.length + + let bv = + branches + |> Seq.filter (fun x -> x.Attribute("vc".X).Value <> "0") + |> Seq.length + let s = valueOf "numSequencePoints" let sv = valueOf "visitedSequencePoints" @@ -210,8 +225,9 @@ module internal Cobertura = copyup "branches-covered" bv target.Attribute("complexity".X).Value <- (summary.Attribute( - "maxCyclomaticComplexity".X - )).Value + "maxCyclomaticComplexity".X + )) + .Value let doBranch bec bev uspid (line: XElement) = let pc = @@ -325,7 +341,12 @@ module internal Cobertura = c + 1, cv + ccplex) - let arrangeMethods (name: String) fileid (methods: XElement) (methodSet: XElement seq) = + let arrangeMethods + (name: String) + fileid + (methods: XElement) + (methodSet: XElement seq) + = methodSet |> Seq.map (fun method -> @@ -352,8 +373,14 @@ module internal Cobertura = |> not) |> Seq.fold (processMethod fileid methods) (0, 0, 0, 0, 0, 0) - let processClass files (classes: XElement) (cvcum, ccum) ((name, fileid), methodSet) = + let processClass + files + (classes: XElement) + (cvcum, ccum) + ((name, fileid), methodSet) + = let document = files |> Map.find fileid + let ``class`` = XElement( "class".X, @@ -364,7 +391,10 @@ module internal Cobertura = classes.Add(``class``) let methods = XElement("methods".X) ``class``.Add(methods) - let (b, bv, s, sv, c, cv) = arrangeMethods name fileid methods methodSet + + let (b, bv, s, sv, c, cv) = + arrangeMethods name fileid methods methodSet + setRate sv s "line-rate" ``class`` setRate bv b "branch-rate" ``class`` setRate cv c "complexity" ``class`` @@ -372,24 +402,31 @@ module internal Cobertura = let processModule files classes (``module``: XElement) = ``module``.Descendants("Method".X) - |> Seq.filter (fun m -> m.Descendants("SequencePoint".X) |> Seq.isEmpty |> not || - m.Descendants("BranchPoint".X) |> Seq.isEmpty |> not) - |> Seq.collect (fun method -> - let cname = (method.Parent.Parent.Descendants("FullName".X) - |> Seq.head) - .Value - [ - method.Descendants("SequencePoint".X) - method.Descendants("BranchPoint".X) - ] - |> Seq.concat - |> Seq.map (fun s -> s.Attribute("fileid".X).Value) - |> Seq.distinct - |> Seq.sort - |> Seq.map (fun d -> (cname, d), method)) + |> Seq.filter + (fun m -> + m.Descendants("SequencePoint".X) + |> Seq.isEmpty + |> not + || m.Descendants("BranchPoint".X) + |> Seq.isEmpty + |> not) + |> Seq.collect + (fun method -> + let cname = + (method.Parent.Parent.Descendants("FullName".X) + |> Seq.head) + .Value + + [ method.Descendants("SequencePoint".X) + method.Descendants("BranchPoint".X) ] + |> Seq.concat + |> Seq.map (fun s -> s.Attribute("fileid".X).Value) + |> Seq.distinct + |> Seq.sort + |> Seq.map (fun d -> (cname, d), method)) |> Seq.groupBy fst - |> Seq.map (fun (k,s) -> k, s |> Seq.map (fun (k,m) -> m)) - |> Seq.sortBy (fun ((c,d), _) -> c + "\u0000" + (files |> Map.find d)) // short classes sort first + |> Seq.map (fun (k, s) -> k, s |> Seq.map (fun (k, m) -> m)) + |> Seq.sortBy (fun ((c, d), _) -> c + "\u0000" + (files |> Map.find d)) // short classes sort first |> Seq.fold (processClass files classes) (0, 0) let lookUpFiles (``module``: XElement) = diff --git a/AltCover.Engine/CommandLine.fs b/AltCover.Engine/CommandLine.fs index cd0440795..d8e5fd11c 100644 --- a/AltCover.Engine/CommandLine.fs +++ b/AltCover.Engine/CommandLine.fs @@ -108,11 +108,11 @@ type internal UsageInfo = Options2: OptionSet } module internal Output = - let mutable internal info : String -> unit = ignore - let mutable internal warn : String -> unit = ignore - let mutable internal echo : String -> unit = ignore - let mutable internal error : String -> unit = ignore - let mutable internal usage : UsageInfo -> unit = ignore + let mutable internal info: String -> unit = ignore + let mutable internal warn: String -> unit = ignore + let mutable internal echo: String -> unit = ignore + let mutable internal error: String -> unit = ignore + let mutable internal usage: UsageInfo -> unit = ignore let internal warnOn x = if x then warn else info @@ -148,8 +148,8 @@ module internal CommandLine = let mutable internal verbosity = 0 let mutable internal help = false - let mutable internal error : string list = [] - let mutable internal exceptions : Exception list = [] + let mutable internal error: string list = [] + let mutable internal exceptions: Exception list = [] let internal dropReturnCode = ref false // ddFlag let internal resources = @@ -218,7 +218,9 @@ module internal CommandLine = proc.BeginErrorReadLine() proc.BeginOutputReadLine() proc.WaitForExitCustom() - proc.ExitCode * (dropReturnCode.Value |> not).ToInt32 + + proc.ExitCode + * (dropReturnCode.Value |> not).ToInt32 let logException store (e: Exception) = error <- e.Message :: error @@ -236,7 +238,7 @@ module internal CommandLine = | :? NotSupportedException as n -> n :> Exception |> (logException store) | :? IOException as i -> i :> Exception |> (logException store) | :? System.Security.SecurityException as s -> - s :> Exception |> (logException store) + s :> Exception |> (logException store) | :? UnauthorizedAccessException as u -> u :> Exception |> (logException store) result @@ -247,16 +249,17 @@ module internal CommandLine = let rec internal doRetry action log limit (rest: int) depth f = try action f - with x -> + with + | x -> match x with | :? IOException | :? System.Security.SecurityException | :? UnauthorizedAccessException -> - if depth < limit then - Threading.Thread.Sleep(rest) - doRetry action log limit rest (depth + 1) f - else - x.ToString() |> log + if depth < limit then + Threading.Thread.Sleep(rest) + doRetry action log limit rest (depth + 1) f + else + x.ToString() |> log | _ -> reraise () @@ -316,7 +319,8 @@ module internal CommandLine = let internal transformCryptographicException f = try f () - with :? CryptographicException as c -> raise ((c.Message, c) |> SecurityException) + with + | :? CryptographicException as c -> raise ((c.Message, c) |> SecurityException) [ Left("UsageError", options) + with + | :? OptionException -> Left("UsageError", options) let internal processHelpOption (parse: Either) = match parse with | Right (_, options) -> - if help then - Left("HelpText", options) - else - parse + if help then + Left("HelpText", options) + else + parse | fail -> fail let internal applyVerbosity () = @@ -408,7 +413,7 @@ module internal CommandLine = reportErrors String.Empty extend Output.usage info - let internal ddFlag (name: string) (flag:bool ref) = + let internal ddFlag (name: string) (flag: bool ref) = (name, (fun (_: string) -> if flag.Value then @@ -426,12 +431,12 @@ module internal CommandLine = match rest |> Seq.toList with | [] -> 0 | cmd :: t -> - let args = t |> CmdLine.fromSeq |> CmdLine.toString + let args = t |> CmdLine.fromSeq |> CmdLine.toString - let cmd' = - [ cmd ] |> CmdLine.fromSeq |> CmdLine.toString + let cmd' = + [ cmd ] |> CmdLine.fromSeq |> CmdLine.toString - I.launch cmd' args toInfo.FullName // Spawn process, echoing asynchronously + I.launch cmd' args toInfo.FullName // Spawn process, echoing asynchronously let internal validateAssembly assembly x = if I.validateFile assembly x then diff --git a/AltCover.Engine/Compatibility.fs b/AltCover.Engine/Compatibility.fs index 052e5eb7c..fb317de6d 100644 --- a/AltCover.Engine/Compatibility.fs +++ b/AltCover.Engine/Compatibility.fs @@ -1,20 +1,35 @@ -namespace AltCover +namespace AltCover open System open System.Diagnostics.CodeAnalysis open System.Net open System.Security.Cryptography +// netstandard 2.0 APIs obsoleted at net 6.0+ + +[] [] module Compatibility = +#if !GUI + [] + let internal sha1Hash () : SHA1 = new SHA1CryptoServiceProvider() :> SHA1 +#endif + [] - let internal sha1Hash () : SHA1 = - new SHA1CryptoServiceProvider() :> SHA1 + let internal createHttp (path: Uri) = + WebRequest.CreateHttp(path) :> WebRequest +#if GUI [] - let internal createHttp (path:Uri) = - WebRequest.CreateHttp(path) :> WebRequest \ No newline at end of file + let internal readAllText (path: Uri) = + use client = new System.Net.WebClient() + client.DownloadString(path) +#endif \ No newline at end of file diff --git a/AltCover.Engine/Filter.fs b/AltCover.Engine/Filter.fs index c9440f91e..df1d9568c 100644 --- a/AltCover.Engine/Filter.fs +++ b/AltCover.Engine/Filter.fs @@ -64,23 +64,23 @@ module internal Filter = let rec internal matchAttribute (name: Regex) f (nameProvider: Object) = (match nameProvider with | :? MethodDefinition as m -> - if m.IsGetter || m.IsSetter then - let owner = - m.DeclaringType.Properties - |> Seq.filter (fun x -> x.GetMethod = m || x.SetMethod = m) - |> Seq.head - - matchAttribute name f owner - else - false + if m.IsGetter || m.IsSetter then + let owner = + m.DeclaringType.Properties + |> Seq.filter (fun x -> x.GetMethod = m || x.SetMethod = m) + |> Seq.head + + matchAttribute name f owner + else + false | _ -> false) || (match nameProvider with | :? ICustomAttributeProvider as attributeProvider -> - attributeProvider.HasCustomAttributes - && attributeProvider.CustomAttributes - |> Seq.cast - |> Seq.exists (fun attr -> name.IsMatch attr.AttributeType.FullName) - |> f + attributeProvider.HasCustomAttributes + && attributeProvider.CustomAttributes + |> Seq.cast + |> Seq.exists (fun attr -> name.IsMatch attr.AttributeType.FullName) + |> f | _ -> false) let internal matchItem<'a> @@ -126,7 +126,8 @@ module internal Filter = ) // (x.ConstructorArguments |> Seq.head).Value match (arg1 :?> SourceConstructFlags) - &&& SourceConstructFlags.KindMask with + &&& SourceConstructFlags.KindMask + with | SourceConstructFlags.SumType | SourceConstructFlags.RecordType -> true | _ -> false) @@ -136,28 +137,28 @@ module internal Filter = match m.IsGetter with | false -> false | _ -> - let owner = - m.DeclaringType.Properties - |> Seq.filter (fun x -> x.GetMethod = m) - |> Seq.head - - if owner.HasCustomAttributes then - owner.CustomAttributes - |> Seq.filter - (fun x -> - x.AttributeType.FullName = "Microsoft.FSharp.Core.CompilationMappingAttribute") - |> Seq.exists - (fun x -> - let arg1 = - Enum.ToObject( - typeof, - x.GetBlob() |> Seq.skip 2 |> Seq.head - ) // (x.ConstructorArguments |> Seq.head).Value - - (arg1 :?> SourceConstructFlags) - &&& SourceConstructFlags.KindMask = SourceConstructFlags.Field) - else - false + let owner = + m.DeclaringType.Properties + |> Seq.filter (fun x -> x.GetMethod = m) + |> Seq.head + + if owner.HasCustomAttributes then + owner.CustomAttributes + |> Seq.filter + (fun x -> + x.AttributeType.FullName = "Microsoft.FSharp.Core.CompilationMappingAttribute") + |> Seq.exists + (fun x -> + let arg1 = + Enum.ToObject( + typeof, + x.GetBlob() |> Seq.skip 2 |> Seq.head + ) // (x.ConstructorArguments |> Seq.head).Value + + (arg1 :?> SourceConstructFlags) + &&& SourceConstructFlags.KindMask = SourceConstructFlags.Field) + else + false mappings && (fieldGetter @@ -205,43 +206,45 @@ module internal Filter = match filter.Scope with | File -> I.matchItem filter.Regex f nameProvider Path.GetFileName | Assembly -> - I.matchItem - filter.Regex - f - nameProvider - (fun assembly -> assembly.Name.Name) + I.matchItem + filter.Regex + f + nameProvider + (fun assembly -> assembly.Name.Name) | Module -> - I.matchItem - filter.Regex - f - nameProvider - (fun ``module`` -> ``module``.Assembly.Name.Name) + I.matchItem + filter.Regex + f + nameProvider + (fun ``module`` -> ``module``.Assembly.Name.Name) | Type -> - I.matchItem - filter.Regex - f - nameProvider - (fun typeDef -> typeDef.FullName) + I.matchItem + filter.Regex + f + nameProvider + (fun typeDef -> typeDef.FullName) | Method -> - I.matchItem - filter.Regex - f - nameProvider - // Interfaces w/implementation have no base type - (fun methodDef -> - let decltype = - methodDef.DeclaringType.BaseType - |> Option.ofObj - |> Option.map (fun x -> x.Name) - |> Option.defaultValue String.Empty - - let name = methodDef.Name - - if decltype.StartsWith("FSharpFunc", StringComparison.Ordinal) - || decltype = "FSharpTypeFunc" then - methodDef.DeclaringType.Name + "." + name - else - name) + I.matchItem + filter.Regex + f + nameProvider + // Interfaces w/implementation have no base type + (fun methodDef -> + let decltype = + methodDef.DeclaringType.BaseType + |> Option.ofObj + |> Option.map (fun x -> x.Name) + |> Option.defaultValue String.Empty + + let name = methodDef.Name + + if + decltype.StartsWith("FSharpFunc", StringComparison.Ordinal) + || decltype = "FSharpTypeFunc" + then + methodDef.DeclaringType.Name + "." + name + else + name) | Attribute -> I.matchAttribute filter.Regex f nameProvider | Path -> I.matchItem filter.Regex f nameProvider canonicalPath diff --git a/AltCover.Engine/Gendarme.fs b/AltCover.Engine/Gendarme.fs index 17ca16ec2..3a81c8c6d 100644 --- a/AltCover.Engine/Gendarme.fs +++ b/AltCover.Engine/Gendarme.fs @@ -43,7 +43,8 @@ module internal Gendarme = match cases |> Seq.head - |> findFirstUnconditionalBranchTarget with + |> findFirstUnconditionalBranchTarget + with | Some unc when unc = operand -> () | _ -> operand |> targets.Add |> ignore @@ -71,38 +72,39 @@ module internal Gendarme = (fun c i -> match i.OpCode.FlowControl with | FlowControl.Branch -> + c + + (Option.ofObj i.Previous + |> Option.map + (fun (previous: Instruction) -> + do + if previous.OpCode.FlowControl = FlowControl.Cond_Branch then + match previous.Operand with + | :? Cil.Instruction as branch -> + if targets.Contains branch then + i |> targets.Add |> ignore + | _ -> () + + previous.OpCode.Code) + |> ``detect ternary pattern``) + | FlowControl.Cond_Branch -> + if i.OpCode = OpCodes.Switch then + accumulateSwitchTargets i targets + c + else + let branch = i.Operand :?> Cil.Instruction + c - + (Option.ofObj i.Previous - |> Option.map + + (Option.ofObj branch.Previous + |> Option.filter (fun (previous: Instruction) -> - do - if previous.OpCode.FlowControl = FlowControl.Cond_Branch then - match previous.Operand with - | :? Cil.Instruction as branch -> - if targets.Contains branch then - i |> targets.Add |> ignore - | _ -> () - - previous.OpCode.Code) - |> ``detect ternary pattern``) - | FlowControl.Cond_Branch -> - if i.OpCode = OpCodes.Switch then - accumulateSwitchTargets i targets - c - else - let branch = i.Operand :?> Cil.Instruction - - c - + (Option.ofObj branch.Previous - |> Option.filter - (fun (previous: Instruction) -> - let pp = previous.Previous - // !previous.Previous.Is (Code.Switch) - // where Is(i, code) => i != null && i.OpCode.Code == code - (pp |> isNull || pp.OpCode.Code <> OpCodes.Switch.Code) - && branch |> targets.Contains |> not) - |> Option.map (fun _ -> 1) - |> Option.defaultValue 0) + let pp = previous.Previous + // !previous.Previous.Is (Code.Switch) + // where Is(i, code) => i != null && i.OpCode.Code == code + (pp |> isNull + || pp.OpCode.Code <> OpCodes.Switch.Code) + && branch |> targets.Contains |> not) + |> Option.map (fun _ -> 1) + |> Option.defaultValue 0) | _ -> c) 1 @@ -114,21 +116,21 @@ module internal Gendarme = m.Body.Instructions |> Seq.cast match instructions - |> Seq.tryFind (fun i -> i.OpCode = OpCodes.Switch) with + |> Seq.tryFind (fun i -> i.OpCode = OpCodes.Switch) + with | None -> - instructions - |> Seq.fold - (fun c i -> - match i.OpCode.FlowControl with - | FlowControl.Cond_Branch -> c + 1 - | FlowControl.Branch -> - c - + (Option.ofObj i.Previous - |> Option.map - (fun (previous: Instruction) -> previous.OpCode.Code) - |> I.``detect ternary pattern``) - | _ -> c) - 1 + instructions + |> Seq.fold + (fun c i -> + match i.OpCode.FlowControl with + | FlowControl.Cond_Branch -> c + 1 + | FlowControl.Branch -> + c + + (Option.ofObj i.Previous + |> Option.map (fun (previous: Instruction) -> previous.OpCode.Code) + |> I.``detect ternary pattern``) + | _ -> c) + 1 | _ -> I.switchCyclomaticComplexity instructions else 1 \ No newline at end of file diff --git a/AltCover.Engine/Instrument.fs b/AltCover.Engine/Instrument.fs index 072b40f39..ef6440af8 100644 --- a/AltCover.Engine/Instrument.fs +++ b/AltCover.Engine/Instrument.fs @@ -111,7 +111,7 @@ type internal InstrumentContext = { InstrumentedAssemblies: string list ModuleId: String RecordingAssembly: AssemblyDefinition - RecorderSource : Stream + RecorderSource: Stream RecordingMethod: MethodDefinition list // initialised once RecordingMethodRef: RecorderRefs // updated each module MethodBody: MethodBody @@ -130,19 +130,87 @@ type internal InstrumentContext = // Module to handle instrumentation visitor module internal Instrument = - let recorderVersion() = + let recorderVersion () = use stream = Assembly .GetExecutingAssembly() .GetManifestResourceStream("AltCover.AltCover.Recorder.net20.dll") + use def = AssemblyDefinition.ReadAssembly stream def.Name.Version.ToString() - let version = recorderVersion() + + let version = recorderVersion () let internal resolutionTable = Dictionary() module internal I = + let prelude = + [ 0x01uy + 0x00uy + 0x02uy + 0x00uy + 0x54uy + 0x0euy + 0x08uy + 0x41uy + 0x73uy + 0x73uy + 0x65uy + 0x6duy + 0x62uy + 0x6cuy + 0x79uy ] + + let interlude = + [ 0x54uy + 0x0euy + 0x0duy + 0x43uy + 0x6fuy + 0x6euy + 0x66uy + 0x69uy + 0x67uy + 0x75uy + 0x72uy + 0x61uy + 0x74uy + 0x69uy + 0x6fuy + 0x6euy ] + + let internal injectInstrumentation + (recorder: AssemblyDefinition) + (assembly: AssemblyEntry) + = + let a = + System.Text.Encoding.ASCII.GetBytes(assembly.Identity.Assembly) + + let c = + System.Text.Encoding.ASCII.GetBytes(assembly.Identity.Configuration) + + let blob = + [| prelude |> List.toArray + [| byte a.Length |] + a + interlude |> List.toArray + [| byte c.Length |] + c |] // slight inefficiency + |> Array.concat + + let attribute = + recorder.MainModule.GetType("AltCover.Recorder.InstrumentationAttribute") + + let constructor = + attribute.GetConstructors() + |> Seq.head + |> assembly.Assembly.MainModule.ImportReference + + let inject = CustomAttribute(constructor, blob) + + assembly.Assembly.CustomAttributes.Add inject + // Locate the method that must be called to register a code point for coverage visit. // param name="assembly">The assembly containing the recorder method // returns>A representation of the method to call to signal a coverage visit. @@ -168,16 +236,16 @@ module internal Instrument = match key with | None -> - assembly.MainModule.Attributes <- - assembly.MainModule.Attributes - &&& (~~~ModuleAttributes.StrongNameSigned) + assembly.MainModule.Attributes <- + assembly.MainModule.Attributes + &&& (~~~ModuleAttributes.StrongNameSigned) - assemblyName.HasPublicKey <- false - assemblyName.PublicKey <- null - assemblyName.PublicKeyToken <- null + assemblyName.HasPublicKey <- false + assemblyName.PublicKey <- null + assemblyName.PublicKeyToken <- null | Some key' -> - assemblyName.HasPublicKey <- true - assemblyName.PublicKey <- key'.PublicKey |> Seq.toArray // sets token implicitly + assemblyName.HasPublicKey <- true + assemblyName.PublicKey <- key'.PublicKey |> Seq.toArray // sets token implicitly // Locate the key, if any, which was used to name this assembly. // param name="name">The name of the assembly @@ -220,7 +288,8 @@ module internal Instrument = try f () assembly - with _ -> + with + | _ -> (assembly :> IDisposable).Dispose() reraise () @@ -229,16 +298,33 @@ module internal Instrument = let internal prepareAssemblyDefinition (definition: AssemblyDefinition) = guard definition - (fun () -> // set the timer interval in ticks + (fun () -> //if monoRuntime |> not then - ProgramDatabase.readSymbols definition + //ProgramDatabase.readSymbols definition definition.Name.Name <- (extractName definition) + ".g" let pair = CoverageParameters.recorderStrongNameKey updateStrongNaming definition pair + definition.MainModule.GetTypes() + |> Seq.iter + (fun t -> + if t.IsPublic + && (not + <| t.FullName.StartsWith("AltCover", StringComparison.Ordinal)) then + t.IsPublic <- false) + + injectInstrumentation + definition + { Assembly = definition + Inspection = Inspections.Ignore + Destinations = [] + Identity = + { Assembly = "AltCover+Recorder+g+" + Configuration = "Uninstrumented++" } } + [ // set the coverage file path and unique token ("get_ReportFile", (fun (w: ILProcessor) -> @@ -312,7 +398,8 @@ module internal Instrument = [] - [] let internal resolveFromNugetCache _ (y: AssemblyNameReference) = let name = y.ToString() @@ -365,17 +452,17 @@ module internal Instrument = match candidate sources with | None -> null | Some x -> - String.Format( - System.Globalization.CultureInfo.CurrentCulture, - CommandLine.resources.GetString "resolved", - y.ToString(), - x - ) - |> (Output.warnOn true) - - let a = AssemblyDefinition.ReadAssembly x - resolutionTable.[name] <- a - a + String.Format( + System.Globalization.CultureInfo.CurrentCulture, + CommandLine.resources.GetString "resolved", + y.ToString(), + x + ) + |> (Output.warnOn true) + + let a = AssemblyDefinition.ReadAssembly x + resolutionTable.[name] <- a + a let internal hookResolveHandler = new AssemblyResolveEventHandler(resolveFromNugetCache) @@ -394,6 +481,31 @@ module internal Instrument = | (_, true) -> Mono.Cecil.Mdb.MdbWriterProvider() :> ISymbolWriterProvider | _ -> null +// #if IDEMPOTENT_INSTRUMENT +// let internal safeWait (mutex: System.Threading.WaitHandle) = +// try +// mutex.WaitOne() |> ignore +// with +// | :? System.Threading.AbandonedMutexException -> () + +// let internal withFileMutex (p: string) f = +// let key = +// p +// |> System.Text.Encoding.UTF8.GetBytes +// |> CoverageParameters.hash.ComputeHash +// |> Convert.ToBase64String + +// use mutex = +// new System.Threading.Mutex(false, "AltCover-" + key.Replace('/', '.') + ".mutex") + +// safeWait mutex + +// try +// f () +// finally +// mutex.ReleaseMutex() +// #endif + // Commit an instrumented assembly to disk // param name="assembly">The instrumented assembly object // param name="path">The full path of the output file @@ -436,11 +548,25 @@ module internal Instrument = try Directory.SetCurrentDirectory(Path.GetDirectoryName(path)) +// #if IDEMPOTENT_INSTRUMENT +// let write (a: AssemblyDefinition) (p: string) pk = +// withFileMutex +// p +// (fun () -> +// if p |> File.Exists |> not +// || DateTime.Now.Year > 2000 // TODO -- check hashes +// then +// use sink = +// File.Open(p, FileMode.Create, FileAccess.ReadWrite) + +// a.Write(sink, pk)) +// #else let write (a: AssemblyDefinition) p pk = use sink = File.Open(p, FileMode.Create, FileAccess.ReadWrite) a.Write(sink, pk) +// #endif let resolver = assembly.MainModule.AssemblyResolver hookResolver resolver @@ -501,28 +627,24 @@ module internal Instrument = let effectiveKey = match token with | None -> - CoverageParameters.defaultStrongNameKey - |> Option.map KeyStore.keyToRecord + CoverageParameters.defaultStrongNameKey + |> Option.map KeyStore.keyToRecord | Some _ -> token match effectiveKey with | None -> - r.HasPublicKey <- false - r.PublicKeyToken <- null - r.PublicKey <- null + r.HasPublicKey <- false + r.PublicKeyToken <- null + r.PublicKey <- null | Some key -> - r.HasPublicKey <- true - r.PublicKey <- key.Pair.PublicKey |> Seq.toArray // implicitly sets token + r.HasPublicKey <- true + r.PublicKey <- key.Pair.PublicKey |> Seq.toArray // implicitly sets token let updated = r.ToString() if not - <| updated.Equals - ( - original, - StringComparison.Ordinal - ) + <| updated.Equals(original, StringComparison.Ordinal) then assemblyReferenceSubstitutions.[original] <- updated) @@ -559,9 +681,9 @@ module internal Instrument = match existingDependencies with | None -> Set.empty | Some p -> - p.Value.Object - |> Seq.map (fun p -> p.Key) - |> Set.ofSeq + p.Value.Object + |> Seq.map (fun p -> p.Key) + |> Set.ofSeq let addFirst (properties: KeyValuePair seq) @@ -586,11 +708,12 @@ module internal Instrument = |> Seq.find (fun p -> p.Key = "dependencies") match app - |> Seq.tryFind (fun p -> p.Key = "dependencies") with + |> Seq.tryFind (fun p -> p.Key = "dependencies") + with | None -> app |> addFirst [ rawDependencies ] | Some p -> - let recorder = rawDependencies.Value.Object |> Seq.head - p.Value.Object.[recorder.Key] <- recorder.Value + let recorder = rawDependencies.Value.Object |> Seq.head + p.Value.Object.[recorder.Key] <- recorder.Value updateDependencies () @@ -643,27 +766,27 @@ module internal Instrument = let restate = match m.Inspection <> Inspections.Ignore with | true -> - let recordingMethod = - match state.RecordingMethod with - | [] -> recordingMethod state.RecordingAssembly - | _ -> state.RecordingMethod - - let refs = - recordingMethod - |> List.map m.Module.ImportReference - - { state with - RecordingMethodRef = - { Visit = refs.[0] - Push = refs.[1] - Pop = refs.[2] } - RecordingMethod = recordingMethod - AsyncSupport = - state.AsyncSupport - |> Option.map - (fun a -> - { a with - LocalWait = a.Wait |> m.Module.ImportReference }) } + let recordingMethod = + match state.RecordingMethod with + | [] -> recordingMethod state.RecordingAssembly + | _ -> state.RecordingMethod + + let refs = + recordingMethod + |> List.map m.Module.ImportReference + + { state with + RecordingMethodRef = + { Visit = refs.[0] + Push = refs.[1] + Pop = refs.[2] } + RecordingMethod = recordingMethod + AsyncSupport = + state.AsyncSupport + |> Option.map + (fun a -> + { a with + LocalWait = a.Wait |> m.Module.ImportReference }) } | _ -> state { restate with @@ -676,11 +799,11 @@ module internal Instrument = let private visitMethod (state: InstrumentContext) m = match m.Inspection.IsInstrumented with | true -> - let body = m.Method.Body + let body = m.Method.Body - { state with - MethodBody = body - MethodWorker = body.GetILProcessor() } + { state with + MethodBody = body + MethodWorker = body.GetILProcessor() } | _ -> state let private updateBranchReferences (body: MethodBody) instruction injected = @@ -730,59 +853,59 @@ module internal Instrument = match branch.Indexes |> Seq.tryFind (fun i -> i = -1) with | Some _ -> - // before - // Cond_Branch xxx - // Next - // - // after - // Cond_Branch xxx - // jump instrument#-1 - // instrument#-1 - // Next - let target = branch.Start.Next - let preamble = instrument target - - let jump = - state.MethodWorker.Create(OpCodes.Br, preamble) - - state.MethodWorker.InsertAfter(branch.Start, jump) - - if branch.Start.OpCode = OpCodes.Switch then - updateSwitch jump + // before + // Cond_Branch xxx + // Next + // + // after + // Cond_Branch xxx + // jump instrument#-1 + // instrument#-1 + // Next + let target = branch.Start.Next + let preamble = instrument target + + let jump = + state.MethodWorker.Create(OpCodes.Br, preamble) + + state.MethodWorker.InsertAfter(branch.Start, jump) + + if branch.Start.OpCode = OpCodes.Switch then + updateSwitch jump | None -> - // before - // Cond_Branch #n - // jump instrument#-1 - // ... - // instrument#-1 - // Next - // - // after - // Cond_Branch instrument#n - // jump instrument#-1 - // instrument#n - // jump #n - // ... - // instrument#-1 - // Next - let target = - if branch.Start.OpCode = OpCodes.Switch then - branch.Start.Operand :?> Instruction [] - |> Seq.skip (branch.Indexes.Head) - |> Seq.head - else - branch.Start.Operand :?> Instruction - - let jump = - state.MethodWorker.Create(OpCodes.Br, target) - - state.MethodWorker.InsertAfter(branch.Start.Next, jump) - let preamble = instrument jump - + // before + // Cond_Branch #n + // jump instrument#-1 + // ... + // instrument#-1 + // Next + // + // after + // Cond_Branch instrument#n + // jump instrument#-1 + // instrument#n + // jump #n + // ... + // instrument#-1 + // Next + let target = if branch.Start.OpCode = OpCodes.Switch then - updateSwitch preamble + branch.Start.Operand :?> Instruction [] + |> Seq.skip (branch.Indexes.Head) + |> Seq.head else - branch.Start.Operand <- preamble + branch.Start.Operand :?> Instruction + + let jump = + state.MethodWorker.Create(OpCodes.Br, target) + + state.MethodWorker.InsertAfter(branch.Start.Next, jump) + let preamble = instrument jump + + if branch.Start.OpCode = OpCodes.Switch then + updateSwitch preamble + else + branch.Start.Operand <- preamble state @@ -861,9 +984,10 @@ module internal Instrument = let asyncChecks = [ isTaskType; isStateMachine ] - let processAsyncAwait (s: InstrumentContext) = + let processAsyncAwait (s: InstrumentContext, unhandled: bool) = - if asyncChecks |> Seq.forall invokePredicate then + if unhandled + && asyncChecks |> Seq.forall invokePredicate then // the instruction list is // IL_0040: call System.Threading.Tasks.Task`1 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::get_Task() // IL_0000: stloc V_1 <<== This one @@ -901,17 +1025,17 @@ module internal Instrument = leave |> Seq.iter ((injectWait methodWorker) >> ignore) - newstate + (newstate, false) else - s + (s, unhandled) let isAsyncType () = [ "Microsoft.FSharp.Control.FSharpAsync`1" ] |> Seq.exists (fun n -> n = e) - let processFSAsync (s: InstrumentContext) = + let processFSAsync (s: InstrumentContext, unhandled: bool) = - if isAsyncType () then + if unhandled && isAsyncType () then let asyncOf = (rtype :?> GenericInstanceType).GenericArguments |> Seq.head // only one @@ -955,13 +1079,57 @@ module internal Instrument = leave |> Seq.iter ((injectWait methodWorker) >> ignore) - newstate + (newstate, false) else - s + (s, unhandled) - state |> processAsyncAwait |> processFSAsync + let processTaskReturns (s: InstrumentContext, unhandled: bool) = + if unhandled && isTaskType () then + let newstate = + { s with + AsyncSupport = + Some( + Option.defaultWith + (fun () -> AsyncSupport.Update m.Method) // TODO + state.AsyncSupport + ) } - ) + let injectWait ilp (i: Instruction) = + // before + // IL_003f: stloc V1 + // IL_0040: leave.s IL_0054 + + // after + // IL_003d: stloc V1 + //+IL_003e: ldloc V1 + //+IL_003f: callvirt instance void [System.Runtime]System.Threading.Tasks.Task::Wait() + //+IL_0044: ldloc V1 + //+IL_0045: stloc.0 + // IL_0046: leave.s IL_005a + + bulkInsertBefore + ilp + i.Next + [ ilp.Create(OpCodes.Ldloc, i.Operand :?> VariableDefinition) + ilp.Create(OpCodes.Ldc_I4, 65535) + ilp.Create(OpCodes.Callvirt, newstate.AsyncSupport.Value.LocalWait) + ilp.Create(OpCodes.Pop) + ilp.Create(OpCodes.Ldloc, i.Operand :?> VariableDefinition) + ilp.Create(OpCodes.Stloc_0) ] + true + + leave + |> Seq.iter ((injectWait methodWorker) >> ignore) + + (newstate, false) + else + (s, unhandled) + + (state, true) + |> processAsyncAwait + |> processFSAsync + |> processTaskReturns + |> fst) state let private visitAfterMethod state (m: MethodEntry) = @@ -994,8 +1162,8 @@ module internal Instrument = Assembly .GetExecutingAssembly() .GetManifestResourceStream("AltCover.AltCover.Recorder.net20.dll") - let recordingAssembly = - prepareAssembly (stream) + + let recordingAssembly = prepareAssembly (stream) { state with RecordingAssembly = recordingAssembly @@ -1046,9 +1214,11 @@ module internal Instrument = File.WriteAllText(f, (f |> File.ReadAllText |> injectJSON)))) finally (state.RecordingAssembly :> IDisposable).Dispose() + state.RecorderSource |> Option.ofObj |> Option.iter (fun a -> a.Close()) + state.AsyncSupport |> Option.iter (fun a -> a.Close()) @@ -1057,6 +1227,18 @@ module internal Instrument = RecorderSource = null AsyncSupport = None } + let visitAssembly state assembly = + updateStrongReferences assembly.Assembly state.InstrumentedAssemblies + |> ignore + + if assembly.Inspection <> Inspections.Ignore then + assembly.Assembly.MainModule.AssemblyReferences.Add(state.RecordingAssembly.Name) + + // TODO -- react to source or destination being stamped + injectInstrumentation state.RecordingAssembly assembly + + state + // Perform visitor operations // param name="state">Contextual information for the visit // param name="node">The node being visited @@ -1064,16 +1246,16 @@ module internal Instrument = let internal instrumentationVisitorCore (state: InstrumentContext) (node: Node) = match node with | Start _ -> visitStart state - | Assembly assembly -> - updateStrongReferences assembly.Assembly state.InstrumentedAssemblies - |> ignore - - if assembly.Inspection <> Inspections.Ignore then - assembly.Assembly.MainModule.AssemblyReferences.Add( - state.RecordingAssembly.Name - ) - - state + | Assembly assembly -> visitAssembly state assembly + //updateStrongReferences assembly.Assembly state.InstrumentedAssemblies + //|> ignore + // + //if assembly.Inspection <> Inspections.Ignore then + // assembly.Assembly.MainModule.AssemblyReferences.Add( + // state.RecordingAssembly.Name + // ) + // + //state | Module m -> visitModule state m | Type _ -> state | Method m -> visitMethod state m @@ -1092,17 +1274,20 @@ module internal Instrument = = try core state node - with _ -> + with + | _ -> match node with | Finish -> () | _ -> - if state.RecordingAssembly.IsNotNull then - (state.RecordingAssembly :> IDisposable).Dispose() - state.RecorderSource - |> Option.ofObj - |> Option.iter (fun a -> a.Close()) - state.AsyncSupport - |> Option.iter (fun a -> a.Close()) + if state.RecordingAssembly.IsNotNull then + (state.RecordingAssembly :> IDisposable).Dispose() + + state.RecorderSource + |> Option.ofObj + |> Option.iter (fun a -> a.Close()) + + state.AsyncSupport + |> Option.iter (fun a -> a.Close()) reraise () @@ -1112,6 +1297,6 @@ module internal Instrument = // "Public" API // Higher-order function that returns a visitor // param name="assemblies">List of assembly paths to visit - // returns>Stateful visitor function + // Stateful visitor function let internal instrumentGenerator (assemblies: string list) = Visitor.encloseState I.instrumentationVisitor (InstrumentContext.Build assemblies) \ No newline at end of file diff --git a/AltCover.Engine/Json.fs b/AltCover.Engine/Json.fs index 508ccb7d7..fc0d63f34 100644 --- a/AltCover.Engine/Json.fs +++ b/AltCover.Engine/Json.fs @@ -10,7 +10,7 @@ open Mono.Cecil.Rocks [] module internal Json = - let internal path : Option ref = ref None + let internal path: Option ref = ref None // --- NCover --- @@ -28,28 +28,28 @@ module internal Json = (mname: string) = let classes = - match modul.TryGetValue (fst doc) with + match modul.TryGetValue(fst doc) with | true, c -> c | _ -> - let c = NativeJson.Classes() - modul.Add(fst doc, c) - NativeJson.injectEmbed c (snd doc) - c + let c = NativeJson.Classes() + modul.Add(fst doc, c) + NativeJson.injectEmbed c (snd doc) + c let methods = match classes.TryGetValue cname with | true, m -> m | _ -> - let m = NativeJson.Methods() - classes.Add(cname, m) - m + let m = NativeJson.Methods() + classes.Add(cname, m) + m match methods.TryGetValue mname with | true, m -> (methods, m) | _ -> - let m = NativeJson.Method.Create(None) - methods.Add(mname, m) - (methods, m) + let m = NativeJson.Method.Create(None) + methods.Add(mname, m) + (methods, m) [ Option.map + |> Option.bind (fun a -> a.MainModule.GetAllTypes() |> Seq.tryFind (fun t -> t.FullName = cname)) - |> Option.flatten let md = td - |> Option.map + |> Option.bind (fun t -> t.Methods |> Seq.tryFind @@ -139,7 +138,6 @@ module internal Json = pt.StartLine = sp.Value.SL && pt.StartColumn = sp.Value.SC))))) - |> Option.flatten let truemd = md @@ -171,6 +169,7 @@ module internal Json = let counts = System.Collections.Generic.Dictionary() + let embeds = System.Collections.Generic.Dictionary() @@ -193,7 +192,8 @@ module internal Json = m.Attribute(XName.Get "excluded").Value |> Boolean.TryParse - let jmethods = System.Collections.Generic.Dictionary() + let jmethods = + System.Collections.Generic.Dictionary() if not excluded then let basename = sprintf "%s::%s" cname mname @@ -206,7 +206,7 @@ module internal Json = let spoints = m.Descendants(XName.Get "seqpnt") - let makeSeqPnt (x:XElement) = + let makeSeqPnt (x: XElement) = let parse n = x.Attribute(XName.Get n) |> Option.ofObj @@ -223,18 +223,11 @@ module internal Json = NativeJson.SeqPnt.Times = null NativeJson.SeqPnt.Tracks = null } - let sp = spoints - |> Seq.tryHead - |> Option.map makeSeqPnt + let sp = + spoints |> Seq.tryHead |> Option.map makeSeqPnt let (className, methodName) = - maybeNames - def - synth - outerclass - sp - cname - mname + maybeNames def synth outerclass sp cname mname spoints |> Seq.iter @@ -244,34 +237,45 @@ module internal Json = |> Boolean.TryParse if not excluded then - let doc = s.Attribute(XName.Get "document").Value - let embed = - let (ok, result) = embeds.TryGetValue(doc) - if ok then result - else - let found = s.Ancestors("module".X) - |> Seq.collect (fun m -> m.Descendants("altcover.file".X)) - |> Seq.filter (fun f -> f.Attribute(XName.Get "document").Value = doc) - |> Seq.tryHead - |> Option.map (fun f -> f.Attribute(XName.Get "embed").Value) - |> Option.filter (String.IsNullOrWhiteSpace >> not) - |> Option.defaultValue String.Empty - embeds.Add(doc, found) - found - - let docname = (doc, embed) - let jmethod = - getMethodRecord modul docname className methodName - jmethods.[doc] <- jmethod - - s - |> makeSeqPnt - |> jmethod.SeqPnts.Add) + let doc = s.Attribute(XName.Get "document").Value + + let embed = + let (ok, result) = embeds.TryGetValue(doc) + + if ok then + result + else + let found = + s.Ancestors("module".X) + |> Seq.collect + (fun m -> m.Descendants("altcover.file".X)) + |> Seq.filter + (fun f -> + f.Attribute(XName.Get "document").Value = doc) + |> Seq.tryHead + |> Option.map + (fun f -> f.Attribute(XName.Get "embed").Value) + |> Option.filter (String.IsNullOrWhiteSpace >> not) + |> Option.defaultValue String.Empty + + embeds.Add(doc, found) + found + + let docname = (doc, embed) + + let jmethod = + getMethodRecord modul docname className methodName + + jmethods.[doc] <- jmethod + + s |> makeSeqPnt |> jmethod.SeqPnts.Add) jmethods.Values - |> Seq.iter (fun jm -> jm.SeqPnts - |> Seq.groupBy (fun s -> s.SL) - |> Seq.iter (fun (l, ss) -> jm.Lines.[l] <- lineVisits ss))) + |> Seq.iter + (fun jm -> + jm.SeqPnts + |> Seq.groupBy (fun s -> s.SL) + |> Seq.iter (fun (l, ss) -> jm.Lines.[l] <- lineVisits ss))) finally maybeDispose def @@ -296,17 +300,18 @@ module internal Json = let modul = NativeJson.Documents() let files = - System.Collections.Generic.Dictionary() + System.Collections.Generic.Dictionary() x.Descendants(XName.Get "File") |> Seq.iter (fun x -> let document = x.Attribute(XName.Get "fullPath").Value - let embed = x.Attribute(XName.Get "altcover.embed") - |> Option.ofObj - |> Option.map (fun e -> e.Value) - |> Option.defaultValue String.Empty + let embed = + x.Attribute(XName.Get "altcover.embed") + |> Option.ofObj + |> Option.map (fun e -> e.Value) + |> Option.defaultValue String.Empty files.Add( x.Attribute(XName.Get "uid").Value, @@ -357,7 +362,9 @@ module internal Json = .Value.Replace('+', '/') let outerclass = cname.Split('/') |> Seq.head - let jmethods = System.Collections.Generic.Dictionary() + + let jmethods = + System.Collections.Generic.Dictionary() m.Descendants(XName.Get "SequencePoint") |> Seq.iter @@ -368,7 +375,9 @@ module internal Json = |> Option.map (fun a -> a.Value |> Int32.TryParse |> snd) |> Option.defaultValue 0 - let docname = files.[s.Attribute(XName.Get "fileid").Value] + let docname = + files.[s.Attribute(XName.Get "fileid").Value] + let sp = { NativeJson.SeqPnt.VC = parse "vc" NativeJson.SeqPnt.SL = parse "sl" @@ -416,8 +425,9 @@ module internal Json = t2 } + let (className, methodName) = - maybeNames def mname outerclass None cname mname + maybeNames def mname outerclass None cname mname let (tid, entry, exit) = if tracked.ContainsKey mname then @@ -426,14 +436,19 @@ module internal Json = else (System.Nullable(), null, null) - updateMethodRecord modul docname className mname (tid, entry, exit) + updateMethodRecord + modul + docname + className + mname + (tid, entry, exit) |> ignore let jmethod = getMethodRecord modul docname className methodName + jmethods.[fst docname] <- jmethod - jmethod.SeqPnts.Add sp - ) + jmethod.SeqPnts.Add sp) let bp = NativeJson.Branches() @@ -446,7 +461,9 @@ module internal Json = |> Option.map (fun a -> a.Value |> Int32.TryParse |> snd) |> Option.defaultValue 0 - let docname = files.[s.Attribute(XName.Get "fileid").Value] + let docname = + files.[s.Attribute(XName.Get "fileid").Value] + let offset = parse "offset" let jbp = @@ -499,8 +516,9 @@ module internal Json = t2 } + let (className, methodName) = - maybeNames def mname outerclass None cname mname + maybeNames def mname outerclass None cname mname let (tid, entry, exit) = if tracked.ContainsKey mname then @@ -509,19 +527,28 @@ module internal Json = else (System.Nullable(), null, null) - updateMethodRecord modul docname className mname (tid, entry, exit) + updateMethodRecord + modul + docname + className + mname + (tid, entry, exit) |> ignore let jmethod = getMethodRecord modul docname className methodName + jmethods.[fst docname] <- jmethod jmethod.Branches.Add jbp bp.Add jbp // for counting paths ) + jmethods.Values - |> Seq.iter (fun jm -> jm.SeqPnts - |> Seq.groupBy (fun s -> s.SL) - |> Seq.iter (fun (l, ss) -> jm.Lines.[l] <- lineVisits ss))) + |> Seq.iter + (fun jm -> + jm.SeqPnts + |> Seq.groupBy (fun s -> s.SL) + |> Seq.iter (fun (l, ss) -> jm.Lines.[l] <- lineVisits ss))) finally maybeDispose def diff --git a/AltCover.Engine/LCov.fs b/AltCover.Engine/LCov.fs index f8d4126e0..50d192dca 100644 --- a/AltCover.Engine/LCov.fs +++ b/AltCover.Engine/LCov.fs @@ -13,7 +13,7 @@ open System.Xml.Linq "CA1704", Justification = "'LCov' is jargon")>] module internal LCov = - let internal path : Option ref = ref None + let internal path: Option ref = ref None let internal sortByFirst s = s |> Seq.sortBy fst module internal I = @@ -24,14 +24,18 @@ module internal LCov = [] - [] let internal lineOfPartialMethod (m: XElement * XElement seq) = let (_, s) = m + s - |> Seq.map (fun x -> x.Attribute("line".X).Value - |> Int32.TryParse - |> snd) + |> Seq.map + (fun x -> + x.Attribute("line".X).Value + |> Int32.TryParse + |> snd) |> Seq.min let internal multiSort (by: 'a -> int) (l: (string * 'a seq) seq) = @@ -39,7 +43,9 @@ module internal LCov = |> Seq.map (fun (f, ms) -> (f, ms |> Seq.sortBy by |> Seq.toList)) |> sortByFirst - let internal multiSortByNameAndPartialStartLine (l: (string * (XElement * XElement seq) seq) seq) = + let internal multiSortByNameAndPartialStartLine + (l: (string * (XElement * XElement seq) seq) seq) + = multiSort lineOfPartialMethod l [] - [] - let internal computeVisitCount (lines : XElement seq) (attr : string) = - let vx = lines - |> Seq.map (fun l -> let v = l.Attribute(attr.X) - if v |> isNull then 0 - else v.Value |> Int32.TryParse |> snd) - if vx |> Seq.exists(fun v -> v > 0) - then vx |> Seq.max - else vx |> Seq.min + let internal computeVisitCount (lines: XElement seq) (attr: string) = + let vx = + lines + |> Seq.map + (fun l -> + let v = l.Attribute(attr.X) + + if v |> isNull then + 0 + else + v.Value |> Int32.TryParse |> snd) + + if vx |> Seq.exists (fun v -> v > 0) then + vx |> Seq.max + else + vx |> Seq.min // from a real sample e.g. https://pastebin.com/588FggQg (* @@ -90,343 +105,378 @@ FN:4,(anonymous_0) (fun writer -> match format with | ReportFormat.NCover -> - report.Descendants("module".X) - |> Seq.iter (fun assembly -> - assembly.Descendants("method".X) - |> Seq.filter - (fun m -> - m.Attribute("excluded".X).Value <> "true" - && m.Descendants("seqpnt".X) - |> Seq.exists (fun s -> s.Attribute("excluded".X).Value <> "true")) - |> Seq.collect( fun m -> m.Descendants("seqpnt".X) - |> Seq.groupBy (fun s -> s.Attribute("document".X) - .Value) - |> Seq.map (fun (d, l) -> (d, (m, l)))) - |> Seq.groupBy fst - |> Seq.map (fun (d, dmlist) -> d, dmlist |> Seq.map snd) - |> I.multiSortByNameAndPartialStartLine - |> Seq.iter - (fun (f, methods) -> - //If available, a tracefile begins with the testname which - // is stored in the following format: - // - // TN: - writer.WriteLine ("TN: " + assembly.Attribute("assemblyIdentity".X).Value) - // For each source file referenced in the .da file, there is a section - // containing filename and coverage data: - // - // SF: - writer.WriteLine("SF:" + f) - - let fullname (m: XElement) = - let fna = m.Attribute("fullname".X) - - if fna |> isNull then - m.Attribute("class".X).Value - + "." - + m.Attribute("name".X).Value - else - fna.Value - // Following is a list of line numbers for each function name found in the - // source file: - // - // FN:, - methods - |> Seq.iter - (fun m -> - let l = - (I.lineOfPartialMethod m) - .ToString(CultureInfo.InvariantCulture) - - let (mx, pts) = m - let name = fullname mx - writer.WriteLine("FN:" + l + "," + name)) - // Next, there is a list of execution counts for each instrumented function: - // - // FNDA:, - let hit = - methods - |> Seq.fold - (fun (n: int) (m,_) -> - let v = - (m.Descendants("seqpnt".X) |> Seq.head).Attribute( - "visitcount".X - ) - .Value - - let name = fullname m - writer.WriteLine("FNDA:" + v + "," + name) - n.Increment(v <> "0")) - 0 - // This list is followed by two lines containing the number of functions - // found and hit: - // - // FNF: - // FNH: - writer.WriteLine( - "FNF:" - + methods.Length.ToString(CultureInfo.InvariantCulture) - ) - - writer.WriteLine( - "FNH:" - + hit.ToString(CultureInfo.InvariantCulture) - ) - // Branch coverage information is stored which one line per branch: - // - // BRDA:,,, - // - // Block number and branch number are gcc internal IDs for the branch. - // Taken is either '-' if the basic block containing the branch was never - // executed or a number indicating how often that branch was taken. - // Branch coverage summaries are stored in two lines: - // - // BRF: - // BRH: - writer.WriteLine("BRF:0") - writer.WriteLine("BRH:0") - // Then there is a list of execution counts for each instrumented line - // (i.e. a line which resulted in executable code): - // - // DA:,[,] - // - // Note that there may be an optional checksum present for each instru‐ - // mented line. The current geninfo implementation uses an MD5 hash as - // checksumming algorithm. - let (lf, lh) = - methods - |> Seq.collect snd - |> Seq.filter - (fun b -> - b.Attribute("line".X).Value - |> String.IsNullOrWhiteSpace - |> not) - |> Seq.groupBy (fun b -> b.Attribute("line".X).Value) - |> Seq.sortBy (fst >> Int32.TryParse >> snd) - |> Seq.fold - (fun (f, (h:int)) (sl,bs) -> - let vc = I.computeVisitCount bs "visitcount" - writer.WriteLine("DA:" + sl + "," + vc.ToString(CultureInfo.InvariantCulture)) - (f + 1, h.Increment (vc <> 0))) - (0, 0) - // At the end of a section, there is a summary about how many lines were - // found and how many were actually instrumented: - // - // LH: - // LF: - writer.WriteLine("LH:" + lh.ToString(CultureInfo.InvariantCulture)) - writer.WriteLine("LF:" + lf.ToString(CultureInfo.InvariantCulture)) - // Each sections ends with: - // - // end_of_record - writer.WriteLine "end_of_record")) + report.Descendants("module".X) + |> Seq.iter + (fun assembly -> + assembly.Descendants("method".X) + |> Seq.filter + (fun m -> + m.Attribute("excluded".X).Value <> "true" + && m.Descendants("seqpnt".X) + |> Seq.exists + (fun s -> s.Attribute("excluded".X).Value <> "true")) + |> Seq.collect + (fun m -> + m.Descendants("seqpnt".X) + |> Seq.groupBy (fun s -> s.Attribute("document".X).Value) + |> Seq.map (fun (d, l) -> (d, (m, l)))) + |> Seq.groupBy fst + |> Seq.map (fun (d, dmlist) -> d, dmlist |> Seq.map snd) + |> I.multiSortByNameAndPartialStartLine + |> Seq.iter + (fun (f, methods) -> + //If available, a tracefile begins with the testname which + // is stored in the following format: + // + // TN: + writer.WriteLine( + "TN: " + + assembly.Attribute("assemblyIdentity".X).Value + ) + // For each source file referenced in the .da file, there is a section + // containing filename and coverage data: + // + // SF: + writer.WriteLine("SF:" + f) + + let fullname (m: XElement) = + let fna = m.Attribute("fullname".X) + + if fna |> isNull then + m.Attribute("class".X).Value + + "." + + m.Attribute("name".X).Value + else + fna.Value + // Following is a list of line numbers for each function name found in the + // source file: + // + // FN:, + methods + |> Seq.iter + (fun m -> + let l = + (I.lineOfPartialMethod m) + .ToString(CultureInfo.InvariantCulture) + + let (mx, pts) = m + let name = fullname mx + writer.WriteLine("FN:" + l + "," + name)) + // Next, there is a list of execution counts for each instrumented function: + // + // FNDA:, + let hit = + methods + |> Seq.fold + (fun (n: int) (m, _) -> + let v = + (m.Descendants("seqpnt".X) |> Seq.head).Attribute( + "visitcount".X + ) + .Value + + let name = fullname m + writer.WriteLine("FNDA:" + v + "," + name) + n.Increment(v <> "0")) + 0 + // This list is followed by two lines containing the number of functions + // found and hit: + // + // FNF: + // FNH: + writer.WriteLine( + "FNF:" + + methods.Length.ToString(CultureInfo.InvariantCulture) + ) + + writer.WriteLine( + "FNH:" + + hit.ToString(CultureInfo.InvariantCulture) + ) + // Branch coverage information is stored which one line per branch: + // + // BRDA:,,, + // + // Block number and branch number are gcc internal IDs for the branch. + // Taken is either '-' if the basic block containing the branch was never + // executed or a number indicating how often that branch was taken. + // Branch coverage summaries are stored in two lines: + // + // BRF: + // BRH: + writer.WriteLine("BRF:0") + writer.WriteLine("BRH:0") + // Then there is a list of execution counts for each instrumented line + // (i.e. a line which resulted in executable code): + // + // DA:,[,] + // + // Note that there may be an optional checksum present for each instru‐ + // mented line. The current geninfo implementation uses an MD5 hash as + // checksumming algorithm. + let (lf, lh) = + methods + |> Seq.collect snd + |> Seq.filter + (fun b -> + b.Attribute("line".X).Value + |> String.IsNullOrWhiteSpace + |> not) + |> Seq.groupBy (fun b -> b.Attribute("line".X).Value) + |> Seq.sortBy (fst >> Int32.TryParse >> snd) + |> Seq.fold + (fun (f, (h: int)) (sl, bs) -> + let vc = I.computeVisitCount bs "visitcount" + + writer.WriteLine( + "DA:" + + sl + + "," + + vc.ToString(CultureInfo.InvariantCulture) + ) + + (f + 1, h.Increment(vc <> 0))) + (0, 0) + // At the end of a section, there is a summary about how many lines were + // found and how many were actually instrumented: + // + // LH: + // LF: + writer.WriteLine( + "LH:" + lh.ToString(CultureInfo.InvariantCulture) + ) + + writer.WriteLine( + "LF:" + lf.ToString(CultureInfo.InvariantCulture) + ) + // Each sections ends with: + // + // end_of_record + writer.WriteLine "end_of_record")) | _ -> - report.Descendants("Module".X) - |> Seq.iter (fun assembly -> - assembly.Descendants("File".X) - |> Seq.sortBy(fun f -> f.Attribute("fullPath".X).Value) - |> Seq.iter - (fun f -> - //If available, a tracefile begins with the testname which - // is stored in the following format: - // - // TN: - writer.WriteLine ("TN: " + (assembly.Descendants("ModuleName".X) - |> Seq.tryHead - |> Option.map (fun n -> n.Value) - |> Option.defaultValue String.Empty)) - // For each source file referenced in the .da file, there is a section - // containing filename and coverage data: - // - // SF: - writer.WriteLine("SF:" + f.Attribute("fullPath".X).Value) - - let uid = f.Attribute("uid".X).Value - let p = f.Parent.Parent - - // Following is a list of line numbers for each function name found in the - // source file: - // - // FN:, - let methods = - p.Descendants("Method".X) - |> Seq.filter - (fun m -> - m.Descendants() - |> Seq.exists (fun r -> - let f = r.Attribute("fileid".X) - f.IsNotNull && f.Value = uid)) - |> Seq.toList - - let FN (ms: XElement list) = // fsharplint:disable-line NonPublicValuesNames - ms - |> Seq.iter - (fun m -> - m.Descendants("SequencePoint".X) - |> Seq.filter (fun s -> s.Attribute("fileid".X).Value = uid) - |> Seq.tryHead - |> Option.iter - (fun s -> - let n = - (m.Descendants("Name".X) |> Seq.head).Value - - let sl = s.Attribute("sl".X).Value - - if sl |> String.IsNullOrWhiteSpace |> not then - writer.WriteLine( - "FN:" + s.Attribute("sl".X).Value + "," + n - ))) - - FN methods - // Next, there is a list of execution counts for each instrumented function: - // - // FNDA:, - let FNDA (ms: XElement list) = // fsharplint:disable-line NonPublicValuesNames - ms - |> Seq.iter - (fun m -> - m.Descendants("SequencePoint".X) + report.Descendants("Module".X) + |> Seq.iter + (fun assembly -> + assembly.Descendants("File".X) + |> Seq.sortBy (fun f -> f.Attribute("fullPath".X).Value) + |> Seq.iter + (fun f -> + //If available, a tracefile begins with the testname which + // is stored in the following format: + // + // TN: + writer.WriteLine( + "TN: " + + (assembly.Descendants("ModuleName".X) + |> Seq.tryHead + |> Option.map (fun n -> n.Value) + |> Option.defaultValue String.Empty) + ) + // For each source file referenced in the .da file, there is a section + // containing filename and coverage data: + // + // SF: + writer.WriteLine("SF:" + f.Attribute("fullPath".X).Value) + + let uid = f.Attribute("uid".X).Value + let p = f.Parent.Parent + + // Following is a list of line numbers for each function name found in the + // source file: + // + // FN:, + let methods = + p.Descendants("Method".X) + |> Seq.filter + (fun m -> + m.Descendants() + |> Seq.exists + (fun r -> + let f = r.Attribute("fileid".X) + f.IsNotNull && f.Value = uid)) + |> Seq.toList + + let FN (ms: XElement list) = // fsharplint:disable-line NonPublicValuesNames + ms + |> Seq.iter + (fun m -> + m.Descendants("SequencePoint".X) + |> Seq.filter + (fun s -> s.Attribute("fileid".X).Value = uid) + |> Seq.tryHead + |> Option.iter + (fun s -> + let n = + (m.Descendants("Name".X) |> Seq.head).Value + + let sl = s.Attribute("sl".X).Value + + if sl |> String.IsNullOrWhiteSpace |> not then + writer.WriteLine( + "FN:" + s.Attribute("sl".X).Value + "," + n + ))) + + FN methods + // Next, there is a list of execution counts for each instrumented function: + // + // FNDA:, + let FNDA (ms: XElement list) = // fsharplint:disable-line NonPublicValuesNames + ms + |> Seq.iter + (fun m -> + m.Descendants("SequencePoint".X) + |> Seq.filter + (fun s -> s.Attribute("fileid".X).Value = uid) + |> Seq.tryHead + |> Option.iter + (fun s -> + let n = + (m.Descendants("Name".X) |> Seq.head).Value + + let mp = + m.Descendants("MethodPoint".X) |> Seq.head + + let sl = s.Attribute("sl".X).Value + + if sl |> String.IsNullOrWhiteSpace |> not then + writer.WriteLine( + "FNDA:" + mp.Attribute("vc".X).Value + "," + n + ))) + + FNDA methods + // This list is followed by two lines containing the number of functions + // found and hit: + // + // FNF: + // FNH: + writer.WriteLine( + "FNF:" + + methods.Length.ToString(CultureInfo.InvariantCulture) + ) + + let hit = + methods + |> List.filter + (fun m -> + m.Attribute("visited".X).Value = "true" + || [ m.Descendants("SequencePoint".X) + m.Descendants("BranchPoint".X) + m.Descendants("MethodPoint".X) ] + |> Seq.concat + |> Seq.exists + (fun s -> + let v = s.Attribute("vc".X).Value + v.IsNotNull && v <> "0")) + + writer.WriteLine( + "FNH:" + + hit.Length.ToString(CultureInfo.InvariantCulture) + ) + // Branch coverage information is stored which one line per branch: + // + // BRDA:,,, + // + // Block number and branch number are gcc internal IDs for the branch. + // Taken is either '-' if the basic block containing the branch was never + // executed or a number indicating how often that branch was taken. + let branch (ms: XElement list) = + let (brf, brh, _) = + ms + |> Seq.collect (fun m -> m.Descendants("BranchPoint".X)) |> Seq.filter (fun s -> s.Attribute("fileid".X).Value = uid) - |> Seq.tryHead - |> Option.iter - (fun s -> - let n = - (m.Descendants("Name".X) |> Seq.head).Value - - let mp = - m.Descendants("MethodPoint".X) |> Seq.head - - let sl = s.Attribute("sl".X).Value - - if sl |> String.IsNullOrWhiteSpace |> not then - writer.WriteLine( - "FNDA:" + mp.Attribute("vc".X).Value + "," + n - ))) - - FNDA methods - // This list is followed by two lines containing the number of functions - // found and hit: - // - // FNF: - // FNH: - writer.WriteLine( - "FNF:" - + methods.Length.ToString(CultureInfo.InvariantCulture) - ) - - let hit = - methods - |> List.filter (fun m -> m.Attribute("visited".X).Value = "true" - || [ - m.Descendants("SequencePoint".X) - m.Descendants("BranchPoint".X) - m.Descendants("MethodPoint".X) - ] - |> Seq.concat - |> Seq.exists(fun s -> let v = s.Attribute("vc".X).Value - v.IsNotNull && v <> "0")) - writer.WriteLine( - "FNH:" - + hit.Length.ToString(CultureInfo.InvariantCulture) - ) - // Branch coverage information is stored which one line per branch: - // - // BRDA:,,, - // - // Block number and branch number are gcc internal IDs for the branch. - // Taken is either '-' if the basic block containing the branch was never - // executed or a number indicating how often that branch was taken. - let branch (ms: XElement list) = - let (brf, brh, _) = - ms - |> Seq.collect (fun m -> m.Descendants("BranchPoint".X)) - |> Seq.filter (fun s -> s.Attribute("fileid".X).Value = uid) - |> Seq.filter - (fun b -> - b.Attribute("sl".X).Value - |> String.IsNullOrWhiteSpace - |> not) - |> Seq.fold - (fun (f, h, (o, u)) b -> - let sl = b.Attribute("sl".X).Value - let off = b.Attribute("offset".X).Value - let usp = b.Attribute("uspid".X).Value - let path = b.Attribute("path".X).Value - let vc = b.Attribute("vc".X).Value - - writer.WriteLine( - "BRDA:" - + sl - + "," - + (if o = off then u else usp) - + "," - + path - + "," - + (if vc = "0" then "-" else vc) - ) - - (f + 1, - h + (if vc = "0" then 0 else 1), - (if o = off then (o, u) else (off, usp)))) - (0, 0, ("?", "?")) - // Branch coverage summaries are stored in two lines: - // - // BRF: - // BRH: - writer.WriteLine( - "BRF:" - + brf.ToString(CultureInfo.InvariantCulture) - ) - - writer.WriteLine( - "BRH:" - + brh.ToString(CultureInfo.InvariantCulture) - ) - - branch methods - // Then there is a list of execution counts for each instrumented line - // (i.e. a line which resulted in executable code): - // - // DA:,[,] - // - // Note that there may be an optional checksum present for each instru‐ - // mented line. The current geninfo implementation uses an MD5 hash as - // checksumming algorithm. - let (lf, lh) = - methods - |> Seq.collect (fun m -> m.Descendants("SequencePoint".X)) - |> Seq.filter (fun s -> s.Attribute("fileid".X).Value = uid) - |> Seq.filter - (fun b -> - b.Attribute("sl".X).Value - |> String.IsNullOrWhiteSpace - |> not) - |> Seq.groupBy - (fun b -> b.Attribute("sl".X).Value |> Int32.TryParse |> snd) - |> Seq.sortBy fst - |> Seq.fold - (fun (f, h) (line, points) -> - let sl = - line.ToString(CultureInfo.InvariantCulture) - - let vc = I.computeVisitCount points "vc" - let vcs = - vc.ToString(CultureInfo.InvariantCulture) - - writer.WriteLine("DA:" + sl + "," + vcs) - (f + 1, h + if vcs = "0" then 0 else 1)) - (0, 0) - // At the end of a section, there is a summary about how many lines were - // found and how many were actually instrumented: - // - // LH: - // LF: - writer.WriteLine("LH:" + lh.ToString(CultureInfo.InvariantCulture)) - writer.WriteLine("LF:" + lf.ToString(CultureInfo.InvariantCulture)) - // Each sections ends with: - // - // end_of_record - writer.WriteLine "end_of_record"))) + |> Seq.filter + (fun b -> + b.Attribute("sl".X).Value + |> String.IsNullOrWhiteSpace + |> not) + |> Seq.fold + (fun (f, h, (o, u)) b -> + let sl = b.Attribute("sl".X).Value + let off = b.Attribute("offset".X).Value + let usp = b.Attribute("uspid".X).Value + let path = b.Attribute("path".X).Value + let vc = b.Attribute("vc".X).Value + + writer.WriteLine( + "BRDA:" + + sl + + "," + + (if o = off then u else usp) + + "," + + path + + "," + + (if vc = "0" then "-" else vc) + ) + + (f + 1, + h + (if vc = "0" then 0 else 1), + (if o = off then (o, u) else (off, usp)))) + (0, 0, ("?", "?")) + // Branch coverage summaries are stored in two lines: + // + // BRF: + // BRH: + writer.WriteLine( + "BRF:" + + brf.ToString(CultureInfo.InvariantCulture) + ) + + writer.WriteLine( + "BRH:" + + brh.ToString(CultureInfo.InvariantCulture) + ) + + branch methods + // Then there is a list of execution counts for each instrumented line + // (i.e. a line which resulted in executable code): + // + // DA:,[,] + // + // Note that there may be an optional checksum present for each instru‐ + // mented line. The current geninfo implementation uses an MD5 hash as + // checksumming algorithm. + let (lf, lh) = + methods + |> Seq.collect (fun m -> m.Descendants("SequencePoint".X)) + |> Seq.filter (fun s -> s.Attribute("fileid".X).Value = uid) + |> Seq.filter + (fun b -> + b.Attribute("sl".X).Value + |> String.IsNullOrWhiteSpace + |> not) + |> Seq.groupBy + (fun b -> + b.Attribute("sl".X).Value |> Int32.TryParse |> snd) + |> Seq.sortBy fst + |> Seq.fold + (fun (f, h) (line, points) -> + let sl = + line.ToString(CultureInfo.InvariantCulture) + + let vc = I.computeVisitCount points "vc" + + let vcs = + vc.ToString(CultureInfo.InvariantCulture) + + writer.WriteLine("DA:" + sl + "," + vcs) + (f + 1, h + if vcs = "0" then 0 else 1)) + (0, 0) + // At the end of a section, there is a summary about how many lines were + // found and how many were actually instrumented: + // + // LH: + // LF: + writer.WriteLine( + "LH:" + lh.ToString(CultureInfo.InvariantCulture) + ) + + writer.WriteLine( + "LF:" + lf.ToString(CultureInfo.InvariantCulture) + ) + // Each sections ends with: + // + // end_of_record + writer.WriteLine "end_of_record"))) let convertJson document s = let x = @@ -440,10 +490,10 @@ FN:4,(anonymous_0) match report with | Unknown -> () | XML document -> - doWithStream - (fun () -> File.OpenWrite(path.Value |> Option.get)) - (convertReport document format) + doWithStream + (fun () -> File.OpenWrite(path.Value |> Option.get)) + (convertReport document format) | JSON x -> - doWithStream (fun () -> File.OpenWrite(path.Value |> Option.get)) (convertJson x) + doWithStream (fun () -> File.OpenWrite(path.Value |> Option.get)) (convertJson x) (result, 0uy, String.Empty) \ No newline at end of file diff --git a/AltCover.Engine/Main.fs b/AltCover.Engine/Main.fs index 12b63c96b..fb79cf31f 100644 --- a/AltCover.Engine/Main.fs +++ b/AltCover.Engine/Main.fs @@ -15,17 +15,14 @@ open Mono.Options type internal AssemblyInfo = { Path: string list Name: string + Hash: string Refs: string list } module internal Main = let internal (|Select|_|) (pattern: String) offered = if offered |> String.IsNullOrWhiteSpace |> not - && pattern.StartsWith - ( - offered, - StringComparison.OrdinalIgnoreCase - ) + && pattern.StartsWith(offered, StringComparison.OrdinalIgnoreCase) then Some offered else @@ -38,6 +35,7 @@ module internal Main = CoverageParameters.defer.Value <- false // ddflag CoverageParameters.theInputDirectories.Clear() CoverageParameters.theOutputDirectories.Clear() + CoverageParameters.configurationHash <- None ProgramDatabase.symbolFolders.Clear() Instrument.resolutionTable.Clear() @@ -266,25 +264,25 @@ module internal Main = (fun _ -> match CoverageParameters.coverstyle with | CoverStyle.LineOnly -> - CommandLine.error <- - CommandLine.Format.Local("MultiplesNotAllowed", "--linecover") - :: CommandLine.error + CommandLine.error <- + CommandLine.Format.Local("MultiplesNotAllowed", "--linecover") + :: CommandLine.error | CoverStyle.BranchOnly -> - CommandLine.error <- - CommandLine.Format.Local("Incompatible", "--linecover", "--branchcover") - :: CommandLine.error + CommandLine.error <- + CommandLine.Format.Local("Incompatible", "--linecover", "--branchcover") + :: CommandLine.error | _ -> CoverageParameters.coverstyle <- CoverStyle.LineOnly)) ("branchcover", (fun _ -> match CoverageParameters.coverstyle with | CoverStyle.BranchOnly -> - CommandLine.error <- - CommandLine.Format.Local("MultiplesNotAllowed", "--branchcover") - :: CommandLine.error + CommandLine.error <- + CommandLine.Format.Local("MultiplesNotAllowed", "--branchcover") + :: CommandLine.error | CoverStyle.LineOnly -> - CommandLine.error <- - CommandLine.Format.Local("Incompatible", "--branchcover", "--linecover") - :: CommandLine.error + CommandLine.error <- + CommandLine.Format.Local("Incompatible", "--branchcover", "--linecover") + :: CommandLine.error | _ -> CoverageParameters.coverstyle <- CoverStyle.BranchOnly)) (CommandLine.ddFlag "dropReturnCode" CommandLine.dropReturnCode) (CommandLine.ddFlag "sourcelink" CoverageParameters.sourcelink) @@ -325,7 +323,7 @@ module internal Main = o.Add(p, CommandLine.resources.GetString(p), new System.Action(a))) (OptionSet()) - let private echoDirectories (outputDirectory:string, inputDirectory:string) = + let private echoDirectories (outputDirectory: string, inputDirectory: string) = if CommandLine.verbosity < 1 // implement it early here then if CoverageParameters.inplace.Value then @@ -346,51 +344,51 @@ module internal Main = = match action with | Right (rest, options) -> - // Check that the directories are distinct - let inputDirectories = CoverageParameters.inputDirectories () - let outputDirectories = CoverageParameters.outputDirectories () - - inputDirectories - |> Seq.iter - (fun fromDirectory -> - if outputDirectories.Contains fromDirectory then - CommandLine.error <- - CommandLine.Format.Local("NotInPlace", fromDirectory) - :: CommandLine.error) - - CommandLine.doPathOperation - (fun () -> - let found = - outputDirectories |> Seq.filter Directory.Exists - - if CoverageParameters.inplace.Value - && CommandLine.error |> List.isEmpty - && found.Any() then - found - |> Seq.iter - (fun toDirectory -> - CommandLine.error <- - CommandLine.Format.Local("SaveExists", toDirectory) - :: CommandLine.error) - - if CommandLine.error |> List.isEmpty then - (Seq.iter CommandLine.ensureDirectory outputDirectories)) - () - false - - if CommandLine.error |> List.isEmpty |> not then - Left("UsageError", options) - else - Seq.zip outputDirectories inputDirectories - |> Seq.iter echoDirectories - - Right( - rest, - inputDirectories |> Seq.map DirectoryInfo, - outputDirectories |> Seq.map DirectoryInfo, - CoverageParameters.sourceDirectories () // "instrument-from" selection of the above - |> Seq.map DirectoryInfo - ) + // Check that the directories are distinct + let inputDirectories = CoverageParameters.inputDirectories () + let outputDirectories = CoverageParameters.outputDirectories () + + inputDirectories + |> Seq.iter + (fun fromDirectory -> + if outputDirectories.Contains fromDirectory then + CommandLine.error <- + CommandLine.Format.Local("NotInPlace", fromDirectory) + :: CommandLine.error) + + CommandLine.doPathOperation + (fun () -> + let found = + outputDirectories |> Seq.filter Directory.Exists + + if CoverageParameters.inplace.Value // Maybe barf if saving somewhere contaminated + && CommandLine.error |> List.isEmpty + && found.Any() then + found + |> Seq.iter + (fun toDirectory -> + CommandLine.error <- + CommandLine.Format.Local("SaveExists", toDirectory) + :: CommandLine.error) + + if CommandLine.error |> List.isEmpty then + (Seq.iter CommandLine.ensureDirectory outputDirectories)) + () + false + + if CommandLine.error |> List.isEmpty |> not then + Left("UsageError", options) + else + Seq.zip outputDirectories inputDirectories + |> Seq.iter echoDirectories + + Right( + rest, + inputDirectories |> Seq.map DirectoryInfo, + outputDirectories |> Seq.map DirectoryInfo, + CoverageParameters.sourceDirectories () // "instrument-from" selection of the above + |> Seq.map DirectoryInfo + ) | Left intro -> Left intro let internal imageLoadResilient (f: unit -> 'a) (tidy: unit -> 'a) = @@ -402,12 +400,43 @@ module internal Main = | :? ArgumentException | :? IOException -> tidy () - let internal matchType = Maybe (System.Environment.GetEnvironmentVariable("OS") = "Windows_NT") - StringComparison.OrdinalIgnoreCase StringComparison.Ordinal + let internal matchType = + Maybe + (System.Environment.GetEnvironmentVariable("OS") = "Windows_NT") + StringComparison.OrdinalIgnoreCase + StringComparison.Ordinal - let internal isInDirectory (file:string) (dir:string) = + let internal isInDirectory (file: string) (dir: string) = file.StartsWith(dir, matchType) + let internal checkKey (a: AssemblyNameReference) = + a.PublicKeyToken + |> Option.ofObj + |> Option.map + (fun t -> + String.Join( + String.Empty, + t + |> Seq.map (fun x -> x.ToString("x2", CultureInfo.InvariantCulture)) + ) = "4ebffcaabf10ce6a") // recorder.snk + |> Option.defaultValue false + + let internal screenAssembly (fullName: String) (a: AssemblyDefinition) = + if a.CustomAttributes + |> Seq.exists + (fun a -> + a.AttributeType.FullName = "AltCover.Recorder.InstrumentationAttribute") + || a.MainModule.AssemblyReferences + |> Seq.cast + |> Seq.exists checkKey + || checkKey a.Name then + CommandLine.Format.Local("alreadyInstrumented", fullName) + |> Output.warn + + None + else + Some a + let internal prepareTargetFiles (inputInfos: DirectoryInfo seq) (outputInfos: DirectoryInfo seq) @@ -429,24 +458,55 @@ module internal Main = (fun (inputInfo, outputInfo) -> // recurse here - let files = inputInfo.GetFiles("*",SearchOption.AllDirectories) - |> Seq.filter (fun i -> outputInfos - |> Seq.exists(fun o -> isInDirectory i.FullName o.FullName) - |> not) - - files - |> Seq.iter - (fun info -> - let fullName = info.FullName - let dirname = info.DirectoryName - let reldir = - Visitor.I.getRelativeDirectoryPath inputInfo.FullName dirname - let copy = Path.Combine(outputInfo.FullName, reldir, info.Name) - copy - |> Path.GetDirectoryName - |> Directory.CreateDirectory - |> ignore - File.Copy(fullName, copy, true))) + // all files in/under the input but not in/under any output + let files = + inputInfo.GetFiles("*", SearchOption.AllDirectories) + |> Seq.filter + (fun i -> + outputInfos + |> Seq.exists (fun o -> isInDirectory i.FullName o.FullName) + |> not) + + // mutable bucket + let filemap = + files + |> Seq.fold + (fun (d: Dictionary) info -> + let fullName = info.FullName + let dirname = info.DirectoryName + + let reldir = + Visitor.I.getRelativeDirectoryPath inputInfo.FullName dirname + + let copy = + Path.Combine(outputInfo.FullName, reldir, info.Name) + + copy + |> Path.GetDirectoryName + |> Directory.CreateDirectory + |> ignore + + d.Add(fullName, copy) + d) + (Dictionary()) + + // filter no-ops here + + // maybe mutex?? +// #if IDEMPOTENT_INSTRUMENT +// Instrument.I.withFileMutex +// fullName +// (fun () -> +// if copy |> File.Exists |> not +// || (File.GetLastWriteTime copy) < (File.GetLastWriteTime +// fullName) then +// File.Copy(fullName, copy, true)))) +// #else +// File.Copy(fullName, copy, true))) +// #endif + + filemap + |> Seq.iter (fun kvp -> File.Copy(kvp.Key, kvp.Value, true))) // Track the symbol-bearing assemblies let assemblies = @@ -464,27 +524,38 @@ module internal Main = use def = AssemblyDefinition.ReadAssembly(stream) ProgramDatabase.readSymbols def - if def.MainModule.HasSymbols - && (def.IsIncluded).IsInstrumented - && (def.MainModule.Attributes - &&& ModuleAttributes.ILOnly = ModuleAttributes.ILOnly) then - CommandLine.Format.Local("instrumenting", fullName) - |> Output.info - - { Path = [ fullName ] - Name = def.Name.Name - Refs = - def.MainModule.AssemblyReferences - |> Seq.map (fun r -> r.Name) - |> Seq.toList } - :: accumulator - else - accumulator) + Some def + |> Option.bind (screenAssembly fullName) + |> Option.filter + (fun def -> + def.MainModule.HasSymbols + && (def.IsIncluded).IsInstrumented + && (def.MainModule.Attributes + &&& ModuleAttributes.ILOnly = ModuleAttributes.ILOnly)) + |> Option.map + (fun def -> + CommandLine.Format.Local("instrumenting", fullName) + |> Output.info + + { Path = [ fullName ] + Name = def.Name.Name + Hash = + use stream = File.OpenRead fullName + + stream + |> CoverageParameters.hash.ComputeHash + |> Convert.ToBase64String + Refs = + def.MainModule.AssemblyReferences + |> Seq.map (fun r -> r.Name) + |> Seq.toList } + :: accumulator) + |> Option.defaultValue accumulator) (fun () -> accumulator)) []) |> Seq.toList |> Seq.concat - |> Seq.groupBy (fun a -> a.Name) // assume name is unique + |> Seq.groupBy (fun a -> a.Hash) // assume hash is unique |> Seq.map (fun (n, agroup) -> { (agroup |> Seq.head) with @@ -516,29 +587,31 @@ module internal Main = match unassigned with | [] -> collection | _ -> - let stage = - (if n <= 1 then - unassigned - else - unassigned - |> List.filter (fun u -> u.Refs |> List.isEmpty)) - |> List.sortBy (fun u -> u.Name) - - let waiting = - stage - |> List.fold (fun s a -> Set.remove a.Name s) unresolved - - let next = - unassigned - |> List.filter (fun u -> u.Refs |> List.isEmpty |> not) - |> List.map - (fun a -> - { a with - Refs = - a.Refs - |> List.filter (fun n -> Set.contains n waiting) }) - - bundle next waiting (stage :: collection) (n - 1) + let stage = + (if n <= 1 then + unassigned + else + unassigned + |> List.filter (fun u -> u.Refs |> List.isEmpty)) + |> List.sortBy (fun u -> u.Name) + + let waiting = + stage + |> List.fold (fun s a -> Set.remove a.Name s) unresolved + + let next = + unassigned + |> List.filter (fun u -> u.Refs |> List.isEmpty |> not) + |> List.map + (fun a -> + { a with + Refs = + a.Refs + |> List.filter (fun n -> Set.contains n waiting) }) + + bundle next waiting (stage :: collection) (n - 1) + + CoverageParameters.makeConfiguration () let sorted = bundle simplified candidates [] (simplified |> List.length) @@ -553,7 +626,10 @@ module internal Main = |> List.map (Path.GetDirectoryName >> (fun d -> mapping.[d])) ({ AssemblyPath = proto - Destinations = targets }, + Destinations = targets + Identity = + { Assembly = a.Hash + Configuration = CoverageParameters.configurationHash.Value } }, a.Name)) List.unzip sorted @@ -588,57 +664,57 @@ module internal Main = match check1 with | Left (intro, options) -> - CommandLine.handleBadArguments - dotnetBuild - arguments - { Intro = intro - Options = options - Options2 = Runner.declareOptions () } - - 255 + CommandLine.handleBadArguments + dotnetBuild + arguments + { Intro = intro + Options = options + Options2 = Runner.declareOptions () } + + 255 | Right (rest, fromInfo, toInfo, targetInfo) -> - CommandLine.applyVerbosity () + CommandLine.applyVerbosity () - let report = CoverageParameters.reportPath () + let report = CoverageParameters.reportPath () - let result = - CommandLine.doPathOperation - (fun () -> - report - |> Path.GetDirectoryName - |> CommandLine.ensureDirectory + let result = + CommandLine.doPathOperation + (fun () -> + report + |> Path.GetDirectoryName + |> CommandLine.ensureDirectory - let (assemblies, assemblyNames) = - prepareTargetFiles - fromInfo - toInfo - targetInfo - (CoverageParameters.instrumentDirectories ()) + let (assemblies, assemblyNames) = + prepareTargetFiles + fromInfo + toInfo + targetInfo + (CoverageParameters.instrumentDirectories ()) - Output.info - <| CommandLine.Format.Local("reportingto", report) + Output.info + <| CommandLine.Format.Local("reportingto", report) - let reporter, document = selectReportGenerator () + let reporter, document = selectReportGenerator () - let visitors = - [ reporter - Instrument.instrumentGenerator assemblyNames ] + let visitors = + [ reporter + Instrument.instrumentGenerator assemblyNames ] - Visitor.visit visitors assemblies - Zip.save document report CoverageParameters.zipReport.Value + Visitor.visit visitors assemblies + Zip.save document report CoverageParameters.zipReport.Value - if CoverageParameters.collect.Value then - Runner.setRecordToFile report + if CoverageParameters.collect.Value then + Runner.setRecordToFile report - CommandLine.processTrailingArguments rest (toInfo |> Seq.head)) - 255 - true + CommandLine.processTrailingArguments rest (toInfo |> Seq.head)) + 255 + true - CommandLine.reportErrors - "Instrumentation" - (dotnetBuild && CoverageParameters.inplace.Value) + CommandLine.reportErrors + "Instrumentation" + (dotnetBuild && CoverageParameters.inplace.Value) - result + result let internal main arguments = let first = @@ -650,38 +726,38 @@ module internal Main = match first with | Select "Runner" _ -> - Runner.init () - Runner.doCoverage arguments (declareOptions ()) + Runner.init () + Runner.doCoverage arguments (declareOptions ()) | Select "ImportModule" _ -> - let here = - Assembly.GetExecutingAssembly().Location - |> Path.GetDirectoryName - - [ "../netcoreapp2.0" - "../netstandard2.0" - "../any" ] - |> Seq.map - (fun d -> - canonicalPath( - Path.Combine(Path.Combine(here, d), "AltCover.PowerShell.dll") - )) - |> Seq.filter File.Exists - |> Seq.tryHead - |> Option.map (sprintf "Import-Module %A") - |> Option.iter Output.info - - 0 + let here = + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName + + [ "../netcoreapp2.0" + "../netstandard2.0" + "../any" ] + |> Seq.map + (fun d -> + canonicalPath ( + Path.Combine(Path.Combine(here, d), "AltCover.PowerShell.dll") + )) + |> Seq.filter File.Exists + |> Seq.tryHead + |> Option.map (sprintf "Import-Module %A") + |> Option.iter Output.info + + 0 | Select "version" _ -> - CommandLine.writeResourceWithFormatItems - "AltCover.Version" - [| AssemblyVersionInformation.AssemblyFileVersion |] - false + CommandLine.writeResourceWithFormatItems + "AltCover.Version" + [| AssemblyVersionInformation.AssemblyFileVersion |] + false - 0 + 0 | _ -> doInstrumentation arguments // mocking point [] - let mutable internal effectiveMain = I.main \ No newline at end of file + let mutable internal effectiveMain = I.main diff --git a/AltCover.Engine/Metadata.fs b/AltCover.Engine/Metadata.fs index 92aeb60b4..c343398a7 100644 --- a/AltCover.Engine/Metadata.fs +++ b/AltCover.Engine/Metadata.fs @@ -8,27 +8,35 @@ open System.IO.Compression open Mono.Cecil.Cil module internal Metadata = - let private squash (source:byte[]) = + let private squash (source: byte []) = use squashed = new MemoryStream() // Get deflation working with this one weird trick // Dispose the deflate stream w/o closing the one it points at! do - use compress = new DeflateStream(squashed, CompressionMode.Compress, true) + use compress = + new DeflateStream(squashed, CompressionMode.Compress, true) + compress.Write(source, 0, source.Length) - let crushed = Array.create (int squashed.Length) 0uy - squashed.Seek (0L, SeekOrigin.Begin) |> ignore - squashed.Read (crushed, 0, crushed.Length) |> ignore + + let crushed = + Array.create (int squashed.Length) 0uy + + squashed.Seek(0L, SeekOrigin.Begin) |> ignore + + squashed.Read(crushed, 0, crushed.Length) + |> ignore + crushed - let internal getCompressedSource (embed:EmbeddedSourceDebugInformation) = + let internal getCompressedSource (embed: EmbeddedSourceDebugInformation) = let datamake = Maybe embed.Compress squash id let data = datamake embed.Content Convert.ToBase64String data - [] - let internal getSource (record:Document) = + [] + let internal getSource (record: Document) = record.CustomDebugInformations |> Seq.tryFind (fun c -> c.Kind = CustomDebugInformationKind.EmbeddedSource) |> Option.map (fun c -> getCompressedSource (c :?> EmbeddedSourceDebugInformation)) diff --git a/AltCover.Engine/NativeJson.fs b/AltCover.Engine/NativeJson.fs index 17cb9902c..07590d6dc 100644 --- a/AltCover.Engine/NativeJson.fs +++ b/AltCover.Engine/NativeJson.fs @@ -434,12 +434,12 @@ module | '\r' -> sb.Append("\\r") | '\t' -> sb.Append("\\t") | h when (int h) >= 128 || Array.get allowed (int h) = 0uy -> - sb - .Append("\\u") - .Append( - ((int) c) - .ToString("X4", CultureInfo.InvariantCulture) - ) + sb + .Append("\\u") + .Append( + ((int) c) + .ToString("X4", CultureInfo.InvariantCulture) + ) | _ -> sb.Append(c)) builder s @@ -673,7 +673,10 @@ module w |> append (slugs.[9]) - |> (if method.Lines |> Seq.isEmpty then append else appendLine) ("\"Lines\": {") + |> (if method.Lines |> Seq.isEmpty then + append + else + appendLine) ("\"Lines\": {") |> ifNotEmpty method.Lines lineToBuilder id post |> appendLine ("},") @@ -692,12 +695,10 @@ module >> append (slugs.[9]) >> appendLine ("\"SeqPnts\": [")) id - |> if Seq.isEmpty method.SeqPnts - then id + |> if Seq.isEmpty method.SeqPnts then + id else - newLine - >> append (slugs.[10]) - >> append ("]") + newLine >> append (slugs.[10]) >> append ("]") // After SeqPnts, now Tracking |> methodTrackingToBuilder method @@ -750,12 +751,14 @@ module let internal summaryElement () = let zero name = XAttribute(XName.Get name, 0) + XElement( XName.Get "Summary", zero "numBranchPoints", zero "visitedBranchPoints", zero "numSequencePoints", - zero "visitedSequencePoints") + zero "visitedSequencePoints" + ) let internal buildSummary (m: XContainer) = let sd = summaryElement () @@ -780,51 +783,57 @@ module value let internal buildMethodElement - (table:Dictionary) (item:XElement) - name fileId = - tryGetValueOrDefault - table - name - (fun () -> - let m2 = - XElement( - XName.Get "Method", - XAttribute(XName.Get "visited", false), - XAttribute(XName.Get "cyclomaticComplexity", 1), - XAttribute(XName.Get "sequenceCoverage", 0), - XAttribute(XName.Get "branchCoverage", 0), - XAttribute(XName.Get "isConstructor", false), - XAttribute(XName.Get "isStatic", false), - XAttribute(XName.Get "isGetter", false), - XAttribute(XName.Get "isSetter", false) - ) - - let sd = buildSummary m2 - - [ "MetadataToken", "0"; "Name", name ] - |> Seq.iter - (fun (name, value) -> - let x = XElement(XName.Get name) - x.Value <- value - m2.Add x) - - let f = - XElement(XName.Get "FileRef", XAttribute(XName.Get "uid", fileId)) - - m2.Add f - item.Add m2 - m2) + (table: Dictionary) + (item: XElement) + name + fileId + = + tryGetValueOrDefault + table + name + (fun () -> + let m2 = + XElement( + XName.Get "Method", + XAttribute(XName.Get "visited", false), + XAttribute(XName.Get "cyclomaticComplexity", 1), + XAttribute(XName.Get "sequenceCoverage", 0), + XAttribute(XName.Get "branchCoverage", 0), + XAttribute(XName.Get "isConstructor", false), + XAttribute(XName.Get "isStatic", false), + XAttribute(XName.Get "isGetter", false), + XAttribute(XName.Get "isSetter", false) + ) + + let sd = buildSummary m2 + + [ "MetadataToken", "0"; "Name", name ] + |> Seq.iter + (fun (name, value) -> + let x = XElement(XName.Get name) + x.Value <- value + m2.Add x) + + let f = + XElement(XName.Get "FileRef", XAttribute(XName.Get "uid", fileId)) + + m2.Add f + item.Add m2 + m2) let internal makeSummary (nb: int) (vb: int) (ns: int) (vs: int) (sd: XElement) = sd.Attribute(XName.Get "numBranchPoints").Value <- nb.ToString( CultureInfo.InvariantCulture ) + sd.Attribute(XName.Get "visitedBranchPoints").Value <- vb.ToString( CultureInfo.InvariantCulture ) + sd.Attribute(XName.Get "numSequencePoints").Value <- ns.ToString( CultureInfo.InvariantCulture ) + sd.Attribute(XName.Get "visitedSequencePoints").Value <- vs.ToString( CultureInfo.InvariantCulture ) @@ -835,26 +844,36 @@ module [] + [] let internal methodToXml - (table:Dictionary) + (table: Dictionary) (fileId: int) (item: XElement) (method: KeyValuePair) = - let m = buildMethodElement table item method.Key fileId + let m = + buildMethodElement table item method.Key fileId // conditional - let sp = m.Descendants("SequencePoints".X) - |> Seq.tryHead - |> Option.defaultWith (fun () -> let tmp = XElement(XName.Get "SequencePoints") - m.Add tmp - tmp) - - let bp = m.Descendants("BranchPoints".X) - |> Seq.tryHead - |> Option.defaultWith (fun () -> let tmp = XElement(XName.Get "BranchPoints") - m.Add tmp - tmp) + let sp = + m.Descendants("SequencePoints".X) + |> Seq.tryHead + |> Option.defaultWith + (fun () -> + let tmp = XElement(XName.Get "SequencePoints") + m.Add tmp + tmp) + + let bp = + m.Descendants("BranchPoints".X) + |> Seq.tryHead + |> Option.defaultWith + (fun () -> + let tmp = XElement(XName.Get "BranchPoints") + m.Add tmp + tmp) let value = method.Value let bec = Dictionary() @@ -893,6 +912,7 @@ module x |> Seq.distinctBy (fun bx -> bx.EndOffset) |> Seq.length) + m.Attribute(XName.Get "cyclomaticComplexity").Value <- (1 + targets) .ToString(CultureInfo.InvariantCulture) @@ -952,32 +972,58 @@ module let sd = m.Descendants("Summary".X) |> Seq.head let branches = bp.Descendants("BranchPoint".X) let nb = branches |> Seq.length - let vb = branches |> Seq.filter (fun x -> x.Attribute("vc".X).Value <> "0") - |> Seq.length + + let vb = + branches + |> Seq.filter (fun x -> x.Attribute("vc".X).Value <> "0") + |> Seq.length + let points = sp.Descendants("SequencePoint".X) let ns = points |> Seq.length - let vs = points |> Seq.filter (fun x -> x.Attribute("vc".X).Value <> "0") - |> Seq.length + + let vs = + points + |> Seq.filter (fun x -> x.Attribute("vc".X).Value <> "0") + |> Seq.length if ns > 0 then - let mp = m.Descendants("MethodPoint".X) |> Seq.tryHead - |> Option.defaultWith (fun () -> let tmp = XElement(XName.Get "MethodPoint", XAttribute(XName.Get "vc", "0")) - m.Add tmp - tmp) - let mvc = points // not Seq.max as that exposes repeated calls to enumerator.Current when bootstrapping - |> Seq.fold (fun max x -> let tmp = x.Attribute("vc".X).Value |> Int32.TryParse |> snd - if tmp > max then tmp else max) 0 // know this is a hard floor + let mp = + m.Descendants("MethodPoint".X) + |> Seq.tryHead + |> Option.defaultWith + (fun () -> + let tmp = + XElement(XName.Get "MethodPoint", XAttribute(XName.Get "vc", "0")) + + m.Add tmp + tmp) + + let mvc = + points // not Seq.max as that exposes repeated calls to enumerator.Current when bootstrapping + |> Seq.fold + (fun max x -> + let tmp = + x.Attribute("vc".X).Value |> Int32.TryParse |> snd + + if tmp > max then tmp else max) + 0 // know this is a hard floor + mp.Attribute("vc".X).Value <- mvc.ToString(CultureInfo.InvariantCulture) // adjust to match OpenCover values for branches - makeSummary (nb.Increment (nb > 0 || ns > 0)) - (vb.Increment (vb > 0 || vs > 0)) ns vs sd + makeSummary (nb.Increment(nb > 0 || ns > 0)) (vb.Increment(vb > 0 || vs > 0)) ns vs sd [] - let internal methodsToXml (fileId: int) (item: XElement) (table:Dictionary) (methods: Methods) = - methods |> Seq.iter (methodToXml table fileId item) + let internal methodsToXml + (fileId: int) + (item: XElement) + (table: Dictionary) + (methods: Methods) + = + methods + |> Seq.iter (methodToXml table fileId item) let private valueOf (x: XElement) (name: string) = x.Attribute(XName.Get name).Value @@ -1001,7 +1047,6 @@ module makeSummary nb vb ns vs sd - [] @@ -1032,7 +1077,10 @@ module item.Elements(XName.Get "Methods") |> Seq.head methodsToXml fileId next methodtable kvp.Value - let sd = item.Descendants("Summary".X) |> Seq.head + + let sd = + item.Descendants("Summary".X) |> Seq.head + summarize sd item "Method") [ Seq.tryFind(fun kvp -> kvp.Key = "\u00ABAltCover.embed\u00BB") - |> Option.map (fun kvp -> kvp.Value.Keys |> Seq.tryHead) - |> Option.flatten - |> Option.iter (fun embed -> item.Add(XAttribute(XName.Get "altcover.embed", embed))) + |> Seq.tryFind (fun kvp -> kvp.Key = "\u00ABAltCover.embed\u00BB") + |> Option.bind (fun kvp -> kvp.Value.Keys |> Seq.tryHead) + |> Option.iter + (fun embed -> item.Add(XAttribute(XName.Get "altcover.embed", embed))) files.Add item classesToXml i classTable methodTable kvp.Value) @@ -1152,10 +1200,12 @@ module |> Seq.sortBy (fun sp -> let offset = sp.Attribute(XName.Get "fileid") - let topword = offset - |> Option.ofObj - |> Option.map(fun x -> x.Value |> Int64.TryParse |> snd) - |> Option.defaultValue 0L + + let topword = + offset + |> Option.ofObj + |> Option.map (fun x -> x.Value |> Int64.TryParse |> snd) + |> Option.defaultValue 0L let sl = sp.Attribute(XName.Get "sl").Value @@ -1203,15 +1253,15 @@ module #if RUNNER // Instrumentation --------------------------------------------------------- - [] - let injectEmbed (c:Classes) (embed:string) = + [] + let injectEmbed (c: Classes) (embed: string) = if embed |> String.IsNullOrWhiteSpace |> not then let dummy = Method.Create(None) let m = Methods() - m.Add (embed, dummy) - c.Add ("\u00ABAltCover.embed\u00BB", m) + m.Add(embed, dummy) + c.Add("\u00ABAltCover.embed\u00BB", m) [] type internal JsonContext = @@ -1250,7 +1300,7 @@ module VisibleMethod = m.VisibleMethod Track = m.Track } - let getMethodRecord (s: JsonContext) (doc: string) (record:Cil.Document) = + let getMethodRecord (s: JsonContext) (doc: string) (record: Cil.Document) = let visibleMethodName = s.VisibleMethod.FullName let visibleTypeName = s.VisibleMethod.DeclaringType.FullName @@ -1258,27 +1308,29 @@ module match s.Documents.TryGetValue doc with | true, c -> c | _ -> - let c = Classes() - s.Documents.Add(doc, c) - record - |> Metadata.getSource - |> Option.iter (injectEmbed c) - c + let c = Classes() + s.Documents.Add(doc, c) + + record + |> Metadata.getSource + |> Option.iter (injectEmbed c) + + c let methods = match classes.TryGetValue visibleTypeName with | true, m -> m | _ -> - let m = Methods() - classes.Add(visibleTypeName, m) - m + let m = Methods() + classes.Add(visibleTypeName, m) + m match methods.TryGetValue visibleMethodName with | true, m -> m | _ -> - let m = Method.Create(s.Track) - methods.Add(visibleMethodName, m) - m + let m = Method.Create(s.Track) + methods.Add(visibleMethodName, m) + m let visitMethodPoint (s: JsonContext) (e: StatementEntry) = if e.Interesting then @@ -1286,9 +1338,12 @@ module |> Option.iter (fun codeSegment -> let doc = - codeSegment.Document.Url |> Visitor.sourceLinkMapping + codeSegment.Document.Url + |> Visitor.sourceLinkMapping + + let mplus = + getMethodRecord s doc codeSegment.Document - let mplus = getMethodRecord s doc codeSegment.Document mplus.Lines.[codeSegment.StartLine] <- int e.DefaultVisitCount mplus.SeqPnts.Add @@ -1310,7 +1365,8 @@ module b.SequencePoint.Document.Url |> Visitor.sourceLinkMapping - let mplus = getMethodRecord s doc b.SequencePoint.Document + let mplus = + getMethodRecord s doc b.SequencePoint.Document mplus.Branches.Add { Line = b.SequencePoint.StartLine diff --git a/AltCover.Engine/OpenCover.fs b/AltCover.Engine/OpenCover.fs index c38a9180d..782e49bfc 100644 --- a/AltCover.Engine/OpenCover.fs +++ b/AltCover.Engine/OpenCover.fs @@ -67,7 +67,8 @@ module internal OpenCover = let internal safeMultiply x y = try Checked.op_Multiply x <| Math.Max(1, y) - with :? OverflowException -> Int32.MaxValue + with + | :? OverflowException -> Int32.MaxValue module internal I = let internal setChain (xbranch: XElement) branch = @@ -79,11 +80,11 @@ module internal OpenCover = match chain with | [] -> null | l -> - String.Join( - " ", - l - |> Seq.map (fun i -> i.ToString(CultureInfo.InvariantCulture)) - ) + String.Join( + " ", + l + |> Seq.map (fun i -> i.ToString(CultureInfo.InvariantCulture)) + ) ) let internal reportGenerator () = @@ -153,24 +154,26 @@ module internal OpenCover = element.Add(XElement("ModuleName".X, def.Assembly.Name.Name)) let (files, embeds) = - if instrumented then - element.Add(XElement("Files".X)) - def - |> ProgramDatabase.getModuleDocuments - |> Seq.fold (fun f d -> let key = d.Url - |> Visitor.sourceLinkMapping - let map = snd f - - let embed = d - |> Metadata.getSource - |> Option.map (fun s -> Map.add key s map) - |> Option.defaultValue map - - (key - |> recordFile (fst f) - |> fst, - embed)) (s.Files, s.Embeds) - else (s.Files, s.Embeds) + if instrumented then + element.Add(XElement("Files".X)) + + def + |> ProgramDatabase.getModuleDocuments + |> Seq.fold + (fun f d -> + let key = d.Url |> Visitor.sourceLinkMapping + let map = snd f + + let embed = + d + |> Metadata.getSource + |> Option.map (fun s -> Map.add key s map) + |> Option.defaultValue map + + (key |> recordFile (fst f) |> fst, embed)) + (s.Files, s.Embeds) + else + (s.Files, s.Embeds) let classes = XElement("Classes".X) element.Add(classes) @@ -308,7 +311,10 @@ module internal OpenCover = let visitCodeSegment (s: OpenCoverContext) (codeSegment: SeqPnt) i vc = let fileset, ref = - recordFile s.Files (codeSegment.Document.Url |> Visitor.sourceLinkMapping) + recordFile + s.Files + (codeSegment.Document.Url + |> Visitor.sourceLinkMapping) let element = methodPointElement codeSegment ref i vc let head = s.Stack |> Seq.head @@ -336,7 +342,7 @@ module internal OpenCover = match (e.Interesting, e.SeqPnt, s.Excluded) with | (true, Some codeSegment, Nothing) -> - visitCodeSegment s codeSegment e.Uid e.DefaultVisitCount + visitCodeSegment s codeSegment e.Uid e.DefaultVisitCount | _ -> s let visitGoTo s branch = @@ -427,8 +433,8 @@ module internal OpenCover = (fun (np0, bec, sq: XElement) x -> match x.Name.LocalName with | "SequencePoint" -> - sq.SetAttributeValue("bec".X, bec) - (safeMultiply np0 bec, 0, x) + sq.SetAttributeValue("bec".X, bec) + (safeMultiply np0 bec, 0, x) | _ -> (np0, bec + 1, sq)) (1, 0, sp.Head) @@ -651,9 +657,11 @@ module internal OpenCover = XAttribute("uid".X, v), XAttribute("fullPath".X, k) ) + f.Add(file) - if s.Embeds.ContainsKey k - then file.Add(XAttribute("altcover.embed".X, s.Embeds.Item k)))) + + if s.Embeds.ContainsKey k then + file.Add(XAttribute("altcover.embed".X, s.Embeds.Item k)))) { s with Stack = tail diff --git a/AltCover.Engine/PostProcess.fs b/AltCover.Engine/PostProcess.fs index 9f71b34b8..2d1a7e946 100644 --- a/AltCover.Engine/PostProcess.fs +++ b/AltCover.Engine/PostProcess.fs @@ -34,28 +34,28 @@ type internal XmlElementAbstraction = member self.CreateElement name = match self with | XmlEl x -> - name - |> x.OwnerDocument.CreateElement - |> XmlElementAbstraction.XmlEl + name + |> x.OwnerDocument.CreateElement + |> XmlElementAbstraction.XmlEl | XEl _ -> - name - |> XName.Get - |> Linq.XElement - |> XmlElementAbstraction.XEl + name + |> XName.Get + |> Linq.XElement + |> XmlElementAbstraction.XEl member self.GetElementsByTagName name = match self with | XmlEl x -> - use elements = x.GetElementsByTagName name + use elements = x.GetElementsByTagName name - elements - |> Seq.cast - |> Seq.map XmlElementAbstraction.XmlEl - |> Seq.toList + elements + |> Seq.cast + |> Seq.map XmlElementAbstraction.XmlEl + |> Seq.toList | XEl x -> - x.Descendants(XName.Get name) - |> Seq.map XmlElementAbstraction.XEl - |> Seq.toList + x.Descendants(XName.Get name) + |> Seq.map XmlElementAbstraction.XEl + |> Seq.toList member self.GetAttribute name = match self with @@ -66,33 +66,33 @@ type internal XmlElementAbstraction = match self with | XmlEl x -> x.SetAttribute(name, value) | XEl x -> - let attr = x.Attribute(XName.Get name) + let attr = x.Attribute(XName.Get name) - if attr |> isNull then - x.Add(Linq.XAttribute(XName.Get name, value)) - else - attr.Value <- value + if attr |> isNull then + x.Add(Linq.XAttribute(XName.Get name, value)) + else + attr.Value <- value member self.SetNSAttribute name ns value = match self with | XmlEl x -> x.SetAttribute(name, ns, value) |> ignore | XEl x -> - let attr = x.Attribute(XName.Get(name, ns)) + let attr = x.Attribute(XName.Get(name, ns)) - if attr |> isNull then - x.Add(Linq.XAttribute(XName.Get(name, ns), value)) - else - attr.Value <- value + if attr |> isNull then + x.Add(Linq.XAttribute(XName.Get(name, ns), value)) + else + attr.Value <- value member self.Attributes = match self with | XmlEl x -> - x.Attributes - |> Seq.cast - |> Seq.map XmlAttributeAbstraction.XmlAttr + x.Attributes + |> Seq.cast + |> Seq.map XmlAttributeAbstraction.XmlAttr | XEl x -> - x.Attributes() - |> Seq.map XmlAttributeAbstraction.XAttr + x.Attributes() + |> Seq.map XmlAttributeAbstraction.XAttr member self.Name = match self with @@ -117,24 +117,24 @@ type internal XmlAbstraction = member self.Elements name = match self with | XmlDoc x -> - use elements = - x.DocumentElement.SelectNodes("//" + name) + use elements = + x.DocumentElement.SelectNodes("//" + name) - elements - |> Seq.cast - |> Seq.map XmlElementAbstraction.XmlEl - |> Seq.toList + elements + |> Seq.cast + |> Seq.map XmlElementAbstraction.XmlEl + |> Seq.toList | XDoc x -> - x.Descendants(XName.Get name) - |> Seq.map XmlElementAbstraction.XEl - |> Seq.toList + x.Descendants(XName.Get name) + |> Seq.map XmlElementAbstraction.XEl + |> Seq.toList member self.RootElement = match self with | XmlDoc x -> x.DocumentElement |> XmlElementAbstraction.XmlEl | XDoc x -> - (x.Elements() |> Seq.head) - |> XmlElementAbstraction.XEl + (x.Elements() |> Seq.head) + |> XmlElementAbstraction.XEl [] module internal PostProcess = @@ -247,259 +247,263 @@ module internal PostProcess = match format with | ReportFormat.OpenCoverWithTracking | ReportFormat.OpenCover -> - if counts.ContainsKey Track.Entry then - fillTrackedVisits document counts.[Track.Entry] "entry" + if counts.ContainsKey Track.Entry then + fillTrackedVisits document counts.[Track.Entry] "entry" - if counts.ContainsKey Track.Exit then - fillTrackedVisits document counts.[Track.Exit] "exit" + if counts.ContainsKey Track.Exit then + fillTrackedVisits document counts.[Track.Exit] "exit" - let scoreToString raw = - (sprintf "%.2f" raw) - .TrimEnd([| '0' |]) - .TrimEnd([| '.' |]) + let scoreToString raw = + (sprintf "%.2f" raw) + .TrimEnd([| '0' |]) + .TrimEnd([| '.' |]) - let stringToScore (node: XmlElementAbstraction) name = - node.GetAttribute(name).InvariantParseDouble() - |> snd + let stringToScore (node: XmlElementAbstraction) name = + node.GetAttribute(name).InvariantParseDouble() + |> snd - let percentCover visits points = - if points = 0 then - "0" + let percentCover visits points = + if points = 0 then + "0" + else + ((float (visits * 100)) / (float points)) + |> scoreToString + + let setSummary + (x: XmlElementAbstraction) + pointVisits + branchVisits + methodVisits + classVisits + ptcover + brcover + minCrap + maxCrap + = + x.GetElementsByTagName("Summary") + |> Seq.tryHead + |> Option.iter + (fun s -> + let minc = + (if minCrap = Double.MaxValue then + 0.0 + else + minCrap) + |> scoreToString + + let maxc = + (if maxCrap = Double.MinValue then + 0.0 + else + maxCrap) + |> scoreToString + + s.SetAttribute "visitedSequencePoints" (sprintf "%d" pointVisits) + s.SetAttribute "visitedBranchPoints" (sprintf "%d" branchVisits) + s.SetAttribute "visitedMethods" (sprintf "%d" methodVisits) + + classVisits + |> Option.iter ( + (sprintf "%d") + >> (s.SetAttribute "visitedClasses") + ) + + s.SetAttribute "branchCoverage" brcover + s.SetAttribute "sequenceCoverage" ptcover + s.SetAttribute "minCrapScore" minc + s.SetAttribute "maxCrapScore" maxc) + + let computeBranchExitCount + (anchor: XmlElementAbstraction) + (sp: XmlElementAbstraction list) + bp + = + let tail = anchor.CreateElement("SequencePoint") + + tail.SetAttribute + orderAttr + (Int32.MaxValue.ToString(CultureInfo.InvariantCulture)) + + let nodes = List.concat [ sp; [ tail ]; bp ] + + let interleave = + nodes + |> Seq.sortBy (fun x -> x.GetAttribute(orderAttr) |> Int32.TryParse |> snd) + + interleave + |> Seq.fold + (fun (bev, sq: XmlElementAbstraction) x -> + match x.Name with + | "SequencePoint" -> + sq.SetAttribute "bev" (sprintf "%d" bev) + (0, x) + | _ -> + (bev + + (if x.GetAttribute("vc") = "0" then + 0 + else + 1), + sq)) + (0, nodes.[0]) + |> ignore + + // https://blog.ndepend.com/crap-metric-thing-tells-risk-code/ + // Let CC(m) = cyclomatic complexity of a method and + // U(m) = the percentage of a method not covered by unit tests. + // CRAP(m) = CC(m)^2 * U(m)^3 + CC(m). + let crapScore forceVisited (method: XmlElementAbstraction) = + let coverage = + if forceVisited then + 100.0 else - ((float (visits * 100)) / (float points)) - |> scoreToString - - let setSummary - (x: XmlElementAbstraction) - pointVisits - branchVisits - methodVisits - classVisits - ptcover - brcover - minCrap - maxCrap - = - x.GetElementsByTagName("Summary") - |> Seq.tryHead - |> Option.iter - (fun s -> - let minc = - (if minCrap = Double.MaxValue then - 0.0 - else - minCrap) - |> scoreToString - - let maxc = - (if maxCrap = Double.MinValue then - 0.0 - else - maxCrap) - |> scoreToString - - s.SetAttribute "visitedSequencePoints" (sprintf "%d" pointVisits) - s.SetAttribute "visitedBranchPoints" (sprintf "%d" branchVisits) - s.SetAttribute "visitedMethods" (sprintf "%d" methodVisits) - - classVisits - |> Option.iter - ((sprintf "%d") >> (s.SetAttribute "visitedClasses")) - - s.SetAttribute "branchCoverage" brcover - s.SetAttribute "sequenceCoverage" ptcover - s.SetAttribute "minCrapScore" minc - s.SetAttribute "maxCrapScore" maxc) - - let computeBranchExitCount - (anchor: XmlElementAbstraction) - (sp: XmlElementAbstraction list) - bp - = - let tail = anchor.CreateElement("SequencePoint") - - tail.SetAttribute - orderAttr - (Int32.MaxValue.ToString(CultureInfo.InvariantCulture)) - - let nodes = List.concat [ sp; [ tail ]; bp ] - - let interleave = - nodes - |> Seq.sortBy (fun x -> x.GetAttribute(orderAttr) |> Int32.TryParse |> snd) - - interleave - |> Seq.fold - (fun (bev, sq: XmlElementAbstraction) x -> - match x.Name with - | "SequencePoint" -> - sq.SetAttribute "bev" (sprintf "%d" bev) - (0, x) - | _ -> - (bev - + (if x.GetAttribute("vc") = "0" then - 0 - else - 1), - sq)) - (0, nodes.[0]) - |> ignore - - // https://blog.ndepend.com/crap-metric-thing-tells-risk-code/ - // Let CC(m) = cyclomatic complexity of a method and - // U(m) = the percentage of a method not covered by unit tests. - // CRAP(m) = CC(m)^2 * U(m)^3 + CC(m). - let crapScore forceVisited (method: XmlElementAbstraction) = - let coverage = - if forceVisited then - 100.0 - else - let cover = stringToScore method "sequenceCoverage" + let cover = stringToScore method "sequenceCoverage" - if cover > 0.0 then - cover - else - stringToScore method "branchCoverage" + if cover > 0.0 then + cover + else + stringToScore method "branchCoverage" - let complexity = - stringToScore method "cyclomaticComplexity" + let complexity = + stringToScore method "cyclomaticComplexity" - let raw = - Math.Pow(complexity, 2.0) - * Math.Pow((1.0 - (coverage / 100.0)), 3.0) - + complexity + let raw = + Math.Pow(complexity, 2.0) + * Math.Pow((1.0 - (coverage / 100.0)), 3.0) + + complexity - let score = raw |> scoreToString - method.SetAttribute "crapScore" score - raw + let score = raw |> scoreToString + method.SetAttribute "crapScore" score + raw - let updateMethod - (dict: Dictionary) - (vb, vs, vm: int, pt, br, minc, maxc) - (method: XmlElementAbstraction) - = - let sp = - method.GetElementsByTagName("SequencePoint") + let updateMethod + (dict: Dictionary) + (vb, vs, vm: int, pt, br, minc, maxc) + (method: XmlElementAbstraction) + = + let sp = + method.GetElementsByTagName("SequencePoint") - let bp = - method.GetElementsByTagName("BranchPoint") + let bp = + method.GetElementsByTagName("BranchPoint") - let mp = - method.GetElementsByTagName("MethodPoint") + let mp = + method.GetElementsByTagName("MethodPoint") - let count = sp |> List.length - let rawCount = bp |> List.length + let count = sp |> List.length + let rawCount = bp |> List.length - // inconsistent name to shut Gendarme up - let numBranches = rawCount + Math.Sign(count + rawCount) + // inconsistent name to shut Gendarme up + let numBranches = rawCount + Math.Sign(count + rawCount) - if count > 0 then - copyFillMethodPoint mp sp - else - fillMethodPoint mp method dict + if count > 0 then + copyFillMethodPoint mp sp + else + fillMethodPoint mp method dict - let pointVisits = visitCount sp - let b0 = visitCount bp - let branchVisits = b0 + Math.Sign b0 - let mVisits = visitCount mp + let pointVisits = visitCount sp + let b0 = visitCount bp + let branchVisits = b0 + Math.Sign b0 + let mVisits = visitCount mp - let methodVisit = - if pointVisits > 0 || b0 > 0 then - 1 - else - 0 - - if methodVisit = 1 || mVisits > 0 then - method.SetAttribute "visited" "true" - - // zero visits still need to fill in CRAP score - let cover = percentCover pointVisits count - let bcover = percentCover branchVisits numBranches - method.SetAttribute "sequenceCoverage" cover - method.SetAttribute "branchCoverage" bcover - let raw = crapScore (mVisits > count) method - - // degenerate methods don't contribute to counts by default - let (maxcrap, mincrap) = - if count > 0 || rawCount > 0 then - (Math.Max(maxc, raw), Math.Min(minc, raw)) - else - (maxc, minc) - - setSummary method pointVisits branchVisits methodVisit None cover bcover raw raw - computeBranchExitCount method sp bp - - (vb + branchVisits, - vs + pointVisits, - vm + methodVisit, - pt + count, - br + numBranches, - mincrap, - maxcrap) - - let updateClass - (dict: Dictionary) - (vb, vs, vm, vc, pt, br, minc0, maxc0) - (``class``: XmlElementAbstraction) - = - let (cvb, cvs, cvm, cpt, cbr, minc, maxc) = - ``class``.GetElementsByTagName("Method") - |> Seq.fold - (updateMethod dict) - (0, 0, 0, 0, 0, Double.MaxValue, Double.MinValue) - - let cover = percentCover cvs cpt - let bcover = percentCover cvb cbr - - let cvc = if cvm > 0 then 1 else 0 - setSummary ``class`` cvs cvb cvm (Some cvc) cover bcover minc maxc - - (vb + cvb, - vs + cvs, - vm + cvm, - vc + cvc, - pt + cpt, - br + cbr, - Math.Min(minc, minc0), - Math.Max(maxc, maxc0)) - - let updateModule - (counts: Dictionary>) - (vb, vs, vm, vc, pt, br, minc0, maxc0) - (``module``: XmlElementAbstraction) - = - let dict = - match (tryGetValue counts) - <| ``module``.GetAttribute("hash") with - | (false, _) -> Dictionary() - | (true, d) -> d - - let (cvb, cvs, cvm, cvc, cpt, cbr, minc, maxc) = - ``module``.GetElementsByTagName("Class") - |> Seq.fold - (dict |> updateClass) - (0, 0, 0, 0, 0, 0, Double.MaxValue, Double.MinValue) - - let cover = percentCover cvs cpt - let bcover = percentCover cvb cbr - setSummary ``module`` cvs cvb cvm (Some cvc) cover bcover minc maxc - - (vb + cvb, - vs + cvs, - vm + cvm, - vc + cvc, - pt + cpt, - br + cbr, - Math.Min(minc, minc0), - Math.Max(maxc, maxc0)) - - let (vb, vs, vm, vc, pt, br, minc, maxc) = - document.Elements "Module" + let methodVisit = + if pointVisits > 0 || b0 > 0 then + 1 + else + 0 + + if methodVisit = 1 || mVisits > 0 then + method.SetAttribute "visited" "true" + + // zero visits still need to fill in CRAP score + let cover = percentCover pointVisits count + let bcover = percentCover branchVisits numBranches + method.SetAttribute "sequenceCoverage" cover + method.SetAttribute "branchCoverage" bcover + let raw = crapScore (mVisits > count) method + + // degenerate methods don't contribute to counts by default + let (maxcrap, mincrap) = + if count > 0 || rawCount > 0 then + (Math.Max(maxc, raw), Math.Min(minc, raw)) + else + (maxc, minc) + + setSummary method pointVisits branchVisits methodVisit None cover bcover raw raw + computeBranchExitCount method sp bp + + (vb + branchVisits, + vs + pointVisits, + vm + methodVisit, + pt + count, + br + numBranches, + mincrap, + maxcrap) + + let updateClass + (dict: Dictionary) + (vb, vs, vm, vc, pt, br, minc0, maxc0) + (``class``: XmlElementAbstraction) + = + let (cvb, cvs, cvm, cpt, cbr, minc, maxc) = + ``class``.GetElementsByTagName("Method") + |> Seq.fold + (updateMethod dict) + (0, 0, 0, 0, 0, Double.MaxValue, Double.MinValue) + + let cover = percentCover cvs cpt + let bcover = percentCover cvb cbr + + let cvc = if cvm > 0 then 1 else 0 + setSummary ``class`` cvs cvb cvm (Some cvc) cover bcover minc maxc + + (vb + cvb, + vs + cvs, + vm + cvm, + vc + cvc, + pt + cpt, + br + cbr, + Math.Min(minc, minc0), + Math.Max(maxc, maxc0)) + + let updateModule + (counts: Dictionary>) + (vb, vs, vm, vc, pt, br, minc0, maxc0) + (``module``: XmlElementAbstraction) + = + let dict = + match + (tryGetValue counts) + <| ``module``.GetAttribute("hash") + with + | (false, _) -> Dictionary() + | (true, d) -> d + + let (cvb, cvs, cvm, cvc, cpt, cbr, minc, maxc) = + ``module``.GetElementsByTagName("Class") |> Seq.fold - (updateModule counts) + (dict |> updateClass) (0, 0, 0, 0, 0, 0, Double.MaxValue, Double.MinValue) - let cover = percentCover vs pt - let bcover = percentCover vb br - setSummary document.RootElement vs vb vm (Some vc) cover bcover minc maxc + let cover = percentCover cvs cpt + let bcover = percentCover cvb cbr + setSummary ``module`` cvs cvb cvm (Some cvc) cover bcover minc maxc + + (vb + cvb, + vs + cvs, + vm + cvm, + vc + cvc, + pt + cpt, + br + cbr, + Math.Min(minc, minc0), + Math.Max(maxc, maxc0)) + + let (vb, vs, vm, vc, pt, br, minc, maxc) = + document.Elements "Module" + |> Seq.fold + (updateModule counts) + (0, 0, 0, 0, 0, 0, Double.MaxValue, Double.MinValue) + + let cover = percentCover vs pt + let bcover = percentCover vb br + setSummary document.RootElement vs vb vm (Some vc) cover bcover minc maxc | _ -> () \ No newline at end of file diff --git a/AltCover.Engine/ProgramDatabase.fs b/AltCover.Engine/ProgramDatabase.fs index cedb1222d..80691d2c7 100644 --- a/AltCover.Engine/ProgramDatabase.fs +++ b/AltCover.Engine/ProgramDatabase.fs @@ -74,13 +74,13 @@ module internal ProgramDatabase = match getPdbFromImage assembly with | None when path |> String.IsNullOrWhiteSpace |> not -> // i.e. assemblies read from disk only - let foldername = Path.GetDirectoryName path - let filename = Path.GetFileName path + let foldername = Path.GetDirectoryName path + let filename = Path.GetFileName path - foldername :: (Seq.toList symbolFolders) - |> Seq.map (I.getSymbolsByFolder filename) - |> Seq.choose id - |> Seq.tryFind (fun _ -> true) + foldername :: (Seq.toList symbolFolders) + |> Seq.map (I.getSymbolsByFolder filename) + |> Seq.choose id + |> Seq.tryFind (fun _ -> true) | pdbpath -> pdbpath // Ensure that we read symbols from the .pdb path we discovered. @@ -90,7 +90,7 @@ module internal ProgramDatabase = getPdbWithFallback assembly |> Option.iter (fun pdbpath -> - let provider : ISymbolReaderProvider = + let provider: ISymbolReaderProvider = if pdbpath.EndsWith(".pdb", StringComparison.OrdinalIgnoreCase) then PdbReaderProvider() :> ISymbolReaderProvider else diff --git a/AltCover.Engine/Report.fs b/AltCover.Engine/Report.fs index 0b9bf9b20..0006634d8 100644 --- a/AltCover.Engine/Report.fs +++ b/AltCover.Engine/Report.fs @@ -25,11 +25,11 @@ module internal Report = "profilerVersion".X, "AltCover " + (System.Diagnostics.FileVersionInfo.GetVersionInfo( - System - .Reflection - .Assembly - .GetExecutingAssembly() - .Location + System + .Reflection + .Assembly + .GetExecutingAssembly() + .Location )) .FileVersion ), @@ -71,14 +71,22 @@ module internal Report = // embed support moduleDef.Module |> ProgramDatabase.getModuleDocuments - |> Seq.iter (fun d -> let key = d.Url - |> Visitor.sourceLinkMapping - d - |> Metadata.getSource - |> Option.iter (fun s -> let x = XElement("altcover.file".X, - XAttribute("document".X, key), - XAttribute("embed".X, s)) - element.Add x)) + |> Seq.iter + (fun d -> + let key = d.Url |> Visitor.sourceLinkMapping + + d + |> Metadata.getSource + |> Option.iter + (fun s -> + let x = + XElement( + "altcover.file".X, + XAttribute("document".X, key), + XAttribute("embed".X, s) + ) + + element.Add x)) element :: s @@ -100,30 +108,37 @@ module internal Report = XAttribute("fullname".X, Naming.fullMethodName methodDef) ) - (head.Elements("altcover.file".X) |> Seq.tryHead + (head.Elements("altcover.file".X) + |> Seq.tryHead |> Option.map (fun x -> x.AddBeforeSelf) - |> Option.defaultValue head.Add) [| element |] + |> Option.defaultValue head.Add) + [| element |] + element :: s let visitMethodPoint (s: list) (head: XElement) (e: StatementEntry) = match e.SeqPnt with | Some codeSegment -> - let element = - XElement( - "seqpnt".X, - XAttribute("visitcount".X, int e.DefaultVisitCount), - XAttribute("line".X, codeSegment.StartLine), - XAttribute("column".X, codeSegment.StartColumn), - XAttribute("endline".X, codeSegment.EndLine), - XAttribute("endcolumn".X, codeSegment.EndColumn), - XAttribute("excluded".X, toExcluded e.Interesting), - XAttribute("document".X, codeSegment.Document.Url |> Visitor.sourceLinkMapping) + let element = + XElement( + "seqpnt".X, + XAttribute("visitcount".X, int e.DefaultVisitCount), + XAttribute("line".X, codeSegment.StartLine), + XAttribute("column".X, codeSegment.StartColumn), + XAttribute("endline".X, codeSegment.EndLine), + XAttribute("endcolumn".X, codeSegment.EndColumn), + XAttribute("excluded".X, toExcluded e.Interesting), + XAttribute( + "document".X, + codeSegment.Document.Url + |> Visitor.sourceLinkMapping ) + ) - if head.IsEmpty then - head.Add(element) - else - head.FirstNode.AddBeforeSelf(element) + if head.IsEmpty then + head.Add(element) + else + head.FirstNode.AddBeforeSelf(element) | None -> () s @@ -139,8 +154,8 @@ module internal Report = | Method m -> visitMethod s head m.Method (m.Inspection.IsInstrumented) | MethodPoint m -> visitMethodPoint s head m | AfterMethod _ -> - if head.IsEmpty then head.Remove() - tail + if head.IsEmpty then head.Remove() + tail | AfterModule _ -> tail | Finish -> s | _ -> s diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 8267dac07..cd7eaecc9 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -58,7 +58,8 @@ type internal SummaryFormat = | ('C', _) -> Many(C :: (SummaryFormat.ToList state)) | _ -> raise (s |> FormatException)) (Many []) - with :? FormatException -> Default + with + | :? FormatException -> Default type internal Threshold = { Statements: uint8 @@ -82,19 +83,19 @@ type internal Threshold = match data with | [] -> result | _ -> - let h = - data - |> List.takeWhile (Char.IsDigit >> not) - |> List.toArray + let h = + data + |> List.takeWhile (Char.IsDigit >> not) + |> List.toArray - let t = - data |> List.skipWhile (Char.IsDigit >> not) + let t = + data |> List.skipWhile (Char.IsDigit >> not) - let h2 = - t |> List.takeWhile Char.IsDigit |> List.toArray + let h2 = + t |> List.takeWhile Char.IsDigit |> List.toArray - let t2 = t |> List.skipWhile Char.IsDigit - partition t2 ((String(h), String(h2)) :: result) + let t2 = t |> List.skipWhile Char.IsDigit + partition t2 ((String(h), String(h2)) :: result) let parse top f t x = let part, v = @@ -148,12 +149,12 @@ type internal Threshold = module internal Runner = - let mutable internal recordingDirectory : Option = None - let mutable internal workingDirectory : Option = None - let internal executable : Option ref = ref None + let mutable internal recordingDirectory: Option = None + let mutable internal workingDirectory: Option = None + let internal executable: Option ref = ref None let internal collect = ref false // ddFlag - let mutable internal threshold : Threshold option = None - let mutable internal output : Option = None + let mutable internal threshold: Threshold option = None + let mutable internal output: Option = None let internal summary = StringBuilder() let mutable internal summaryFormat = SummaryFormat.Default @@ -376,62 +377,65 @@ module internal Runner = (amv, acv) type Category = - { - Number : string; - Visited : string; - Coverage : string; - } + { Number: string + Visited: string + Coverage: string } [] - let private summariseBase (summary: XElement) go (visit: string) (number: string) (precalc: string option) key = + let private summariseBase + (summary: XElement) + go + (visit: string) + (number: string) + (precalc: string option) + key + = let vc = summary.Attribute(visit.X).Value let nc = summary.Attribute(number.X).Value let pc = match precalc with | None -> - if nc = "0" then - "n/a" - else - let vc1 = vc |> Int32.TryParse |> snd |> float + if nc = "0" then + "n/a" + else + let vc1 = vc |> Int32.TryParse |> snd |> float - let nc1 = nc |> Int32.TryParse |> snd |> float + let nc1 = nc |> Int32.TryParse |> snd |> float - Math - .Round(vc1 * 100.0 / nc1, 2) - .ToString(CultureInfo.InvariantCulture) + Math + .Round(vc1 * 100.0 / nc1, 2) + .ToString(CultureInfo.InvariantCulture) | Some x -> summary.Attribute(x.X).Value if go then writeSummary key vc nc pc - { - Number = nc + { Number = nc Visited = vc - Coverage = pc - } + Coverage = pc } let private allTC l classes methods statements branches = - writeTC totalTC "C" classes.Number - writeTC coverTC "C" classes.Visited - writeTC totalTC "M" methods.Number - writeTC coverTC "M" methods.Visited - writeTC totalTC "S" statements.Number - writeTC coverTC "S" statements.Visited - - l - |> Seq.iter - (fun f -> - let tag = - match f with - | R -> "R" - | B -> "B" - | _ -> String.Empty + writeTC totalTC "C" classes.Number + writeTC coverTC "C" classes.Visited + writeTC totalTC "M" methods.Number + writeTC coverTC "M" methods.Visited + writeTC totalTC "S" statements.Number + writeTC coverTC "S" statements.Visited + + l + |> Seq.iter + (fun f -> + let tag = + match f with + | R -> "R" + | B -> "B" + | _ -> String.Empty - if tag |> String.IsNullOrEmpty |> not then - writeTC totalTC tag branches.Number - writeTC coverTC tag branches.Visited) + if tag |> String.IsNullOrEmpty |> not then + writeTC totalTC tag branches.Number + writeTC coverTC tag branches.Visited) [ [] //(result, 0uy, String.Empty) | XML report -> - report - |> match format with - | ReportFormat.NCover -> nCoverSummary - | _ -> openCoverSummary + report + |> match format with + | ReportFormat.NCover -> nCoverSummary + | _ -> openCoverSummary | JSON jtext -> jsonSummary jtext // (result, 0uy, String.Empty) // TODO let best = (result, 0uy, String.Empty) @@ -664,62 +668,62 @@ module internal Runner = match threshold with | None -> [ best ] | Some t -> - let found = - covered - |> List.map (fun d -> d.InvariantParseDouble()) - - let ceil (f: float) (value: float) = - if f <= value && value > 0.0 && f > 0.0 then - None - else - Math.Ceiling(f - value) |> int |> Some - - let sink _ : int option = None - - let funs = - [ (ceil (float t.Statements), t.Statements, "Statements") - (if format = ReportFormat.NCover then - sink - else - ceil (float t.Branches)), - t.Branches, - "Branches" - (ceil (float t.Methods), t.Methods, "Methods") - (if format = ReportFormat.NCover then - sink - else - ceil (float t.AltMethods)), - t.AltMethods, - "AltMethods" - (if format = ReportFormat.NCover || t.Crap = 0uy then - sink - else - (fun c -> ceil c (float t.Crap))), - t.Crap, - "Crap" - (if format = ReportFormat.NCover || t.AltCrap = 0uy then - sink - else - (fun c -> ceil c (float t.AltCrap))), - t.AltCrap, - "AltCrap" ] - - List.zip found funs - |> List.filter (fst >> fst) - |> List.map - (fun (c, (f, x, y)) -> - match c |> snd |> f with - | Some q -> Some(q, x, y) - | None -> None) - |> List.filter Option.isSome - |> List.map Option.get - |> List.filter (fun (a, _, _) -> a >= 0) + let found = + covered + |> List.map (fun d -> d.InvariantParseDouble()) + + let ceil (f: float) (value: float) = + if f <= value && value > 0.0 && f > 0.0 then + None + else + Math.Ceiling(f - value) |> int |> Some + + let sink _ : int option = None + + let funs = + [ (ceil (float t.Statements), t.Statements, "Statements") + (if format = ReportFormat.NCover then + sink + else + ceil (float t.Branches)), + t.Branches, + "Branches" + (ceil (float t.Methods), t.Methods, "Methods") + (if format = ReportFormat.NCover then + sink + else + ceil (float t.AltMethods)), + t.AltMethods, + "AltMethods" + (if format = ReportFormat.NCover || t.Crap = 0uy then + sink + else + (fun c -> ceil c (float t.Crap))), + t.Crap, + "Crap" + (if format = ReportFormat.NCover || t.AltCrap = 0uy then + sink + else + (fun c -> ceil c (float t.AltCrap))), + t.AltCrap, + "AltCrap" ] + + List.zip found funs + |> List.filter (fst >> fst) + |> List.map + (fun (c, (f, x, y)) -> + match c |> snd |> f with + | Some q -> Some(q, x, y) + | None -> None) + |> List.filter Option.isSome + |> List.map Option.get + |> List.filter (fun (a, _, _) -> a >= 0) match possibles with | [] -> best | _ -> possibles |> List.maxBy (fun (a, _, _) -> a) - let mutable internal summaries : (DocumentType -> ReportFormat -> int -> (int * byte * string)) list = + let mutable internal summaries: (DocumentType -> ReportFormat -> int -> (int * byte * string)) list = [] let internal addLCovSummary () = summaries <- LCov.summary :: summaries @@ -835,23 +839,23 @@ module internal Runner = let internal requireRecorderTest recordingDirectory success fail = match recordingDirectory with | None -> - CommandLine.error <- - (CommandLine.resources.GetString "recorderRequired") - :: CommandLine.error + CommandLine.error <- + (CommandLine.resources.GetString "recorderRequired") + :: CommandLine.error - fail + fail | Some path -> - let dll = - Path.Combine(path, "AltCover.Recorder.g.dll") + let dll = + Path.Combine(path, "AltCover.Recorder.g.dll") - if File.Exists dll then - success - else - CommandLine.error <- - CommandLine.Format.Local("recorderNotFound", dll) - :: CommandLine.error + if File.Exists dll then + success + else + CommandLine.error <- + CommandLine.Format.Local("recorderNotFound", dll) + :: CommandLine.error - fail + fail let internal setRecordToFile report = doWithStream @@ -864,16 +868,16 @@ module internal Runner = let internal requireExe (parse: Either) = match parse with | Right (l, options) -> - match (executable.Value, collect.Value) with - | (None, false) - | (Some _, true) -> - CommandLine.error <- - (CommandLine.resources.GetString "executableRequired") - :: CommandLine.error - - Left("UsageError", options) - | (None, _) -> Right([], options) - | (Some exe, _) -> Right(exe :: l, options) + match (executable.Value, collect.Value) with + | (None, false) + | (Some _, true) -> + CommandLine.error <- + (CommandLine.resources.GetString "executableRequired") + :: CommandLine.error + + Left("UsageError", options) + | (None, _) -> Right([], options) + | (Some exe, _) -> Right(exe :: l, options) | fail -> fail let internal requireRecorder @@ -881,7 +885,7 @@ module internal Runner = = match parse with | Right (_, options) -> - requireRecorderTest recordingDirectory parse (Left("UsageError", options)) + requireRecorderTest recordingDirectory parse (Left("UsageError", options)) | fail -> fail let internal requireWorker @@ -889,11 +893,11 @@ module internal Runner = = match parse with | Right _ -> - match workingDirectory with - | None -> workingDirectory <- Directory.GetCurrentDirectory() |> Some - | _ -> () + match workingDirectory with + | None -> workingDirectory <- Directory.GetCurrentDirectory() |> Some + | _ -> () - parse + parse | fail -> fail // mocking point @@ -990,82 +994,83 @@ module internal Runner = | Tag.Time -> Time <| formatter.ReadInt64() | Tag.Call -> Call <| formatter.ReadInt32() | Tag.Both -> - let time = formatter.ReadInt64() - let call = formatter.ReadInt32() - Both { Time = time; Call = call } + let time = formatter.ReadInt64() + let call = formatter.ReadInt32() + Both { Time = time; Call = call } | Tag.Table -> - let t = - Dictionary>() - - let rec ``module`` () = - let m = formatter.ReadString() - - if String.IsNullOrEmpty m then - () - else - if m |> t.ContainsKey |> not then - t.Add(m, Dictionary()) - - let points = formatter.ReadInt32() - - let rec sequencePoint pts = - if pts > 0 then - let p = formatter.ReadInt32() - let n = formatter.ReadInt64() - - if p |> t.[m].ContainsKey |> not then - t.[m].Add(p, PointVisit.Create()) - - let pv = t.[m].[p] - pv.Count <- pv.Count + n - - let rec tracking () = - let track = formatter.ReadByte() |> int - - match enum track with - | Tag.Time -> - pv.Tracks.Add(Time <| formatter.ReadInt64()) - tracking () - | Tag.Call -> - pv.Tracks.Add(Call <| formatter.ReadInt32()) - tracking () - | Tag.Both -> - pv.Tracks.Add( - let time = formatter.ReadInt64() - let call = formatter.ReadInt32() - Both { Time = time; Call = call } - ) - - tracking () - // Expect never to happen | Tag.Table -> ``module``() - | _ -> sequencePoint (pts - 1) - - tracking () - else - ``module`` () - - sequencePoint points - - ``module`` () - Table t + let t = + Dictionary>() + + let rec ``module`` () = + let m = formatter.ReadString() + + if String.IsNullOrEmpty m then + () + else + if m |> t.ContainsKey |> not then + t.Add(m, Dictionary()) + + let points = formatter.ReadInt32() + + let rec sequencePoint pts = + if pts > 0 then + let p = formatter.ReadInt32() + let n = formatter.ReadInt64() + + if p |> t.[m].ContainsKey |> not then + t.[m].Add(p, PointVisit.Create()) + + let pv = t.[m].[p] + pv.Count <- pv.Count + n + + let rec tracking () = + let track = formatter.ReadByte() |> int + + match enum track with + | Tag.Time -> + pv.Tracks.Add(Time <| formatter.ReadInt64()) + tracking () + | Tag.Call -> + pv.Tracks.Add(Call <| formatter.ReadInt32()) + tracking () + | Tag.Both -> + pv.Tracks.Add( + let time = formatter.ReadInt64() + let call = formatter.ReadInt32() + Both { Time = time; Call = call } + ) + + tracking () + // Expect never to happen | Tag.Table -> ``module``() + | _ -> sequencePoint (pts - 1) + + tracking () + else + ``module`` () + + sequencePoint points + + ``module`` () + Table t | _ -> Null ) - with :? EndOfStreamException -> None + with + | :? EndOfStreamException -> None match hit with | Some tuple -> - let (key, hitPointId, visit) = tuple - - let increment = - if key |> String.IsNullOrWhiteSpace |> not - || ((String.IsNullOrEmpty key) - && hitPointId = 0 - && visit.GetType().ToString() = "AltCover.Track+Table") then - Counter.addVisit hits key hitPointId visit - else - 0L - - sink (hitcount + increment) + let (key, hitPointId, visit) = tuple + + let increment = + if key |> String.IsNullOrWhiteSpace |> not + || ((String.IsNullOrEmpty key) + && hitPointId = 0 + && visit.GetType().ToString() = "AltCover.Track+Table") then + Counter.addVisit hits key hitPointId visit + else + 0L + + sink (hitcount + increment) | None -> hitcount let after = sink before @@ -1117,23 +1122,23 @@ module internal Runner = match items with | [] -> () | _ -> - let outer = - pt.OwnerDocument.CreateElement(outername) + let outer = + pt.OwnerDocument.CreateElement(outername) - outer |> pt.AppendChild |> ignore + outer |> pt.AppendChild |> ignore - items - |> Seq.choose id - |> Seq.countBy id - |> Seq.sortBy fst - |> Seq.iter - (fun (t, n) -> - let inner = - pt.OwnerDocument.CreateElement(innername) + items + |> Seq.choose id + |> Seq.countBy id + |> Seq.sortBy fst + |> Seq.iter + (fun (t, n) -> + let inner = + pt.OwnerDocument.CreateElement(innername) - inner |> outer.AppendChild |> ignore - inner.SetAttribute(attribute, t.ToString()) - inner.SetAttribute("vc", sprintf "%d" n)) + inner |> outer.AppendChild |> ignore + inner.SetAttribute(attribute, t.ToString()) + inner.SetAttribute("vc", sprintf "%d" n)) let internal extractTracks tracks = tracks @@ -1270,7 +1275,8 @@ module internal Runner = [] - [] let writeNativeJsonReport (hits: Dictionary>) @@ -1395,61 +1401,61 @@ module internal Runner = match check1 with | Left (intro, options) -> - CommandLine.handleBadArguments - false - arguments - { Intro = intro - Options = options1 - Options2 = options } - - 255 + CommandLine.handleBadArguments + false + arguments + { Intro = intro + Options = options1 + Options2 = options } + + 255 | Right (rest, _) -> - CommandLine.applyVerbosity () - - let value = - CommandLine.doPathOperation - (fun () -> - let pair = J.recorderInstance () - let instance = snd pair - - let report = - (J.getMethod instance "get_ReportFile") - |> J.getFirstOperandAsString - |> canonicalPath - - let format = - (J.getMethod instance "get_CoverageFormat") - |> J.getFirstOperandAsNumber - |> enum - - let hits = - Dictionary>() - - let payload = J.getPayload - let result = J.getMonitor hits report payload rest - let delta = J.doReport hits format report output - - CommandLine.writeResourceWithFormatItems - "Coverage statistics flushing took {0:N} seconds" - [| delta.TotalSeconds |] - false - - // And tidy up after everything's done - File.Delete(report + ".acv") - - Directory.GetFiles( - Path.GetDirectoryName(report), - Path.GetFileName(report) + ".*.acv" - ) - |> Seq.iter File.Delete - - let document = DocumentType.LoadReport format report - J.doSummaries document format result) - 255 - true - - CommandLine.reportErrors "Collection" false - value + CommandLine.applyVerbosity () + + let value = + CommandLine.doPathOperation + (fun () -> + let pair = J.recorderInstance () + let instance = snd pair + + let report = + (J.getMethod instance "get_ReportFile") + |> J.getFirstOperandAsString + |> canonicalPath + + let format = + (J.getMethod instance "get_CoverageFormat") + |> J.getFirstOperandAsNumber + |> enum + + let hits = + Dictionary>() + + let payload = J.getPayload + let result = J.getMonitor hits report payload rest + let delta = J.doReport hits format report output + + CommandLine.writeResourceWithFormatItems + "Coverage statistics flushing took {0:N} seconds" + [| delta.TotalSeconds |] + false + + // And tidy up after everything's done + File.Delete(report + ".acv") + + Directory.GetFiles( + Path.GetDirectoryName(report), + Path.GetFileName(report) + ".*.acv" + ) + |> Seq.iter File.Delete + + let document = DocumentType.LoadReport format report + J.doSummaries document format result) + 255 + true + + CommandLine.reportErrors "Collection" false + value [ Laŭvola, multnombra: Kvieta reĝimo - unufoje por malŝalti informajn mesaĝojn, dufoje por malŝalti ankaŭ avertojn, tri (aŭ pli) fojojn por malŝalti ĉiujn mesaĝojn. + + Preterpasi {0} ĉar ĝi jam estis instrumentita. + \ No newline at end of file diff --git a/AltCover.Engine/Strings.resx b/AltCover.Engine/Strings.resx index 7e0692055..3da973d32 100644 --- a/AltCover.Engine/Strings.resx +++ b/AltCover.Engine/Strings.resx @@ -457,4 +457,7 @@ If the option is not present, then the default is 'OC'. Optional, multiple: Quiet mode -- once to switch off informational messages, twice to switch off warnings as well, three (or more) times to switch off all messages. + + Skipping {0} as it has already been instrumented. + \ No newline at end of file diff --git a/AltCover.Engine/Tasks.fs b/AltCover.Engine/Tasks.fs index 1beeea943..2a452ee69 100644 --- a/AltCover.Engine/Tasks.fs +++ b/AltCover.Engine/Tasks.fs @@ -387,9 +387,9 @@ type RunSettings() = match parent.Descendants(xname childName) |> Seq.tryHead with | Some child -> child | _ -> - let extra = XElement(xname childName) - parent.Add extra - extra + let extra = XElement(xname childName) + parent.Add extra + extra let here = Assembly.GetExecutingAssembly().Location @@ -469,21 +469,23 @@ type ContingentCopy() = //base.Log.LogMessage(MessageImportance.High, sprintf "BuildOutputDirectory %A" self.BuildOutputDirectory) //base.Log.LogMessage(MessageImportance.High, sprintf "InstrumentDirectory %A" self.InstrumentDirectory) - let relativeDir = if self.ProjectDir |> String.IsNullOrWhiteSpace |> not && - self.ProjectDir |> Path.IsPathRooted && - self.RelativeDir |> Path.IsPathRooted - then Visitor.I.getRelativeDirectoryPath self.ProjectDir self.RelativeDir - else self.RelativeDir + let relativeDir = + if self.ProjectDir + |> String.IsNullOrWhiteSpace + |> not + && self.ProjectDir |> Path.IsPathRooted + && self.RelativeDir |> Path.IsPathRooted then + Visitor.I.getRelativeDirectoryPath self.ProjectDir self.RelativeDir + else + self.RelativeDir // base.Log.LogMessage(MessageImportance.High, sprintf "Actual Relative dir %A" relativeDir) if (self.CopyToOutputDirectory = "Always" || self.CopyToOutputDirectory = "PreserveNewest") && (relativeDir |> Path.IsPathRooted |> not) - // && (relativeDir.StartsWith(".." + Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) |> not) - && (relativeDir - |> String.IsNullOrWhiteSpace - |> not) + // && (relativeDir.StartsWith(".." + Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) |> not) + && (relativeDir |> String.IsNullOrWhiteSpace |> not) && (self.FileName |> String.IsNullOrWhiteSpace |> not) then let toDir = Path.Combine(self.InstrumentDirectory, relativeDir) @@ -497,6 +499,7 @@ type ContingentCopy() = if File.Exists from then if toDir |> Directory.Exists |> not then toDir |> Directory.CreateDirectory |> ignore + File.Copy(from, toFile, true) true diff --git a/AltCover.Engine/TypeSafe.fs b/AltCover.Engine/TypeSafe.fs index c270c9611..c5d8f1bc5 100644 --- a/AltCover.Engine/TypeSafe.fs +++ b/AltCover.Engine/TypeSafe.fs @@ -83,18 +83,18 @@ module TypeSafe = match self with | NoThreshold -> String.Empty | Threshold t -> - let facet k n = - (if n <> 0uy then - k + n.ToString(CultureInfo.InvariantCulture) - else - String.Empty) + let facet k n = + (if n <> 0uy then + k + n.ToString(CultureInfo.InvariantCulture) + else + String.Empty) - (facet "S" t.Statements) - + (facet "B" t.Branches) - + (facet "M" t.Methods) - + (facet "C" t.MaxCrap) - + (facet "AM" t.AltMethods) - + (facet "AC" t.AltMaxCrap) + (facet "S" t.Statements) + + (facet "B" t.Branches) + + (facet "M" t.Methods) + + (facet "C" t.MaxCrap) + + (facet "AM" t.AltMethods) + + (facet "AC" t.AltMaxCrap) [] type Flag = @@ -211,12 +211,12 @@ module TypeSafe = | BPlus -> "BOC" | RPlus -> "ROC" | Many s -> - let raw = - String.Join(String.Empty, s |> Seq.map (fun x -> x.AsString())) - |> Seq.distinct - |> Seq.toArray + let raw = + String.Join(String.Empty, s |> Seq.map (fun x -> x.AsString())) + |> Seq.distinct + |> Seq.toArray - String(raw) + String(raw) [] type StaticFormat = diff --git a/AltCover.Engine/Visitor.fs b/AltCover.Engine/Visitor.fs index b5e1888b6..d3f8db69e 100644 --- a/AltCover.Engine/Visitor.fs +++ b/AltCover.Engine/Visitor.fs @@ -78,16 +78,23 @@ type internal GoTo = Representative: Reporting Key: int } +[] +type internal Hallmark = + { Assembly: string + Configuration: string } + [] type internal AssemblyDespatch = { AssemblyPath: string - Destinations: string list } + Destinations: string list + Identity: Hallmark } [] type internal AssemblyEntry = { Assembly: AssemblyDefinition Inspection: Inspections - Destinations: string list } + Destinations: string list + Identity: Hallmark } [] type internal ModuleEntry = @@ -212,8 +219,7 @@ type internal SequenceType = [] module internal KeyStore = - let private hash = - sha1Hash() + let private hash = sha1Hash () let private publicKeyOfKey (key: StrongNameKeyData) = key.PublicKey @@ -257,6 +263,8 @@ type internal Fix<'T> = delegate of 'T -> Fix<'T> [] module internal CoverageParameters = + let internal hash = + System.Security.Cryptography.SHA256.Create() let internal methodPoint = ref false // ddFlag let internal collect = ref false // ddFlag @@ -264,7 +272,7 @@ module internal CoverageParameters = let internal topLevel = new List() let internal nameFilters = new List() - let mutable internal staticFilter : StaticFilter option = None + let mutable internal staticFilter: StaticFilter option = None let internal showGenerated = ref false let generationFilter = @@ -315,7 +323,8 @@ module internal CoverageParameters = [] - [] let private defaultOutputDirectory _ = inplaceSelection "__Saved" "__Instrumented" @@ -336,15 +345,15 @@ module internal CoverageParameters = let internal sourceDirectories () = (inplaceSelection outputDirectories inputDirectories) () - let mutable internal theReportPath : Option = None + let mutable internal theReportPath: Option = None let internal zipReport = ref false // ddFlag - let mutable internal theInterval : Option = None + let mutable internal theInterval: Option = None let internal defaultInterval = 0 let internal interval () = (Option.defaultValue defaultInterval theInterval) - let mutable internal theReportFormat : Option = None + let mutable internal theReportFormat: Option = None let mutable internal coverstyle = CoverStyle.All let internal reportKind () = @@ -357,9 +366,12 @@ module internal CoverageParameters = "coverage.xml" let internal reportPath () = - let r = canonicalPath(Option.defaultValue (defaultReportPath ()) theReportPath) + let r = + canonicalPath (Option.defaultValue (defaultReportPath ()) theReportPath) + let suffix = (Path.GetExtension r).ToUpperInvariant() - match (suffix, reportKind()) with + + match (suffix, reportKind ()) with | (".XML", ReportFormat.NativeJson) -> Path.ChangeExtension(r, ".json") | (".JSON", ReportFormat.OpenCover) | (".JSON", ReportFormat.NCover) -> Path.ChangeExtension(r, ".xml") @@ -385,14 +397,67 @@ module internal CoverageParameters = let withBranches () = reportFormat () <> ReportFormat.NCover - let mutable internal defaultStrongNameKey : option = None - let mutable internal recorderStrongNameKey : option = None + let mutable internal defaultStrongNameKey: option = None + let mutable internal recorderStrongNameKey: option = None let internal keys = new Dictionary() let internal add (key: StrongNameKeyData) = let index = KeyStore.keyToIndex key keys.[index] <- KeyStore.keyToRecord key + let mutable internal configurationHash: option = None + + [] + let private filterString (n: FilterClass) = + (string n) + .Replace('\r', ';') + .Replace('\n', ';') + .Replace(";;", ";") + + [] + [] + let internal makeConfiguration () = + let components = + [ "--methodpoint\t" + string methodPoint.Value + "--callContext-A\t" + + String.Join("\t", trackingNames) + "--topLevels\t" + + String.Join("\t", topLevel |> Seq.map filterString |> Seq.sort) + "--filters\t" + + String.Join("\t", nameFilters |> Seq.map filterString |> Seq.sort) + "--showstatic\t" + string staticFilter + "--showGenerated\t" + string showGenerated.Value + "--visibleBranches\t" + + string coalesceBranches.Value + "--localSource\t" + string local.Value + "--sourceLink\t" + string sourcelink.Value + "--callContext-B\t" + (string <| interval ()) + "--line/branch-cover\t" + string coverstyle + "--reportFormat\t" + (string <| reportFormat ()) + "--strongNameKey\t" + + (defaultStrongNameKey + |> Option.map KeyStore.keyToIndex + |> string) + "!!recorderStrongNameKey\t" + + (recorderStrongNameKey + |> Option.map KeyStore.keyToIndex + |> string) + "--key\t" + + String.Join("\t", keys.Keys |> Seq.map string |> Seq.sort) ] + + configurationHash <- + String.Join("\n", components) + |> System.Text.Encoding.ASCII.GetBytes + |> hash.ComputeHash + |> Convert.ToBase64String + |> Some + [] module internal Inspector = type Inspections with @@ -411,21 +476,21 @@ module internal Inspector = member nameProvider.LocalFilter: bool = match nameProvider with | :? AssemblyDefinition as a -> - (CoverageParameters.local.Value) - && a.MainModule - |> ProgramDatabase.getModuleDocuments - |> Seq.map (fun d -> d.Url) - |> Seq.exists File.Exists - |> not + (CoverageParameters.local.Value) + && a.MainModule + |> ProgramDatabase.getModuleDocuments + |> Seq.map (fun d -> d.Url) + |> Seq.exists File.Exists + |> not | _ -> false [] module internal Visitor = let private accumulator = HashSet() - let mutable private pointNumber : int = 0 - let mutable private branchNumber : int = 0 - let mutable private methodNumber : int = 0 - let mutable internal sourceLinkDocuments : Dictionary option = None + let mutable private pointNumber: int = 0 + let mutable private branchNumber: int = 0 + let mutable private methodNumber: int = 0 + let mutable internal sourceLinkDocuments: Dictionary option = None let internal zeroPoints () = pointNumber <- 0 @@ -450,17 +515,22 @@ module internal Visitor = let internal getRelativeDirectoryPath (relativeTo: string) path = let rebase = canonicalDirectory relativeTo let canon = canonicalDirectory path + if canon = rebase then String.Empty else let uri = Uri(Uri("file://"), rebase) Uri - .UnescapeDataString(uri.MakeRelativeUri(Uri(Uri("file://"), canon)).ToString()) + .UnescapeDataString( + uri + .MakeRelativeUri(Uri(Uri("file://"), canon)) + .ToString() + ) .Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar) // overkill let internal exists (url: Uri) = - let request = createHttp(url) + let request = createHttp (url) request.Method <- "HEAD" try @@ -470,7 +540,8 @@ module internal Visitor = && (response :?> System.Net.HttpWebResponse) .StatusCode |> int < 400 - with :? WebException -> false + with + | :? WebException -> false let internal findClosestMatch file (dict: Dictionary) = dict.Keys @@ -478,7 +549,9 @@ module internal Visitor = |> Seq.map (fun x -> (x, - getRelativeDirectoryPath (x |> Path.GetDirectoryName) (file |> Path.GetDirectoryName))) + getRelativeDirectoryPath + (x |> Path.GetDirectoryName) + (file |> Path.GetDirectoryName))) |> Seq.filter (fun (x, r) -> r.IndexOf("..", StringComparison.Ordinal) < 0) |> Seq.sortBy (fun (x, r) -> r.Length) |> Seq.tryHead @@ -494,16 +567,16 @@ module internal Visitor = match find with | Some (best, relative) -> - let replacement = - Path - .Combine(relative, Path.GetFileName(file)) - .Replace('\\', '/') + let replacement = + Path + .Combine(relative, Path.GetFileName(file)) + .Replace('\\', '/') - let url = dict.[best].Replace("*", replacement) + let url = dict.[best].Replace("*", replacement) - let map = if Uri(url) |> exists then url else file - dict.Add(file, map) - map + let map = if Uri(url) |> exists then url else file + dict.Add(file, map) + map | _ -> file let internal isFSharpStaticClass (t: TypeDefinition) = @@ -574,7 +647,8 @@ module internal Visitor = Assembly { Assembly = x Inspection = included - Destinations = path.Destinations } + Destinations = path.Destinations + Identity = path.Identity } path.AssemblyPath |> (AssemblyDefinition.ReadAssembly @@ -624,11 +698,10 @@ module internal Visitor = sourceLinkDocuments <- Some x.Module |> Option.filter (fun _ -> CoverageParameters.sourcelink.Value) - |> Option.map + |> Option.bind (fun x -> x.CustomDebugInformations |> Seq.tryFind (fun i -> i.Kind = CustomDebugInformationKind.SourceLink)) - |> Option.flatten |> Option.map (fun i -> let c = @@ -741,28 +814,30 @@ module internal Visitor = match candidates with | [ x ] -> Some x | _ -> - let tag = "<" + stripped + ">" - - candidates - .Concat(methods - |> Seq.filter - (fun mx -> - (mx.Name.IndexOf(tag, StringComparison.Ordinal) - >= 0) - && mx.HasBody)) - .Concat( - ct.NestedTypes - |> Seq.filter (fun tx -> tx.Name.StartsWith("<", StringComparison.Ordinal)) - |> Seq.collect (fun tx -> tx.Methods) - |> Seq.filter - (fun mx -> - mx.HasBody - && (mx.Name.IndexOf(tag, StringComparison.Ordinal) - >= 0 - || mx.DeclaringType.Name.IndexOf(tag, StringComparison.Ordinal) - >= 0)) - ) - |> Seq.tryFind predicate + let tag = "<" + stripped + ">" + + candidates + .Concat( + methods + |> Seq.filter + (fun mx -> + (mx.Name.IndexOf(tag, StringComparison.Ordinal) + >= 0) + && mx.HasBody) + ) + .Concat( + ct.NestedTypes + |> Seq.filter (fun tx -> tx.Name.StartsWith("<", StringComparison.Ordinal)) + |> Seq.collect (fun tx -> tx.Methods) + |> Seq.filter + (fun mx -> + mx.HasBody + && (mx.Name.IndexOf(tag, StringComparison.Ordinal) + >= 0 + || mx.DeclaringType.Name.IndexOf(tag, StringComparison.Ordinal) + >= 0)) + ) + |> Seq.tryFind predicate let internal sameType (target: TypeReference) (candidate: TypeReference) = if target = candidate then @@ -805,8 +880,7 @@ module internal Visitor = |> Seq.filter (fun i -> i.OpCode = OpCodes.Ldsfld) |> Seq.exists (fun i -> - let tn = - (i.Operand :?> FieldReference).FieldType + let tn = (i.Operand :?> FieldReference).FieldType sameType t tn) @@ -823,8 +897,10 @@ module internal Visitor = |> Seq.filter (fun m -> m.HasBody) candidates - |> Seq.tryFind (fun c -> (methodConstructsType tx c) || - (methodLoadsType tx c)) + |> Seq.tryFind + (fun c -> + (methodConstructsType tx c) + || (methodLoadsType tx c)) let internal methodCallsMethod (t: MethodReference) (m: MethodDefinition) = m.Body.Instructions @@ -858,8 +934,10 @@ module internal Visitor = nesting > 0) |> Seq.length - if mname.StartsWith("<", StringComparison.Ordinal) - && charIndexOf mname '|' > 0 then + if + mname.StartsWith("<", StringComparison.Ordinal) + && charIndexOf mname '|' > 0 + then let index = (indexOfMatchingClosingAngleBracket mname) - 1 @@ -902,7 +980,8 @@ module internal Visitor = m.IsConstructor && m.HasParameters && (m.Parameters.Count = 1)) - |> Option.map (fun m -> m.Parameters |> Seq.head) with + |> Option.map (fun m -> m.Parameters |> Seq.head) + with | None -> t :> TypeReference | Some other -> other.ParameterType else @@ -926,16 +1005,16 @@ module internal Visitor = match state with | None -> None | Some x -> - Some( - x, - if - CoverageParameters.topLevel - |> Seq.exists (Filter.``match`` x) - then - None - else - containingMethod x - )) + Some( + x, + if + CoverageParameters.topLevel + |> Seq.exists (Filter.``match`` x) + then + None + else + containingMethod x + )) (Some m) |> Seq.toList @@ -1005,12 +1084,12 @@ module internal Visitor = = match seq with | null -> - if genuine = FakeAtReturn - && instruction.IsNotNull - && instruction.OpCode = OpCodes.Ret then - SequencePoint(instruction, Document(null)) - else - null + if genuine = FakeAtReturn + && instruction.IsNotNull + && instruction.OpCode = OpCodes.Ret then + SequencePoint(instruction, Document(null)) + else + null | _ -> seq let internal findEffectiveSequencePoint @@ -1107,11 +1186,12 @@ module internal Visitor = // This covers a multitude of compiler generated branching cases // TODO can we simplify match (CoverageParameters.coalesceBranches.Value, - includedSequencePoint dbg toNext toJump) with + includedSequencePoint dbg toNext toJump) + with | (true, _) | (_, Some _) -> - [ (i, toNext, next.Offset, -1) - (i, toJump, jump.Offset, 0) ] + [ (i, toNext, next.Offset, -1) + (i, toJump, jump.Offset, 0) ] | _ -> [] let private coalesceBranchPoints dbg (bps: GoTo seq) = @@ -1398,6 +1478,6 @@ module internal Visitor = match sourceLinkDocuments with | None -> file | Some dict -> - match dict.TryGetValue file with - | (true, url) -> url - | _ -> I.locateMatch file dict \ No newline at end of file + match dict.TryGetValue file with + | (true, url) -> url + | _ -> I.locateMatch file dict \ No newline at end of file diff --git a/AltCover.Expecto.Tests/AltCover.Expecto.Tests.fsproj b/AltCover.Expecto.Tests/AltCover.Expecto.Tests.fsproj index 3d700f066..e09f11f07 100644 --- a/AltCover.Expecto.Tests/AltCover.Expecto.Tests.fsproj +++ b/AltCover.Expecto.Tests/AltCover.Expecto.Tests.fsproj @@ -3,8 +3,6 @@ Exe net6.0 - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ DEBUG;TRACE;EXPECTO_MAIN false @@ -24,7 +22,7 @@ - + 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 80da7f9f6..360e85526 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 @@ -5,36 +5,15 @@ netstandard2.0 AltCover.Fake.DotNet.Testing.AltCover AltCover.Fake.DotNet.Testing.AltCover - false - true NoCanonicalDirectories - $(ProjectDir)../ - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - --keyfile:$(SolutionDir)Build\Infrastructure.snk MSB3277;MSB3245 - - false - false - - - true - true - - TRACE;DEBUG;CODE_ANALYSIS;$(GlobalDefineConstants) - 4 - true - - true - true TRACE;$(GlobalDefineConstants) diff --git a/AltCover.Fake.DotNet.Testing.AltCover/AltCoverCommand.fs b/AltCover.Fake.DotNet.Testing.AltCover/AltCoverCommand.fs index 14b3f7ae8..b50fc8bcd 100644 --- a/AltCover.Fake.DotNet.Testing.AltCover/AltCoverCommand.fs +++ b/AltCover.Fake.DotNet.Testing.AltCover/AltCoverCommand.fs @@ -27,55 +27,55 @@ module AltCoverCommand = match collect with | AltCover.Primitive p -> AltCover.Primitive { p with Executable = tool } | AltCover.TypeSafe t -> - AltCover.TypeSafe - { t with - Executable = TypeSafe.Tool tool } + AltCover.TypeSafe + { t with + Executable = TypeSafe.Tool tool } | AltCover.Abstract a -> - let copy : Primitive.CollectOptions = - { RecorderDirectory = a.RecorderDirectory - WorkingDirectory = a.WorkingDirectory - Executable = tool - LcovReport = a.LcovReport - Threshold = a.Threshold - Cobertura = a.Cobertura - OutputFile = a.OutputFile - CommandLine = a.CommandLine - ExposeReturnCode = a.ExposeReturnCode - SummaryFormat = a.SummaryFormat - Verbosity = a.Verbosity } - - AltCover.Primitive copy + let copy: Primitive.CollectOptions = + { RecorderDirectory = a.RecorderDirectory + WorkingDirectory = a.WorkingDirectory + Executable = tool + LcovReport = a.LcovReport + Threshold = a.Threshold + Cobertura = a.Cobertura + OutputFile = a.OutputFile + CommandLine = a.CommandLine + ExposeReturnCode = a.ExposeReturnCode + SummaryFormat = a.SummaryFormat + Verbosity = a.Verbosity } + + AltCover.Primitive copy let internal setCollectCommandLine (args: string seq) collect = match collect with | AltCover.Primitive p -> AltCover.Primitive { p with CommandLine = args } | AltCover.Abstract a -> - let copy : Primitive.CollectOptions = - { RecorderDirectory = a.RecorderDirectory - WorkingDirectory = a.WorkingDirectory - Executable = a.Executable - LcovReport = a.LcovReport - Threshold = a.Threshold - Cobertura = a.Cobertura - OutputFile = a.OutputFile - CommandLine = args |> toSeq - ExposeReturnCode = a.ExposeReturnCode - SummaryFormat = a.SummaryFormat - Verbosity = a.Verbosity } - - AltCover.Primitive copy + let copy: Primitive.CollectOptions = + { RecorderDirectory = a.RecorderDirectory + WorkingDirectory = a.WorkingDirectory + Executable = a.Executable + LcovReport = a.LcovReport + Threshold = a.Threshold + Cobertura = a.Cobertura + OutputFile = a.OutputFile + CommandLine = args |> toSeq + ExposeReturnCode = a.ExposeReturnCode + SummaryFormat = a.SummaryFormat + Verbosity = a.Verbosity } + + AltCover.Primitive copy | AltCover.TypeSafe t -> - AltCover.TypeSafe - { t with - CommandLine = - let newargs = - args - |> (Seq.map TypeSafe.CommandArgument) - |> Seq.toList - - match newargs with - | [] -> TypeSafe.NoCommand - | _ -> TypeSafe.CommandArguments newargs } + AltCover.TypeSafe + { t with + CommandLine = + let newargs = + args + |> (Seq.map TypeSafe.CommandArgument) + |> Seq.toList + + match newargs with + | [] -> TypeSafe.NoCommand + | _ -> TypeSafe.CommandArguments newargs } let internal setPrepareCommandLine (args: string seq) @@ -83,58 +83,58 @@ module AltCoverCommand = = match prepare with | AltCover.PrepareOptions.Primitive p -> - AltCover.PrepareOptions.Primitive { p with CommandLine = args } + AltCover.PrepareOptions.Primitive { p with CommandLine = args } | AltCover.PrepareOptions.Abstract a -> - let copy : Primitive.PrepareOptions = - { InputDirectories = a.InputDirectories - OutputDirectories = a.OutputDirectories - SymbolDirectories = a.SymbolDirectories - Dependencies = a.Dependencies - Keys = a.Keys - StrongNameKey = a.StrongNameKey - Report = a.Report - FileFilter = a.FileFilter - AssemblyFilter = a.AssemblyFilter - AssemblyExcludeFilter = a.AssemblyExcludeFilter - TypeFilter = a.TypeFilter - MethodFilter = a.MethodFilter - AttributeFilter = a.AttributeFilter - PathFilter = a.PathFilter - AttributeTopLevel = a.AttributeTopLevel - TypeTopLevel = a.TypeTopLevel - MethodTopLevel = a.MethodTopLevel - CallContext = a.CallContext - ReportFormat = a.ReportFormat - InPlace = a.InPlace - Save = a.Save - ZipFile = a.ZipFile - MethodPoint = a.MethodPoint - SingleVisit = a.SingleVisit - LineCover = a.LineCover - BranchCover = a.BranchCover - CommandLine = args |> toSeq - ExposeReturnCode = a.ExposeReturnCode - SourceLink = a.SourceLink - Defer = a.Defer - LocalSource = a.LocalSource - VisibleBranches = a.VisibleBranches - ShowStatic = a.ShowStatic - ShowGenerated = a.ShowGenerated - Verbosity = a.Verbosity } - - AltCover.PrepareOptions.Primitive copy + let copy: Primitive.PrepareOptions = + { InputDirectories = a.InputDirectories + OutputDirectories = a.OutputDirectories + SymbolDirectories = a.SymbolDirectories + Dependencies = a.Dependencies + Keys = a.Keys + StrongNameKey = a.StrongNameKey + Report = a.Report + FileFilter = a.FileFilter + AssemblyFilter = a.AssemblyFilter + AssemblyExcludeFilter = a.AssemblyExcludeFilter + TypeFilter = a.TypeFilter + MethodFilter = a.MethodFilter + AttributeFilter = a.AttributeFilter + PathFilter = a.PathFilter + AttributeTopLevel = a.AttributeTopLevel + TypeTopLevel = a.TypeTopLevel + MethodTopLevel = a.MethodTopLevel + CallContext = a.CallContext + ReportFormat = a.ReportFormat + InPlace = a.InPlace + Save = a.Save + ZipFile = a.ZipFile + MethodPoint = a.MethodPoint + SingleVisit = a.SingleVisit + LineCover = a.LineCover + BranchCover = a.BranchCover + CommandLine = args |> toSeq + ExposeReturnCode = a.ExposeReturnCode + SourceLink = a.SourceLink + Defer = a.Defer + LocalSource = a.LocalSource + VisibleBranches = a.VisibleBranches + ShowStatic = a.ShowStatic + ShowGenerated = a.ShowGenerated + Verbosity = a.Verbosity } + + AltCover.PrepareOptions.Primitive copy | AltCover.PrepareOptions.TypeSafe t -> - AltCover.PrepareOptions.TypeSafe - { t with - CommandLine = - let newargs = - args - |> (Seq.map TypeSafe.CommandArgument) - |> Seq.toList - - match newargs with - | [] -> TypeSafe.NoCommand - | _ -> TypeSafe.CommandArguments newargs } + AltCover.PrepareOptions.TypeSafe + { t with + CommandLine = + let newargs = + args + |> (Seq.map TypeSafe.CommandArgument) + |> Seq.toList + + match newargs with + | [] -> TypeSafe.NoCommand + | _ -> TypeSafe.CommandArguments newargs } [) = match command.Command with | RawCommand (tool, args) -> - match this.Args with - | Collect c -> - { this with - Args = - ArgumentType.Collect( - c - |> setExecutable tool - |> setCollectCommandLine (Arguments.toList args) - ) } - | Prepare p -> - { this with - Args = - ArgumentType.Prepare( - p - |> setPrepareCommandLine (tool :: (Arguments.toList args)) - ) } - | ImportModule -> this - | GetVersion -> this + match this.Args with + | Collect c -> + { this with + Args = + ArgumentType.Collect( + c + |> setExecutable tool + |> setCollectCommandLine (Arguments.toList args) + ) } + | Prepare p -> + { this with + Args = + ArgumentType.Prepare( + p + |> setPrepareCommandLine (tool :: (Arguments.toList args)) + ) } + | ImportModule -> this + | GetVersion -> this | _ -> this let internal createArgs options = @@ -292,18 +292,18 @@ module AltCoverCommand = && Fake.Core.Environment.isWindows then match command.Command with | RawCommand (tool, args) -> - let newArgs = - tool :: "--debug" :: (Arguments.toList args) - - let newRaw = - RawCommand( - (match monoPath with - | Some x -> x - | _ -> "mono"), - Arguments.OfArgs newArgs - ) - - command |> CreateProcess.withCommand newRaw + let newArgs = + tool :: "--debug" :: (Arguments.toList args) + + let newRaw = + RawCommand( + (match monoPath with + | Some x -> x + | _ -> "mono"), + Arguments.OfArgs newArgs + ) + + command |> CreateProcess.withCommand newRaw | _ -> command else diff --git a/AltCover.Fake/AltCover.Fake.fsproj b/AltCover.Fake/AltCover.Fake.fsproj index 06fbb4d82..9d7253833 100644 --- a/AltCover.Fake/AltCover.Fake.fsproj +++ b/AltCover.Fake/AltCover.Fake.fsproj @@ -5,34 +5,13 @@ netstandard2.0 AltCover.Fake AltCover.Fake - false - true RUNNER - $(ProjectDir)../ - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - --keyfile:$(SolutionDir)Build\Infrastructure.snk - - - - false - false - - - true - true TRACE;DEBUG;CODE_ANALYSIS;$(GlobalDefineConstants) - 4 - true - - true - true TRACE;$(GlobalDefineConstants) diff --git a/AltCover.Fake/Fake.fs b/AltCover.Fake/Fake.fs index 6eefc8a28..c2ca6a2d2 100644 --- a/AltCover.Fake/Fake.fs +++ b/AltCover.Fake/Fake.fs @@ -54,8 +54,10 @@ type Command private () = | Framework _ -> "AltCover.exe" | _ -> "AltCover.dll" - match Directory.GetFiles(root, target, SearchOption.AllDirectories) - |> Seq.tryHead with + match + Directory.GetFiles(root, target, SearchOption.AllDirectories) + |> Seq.tryHead + with | Some path -> path |> Path.GetFullPath | None -> String.Empty #else diff --git a/AltCover.FontSupport/AltCover.FontSupport.csproj b/AltCover.FontSupport/AltCover.FontSupport.csproj index 701bfa110..2b03a0811 100644 --- a/AltCover.FontSupport/AltCover.FontSupport.csproj +++ b/AltCover.FontSupport/AltCover.FontSupport.csproj @@ -5,32 +5,15 @@ AltCover.FontSupport AltCover.FontSupport false - true - $(ProjectDir)../ - true - $(SolutionDir)\Build\Infrastructure.snk - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ 1701;1702;8002 NU1605 - true - true - - - - false - false - - - true - true + TRACE;DEBUG;CODE_ANALYSIS - true TRACE;$(GlobalDefineConstants) diff --git a/AltCover.Monitor.Tests/AltCover.Monitor.Tests.fsproj b/AltCover.Monitor.Tests/AltCover.Monitor.Tests.fsproj index 54932035c..080be4432 100644 --- a/AltCover.Monitor.Tests/AltCover.Monitor.Tests.fsproj +++ b/AltCover.Monitor.Tests/AltCover.Monitor.Tests.fsproj @@ -9,12 +9,8 @@ Library $(AssemblySearchPaths);{GAC} - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk DEBUG;TRACE;CODE_ANALYSIS;Monitor DEBUG;TRACE;CODE_ANALYSIS;Monitor;BUILD_ON_APPVEYOR - Major @@ -28,7 +24,7 @@ ..\ThirdParty\Unquote.dll - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/AltCover.Monitor.Tests/MonitorTest.fs b/AltCover.Monitor.Tests/MonitorTest.fs index 021351229..16c94348a 100644 --- a/AltCover.Monitor.Tests/MonitorTest.fs +++ b/AltCover.Monitor.Tests/MonitorTest.fs @@ -51,10 +51,12 @@ module MonitorTests = maybeIgnore (fun () -> not (a && a0)) let code = b.Code let branch = b.Branch + let text = Path.Combine( SolutionRoot.location, "_Reports/MonitorTestWithAltCoverCoreRunner.net6.0.xml" ) |> File.ReadAllText - test' <@ (code, branch) = (109, 14) @> text + + test' <@ (code, branch) = (109, 14) @> text \ No newline at end of file diff --git a/AltCover.Monitor/AltCover.Monitor.csproj b/AltCover.Monitor/AltCover.Monitor.csproj index da74cd463..f97b9e454 100644 --- a/AltCover.Monitor/AltCover.Monitor.csproj +++ b/AltCover.Monitor/AltCover.Monitor.csproj @@ -4,36 +4,13 @@ net20;netstandard2.0 AltCover AltCover.Monitor - false - true - $(ProjectDir)../ - true - $(SolutionDir)\Build\Infrastructure.snk 1701;1702;NU1603 - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - true - true - - - - false - false - - - true - true TRACE;DEBUG;CODE_ANALYSIS - true - - - true TRACE diff --git a/AltCover.PowerShell/AltCover.PowerShell.fsproj b/AltCover.PowerShell/AltCover.PowerShell.fsproj index a54f6704a..d7aa37876 100644 --- a/AltCover.PowerShell/AltCover.PowerShell.fsproj +++ b/AltCover.PowerShell/AltCover.PowerShell.fsproj @@ -5,35 +5,13 @@ netstandard2.0 AltCover.PowerShell AltCover.PowerShell - false - true - $(ProjectDir)../ - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - - - - false - false - - - true - true TRACE;DEBUG;CODE_ANALYSIS;$(GlobalDefineConstants) - --tailcalls+ --keyfile:$(ProjectDir)..\Build\Infrastructure.snk - 4 - true - - true - true TRACE;$(GlobalDefineConstants) - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk diff --git a/AltCover.PowerShell/Command.fs b/AltCover.PowerShell/Command.fs index fd8dece31..4b2635f77 100644 --- a/AltCover.PowerShell/Command.fs +++ b/AltCover.PowerShell/Command.fs @@ -694,32 +694,32 @@ type InvokeAltCoverCommand() = (match (self.Version.IsPresent, self.Runner.IsPresent) with | (true, _) -> - (fun _ -> - Command.FormattedVersion() |> log.Info - 0) + (fun _ -> + Command.FormattedVersion() |> log.Info + 0) | (_, true) -> - let task = self.Collect() - // unset is error, but if set the recorder may not exist yet - let recording = - self.RecorderDirectory - |> String.IsNullOrWhiteSpace - || Path.Combine(self.RecorderDirectory, "AltCover.Recorder.g.dll") - |> File.Exists - - if (self.ShouldProcess( - "Command Line : " - + task.WhatIf(recording).ToString() - )) then - Command.Collect task - else - zero + let task = self.Collect() + // unset is error, but if set the recorder may not exist yet + let recording = + self.RecorderDirectory + |> String.IsNullOrWhiteSpace + || Path.Combine(self.RecorderDirectory, "AltCover.Recorder.g.dll") + |> File.Exists + + if (self.ShouldProcess( + "Command Line : " + + task.WhatIf(recording).ToString() + )) then + Command.Collect task + else + zero | _ -> - let task = self.Prepare() + let task = self.Prepare() - if (self.ShouldProcess("Command Line : " + task.WhatIf().ToString())) then - Command.Prepare task - else - zero) + if (self.ShouldProcess("Command Line : " + task.WhatIf().ToString())) then + Command.Prepare task + else + zero) log /// @@ -748,7 +748,7 @@ type InvokeAltCoverCommand() = match self.Fail with | [] -> () | things -> - String.Join(Environment.NewLine, things |> List.rev) - |> makeError + String.Join(Environment.NewLine, things |> List.rev) + |> makeError finally Directory.SetCurrentDirectory here \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Adapter.fs b/AltCover.Recorder.Tests/Adapter.fs index c5f52d005..abf2558f4 100644 --- a/AltCover.Recorder.Tests/Adapter.fs +++ b/AltCover.Recorder.Tests/Adapter.fs @@ -34,16 +34,16 @@ module Adapter = let VisitsAdd (name, line, number) = prepareName name - let v = init(number, []) + 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 ]) + let v1 = init (number, [ Call 17; Call 42 ]) Instance.I.visits.[name].Add(line, v1) let v2 = - init( + init ( (number + 1L), [ Time 17L Both { Time = 42L; Call = 23 } ] @@ -95,9 +95,9 @@ module Adapter = match t with | (n, p, Table d) -> - r.Add(n) - r.Add(p) - r.Add(d) + r.Add(n) + r.Add(p) + r.Add(d) | _ -> () r @@ -166,9 +166,10 @@ module Adapter = | _ -> x.Message = unique Instance.I.issue71Wrapper () () () () catcher pitcher - + let internal invokeCurriedIssue71Wrapper<'T when 'T :> System.Exception> - (unique: string) = + (unique: string) + = let constructor = typeof<'T>.GetConstructor ([| typeof |]) diff --git a/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj b/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj index 95563157c..bafed9a63 100644 --- a/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj +++ b/AltCover.Recorder.Tests/AltCover.Recorder.Tests.fsproj @@ -5,24 +5,16 @@ false AltCover.Recorder.Tests false - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - NU1702 NU1702 - Major - false - false TRACE;DEBUG;ALTCOVER_TEST;$(ExtraDefines) - --tailcalls+ --keyfile:$(ProjectDir)..\Build\Infrastructure.snk TRACE;RELEASE;ALTCOVER_TEST;$(ExtraDefines) - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk @@ -77,7 +69,7 @@ - + contentfiles diff --git a/AltCover.Recorder.Tests/Recorder.Tests.fs b/AltCover.Recorder.Tests/Recorder.Tests.fs index e85e57678..5fcb2de44 100644 --- a/AltCover.Recorder.Tests/Recorder.Tests.fs +++ b/AltCover.Recorder.Tests/Recorder.Tests.fs @@ -43,10 +43,10 @@ module AltCoverTests = |> Seq.find (fun n -> n.EndsWith("SimpleCoverage.xml", StringComparison.Ordinal)) let private updateReport a b = - Adapter.updateReport(a, ReportFormat.NCover, b, b) + Adapter.updateReport (a, ReportFormat.NCover, b, b) |> ignore - let private pointVisitInit a b = Adapter.init(a, b) + let private pointVisitInit a b = Adapter.init (a, b) let resource2 = Assembly @@ -56,6 +56,16 @@ module AltCoverTests = (fun n -> n.EndsWith("Sample1WithModifiedOpenCover.xml", StringComparison.Ordinal)) + [] + let ShouldCoverTrivalClass () = + let mark = 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) + [] let ShouldFailXmlDataForNativeJson () = Assert.Throws @@ -95,22 +105,22 @@ module AltCoverTests = (fun () -> try Adapter.SamplesClear() - Assert.True(Adapter.addSample("module", 23, Null)) - Assert.True(Adapter.addSample("module", 24, Null)) - Assert.True(Adapter.addSample("newmodule", 23, Null)) - Assert.True(Adapter.addSample("module", 23, Null) |> not) - Assert.True(Adapter.addSampleUnconditional("module", 23, Null)) - Assert.True(Adapter.addSample("module", 23, Call 1)) - Assert.True(Adapter.addSample("module", 23, Time 0L)) - Assert.True(Adapter.addSample("module", 24, Both { Call = 1; Time = 0L })) - Assert.True(Adapter.addSample("module", 25, Both { Call = 1; Time = 0L })) - Assert.True(Adapter.addSample("module", 25, Call 1) |> not) - Assert.True(Adapter.addSample("module", 25, Call 1) |> not) - Assert.True(Adapter.addSample("module", 25, Null) |> not) + Assert.True(Adapter.addSample ("module", 23, Null)) + Assert.True(Adapter.addSample ("module", 24, Null)) + Assert.True(Adapter.addSample ("newmodule", 23, Null)) + Assert.True(Adapter.addSample ("module", 23, Null) |> not) + Assert.True(Adapter.addSampleUnconditional ("module", 23, Null)) + Assert.True(Adapter.addSample ("module", 23, Call 1)) + Assert.True(Adapter.addSample ("module", 23, Time 0L)) + Assert.True(Adapter.addSample ("module", 24, Both { Call = 1; Time = 0L })) + Assert.True(Adapter.addSample ("module", 25, Both { Call = 1; Time = 0L })) + Assert.True(Adapter.addSample ("module", 25, Call 1) |> not) + Assert.True(Adapter.addSample ("module", 25, Call 1) |> not) + Assert.True(Adapter.addSample ("module", 25, Null) |> not) Assert.Throws (fun () -> - Adapter.addSample("module", 23, Table null) + Adapter.addSample ("module", 23, Table null) |> ignore) |> ignore finally @@ -163,20 +173,20 @@ module AltCoverTests = Instance.I.isRunner <- false Instance.CoverageFormat <- ReportFormat.OpenCoverWithTracking Assert.True(Instance.I.callerId () |> Option.isNone) - Assert.True(Adapter.payloadSelector false = Adapter.asNull()) - Assert.True(Adapter.payloadSelector true = Adapter.asNull()) + Assert.True(Adapter.payloadSelector false = Adapter.asNull ()) + Assert.True(Adapter.payloadSelector true = Adapter.asNull ()) Instance.Push 4321 - Assert.True(Adapter.payloadSelector false = Adapter.asNull()) + Assert.True(Adapter.payloadSelector false = Adapter.asNull ()) Assert.True(Adapter.payloadSelector true = (Adapter.asCall 4321)) try Instance.Push 6789 // 0x1234123412341234 == 1311693406324658740 let result = - Adapter.payloadSelection(1311693406324658740L, 1000L, true) + Adapter.payloadSelection (1311693406324658740L, 1000L, true) let expected = - Adapter.newBoth(1311693406324658000L, 6789) + Adapter.newBoth (1311693406324658000L, 6789) Assert.True((result = expected)) finally @@ -188,14 +198,14 @@ module AltCoverTests = Instance.CoverageFormat <- ReportFormat.NCover let result2 = - Adapter.payloadSelection(1311693406324658740L, 1000L, true) + Adapter.payloadSelection (1311693406324658740L, 1000L, true) let expected2 = Adapter.time 1311693406324658000L Assert.True((result2 = expected2)) let v1 = DateTime.UtcNow.Ticks - let probed = Adapter.payloadControl(1000L, true) + let probed = Adapter.payloadControl (1000L, true) let v2 = DateTime.UtcNow.Ticks - Assert.True(Adapter.asNull() |> Adapter.untime |> Seq.isEmpty) + Assert.True(Adapter.asNull () |> Adapter.untime |> Seq.isEmpty) let [ probe ] = Adapter.untime probed |> Seq.toList Assert.True(probe % 1000L = 0L) Assert.True(probe <= v2) @@ -212,20 +222,20 @@ module AltCoverTests = Adapter.VisitsClear() Assert.True(Instance.I.callerId () |> Option.isNone) - Assert.True(Adapter.payloadSelector false = Adapter.asNull()) - Assert.True(Adapter.payloadSelector true = Adapter.asNull()) + Assert.True(Adapter.payloadSelector false = Adapter.asNull ()) + Assert.True(Adapter.payloadSelector true = Adapter.asNull ()) Instance.Push 4321 - Assert.True(Adapter.payloadSelector false = Adapter.asNull()) + Assert.True(Adapter.payloadSelector false = Adapter.asNull ()) Assert.True(Adapter.payloadSelector true = (Adapter.asCall 4321)) try Instance.Push 6789 // 0x1234123412341234 == 1311693406324658740 let result = - Adapter.payloadSelection(1311693406324658740L, 1000L, true) + Adapter.payloadSelection (1311693406324658740L, 1000L, true) let expected = - Adapter.newBoth(1311693406324658000L, 6789) + Adapter.newBoth (1311693406324658000L, 6789) Assert.True((result = expected)) finally @@ -238,14 +248,14 @@ module AltCoverTests = Instance.CoverageFormat <- ReportFormat.NCover let result2 = - Adapter.payloadSelection(1311693406324658740L, 1000L, true) + Adapter.payloadSelection (1311693406324658740L, 1000L, true) let expected2 = Adapter.time 1311693406324658000L Assert.True((result2 = expected2)) let v1 = DateTime.UtcNow.Ticks - let probed = Adapter.payloadControl(1000L, true) + let probed = Adapter.payloadControl (1000L, true) let v2 = DateTime.UtcNow.Ticks - Assert.True(Adapter.asNull() |> Adapter.untime |> Seq.isEmpty) + Assert.True(Adapter.asNull () |> Adapter.untime |> Seq.isEmpty) let [ probe ] = Adapter.untime probed |> Seq.toList Assert.True(probe % 1000L = 0L) Assert.True(probe <= v2) @@ -310,7 +320,7 @@ module AltCoverTests = Instance.I.trace <- Adapter.makeNullTrace null let key = " " - Instance.I.visitSelection (Adapter.asNull()) key 23 + Instance.I.visitSelection (Adapter.asNull ()) key 23 Assert.That( Instance.I.visits.Count, @@ -378,7 +388,7 @@ module AltCoverTests = let third = Directory.GetFiles(where, "*.exn") Assert.That(third.Length, Is.EqualTo before.Length) - + [] let WrappedExceptionLoggedToFile () = let path = Instance.ReportFile |> Path.GetFullPath @@ -401,17 +411,18 @@ module AltCoverTests = |> Seq.zip [ "ModuleId = \"b\"" "hitPointId = \"c\"" "context = \"d\"" - "exception = System.NullReferenceException: " + unique ] + "exception = System.NullReferenceException: " + + unique ] |> Seq.iter (fun (a, b) -> Assert.That(b, Is.EqualTo a)) let third = Directory.GetFiles(where, "*.exn") - Assert.That(third.Length, Is.EqualTo before.Length) + Assert.That(third.Length, Is.EqualTo before.Length) [] let Issue71WrapperHandlesKeyNotFoundException () = let pair = [| false; false |] let unique = System.Guid.NewGuid().ToString() - Adapter.invokeIssue71Wrapper(unique, pair) + Adapter.invokeIssue71Wrapper (unique, pair) Assert.That(pair |> Seq.head, Is.True) Assert.That(pair |> Seq.last, Is.True) @@ -419,7 +430,7 @@ module AltCoverTests = let Issue71WrapperHandlesNullReferenceException () = let pair = [| false; false |] let unique = System.Guid.NewGuid().ToString() - Adapter.invokeIssue71Wrapper(unique, pair) + Adapter.invokeIssue71Wrapper (unique, pair) Assert.That(pair |> Seq.head, Is.True) Assert.That(pair |> Seq.last, Is.True) @@ -427,7 +438,7 @@ module AltCoverTests = let Issue71WrapperHandlesArgumentNullException () = let pair = [| false; false |] let unique = System.Guid.NewGuid().ToString() - Adapter.invokeIssue71Wrapper(unique, pair) + Adapter.invokeIssue71Wrapper (unique, pair) Assert.That(pair |> Seq.head, Is.True) Assert.That(pair |> Seq.last, Is.True) @@ -438,13 +449,13 @@ module AltCoverTests = let exn = Assert.Throws - (fun () -> Adapter.invokeIssue71Wrapper(unique, pair)) + (fun () -> Adapter.invokeIssue71Wrapper (unique, pair)) Assert.That(pair |> Seq.head, Is.False) Assert.That(pair |> Seq.last, Is.False) Assert.That(exn.Message, Is.EqualTo unique) -#if NET5_0 +#if !NET472 && !NET20 [] let NullRefShouldBeHandled () = getMyMethodName "=>" @@ -459,7 +470,7 @@ module AltCoverTests = let path = Instance.ReportFile |> Path.GetFullPath let where = path |> Path.GetDirectoryName 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") Assert.That(after.Length, Is.GreaterThan before.Length) let all = HashSet(after) @@ -498,8 +509,8 @@ module AltCoverTests = try Instance.I.visits.Clear() let 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.Count, Is.EqualTo 2) finally Instance.I.visits.Clear()) @@ -516,8 +527,8 @@ module AltCoverTests = try Instance.I.visits.Clear() let 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.Count, Is.EqualTo 1) Assert.That(Instance.I.visits.[key].Count, Is.EqualTo 2) finally @@ -537,8 +548,8 @@ module AltCoverTests = try Instance.I.visits.Clear() let key = " " - 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 @@ -559,7 +570,7 @@ module AltCoverTests = Instance.I.visits.Clear() let key = " " let payload = Adapter.time DateTime.UtcNow.Ticks - Instance.I.visitImpl key 23 (Adapter.asNull()) + 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 ]) @@ -623,7 +634,7 @@ module AltCoverTests = .GetManifestResourceStream(resource) ) - updateReport(Dictionary>()) worker + updateReport (Dictionary>()) worker worker.Position <- 0L let after = XmlDocument() after.Load worker @@ -674,7 +685,7 @@ module AltCoverTests = .GetManifestResourceStream(resource) ) - updateReport(Dictionary>()) worker + updateReport (Dictionary>()) worker worker.Position <- 0L let after = XmlDocument() after.Load worker @@ -725,7 +736,7 @@ module AltCoverTests = .GetManifestResourceStream(resource) ) - updateReport(Dictionary>()) worker + updateReport (Dictionary>()) worker worker.Position <- 0L let after = XmlDocument() after.Load worker @@ -774,7 +785,7 @@ module AltCoverTests = .GetManifestResourceStream(resource) ) - updateReport(Dictionary>()) worker + updateReport (Dictionary>()) worker worker.Position <- 0L let after = XmlDocument() after.Load worker @@ -981,7 +992,7 @@ module AltCoverTests = let payload = Dictionary() [ 0 .. 9 ] - |> Seq.iter (fun i -> payload.[i] <- pointVisitInit(int64 (i + 1)) []) + |> Seq.iter (fun i -> payload.[i] <- pointVisitInit (int64 (i + 1)) []) let item = Dictionary>() @@ -1034,19 +1045,19 @@ module AltCoverTests = let payload = Dictionary() [ 0 .. 9 ] - |> Seq.iter (fun i -> payload.[10 - i] <- pointVisitInit(int64 (i + 1)) []) + |> Seq.iter (fun i -> payload.[10 - i] <- pointVisitInit (int64 (i + 1)) []) [ 11 .. 12 ] |> Seq.iter (fun i -> - payload.[i ||| Counter.branchFlag] <- pointVisitInit(int64 (i - 10)) []) + payload.[i ||| Counter.branchFlag] <- pointVisitInit (int64 (i - 10)) []) let item = Dictionary>() 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) + Adapter.updateReport (item, ReportFormat.OpenCover, worker, worker) |> ignore worker.Position <- 0L @@ -1102,7 +1113,8 @@ module AltCoverTests = let trywith<'a when 'a :> exn> f g = try f () - with :? 'a -> g () + with + | :? 'a -> g () let trywithrelease<'a when 'a :> exn> f = trywith f Instance.I.mutex.ReleaseMutex @@ -1580,11 +1592,11 @@ module AltCoverTests = let payload = Dictionary() [ 0 .. 9 ] - |> Seq.iter (fun i -> payload.[i] <- pointVisitInit(int64 (i + 1)) []) + |> Seq.iter (fun i -> payload.[i] <- pointVisitInit (int64 (i + 1)) []) visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - Adapter.doFlush( + Adapter.doFlush ( visits, AltCover.Recorder.ReportFormat.NCover, reportFile, @@ -1668,11 +1680,11 @@ module AltCoverTests = let payload = Dictionary() [ 0 .. 9 ] - |> Seq.iter (fun i -> payload.[i] <- pointVisitInit(int64 (i + 1)) []) + |> Seq.iter (fun i -> payload.[i] <- pointVisitInit (int64 (i + 1)) []) visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - Adapter.doFlush( + Adapter.doFlush ( visits, AltCover.Recorder.ReportFormat.NCover, reportFile, @@ -1748,11 +1760,11 @@ module AltCoverTests = let payload = Dictionary() [ 0 .. 9 ] - |> Seq.iter (fun i -> payload.[i] <- pointVisitInit(int64 (i + 1)) []) + |> Seq.iter (fun i -> payload.[i] <- pointVisitInit (int64 (i + 1)) []) visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - Adapter.doFlush( + Adapter.doFlush ( visits, AltCover.Recorder.ReportFormat.NCover, reportFile, @@ -1837,11 +1849,11 @@ module AltCoverTests = let payload = Dictionary() [ 0 .. 9 ] - |> Seq.iter (fun i -> payload.[i] <- pointVisitInit(int64 (i + 1)) []) + |> Seq.iter (fun i -> payload.[i] <- pointVisitInit (int64 (i + 1)) []) visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - Adapter.doFlush( + Adapter.doFlush ( visits, AltCover.Recorder.ReportFormat.NCover, reportFile, @@ -1910,11 +1922,11 @@ module AltCoverTests = let payload = Dictionary() [ 0 .. 9 ] - |> Seq.iter (fun i -> payload.[i] <- pointVisitInit(int64 (i + 1)) []) + |> Seq.iter (fun i -> payload.[i] <- pointVisitInit (int64 (i + 1)) []) visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload - Adapter.doFlush(visits, AltCover.Recorder.ReportFormat.NCover, reportFile, null) + Adapter.doFlush (visits, AltCover.Recorder.ReportFormat.NCover, reportFile, null) |> ignore Assert.That(reportFile |> File.Exists |> not) @@ -2056,4 +2068,8 @@ module AltCoverTests = #if !NET20 ZipFlushLeavesExpectedTraces() #endif - FlushLeavesExpectedTraces() \ No newline at end of file + FlushLeavesExpectedTraces() + +[] +() \ No newline at end of file diff --git a/AltCover.Recorder.Tests/Tracer.Tests.fs b/AltCover.Recorder.Tests/Tracer.Tests.fs index 4c196cb08..d4a2c7166 100644 --- a/AltCover.Recorder.Tests/Tracer.Tests.fs +++ b/AltCover.Recorder.Tests/Tracer.Tests.fs @@ -22,80 +22,100 @@ open NUnit.Framework module AltCoverCoreTests = let maybeIOException f = try - f() - with :? IOException -> () + f () + with + | :? IOException -> () - let maybeDeleteFile f = - if File.Exists f - then File.Delete f + let maybeDeleteFile f = if File.Exists f then File.Delete f let maybeReraise f g = try - f() - with _ -> - g() - reraise() + f () + with + | _ -> + g () + reraise () [] - let ExcerciseItAll() = - let where = Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName - let unique = Path.Combine(Path.Combine(where, Guid.NewGuid().ToString()), "nonesuch.txt") + let ExcerciseItAll () = + let where = + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName + + let unique = + Path.Combine(Path.Combine(where, Guid.NewGuid().ToString()), "nonesuch.txt") + maybeDeleteFile unique - maybeIOException (fun () -> - maybeReraise (fun () -> File.Delete unique) ignore - ) - maybeIOException (fun () -> - maybeReraise (fun () -> IOException() |> raise) ignore - ) + maybeIOException (fun () -> maybeReraise (fun () -> File.Delete unique) ignore) + maybeIOException (fun () -> maybeReraise (fun () -> IOException() |> raise) ignore) [] - let WillNotConnectSpontaneously() = - let where = Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName - let unique = Path.Combine(where, Guid.NewGuid().ToString()) + let WillNotConnectSpontaneously () = + let where = + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName + + let unique = + Path.Combine(where, Guid.NewGuid().ToString()) + let mutable client = Tracer.Create unique let close = (fun () -> client.Close()) maybeReraise - (fun () -> + (fun () -> client <- client.OnStart() Assert.True(client.IsConnected |> not) - close()) + close ()) close [] - let ValidTokenWillConnect() = - let where = Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName - let unique = Path.Combine(where, Guid.NewGuid().ToString()) - do use stream = File.Create(unique) - () + let ValidTokenWillConnect () = + let where = + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName + + let unique = + Path.Combine(where, Guid.NewGuid().ToString()) + + do + use stream = File.Create(unique) + () + let mutable client = Tracer.Create unique + try client <- client.OnStart() Assert.True(client.IsConnected) finally client.Close() - let internal readResults(stream : Stream) = + let internal readResults (stream: Stream) = let hits = List() use formatter = new System.IO.BinaryReader(stream) - let rec sink() = - maybeIOException (fun () -> - let id = formatter.ReadString() - let strike = formatter.ReadInt32() - let tag = formatter.ReadByte() |> int - (id, strike, - match enum tag with - //| Tag.Time -> Adapter.Time <| formatter.ReadInt64() - | Tag.Call -> Adapter.asCall <| formatter.ReadInt32() - //| Tag.Both -> Adapter.NewBoth((formatter.ReadInt64()), (formatter.ReadInt32())) - | Tag.Table -> - Assert.True(( id = String.Empty )) - Assert.True(( strike = 0 )) - let t = Dictionary>() - - let rec ``module``() = + let rec sink () = + maybeIOException + (fun () -> + let id = formatter.ReadString() + let strike = formatter.ReadInt32() + let tag = formatter.ReadByte() |> int + + (id, + strike, + match enum tag with + //| Tag.Time -> Adapter.Time <| formatter.ReadInt64() + | Tag.Call -> Adapter.asCall <| formatter.ReadInt32() + //| Tag.Both -> Adapter.NewBoth((formatter.ReadInt64()), (formatter.ReadInt32())) + | Tag.Table -> + Assert.True((id = String.Empty)) + Assert.True((strike = 0)) + + let t = + Dictionary>() + + let rec ``module`` () = let m = formatter.ReadString() + if String.IsNullOrEmpty m then () else @@ -106,52 +126,73 @@ module AltCoverCoreTests = if pts > 0 then let p = formatter.ReadInt32() let n = formatter.ReadInt64() - let pv = Adapter.init(n, []) + let pv = Adapter.init (n, []) t.[m].Add(p, pv) - let rec tracking() = + + let rec tracking () = let track = formatter.ReadByte() |> int + match enum track with | Tag.Time -> - pv.Tracks.Add(Adapter.time <| formatter.ReadInt64()) - tracking() + pv.Tracks.Add(Adapter.time <| formatter.ReadInt64()) + tracking () | Tag.Call -> - pv.Tracks.Add(Adapter.asCall <| formatter.ReadInt32()) - tracking() + pv.Tracks.Add(Adapter.asCall <| formatter.ReadInt32()) + tracking () | Tag.Both -> - pv.Tracks.Add - (Adapter.newBoth - ((formatter.ReadInt64()), (formatter.ReadInt32()))) - tracking() + pv.Tracks.Add( + Adapter.newBoth ( + (formatter.ReadInt64()), + (formatter.ReadInt32()) + ) + ) + + tracking () //| Tag.Table -> Assert.True( false, "No nested tables!!") | _ -> sequencePoint (pts - 1) - tracking() + + tracking () else - ``module``() + ``module`` () + sequencePoint points - ``module``() + + ``module`` () Adapter.table t - | _ -> Adapter.asNull()) - |> hits.Add - sink()) - sink() + | _ -> Adapter.asNull ()) + |> hits.Add + + sink ()) + + sink () hits [] - let VisitShouldSignal() = + let VisitShouldSignal () = let save = Instance.I.trace - let where = Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName - let unique = Path.Combine(where, Guid.NewGuid().ToString()) + + let where = + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName + + let unique = + Path.Combine(where, Guid.NewGuid().ToString()) + let tag = unique + ".acv" - let expected = [ ("name", 23, Adapter.asNull()) ] - do use stream = File.Create tag - () + let expected = [ ("name", 23, Adapter.asNull ()) ] + + do + use stream = File.Create tag + () + try let mutable client = Tracer.Create tag + try Adapter.VisitsClear() Instance.I.trace <- client.OnStart() - Assert.True( Instance.I.trace.IsConnected, "connection failed") + Assert.True(Instance.I.trace.IsConnected, "connection failed") Instance.I.isRunner <- true Adapter.VisitImplNone("name", 23) finally @@ -159,43 +200,56 @@ module AltCoverCoreTests = Instance.I.trace.Close() Instance.I.trace.Close() Instance.I.trace <- save + use stream = new DeflateStream(File.OpenRead(unique + ".0.acv"), CompressionMode.Decompress) + let results = readResults stream |> Seq.toList - Assert.True( Adapter.VisitsSeq() |> Seq.isEmpty, "unexpected local write") + Assert.True(Adapter.VisitsSeq() |> Seq.isEmpty, "unexpected local write") Assert.True((results = expected), "unexpected result") finally Adapter.Reset() [] - let VisitShouldSignalTrack() = + let VisitShouldSignalTrack () = let save = Instance.I.trace - let where = Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName - let unique = Path.Combine(where, Guid.NewGuid().ToString()) + + let where = + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName + + let unique = + Path.Combine(where, Guid.NewGuid().ToString()) + let tag = unique + ".acv" - let t = Dictionary>() + + let t = + Dictionary>() + t.["name"] <- Dictionary() - let expect23 = - [ Adapter.asCall 17 - Adapter.asCall 42 ] + let expect23 = [ Adapter.asCall 17; Adapter.asCall 42 ] let expect24 = [ Adapter.time 17L - Adapter.newBoth(42L, 23) ] + Adapter.newBoth (42L, 23) ] - t.["name"].[23] <- Adapter.init(1L, expect23) - t.["name"].[24] <- Adapter.init(2L, expect24) + t.["name"].[23] <- Adapter.init (1L, expect23) + t.["name"].[24] <- Adapter.init (2L, expect24) let expected = [ (String.Empty, 0, Adapter.table t) ("name", 23, Adapter.asCall 5) ] - do use stream = File.Create tag - () + + do + use stream = File.Create tag + () + try let mutable client = Tracer.Create tag + try Instance.I.trace <- client.OnStart() - Assert.True( Instance.I.trace.IsConnected, "connection failed") + Assert.True(Instance.I.trace.IsConnected, "connection failed") Instance.I.isRunner <- true Adapter.VisitsClear() @@ -205,40 +259,53 @@ module AltCoverCoreTests = Instance.I.isRunner <- false Instance.I.trace.Close() Instance.I.trace <- save + use stream = new DeflateStream(File.OpenRead(unique + ".0.acv"), CompressionMode.Decompress) + let results = readResults stream - Assert.True( ("no", 0, Adapter.asNull()) - |> Adapter.untable - |> Seq.isEmpty) - Assert.True( Adapter.VisitsSeq() |> Seq.isEmpty, "unexpected local write") - Assert.True( results.Count = 2 ) - Assert.True( (results - |> Seq.skip 1 - |> Seq.head) = - (expected - |> Seq.skip 1 - |> Seq.head), "unexpected result") + + Assert.True( + ("no", 0, Adapter.asNull ()) + |> Adapter.untable + |> Seq.isEmpty + ) + + Assert.True(Adapter.VisitsSeq() |> Seq.isEmpty, "unexpected local write") + Assert.True(results.Count = 2) + + Assert.True( + (results |> Seq.skip 1 |> Seq.head) = (expected |> Seq.skip 1 |> Seq.head), + "unexpected result" + ) let [ n'; p'; d' ] = - results - |> Seq.head - |> Adapter.untable - |> Seq.toList + results + |> Seq.head + |> Adapter.untable + |> Seq.toList + let n = n' :?> String let p = p' :?> int - let d = d' :?> Dictionary> - Assert.True( n |> Seq.isEmpty ) - Assert.True(( p = 0 )) - Assert.True(( d.Count = 1 )) - Assert.True( d.["name"] - |> Seq.sortBy (fun kv -> kv.Key) - |> Seq.map (fun kv -> kv.Key) - |> Seq.toList = - (t.["name"] - |> Seq.sortBy (fun kv -> kv.Key) - |> Seq.map (fun kv -> kv.Key) - |> Seq.toList) ) + + let d = + d' :?> Dictionary> + + Assert.True(n |> Seq.isEmpty) + Assert.True((p = 0)) + Assert.True((d.Count = 1)) + + Assert.True( + d.["name"] + |> Seq.sortBy (fun kv -> kv.Key) + |> Seq.map (fun kv -> kv.Key) + |> Seq.toList = + (t.["name"] + |> Seq.sortBy (fun kv -> kv.Key) + |> Seq.map (fun kv -> kv.Key) + |> Seq.toList) + ) + let left = d.["name"] |> Seq.sortBy (fun kv -> kv.Key) @@ -251,7 +318,8 @@ module AltCoverCoreTests = |> Seq.map (fun kv -> kv.Value.Count) |> Seq.toList - Assert.True(( left = right )) + Assert.True((left = right)) + let left2 = d.["name"] |> Seq.sortBy (fun kv -> kv.Key) @@ -264,42 +332,55 @@ module AltCoverCoreTests = |> Seq.map (fun kv -> kv.Value.Tracks |> Seq.toList) |> Seq.toList - Assert.True(( left2 = right2 )) + Assert.True((left2 = right2)) finally Adapter.VisitsClear() [] - let FlushShouldTidyUp() = // also throw a bone to OpenCover 615 + let FlushShouldTidyUp () = // also throw a bone to OpenCover 615 let save = Instance.I.trace - let where = Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName - let root = Path.Combine(where, Guid.NewGuid().ToString()) + + let where = + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName + + let root = + Path.Combine(where, Guid.NewGuid().ToString()) + let unique = root + ".acv" - do use stream = File.Create unique - () + + do + use stream = File.Create unique + () + try let client = Tracer.Create unique - let expected = [ ("name", client.GetHashCode(), Adapter.asNull()) ] + + let expected = + [ ("name", client.GetHashCode(), Adapter.asNull ()) ] + try Adapter.VisitsClear() 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 formatter = System.Runtime.Serialization.Formatters.Binary.BinaryFormatter() + + let formatter = + System.Runtime.Serialization.Formatters.Binary.BinaryFormatter() + let (a, b, c) = expected |> Seq.head - Adapter.tracePush(a, b, c) + Adapter.tracePush (a, b, c) Instance.FlushFinish() finally Instance.I.trace.Close() System.Threading.Thread.Sleep 100 Instance.I.trace <- save + use stream = new DeflateStream(File.OpenRead(root + ".0.acv"), CompressionMode.Decompress) - let results = - stream - |> readResults - |> Seq.toList + let results = stream |> readResults |> Seq.toList Assert.True(Adapter.VisitsSeq() |> Seq.isEmpty, "unexpected local write") Assert.True((results = expected), "unexpected result") finally diff --git a/AltCover.Recorder.sln b/AltCover.Recorder.sln index b0dae13ae..b9b6de952 100644 --- a/AltCover.Recorder.sln +++ b/AltCover.Recorder.sln @@ -38,6 +38,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Items", "Build Items" Build\targets.fsx = Build\targets.fsx EndProjectSection EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Sample25", "Samples\Sample25\Sample25.fsproj", "{54E57C76-339C-496E-B6EF-832534C7D545}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -54,6 +56,9 @@ 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 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/AltCover.Recorder/AltCover.Recorder.fsproj b/AltCover.Recorder/AltCover.Recorder.fsproj index 8675ef4ec..16e02278e 100644 --- a/AltCover.Recorder/AltCover.Recorder.fsproj +++ b/AltCover.Recorder/AltCover.Recorder.fsproj @@ -4,27 +4,18 @@ net20;net46 AltCover.Recorder AltCover.Recorder - false - true false false - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ false TRACE - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk --standalone --staticlink:ICSharpCode.SharpZipLib + $(OtherFlags) --standalone --staticlink:ICSharpCode.SharpZipLib TRACE;DEBUG;CODE_ANALYSIS - 4 - 52 - true - - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk @@ -34,6 +25,7 @@ + AltCover.Recorder.Strings.resources diff --git a/AltCover.Recorder/Base.fs b/AltCover.Recorder/Base.fs index 325c551e6..c899da16d 100644 --- a/AltCover.Recorder/Base.fs +++ b/AltCover.Recorder/Base.fs @@ -129,7 +129,8 @@ module internal Counter = try doc.Load(stream) - with :? XmlException -> doc.LoadXml "" + with + | :? XmlException -> doc.LoadXml "" doc @@ -168,11 +169,7 @@ module internal Counter = | ReportFormat.OpenCoverWithTracking | ReportFormat.OpenCover -> openCoverXml | ReportFormat.NCover -> nCoverXml - | _ -> - raise ( - format - |> (sprintf "%A") - |> NotSupportedException) + | _ -> raise (format |> (sprintf "%A") |> NotSupportedException) let internal minTime (t1: DateTime) (t2: DateTime) = if t1 < t2 then t1 else t2 @@ -287,9 +284,9 @@ module internal Counter = ((match format with | ReportFormat.OpenCoverWithTracking | ReportFormat.OpenCover -> - "uspid" - |> pt.GetAttribute - |> (findIndexFromUspid flag) + "uspid" + |> pt.GetAttribute + |> (findIndexFromUspid flag) | _ -> counter), pt)) |> Seq.filter (fst >> moduleHits.ContainsKey) @@ -414,8 +411,8 @@ module internal Counter = match context with | Table t -> I.addTable counts t | _ -> - addSingleVisit counts moduleId hitPointId context - 1L + addSingleVisit counts moduleId hitPointId context + 1L #endif [ new MemoryStream() :> Stream | Some f -> - new FileStream( - f, - FileMode.OpenOrCreate, - FileAccess.Write, - FileShare.None, - 4096, - FileOptions.SequentialScan - ) - :> Stream + new FileStream( + f, + FileMode.OpenOrCreate, + FileAccess.Write, + FileShare.None, + 4096, + FileOptions.SequentialScan + ) + :> Stream let outputFile = if Option.isSome output then @@ -493,15 +490,15 @@ module internal Counter = match output with | None -> new MemoryStream() :> Stream | Some f -> - new FileStream( - f, - FileMode.OpenOrCreate, - FileAccess.Write, - FileShare.None, - 4096, - FileOptions.SequentialScan - ) - :> Stream + 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 @@ -530,7 +527,8 @@ module internal Counter = result finally zip.Close() - with :? ZipException -> + with + | :? ZipException -> use reader = new MemoryStream() I.doFlush postProcess pointProcess own counts format reader target diff --git a/AltCover.Recorder/InstrumentationAttribute.fs b/AltCover.Recorder/InstrumentationAttribute.fs new file mode 100644 index 000000000..2c929b816 --- /dev/null +++ b/AltCover.Recorder/InstrumentationAttribute.fs @@ -0,0 +1,32 @@ +namespace AltCover.Recorder + +open System +open System.Diagnostics.CodeAnalysis + +/// +/// An attribute to label an instrumented assembly by provenance +/// +[] +[] +type InstrumentationAttribute() = + class + inherit Attribute() + + /// + /// SHA-256 hash of the original assembly + /// + member val Assembly = "AltCover.Recorder.g!" with get, set + + /// + /// SHA-256 hash of instrumentation parameters + /// + member val Configuration = "Uninstrumented!!" with get, set + end + +[] +[] +() \ No newline at end of file diff --git a/AltCover.Recorder/Recorder.fs b/AltCover.Recorder/Recorder.fs index 4278dbb6b..2de4e24da 100644 --- a/AltCover.Recorder/Recorder.fs +++ b/AltCover.Recorder/Recorder.fs @@ -238,20 +238,20 @@ module Instance = match counts.Count with | 0 -> () | _ -> - withMutex - (fun own -> - let delta = - Counter.doFlushFile - ignore - (fun _ _ -> ()) - own - counts - CoverageFormat - ReportFile - None - - getResource "Coverage statistics flushing took {0:N} seconds" - |> Option.iter (fun s -> Console.Out.WriteLine(s, delta.TotalSeconds)))) + withMutex + (fun own -> + let delta = + Counter.doFlushFile + ignore + (fun _ _ -> ()) + own + counts + CoverageFormat + ReportFile + None + + getResource "Coverage statistics flushing took {0:N} seconds" + |> Option.iter (fun s -> Console.Out.WriteLine(s, delta.TotalSeconds)))) let internal flushPause () = ("PauseHandler") @@ -317,7 +317,8 @@ module Instance = internal issue71Wrapper visits moduleId hitPointId context handler add = try add visits moduleId hitPointId context - with x -> + with + | x -> match x with | :? KeyNotFoundException | :? NullReferenceException @@ -332,61 +333,56 @@ module Instance = issue71Wrapper visits moduleId hitPointId context logException add let internal addVisit moduleId hitPointId context = - curriedIssue71Wrapper - visits - moduleId - hitPointId - context - Counter.addSingleVisit + curriedIssue71Wrapper visits moduleId hitPointId context Counter.addSingleVisit 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.ToString() - |> InvalidDataException - |> raise - |> Seq.map - (fun hit -> - let mutable hasModuleKey = samples.ContainsKey(moduleId) - - if hasModuleKey |> not then - lock - samples - (fun () -> - hasModuleKey <- samples.ContainsKey(moduleId) - - if hasModuleKey |> not then - samples.Add(moduleId, Dictionary())) - - 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)) - - (hasPointKey && hasModuleKey) |> not) - |> Seq.fold (||) false // true if any are novel -- all must be evaluated + (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.ToString() + |> InvalidDataException + |> raise) + |> Seq.map + (fun hit -> + let mutable hasModuleKey = samples.ContainsKey(moduleId) + + if hasModuleKey |> not then + lock + samples + (fun () -> + hasModuleKey <- samples.ContainsKey(moduleId) + + if hasModuleKey |> not then + samples.Add(moduleId, Dictionary())) + + 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)) + + (hasPointKey && hasModuleKey) |> not) + |> Seq.fold (||) false // true if any are novel -- all must be evaluated /// /// This method is executed from instrumented assemblies. @@ -419,9 +415,9 @@ module Instance = | (t, None) -> Time(t * (clock () / t)) | (0L, n) -> Call n.Value | (t, n) -> - Both - { Time = t * (clock () / t) - Call = n.Value } + Both + { Time = t * (clock () / t) + Call = n.Value } else Null @@ -436,10 +432,10 @@ module Instance = | Resume -> flushResume () | Pause -> flushPause () | _ -> - recording <- false + recording <- false - if supervision |> not then - flushAll finish + if supervision |> not then + flushAll finish // Register event handling let internal doPause = @@ -505,4 +501,7 @@ module Instance = Scope = "member", Target = ".$Recorder.#.cctor()", Justification = "Compiler generated")>] +// add during instrumentation process +//[] // self label fails compilation () \ No newline at end of file diff --git a/AltCover.Recorder/Tracer.fs b/AltCover.Recorder/Tracer.fs index 9ca435f02..42377e8b1 100644 --- a/AltCover.Recorder/Tracer.fs +++ b/AltCover.Recorder/Tracer.fs @@ -14,7 +14,7 @@ type internal Close = | Resume [] -type Tracer = +type internal Tracer = { Tracer: string Runner: bool Definitive: bool @@ -72,34 +72,34 @@ type Tracer = match context with | Null -> this.Formatter.Write(Tag.Null |> byte) | Time t -> - this.Formatter.Write(Tag.Time |> byte) - this.Formatter.Write(t) + this.Formatter.Write(Tag.Time |> byte) + this.Formatter.Write(t) | Call t -> - this.Formatter.Write(Tag.Call |> byte) - this.Formatter.Write(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) + 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.iter - (fun m -> - this.Formatter.Write m - this.Formatter.Write t.[m].Keys.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 + this.Formatter.Write(Tag.Table |> byte) + + t.Keys + |> Seq.iter + (fun m -> + this.Formatter.Write m + this.Formatter.Write t.[m].Keys.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 member internal this.Push (moduleId: string) (hitPointId: int) context = this.Formatter.Write moduleId diff --git a/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj b/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj index 2ac7b8133..5ee927bbb 100644 --- a/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj +++ b/AltCover.Recorder2.Tests/AltCover.Recorder2.Tests.fsproj @@ -5,25 +5,17 @@ false AltCover.Recorder2.Tests false - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - - NU1702 NU1702 - Major - false - false TRACE;DEBUG;ALTCOVER_TEST;$(ExtraDefines) - --tailcalls+ --keyfile:$(ProjectDir)..\Build\Infrastructure.snk TRACE;RELEASE;ALTCOVER_TEST;$(ExtraDefines) - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk + diff --git a/AltCover.Tests/AltCover.Tests.fsproj b/AltCover.Tests/AltCover.Tests.fsproj index 56d74603c..6dd933b47 100644 --- a/AltCover.Tests/AltCover.Tests.fsproj +++ b/AltCover.Tests/AltCover.Tests.fsproj @@ -5,22 +5,25 @@ false AltCover.Tests MONO - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - - Major + WINDOWS TRACE;$(ExtraDefines) - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk - + 3239;0058 + + Never + + + Never + + @@ -28,6 +31,7 @@ + @@ -109,6 +113,7 @@ + diff --git a/AltCover.Tests/Expecto.fs b/AltCover.Tests/Expecto.fs index 9771f632c..b1089c19e 100644 --- a/AltCover.Tests/Expecto.fs +++ b/AltCover.Tests/Expecto.fs @@ -1,9 +1,7 @@ namespace Tests -#if NET472 // remove for fantomas - -junk goes here // remove for fantomas - -#else // remove for fantomas +#if NET472 +does not build using the framework version +#endif #if EXPECTO_MAIN module Manifest = @@ -14,878 +12,901 @@ module ExpectoTestManifest = let simpleTests () = [| #endif - Tests.TestCommonTests.TestIgnoredTests, "TestCommonTests.TestIgnoredTests" - Tests.TestCommonTests.ExerciseItAll, "TestCommonTests.ExerciseItAll" - Tests.TestCommonTests.SelfTest, "TestCommonTests.SelfTest" - Tests.AltCoverRunnerTests.ShouldFailXmlDataForNativeJson, - "Runner.ShouldFailXmlDataForNativeJson" - Tests.AltCoverRunnerTests.MaxTimeFirst, "Runner.MaxTimeFirst" - Tests.AltCoverRunnerTests.MaxTimeLast, "Runner.MaxTimeLast" - Tests.AltCoverRunnerTests.MinTimeFirst, "Runner.MinTimeFirst" - Tests.AltCoverRunnerTests.MinTimeLast, "Runner.MinTimeLast" - Tests.AltCoverRunnerTests.JunkUspidGivesNegativeIndex, - "Runner.JunkUspidGivesNegativeIndex" - Tests.AltCoverRunnerTests.RealIdShouldIncrementCount, - "Runner.RealIdShouldIncrementCount" - Tests.AltCoverRunnerTests.RealIdShouldIncrementList, - "Runner.RealIdShouldIncrementList" - Tests.AltCoverRunnerTests.DistinctIdShouldBeDistinct, - "Runner.DistinctIdShouldBeDistinct" - Tests.AltCoverRunnerTests.DistinctLineShouldBeDistinct, - "Runner.DistinctLineShouldBeDistinct" - Tests.AltCoverRunnerTests.RepeatVisitsShouldIncrementCount, - "Runner.RepeatVisitsShouldIncrementCount" - Tests.AltCoverRunnerTests.RepeatVisitsShouldIncrementTotal, - "Runner.RepeatVisitsShouldIncrementTotal" - Tests.AltCoverRunnerTests.KnownModuleWithPayloadMakesExpectedChangeInOpenCover, - "Runner.KnownModuleWithPayloadMakesExpectedChangeInOpenCover" - Tests.AltCoverRunnerTests.FlushLeavesExpectedTraces, - "Runner.FlushLeavesExpectedTraces" - Tests.AltCoverRunnerTests.FlushLeavesExpectedTracesWhenDiverted, - "Runner.FlushLeavesExpectedTracesWhenDiverted" - Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleJson, - "Runner.NCoverShouldGeneratePlausibleJson" - Tests.AltCoverRunnerTests.OpenCoverShouldGeneratePlausibleJson, - "Runner.OpenCoverShouldGeneratePlausibleJson" - Tests.AltCoverRunnerTests.UsageIsAsExpected, "Runner.UsageIsAsExpected" - Tests.AltCoverRunnerTests.ShouldLaunchWithExpectedOutput, - "Runner.ShouldLaunchWithExpectedOutput" - Tests.AltCoverRunnerTests.ShouldHaveExpectedOptions, - "Runner.ShouldHaveExpectedOptions" - Tests.AltCoverRunnerTests.ParsingJunkIsAnError, "Runner.ParsingJunkIsAnError" - Tests.AltCoverRunnerTests.ParsingJunkAfterSeparatorIsExpected, - "Runner.ParsingJunkAfterSeparatorIsExpected" - Tests.AltCoverRunnerTests.ParsingHelpGivesHelp, "Runner.ParsingHelpGivesHelp" - Tests.AltCoverRunnerTests.ParsingErrorHelpGivesHelp, - "Runner.ParsingErrorHelpGivesHelp" - Tests.AltCoverRunnerTests.ParsingExeGivesExe, "Runner.ParsingExeGivesExe" - Tests.AltCoverRunnerTests.ParsingMultipleExeGivesFailure, - "Runner.ParsingMultipleExeGivesFailure" - Tests.AltCoverRunnerTests.ParsingNoExeGivesFailure, - "Runner.ParsingNoExeGivesFailure" - Tests.AltCoverRunnerTests.ParsingWorkerGivesWorker, - "Runner.ParsingWorkerGivesWorker" - Tests.AltCoverRunnerTests.ParsingMultipleWorkerGivesFailure, - "Runner.ParsingMultipleWorkerGivesFailure" - Tests.AltCoverRunnerTests.ParsingBadWorkerGivesFailure, - "Runner.ParsingBadWorkerGivesFailure" - Tests.AltCoverRunnerTests.ParsingNoWorkerGivesFailure, - "Runner.ParsingNoWorkerGivesFailure" - Tests.AltCoverRunnerTests.ParsingRecorderGivesRecorder, - "Runner.ParsingRecorderGivesRecorder" - Tests.AltCoverRunnerTests.ParsingMultipleRecorderGivesFailure, - "Runner.ParsingMultipleRecorderGivesFailure" - Tests.AltCoverRunnerTests.ParsingBadRecorderGivesFailure, - "Runner.ParsingBadRecorderGivesFailure" - Tests.AltCoverRunnerTests.ParsingNoRecorderGivesFailure, - "Runner.ParsingNoRecorderGivesFailure" - Tests.AltCoverRunnerTests.ParsingCollectGivesCollect, - "Runner.ParsingCollectGivesCollect" - Tests.AltCoverRunnerTests.ParsingMultipleCollectGivesFailure, - "Runner.ParsingMultipleCollectGivesFailure" - Tests.AltCoverRunnerTests.ParsingLcovGivesLcov, "Runner.ParsingLcovGivesLcov" - Tests.AltCoverRunnerTests.ParsingMultipleLcovGivesFailure, - "Runner.ParsingMultipleLcovGivesFailure" - Tests.AltCoverRunnerTests.ParsingNoLcovGivesFailure, - "Runner.ParsingNoLcovGivesFailure" - Tests.AltCoverRunnerTests.ParsingThresholdGivesThreshold, - "Runner.ParsingThresholdGivesThreshold" - Tests.AltCoverRunnerTests.ParsingTopThresholdGivesThreshold, - "Runner.ParsingTopThresholdGivesThreshold" - Tests.AltCoverRunnerTests.ParsingLowThresholdGivesThreshold, - "Runner.ParsingLowThresholdGivesThreshold" - Tests.AltCoverRunnerTests.ParsingComplexThresholdGivesThreshold, - "Runner.ParsingComplexThresholdGivesThreshold" - Tests.AltCoverRunnerTests.ParsingMultipleThresholdGivesFailure, - "Runner.ParsingMultipleThresholdGivesFailure" - Tests.AltCoverRunnerTests.ParsingBadThresholdGivesFailure, - "Runner.ParsingBadThresholdGivesFailure" - Tests.AltCoverRunnerTests.ParsingBadThreshold2GivesFailure, - "Runner.ParsingBadThreshold2GivesFailure" - Tests.AltCoverRunnerTests.ParsingBadThreshold3GivesFailure, - "Runner.ParsingBadThreshold3GivesFailure" - Tests.AltCoverRunnerTests.ParsingBadThreshold4GivesFailure, - "Runner.ParsingBadThreshold4GivesFailure" - Tests.AltCoverRunnerTests.ParsingBadThreshold5GivesFailure, - "Runner.ParsingBadThreshold5GivesFailure" - Tests.AltCoverRunnerTests.ParsingBadThreshold6GivesFailure, - "Runner.ParsingBadThreshold6GivesFailure" - Tests.AltCoverRunnerTests.ParsingBadThreshold7GivesFailure, - "Runner.ParsingBadThreshold7GivesFailure" - Tests.AltCoverRunnerTests.ParsingEmptyThresholdGivesFailure, - "Runner.ParsingEmptyThresholdGivesFailure" - Tests.AltCoverRunnerTests.ParsingNoThresholdGivesFailure, - "Runner.ParsingNoThresholdGivesFailure" - Tests.AltCoverRunnerTests.ParsingCoberturaGivesCobertura, - "Runner.ParsingCoberturaGivesCobertura" - Tests.AltCoverRunnerTests.ParsingMultipleCoberturaGivesFailure, - "Runner.ParsingMultipleCoberturaGivesFailure" - Tests.AltCoverRunnerTests.ParsingNoCoberturaGivesFailure, - "Runner.ParsingNoCoberturaGivesFailure" - Tests.AltCoverRunnerTests.ParsingOutputGivesOutput, - "Runner.ParsingOutputGivesOutput" - Tests.AltCoverRunnerTests.ParsingMultipleOutputGivesFailure, - "Runner.ParsingMultipleOutputGivesFailure" - Tests.AltCoverRunnerTests.ParsingNoOutputGivesFailure, - "Runner.ParsingNoOutputGivesFailure" - Tests.AltCoverRunnerTests.ParsingDropGivesDrop, "Runner.ParsingDropGivesDrop" - Tests.AltCoverRunnerTests.ParsingMultipleDropGivesFailure, - "Runner.ParsingMultipleDropGivesFailure" - Tests.AltCoverRunnerTests.ParsingTCString, "Runner.ParsingTCString" - Tests.AltCoverRunnerTests.ParsingTCGivesTC, "Runner.ParsingTCGivesTC" - Tests.AltCoverRunnerTests.ParsingMultipleTCGivesFailure, - "Runner.ParsingMultipleTCGivesFailure" - Tests.AltCoverRunnerTests.ParsingBadTCGivesFailure, - "Runner.ParsingBadTCGivesFailure" - Tests.AltCoverRunnerTests.ParsingQuietWorks, "Runner.ParsingQuietWorks" - Tests.AltCoverRunnerTests.ParsingMultiQuietWorks, "Runner.ParsingMultiQuietWorks" - Tests.AltCoverRunnerTests.ParsingBatchMultiQuietWorks, - "Runner.ParsingBatchMultiQuietWorks" - Tests.AltCoverRunnerTests.ShouldRequireExe, "Runner.ShouldRequireExe" - Tests.AltCoverRunnerTests.ShouldAcceptExe, "Runner.ShouldAcceptExe" - Tests.AltCoverRunnerTests.ShouldRequireCollectIfNotExe, - "Runner.ShouldRequireCollectIfNotExe" - Tests.AltCoverRunnerTests.ShouldRejectExeIfCollect, - "Runner.ShouldRejectExeIfCollect" - Tests.AltCoverRunnerTests.ShouldRequireWorker, "Runner.ShouldRequireWorker" - Tests.AltCoverRunnerTests.ShouldAcceptWorker, "Runner.ShouldAcceptWorker" - Tests.AltCoverRunnerTests.ShouldRequireRecorder, "Runner.ShouldRequireRecorder" - Tests.AltCoverRunnerTests.ShouldRequireRecorderDll, - "Runner.ShouldRequireRecorderDll" - Tests.AltCoverRunnerTests.ShouldAcceptRecorder, "Runner.ShouldAcceptRecorder" - Tests.AltCoverRunnerTests.ShouldHandleReturnCodes, "Runner.ShouldHandleReturnCodes" - Tests.AltCoverRunnerTests.ShouldProcessTrailingArguments, - "Runner.ShouldProcessTrailingArguments" - Tests.AltCoverRunnerTests.ShouldNoOp, "Runner.ShouldNoOp" - Tests.AltCoverRunnerTests.ErrorResponseIsAsExpected, - "Runner.ErrorResponseIsAsExpected" - Tests.AltCoverRunnerTests.ShouldGetStringConstants, - "Runner.ShouldGetStringConstants" - Tests.AltCoverRunnerTests.ShouldProcessPayload, "Runner.ShouldProcessPayload" - Tests.AltCoverRunnerTests.WriteJsonLeavesExpectedTraces, - "Runner.WriteJsonLeavesExpectedTraces" - Tests.AltCoverRunnerTests.ZipWriteJsonLeavesExpectedTraces, - "Runner.ZipWriteJsonLeavesExpectedTraces" - Tests.AltCoverRunnerTests.NullPayloadShouldReportNothing, - "Runner.NullPayloadShouldReportNothing" - Tests.AltCoverRunnerTests.WriteLeavesExpectedTraces, - "Runner.WriteLeavesExpectedTraces" - Tests.AltCoverRunnerTests.ZipWriteLeavesExpectedTraces, - "Runner.ZipWriteLeavesExpectedTraces" - Tests.AltCoverRunnerTests.ActivePayloadShouldReportAsExpected, - "Runner.ActivePayloadShouldReportAsExpected" - Tests.AltCoverRunnerTests.CollectShouldReportAsExpected, - "Runner.CollectShouldReportAsExpected" - Tests.AltCoverRunnerTests.JunkPayloadShouldReportAsExpected, - "Runner.JunkPayloadShouldReportAsExpected" - Tests.AltCoverRunnerTests.TrackingPayloadShouldReportAsExpected, - "Runner.TrackingPayloadShouldReportAsExpected" - Tests.AltCoverRunnerTests.PointProcessShouldCaptureTimes, - "Runner.PointProcessShouldCaptureTimes" - Tests.AltCoverRunnerTests.PostprocessShouldHandleNullCase, - "Runner.PostprocessShouldHandleNullCase" - Tests.AltCoverRunnerTests.PostprocessShouldHandleEntryAndExitTimes, - "Runner.PostprocessShouldHandleEntryAndExitTimes" - Tests.AltCoverRunnerTests.PostprocessShouldRestoreKnownOpenCoverState, - "Runner.PostprocessShouldRestoreKnownOpenCoverState" - Tests.AltCoverRunnerTests.PostprocessShouldRestoreKnownOpenCoverStateFromMono, - "Runner.PostprocessShouldRestoreKnownOpenCoverStateFromMono" - Tests.AltCoverRunnerTests.PostprocessShouldRestoreDegenerateOpenCoverState, - "Runner.PostprocessShouldRestoreDegenerateOpenCoverState" - Tests.AltCoverRunnerTests.PostprocessShouldRestoreBranchOnlyOpenCoverState, - "Runner.PostprocessShouldRestoreBranchOnlyOpenCoverState" - Tests.AltCoverRunnerTests.PostprocessShouldRestoreBranchOnlyOpenCoverStateXDoc, - "Runner.PostprocessShouldRestoreBranchOnlyOpenCoverStateXDoc" - Tests.AltCoverRunnerTests.JunkTokenShouldDefaultZero, - "Runner.JunkTokenShouldDefaultZero" - Tests.AltCoverRunnerTests.EmptyJsonGeneratesExpectedSummary, - "Runner.EmptyJsonGeneratesExpectedSummary" - Tests.AltCoverRunnerTests.EmptyJsonGeneratesExpectedTCSummary, - "Runner.EmptyJsonGeneratesExpectedTCSummary" - Tests.AltCoverRunnerTests.EmptyJsonGeneratesExpectedSummaries, - "Runner.EmptyJsonGeneratesExpectedSummaries" - Tests.AltCoverRunnerTests.SimpleJsonShouldGeneratePlausibleSummary, - "Runner.SimpleJsonShouldGeneratePlausibleSummary" - Tests.AltCoverRunnerTests.ComplexJsonShouldGeneratePlausibleSummary, - "Runner.ComplexJsonShouldGeneratePlausibleSummary" - Tests.AltCoverRunnerTests.EmptyNCoverGeneratesExpectedSummary, - "Runner.EmptyNCoverGeneratesExpectedSummary" - Tests.AltCoverRunnerTests.EmptyNCoverGeneratesExpectedTCSummary, - "Runner.EmptyNCoverGeneratesExpectedTCSummary" - Tests.AltCoverRunnerTests.EmptyNCoverGeneratesExpectedSummaries, - "Runner.EmptyNCoverGeneratesExpectedSummaries" - Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleSummary, - "Runner.NCoverShouldGeneratePlausibleSummary" - Tests.AltCoverRunnerTests.EmptyOpenCoverGeneratesExpectedSummary, - "Runner.EmptyOpenCoverGeneratesExpectedSummary" - Tests.AltCoverRunnerTests.EmptyOpenCoverGeneratesExpectedTCSummary, - "Runner.EmptyOpenCoverGeneratesExpectedTCSummary" - Tests.AltCoverRunnerTests.EmptyOpenCoverGeneratesExpectedSummaries, - "Runner.EmptyOpenCoverGeneratesExpectedSummaries" - Tests.AltCoverRunnerTests.OpenCoverShouldGeneratePlausibleSummary, - "Runner.OpenCoverShouldGeneratePlausibleSummary" - Tests.AltCoverRunnerTests.OpenCoverShouldGeneratePlausiblePartialSummary, - "Runner.OpenCoverShouldGeneratePlausiblePartialSummary" - Tests.AltCoverRunnerTests.DegenerateCasesShouldNotGenerateLcov, - "Runner.DegenerateCasesShouldNotGenerateLcov" - Tests.AltCoverRunnerTests.OpenCoverShouldGeneratePlausibleLcov, - "Runner.OpenCoverShouldGeneratePlausibleLcov" - Tests.AltCoverRunnerTests.OpenCoverWithPartialsShouldGeneratePlausibleLcov, - "Runner.OpenCoverWithPartialsShouldGeneratePlausibleLcov" - Tests.AltCoverRunnerTests.JsonShouldGeneratePlausibleLcov, - "Runner.JsonShouldGeneratePlausibleLcov" - Tests.AltCoverRunnerTests.JsonWithPartialsShouldGeneratePlausibleLcov, - "Runner.JsonWithPartialsShouldGeneratePlausibleLcov" - Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleLcov, - "Runner.NCoverShouldGeneratePlausibleLcov" - Tests.AltCoverRunnerTests.NCoverWithPartialsShouldGeneratePlausibleLcov, - "Runner.NCoverWithPartialsShouldGeneratePlausibleLcov" - Tests.AltCoverRunnerTests.NCoverShouldGenerateMorePlausibleLcov, - "Runner.NCoverShouldGenerateMorePlausibleLcov" - Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleLcovWithMissingFullName, - "Runner.NCoverShouldGeneratePlausibleLcovWithMissingFullName" - Tests.AltCoverRunnerTests.MultiSortDoesItsThing, "Runner.MultiSortDoesItsThing" - Tests.AltCoverRunnerTests.JsonShouldGeneratePlausibleXml, - "Runner.JsonShouldGeneratePlausibleXml" - Tests.AltCoverRunnerTests.JsonWithPartialsShouldGeneratePlausibleXml, - "Runner.JsonWithPartialsShouldGeneratePlausibleXml" - Tests.AltCoverRunnerTests.JsonShouldGeneratePlausibleCobertura, - "Runner.JsonShouldGeneratePlausibleCobertura" - Tests.AltCoverRunnerTests.JsonWithPartialsShouldGeneratePlausibleCobertura, - "Runner.JsonWithPartialsShouldGeneratePlausibleCobertura" - Tests.AltCoverRunnerTests.JsonFromComplexNestingShouldGeneratePlausibleCobertura, - "Runner.JsonFromComplexNestingShouldGeneratePlausibleCobertura" - Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleCobertura, - "Runner.NCoverShouldGeneratePlausibleCobertura" - Tests.AltCoverRunnerTests.NCoverWithPartialsShouldGeneratePlausibleCobertura, - "Runner.NCoverWithPartialsShouldGeneratePlausibleCobertura" - Tests.AltCoverRunnerTests.NCoverShouldGenerateMorePlausibleCobertura, - "Runner.NCoverShouldGenerateMorePlausibleCobertura" - Tests.AltCoverRunnerTests.DegenerateCasesShouldNotGenerateCobertura, - "Runner.DegenerateCasesShouldNotGenerateCobertura" - Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleCoberturaWithMissingFullName, - "Runner.NCoverShouldGeneratePlausibleCoberturaWithMissingFullName" - Tests.AltCoverRunnerTests.OpenCoverShouldGeneratePlausibleCobertura, - "Runner.OpenCoverShouldGeneratePlausibleCobertura" - Tests.AltCoverRunnerTests.OpenCoverWithPartialsShouldGeneratePlausibleCobertura, - "Runner.OpenCoverWithPartialsShouldGeneratePlausibleCobertura" - Tests.AltCoverRunnerTests.ThresholdViolationShouldBeReported, - "Runner.ThresholdViolationShouldBeReported" - Tests.AltCoverRunnerTests.TryGetValueHandlesNull, "Runner.TryGetValueHandlesNull" - Tests.AltCoverTests.ReportFileShouldBeCorrectlySuffixed, "Tests.ReportFileShouldBeCorrectlySuffixed" - Tests.AltCoverTests.CanSwitchSampling, "Tests.CanSwitchSampling" - Tests.AltCoverTests.ShouldGetPdbFromImage, "Tests.ShouldGetPdbFromImage" - Tests.AltCoverTests.ShouldGetEmbeddedPdbFromImage, - "Tests.ShouldGetEmbeddedPdbFromImage" - Tests.AltCoverTests.ShouldGetNoMdbFromMonoImage, "Tests.ShouldGetNoMdbFromMonoImage" - Tests.AltCoverTests.ShouldGetPdbWithFallback, "Tests.ShouldGetPdbWithFallback" - Tests.AltCoverTests.ShouldGetForeignPdbWithFallback, - "Tests.ShouldGetForeignPdbWithFallback" - Tests.AltCoverTests.ShouldGetForeignPdbWithFallbackWhenNotColocated, - "Tests.ShouldGetForeignPdbWithFallbackWhenNotColocated" - Tests.AltCoverTests.ShouldGetMdbWithFallback, "Tests.ShouldGetMdbWithFallback" - Tests.AltCoverTests.ShouldGetSymbolsFromPdb, "Tests.ShouldGetSymbolsFromPdb" - Tests.AltCoverTests.ShouldGetSymbolsFromEmbeddedPdb, - "Tests.ShouldGetSymbolsFromEmbeddedPdb" - Tests.AltCoverTests.ShouldNotGetSymbolsWhenNoPdb, - "Tests.ShouldNotGetSymbolsWhenNoPdb" - Tests.AltCoverTests.ShouldGetSymbolsFromMdb, "Tests.ShouldGetSymbolsFromMdb" - Tests.AltCoverTests.NoneOfTheAboveMatchesNoType, "Tests.NoneOfTheAboveMatchesNoType" - Tests.AltCoverTests.NoneOfTheAboveMatchesNoAttribute, - "Tests.NoneOfTheAboveMatchesNoAttribute" - Tests.AltCoverTests.NoneOfTheAboveMatchesNoAssembly, - "Tests.NoneOfTheAboveMatchesNoAssembly" - Tests.AltCoverTests.NoneOfTheAboveMatchesNoModule, - "Tests.NoneOfTheAboveMatchesNoModule" - Tests.AltCoverTests.NoneOfTheAboveMatchesNoFile, "Tests.NoneOfTheAboveMatchesNoFile" - Tests.AltCoverTests.NoneOfTheAboveMatchesNoPath, "Tests.NoneOfTheAboveMatchesNoPath" - Tests.AltCoverTests.NoneOfTheAboveMatchesNoMethod, - "Tests.NoneOfTheAboveMatchesNoMethod" - Tests.AltCoverTests.FileDoesNotMatchNonFileClass, - "Tests.FileDoesNotMatchNonFileClass" - Tests.AltCoverTests.FileDoesMatchFileClass, "Tests.FileDoesMatchFileClass" - Tests.AltCoverTests.PathDoesNotMatchNonPathClass, - "Tests.PathDoesNotMatchNonPathClass" - Tests.AltCoverTests.PathDoesMatchPathClass, "Tests.PathDoesMatchPathClass" - Tests.AltCoverTests.AssemblyDoesNotMatchNonAssemblyClass, - "Tests.AssemblyDoesNotMatchNonAssemblyClass" - Tests.AltCoverTests.AssemblyDoesMatchAssemblyClass, - "Tests.AssemblyDoesMatchAssemblyClass" - Tests.AltCoverTests.ModuleDoesNotMatchNonModuleClass, - "Tests.ModuleDoesNotMatchNonModuleClass" - Tests.AltCoverTests.ModuleDoesMatchModuleClass, "Tests.ModuleDoesMatchModuleClass" - Tests.AltCoverTests.TypeDoesNotMatchNonTypeClass, - "Tests.TypeDoesNotMatchNonTypeClass" - Tests.AltCoverTests.TypeDoesMatchTypeClass, "Tests.TypeDoesMatchTypeClass" - Tests.AltCoverTests.MethodDoesNotMatchNonMethodClass, - "Tests.MethodDoesNotMatchNonMethodClass" - Tests.AltCoverTests.MethodDoesMatchMethodClass, "Tests.MethodDoesMatchMethodClass" - Tests.AltCoverTests.AttributeDoesNotMatchNonAttributeClass, - "Tests.AttributeDoesNotMatchNonAttributeClass" - Tests.AltCoverTests.AttributeDoesMatchAttributeClass, - "Tests.AttributeDoesMatchAttributeClass" - Tests.AltCoverTests.CanExcludeCSharpPropertiesByAttribute, - "Tests.CanExcludeCSharpPropertiesByAttribute" - Tests.AltCoverTests.Sample3Class1IsCSharpAutoproperty, - "Tests.Sample3Class1IsCSharpAutoproperty" - Tests.AltCoverTests.Sample3Class2IsNotCSharpAutoproperty, - "Tests.Sample3Class2IsNotCSharpAutoproperty" - Tests.AltCoverTests.CanIdentifyExcludedFSharpMethods, - "Tests.CanIdentifyExcludedFSharpMethods" - Tests.AltCoverTests.CanIdentifyExcludedCSharpAutoProperties, - "Tests.CanIdentifyExcludedCSharpAutoProperties" - Tests.AltCoverTests.CanIdentifyIncludedCSharpProperties, - "Tests.CanIdentifyIncludedCSharpProperties" - Tests.AltCoverTests.ValidateStaticExemption, "Tests.ValidateStaticExemption" - Tests.AltCoverTests.ValidateStaticClass, "Tests.ValidateStaticClass" - Tests.AltCoverTests.ValidateAutomaticExemption, "Tests.ValidateAutomaticExemption" - Tests.AltCoverTests.DetectLocalSource, "Tests.DetectLocalSource" - Tests.AltCoverTests.LocateMatchShouldChooseLongerWildCardPath, - "Tests.LocateMatchShouldChooseLongerWildCardPath" - Tests.AltCoverTests.LocateMatchFallsBackOK, "Tests.LocateMatchFallsBackOK" - Tests.AltCoverTests.AsyncTestInContext, "Tests.AsyncTestInContext" - Tests.AltCoverTests.AnotherAsyncTestInContext, "Tests.AnotherAsyncTestInContext" - Tests.AltCoverTests.DebugBuildTernaryTestInContext, - "Tests.DebugBuildTernaryTestInContext" - Tests.AltCoverTests.ReleaseBuildTernaryTest, "Tests.ReleaseBuildTernaryTest" - Tests.AltCoverTests.ReleaseBuildTernaryTestInContext, - "Tests.ReleaseBuildTernaryTestInContext" - Tests.AltCoverTests.ReleaseBuildTernaryTestInContextWithCoalescence, - "Tests.ReleaseBuildTernaryTestInContextWithCoalescence" - Tests.AltCoverTests.CSharpNestedMethods, "Tests.CSharpNestedMethods" - Tests.AltCoverTests.FSharpNestedMethodsClassic, "Tests.FSharpNestedMethodsClassic" - Tests.AltCoverTests.FSharpNestedMethods5x0x201, "Tests.FSharpNestedMethods_5_0_201" - Tests.AltCoverTests.ValidateSeqPntFixUp, "Tests.ValidateSeqPntFixUp" // HACK HACK HACK - Tests.AltCoverTests.EmptyArrayHasExpectedHash, "Tests.EmptyArrayHasExpectedHash" - Tests.AltCoverTests.KeyHasExpectedToken, "Tests.KeyHasExpectedToken" - Tests.AltCoverTests.TokenGeneratesExpectedULong, "Tests.TokenGeneratesExpectedULong" - Tests.AltCoverTests.KeyHasExpectedIndex, "Tests.KeyHasExpectedIndex" - Tests.AltCoverTests.EmptyArrayHasExpectedIndex, "Tests.EmptyArrayHasExpectedIndex" - Tests.AltCoverTests.KeyHasExpectedRecord, "Tests.KeyHasExpectedRecord" - Tests.AltCoverTests.KeyHasExpectedPlaceInIndex, "Tests.KeyHasExpectedPlaceInIndex" - Tests.AltCoverTests.EmptyFiltersPassAll, "Tests.EmptyFiltersPassAll" - Tests.AltCoverTests.NonEmptyFiltersCatchAnExpectedValue, - "Tests.NonEmptyFiltersCatchAnExpectedValue" - Tests.AltCoverTests.NonEmptyFiltersPassAnExpectedValue, - "Tests.NonEmptyFiltersPassAnExpectedValue" - Tests.AltCoverTests.AfterProcessingYieldsAnExpectedValue, - "Tests.AfterProcessingYieldsAnExpectedValue" - Tests.AltCoverTests.Sample3Class1PropertyIsNotSignificant, - "Tests.Sample3Class1PropertyIsNotSignificant" - Tests.AltCoverTests.Sample3Class2IPropertyIsSignificant, - "Tests.Sample3Class2IPropertyIsSignificant" - Tests.AltCoverTests.TerminalCasesGoNoDeeper, "Tests.TerminalCasesGoNoDeeper" - Tests.AltCoverTests.MethodPointsAreDeeperThanMethods, - "Tests.MethodPointsAreDeeperThanMethods" - Tests.AltCoverTests.BranchPointsAreComputedForSwitch, - "Tests.BranchPointsAreComputedForSwitch" - Tests.AltCoverTests.BranchPointsAreComputedForMatch, - "Tests.BranchPointsAreComputedForMatch" - Tests.AltCoverTests.MethodsAreDeeperThanTypes, "Tests.MethodsAreDeeperThanTypes" - Tests.AltCoverTests.TypesAreDeeperThanModules, "Tests.TypesAreDeeperThanModules" - Tests.AltCoverTests.ModulesAreDeeperThanAssemblies, - "Tests.ModulesAreDeeperThanAssemblies" - Tests.AltCoverTests.AssembliesAreDeeperThanPaths, - "Tests.AssembliesAreDeeperThanPaths" - Tests.AltCoverTests.FilteredAssembliesDoNotHaveSequencePoints, - "Tests.FilteredAssembliesDoNotHaveSequencePoints" - Tests.AltCoverTests.TestFixPointInvoke, "Tests.TestFixPointInvoke" - Tests.AltCoverTests.TestFixPointApply, "Tests.TestFixPointApply" - Tests.AltCoverTests.PathsAreDeeperThanAVisit, "Tests.PathsAreDeeperThanAVisit" - Tests.AltCoverTests.TrackingDetectsTests, "Tests.TrackingDetectsTests" - Tests.AltCoverTests.TrackingDetectsExpectedTests, - "Tests.TrackingDetectsExpectedTests" - Tests.AltCoverTests.TrackingDetectsTestsByFullType, - "Tests.TrackingDetectsTestsByFullType" - Tests.AltCoverTests.TrackingDetectsMethods, "Tests.TrackingDetectsMethods" - Tests.AltCoverTests.NamingDetectEmpties, "Tests.NamingDetectEmpties" - Tests.AltCoverTests.NamingSuffixDetectEmpties, "Tests.NamingSuffixDetectEmpties" - Tests.AltCoverTests.TypeNamesAreExtracted, "Tests.TypeNamesAreExtracted" - Tests.AltCoverTests.FullTypeNamesAreExtracted, "Tests.FullTypeNamesAreExtracted" - Tests.AltCoverTests.TypeRefNamesAreExtracted, "Tests.TypeRefNamesAreExtracted" - Tests.AltCoverTests.FullTypeRefNamesAreExtracted, - "Tests.FullTypeRefNamesAreExtracted" - Tests.AltCoverTests.MethodNamesAreExtracted, "Tests.MethodNamesAreExtracted" - Tests.AltCoverTests.FullMethodNamesAreExtracted, "Tests.FullMethodNamesAreExtracted" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNet, - "Tests.ShouldGenerateExpectedXmlReportFromDotNet" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithEmbeds, - "Tests.ShouldGenerateExpectedXmlReportFromWithEmbeds" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithPartials, - "Tests.ShouldGenerateExpectedXmlReportFromWithPartials" - Tests.AltCoverTests.ShouldGenerateExpectedJsonReportFromDotNet, - "Tests.ShouldGenerateExpectedJsonReportFromDotNet" - Tests.AltCoverTests.ShouldGenerateExpectedJsonReportWithEmbeds, - "Tests.ShouldGenerateExpectedJsonReportWithEmbeds" - Tests.AltCoverTests.ShouldGenerateExpectedJsonReportWithPartials, - "Tests.ShouldGenerateExpectedJsonReportWithPartials" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportForNCoverWithMethodPointOnly, - "Tests.ShouldGenerateExpectedXmlReportForNCoverWithMethodPointOnly" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportForNCoverWithTopLevel, - "Tests.ShouldGenerateExpectedXmlReportForNCoverWithTopLevel" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportForOpenCoverWithMethodPointOnly, - "Tests.ShouldGenerateExpectedXmlReportForOpenCoverWithMethodPointOnly" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithSourceLink, - "Tests.ShouldGenerateExpectedXmlReportWithSourceLink" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetWithPathFilter, - "Tests.ShouldGenerateExpectedXmlReportFromDotNetWithPathFilter" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetWhenExcluded, - "Tests.ShouldGenerateExpectedXmlReportFromDotNetWhenExcluded" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetWhenExcludedEvenIfTracked, - "Tests.ShouldGenerateExpectedXmlReportFromDotNetWhenExcludedEvenIfTracked" - Tests.AltCoverTests.ShouldDetectTernary, "Tests.ShouldDetectTernary" - Tests.AltCoverTests.ShouldDetectSwitchNesting, "Tests.ShouldDetectSwitchNesting" - Tests.AltCoverTests.SafeMultiplyIsSafe, "Tests.SafeMultiplyIsSafe" - Tests.AltCoverTests.EmptyMethodHasComplexity1, "Tests.EmptyMethodHasComplexity1" - Tests.AltCoverTests.BranchChainsSerialize, "Tests.BranchChainsSerialize" - Tests.AltCoverTests.BranchChainsTerminate, "Tests.BranchChainsTerminate" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithSourceLinkOpenCoverStyle, - "Tests.ShouldGenerateExpectedXmlReportWithSourceLinkOpenCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetOpenCoverStyle, - "Tests.ShouldGenerateExpectedXmlReportFromDotNetOpenCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithEmbedsOpenCoverStyle, - "Tests.ShouldGenerateExpectedXmlReportWithEmbedsOpenCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithPartialsOpenCoverStyle, - "Tests.ShouldGenerateExpectedXmlReportWithPartialsOpenCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetLineCoverStyle, - "Tests.ShouldGenerateExpectedXmlReportFromDotNetLineCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetBranchCoverStyle, - "Tests.ShouldGenerateExpectedXmlReportFromDotNetBranchCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetOpenCoverStyleWithTracking, - "Tests.ShouldGenerateExpectedXmlReportFromDotNetOpenCoverStyleWithTracking" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithModuleExclusionOpenCoverStyle, - "Tests.ShouldGenerateExpectedXmlReportWithModuleExclusionOpenCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedTrackingXmlReportWithModuleExclusionOpenCoverStyle, - "Tests.ShouldGenerateExpectedTrackingXmlReportWithModuleExclusionOpenCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithClassExclusionOpenCoverStyle, - "Tests.ShouldGenerateExpectedXmlReportWithClassExclusionOpenCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedTrackingXmlReportWithClassExclusionOpenCoverStyle, - "Tests.ShouldGenerateExpectedTrackingXmlReportWithClassExclusionOpenCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithMethodExclusionOpenCoverStyle, - "Tests.ShouldGenerateExpectedXmlReportWithMethodExclusionOpenCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithFileExclusionOpenCoverStyle, - "Tests.ShouldGenerateExpectedXmlReportWithFileExclusionOpenCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedTrackingXmlReportWithMethodExclusionOpenCoverStyle, - "Tests.ShouldGenerateExpectedTrackingXmlReportWithMethodExclusionOpenCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithTraditionalInterfacesOpenCoverStyle, - "Tests.ShouldGenerateExpectedXmlReportWithTraditionalInterfacesOpenCoverStyle" - Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithModernInterfacesOpenCoverStyle, - "Tests.ShouldGenerateExpectedXmlReportWithModernInterfacesOpenCoverStyle" - Tests.AltCoverTests.ShouldSortFileIds, "Tests.ShouldSortFileIds" - Tests.AltCoverTests.ZeroIsNotVisited, "Tests.ZeroIsNotVisited" - Tests.AltCoverTests.PositiveIsVisited, "Tests.PositiveIsVisited" - Tests.AltCoverTests.NegativesSpray, "Tests.NegativesSpray" - Tests.AltCoverTests2.ShouldBeAbleToGetTheVisitReportMethod, - "Tests2.ShouldBeAbleToGetTheVisitReportMethod" - Tests.AltCoverTests2.ShouldBeAbleToClearTheStrongNameKey, - "Tests2.ShouldBeAbleToClearTheStrongNameKey" - Tests.AltCoverTests2.ShouldBeAbleToUpdateTheStrongNameKeyWherePossible, - "Tests2.ShouldBeAbleToUpdateTheStrongNameKeyWherePossible" - Tests.AltCoverTests2.NoKnownKeyInEmptyIndex, "Tests2.NoKnownKeyInEmptyIndex" - Tests.AltCoverTests2.KnownKeyMatchedInIndex, "Tests2.KnownKeyMatchedInIndex" - Tests.AltCoverTests2.ThirdPartyKeyNotMatchedInIndex, - "Tests2.ThirdPartyKeyNotMatchedInIndex" - Tests.AltCoverTests2.FakedUpKeyIsMatchedInIndex, "Tests2.FakedUpKeyIsMatchedInIndex" - Tests.AltCoverTests2.NoKnownKeyIfAssemblyHasNone, - "Tests2.NoKnownKeyIfAssemblyHasNone" - Tests.AltCoverTests2.NoKnownTokenInEmptyIndex, "Tests2.NoKnownTokenInEmptyIndex" - Tests.AltCoverTests2.KnownTokenMatchedInIndex, "Tests2.KnownTokenMatchedInIndex" - Tests.AltCoverTests2.NoKnownTokenIfAssemblyHasNone, - "Tests2.NoKnownTokenIfAssemblyHasNone" - Tests.AltCoverTests2.ForeignTokenIsNotMatchedInIndex, - "Tests2.ForeignTokenIsNotMatchedInIndex" - Tests.AltCoverTests2.FakedUpTokenIsMatchedInIndex, - "Tests2.FakedUpTokenIsMatchedInIndex" - Tests.AltCoverTests2.MonoCombinationCanBeExercisedOnNetCore, - "Tests2.MonoCombinationCanBeExercisedOnNetCore" - Tests.AltCoverTests2.GuardShouldDisposeRecordingAssemblyOnException, - "Tests2.GuardShouldDisposeRecordingAssemblyOnException" - Tests.AltCoverTests2.ShouldBeAbleToTellAnAssembly, - "Tests2.ShouldBeAbleToTellAnAssembly" - Tests.AltCoverTests2.ShouldBeAbleToValidateAnAssembly, - "Tests2.ShouldBeAbleToValidateAnAssembly" - Tests.AltCoverTests2.ShouldBeAbleToLocateAReference, - "Tests2.ShouldBeAbleToLocateAReference" - Tests.AltCoverTests2.ShouldBeAbleToPrepareTheAssembly, - "Tests2.ShouldBeAbleToPrepareTheAssembly" - Tests.AltCoverTests2.ShouldGetTrackingStyleIfSet, - "Tests2.ShouldGetTrackingStyleIfSet" - Tests.AltCoverTests2.ShouldSymbolWriterAsExpected, - "Tests2.ShouldSymbolWriterAsExpected" - Tests.AltCoverTests2.ShouldGetNewFilePathFromPreparedAssembly, - "Tests2.ShouldGetNewFilePathFromPreparedAssembly" - Tests.AltCoverTests2.ShouldWriteMonoAssemblyOK, "Tests2.ShouldWriteMonoAssemblyOK" - Tests.AltCoverTests2.ShouldGetVisitFromWrittenAssembly, - "Tests2.ShouldGetVisitFromWrittenAssembly" - //Tests.AltCoverTests2.ShouldUpdateHandlerOK([] selection) - Tests.AltCoverTests2.ShouldSubstituteInstructionOperand, - "Tests2.ShouldSubstituteInstructionOperand" - Tests.AltCoverTests2.ShouldNotSubstituteDifferentInstructionOperand, - "Tests2.ShouldNotSubstituteDifferentInstructionOperand" - Tests.AltCoverTests2.ShouldSubstituteIntoInstructionOperandArray, - "Tests2.ShouldSubstituteIntoInstructionOperandArray" - Tests.AltCoverTests2.ShouldNotSubstituteOutsideInstructionOperandArray, - "Tests2.ShouldNotSubstituteOutsideInstructionOperandArray" - Tests.AltCoverTests2.ShouldNotSubstituteOtherOperand, - "Tests2.ShouldNotSubstituteOtherOperand" - Tests.AltCoverTests2.ShouldBeAbleToTrackAMethod, "Tests2.ShouldBeAbleToTrackAMethod" - Tests.AltCoverTests2.ShouldBeAbleToTrackAMethodWithTailCalls, - "Tests2.ShouldBeAbleToTrackAMethodWithTailCalls" - Tests.AltCoverTests2.ShouldBeAbleToTrackAMethodWithNonVoidReturn, - "Tests2.ShouldBeAbleToTrackAMethodWithNonVoidReturn" - Tests.AltCoverTests2.ShouldBeAbleToTrackAnAsyncMethod, - "Tests2.ShouldBeAbleToTrackAnAsyncMethod" - Tests.AltCoverTests2.ShouldBeAbleToTrackAnFSAsyncMethod, - "Tests2.ShouldBeAbleToTrackAnFSAsyncMethod" - Tests.AltCoverTests2.ShouldBeAbleToInstrumentASwitchForNCover, - "Tests2.ShouldBeAbleToInstrumentASwitchForNCover" - Tests.AltCoverTests2.ShouldNotChangeAnUntrackedMethod, - "Tests2.ShouldNotChangeAnUntrackedMethod" - Tests.AltCoverTests2.SwitchBranchesShouldInstrumentByPushingDown, - "Tests2.SwitchBranchesShouldInstrumentByPushingDown" - Tests.AltCoverTests2.PseudoSwitchVisibleBranchesShouldSkipNonRepresentativeCases, - "Tests2.PseudoSwitchVisibleBranchesShouldSkipNonRepresentativeCases" - Tests.AltCoverTests2.SimpleBranchShouldInstrumentByPushingDown, - "Tests2.SimpleBranchShouldInstrumentByPushingDown" - Tests.AltCoverTests2.StartShouldLoadRecordingAssembly, - "Tests2.StartShouldLoadRecordingAssembly" - Tests.AltCoverTests2.TypeShouldNotChangeState, "Tests2.TypeShouldNotChangeState" - Tests.AltCoverTests2.ExcludedMethodShouldNotChangeState, - "Tests2.ExcludedMethodShouldNotChangeState" - Tests.AltCoverTests2.IncludedMethodShouldChangeState, - "Tests2.IncludedMethodShouldChangeState" - Tests.AltCoverTests2.ExcludedAfterMethodShouldNotChangeState, - "Tests2.ExcludedAfterMethodShouldNotChangeState" - Tests.AltCoverTests2.IncludedAfterMethodShouldRewriteMethod, - "Tests2.IncludedAfterMethodShouldRewriteMethod" - Tests.AltCoverTests2.UpdateStrongReferencesShouldChangeSigningKeyWherePossible, - "Tests2.UpdateStrongReferencesShouldChangeSigningKeyWherePossible" - Tests.AltCoverTests2.UpdateStrongReferencesShouldChangeSigningKeyWherePossible2, - "Tests2.UpdateStrongReferencesShouldChangeSigningKeyWherePossible2" - Tests.AltCoverTests2.UpdateStrongReferencesShouldRemoveSigningKeyIfRequired, - "Tests2.UpdateStrongReferencesShouldRemoveSigningKeyIfRequired" - Tests.AltCoverTests2.UpdateStrongReferencesShouldNotAddASigningKey, - "Tests2.UpdateStrongReferencesShouldNotAddASigningKey" - Tests.AltCoverTests2.UpdateStrongReferencesShouldTrackReferences, - "Tests2.UpdateStrongReferencesShouldTrackReferences" - Tests.AltCoverTests2.UpdateStrongReferencesShouldTrackReferencesEvenFakes, - "Tests2.UpdateStrongReferencesShouldTrackReferencesEvenFakes" - Tests.AltCoverTests2.ExcludedAssemblyRefsAreNotUpdated, - "Tests2.ExcludedAssemblyRefsAreNotUpdated" - Tests.AltCoverTests2.IncludedAssemblyRefsAreUpdated, - "Tests2.IncludedAssemblyRefsAreUpdated" - Tests.AltCoverTests2.ExcludedModuleJustRecordsMVid, - "Tests2.ExcludedModuleJustRecordsMVid" - Tests.AltCoverTests2.ExcludedModuleJustRecordsNameForJson, - "Tests2.ExcludedModuleJustRecordsNameForJson" - Tests.AltCoverTests2.ExcludedModuleJustRecordsHashForOpenCover, - "Tests2.ExcludedModuleJustRecordsHashForOpenCover" - Tests.AltCoverTests2.IncludedModuleEnsuresRecorder, - "Tests2.IncludedModuleEnsuresRecorder" - Tests.AltCoverTests2.ExcludedMethodPointIsPassThrough, - "Tests2.ExcludedMethodPointIsPassThrough" - Tests.AltCoverTests2.IncludedMethodPointInsertsVisit, - "Tests2.IncludedMethodPointInsertsVisit" - Tests.AltCoverTests2.IncludedModuleDoesNotChangeRecorderJustTheReference, - "Tests2.IncludedModuleDoesNotChangeRecorderJustTheReference" - Tests.AltCoverTests2.AfterModuleShouldNotChangeState, - "Tests2.AfterModuleShouldNotChangeState" - Tests.AltCoverTests2.JSONInjectionTransformsSimpleFileAsExpected, - "Tests2.JSONInjectionTransformsSimpleFileAsExpected" - Tests.AltCoverTests2.JSONInjectionTransformsStandaloneFileAsExpected, - "Tests2.JSONInjectionTransformsStandaloneFileAsExpected" - Tests.AltCoverTests2.JSONInjectionTransformsDependencyFileAsExpected, - "Tests2.JSONInjectionTransformsDependencyFileAsExpected" - Tests.AltCoverTests2.JSONInjectionIsIdempotent, "Tests2.JSONInjectionIsIdempotent" - Tests.AltCoverTests2.NonFinishShouldDisposeRecordingAssembly, - "Tests2.NonFinishShouldDisposeRecordingAssembly" - Tests.AltCoverTests2.NonFinishShouldDisposeThreadingAssembly, - "Tests2.NonFinishShouldDisposeThreadingAssembly" - Tests.AltCoverTests2.NonFinishShouldNotDisposeNullRecordingAssembly, - "Tests2.NonFinishShouldNotDisposeNullRecordingAssembly" - Tests.AltCoverTests2.FinishShouldLeaveRecordingAssembly, - "Tests2.FinishShouldLeaveRecordingAssembly" - Tests.AltCoverTests2.StrongNameKeyCanBeValidated, - "Tests2.StrongNameKeyCanBeValidated" - Tests.AltCoverTests2.VerbosityShouldBeHonoured, "Tests2.VerbosityShouldBeHonoured" - Tests.AltCoverTests2.CryptographicExceptionIsTransformed, - "Tests2.CryptographicExceptionIsTransformed" - Tests.AltCoverTests2.OutputCanBeExercised, "Tests2.OutputCanBeExercised" - Tests.AltCoverTests2.NoThrowNoErrorLeavesAllOK, "Tests2.NoThrowNoErrorLeavesAllOK" - Tests.AltCoverTests2.NoThrowWithErrorIsSignalled, - "Tests2.NoThrowWithErrorIsSignalled" - Tests.AltCoverTests2.ArgumentExceptionWrites, "Tests2.ArgumentExceptionWrites" - Tests.AltCoverTests2.ArgumentExceptionWritesEx, "Tests2.ArgumentExceptionWritesEx" - Tests.AltCoverTests2.IOExceptionWrites, "Tests2.IOExceptionWrites" - Tests.AltCoverTests2.NotSupportedExceptionWrites, - "Tests2.NotSupportedExceptionWrites" - Tests.AltCoverTests2.SecurityExceptionWrites, "Tests2.SecurityExceptionWrites" - Tests.AltCoverTests2.UnauthorizedAccessExceptionWrites, - "Tests2.UnauthorizedAccessExceptionWrites" - Tests.AltCoverTests3.ShouldLaunchWithExpectedOutput, - "Tests3.ShouldLaunchWithExpectedOutput" - Tests.AltCoverTests3.ShouldHaveExpectedOptions, "Tests3.ShouldHaveExpectedOptions" - Tests.AltCoverTests3.ParsingJunkIsAnError, "Tests3.ParsingJunkIsAnError" - Tests.AltCoverTests3.ParsingJunkBeforeSeparatorIsAnError, - "Tests3.ParsingJunkBeforeSeparatorIsAnError" - Tests.AltCoverTests3.ParsingJunkAfterSeparatorIsExpected, - "Tests3.ParsingJunkAfterSeparatorIsExpected" - Tests.AltCoverTests3.ParsingHelpGivesHelp, "Tests3.ParsingHelpGivesHelp" - Tests.AltCoverTests3.ParsingErrorHelpGivesHelp, "Tests3.ParsingErrorHelpGivesHelp" - Tests.AltCoverTests3.ParsingAttributesGivesAttributes, - "Tests3.ParsingAttributesGivesAttributes" - Tests.AltCoverTests3.ParsingTopLevelGivesTopLevel, - "Tests3.ParsingTopLevelGivesTopLevel" - Tests.AltCoverTests3.ParsingMethodsGivesMethods, "Tests3.ParsingMethodsGivesMethods" - Tests.AltCoverTests3.ParsingTypesGivesTypes, "Tests3.ParsingTypesGivesTypes" - Tests.AltCoverTests3.ParsingAssembliesGivesAssemblies, - "Tests3.ParsingAssembliesGivesAssemblies" - Tests.AltCoverTests3.ParsingEscapeCasesWork, "Tests3.ParsingEscapeCasesWork" - Tests.AltCoverTests3.ParsingModulesGivesModules, "Tests3.ParsingModulesGivesModules" - Tests.AltCoverTests3.ParsingFilesGivesFiles, "Tests3.ParsingFilesGivesFiles" - Tests.AltCoverTests3.ParsingPathsGivesPaths, "Tests3.ParsingPathsGivesPaths" - Tests.AltCoverTests3.ParsingReportGivesReport, "Tests3.ParsingReportGivesReport" - Tests.AltCoverTests3.ParsingMultipleReportGivesFailure, - "Tests3.ParsingMultipleReportGivesFailure" - Tests.AltCoverTests3.ParsingBadReportGivesFailure, - "Tests3.ParsingBadReportGivesFailure" - Tests.AltCoverTests3.ParsingNoReportGivesFailure, - "Tests3.ParsingNoReportGivesFailure" - Tests.AltCoverTests3.ParsingEmptyReportGivesFailure, - "Tests3.ParsingEmptyReportGivesFailure" - Tests.AltCoverTests3.ParsingInputGivesInput, "Tests3.ParsingInputGivesInput" - Tests.AltCoverTests3.ParsingMultipleInputIsOKToo, - "Tests3.ParsingMultipleInputIsOKToo" - Tests.AltCoverTests3.ParsingDuplicateInputGivesFailure, - "Tests3.ParsingDuplicateInputGivesFailure" - Tests.AltCoverTests3.ParsingBadInputGivesFailure, - "Tests3.ParsingBadInputGivesFailure" - Tests.AltCoverTests3.ParsingNoInputGivesFailure, "Tests3.ParsingNoInputGivesFailure" - Tests.AltCoverTests3.ParsingOutputGivesOutput, "Tests3.ParsingOutputGivesOutput" - Tests.AltCoverTests3.ParsingDuplicateOutputGivesFailure, - "Tests3.ParsingDuplicateOutputGivesFailure" - Tests.AltCoverTests3.ParsingMultipleOutputIsOK, "Tests3.ParsingMultipleOutputIsOK" - Tests.AltCoverTests3.ParsingBadOutputGivesFailure, - "Tests3.ParsingBadOutputGivesFailure" - Tests.AltCoverTests3.ParsingNoOutputGivesFailure, - "Tests3.ParsingNoOutputGivesFailure" - Tests.AltCoverTests3.ParsingEmptyOutputGivesFailure, - "Tests3.ParsingEmptyOutputGivesFailure" - Tests.AltCoverTests3.ParsingSymbolGivesSymbol, "Tests3.ParsingSymbolGivesSymbol" - Tests.AltCoverTests3.ParsingMultipleSymbolGivesOK, - "Tests3.ParsingMultipleSymbolGivesOK" - Tests.AltCoverTests3.ParsingBadSymbolGivesFailure, - "Tests3.ParsingBadSymbolGivesFailure" - Tests.AltCoverTests3.ParsingNoSymbolGivesFailure, - "Tests3.ParsingNoSymbolGivesFailure" - Tests.AltCoverTests3.ParsingMultipleDependencyIsOk, - "Tests3.ParsingMultipleDependencyIsOk" - Tests.AltCoverTests3.ParsingBadDependencyGivesFailure, - "Tests3.ParsingBadDependencyGivesFailure" - Tests.AltCoverTests3.ParsingNonDependencyGivesFailure, - "Tests3.ParsingNonDependencyGivesFailure" - Tests.AltCoverTests3.ParsingStrongNameGivesStrongName, - "Tests3.ParsingStrongNameGivesStrongName" - Tests.AltCoverTests3.ParsingMultipleStrongNameGivesFailure, - "Tests3.ParsingMultipleStrongNameGivesFailure" - Tests.AltCoverTests3.ParsingBadStrongNameGivesFailure, - "Tests3.ParsingBadStrongNameGivesFailure" - Tests.AltCoverTests3.ParsingNonStrongNameGivesFailure, - "Tests3.ParsingNonStrongNameGivesFailure" - Tests.AltCoverTests3.ParsingNoStrongNameGivesFailure, - "Tests3.ParsingNoStrongNameGivesFailure" - Tests.AltCoverTests3.ParsingMultipleAltStrongNameIsOk, - "Tests3.ParsingMultipleAltStrongNameIsOk" - Tests.AltCoverTests3.ParsingNoAltStrongNameGivesFailure, - "Tests3.ParsingNoAltStrongNameGivesFailure" - Tests.AltCoverTests3.ParsingBadAltStrongNameGivesFailure, - "Tests3.ParsingBadAltStrongNameGivesFailure" - Tests.AltCoverTests3.ParsingNonAltsStrongNameGivesFailure, - "Tests3.ParsingNonAltsStrongNameGivesFailure" - Tests.AltCoverTests3.ParsingLocalGivesLocal, "Tests3.ParsingLocalGivesLocal" - Tests.AltCoverTests3.ParsingMultipleLocalGivesFailure, - "Tests3.ParsingMultipleLocalGivesFailure" - Tests.AltCoverTests3.ParsingVisibleGivesVisible, "Tests3.ParsingVisibleGivesVisible" - Tests.AltCoverTests3.ParsingMultipleVisibleGivesFailure, - "Tests3.ParsingMultipleVisibleGivesFailure" - Tests.AltCoverTests3.ParsingTimeGivesTime, "Tests3.ParsingTimeGivesTime" - Tests.AltCoverTests3.ParsingOnlyArabicNumeralsNotThatSortofArabicNumeralsGivesTime, - "Tests3.ParsingOnlyArabicNumeralsNotThatSortofArabicNumeralsGivesTime" - Tests.AltCoverTests3.ParsingMultipleTimesGivesFailure, - "Tests3.ParsingMultipleTimesGivesFailure" - Tests.AltCoverTests3.ParsingTimeAndNamesGivesOK, "Tests3.ParsingTimeAndNamesGivesOK" - Tests.AltCoverTests3.ParsingBadTimeGivesNoOp, "Tests3.ParsingBadTimeGivesNoOp" - Tests.AltCoverTests3.ParsingNonTimeGivesFailure, "Tests3.ParsingNonTimeGivesFailure" - Tests.AltCoverTests3.ParsingNoTimeGivesFailure, "Tests3.ParsingNoTimeGivesFailure" - Tests.AltCoverTests3.ParsingJsonFormatGivesJson, "Tests3.ParsingJsonFormatGivesJson" - Tests.AltCoverTests3.ParsingNCoverFormatGivesNCover, - "Tests3.ParsingNCoverFormatGivesNCover" - Tests.AltCoverTests3.ParsingOpenCoverFormatGivesOpenCover, - "Tests3.ParsingOpenCoverFormatGivesOpenCover" - Tests.AltCoverTests3.ParsingMultipleReportFormatGivesFailure, - "Tests3.ParsingMultipleReportFormatGivesFailure" - Tests.AltCoverTests3.ParsingInPlaceGivesInPlace, "Tests3.ParsingInPlaceGivesInPlace" - Tests.AltCoverTests3.ParsingMultipleInPlaceGivesFailure, - "Tests3.ParsingMultipleInPlaceGivesFailure" - Tests.AltCoverTests3.ParsingSaveGivesSave, "Tests3.ParsingSaveGivesSave" - Tests.AltCoverTests3.ParsingMultipleSaveGivesFailure, - "Tests3.ParsingMultipleSaveGivesFailure" - Tests.AltCoverTests3.ParsingSingleGivesSingle, "Tests3.ParsingSingleGivesSingle" - Tests.AltCoverTests3.ParsingMultipleSingleGivesFailure, - "Tests3.ParsingMultipleSingleGivesFailure" - Tests.AltCoverTests3.ParsingLineCoverGivesLineCover, - "Tests3.ParsingLineCoverGivesLineCover" - Tests.AltCoverTests3.OpenCoverIsCompatibleWithLineCover, - "Tests3.OpenCoverIsCompatibleWithLineCover" - Tests.AltCoverTests3.LineCoverIsCompatibleWithOpenCover, - "Tests3.LineCoverIsCompatibleWithOpenCover" - Tests.AltCoverTests3.ParsingMultipleLineCoverGivesFailure, - "Tests3.ParsingMultipleLineCoverGivesFailure" - Tests.AltCoverTests3.LineCoverIsNotCompatibleWithBranchCover, - "Tests3.LineCoverIsNotCompatibleWithBranchCover" - Tests.AltCoverTests3.ParsingBranchCoverGivesBranchCover, - "Tests3.ParsingBranchCoverGivesBranchCover" - Tests.AltCoverTests3.OpenCoverIsCompatibleWithBranchCover, - "Tests3.OpenCoverIsCompatibleWithBranchCover" - Tests.AltCoverTests3.BranchCoverIsCompatibleWithOpenCover, - "Tests3.BranchCoverIsCompatibleWithOpenCover" - Tests.AltCoverTests3.ParsingMultipleBranchCoverGivesFailure, - "Tests3.ParsingMultipleBranchCoverGivesFailure" - Tests.AltCoverTests3.BranchCoverIsNotCompatibleWithLineCover, - "Tests3.BranchCoverIsNotCompatibleWithLineCover" - Tests.AltCoverTests3.ParsingDropGivesDrop, "Tests3.ParsingDropGivesDrop" - Tests.AltCoverTests3.ParsingMultipleDropGivesFailure, - "Tests3.ParsingMultipleDropGivesFailure" - Tests.AltCoverTests3.ParsingDeferWorks, "Tests3.ParsingDeferWorks" - Tests.AltCoverTests3.ParsingMultipleDeferGivesFailure, - "Tests3.ParsingMultipleDeferGivesFailure" - Tests.AltCoverTests3.ParsingStaticGivesStatic, "Tests3.ParsingStaticGivesStatic" - Tests.AltCoverTests3.ParsingStaticPlusGivesStatic, - "Tests3.ParsingStaticPlusGivesStatic" - Tests.AltCoverTests3.ParsingStaticPlusPlusGivesStaticPlus, - "Tests3.ParsingStaticPlusPlusGivesStaticPlus" - Tests.AltCoverTests3.ParsingStaticMinusGivesNoStatic, - "Tests3.ParsingStaticMinusGivesNoStatic" - Tests.AltCoverTests3.ParsingMultipleStaticGivesFailure, - "Tests3.ParsingMultipleStaticGivesFailure" - Tests.AltCoverTests3.ParsingJunkStaticGivesFailure, - "Tests3.ParsingJunkStaticGivesFailure" - Tests.AltCoverTests3.ParsingQuietWorks, "Tests3.ParsingQuietWorks" - Tests.AltCoverTests3.ParsingMultiQuietWorks, "Tests3.ParsingMultiQuietWorks" - Tests.AltCoverTests3.ParsingBatchMultiQuietWorks, - "Tests3.ParsingBatchMultiQuietWorks" - Tests.AltCoverTests3.OutputLeftPassesThrough, "Tests3.OutputLeftPassesThrough" - Tests.AltCoverTests3.OutputInPlaceFails, "Tests3.OutputInPlaceFails" - Tests.AltCoverTests3.OutputToNewPlaceIsOK, "Tests3.OutputToNewPlaceIsOK" - Tests.AltCoverTests3.OutputToReallyNewPlaceIsOK, "Tests3.OutputToReallyNewPlaceIsOK" - Tests.AltCoverTests3.InPlaceToExistingPlaceFails, - "Tests3.InPlaceToExistingPlaceFails" - Tests.AltCoverTests3.InPlaceOperationIsAsExpected, - "Tests3.InPlaceOperationIsAsExpected" - Tests.AltCoverTests3.ImageLoadResilientPassesThrough, - "Tests3.ImageLoadResilientPassesThrough" - Tests.AltCoverTests3.ResilientHandlesIOException, - "Tests3.ResilientHandlesIOException" - Tests.AltCoverTests3.ResilientHandlesBadImageFormatException, - "Tests3.ResilientHandlesBadImageFormatException" - Tests.AltCoverTests3.ResilientHandlesArgumentException, - "Tests3.ResilientHandlesArgumentException" - Tests.AltCoverTests3.FolderNestingIsDetectedCorrectly, - "Tests3.FolderNestingIsDetectedCorrectly" - Tests.AltCoverTests3.PreparingNewPlaceShouldCopyEverything, - "Tests3.PreparingNewPlaceShouldCopyEverything" - Tests.AltCoverTests3.ShouldProcessTrailingArguments, - "Tests3.ShouldProcessTrailingArguments" - Tests.AltCoverTests3.StoresAsExpected, "Tests3.StoresAsExpected" - Tests.AltCoverTests3.ImportModuleIsAsExpected, "Tests3.ImportModuleIsAsExpected" - Tests.AltCoverTests3.VersionIsAsExpected, "Tests3.VersionIsAsExpected" - Tests.AltCoverTests3.TargetsPathIsAsExpected, "Tests3.TargetsPathIsAsExpected" - Tests.AltCoverTests3.UsageIsAsExpected, "Tests3.UsageIsAsExpected" - Tests.AltCoverTests3.ErrorResponseIsAsExpected, "Tests3.ErrorResponseIsAsExpected" - Tests.AltCoverTests3.LoggingCanBeExercised, "Tests3.LoggingCanBeExercised" - Tests.AltCoverTests3.EmptyInstrumentIsJustTheDefaults, - "Tests3.EmptyInstrumentIsJustTheDefaults" - Tests.AltCoverTests3.InstrumentLevelsCanBeSet, "Tests3.InstrumentLevelsCanBeSet" - Tests.AltCoverTests3.NonDefaultInstrumentObsoleteIsOK, - "Tests3.NonDefaultInstrumentObsoleteIsOK" - Tests.AltCoverTests3.NonDefaultInstrumentIsOK, "Tests3.NonDefaultInstrumentIsOK" - Tests.AltCoverTests3.EmptyCollectIsJustTheDefaults, - "Tests3.EmptyCollectIsJustTheDefaults" - Tests.AltCoverTests3.CollectLevelsCanBeSet, "Tests3.CollectLevelsCanBeSet" - Tests.AltCoverTests3.CollectWithExeIsNotCollecting, - "Tests3.CollectWithExeIsNotCollecting" - Tests.AltCoverTests3.EmptyPowerShellIsJustTheDefaults, - "Tests3.EmptyPowerShellIsJustTheDefaults" - Tests.AltCoverTests3.EmptyVersionIsJustTheDefaults, - "Tests3.EmptyVersionIsJustTheDefaults" - Tests.AltCoverTests3.EchoWorks, "Tests3.EchoWorks" - Tests.AltCoverTests3.EchoFallsSilent, "Tests3.EchoFallsSilent" - Tests.AltCoverTests3.RunSettingsFailsIfCollectorNotFound, - "Tests3.RunSettingsFailsIfCollectorNotFound" - Tests.AltCoverTests3.RunSettingsWorksIfOK, "Tests3.RunSettingsWorksIfOK" - Tests.AltCoverTests3.RunSettingsExtendsOK, "Tests3.RunSettingsExtendsOK" - Tests.AltCoverTests3.RunSettingsRecoversOK, "Tests3.RunSettingsRecoversOK" - Tests.AltCoverTests3.RunSettingsThrowsIfUninitialized, - "Tests3.RunSettingsThrowsIfUninitialized" - Tests.AltCoverTests3.ContingentCopyTest, "Tests3.ContingentCopyTest" - Tests.AltCoverTests3.RetryDeleteTest, "Tests3.RetryDeleteTest" - Tests.AltCoverXTests.CollectOptionsCanBeValidated, - "XTests.CollectOptionsCanBeValidated" - Tests.AltCoverXTests.TypeSafeEmptyThresholdCanBeValidated, - "XTests.TypeSafeEmptyThresholdCanBeValidated" - Tests.AltCoverXTests.TypeSafeCollectOptionsCanBeValidated, - "XTests.TypeSafeCollectOptionsCanBeValidated" - Tests.AltCoverXTests.TypeSafeCollectSummaryCanBeValidated, - "XTests.TypeSafeCollectSummaryCanBeValidated" - Tests.AltCoverXTests.CollectOptionsCanBeValidatedWithErrors, - "XTests.CollectOptionsCanBeValidatedWithErrors" - Tests.AltCoverXTests.TypeSafeCollectOptionsCanBeValidatedWithErrors, - "XTests.TypeSafeCollectOptionsCanBeValidatedWithErrors" - Tests.AltCoverXTests.CollectOptionsCanBePositivelyValidatedWithErrors, - "XTests.CollectOptionsCanBePositivelyValidatedWithErrors" - Tests.AltCoverXTests.TypeSafeCollectOptionsCanBePositivelyValidatedWithErrors, - "XTests.TypeSafeCollectOptionsCanBePositivelyValidatedWithErrors" - Tests.AltCoverXTests.PrepareOptionsCanBeValidated, - "XTests.PrepareOptionsCanBeValidated" - Tests.AltCoverXTests.TypeSafePrepareOptionsCanBeValidated, - "XTests.TypeSafePrepareOptionsCanBeValidated" - Tests.AltCoverXTests.TypeSafePrepareOptionsCanBeValidatedAgain, - "XTests.TypeSafePrepareOptionsCanBeValidatedAgain" - Tests.AltCoverXTests.PrepareOptionsStrongNamesCanBeValidated, - "XTests.PrepareOptionsStrongNamesCanBeValidated" - Tests.AltCoverXTests.TypeSafePrepareOptionsStrongNamesCanBeValidated, - "XTests.TypeSafePrepareOptionsStrongNamesCanBeValidated" - Tests.AltCoverXTests.PrepareOptionsCanBeValidatedWithNulls, - "XTests.PrepareOptionsCanBeValidatedWithNulls" - Tests.AltCoverXTests.PrepareOptionsCanBeValidatedAndDetectInconsistency, - "XTests.PrepareOptionsCanBeValidatedAndDetectInconsistency" - Tests.AltCoverXTests.TypeSafePrepareStaticCanBeValidated, - "XTests.TypeSafePrepareStaticCanBeValidated" - Tests.AltCoverXTests.TypeSafePrepareOptionsCanBeValidatedAndDetectInconsistency, - "XTests.TypeSafePrepareOptionsCanBeValidatedAndDetectInconsistency" - Tests.AltCoverXTests.PrepareOptionsCanBeValidatedWithErrors, - "XTests.PrepareOptionsCanBeValidatedWithErrors" - Tests.AltCoverXTests.NullListsAreEmpty, "XTests.NullListsAreEmpty" - Tests.AltCoverXTests.ValidateAssemblyOption, "XTests.ValidateAssemblyOption" - Tests.AltCoverXTests.ADotNetDryRunLooksAsExpected, - "XTests.ADotNetDryRunLooksAsExpected" - Tests.AltCoverXTests.ADryRunLooksAsExpected, "XTests.ADryRunLooksAsExpected" - Tests.AltCoverXTests.AfterAssemblyCommitsThatAssembly, - "XTests.AfterAssemblyCommitsThatAssembly" - Tests.AltCoverXTests.AfterAssemblyCommitsThatAssemblyForMono, - "XTests.AfterAssemblyCommitsThatAssemblyForMono" - Tests.AltCoverXTests.FinishCommitsTheRecordingAssembly, - "XTests.FinishCommitsTheRecordingAssembly" - Tests.AltCoverXTests.FinishCommitsTheAsyncRecordingAssembly, - "XTests.FinishCommitsTheAsyncRecordingAssembly" - Tests.AltCoverXTests.ShouldDoCoverage, "XTests.ShouldDoCoverage" - Tests.AltCoverXTests.ShouldGenerateExpectedXmlReportFromMono, - "XTests.ShouldGenerateExpectedXmlReportFromMono" - Tests.AltCoverXTests.ShouldGenerateExpectedXmlReportFromMonoOpenCoverStyle, - "XTests.ShouldGenerateExpectedXmlReportFromMonoOpenCoverStyle" |] |> Array.toList + Tests.TestCommonTests.TestIgnoredTests, "TestCommonTests.TestIgnoredTests" + Tests.TestCommonTests.ExerciseItAll, "TestCommonTests.ExerciseItAll" + Tests.TestCommonTests.SelfTest, "TestCommonTests.SelfTest" + Tests.AltCoverRunnerTests.ShouldFailXmlDataForNativeJson, + "Runner.ShouldFailXmlDataForNativeJson" + Tests.AltCoverRunnerTests.MaxTimeFirst, "Runner.MaxTimeFirst" + Tests.AltCoverRunnerTests.MaxTimeLast, "Runner.MaxTimeLast" + Tests.AltCoverRunnerTests.MinTimeFirst, "Runner.MinTimeFirst" + Tests.AltCoverRunnerTests.MinTimeLast, "Runner.MinTimeLast" + Tests.AltCoverRunnerTests.JunkUspidGivesNegativeIndex, + "Runner.JunkUspidGivesNegativeIndex" + Tests.AltCoverRunnerTests.RealIdShouldIncrementCount, + "Runner.RealIdShouldIncrementCount" + Tests.AltCoverRunnerTests.RealIdShouldIncrementList, + "Runner.RealIdShouldIncrementList" + Tests.AltCoverRunnerTests.DistinctIdShouldBeDistinct, + "Runner.DistinctIdShouldBeDistinct" + Tests.AltCoverRunnerTests.DistinctLineShouldBeDistinct, + "Runner.DistinctLineShouldBeDistinct" + Tests.AltCoverRunnerTests.RepeatVisitsShouldIncrementCount, + "Runner.RepeatVisitsShouldIncrementCount" + Tests.AltCoverRunnerTests.RepeatVisitsShouldIncrementTotal, + "Runner.RepeatVisitsShouldIncrementTotal" + Tests.AltCoverRunnerTests.KnownModuleWithPayloadMakesExpectedChangeInOpenCover, + "Runner.KnownModuleWithPayloadMakesExpectedChangeInOpenCover" + Tests.AltCoverRunnerTests.FlushLeavesExpectedTraces, + "Runner.FlushLeavesExpectedTraces" + Tests.AltCoverRunnerTests.FlushLeavesExpectedTracesWhenDiverted, + "Runner.FlushLeavesExpectedTracesWhenDiverted" + Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleJson, + "Runner.NCoverShouldGeneratePlausibleJson" + Tests.AltCoverRunnerTests.OpenCoverShouldGeneratePlausibleJson, + "Runner.OpenCoverShouldGeneratePlausibleJson" + Tests.AltCoverRunnerTests.UsageIsAsExpected, "Runner.UsageIsAsExpected" + Tests.AltCoverRunnerTests.ShouldLaunchWithExpectedOutput, + "Runner.ShouldLaunchWithExpectedOutput" + Tests.AltCoverRunnerTests.ShouldHaveExpectedOptions, + "Runner.ShouldHaveExpectedOptions" + Tests.AltCoverRunnerTests.ParsingJunkIsAnError, "Runner.ParsingJunkIsAnError" + Tests.AltCoverRunnerTests.ParsingJunkAfterSeparatorIsExpected, + "Runner.ParsingJunkAfterSeparatorIsExpected" + Tests.AltCoverRunnerTests.ParsingHelpGivesHelp, "Runner.ParsingHelpGivesHelp" + Tests.AltCoverRunnerTests.ParsingErrorHelpGivesHelp, + "Runner.ParsingErrorHelpGivesHelp" + Tests.AltCoverRunnerTests.ParsingExeGivesExe, "Runner.ParsingExeGivesExe" + Tests.AltCoverRunnerTests.ParsingMultipleExeGivesFailure, + "Runner.ParsingMultipleExeGivesFailure" + Tests.AltCoverRunnerTests.ParsingNoExeGivesFailure, + "Runner.ParsingNoExeGivesFailure" + Tests.AltCoverRunnerTests.ParsingWorkerGivesWorker, + "Runner.ParsingWorkerGivesWorker" + Tests.AltCoverRunnerTests.ParsingMultipleWorkerGivesFailure, + "Runner.ParsingMultipleWorkerGivesFailure" + Tests.AltCoverRunnerTests.ParsingBadWorkerGivesFailure, + "Runner.ParsingBadWorkerGivesFailure" + Tests.AltCoverRunnerTests.ParsingNoWorkerGivesFailure, + "Runner.ParsingNoWorkerGivesFailure" + Tests.AltCoverRunnerTests.ParsingRecorderGivesRecorder, + "Runner.ParsingRecorderGivesRecorder" + Tests.AltCoverRunnerTests.ParsingMultipleRecorderGivesFailure, + "Runner.ParsingMultipleRecorderGivesFailure" + Tests.AltCoverRunnerTests.ParsingBadRecorderGivesFailure, + "Runner.ParsingBadRecorderGivesFailure" + Tests.AltCoverRunnerTests.ParsingNoRecorderGivesFailure, + "Runner.ParsingNoRecorderGivesFailure" + Tests.AltCoverRunnerTests.ParsingCollectGivesCollect, + "Runner.ParsingCollectGivesCollect" + Tests.AltCoverRunnerTests.ParsingMultipleCollectGivesFailure, + "Runner.ParsingMultipleCollectGivesFailure" + Tests.AltCoverRunnerTests.ParsingLcovGivesLcov, "Runner.ParsingLcovGivesLcov" + Tests.AltCoverRunnerTests.ParsingMultipleLcovGivesFailure, + "Runner.ParsingMultipleLcovGivesFailure" + Tests.AltCoverRunnerTests.ParsingNoLcovGivesFailure, + "Runner.ParsingNoLcovGivesFailure" + Tests.AltCoverRunnerTests.ParsingThresholdGivesThreshold, + "Runner.ParsingThresholdGivesThreshold" + Tests.AltCoverRunnerTests.ParsingTopThresholdGivesThreshold, + "Runner.ParsingTopThresholdGivesThreshold" + Tests.AltCoverRunnerTests.ParsingLowThresholdGivesThreshold, + "Runner.ParsingLowThresholdGivesThreshold" + Tests.AltCoverRunnerTests.ParsingComplexThresholdGivesThreshold, + "Runner.ParsingComplexThresholdGivesThreshold" + Tests.AltCoverRunnerTests.ParsingMultipleThresholdGivesFailure, + "Runner.ParsingMultipleThresholdGivesFailure" + Tests.AltCoverRunnerTests.ParsingBadThresholdGivesFailure, + "Runner.ParsingBadThresholdGivesFailure" + Tests.AltCoverRunnerTests.ParsingBadThreshold2GivesFailure, + "Runner.ParsingBadThreshold2GivesFailure" + Tests.AltCoverRunnerTests.ParsingBadThreshold3GivesFailure, + "Runner.ParsingBadThreshold3GivesFailure" + Tests.AltCoverRunnerTests.ParsingBadThreshold4GivesFailure, + "Runner.ParsingBadThreshold4GivesFailure" + Tests.AltCoverRunnerTests.ParsingBadThreshold5GivesFailure, + "Runner.ParsingBadThreshold5GivesFailure" + Tests.AltCoverRunnerTests.ParsingBadThreshold6GivesFailure, + "Runner.ParsingBadThreshold6GivesFailure" + Tests.AltCoverRunnerTests.ParsingBadThreshold7GivesFailure, + "Runner.ParsingBadThreshold7GivesFailure" + Tests.AltCoverRunnerTests.ParsingEmptyThresholdGivesFailure, + "Runner.ParsingEmptyThresholdGivesFailure" + Tests.AltCoverRunnerTests.ParsingNoThresholdGivesFailure, + "Runner.ParsingNoThresholdGivesFailure" + Tests.AltCoverRunnerTests.ParsingCoberturaGivesCobertura, + "Runner.ParsingCoberturaGivesCobertura" + Tests.AltCoverRunnerTests.ParsingMultipleCoberturaGivesFailure, + "Runner.ParsingMultipleCoberturaGivesFailure" + Tests.AltCoverRunnerTests.ParsingNoCoberturaGivesFailure, + "Runner.ParsingNoCoberturaGivesFailure" + Tests.AltCoverRunnerTests.ParsingOutputGivesOutput, + "Runner.ParsingOutputGivesOutput" + Tests.AltCoverRunnerTests.ParsingMultipleOutputGivesFailure, + "Runner.ParsingMultipleOutputGivesFailure" + Tests.AltCoverRunnerTests.ParsingNoOutputGivesFailure, + "Runner.ParsingNoOutputGivesFailure" + Tests.AltCoverRunnerTests.ParsingDropGivesDrop, "Runner.ParsingDropGivesDrop" + Tests.AltCoverRunnerTests.ParsingMultipleDropGivesFailure, + "Runner.ParsingMultipleDropGivesFailure" + Tests.AltCoverRunnerTests.ParsingTCString, "Runner.ParsingTCString" + Tests.AltCoverRunnerTests.ParsingTCGivesTC, "Runner.ParsingTCGivesTC" + Tests.AltCoverRunnerTests.ParsingMultipleTCGivesFailure, + "Runner.ParsingMultipleTCGivesFailure" + Tests.AltCoverRunnerTests.ParsingBadTCGivesFailure, + "Runner.ParsingBadTCGivesFailure" + Tests.AltCoverRunnerTests.ParsingQuietWorks, "Runner.ParsingQuietWorks" + Tests.AltCoverRunnerTests.ParsingMultiQuietWorks, "Runner.ParsingMultiQuietWorks" + Tests.AltCoverRunnerTests.ParsingBatchMultiQuietWorks, + "Runner.ParsingBatchMultiQuietWorks" + Tests.AltCoverRunnerTests.ShouldRequireExe, "Runner.ShouldRequireExe" + Tests.AltCoverRunnerTests.ShouldAcceptExe, "Runner.ShouldAcceptExe" + Tests.AltCoverRunnerTests.ShouldRequireCollectIfNotExe, + "Runner.ShouldRequireCollectIfNotExe" + Tests.AltCoverRunnerTests.ShouldRejectExeIfCollect, + "Runner.ShouldRejectExeIfCollect" + Tests.AltCoverRunnerTests.ShouldRequireWorker, "Runner.ShouldRequireWorker" + Tests.AltCoverRunnerTests.ShouldAcceptWorker, "Runner.ShouldAcceptWorker" + Tests.AltCoverRunnerTests.ShouldRequireRecorder, "Runner.ShouldRequireRecorder" + Tests.AltCoverRunnerTests.ShouldRequireRecorderDll, + "Runner.ShouldRequireRecorderDll" + Tests.AltCoverRunnerTests.ShouldAcceptRecorder, "Runner.ShouldAcceptRecorder" + Tests.AltCoverRunnerTests.ShouldHandleReturnCodes, "Runner.ShouldHandleReturnCodes" + Tests.AltCoverRunnerTests.ShouldProcessTrailingArguments, + "Runner.ShouldProcessTrailingArguments" + Tests.AltCoverRunnerTests.ShouldNoOp, "Runner.ShouldNoOp" + Tests.AltCoverRunnerTests.ErrorResponseIsAsExpected, + "Runner.ErrorResponseIsAsExpected" + Tests.AltCoverRunnerTests.ShouldGetStringConstants, + "Runner.ShouldGetStringConstants" + Tests.AltCoverRunnerTests.ShouldProcessPayload, "Runner.ShouldProcessPayload" + Tests.AltCoverRunnerTests.WriteJsonLeavesExpectedTraces, + "Runner.WriteJsonLeavesExpectedTraces" + Tests.AltCoverRunnerTests.ZipWriteJsonLeavesExpectedTraces, + "Runner.ZipWriteJsonLeavesExpectedTraces" + Tests.AltCoverRunnerTests.NullPayloadShouldReportNothing, + "Runner.NullPayloadShouldReportNothing" + Tests.AltCoverRunnerTests.WriteLeavesExpectedTraces, + "Runner.WriteLeavesExpectedTraces" + Tests.AltCoverRunnerTests.ZipWriteLeavesExpectedTraces, + "Runner.ZipWriteLeavesExpectedTraces" + Tests.AltCoverRunnerTests.ActivePayloadShouldReportAsExpected, + "Runner.ActivePayloadShouldReportAsExpected" + Tests.AltCoverRunnerTests.CollectShouldReportAsExpected, + "Runner.CollectShouldReportAsExpected" + Tests.AltCoverRunnerTests.JunkPayloadShouldReportAsExpected, + "Runner.JunkPayloadShouldReportAsExpected" + Tests.AltCoverRunnerTests.TrackingPayloadShouldReportAsExpected, + "Runner.TrackingPayloadShouldReportAsExpected" + Tests.AltCoverRunnerTests.PointProcessShouldCaptureTimes, + "Runner.PointProcessShouldCaptureTimes" + Tests.AltCoverRunnerTests.PostprocessShouldHandleNullCase, + "Runner.PostprocessShouldHandleNullCase" + Tests.AltCoverRunnerTests.PostprocessShouldHandleEntryAndExitTimes, + "Runner.PostprocessShouldHandleEntryAndExitTimes" + Tests.AltCoverRunnerTests.PostprocessShouldRestoreKnownOpenCoverState, + "Runner.PostprocessShouldRestoreKnownOpenCoverState" + Tests.AltCoverRunnerTests.PostprocessShouldRestoreKnownOpenCoverStateFromMono, + "Runner.PostprocessShouldRestoreKnownOpenCoverStateFromMono" + Tests.AltCoverRunnerTests.PostprocessShouldRestoreDegenerateOpenCoverState, + "Runner.PostprocessShouldRestoreDegenerateOpenCoverState" + Tests.AltCoverRunnerTests.PostprocessShouldRestoreBranchOnlyOpenCoverState, + "Runner.PostprocessShouldRestoreBranchOnlyOpenCoverState" + Tests.AltCoverRunnerTests.PostprocessShouldRestoreBranchOnlyOpenCoverStateXDoc, + "Runner.PostprocessShouldRestoreBranchOnlyOpenCoverStateXDoc" + Tests.AltCoverRunnerTests.JunkTokenShouldDefaultZero, + "Runner.JunkTokenShouldDefaultZero" + Tests.AltCoverRunnerTests.EmptyJsonGeneratesExpectedSummary, + "Runner.EmptyJsonGeneratesExpectedSummary" + Tests.AltCoverRunnerTests.EmptyJsonGeneratesExpectedTCSummary, + "Runner.EmptyJsonGeneratesExpectedTCSummary" + Tests.AltCoverRunnerTests.EmptyJsonGeneratesExpectedSummaries, + "Runner.EmptyJsonGeneratesExpectedSummaries" + Tests.AltCoverRunnerTests.SimpleJsonShouldGeneratePlausibleSummary, + "Runner.SimpleJsonShouldGeneratePlausibleSummary" + Tests.AltCoverRunnerTests.ComplexJsonShouldGeneratePlausibleSummary, + "Runner.ComplexJsonShouldGeneratePlausibleSummary" + Tests.AltCoverRunnerTests.EmptyNCoverGeneratesExpectedSummary, + "Runner.EmptyNCoverGeneratesExpectedSummary" + Tests.AltCoverRunnerTests.EmptyNCoverGeneratesExpectedTCSummary, + "Runner.EmptyNCoverGeneratesExpectedTCSummary" + Tests.AltCoverRunnerTests.EmptyNCoverGeneratesExpectedSummaries, + "Runner.EmptyNCoverGeneratesExpectedSummaries" + Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleSummary, + "Runner.NCoverShouldGeneratePlausibleSummary" + Tests.AltCoverRunnerTests.EmptyOpenCoverGeneratesExpectedSummary, + "Runner.EmptyOpenCoverGeneratesExpectedSummary" + Tests.AltCoverRunnerTests.EmptyOpenCoverGeneratesExpectedTCSummary, + "Runner.EmptyOpenCoverGeneratesExpectedTCSummary" + Tests.AltCoverRunnerTests.EmptyOpenCoverGeneratesExpectedSummaries, + "Runner.EmptyOpenCoverGeneratesExpectedSummaries" + Tests.AltCoverRunnerTests.OpenCoverShouldGeneratePlausibleSummary, + "Runner.OpenCoverShouldGeneratePlausibleSummary" + Tests.AltCoverRunnerTests.OpenCoverShouldGeneratePlausiblePartialSummary, + "Runner.OpenCoverShouldGeneratePlausiblePartialSummary" + Tests.AltCoverRunnerTests.DegenerateCasesShouldNotGenerateLcov, + "Runner.DegenerateCasesShouldNotGenerateLcov" + Tests.AltCoverRunnerTests.OpenCoverShouldGeneratePlausibleLcov, + "Runner.OpenCoverShouldGeneratePlausibleLcov" + Tests.AltCoverRunnerTests.OpenCoverWithPartialsShouldGeneratePlausibleLcov, + "Runner.OpenCoverWithPartialsShouldGeneratePlausibleLcov" + Tests.AltCoverRunnerTests.JsonShouldGeneratePlausibleLcov, + "Runner.JsonShouldGeneratePlausibleLcov" + Tests.AltCoverRunnerTests.JsonWithPartialsShouldGeneratePlausibleLcov, + "Runner.JsonWithPartialsShouldGeneratePlausibleLcov" + Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleLcov, + "Runner.NCoverShouldGeneratePlausibleLcov" + Tests.AltCoverRunnerTests.NCoverWithPartialsShouldGeneratePlausibleLcov, + "Runner.NCoverWithPartialsShouldGeneratePlausibleLcov" + Tests.AltCoverRunnerTests.NCoverShouldGenerateMorePlausibleLcov, + "Runner.NCoverShouldGenerateMorePlausibleLcov" + Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleLcovWithMissingFullName, + "Runner.NCoverShouldGeneratePlausibleLcovWithMissingFullName" + Tests.AltCoverRunnerTests.MultiSortDoesItsThing, "Runner.MultiSortDoesItsThing" + Tests.AltCoverRunnerTests.JsonShouldGeneratePlausibleXml, + "Runner.JsonShouldGeneratePlausibleXml" + Tests.AltCoverRunnerTests.JsonWithPartialsShouldGeneratePlausibleXml, + "Runner.JsonWithPartialsShouldGeneratePlausibleXml" + Tests.AltCoverRunnerTests.JsonShouldGeneratePlausibleCobertura, + "Runner.JsonShouldGeneratePlausibleCobertura" + Tests.AltCoverRunnerTests.JsonWithPartialsShouldGeneratePlausibleCobertura, + "Runner.JsonWithPartialsShouldGeneratePlausibleCobertura" + Tests.AltCoverRunnerTests.JsonFromComplexNestingShouldGeneratePlausibleCobertura, + "Runner.JsonFromComplexNestingShouldGeneratePlausibleCobertura" + Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleCobertura, + "Runner.NCoverShouldGeneratePlausibleCobertura" + Tests.AltCoverRunnerTests.NCoverWithPartialsShouldGeneratePlausibleCobertura, + "Runner.NCoverWithPartialsShouldGeneratePlausibleCobertura" + Tests.AltCoverRunnerTests.NCoverShouldGenerateMorePlausibleCobertura, + "Runner.NCoverShouldGenerateMorePlausibleCobertura" + Tests.AltCoverRunnerTests.DegenerateCasesShouldNotGenerateCobertura, + "Runner.DegenerateCasesShouldNotGenerateCobertura" + Tests.AltCoverRunnerTests.NCoverShouldGeneratePlausibleCoberturaWithMissingFullName, + "Runner.NCoverShouldGeneratePlausibleCoberturaWithMissingFullName" + Tests.AltCoverRunnerTests.OpenCoverShouldGeneratePlausibleCobertura, + "Runner.OpenCoverShouldGeneratePlausibleCobertura" + Tests.AltCoverRunnerTests.OpenCoverWithPartialsShouldGeneratePlausibleCobertura, + "Runner.OpenCoverWithPartialsShouldGeneratePlausibleCobertura" + Tests.AltCoverRunnerTests.ThresholdViolationShouldBeReported, + "Runner.ThresholdViolationShouldBeReported" + Tests.AltCoverRunnerTests.TryGetValueHandlesNull, "Runner.TryGetValueHandlesNull" + Tests.AltCoverTests.ReportFileShouldBeCorrectlySuffixed, + "Tests.ReportFileShouldBeCorrectlySuffixed" + Tests.AltCoverTests.CanSwitchSampling, "Tests.CanSwitchSampling" + Tests.AltCoverTests.ShouldGetPdbFromImage, "Tests.ShouldGetPdbFromImage" + Tests.AltCoverTests.ShouldGetEmbeddedPdbFromImage, + "Tests.ShouldGetEmbeddedPdbFromImage" + Tests.AltCoverTests.ShouldGetNoMdbFromMonoImage, + "Tests.ShouldGetNoMdbFromMonoImage" + Tests.AltCoverTests.ShouldGetPdbWithFallback, "Tests.ShouldGetPdbWithFallback" + Tests.AltCoverTests.ShouldGetForeignPdbWithFallback, + "Tests.ShouldGetForeignPdbWithFallback" + Tests.AltCoverTests.ShouldGetForeignPdbWithFallbackWhenNotColocated, + "Tests.ShouldGetForeignPdbWithFallbackWhenNotColocated" + Tests.AltCoverTests.ShouldGetMdbWithFallback, "Tests.ShouldGetMdbWithFallback" + Tests.AltCoverTests.ShouldGetSymbolsFromPdb, "Tests.ShouldGetSymbolsFromPdb" + Tests.AltCoverTests.ShouldGetSymbolsFromEmbeddedPdb, + "Tests.ShouldGetSymbolsFromEmbeddedPdb" + Tests.AltCoverTests.ShouldNotGetSymbolsWhenNoPdb, + "Tests.ShouldNotGetSymbolsWhenNoPdb" + Tests.AltCoverTests.ShouldGetSymbolsFromMdb, "Tests.ShouldGetSymbolsFromMdb" + Tests.AltCoverTests.NoneOfTheAboveMatchesNoType, + "Tests.NoneOfTheAboveMatchesNoType" + Tests.AltCoverTests.NoneOfTheAboveMatchesNoAttribute, + "Tests.NoneOfTheAboveMatchesNoAttribute" + Tests.AltCoverTests.NoneOfTheAboveMatchesNoAssembly, + "Tests.NoneOfTheAboveMatchesNoAssembly" + Tests.AltCoverTests.NoneOfTheAboveMatchesNoModule, + "Tests.NoneOfTheAboveMatchesNoModule" + Tests.AltCoverTests.NoneOfTheAboveMatchesNoFile, + "Tests.NoneOfTheAboveMatchesNoFile" + Tests.AltCoverTests.NoneOfTheAboveMatchesNoPath, + "Tests.NoneOfTheAboveMatchesNoPath" + Tests.AltCoverTests.NoneOfTheAboveMatchesNoMethod, + "Tests.NoneOfTheAboveMatchesNoMethod" + Tests.AltCoverTests.FileDoesNotMatchNonFileClass, + "Tests.FileDoesNotMatchNonFileClass" + Tests.AltCoverTests.FileDoesMatchFileClass, "Tests.FileDoesMatchFileClass" + Tests.AltCoverTests.PathDoesNotMatchNonPathClass, + "Tests.PathDoesNotMatchNonPathClass" + Tests.AltCoverTests.PathDoesMatchPathClass, "Tests.PathDoesMatchPathClass" + Tests.AltCoverTests.AssemblyDoesNotMatchNonAssemblyClass, + "Tests.AssemblyDoesNotMatchNonAssemblyClass" + Tests.AltCoverTests.AssemblyDoesMatchAssemblyClass, + "Tests.AssemblyDoesMatchAssemblyClass" + Tests.AltCoverTests.ModuleDoesNotMatchNonModuleClass, + "Tests.ModuleDoesNotMatchNonModuleClass" + Tests.AltCoverTests.ModuleDoesMatchModuleClass, "Tests.ModuleDoesMatchModuleClass" + Tests.AltCoverTests.TypeDoesNotMatchNonTypeClass, + "Tests.TypeDoesNotMatchNonTypeClass" + Tests.AltCoverTests.TypeDoesMatchTypeClass, "Tests.TypeDoesMatchTypeClass" + Tests.AltCoverTests.MethodDoesNotMatchNonMethodClass, + "Tests.MethodDoesNotMatchNonMethodClass" + Tests.AltCoverTests.MethodDoesMatchMethodClass, "Tests.MethodDoesMatchMethodClass" + Tests.AltCoverTests.AttributeDoesNotMatchNonAttributeClass, + "Tests.AttributeDoesNotMatchNonAttributeClass" + Tests.AltCoverTests.AttributeDoesMatchAttributeClass, + "Tests.AttributeDoesMatchAttributeClass" + Tests.AltCoverTests.CanExcludeCSharpPropertiesByAttribute, + "Tests.CanExcludeCSharpPropertiesByAttribute" + Tests.AltCoverTests.Sample3Class1IsCSharpAutoproperty, + "Tests.Sample3Class1IsCSharpAutoproperty" + Tests.AltCoverTests.Sample3Class2IsNotCSharpAutoproperty, + "Tests.Sample3Class2IsNotCSharpAutoproperty" + Tests.AltCoverTests.CanIdentifyExcludedFSharpMethods, + "Tests.CanIdentifyExcludedFSharpMethods" + Tests.AltCoverTests.CanIdentifyExcludedCSharpAutoProperties, + "Tests.CanIdentifyExcludedCSharpAutoProperties" + Tests.AltCoverTests.CanIdentifyIncludedCSharpProperties, + "Tests.CanIdentifyIncludedCSharpProperties" + Tests.AltCoverTests.ValidateStaticExemption, "Tests.ValidateStaticExemption" + Tests.AltCoverTests.ValidateStaticClass, "Tests.ValidateStaticClass" + Tests.AltCoverTests.ValidateAutomaticExemption, "Tests.ValidateAutomaticExemption" + Tests.AltCoverTests.DetectLocalSource, "Tests.DetectLocalSource" + Tests.AltCoverTests.LocateMatchShouldChooseLongerWildCardPath, + "Tests.LocateMatchShouldChooseLongerWildCardPath" + Tests.AltCoverTests.LocateMatchFallsBackOK, "Tests.LocateMatchFallsBackOK" + Tests.AltCoverTests.AsyncTestInContext, "Tests.AsyncTestInContext" + Tests.AltCoverTests.AnotherAsyncTestInContext, "Tests.AnotherAsyncTestInContext" + Tests.AltCoverTests.DebugBuildTernaryTestInContext, + "Tests.DebugBuildTernaryTestInContext" + Tests.AltCoverTests.ReleaseBuildTernaryTest, "Tests.ReleaseBuildTernaryTest" + Tests.AltCoverTests.ReleaseBuildTernaryTestInContext, + "Tests.ReleaseBuildTernaryTestInContext" + Tests.AltCoverTests.ReleaseBuildTernaryTestInContextWithCoalescence, + "Tests.ReleaseBuildTernaryTestInContextWithCoalescence" + Tests.AltCoverTests.CSharpNestedMethods, "Tests.CSharpNestedMethods" + Tests.AltCoverTests.FSharpNestedMethodsClassic, "Tests.FSharpNestedMethodsClassic" + Tests.AltCoverTests.FSharpNestedMethods5x0x201, "Tests.FSharpNestedMethods_5_0_201" + Tests.AltCoverTests.ValidateSeqPntFixUp, "Tests.ValidateSeqPntFixUp" // HACK HACK HACK + Tests.AltCoverTests.EmptyArrayHasExpectedHash, "Tests.EmptyArrayHasExpectedHash" + Tests.AltCoverTests.KeyHasExpectedToken, "Tests.KeyHasExpectedToken" + Tests.AltCoverTests.TokenGeneratesExpectedULong, + "Tests.TokenGeneratesExpectedULong" + Tests.AltCoverTests.KeyHasExpectedIndex, "Tests.KeyHasExpectedIndex" + Tests.AltCoverTests.EmptyArrayHasExpectedIndex, "Tests.EmptyArrayHasExpectedIndex" + Tests.AltCoverTests.KeyHasExpectedRecord, "Tests.KeyHasExpectedRecord" + Tests.AltCoverTests.KeyHasExpectedPlaceInIndex, "Tests.KeyHasExpectedPlaceInIndex" + Tests.AltCoverTests.EmptyFiltersPassAll, "Tests.EmptyFiltersPassAll" + Tests.AltCoverTests.NonEmptyFiltersCatchAnExpectedValue, + "Tests.NonEmptyFiltersCatchAnExpectedValue" + Tests.AltCoverTests.NonEmptyFiltersPassAnExpectedValue, + "Tests.NonEmptyFiltersPassAnExpectedValue" + Tests.AltCoverTests.AfterProcessingYieldsAnExpectedValue, + "Tests.AfterProcessingYieldsAnExpectedValue" + Tests.AltCoverTests.Sample3Class1PropertyIsNotSignificant, + "Tests.Sample3Class1PropertyIsNotSignificant" + Tests.AltCoverTests.Sample3Class2IPropertyIsSignificant, + "Tests.Sample3Class2IPropertyIsSignificant" + Tests.AltCoverTests.TerminalCasesGoNoDeeper, "Tests.TerminalCasesGoNoDeeper" + Tests.AltCoverTests.MethodPointsAreDeeperThanMethods, + "Tests.MethodPointsAreDeeperThanMethods" + Tests.AltCoverTests.BranchPointsAreComputedForSwitch, + "Tests.BranchPointsAreComputedForSwitch" + Tests.AltCoverTests.BranchPointsAreComputedForMatch, + "Tests.BranchPointsAreComputedForMatch" + Tests.AltCoverTests.MethodsAreDeeperThanTypes, "Tests.MethodsAreDeeperThanTypes" + Tests.AltCoverTests.TypesAreDeeperThanModules, "Tests.TypesAreDeeperThanModules" + Tests.AltCoverTests.ModulesAreDeeperThanAssemblies, + "Tests.ModulesAreDeeperThanAssemblies" + Tests.AltCoverTests.AssembliesAreDeeperThanPaths, + "Tests.AssembliesAreDeeperThanPaths" + Tests.AltCoverTests.FilteredAssembliesDoNotHaveSequencePoints, + "Tests.FilteredAssembliesDoNotHaveSequencePoints" + Tests.AltCoverTests.TestFixPointInvoke, "Tests.TestFixPointInvoke" + Tests.AltCoverTests.TestFixPointApply, "Tests.TestFixPointApply" + Tests.AltCoverTests.PathsAreDeeperThanAVisit, "Tests.PathsAreDeeperThanAVisit" + Tests.AltCoverTests.TrackingDetectsTests, "Tests.TrackingDetectsTests" + Tests.AltCoverTests.TrackingDetectsExpectedTests, + "Tests.TrackingDetectsExpectedTests" + Tests.AltCoverTests.TrackingDetectsTestsByFullType, + "Tests.TrackingDetectsTestsByFullType" + Tests.AltCoverTests.TrackingDetectsMethods, "Tests.TrackingDetectsMethods" + Tests.AltCoverTests.NamingDetectEmpties, "Tests.NamingDetectEmpties" + Tests.AltCoverTests.NamingSuffixDetectEmpties, "Tests.NamingSuffixDetectEmpties" + Tests.AltCoverTests.TypeNamesAreExtracted, "Tests.TypeNamesAreExtracted" + Tests.AltCoverTests.FullTypeNamesAreExtracted, "Tests.FullTypeNamesAreExtracted" + Tests.AltCoverTests.TypeRefNamesAreExtracted, "Tests.TypeRefNamesAreExtracted" + Tests.AltCoverTests.FullTypeRefNamesAreExtracted, + "Tests.FullTypeRefNamesAreExtracted" + Tests.AltCoverTests.MethodNamesAreExtracted, "Tests.MethodNamesAreExtracted" + Tests.AltCoverTests.FullMethodNamesAreExtracted, + "Tests.FullMethodNamesAreExtracted" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNet, + "Tests.ShouldGenerateExpectedXmlReportFromDotNet" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithEmbeds, + "Tests.ShouldGenerateExpectedXmlReportFromWithEmbeds" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithPartials, + "Tests.ShouldGenerateExpectedXmlReportFromWithPartials" + Tests.AltCoverTests.ShouldGenerateExpectedJsonReportFromDotNet, + "Tests.ShouldGenerateExpectedJsonReportFromDotNet" + Tests.AltCoverTests.ShouldGenerateExpectedJsonReportWithEmbeds, + "Tests.ShouldGenerateExpectedJsonReportWithEmbeds" + Tests.AltCoverTests.ShouldGenerateExpectedJsonReportWithPartials, + "Tests.ShouldGenerateExpectedJsonReportWithPartials" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportForNCoverWithMethodPointOnly, + "Tests.ShouldGenerateExpectedXmlReportForNCoverWithMethodPointOnly" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportForNCoverWithTopLevel, + "Tests.ShouldGenerateExpectedXmlReportForNCoverWithTopLevel" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportForOpenCoverWithMethodPointOnly, + "Tests.ShouldGenerateExpectedXmlReportForOpenCoverWithMethodPointOnly" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithSourceLink, + "Tests.ShouldGenerateExpectedXmlReportWithSourceLink" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetWithPathFilter, + "Tests.ShouldGenerateExpectedXmlReportFromDotNetWithPathFilter" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetWhenExcluded, + "Tests.ShouldGenerateExpectedXmlReportFromDotNetWhenExcluded" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetWhenExcludedEvenIfTracked, + "Tests.ShouldGenerateExpectedXmlReportFromDotNetWhenExcludedEvenIfTracked" + Tests.AltCoverTests.ShouldDetectTernary, "Tests.ShouldDetectTernary" + Tests.AltCoverTests.ShouldDetectSwitchNesting, "Tests.ShouldDetectSwitchNesting" + Tests.AltCoverTests.SafeMultiplyIsSafe, "Tests.SafeMultiplyIsSafe" + Tests.AltCoverTests.EmptyMethodHasComplexity1, "Tests.EmptyMethodHasComplexity1" + Tests.AltCoverTests.BranchChainsSerialize, "Tests.BranchChainsSerialize" + Tests.AltCoverTests.BranchChainsTerminate, "Tests.BranchChainsTerminate" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithSourceLinkOpenCoverStyle, + "Tests.ShouldGenerateExpectedXmlReportWithSourceLinkOpenCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetOpenCoverStyle, + "Tests.ShouldGenerateExpectedXmlReportFromDotNetOpenCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithEmbedsOpenCoverStyle, + "Tests.ShouldGenerateExpectedXmlReportWithEmbedsOpenCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithPartialsOpenCoverStyle, + "Tests.ShouldGenerateExpectedXmlReportWithPartialsOpenCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetLineCoverStyle, + "Tests.ShouldGenerateExpectedXmlReportFromDotNetLineCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetBranchCoverStyle, + "Tests.ShouldGenerateExpectedXmlReportFromDotNetBranchCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportFromDotNetOpenCoverStyleWithTracking, + "Tests.ShouldGenerateExpectedXmlReportFromDotNetOpenCoverStyleWithTracking" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithModuleExclusionOpenCoverStyle, + "Tests.ShouldGenerateExpectedXmlReportWithModuleExclusionOpenCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedTrackingXmlReportWithModuleExclusionOpenCoverStyle, + "Tests.ShouldGenerateExpectedTrackingXmlReportWithModuleExclusionOpenCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithClassExclusionOpenCoverStyle, + "Tests.ShouldGenerateExpectedXmlReportWithClassExclusionOpenCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedTrackingXmlReportWithClassExclusionOpenCoverStyle, + "Tests.ShouldGenerateExpectedTrackingXmlReportWithClassExclusionOpenCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithMethodExclusionOpenCoverStyle, + "Tests.ShouldGenerateExpectedXmlReportWithMethodExclusionOpenCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithFileExclusionOpenCoverStyle, + "Tests.ShouldGenerateExpectedXmlReportWithFileExclusionOpenCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedTrackingXmlReportWithMethodExclusionOpenCoverStyle, + "Tests.ShouldGenerateExpectedTrackingXmlReportWithMethodExclusionOpenCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithTraditionalInterfacesOpenCoverStyle, + "Tests.ShouldGenerateExpectedXmlReportWithTraditionalInterfacesOpenCoverStyle" + Tests.AltCoverTests.ShouldGenerateExpectedXmlReportWithModernInterfacesOpenCoverStyle, + "Tests.ShouldGenerateExpectedXmlReportWithModernInterfacesOpenCoverStyle" + Tests.AltCoverTests.ShouldSortFileIds, "Tests.ShouldSortFileIds" + Tests.AltCoverTests.ZeroIsNotVisited, "Tests.ZeroIsNotVisited" + Tests.AltCoverTests.PositiveIsVisited, "Tests.PositiveIsVisited" + Tests.AltCoverTests.NegativesSpray, "Tests.NegativesSpray" + Tests.AltCoverTests2.ShouldBeAbleToGetTheVisitReportMethod, + "Tests2.ShouldBeAbleToGetTheVisitReportMethod" + Tests.AltCoverTests2.ShouldBeAbleToClearTheStrongNameKey, + "Tests2.ShouldBeAbleToClearTheStrongNameKey" + Tests.AltCoverTests2.ShouldBeAbleToUpdateTheStrongNameKeyWherePossible, + "Tests2.ShouldBeAbleToUpdateTheStrongNameKeyWherePossible" + Tests.AltCoverTests2.NoKnownKeyInEmptyIndex, "Tests2.NoKnownKeyInEmptyIndex" + Tests.AltCoverTests2.KnownKeyMatchedInIndex, "Tests2.KnownKeyMatchedInIndex" + Tests.AltCoverTests2.ThirdPartyKeyNotMatchedInIndex, + "Tests2.ThirdPartyKeyNotMatchedInIndex" + Tests.AltCoverTests2.FakedUpKeyIsMatchedInIndex, + "Tests2.FakedUpKeyIsMatchedInIndex" + Tests.AltCoverTests2.NoKnownKeyIfAssemblyHasNone, + "Tests2.NoKnownKeyIfAssemblyHasNone" + Tests.AltCoverTests2.NoKnownTokenInEmptyIndex, "Tests2.NoKnownTokenInEmptyIndex" + Tests.AltCoverTests2.KnownTokenMatchedInIndex, "Tests2.KnownTokenMatchedInIndex" + Tests.AltCoverTests2.NoKnownTokenIfAssemblyHasNone, + "Tests2.NoKnownTokenIfAssemblyHasNone" + Tests.AltCoverTests2.ForeignTokenIsNotMatchedInIndex, + "Tests2.ForeignTokenIsNotMatchedInIndex" + Tests.AltCoverTests2.FakedUpTokenIsMatchedInIndex, + "Tests2.FakedUpTokenIsMatchedInIndex" + Tests.AltCoverTests2.MonoCombinationCanBeExercisedOnNetCore, + "Tests2.MonoCombinationCanBeExercisedOnNetCore" + Tests.AltCoverTests2.GuardShouldDisposeRecordingAssemblyOnException, + "Tests2.GuardShouldDisposeRecordingAssemblyOnException" + Tests.AltCoverTests2.ShouldBeAbleToTellAnAssembly, + "Tests2.ShouldBeAbleToTellAnAssembly" + Tests.AltCoverTests2.ShouldBeAbleToValidateAnAssembly, + "Tests2.ShouldBeAbleToValidateAnAssembly" + Tests.AltCoverTests2.ShouldBeAbleToLocateAReference, + "Tests2.ShouldBeAbleToLocateAReference" + Tests.AltCoverTests2.ShouldBeAbleToPrepareTheAssembly, + "Tests2.ShouldBeAbleToPrepareTheAssembly" + Tests.AltCoverTests2.ShouldGetTrackingStyleIfSet, + "Tests2.ShouldGetTrackingStyleIfSet" + Tests.AltCoverTests2.ShouldSymbolWriterAsExpected, + "Tests2.ShouldSymbolWriterAsExpected" + Tests.AltCoverTests2.ShouldGetNewFilePathFromPreparedAssembly, + "Tests2.ShouldGetNewFilePathFromPreparedAssembly" + Tests.AltCoverTests2.ShouldRescopeMonoMethodOK, "Tests2.ShouldRescopeMonoMethodOK" + Tests.AltCoverTests2.ShouldWriteMonoAssemblyOK, "Tests2.ShouldWriteMonoAssemblyOK" + Tests.AltCoverTests2.ShouldGetVisitFromWrittenAssembly, + "Tests2.ShouldGetVisitFromWrittenAssembly" + //Tests.AltCoverTests2.ShouldUpdateHandlerOK([] selection) + Tests.AltCoverTests2.ShouldSubstituteInstructionOperand, + "Tests2.ShouldSubstituteInstructionOperand" + Tests.AltCoverTests2.ShouldNotSubstituteDifferentInstructionOperand, + "Tests2.ShouldNotSubstituteDifferentInstructionOperand" + Tests.AltCoverTests2.ShouldSubstituteIntoInstructionOperandArray, + "Tests2.ShouldSubstituteIntoInstructionOperandArray" + Tests.AltCoverTests2.ShouldNotSubstituteOutsideInstructionOperandArray, + "Tests2.ShouldNotSubstituteOutsideInstructionOperandArray" + Tests.AltCoverTests2.ShouldNotSubstituteOtherOperand, + "Tests2.ShouldNotSubstituteOtherOperand" + Tests.AltCoverTests2.ShouldBeAbleToTrackAMethod, + "Tests2.ShouldBeAbleToTrackAMethod" + Tests.AltCoverTests2.ShouldBeAbleToTrackAMethodWithTailCalls, + "Tests2.ShouldBeAbleToTrackAMethodWithTailCalls" + Tests.AltCoverTests2.ShouldBeAbleToTrackAMethodWithNonVoidReturn, + "Tests2.ShouldBeAbleToTrackAMethodWithNonVoidReturn" + Tests.AltCoverTests2.ShouldBeAbleToTrackAnAsyncMethod, + "Tests2.ShouldBeAbleToTrackAnAsyncMethod" + Tests.AltCoverTests2.ShouldBeAbleToTrackAnFSAsyncMethod, + "Tests2.ShouldBeAbleToTrackAnFSAsyncMethod" + Tests.AltCoverTests2.ShouldBeAbleToTrackAnFSTaskMethod, + "Tests2.ShouldBeAbleToTrackAnFSTaskMethod" + Tests.AltCoverTests2.ShouldBeAbleToInstrumentASwitchForNCover, + "Tests2.ShouldBeAbleToInstrumentASwitchForNCover" + Tests.AltCoverTests2.ShouldNotChangeAnUntrackedMethod, + "Tests2.ShouldNotChangeAnUntrackedMethod" + Tests.AltCoverTests2.SwitchBranchesShouldInstrumentByPushingDown, + "Tests2.SwitchBranchesShouldInstrumentByPushingDown" + Tests.AltCoverTests2.PseudoSwitchVisibleBranchesShouldSkipNonRepresentativeCases, + "Tests2.PseudoSwitchVisibleBranchesShouldSkipNonRepresentativeCases" + Tests.AltCoverTests2.SimpleBranchShouldInstrumentByPushingDown, + "Tests2.SimpleBranchShouldInstrumentByPushingDown" + Tests.AltCoverTests2.StartShouldLoadRecordingAssembly, + "Tests2.StartShouldLoadRecordingAssembly" + Tests.AltCoverTests2.TypeShouldNotChangeState, "Tests2.TypeShouldNotChangeState" + Tests.AltCoverTests2.ExcludedMethodShouldNotChangeState, + "Tests2.ExcludedMethodShouldNotChangeState" + Tests.AltCoverTests2.IncludedMethodShouldChangeState, + "Tests2.IncludedMethodShouldChangeState" + Tests.AltCoverTests2.ExcludedAfterMethodShouldNotChangeState, + "Tests2.ExcludedAfterMethodShouldNotChangeState" + Tests.AltCoverTests2.IncludedAfterMethodShouldRewriteMethod, + "Tests2.IncludedAfterMethodShouldRewriteMethod" + Tests.AltCoverTests2.UpdateStrongReferencesShouldChangeSigningKeyWherePossible, + "Tests2.UpdateStrongReferencesShouldChangeSigningKeyWherePossible" + Tests.AltCoverTests2.UpdateStrongReferencesShouldChangeSigningKeyWherePossible2, + "Tests2.UpdateStrongReferencesShouldChangeSigningKeyWherePossible2" + Tests.AltCoverTests2.UpdateStrongReferencesShouldRemoveSigningKeyIfRequired, + "Tests2.UpdateStrongReferencesShouldRemoveSigningKeyIfRequired" + Tests.AltCoverTests2.UpdateStrongReferencesShouldNotAddASigningKey, + "Tests2.UpdateStrongReferencesShouldNotAddASigningKey" + Tests.AltCoverTests2.UpdateStrongReferencesShouldTrackReferences, + "Tests2.UpdateStrongReferencesShouldTrackReferences" + Tests.AltCoverTests2.UpdateStrongReferencesShouldTrackReferencesEvenFakes, + "Tests2.UpdateStrongReferencesShouldTrackReferencesEvenFakes" + Tests.AltCoverTests2.ExcludedAssemblyRefsAreNotUpdated, + "Tests2.ExcludedAssemblyRefsAreNotUpdated" + Tests.AltCoverTests2.IncludedAssemblyRefsAreUpdated, + "Tests2.IncludedAssemblyRefsAreUpdated" + Tests.AltCoverTests2.ExcludedModuleJustRecordsMVid, + "Tests2.ExcludedModuleJustRecordsMVid" + Tests.AltCoverTests2.ExcludedModuleJustRecordsNameForJson, + "Tests2.ExcludedModuleJustRecordsNameForJson" + Tests.AltCoverTests2.ExcludedModuleJustRecordsHashForOpenCover, + "Tests2.ExcludedModuleJustRecordsHashForOpenCover" + Tests.AltCoverTests2.IncludedModuleEnsuresRecorder, + "Tests2.IncludedModuleEnsuresRecorder" + Tests.AltCoverTests2.ExcludedMethodPointIsPassThrough, + "Tests2.ExcludedMethodPointIsPassThrough" + Tests.AltCoverTests2.IncludedMethodPointInsertsVisit, + "Tests2.IncludedMethodPointInsertsVisit" + Tests.AltCoverTests2.IncludedModuleDoesNotChangeRecorderJustTheReference, + "Tests2.IncludedModuleDoesNotChangeRecorderJustTheReference" + Tests.AltCoverTests2.AfterModuleShouldNotChangeState, + "Tests2.AfterModuleShouldNotChangeState" + Tests.AltCoverTests2.JSONInjectionTransformsSimpleFileAsExpected, + "Tests2.JSONInjectionTransformsSimpleFileAsExpected" + Tests.AltCoverTests2.JSONInjectionTransformsStandaloneFileAsExpected, + "Tests2.JSONInjectionTransformsStandaloneFileAsExpected" + Tests.AltCoverTests2.JSONInjectionTransformsDependencyFileAsExpected, + "Tests2.JSONInjectionTransformsDependencyFileAsExpected" + Tests.AltCoverTests2.JSONInjectionIsIdempotent, "Tests2.JSONInjectionIsIdempotent" + Tests.AltCoverTests2.NonFinishShouldDisposeRecordingAssembly, + "Tests2.NonFinishShouldDisposeRecordingAssembly" + Tests.AltCoverTests2.NonFinishShouldDisposeThreadingAssembly, + "Tests2.NonFinishShouldDisposeThreadingAssembly" + Tests.AltCoverTests2.NonFinishShouldNotDisposeNullRecordingAssembly, + "Tests2.NonFinishShouldNotDisposeNullRecordingAssembly" + Tests.AltCoverTests2.FinishShouldLeaveRecordingAssembly, + "Tests2.FinishShouldLeaveRecordingAssembly" + Tests.AltCoverTests2.StrongNameKeyCanBeValidated, + "Tests2.StrongNameKeyCanBeValidated" + Tests.AltCoverTests2.VerbosityShouldBeHonoured, "Tests2.VerbosityShouldBeHonoured" + Tests.AltCoverTests2.CryptographicExceptionIsTransformed, + "Tests2.CryptographicExceptionIsTransformed" + Tests.AltCoverTests2.OutputCanBeExercised, "Tests2.OutputCanBeExercised" + Tests.AltCoverTests2.NoThrowNoErrorLeavesAllOK, "Tests2.NoThrowNoErrorLeavesAllOK" + Tests.AltCoverTests2.NoThrowWithErrorIsSignalled, + "Tests2.NoThrowWithErrorIsSignalled" + Tests.AltCoverTests2.ArgumentExceptionWrites, "Tests2.ArgumentExceptionWrites" + Tests.AltCoverTests2.ArgumentExceptionWritesEx, "Tests2.ArgumentExceptionWritesEx" + Tests.AltCoverTests2.IOExceptionWrites, "Tests2.IOExceptionWrites" + Tests.AltCoverTests2.NotSupportedExceptionWrites, + "Tests2.NotSupportedExceptionWrites" + Tests.AltCoverTests2.SecurityExceptionWrites, "Tests2.SecurityExceptionWrites" + Tests.AltCoverTests2.UnauthorizedAccessExceptionWrites, + "Tests2.UnauthorizedAccessExceptionWrites" + Tests.AltCoverTests3.ShouldLaunchWithExpectedOutput, + "Tests3.ShouldLaunchWithExpectedOutput" + Tests.AltCoverTests3.ShouldHaveExpectedOptions, "Tests3.ShouldHaveExpectedOptions" + Tests.AltCoverTests3.ParsingJunkIsAnError, "Tests3.ParsingJunkIsAnError" + Tests.AltCoverTests3.ParsingJunkBeforeSeparatorIsAnError, + "Tests3.ParsingJunkBeforeSeparatorIsAnError" + Tests.AltCoverTests3.ParsingJunkAfterSeparatorIsExpected, + "Tests3.ParsingJunkAfterSeparatorIsExpected" + Tests.AltCoverTests3.ParsingHelpGivesHelp, "Tests3.ParsingHelpGivesHelp" + Tests.AltCoverTests3.ParsingErrorHelpGivesHelp, "Tests3.ParsingErrorHelpGivesHelp" + Tests.AltCoverTests3.ParsingAttributesGivesAttributes, + "Tests3.ParsingAttributesGivesAttributes" + Tests.AltCoverTests3.ParsingTopLevelGivesTopLevel, + "Tests3.ParsingTopLevelGivesTopLevel" + Tests.AltCoverTests3.ParsingMethodsGivesMethods, + "Tests3.ParsingMethodsGivesMethods" + Tests.AltCoverTests3.ParsingTypesGivesTypes, "Tests3.ParsingTypesGivesTypes" + Tests.AltCoverTests3.ParsingAssembliesGivesAssemblies, + "Tests3.ParsingAssembliesGivesAssemblies" + Tests.AltCoverTests3.ParsingEscapeCasesWork, "Tests3.ParsingEscapeCasesWork" + Tests.AltCoverTests3.ParsingModulesGivesModules, + "Tests3.ParsingModulesGivesModules" + Tests.AltCoverTests3.ParsingFilesGivesFiles, "Tests3.ParsingFilesGivesFiles" + Tests.AltCoverTests3.ParsingPathsGivesPaths, "Tests3.ParsingPathsGivesPaths" + Tests.AltCoverTests3.ParsingReportGivesReport, "Tests3.ParsingReportGivesReport" + Tests.AltCoverTests3.ParsingMultipleReportGivesFailure, + "Tests3.ParsingMultipleReportGivesFailure" + Tests.AltCoverTests3.ParsingBadReportGivesFailure, + "Tests3.ParsingBadReportGivesFailure" + Tests.AltCoverTests3.ParsingNoReportGivesFailure, + "Tests3.ParsingNoReportGivesFailure" + Tests.AltCoverTests3.ParsingEmptyReportGivesFailure, + "Tests3.ParsingEmptyReportGivesFailure" + Tests.AltCoverTests3.ParsingInputGivesInput, "Tests3.ParsingInputGivesInput" + Tests.AltCoverTests3.ParsingMultipleInputIsOKToo, + "Tests3.ParsingMultipleInputIsOKToo" + Tests.AltCoverTests3.ParsingDuplicateInputGivesFailure, + "Tests3.ParsingDuplicateInputGivesFailure" + Tests.AltCoverTests3.ParsingBadInputGivesFailure, + "Tests3.ParsingBadInputGivesFailure" + Tests.AltCoverTests3.ParsingNoInputGivesFailure, + "Tests3.ParsingNoInputGivesFailure" + Tests.AltCoverTests3.ParsingOutputGivesOutput, "Tests3.ParsingOutputGivesOutput" + Tests.AltCoverTests3.ParsingDuplicateOutputGivesFailure, + "Tests3.ParsingDuplicateOutputGivesFailure" + Tests.AltCoverTests3.ParsingMultipleOutputIsOK, "Tests3.ParsingMultipleOutputIsOK" + Tests.AltCoverTests3.ParsingBadOutputGivesFailure, + "Tests3.ParsingBadOutputGivesFailure" + Tests.AltCoverTests3.ParsingNoOutputGivesFailure, + "Tests3.ParsingNoOutputGivesFailure" + Tests.AltCoverTests3.ParsingEmptyOutputGivesFailure, + "Tests3.ParsingEmptyOutputGivesFailure" + Tests.AltCoverTests3.ParsingSymbolGivesSymbol, "Tests3.ParsingSymbolGivesSymbol" + Tests.AltCoverTests3.ParsingMultipleSymbolGivesOK, + "Tests3.ParsingMultipleSymbolGivesOK" + Tests.AltCoverTests3.ParsingBadSymbolGivesFailure, + "Tests3.ParsingBadSymbolGivesFailure" + Tests.AltCoverTests3.ParsingNoSymbolGivesFailure, + "Tests3.ParsingNoSymbolGivesFailure" + Tests.AltCoverTests3.ParsingMultipleDependencyIsOk, + "Tests3.ParsingMultipleDependencyIsOk" + Tests.AltCoverTests3.ParsingBadDependencyGivesFailure, + "Tests3.ParsingBadDependencyGivesFailure" + Tests.AltCoverTests3.ParsingNonDependencyGivesFailure, + "Tests3.ParsingNonDependencyGivesFailure" + Tests.AltCoverTests3.ParsingStrongNameGivesStrongName, + "Tests3.ParsingStrongNameGivesStrongName" + Tests.AltCoverTests3.ParsingMultipleStrongNameGivesFailure, + "Tests3.ParsingMultipleStrongNameGivesFailure" + Tests.AltCoverTests3.ParsingBadStrongNameGivesFailure, + "Tests3.ParsingBadStrongNameGivesFailure" + Tests.AltCoverTests3.ParsingNonStrongNameGivesFailure, + "Tests3.ParsingNonStrongNameGivesFailure" + Tests.AltCoverTests3.ParsingNoStrongNameGivesFailure, + "Tests3.ParsingNoStrongNameGivesFailure" + Tests.AltCoverTests3.ParsingMultipleAltStrongNameIsOk, + "Tests3.ParsingMultipleAltStrongNameIsOk" + Tests.AltCoverTests3.ParsingNoAltStrongNameGivesFailure, + "Tests3.ParsingNoAltStrongNameGivesFailure" + Tests.AltCoverTests3.ParsingBadAltStrongNameGivesFailure, + "Tests3.ParsingBadAltStrongNameGivesFailure" + Tests.AltCoverTests3.ParsingNonAltsStrongNameGivesFailure, + "Tests3.ParsingNonAltsStrongNameGivesFailure" + Tests.AltCoverTests3.ParsingLocalGivesLocal, "Tests3.ParsingLocalGivesLocal" + Tests.AltCoverTests3.ParsingMultipleLocalGivesFailure, + "Tests3.ParsingMultipleLocalGivesFailure" + Tests.AltCoverTests3.ParsingVisibleGivesVisible, + "Tests3.ParsingVisibleGivesVisible" + Tests.AltCoverTests3.ParsingMultipleVisibleGivesFailure, + "Tests3.ParsingMultipleVisibleGivesFailure" + Tests.AltCoverTests3.ParsingTimeGivesTime, "Tests3.ParsingTimeGivesTime" + Tests.AltCoverTests3.ParsingOnlyArabicNumeralsNotThatSortofArabicNumeralsGivesTime, + "Tests3.ParsingOnlyArabicNumeralsNotThatSortofArabicNumeralsGivesTime" + Tests.AltCoverTests3.ParsingMultipleTimesGivesFailure, + "Tests3.ParsingMultipleTimesGivesFailure" + Tests.AltCoverTests3.ParsingTimeAndNamesGivesOK, + "Tests3.ParsingTimeAndNamesGivesOK" + Tests.AltCoverTests3.ParsingBadTimeGivesNoOp, "Tests3.ParsingBadTimeGivesNoOp" + Tests.AltCoverTests3.ParsingNonTimeGivesFailure, + "Tests3.ParsingNonTimeGivesFailure" + Tests.AltCoverTests3.ParsingNoTimeGivesFailure, "Tests3.ParsingNoTimeGivesFailure" + Tests.AltCoverTests3.ParsingJsonFormatGivesJson, + "Tests3.ParsingJsonFormatGivesJson" + Tests.AltCoverTests3.ParsingNCoverFormatGivesNCover, + "Tests3.ParsingNCoverFormatGivesNCover" + Tests.AltCoverTests3.ParsingOpenCoverFormatGivesOpenCover, + "Tests3.ParsingOpenCoverFormatGivesOpenCover" + Tests.AltCoverTests3.ParsingMultipleReportFormatGivesFailure, + "Tests3.ParsingMultipleReportFormatGivesFailure" + Tests.AltCoverTests3.ParsingInPlaceGivesInPlace, + "Tests3.ParsingInPlaceGivesInPlace" + Tests.AltCoverTests3.ParsingMultipleInPlaceGivesFailure, + "Tests3.ParsingMultipleInPlaceGivesFailure" + Tests.AltCoverTests3.ParsingSaveGivesSave, "Tests3.ParsingSaveGivesSave" + Tests.AltCoverTests3.ParsingMultipleSaveGivesFailure, + "Tests3.ParsingMultipleSaveGivesFailure" + Tests.AltCoverTests3.ParsingSingleGivesSingle, "Tests3.ParsingSingleGivesSingle" + Tests.AltCoverTests3.ParsingMultipleSingleGivesFailure, + "Tests3.ParsingMultipleSingleGivesFailure" + Tests.AltCoverTests3.ParsingLineCoverGivesLineCover, + "Tests3.ParsingLineCoverGivesLineCover" + Tests.AltCoverTests3.OpenCoverIsCompatibleWithLineCover, + "Tests3.OpenCoverIsCompatibleWithLineCover" + Tests.AltCoverTests3.LineCoverIsCompatibleWithOpenCover, + "Tests3.LineCoverIsCompatibleWithOpenCover" + Tests.AltCoverTests3.ParsingMultipleLineCoverGivesFailure, + "Tests3.ParsingMultipleLineCoverGivesFailure" + Tests.AltCoverTests3.LineCoverIsNotCompatibleWithBranchCover, + "Tests3.LineCoverIsNotCompatibleWithBranchCover" + Tests.AltCoverTests3.ParsingBranchCoverGivesBranchCover, + "Tests3.ParsingBranchCoverGivesBranchCover" + Tests.AltCoverTests3.OpenCoverIsCompatibleWithBranchCover, + "Tests3.OpenCoverIsCompatibleWithBranchCover" + Tests.AltCoverTests3.BranchCoverIsCompatibleWithOpenCover, + "Tests3.BranchCoverIsCompatibleWithOpenCover" + Tests.AltCoverTests3.ParsingMultipleBranchCoverGivesFailure, + "Tests3.ParsingMultipleBranchCoverGivesFailure" + Tests.AltCoverTests3.BranchCoverIsNotCompatibleWithLineCover, + "Tests3.BranchCoverIsNotCompatibleWithLineCover" + Tests.AltCoverTests3.ParsingDropGivesDrop, "Tests3.ParsingDropGivesDrop" + Tests.AltCoverTests3.ParsingMultipleDropGivesFailure, + "Tests3.ParsingMultipleDropGivesFailure" + Tests.AltCoverTests3.ParsingDeferWorks, "Tests3.ParsingDeferWorks" + Tests.AltCoverTests3.ParsingMultipleDeferGivesFailure, + "Tests3.ParsingMultipleDeferGivesFailure" + Tests.AltCoverTests3.ParsingStaticGivesStatic, "Tests3.ParsingStaticGivesStatic" + Tests.AltCoverTests3.ParsingStaticPlusGivesStatic, + "Tests3.ParsingStaticPlusGivesStatic" + Tests.AltCoverTests3.ParsingStaticPlusPlusGivesStaticPlus, + "Tests3.ParsingStaticPlusPlusGivesStaticPlus" + Tests.AltCoverTests3.ParsingStaticMinusGivesNoStatic, + "Tests3.ParsingStaticMinusGivesNoStatic" + Tests.AltCoverTests3.ParsingMultipleStaticGivesFailure, + "Tests3.ParsingMultipleStaticGivesFailure" + Tests.AltCoverTests3.ParsingJunkStaticGivesFailure, + "Tests3.ParsingJunkStaticGivesFailure" + Tests.AltCoverTests3.ParsingQuietWorks, "Tests3.ParsingQuietWorks" + Tests.AltCoverTests3.ParsingMultiQuietWorks, "Tests3.ParsingMultiQuietWorks" + Tests.AltCoverTests3.ParsingBatchMultiQuietWorks, + "Tests3.ParsingBatchMultiQuietWorks" + Tests.AltCoverTests3.OutputLeftPassesThrough, "Tests3.OutputLeftPassesThrough" + Tests.AltCoverTests3.OutputInPlaceFails, "Tests3.OutputInPlaceFails" + Tests.AltCoverTests3.ScreeningFilesShouldRejectTheInstrumentedOnes, + "Tests3.ScreeningFilesShouldRejectTheInstrumentedOnes" + Tests.AltCoverTests3.OutputToNewPlaceIsOK, "Tests3.OutputToNewPlaceIsOK" + Tests.AltCoverTests3.OutputToReallyNewPlaceIsOK, + "Tests3.OutputToReallyNewPlaceIsOK" + Tests.AltCoverTests3.InPlaceToExistingPlaceFails, + "Tests3.InPlaceToExistingPlaceFails" + Tests.AltCoverTests3.InPlaceOperationIsAsExpected, + "Tests3.InPlaceOperationIsAsExpected" + Tests.AltCoverTests3.ImageLoadResilientPassesThrough, + "Tests3.ImageLoadResilientPassesThrough" + Tests.AltCoverTests3.ResilientHandlesIOException, + "Tests3.ResilientHandlesIOException" + Tests.AltCoverTests3.ResilientHandlesBadImageFormatException, + "Tests3.ResilientHandlesBadImageFormatException" + Tests.AltCoverTests3.ResilientHandlesArgumentException, + "Tests3.ResilientHandlesArgumentException" + Tests.AltCoverTests3.FolderNestingIsDetectedCorrectly, + "Tests3.FolderNestingIsDetectedCorrectly" + Tests.AltCoverTests3.PreparingNewPlaceShouldCopyEverything, + "Tests3.PreparingNewPlaceShouldCopyEverything" + Tests.AltCoverTests3.ShouldProcessTrailingArguments, + "Tests3.ShouldProcessTrailingArguments" + Tests.AltCoverTests3.StoresAsExpected, "Tests3.StoresAsExpected" + Tests.AltCoverTests3.ImportModuleIsAsExpected, "Tests3.ImportModuleIsAsExpected" + Tests.AltCoverTests3.VersionIsAsExpected, "Tests3.VersionIsAsExpected" + Tests.AltCoverTests3.TargetsPathIsAsExpected, "Tests3.TargetsPathIsAsExpected" + Tests.AltCoverTests3.UsageIsAsExpected, "Tests3.UsageIsAsExpected" + Tests.AltCoverTests3.ErrorResponseIsAsExpected, "Tests3.ErrorResponseIsAsExpected" + Tests.AltCoverTests3.LoggingCanBeExercised, "Tests3.LoggingCanBeExercised" + Tests.AltCoverTests3.EmptyInstrumentIsJustTheDefaults, + "Tests3.EmptyInstrumentIsJustTheDefaults" + Tests.AltCoverTests3.InstrumentLevelsCanBeSet, "Tests3.InstrumentLevelsCanBeSet" + Tests.AltCoverTests3.NonDefaultInstrumentObsoleteIsOK, + "Tests3.NonDefaultInstrumentObsoleteIsOK" + Tests.AltCoverTests3.NonDefaultInstrumentIsOK, "Tests3.NonDefaultInstrumentIsOK" + Tests.AltCoverTests3.EmptyCollectIsJustTheDefaults, + "Tests3.EmptyCollectIsJustTheDefaults" + Tests.AltCoverTests3.CollectLevelsCanBeSet, "Tests3.CollectLevelsCanBeSet" + Tests.AltCoverTests3.CollectWithExeIsNotCollecting, + "Tests3.CollectWithExeIsNotCollecting" + Tests.AltCoverTests3.EmptyPowerShellIsJustTheDefaults, + "Tests3.EmptyPowerShellIsJustTheDefaults" + Tests.AltCoverTests3.EmptyVersionIsJustTheDefaults, + "Tests3.EmptyVersionIsJustTheDefaults" + Tests.AltCoverTests3.EchoWorks, "Tests3.EchoWorks" + Tests.AltCoverTests3.EchoFallsSilent, "Tests3.EchoFallsSilent" + Tests.AltCoverTests3.RunSettingsFailsIfCollectorNotFound, + "Tests3.RunSettingsFailsIfCollectorNotFound" + Tests.AltCoverTests3.RunSettingsWorksIfOK, "Tests3.RunSettingsWorksIfOK" + Tests.AltCoverTests3.RunSettingsExtendsOK, "Tests3.RunSettingsExtendsOK" + Tests.AltCoverTests3.RunSettingsRecoversOK, "Tests3.RunSettingsRecoversOK" + Tests.AltCoverTests3.RunSettingsThrowsIfUninitialized, + "Tests3.RunSettingsThrowsIfUninitialized" + Tests.AltCoverTests3.ContingentCopyTest, "Tests3.ContingentCopyTest" + Tests.AltCoverTests3.RetryDeleteTest, "Tests3.RetryDeleteTest" + Tests.AltCoverXTests.CollectOptionsCanBeValidated, + "XTests.CollectOptionsCanBeValidated" + Tests.AltCoverXTests.TypeSafeEmptyThresholdCanBeValidated, + "XTests.TypeSafeEmptyThresholdCanBeValidated" + Tests.AltCoverXTests.TypeSafeCollectOptionsCanBeValidated, + "XTests.TypeSafeCollectOptionsCanBeValidated" + Tests.AltCoverXTests.TypeSafeCollectSummaryCanBeValidated, + "XTests.TypeSafeCollectSummaryCanBeValidated" + Tests.AltCoverXTests.CollectOptionsCanBeValidatedWithErrors, + "XTests.CollectOptionsCanBeValidatedWithErrors" + Tests.AltCoverXTests.TypeSafeCollectOptionsCanBeValidatedWithErrors, + "XTests.TypeSafeCollectOptionsCanBeValidatedWithErrors" + Tests.AltCoverXTests.CollectOptionsCanBePositivelyValidatedWithErrors, + "XTests.CollectOptionsCanBePositivelyValidatedWithErrors" + Tests.AltCoverXTests.TypeSafeCollectOptionsCanBePositivelyValidatedWithErrors, + "XTests.TypeSafeCollectOptionsCanBePositivelyValidatedWithErrors" + Tests.AltCoverXTests.PrepareOptionsCanBeValidated, + "XTests.PrepareOptionsCanBeValidated" + Tests.AltCoverXTests.TypeSafePrepareOptionsCanBeValidated, + "XTests.TypeSafePrepareOptionsCanBeValidated" + Tests.AltCoverXTests.TypeSafePrepareOptionsCanBeValidatedAgain, + "XTests.TypeSafePrepareOptionsCanBeValidatedAgain" + Tests.AltCoverXTests.PrepareOptionsStrongNamesCanBeValidated, + "XTests.PrepareOptionsStrongNamesCanBeValidated" + Tests.AltCoverXTests.TypeSafePrepareOptionsStrongNamesCanBeValidated, + "XTests.TypeSafePrepareOptionsStrongNamesCanBeValidated" + Tests.AltCoverXTests.PrepareOptionsCanBeValidatedWithNulls, + "XTests.PrepareOptionsCanBeValidatedWithNulls" + Tests.AltCoverXTests.PrepareOptionsCanBeValidatedAndDetectInconsistency, + "XTests.PrepareOptionsCanBeValidatedAndDetectInconsistency" + Tests.AltCoverXTests.TypeSafePrepareStaticCanBeValidated, + "XTests.TypeSafePrepareStaticCanBeValidated" + Tests.AltCoverXTests.TypeSafePrepareOptionsCanBeValidatedAndDetectInconsistency, + "XTests.TypeSafePrepareOptionsCanBeValidatedAndDetectInconsistency" + Tests.AltCoverXTests.PrepareOptionsCanBeValidatedWithErrors, + "XTests.PrepareOptionsCanBeValidatedWithErrors" + Tests.AltCoverXTests.NullListsAreEmpty, "XTests.NullListsAreEmpty" + Tests.AltCoverXTests.ValidateAssemblyOption, "XTests.ValidateAssemblyOption" + Tests.AltCoverXTests.ADotNetDryRunLooksAsExpected, + "XTests.ADotNetDryRunLooksAsExpected" + Tests.AltCoverXTests.ADryRunLooksAsExpected, "XTests.ADryRunLooksAsExpected" + Tests.AltCoverXTests.AfterAssemblyCommitsThatAssembly, + "XTests.AfterAssemblyCommitsThatAssembly" + Tests.AltCoverXTests.AfterAssemblyCommitsThatAssemblyForMono, + "XTests.AfterAssemblyCommitsThatAssemblyForMono" + Tests.AltCoverXTests.FinishCommitsTheRecordingAssembly, + "XTests.FinishCommitsTheRecordingAssembly" + Tests.AltCoverXTests.FinishCommitsTheAsyncRecordingAssembly, + "XTests.FinishCommitsTheAsyncRecordingAssembly" + Tests.AltCoverXTests.ShouldDoCoverage, "XTests.ShouldDoCoverage" + Tests.AltCoverXTests.ShouldGenerateExpectedXmlReportFromMono, + "XTests.ShouldGenerateExpectedXmlReportFromMono" + Tests.AltCoverXTests.ShouldGenerateExpectedXmlReportFromMonoOpenCoverStyle, + "XTests.ShouldGenerateExpectedXmlReportFromMonoOpenCoverStyle" |] + |> Array.toList #if !EXPECTO_MAIN let consistencyCheck specials = ExpectoTestCommon.consistencyCheck (simpleTests ()) specials //["Tests.AltCoverTests2::ShouldUpdateHandlerOK"] -#endif -#endif // remove for fantomas \ No newline at end of file +#endif \ No newline at end of file diff --git a/AltCover.Tests/OpenCoverForPester.coverlet.xml b/AltCover.Tests/OpenCoverForPester.coverlet.xml index b4bc2ed90..abbaeb39a 100644 --- a/AltCover.Tests/OpenCoverForPester.coverlet.xml +++ b/AltCover.Tests/OpenCoverForPester.coverlet.xml @@ -175,12 +175,12 @@ - - - - - - + + + + + + diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index df7ecb83a..010b8b554 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -59,9 +59,7 @@ module AltCoverRunnerTests = [] let ShouldFailXmlDataForNativeJson () = Assert.Throws - (fun () -> - ignore (ReportFormat.NativeJson - |> Counter.I.xmlByFormat)) + (fun () -> ignore (ReportFormat.NativeJson |> Counter.I.xmlByFormat)) |> ignore [] @@ -230,10 +228,10 @@ module AltCoverRunnerTests = let payload = Dictionary() [ 0 .. 9 ] - |> Seq.iter (fun i -> payload.[10 - i] <- init(int64 (i + 1)) []) + |> Seq.iter (fun i -> payload.[10 - i] <- init (int64 (i + 1)) []) [ 11 .. 12 ] - |> Seq.iter (fun i -> payload.[i ||| Counter.branchFlag] <- init(int64 (i - 10)) []) + |> Seq.iter (fun i -> payload.[i ||| Counter.branchFlag] <- init (int64 (i - 10)) []) let item = Dictionary>() @@ -324,7 +322,7 @@ module AltCoverRunnerTests = let payload = Dictionary() [ 0 .. 9 ] - |> Seq.iter (fun i -> payload.[i] <- init(int64 (i + 1)) []) + |> Seq.iter (fun i -> payload.[i] <- init (int64 (i + 1)) []) visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload @@ -426,7 +424,7 @@ module AltCoverRunnerTests = let payload = Dictionary() [ 0 .. 9 ] - |> Seq.iter (fun i -> payload.[i] <- init(int64 (i + 1)) []) + |> Seq.iter (fun i -> payload.[i] <- init (int64 (i + 1)) []) visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload @@ -551,12 +549,21 @@ module AltCoverRunnerTests = [] let OpenCoverShouldGeneratePlausibleJson () = - let dummy = SortedDictionary() + let dummy = + SortedDictionary() + dummy.Add("\"\\\b\f\n\r\tA<>\u2012", SortedDictionary()) - let escaped = NativeJson.toText(dummy).Replace("\r", String.Empty) - .Replace("\n", String.Empty) - let expectedEscapes = """{ "\"\\\b\f\n\r\tA\u003C\u003E\u2012": { }}""" - Assert.That (escaped, Is.EqualTo expectedEscapes) + + let escaped = + NativeJson + .toText(dummy) + .Replace("\r", String.Empty) + .Replace("\n", String.Empty) + + let expectedEscapes = + """{ "\"\\\b\f\n\r\tA\u003C\u003E\u2012": { }}""" + + Assert.That(escaped, Is.EqualTo expectedEscapes) test <@ escaped = expectedEscapes @> Runner.init () @@ -927,8 +934,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(x, Is.EqualTo "UsageError") - Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) [] let ParsingJunkAfterSeparatorIsExpected () = @@ -945,8 +952,8 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(x, Is.EquivalentTo(input |> Seq.skip 1)) - Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EquivalentTo(input |> Seq.skip 1)) + Assert.That(y, Is.SameAs options) [] let ParsingHelpGivesHelp () = @@ -962,8 +969,8 @@ module AltCoverRunnerTests = match CommandLine.processHelpOption parse with | Left (x, y) -> - Assert.That(x, Is.EqualTo "HelpText") - Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "HelpText") + Assert.That(y, Is.SameAs options) // a "not sticky" test lock Runner.executable @@ -971,10 +978,11 @@ module AltCoverRunnerTests = Runner.executable.Value <- None match CommandLine.parseCommandLine [| "/x"; "x" |] options - |> CommandLine.processHelpOption with + |> CommandLine.processHelpOption + with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty)) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty)) [] let ParsingErrorHelpGivesHelp () = @@ -990,13 +998,13 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(x, Is.EqualTo "UsageError") - Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) match CommandLine.processHelpOption parse with | Left (x, y) -> - Assert.That(x, Is.EqualTo "UsageError") - Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) // a "not sticky" test lock Runner.executable @@ -1004,10 +1012,11 @@ module AltCoverRunnerTests = Runner.executable.Value <- None match CommandLine.parseCommandLine [| "/x"; "x" |] options - |> CommandLine.processHelpOption with + |> CommandLine.processHelpOption + with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty)) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty)) [] let ParsingExeGivesExe () = @@ -1027,8 +1036,8 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match Runner.executable.Value with | Some x -> Assert.That(Path.GetFileName x, Is.EqualTo unique) @@ -1058,13 +1067,13 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--executable : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--executable : specify this only once" + ) finally Runner.executable.Value <- None) @@ -1086,8 +1095,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.executable.Value <- None) @@ -1106,11 +1115,11 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match Runner.workingDirectory with - | Some x -> Assert.That(x, Is.EqualTo (canonicalDirectory unique)) + | Some x -> Assert.That(x, Is.EqualTo(canonicalDirectory unique)) finally Runner.workingDirectory <- None @@ -1133,13 +1142,13 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--workingDirectory : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--workingDirectory : specify this only once" + ) finally Runner.workingDirectory <- None @@ -1161,8 +1170,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.workingDirectory <- None @@ -1180,8 +1189,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.workingDirectory <- None @@ -1200,11 +1209,11 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match Runner.recordingDirectory with - | Some x -> Assert.That(x, Is.EqualTo (canonicalDirectory unique)) + | Some x -> Assert.That(x, Is.EqualTo(canonicalDirectory unique)) finally Runner.recordingDirectory <- None @@ -1227,13 +1236,13 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--recorderDirectory : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--recorderDirectory : specify this only once" + ) finally Runner.recordingDirectory <- None @@ -1255,8 +1264,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.recordingDirectory <- None @@ -1274,8 +1283,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.recordingDirectory <- None @@ -1293,8 +1302,8 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(Runner.collect.Value, Is.True) finally @@ -1314,13 +1323,13 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--collect : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--collect : specify this only once" + ) finally Runner.collect.Value <- false @@ -1344,8 +1353,8 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match LCov.path.Value with | Some x -> Assert.That(Path.GetFileName x, Is.EqualTo unique) @@ -1380,13 +1389,13 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--lcovReport : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--lcovReport : specify this only once" + ) finally Runner.I.initSummary () LCov.path.Value <- None) @@ -1411,8 +1420,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.I.initSummary () LCov.path.Value <- None) @@ -1431,21 +1440,21 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match Runner.threshold with | Some x -> - Assert.That( - x, - Is.EqualTo - { Statements = 57uy - Branches = 0uy - Methods = 0uy - Crap = 0uy - AltMethods = 0uy - AltCrap = 0uy } - ) + Assert.That( + x, + Is.EqualTo + { Statements = 57uy + Branches = 0uy + Methods = 0uy + Crap = 0uy + AltMethods = 0uy + AltCrap = 0uy } + ) finally Runner.threshold <- None @@ -1463,21 +1472,21 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match Runner.threshold with | Some x -> - Assert.That( - x, - Is.EqualTo - { Statements = 16uy - Branches = 7uy - Methods = 57uy - Crap = 42uy - AltMethods = 14uy - AltCrap = 101uy } - ) + Assert.That( + x, + Is.EqualTo + { Statements = 16uy + Branches = 7uy + Methods = 57uy + Crap = 42uy + AltMethods = 14uy + AltCrap = 101uy } + ) finally Runner.threshold <- None @@ -1495,21 +1504,21 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match Runner.threshold with | Some x -> - Assert.That( - x, - Is.EqualTo - { Statements = 100uy - Branches = 100uy - Methods = 100uy - Crap = 255uy - AltMethods = 100uy - AltCrap = 255uy } - ) + Assert.That( + x, + Is.EqualTo + { Statements = 100uy + Branches = 100uy + Methods = 100uy + Crap = 255uy + AltMethods = 100uy + AltCrap = 255uy } + ) finally Runner.threshold <- None @@ -1527,21 +1536,21 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match Runner.threshold with | Some x -> - Assert.That( - x, - Is.EqualTo - { Statements = 0uy - Branches = 0uy - Methods = 0uy - Crap = 0uy - AltMethods = 0uy - AltCrap = 0uy } - ) + Assert.That( + x, + Is.EqualTo + { Statements = 0uy + Branches = 0uy + Methods = 0uy + Crap = 0uy + AltMethods = 0uy + AltCrap = 0uy } + ) finally Runner.threshold <- None @@ -1559,13 +1568,13 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--threshold : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--threshold : specify this only once" + ) finally Runner.threshold <- None @@ -1583,8 +1592,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.threshold <- None @@ -1602,8 +1611,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.threshold <- None @@ -1621,8 +1630,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.threshold <- None @@ -1640,8 +1649,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.threshold <- None @@ -1659,8 +1668,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.threshold <- None @@ -1678,8 +1687,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.threshold <- None @@ -1697,8 +1706,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.threshold <- None @@ -1716,8 +1725,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.threshold <- None @@ -1735,8 +1744,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.threshold <- None @@ -1760,8 +1769,8 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match Cobertura.path.Value with | Some x -> Assert.That(Path.GetFileName x, Is.EqualTo unique) @@ -1796,13 +1805,13 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--cobertura : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--cobertura : specify this only once" + ) finally Runner.I.initSummary () Cobertura.path.Value <- None) @@ -1827,8 +1836,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.I.initSummary () Cobertura.path.Value <- None) @@ -1848,8 +1857,8 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match Runner.output with | Some x -> Assert.That(Path.GetFileName x, Is.EqualTo unique) @@ -1878,13 +1887,13 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--outputFile : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--outputFile : specify this only once" + ) finally Runner.output <- None @@ -1903,8 +1912,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.output <- None @@ -1922,8 +1931,8 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CommandLine.dropReturnCode.Value, Is.True) finally @@ -1946,13 +1955,13 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--dropReturnCode : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--dropReturnCode : specify this only once" + ) finally CommandLine.dropReturnCode.Value <- false @@ -2015,8 +2024,8 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match Runner.summaryFormat with | x when v = x -> ())) @@ -2037,13 +2046,13 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--summary : specify this only once" - )) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--summary : specify this only once" + )) [] let ParsingBadTCGivesFailure () = @@ -2062,8 +2071,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError")) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError")) [] let ParsingQuietWorks () = @@ -2078,8 +2087,8 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CommandLine.verbosity, Is.EqualTo 1) finally @@ -2098,8 +2107,8 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CommandLine.verbosity, Is.EqualTo 3) finally @@ -2118,8 +2127,8 @@ module AltCoverRunnerTests = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CommandLine.verbosity, Is.EqualTo 2) finally @@ -2139,8 +2148,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.executable.Value <- None) @@ -2160,9 +2169,9 @@ module AltCoverRunnerTests = match parse with | Right (x :: y, z) -> - Assert.That(z, Is.SameAs options) - Assert.That(x, Is.EqualTo "xxx") - Assert.That(y, Is.EquivalentTo [ "b" ]) + Assert.That(z, Is.SameAs options) + Assert.That(x, Is.EqualTo "xxx") + Assert.That(y, Is.EquivalentTo [ "b" ]) finally Runner.executable.Value <- None) @@ -2206,8 +2215,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.collect.Value <- false Runner.executable.Value <- None) @@ -2224,8 +2233,8 @@ module AltCoverRunnerTests = match parse with | Right _ -> - Assert.That(parse, Is.SameAs input) - Assert.That(Option.isSome Runner.workingDirectory) + Assert.That(parse, Is.SameAs input) + Assert.That(Option.isSome Runner.workingDirectory) finally Runner.workingDirectory <- None @@ -2241,8 +2250,8 @@ module AltCoverRunnerTests = match parse with | Right _ -> - Assert.That(parse, Is.SameAs input) - Assert.That(Runner.workingDirectory, Is.EqualTo(Some "ShouldAcceptWorker")) + Assert.That(parse, Is.SameAs input) + Assert.That(Runner.workingDirectory, Is.EqualTo(Some "ShouldAcceptWorker")) finally Runner.workingDirectory <- None @@ -2258,8 +2267,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.recordingDirectory <- None @@ -2278,8 +2287,8 @@ module AltCoverRunnerTests = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Runner.recordingDirectory <- None @@ -2307,7 +2316,10 @@ module AltCoverRunnerTests = Assembly .GetExecutingAssembly() .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("AltCover.Recorder.net20.dll", StringComparison.Ordinal)) + |> Seq.find + (fun n -> + n.EndsWith("AltCover.Recorder.net20.dll", StringComparison.Ordinal)) + use frombytes = Assembly .GetExecutingAssembly() @@ -2551,7 +2563,10 @@ module AltCoverRunnerTests = Assembly .GetExecutingAssembly() .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("AltCover.Recorder.net20.dll", StringComparison.Ordinal)) + |> Seq.find + (fun n -> + n.EndsWith("AltCover.Recorder.net20.dll", StringComparison.Ordinal)) + use frombytes = Assembly .GetExecutingAssembly() @@ -3443,51 +3458,51 @@ module AltCoverRunnerTests = match y with | Null -> formatter.Write(Tag.Null |> byte) | Time t -> - formatter.Write(Tag.Time |> byte) - formatter.Write(t) + formatter.Write(Tag.Time |> byte) + formatter.Write(t) | Call t -> - formatter.Write(Tag.Call |> byte) - formatter.Write(t) + formatter.Write(Tag.Call |> byte) + formatter.Write(t) | Both b -> - formatter.Write(Tag.Both |> byte) - formatter.Write(b.Time) - formatter.Write(b.Call) + formatter.Write(Tag.Both |> byte) + formatter.Write(b.Time) + formatter.Write(b.Call) | Table t -> - formatter.Write(Tag.Table |> byte) - - t.Keys - |> Seq.iter - (fun m -> - formatter.Write m - formatter.Write t.[m].Keys.Count - - t.[m].Keys - |> Seq.iter - (fun p -> - formatter.Write p - let v = t.[m].[p] - formatter.Write v.Count - - v.Tracks - |> Seq.iter - (fun tx -> - match tx with - | Time t -> - formatter.Write(Tag.Time |> byte) - formatter.Write(t) - | Call t -> - formatter.Write(Tag.Call |> byte) - formatter.Write(t) - | Both b -> - formatter.Write(Tag.Both |> byte) - formatter.Write(b.Time) - formatter.Write(b.Call) - //| _ -> tx |> (sprintf "%A") |> Assert.Fail - ) - - formatter.Write(Tag.Null |> byte))) - - formatter.Write String.Empty + formatter.Write(Tag.Table |> byte) + + t.Keys + |> Seq.iter + (fun m -> + formatter.Write m + formatter.Write t.[m].Keys.Count + + t.[m].Keys + |> Seq.iter + (fun p -> + formatter.Write p + let v = t.[m].[p] + formatter.Write v.Count + + v.Tracks + |> Seq.iter + (fun tx -> + match tx with + | Time t -> + formatter.Write(Tag.Time |> byte) + formatter.Write(t) + | Call t -> + formatter.Write(Tag.Call |> byte) + formatter.Write(t) + | Both b -> + formatter.Write(Tag.Both |> byte) + formatter.Write(b.Time) + formatter.Write(b.Call) + //| _ -> tx |> (sprintf "%A") |> Assert.Fail + ) + + formatter.Write(Tag.Null |> byte))) + + formatter.Write String.Empty x) |> List.length) @@ -3561,10 +3576,12 @@ module AltCoverRunnerTests = [] let PostprocessShouldHandleNullCase () = - let minimal = """ + let minimal = + """ """ + let after = XmlDocument() use reader = new StringReader(minimal) after.Load(reader) @@ -3588,7 +3605,8 @@ module AltCoverRunnerTests = [] let PostprocessShouldHandleEntryAndExitTimes () = - let minimal = """ + let minimal = + """ @@ -3606,6 +3624,7 @@ module AltCoverRunnerTests = """ + let after = XmlDocument() use reader = new StringReader(minimal) after.Load(reader) @@ -3639,7 +3658,8 @@ module AltCoverRunnerTests = let processed = after.DocumentElement.OuterXml.Replace("\r\n", "\n") - let expected = """ + let expected = + """ @@ -4951,7 +4971,8 @@ module AltCoverRunnerTests = Path.Combine( Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName, - Guid.NewGuid().ToString() + "/OpenCoverWithPartials.lcov" + Guid.NewGuid().ToString() + + "/OpenCoverWithPartials.lcov" ) LCov.path.Value <- Some unique @@ -4975,7 +4996,8 @@ module AltCoverRunnerTests = Assembly .GetExecutingAssembly() .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("OpenCoverWithPartials.lcov", StringComparison.Ordinal)) + |> Seq.find + (fun n -> n.EndsWith("OpenCoverWithPartials.lcov", StringComparison.Ordinal)) use stream2 = Assembly @@ -5073,7 +5095,8 @@ module AltCoverRunnerTests = Assembly .GetExecutingAssembly() .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("NCoverWithPartials.xml", StringComparison.Ordinal)) + |> Seq.find + (fun n -> n.EndsWith("NCoverWithPartials.xml", StringComparison.Ordinal)) use stream = Assembly @@ -5108,7 +5131,8 @@ module AltCoverRunnerTests = Assembly .GetExecutingAssembly() .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("NCoverWithPartials.lcov", StringComparison.Ordinal)) + |> Seq.find + (fun n -> n.EndsWith("NCoverWithPartials.lcov", StringComparison.Ordinal)) use stream2 = Assembly @@ -5443,14 +5467,14 @@ module AltCoverRunnerTests = (f, ms |> Seq.map - (fun (m,l) -> + (fun (m, l) -> m .ToString() .Replace("\r", String.Empty) .Replace("\n", String.Empty) .Replace(" <", "<") - + "|" + String.Join("|", l |> Seq.map string) - ) + + "|" + + String.Join("|", l |> Seq.map string)) |> Seq.toList)) |> Seq.toList @@ -5486,7 +5510,7 @@ module AltCoverRunnerTests = schemas let private validate result = - let schema = loadSchema() + let schema = loadSchema () let xmlDocument = XmlDocument() xmlDocument.LoadXml(result) xmlDocument.Schemas <- schema @@ -5561,9 +5585,11 @@ module AltCoverRunnerTests = let result = Regex - .Replace(File.ReadAllText unique, - """timestamp=\"\d*\">""", - """timestamp="xx">""") + .Replace( + File.ReadAllText unique, + """timestamp=\"\d*\">""", + """timestamp="xx">""" + ) .Replace("\\", "/") //printfn "%s" result let resource2 = @@ -5605,7 +5631,8 @@ module AltCoverRunnerTests = Assembly .GetExecutingAssembly() .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("NCoverWithPartials.xml", StringComparison.Ordinal)) + |> Seq.find + (fun n -> n.EndsWith("NCoverWithPartials.xml", StringComparison.Ordinal)) use stream = Assembly @@ -5618,7 +5645,8 @@ module AltCoverRunnerTests = Path.Combine( Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName, - Guid.NewGuid().ToString() + "/NCoverWithPartials.cobertura" + Guid.NewGuid().ToString() + + "/NCoverWithPartials.cobertura" ) Cobertura.path.Value <- Some unique @@ -5639,16 +5667,19 @@ module AltCoverRunnerTests = let result = Regex - .Replace(File.ReadAllText unique, - """timestamp=\"\d*\">""", - """timestamp="xx">""") + .Replace( + File.ReadAllText unique, + """timestamp=\"\d*\">""", + """timestamp="xx">""" + ) .Replace("\\", "/") //printfn "%s" result let resource2 = Assembly .GetExecutingAssembly() .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("NCoverWithPartials.cob.xml", StringComparison.Ordinal)) + |> Seq.find + (fun n -> n.EndsWith("NCoverWithPartials.cob.xml", StringComparison.Ordinal)) use stream2 = Assembly @@ -5718,9 +5749,11 @@ module AltCoverRunnerTests = let result = Regex - .Replace(File.ReadAllText unique, - """timestamp=\"\d*\">""", - """timestamp="xx">""") + .Replace( + File.ReadAllText unique, + """timestamp=\"\d*\">""", + """timestamp="xx">""" + ) .Replace("\\", "/") //printfn "%s" result let resource2 = @@ -5801,9 +5834,11 @@ module AltCoverRunnerTests = let result = Regex - .Replace(File.ReadAllText unique, - """timestamp=\"\d*\">""", - """timestamp="xx">""") + .Replace( + File.ReadAllText unique, + """timestamp=\"\d*\">""", + """timestamp="xx">""" + ) .Replace("\\", "/") //printfn "%s" result let resource2 = @@ -5847,8 +5882,7 @@ module AltCoverRunnerTests = Assembly .GetExecutingAssembly() .GetManifestResourceNames() - |> Seq.find - (fun n -> n.EndsWith("JsonWithPartials.json", StringComparison.Ordinal)) + |> Seq.find (fun n -> n.EndsWith("JsonWithPartials.json", StringComparison.Ordinal)) use stream = Assembly @@ -5885,9 +5919,11 @@ module AltCoverRunnerTests = let result = Regex - .Replace(File.ReadAllText unique, - """timestamp=\"\d*\">""", - """timestamp="xx">""") + .Replace( + File.ReadAllText unique, + """timestamp=\"\d*\">""", + """timestamp="xx">""" + ) .Replace("\\", "/") //printfn "%s" result let resource2 = @@ -5919,13 +5955,16 @@ module AltCoverRunnerTests = ) .Replace( // different computations TODO!! """complexity="2.2""", - """complexity="1.8""") + """complexity="1.8""" + ) .Replace( // different computations TODO!! """complexity="2""", - """complexity="1""") + """complexity="1""" + ) .Replace( // different computations TODO!! """.cpp" line-rate="0.78" branch-rate="0""", - """.cpp" line-rate="0.78" branch-rate="1""") + """.cpp" line-rate="0.78" branch-rate="1""" + ) Assert.That(result.Replace("\r", String.Empty), Is.EqualTo expected, result) validate result @@ -5977,9 +6016,11 @@ module AltCoverRunnerTests = let result = Regex - .Replace(File.ReadAllText unique, - """timestamp=\"\d*\">""", - """timestamp="xx">""") + .Replace( + File.ReadAllText unique, + """timestamp=\"\d*\">""", + """timestamp="xx">""" + ) .Replace("\\", "/") //printfn "%s" result let resource2 = @@ -6057,7 +6098,8 @@ module AltCoverRunnerTests = Assembly .GetExecutingAssembly() .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("Sample5.raw-native.xml", StringComparison.Ordinal)) + |> Seq.find + (fun n -> n.EndsWith("Sample5.raw-native.xml", StringComparison.Ordinal)) use stream2 = Assembly @@ -6120,7 +6162,8 @@ module AltCoverRunnerTests = Path.Combine( Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName, - Guid.NewGuid().ToString() + "/JsonWithPartialsToRawXml.xml" + Guid.NewGuid().ToString() + + "/JsonWithPartialsToRawXml.xml" ) unique @@ -6135,7 +6178,8 @@ module AltCoverRunnerTests = Assembly .GetExecutingAssembly() .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("JsonWithPartialsToRawXml.xml", StringComparison.Ordinal)) + |> Seq.find + (fun n -> n.EndsWith("JsonWithPartialsToRawXml.xml", StringComparison.Ordinal)) use stream2 = Assembly @@ -6217,9 +6261,11 @@ module AltCoverRunnerTests = let result = Regex - .Replace(File.ReadAllText unique, - """timestamp=\"\d*\">""", - """timestamp="xx">""") + .Replace( + File.ReadAllText unique, + """timestamp=\"\d*\">""", + """timestamp="xx">""" + ) .Replace("\\", "/") let resource2 = @@ -6344,7 +6390,8 @@ module AltCoverRunnerTests = Assembly .GetExecutingAssembly() .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("OpenCoverWithPartials.xml", StringComparison.Ordinal)) + |> Seq.find + (fun n -> n.EndsWith("OpenCoverWithPartials.xml", StringComparison.Ordinal)) use stream = Assembly @@ -6357,7 +6404,8 @@ module AltCoverRunnerTests = Path.Combine( Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName, - Guid.NewGuid().ToString() + "/OpenCoverWithPartials.cobertura" + Guid.NewGuid().ToString() + + "/OpenCoverWithPartials.cobertura" ) Cobertura.path.Value <- Some unique @@ -6384,7 +6432,9 @@ module AltCoverRunnerTests = Assembly .GetExecutingAssembly() .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("OpenCoverWithPartials.cob.xml", StringComparison.Ordinal)) + |> Seq.find + (fun n -> + n.EndsWith("OpenCoverWithPartials.cob.xml", StringComparison.Ordinal)) use stream2 = Assembly @@ -6452,5 +6502,5 @@ module AltCoverRunnerTests = [] let TryGetValueHandlesNull () = Runner.init () - let dict : Dictionary = null + let dict: Dictionary = null Assert.That(PostProcess.tryGetValue dict 0 |> fst, Is.False) \ No newline at end of file diff --git a/AltCover.Tests/Sample31.dll b/AltCover.Tests/Sample31.dll new file mode 100644 index 000000000..ce7ad5fc0 Binary files /dev/null and b/AltCover.Tests/Sample31.dll differ diff --git a/AltCover.Tests/Sample31.dll.mdb b/AltCover.Tests/Sample31.dll.mdb new file mode 100644 index 000000000..dd623029f Binary files /dev/null and b/AltCover.Tests/Sample31.dll.mdb differ diff --git a/AltCover.Tests/Tests.fs b/AltCover.Tests/Tests.fs index 9436f1abd..c13662f48 100644 --- a/AltCover.Tests/Tests.fs +++ b/AltCover.Tests/Tests.fs @@ -17,6 +17,13 @@ open N #nowarn "25" +[] +module Extra = + type Hallmark with + static member internal Build() = + { Assembly = String.Empty + Configuration = String.Empty } + [] type ProxyObject() = inherit MarshalByRefObject() @@ -140,10 +147,8 @@ module AltCoverTests = [] let ShouldGetPdbFromImage () = let files = - [ - Directory.GetFiles(dir, "AltCover*") - Directory.GetFiles(dir, "Sample*") - ] + [ Directory.GetFiles(dir, "AltCover*") + Directory.GetFiles(dir, "Sample*") ] |> Seq.concat |> Seq.filter (fun x -> @@ -165,19 +170,21 @@ module AltCoverTests = |> Seq.iter (fun x -> let f = fst x + match snd x with // Case of true - | None -> Assert.That(f |> Path.GetFileName, Is.EqualTo "Sample2.dll", f) + //| None -> Assert.That(f |> Path.GetFileName, Is.EqualTo "Sample2.dll", f) | Some name -> - let probe = Path.ChangeExtension(f, ".pdb") - let file = FileInfo(probe) - let filename = file.Name.Replace("\\", "/") - - Assert.That( - "/" + name.Replace("\\", "/"), - Does.EndWith("/" + filename), - (fst x) + " -> " + name - )) + //Assert.That(f |> Path.GetFileName, Is.Not.EqualTo "Sample2.dll", f) + let probe = Path.ChangeExtension(f, ".pdb") + let file = FileInfo(probe) + let filename = file.Name.Replace("\\", "/") + + Assert.That( + "/" + name.Replace("\\", "/"), + Does.EndWith("/" + filename), + (fst x) + " -> " + name + )) [] let ShouldGetEmbeddedPdbFromImage () = @@ -243,21 +250,21 @@ module AltCoverTests = match pdb with | None -> - Assert.That( - File.Exists(Path.ChangeExtension(x, ".pdb")), - Is.Not.True, - "No .pdb for " + x - ) + Assert.That( + File.Exists(Path.ChangeExtension(x, ".pdb")), + Is.Not.True, + "No .pdb for " + x + ) | Some name -> - let probe = Path.ChangeExtension(x, ".pdb") - let file = FileInfo(probe) - let filename = file.Name.Replace("\\", "/") - - Assert.That( - "/" + name.Replace("\\", "/"), - Does.EndWith("/" + filename), - x + " -> " + name - )) + let probe = Path.ChangeExtension(x, ".pdb") + let file = FileInfo(probe) + let filename = file.Name.Replace("\\", "/") + + Assert.That( + "/" + name.Replace("\\", "/"), + Does.EndWith("/" + filename), + x + " -> " + name + )) [] let ShouldGetForeignPdbWithFallback () = @@ -284,7 +291,8 @@ module AltCoverTests = match pdb with | Some name -> Assert.That(name, Is.EqualTo normalized) - with :? BadImageFormatException -> ()) + with + | :? BadImageFormatException -> ()) [] let ShouldGetForeignPdbWithFallbackWhenNotColocated () = @@ -329,10 +337,11 @@ module AltCoverTests = match pdb with | Some name -> - Assert.That(name, Is.EqualTo normalized) - AltCover.ProgramDatabase.readSymbols def - Assert.That(def.MainModule.HasSymbols, def.MainModule.FileName) - with :? BadImageFormatException -> ()) + Assert.That(name, Is.EqualTo normalized) + AltCover.ProgramDatabase.readSymbols def + Assert.That(def.MainModule.HasSymbols, def.MainModule.FileName) + with + | :? BadImageFormatException -> ()) finally ProgramDatabase.symbolFolders.Clear() @@ -358,15 +367,15 @@ module AltCoverTests = match mdb with // | None -> Assert.That(File.Exists(x + ".mdb"), Is.Not.True, "No .mdb for " + x) | Some name -> - let probe = x + ".mdb" - let file = FileInfo(probe) - let filename = file.Name.Replace("\\", "/") - - Assert.That( - name.Replace("\\", "/") + ".mdb", - Does.EndWith("/" + filename), - x + " -> " + name - )) + let probe = x + ".mdb" + let file = FileInfo(probe) + let filename = file.Name.Replace("\\", "/") + + Assert.That( + name.Replace("\\", "/") + ".mdb", + Does.EndWith("/" + filename), + x + " -> " + name + )) [] let ShouldGetSymbolsFromPdb () = @@ -468,64 +477,85 @@ module AltCoverTests = // Filter.fs [] let NoneOfTheAboveMatchesNoType () = - Assert.That(Filter.``match`` () (ff(FilterScope.Type, Regex "23", Exclude)), Is.False) - Assert.That(Filter.``match`` () (ff(FilterScope.Type, Regex "23", Include)), Is.False) + Assert.That( + Filter.``match`` () (ff (FilterScope.Type, Regex "23", Exclude)), + Is.False + ) + + Assert.That( + Filter.``match`` () (ff (FilterScope.Type, Regex "23", Include)), + Is.False + ) [] let NoneOfTheAboveMatchesNoAttribute () = Assert.That( - Filter.``match`` () (ff(FilterScope.Attribute, Regex "23", Exclude)), + Filter.``match`` () (ff (FilterScope.Attribute, Regex "23", Exclude)), Is.False ) Assert.That( - Filter.``match`` () (ff(FilterScope.Attribute, Regex "23", Include)), + Filter.``match`` () (ff (FilterScope.Attribute, Regex "23", Include)), Is.False ) [] let NoneOfTheAboveMatchesNoAssembly () = Assert.That( - Filter.``match`` () (ff(FilterScope.Assembly, Regex "23", Exclude)), + Filter.``match`` () (ff (FilterScope.Assembly, Regex "23", Exclude)), Is.False ) Assert.That( - Filter.``match`` () (ff(FilterScope.Assembly, Regex "23", Include)), + Filter.``match`` () (ff (FilterScope.Assembly, Regex "23", Include)), Is.False ) [] let NoneOfTheAboveMatchesNoModule () = Assert.That( - Filter.``match`` () (ff(FilterScope.Module, Regex "23", Exclude)), + Filter.``match`` () (ff (FilterScope.Module, Regex "23", Exclude)), Is.False ) Assert.That( - Filter.``match`` () (ff(FilterScope.Module, Regex "23", Include)), + Filter.``match`` () (ff (FilterScope.Module, Regex "23", Include)), Is.False ) [] let NoneOfTheAboveMatchesNoFile () = - Assert.That(Filter.``match`` () (ff(FilterScope.File, Regex "23", Exclude)), Is.False) - Assert.That(Filter.``match`` () (ff(FilterScope.File, Regex "23", Include)), Is.False) + Assert.That( + Filter.``match`` () (ff (FilterScope.File, Regex "23", Exclude)), + Is.False + ) + + Assert.That( + Filter.``match`` () (ff (FilterScope.File, Regex "23", Include)), + Is.False + ) [] let NoneOfTheAboveMatchesNoPath () = - Assert.That(Filter.``match`` () (ff(FilterScope.Path, Regex "23", Exclude)), Is.False) - Assert.That(Filter.``match`` () (ff(FilterScope.Path, Regex "23", Include)), Is.False) + Assert.That( + Filter.``match`` () (ff (FilterScope.Path, Regex "23", Exclude)), + Is.False + ) + + Assert.That( + Filter.``match`` () (ff (FilterScope.Path, Regex "23", Include)), + Is.False + ) [] let NoneOfTheAboveMatchesNoMethod () = Assert.That( - Filter.``match`` () (ff(FilterScope.Method, Regex "23", Exclude)), + Filter.``match`` () (ff (FilterScope.Method, Regex "23", Exclude)), Is.False ) Assert.That( - Filter.``match`` () (ff(FilterScope.Method, Regex "23", Include)), + Filter.``match`` () (ff (FilterScope.Method, Regex "23", Include)), Is.False ) @@ -534,7 +564,7 @@ module AltCoverTests = Assert.That( Filter.``match`` (Assembly.GetExecutingAssembly().Location) - (ff(FilterScope.Type, Regex "23", Exclude)), + (ff (FilterScope.Type, Regex "23", Exclude)), Is.False ) @@ -543,14 +573,14 @@ module AltCoverTests = Assert.That( Filter.``match`` (Assembly.GetExecutingAssembly().Location) - (ff(FilterScope.File, Regex "Cove", Exclude)), + (ff (FilterScope.File, Regex "Cove", Exclude)), Is.True ) Assert.That( Filter.``match`` (Assembly.GetExecutingAssembly().Location) - (ff(FilterScope.File, Regex "Cove", Include)), + (ff (FilterScope.File, Regex "Cove", Include)), Is.False ) @@ -559,7 +589,7 @@ module AltCoverTests = Assert.That( Filter.``match`` (Assembly.GetExecutingAssembly().Location) - (ff(FilterScope.Type, Regex "23", Exclude)), + (ff (FilterScope.Type, Regex "23", Exclude)), Is.False ) @@ -572,14 +602,14 @@ module AltCoverTests = Assert.That( Filter.``match`` (Assembly.GetExecutingAssembly().Location) - (ff(FilterScope.Path, Regex(x + "_Binaries" + x), Exclude)), + (ff (FilterScope.Path, Regex(x + "_Binaries" + x), Exclude)), Is.True ) Assert.That( Filter.``match`` (Assembly.GetExecutingAssembly().Location) - (ff(FilterScope.Path, Regex(x + "_Binaries" + x), Include)), + (ff (FilterScope.Path, Regex(x + "_Binaries" + x), Include)), Is.False ) @@ -589,12 +619,12 @@ module AltCoverTests = Mono.Cecil.AssemblyDefinition.ReadAssembly(Assembly.GetExecutingAssembly().Location) Assert.That( - Filter.``match`` def (ff(FilterScope.Type, Regex "23", Exclude)), + Filter.``match`` def (ff (FilterScope.Type, Regex "23", Exclude)), Is.False ) Assert.That( - Filter.``match`` def (ff(FilterScope.Type, Regex "23", Include)), + Filter.``match`` def (ff (FilterScope.Type, Regex "23", Include)), Is.False ) @@ -604,12 +634,12 @@ module AltCoverTests = Mono.Cecil.AssemblyDefinition.ReadAssembly(Assembly.GetExecutingAssembly().Location) Assert.That( - Filter.``match`` def (ff(FilterScope.Assembly, Regex "Cove", Exclude)), + Filter.``match`` def (ff (FilterScope.Assembly, Regex "Cove", Exclude)), Is.True ) Assert.That( - Filter.``match`` def (ff(FilterScope.Assembly, Regex "Cove", Include)), + Filter.``match`` def (ff (FilterScope.Assembly, Regex "Cove", Include)), Is.False ) @@ -619,7 +649,7 @@ module AltCoverTests = Mono.Cecil.AssemblyDefinition.ReadAssembly(Assembly.GetExecutingAssembly().Location) Assert.That( - Filter.``match`` def.MainModule (ff(FilterScope.Type, Regex "23", Exclude)), + Filter.``match`` def.MainModule (ff (FilterScope.Type, Regex "23", Exclude)), Is.False ) @@ -629,12 +659,12 @@ module AltCoverTests = Mono.Cecil.AssemblyDefinition.ReadAssembly(Assembly.GetExecutingAssembly().Location) Assert.That( - Filter.``match`` def.MainModule (ff(FilterScope.Module, Regex "Cove", Exclude)), + Filter.``match`` def.MainModule (ff (FilterScope.Module, Regex "Cove", Exclude)), Is.True ) Assert.That( - Filter.``match`` def.MainModule (ff(FilterScope.Module, Regex "Cove", Include)), + Filter.``match`` def.MainModule (ff (FilterScope.Module, Regex "Cove", Include)), Is.False ) @@ -647,7 +677,7 @@ module AltCoverTests = |> Seq.iter (fun t -> Assert.That( - Filter.``match`` t (ff(FilterScope.File, Regex "23", Exclude)), + Filter.``match`` t (ff (FilterScope.File, Regex "23", Exclude)), Is.False, t.FullName )) @@ -662,13 +692,13 @@ module AltCoverTests = |> Seq.iter (fun t -> Assert.That( - Filter.``match`` t (ff(FilterScope.Type, Regex "Cove", Exclude)), + Filter.``match`` t (ff (FilterScope.Type, Regex "Cove", Exclude)), Is.True, t.FullName ) Assert.That( - Filter.``match`` t (ff(FilterScope.Type, Regex "Cove", Include)), + Filter.``match`` t (ff (FilterScope.Type, Regex "Cove", Include)), Is.False, t.FullName )) @@ -684,7 +714,7 @@ module AltCoverTests = |> Seq.iter (fun m -> Assert.That( - Filter.``match`` m (ff(FilterScope.Type, Regex "23", Exclude)), + Filter.``match`` m (ff (FilterScope.Type, Regex "23", Exclude)), Is.False )) @@ -702,7 +732,7 @@ module AltCoverTests = (fun m -> Filter.``match`` m - (ff(FilterScope.Method, Regex "MethodDoesMatchMethodClass", Exclude))) + (ff (FilterScope.Method, Regex "MethodDoesMatchMethodClass", Exclude))) |> Seq.length, Is.EqualTo(1) ) @@ -716,7 +746,7 @@ module AltCoverTests = (fun m -> Filter.``match`` m - (ff(FilterScope.Method, Regex "MethodDoesMatchMethodClass", Include)) + (ff (FilterScope.Method, Regex "MethodDoesMatchMethodClass", Include)) |> not) |> Seq.length, Is.EqualTo(1) @@ -733,7 +763,7 @@ module AltCoverTests = Assert.That( Filter.``match`` t.CustomAttributes - (ff(FilterScope.File, Regex "23", Exclude)), + (ff (FilterScope.File, Regex "23", Exclude)), Is.False, t.FullName )) @@ -752,13 +782,13 @@ module AltCoverTests = |> Seq.iter (fun t -> Assert.That( - Filter.``match`` t (ff(FilterScope.Attribute, Regex "Exclu", Exclude)), + Filter.``match`` t (ff (FilterScope.Attribute, Regex "Exclu", Exclude)), Is.True, t.FullName ) Assert.That( - Filter.``match`` t (ff(FilterScope.Attribute, Regex "Exclu", Include)), + Filter.``match`` t (ff (FilterScope.Attribute, Regex "Exclu", Include)), Is.False, t.FullName )) @@ -932,9 +962,14 @@ module AltCoverTests = [] let ReportFileShouldBeCorrectlySuffixed () = try - let path1 = Path.Combine(SolutionRoot.location, "test.xml") - let path2 = Path.Combine(SolutionRoot.location, "test") - let path3 = Path.Combine(SolutionRoot.location, "test.json") + let path1 = + Path.Combine(SolutionRoot.location, "test.xml") + + let path2 = + Path.Combine(SolutionRoot.location, "test") + + let path3 = + Path.Combine(SolutionRoot.location, "test.json") CoverageParameters.theReportFormat <- Some ReportFormat.NCover CoverageParameters.theReportPath <- Some path1 @@ -1113,18 +1148,23 @@ module AltCoverTests = ) #else let dir = - Path.Combine( - SolutionRoot.location, - "_Binaries/AltCover.Engine/Debug+AnyCPU/net472" - ) + Path.Combine(SolutionRoot.location, "_Binaries/AltCover.Engine/Debug+AnyCPU/net472") #endif - let localAssembly = Path.Combine(dir, "AltCover.Engine.dll") - |> AssemblyDefinition.ReadAssembly + let localAssembly = + Path.Combine(dir, "AltCover.Engine.dll") + |> AssemblyDefinition.ReadAssembly + ProgramDatabase.readSymbols localAssembly Assert.That(localAssembly.LocalFilter, Is.False, "local engine Assembly non-local") - Assert.That(localAssembly.MainModule.LocalFilter, Is.False, "local engine MainModule non-local") + + Assert.That( + localAssembly.MainModule.LocalFilter, + Is.False, + "local engine MainModule non-local" + ) + Assert.That(a.LocalFilter, Is.False, "Assembly non-local") Assert.That(a.MainModule.LocalFilter, Is.False, "MainModule non-local") Assert.That(m.LocalFilter, Is.False, "dll Assembly non-local") @@ -1135,7 +1175,13 @@ module AltCoverTests = try CoverageParameters.local.Value <- true Assert.That(localAssembly.LocalFilter, Is.False, "local engine Assembly local") - Assert.That(localAssembly.MainModule.LocalFilter, Is.False, "local engine MainModule local") + + Assert.That( + localAssembly.MainModule.LocalFilter, + Is.False, + "local engine MainModule local" + ) + Assert.That(a.LocalFilter, Is.True, "Assembly local") Assert.That(a.MainModule.LocalFilter, Is.False, "MainModule local") Assert.That(m.LocalFilter, Is.True, "dll Assembly local") @@ -1233,8 +1279,8 @@ module AltCoverTests = Uid = n Interesting = b DefaultVisitCount = Exemption.None } -> - Assert.That(n, Is.EqualTo i, "synch point number") - Assert.That(b, Is.True, "synch flag " + i.ToString())) + Assert.That(n, Is.EqualTo i, "synch point number") + Assert.That(b, Is.True, "synch flag " + i.ToString())) Visitor.visit [] [] @@ -1257,8 +1303,8 @@ module AltCoverTests = Uid = n Interesting = b DefaultVisitCount = Exemption.None } -> - Assert.That(n, Is.EqualTo i, "point number") - Assert.That(b, Is.True, "flag " + i.ToString())) + Assert.That(n, Is.EqualTo i, "point number") + Assert.That(b, Is.True, "flag " + i.ToString())) Assert.That(deeper.Length, Is.EqualTo synchStructure.Length) finally @@ -1376,7 +1422,7 @@ module AltCoverTests = Uid = uid DefaultVisitCount = Exemption.None Interesting = true } -> - Assert.That(uid, Is.EqualTo i, "point number")) + Assert.That(uid, Is.EqualTo i, "point number")) finally CoverageParameters.nameFilters.Clear() CoverageParameters.theReportFormat <- None @@ -1479,7 +1525,7 @@ module AltCoverTests = Uid = uid DefaultVisitCount = Exemption.None Interesting = true } -> - Assert.That(uid, Is.EqualTo i, "point number")) + Assert.That(uid, Is.EqualTo i, "point number")) finally CoverageParameters.nameFilters.Clear() CoverageParameters.theReportFormat <- None @@ -1562,7 +1608,7 @@ module AltCoverTests = Uid = uid DefaultVisitCount = Exemption.Automatic Interesting = true } -> - Assert.That(uid, Is.EqualTo i, "point number")) + Assert.That(uid, Is.EqualTo i, "point number")) finally CoverageParameters.coalesceBranches.Value <- false CoverageParameters.nameFilters.Clear() @@ -1589,7 +1635,7 @@ module AltCoverTests = |> Seq.map (fun (mo: MethodDefinition option) -> mo |> Option.map id) let expected = - [Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // K Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::System.Collections.Generic.IEnumerator.get_Current() + [ Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // K Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::System.Collections.Generic.IEnumerator.get_Current() Some "get_ValuesWorks" // K Sample5.RecursiveSyntheticInvocation`2/d__4::System.Collections.Generic.IEnumerator.get_Current() None // K Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IReadOnlyDictionary.get_Item(T) Some "F2" // System.Boolean Sample5.Class1/d__1::MoveNext() @@ -1662,7 +1708,7 @@ module AltCoverTests = Some "get_ValuesWorks" // System.Void Sample5.RecursiveSyntheticInvocation`2/d__4::System.IDisposable.Dispose() None // System.Void Sample5.RecursiveSyntheticInvocation`2::.ctor() Some "G2" // T Sample5.Class1/Inner/d__2`1::System.Collections.Generic.IEnumerator.get_Current() - Some "g__Recursive|0_4"] // T[] Sample5.Class1/Inner::g__InteriorToArray|0_1(T) + Some "g__Recursive|0_4" ] // T[] Sample5.Class1/Inner::g__InteriorToArray|0_1(T) // methods |> Seq.iter (fun x -> printfn "%A" x.FullName) // Assert.That (result, Is.EquivalentTo expected) @@ -1718,7 +1764,8 @@ module AltCoverTests = [] let FSharpNestedMethodsClassic () = - let sample3 = Path.Combine(SolutionRoot.location, "Samples/Sample6/Sample6Classic.dll") + let sample3 = + Path.Combine(SolutionRoot.location, "Samples/Sample6/Sample6Classic.dll") use def = Mono.Cecil.AssemblyDefinition.ReadAssembly(sample3) @@ -1838,8 +1885,7 @@ module AltCoverTests = Some "fetchUrlAsync@21::Invoke" //"Microsoft.FSharp.Control.FSharpAsync`1 Sample6.Module/fetchUrlAsync@22-1::Invoke(Microsoft.FSharp.Core.Unit)" Some "Module::F2" //*//"System.Void Sample6.Module/fetchUrlAsync@21::.ctor()" Some "Module::F2" //*//"Microsoft.FSharp.Control.FSharpAsync`1 Sample6.Module/fetchUrlAsync@21::Invoke(System.String)" - Some "Module::F2" //*//"System.Void Sample6.Module/fetchUrlAsync@21::.cctor()" - ] + Some "Module::F2" ] //*//"System.Void Sample6.Module/fetchUrlAsync@21::.cctor()" //methods |> Seq.iter (fun x -> printfn "%A" x.FullName) //Assert.That (result, Is.EquivalentTo expected) @@ -1930,7 +1976,7 @@ module AltCoverTests = [] let KeyHasExpectedToken () = - let token = KeyStore.tokenOfKey <| provideKeyPair() + let token = KeyStore.tokenOfKey <| provideKeyPair () let token' = String.Join(String.Empty, token |> List.map (fun x -> x.ToString("x2"))) @@ -1953,7 +1999,7 @@ module AltCoverTests = [] let KeyHasExpectedIndex () = - let token = KeyStore.keyToIndex <| provideKeyPair() + let token = KeyStore.keyToIndex <| provideKeyPair () Assert.That(token, Is.EqualTo(0xe8ad7c5b9f1a2bc0UL), sprintf "%x" token) [] @@ -1962,7 +2008,7 @@ module AltCoverTests = [] let KeyHasExpectedRecord () = - let pair = provideKeyPair() + let pair = provideKeyPair () #if NET472 // Strong-name signing is not supported on this platform. let computed = pair.PublicKey @@ -1993,7 +2039,7 @@ module AltCoverTests = CoverageParameters.keys.Clear() Assert.That(CoverageParameters.keys.Count, Is.EqualTo(0)) - let pair = provideKeyPair() + let pair = provideKeyPair () CoverageParameters.add (pair) let key = 0xe8ad7c5b9f1a2bc0UL @@ -2023,8 +2069,8 @@ module AltCoverTests = Assert.That(CoverageParameters.nameFilters.Count, Is.EqualTo(0)) CoverageParameters.nameFilters.AddRange( - [ ff(FilterScope.File, Regex "Cove", Exclude) - ff(FilterScope.Method, Regex "Augment", Exclude) ] + [ ff (FilterScope.File, Regex "Cove", Exclude) + ff (FilterScope.Method, Regex "Augment", Exclude) ] ) Assert.That( @@ -2041,8 +2087,8 @@ module AltCoverTests = Assert.That(CoverageParameters.nameFilters.Count, Is.EqualTo(0)) CoverageParameters.nameFilters.AddRange( - [ ff(FilterScope.File, Regex "System", Exclude) - ff(FilterScope.Method, Regex "Augment", Exclude) ] + [ ff (FilterScope.File, Regex "System", Exclude) + ff (FilterScope.Method, Regex "Augment", Exclude) ] ) Assert.That( @@ -2063,6 +2109,7 @@ module AltCoverTests = Node.Assembly { Assembly = def Inspection = Inspections.Instrument + Identity = Hallmark.Build() Destinations = [] } Node.Module { Module = null @@ -2094,6 +2141,7 @@ module AltCoverTests = Node.AfterAssembly { Assembly = def Inspection = Inspections.Instrument + Identity = Hallmark.Build() Destinations = [] } Node.Finish ] @@ -2107,6 +2155,7 @@ module AltCoverTests = [ AfterAssembly { Assembly = def Inspection = Inspections.Instrument + Identity = Hallmark.Build() Destinations = [] } ] [ AfterModule ] [ AfterType ] @@ -2172,6 +2221,7 @@ module AltCoverTests = Node.AfterAssembly { Assembly = def Inspection = Inspections.Instrument + Identity = Hallmark.Build() Destinations = [] } Node.Finish ] @@ -2180,7 +2230,7 @@ module AltCoverTests = |> Seq.map (Visitor.I.deeper >> Seq.toList) |> Seq.toList - let expected : Node list list = [ []; []; []; []; [] ] + let expected: Node list list = [ []; []; []; []; [] ] //Assert.That(outputs, Is.EquivalentTo(expected)) test <@ outputs = expected @> @@ -2241,7 +2291,7 @@ module AltCoverTests = Uid = uid DefaultVisitCount = Exemption.None Interesting = false } -> - Assert.That(uid, Is.EqualTo i, "point number")) + Assert.That(uid, Is.EqualTo i, "point number")) finally CoverageParameters.nameFilters.Clear() @@ -2301,8 +2351,8 @@ module AltCoverTests = (fun i node -> match node with | (BranchPoint b) -> - Assert.That(b.Uid, Is.EqualTo i, "branch point number") - Some b) + Assert.That(b.Uid, Is.EqualTo i, "branch point number") + Some b) |> List.choose id deeper @@ -2315,7 +2365,7 @@ module AltCoverTests = Uid = uid DefaultVisitCount = Exemption.Declared Interesting = true } -> - Assert.That(uid, Is.EqualTo i, "point number")) + Assert.That(uid, Is.EqualTo i, "point number")) Assert.That( branches |> List.map (fun b -> b.Path), @@ -2394,7 +2444,7 @@ module AltCoverTests = Uid = uid DefaultVisitCount = Exemption.StaticAnalysis Interesting = true } -> - Assert.That(uid, Is.EqualTo i, "point number")) + Assert.That(uid, Is.EqualTo i, "point number")) finally CoverageParameters.coalesceBranches.Value <- false @@ -2508,7 +2558,7 @@ module AltCoverTests = |> Seq.map (fun t -> let flag = - Maybe (t.Name <> "Program") Inspections.Instrument Inspections.Ignore + Maybe(t.Name <> "Program") Inspections.Instrument Inspections.Ignore let node = Node.Type @@ -2547,6 +2597,7 @@ module AltCoverTests = <| Node.Assembly { Assembly = def Inspection = Inspections.Instrument + Identity = Hallmark.Build() Destinations = [] } |> Seq.toList @@ -2583,6 +2634,7 @@ module AltCoverTests = let deeper = Visitor.I.deeper <| Node.Start [ { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] } ] |> Seq.toList @@ -2597,6 +2649,7 @@ module AltCoverTests = Node.Assembly { Assembly = def Inspection = Inspections.Instrument + Identity = Hallmark.Build() Destinations = [] } let expected = @@ -2605,6 +2658,7 @@ module AltCoverTests = [ AfterAssembly { Assembly = def Inspection = Inspections.Instrument + Identity = Hallmark.Build() Destinations = [] } ] ] //deeper |> Seq.map (fun x -> x.GetType().Name) |> Seq.iter (printfn "%A") @@ -2635,6 +2689,7 @@ module AltCoverTests = let deeper = Visitor.I.deeper <| Node.Start [ { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] } ] |> Seq.toList @@ -2649,6 +2704,7 @@ module AltCoverTests = Node.Assembly { Assembly = def Inspection = Inspections.Ignore + Identity = Hallmark.Build() Destinations = [] } let expected = @@ -2657,6 +2713,7 @@ module AltCoverTests = [ AfterAssembly { Assembly = def Inspection = Inspections.Ignore + Identity = Hallmark.Build() Destinations = [] } ] ] Assert.That(deeper.Length, Is.EqualTo 4) @@ -2722,6 +2779,7 @@ module AltCoverTests = Visitor.visit [ fix ] [ { AssemblyPath = path + Identity = Hallmark.Build() Destinations = ux } ] // assembly definitions care about being separate references in equality tests @@ -2735,16 +2793,19 @@ module AltCoverTests = Node.Assembly { Assembly = def Inspection = Inspections.Instrument + Identity = Hallmark.Build() Destinations = ux } let expected = List.concat [ [ Start [ { AssemblyPath = path + Identity = Hallmark.Build() Destinations = ux } ] assembly ] (Visitor.I.deeper >> Seq.toList) assembly [ AfterAssembly { Assembly = def Inspection = Inspections.Instrument + Identity = Hallmark.Build() Destinations = ux } Finish ] ] @@ -2953,7 +3014,9 @@ module AltCoverTests = "Class1" "Class2" "Class3" - "Class4" ] + "Class4" + "IsExternalInit" + "InstrumentationAttribute" ] Assert.That(names, Is.EquivalentTo expected) @@ -2972,10 +3035,12 @@ module AltCoverTests = let expected = [ "" - "Sample3.Class1" - "Sample3.Class2" - "Sample3.Class3" - "Sample3.Class3+Class4" ] + "AltCover.Sample3.Class1" + "AltCover.Sample3.Class2" + "AltCover.Sample3.Class3" + "AltCover.Sample3.Class3+Class4" + "System.Runtime.CompilerServices.IsExternalInit" + "AltCover.Recorder.InstrumentationAttribute" ] Assert.That(names, Is.EquivalentTo expected) @@ -3001,7 +3066,9 @@ module AltCoverTests = "Class1" "Class2" "Class3" - "Class4" ] + "Class4" + "IsExternalInit" + "InstrumentationAttribute" ] Assert.That(names, Is.EquivalentTo expected) @@ -3034,10 +3101,12 @@ module AltCoverTests = let expected = [ "" - "Sample3.Class1" - "Sample3.Class2" - "Sample3.Class3" - "Sample3.Class3+Class4" ] + "AltCover.Sample3.Class1" + "AltCover.Sample3.Class2" + "AltCover.Sample3.Class3" + "AltCover.Sample3.Class3+Class4" + "System.Runtime.CompilerServices.IsExternalInit" + "AltCover.Recorder.InstrumentationAttribute" ] Assert.That(names, Is.EquivalentTo expected) @@ -3058,6 +3127,8 @@ module AltCoverTests = let expected = [ "get_Property" "set_Property" + "get_Property2" + "set_Property2" "#ctor" "get_Property" "set_Property" @@ -3082,7 +3153,12 @@ module AltCoverTests = "get_Sample" "set_Sample" "ToList" - "#ctor" ] + "#ctor" + "#ctor" + "get_Assembly" + "get_Configuration" + "set_Assembly" + "set_Configuration" ] Assert.That(names, Is.EquivalentTo expected) @@ -3101,38 +3177,46 @@ module AltCoverTests = |> Seq.toList let expected = - [ "System.Int32 Sample3.Class1.get_Property()" - "System.Void Sample3.Class1.set_Property(System.Int32)" - "System.Void Sample3.Class1.#ctor()" - "System.Int32 Sample3.Class2.get_Property()" - "System.Void Sample3.Class2.set_Property(System.Int32)" - "System.Void Sample3.Class2.#ctor()" - "System.Collections.Generic.List`1 Sample3.Class3.get_Visits()" - "System.Void Sample3.Class3.Log(System.String,System.Int32)" - "System.Int32 Sample3.Class3.GetOperandType(Mono.Cecil.Cil.Instruction)" - "System.Void Sample3.Class3.#ctor()" - "System.Void Sample3.Class3..cctor()" - "System.Boolean Sample3.Class3+Class4.get_Defer()" - "System.Void Sample3.Class3+Class4.set_Defer(System.Boolean)" - "Sample3.Class1 Sample3.Class3+Class4.get_Property()" - "System.Void Sample3.Class3+Class4.set_Property(Sample3.Class1)" - "System.String Sample3.Class3+Class4.get_ReportFile()" - "System.Void Sample3.Class3+Class4.set_ReportFile(System.String)" - "System.Int64 Sample3.Class3+Class4.get_Timer()" - "System.Void Sample3.Class3+Class4.set_Timer(System.Int64)" - "System.String Sample3.Class3+Class4.get_Token()" - "System.Void Sample3.Class3+Class4.set_Token(System.String)" - "System.Int32 Sample3.Class3+Class4.get_CoverageFormat()" - "System.Void Sample3.Class3+Class4.set_CoverageFormat(System.Int32)" - "System.Int32 Sample3.Class3+Class4.get_Sample()" - "System.Void Sample3.Class3+Class4.set_Sample(System.Int32)" - "System.Collections.Generic.List`1 Sample3.Class3+Class4.ToList(T)" - "System.Void Sample3.Class3+Class4.#ctor()" ] + [ "System.Int32 AltCover.Sample3.Class1.get_Property()" + "System.Void AltCover.Sample3.Class1.set_Property(System.Int32)" + "System.Int32 AltCover.Sample3.Class1.get_Property2()" + "System.Void modreq(System.Runtime.CompilerServices.IsExternalInit) AltCover.Sample3.Class1.set_Property2(System.Int32)" + "System.Void AltCover.Sample3.Class1.#ctor()" + "System.Int32 AltCover.Sample3.Class2.get_Property()" + "System.Void AltCover.Sample3.Class2.set_Property(System.Int32)" + "System.Void AltCover.Sample3.Class2.#ctor()" + "System.Collections.Generic.List`1 AltCover.Sample3.Class3.get_Visits()" + "System.Void AltCover.Sample3.Class3.Log(System.String,System.Int32)" + "System.Int32 AltCover.Sample3.Class3.GetOperandType(Mono.Cecil.Cil.Instruction)" + "System.Void AltCover.Sample3.Class3.#ctor()" + "System.Void AltCover.Sample3.Class3..cctor()" + "System.Boolean AltCover.Sample3.Class3+Class4.get_Defer()" + "System.Void AltCover.Sample3.Class3+Class4.set_Defer(System.Boolean)" + "AltCover.Sample3.Class1 AltCover.Sample3.Class3+Class4.get_Property()" + "System.Void AltCover.Sample3.Class3+Class4.set_Property(AltCover.Sample3.Class1)" + "System.String AltCover.Sample3.Class3+Class4.get_ReportFile()" + "System.Void AltCover.Sample3.Class3+Class4.set_ReportFile(System.String)" + "System.Int64 AltCover.Sample3.Class3+Class4.get_Timer()" + "System.Void AltCover.Sample3.Class3+Class4.set_Timer(System.Int64)" + "System.String AltCover.Sample3.Class3+Class4.get_Token()" + "System.Void AltCover.Sample3.Class3+Class4.set_Token(System.String)" + "System.Int32 AltCover.Sample3.Class3+Class4.get_CoverageFormat()" + "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.Collections.Generic.List`1 AltCover.Sample3.Class3+Class4.ToList(T)" + "System.Void AltCover.Sample3.Class3+Class4.#ctor()" + "System.String AltCover.Recorder.InstrumentationAttribute.get_Assembly()" + "System.String AltCover.Recorder.InstrumentationAttribute.get_Configuration()" + "System.Void AltCover.Recorder.InstrumentationAttribute.#ctor()" + "System.Void AltCover.Recorder.InstrumentationAttribute.set_Assembly(System.String)" + "System.Void AltCover.Recorder.InstrumentationAttribute.set_Configuration(System.String)" ] Assert.That(names, Is.EquivalentTo expected) // Report.fs - let TTBaseline = " + let TTBaseline = + " @@ -3176,30 +3260,30 @@ module AltCoverTests = | "startTime" | "measureTime" -> () | "document" -> - Assert.That( - a1.Value.Replace("\\", "/"), - Does.EndWith(a2.Value.Replace("\\", "/")), - a1.Name.ToString() - + " : " - + r.ToString() - + " -> document" - ) + Assert.That( + a1.Value.Replace("\\", "/"), + Does.EndWith(a2.Value.Replace("\\", "/")), + a1.Name.ToString() + + " : " + + r.ToString() + + " -> document" + ) | "visitcount" -> - let expected = Maybe zero "0" a2.Value + let expected = Maybe zero "0" a2.Value - Assert.That( - a1.Value, - Is.EqualTo(expected), - r.ToString() + " -> visitcount" - ) + Assert.That( + a1.Value, + Is.EqualTo(expected), + r.ToString() + " -> visitcount" + ) | _ -> - Assert.That( - a1.Value.Replace("\\", "/"), - Is.EqualTo(a2.Value.Replace("\\", "/")), - r.ToString() + " -> " + a1.Name.ToString() - )) + Assert.That( + a1.Value.Replace("\\", "/"), + Is.EqualTo(a2.Value.Replace("\\", "/")), + r.ToString() + " -> " + a1.Name.ToString() + )) - recursiveValidate(r.Elements()) (e.Elements()) (depth + 1) zero) + recursiveValidate (r.Elements()) (e.Elements()) (depth + 1) zero) let makeDocument (f: Stream -> unit) = use stash = new MemoryStream() @@ -3223,6 +3307,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) use def = @@ -3248,7 +3333,14 @@ module AltCoverTests = [] let ShouldGenerateExpectedXmlReportWithEmbeds () = let visitor, document = Report.reportGenerator () - let path = Path.Combine(SolutionDir(), "Samples/Sample28/GeneratedDemo/bin/Debug/netcoreapp3.1/CSharpGeneratedDemo.dll") + + let path = + Path.Combine( + SolutionDir(), + "_Binaries/CSharpGeneratedDemo/Debug+AnyCPU/netcoreapp3.1/CSharpGeneratedDemo.dll" + ) + + maybeIgnore (fun () -> path |> File.Exists |> not) try CoverageParameters.nameFilters.Clear() @@ -3258,22 +3350,29 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) //printfn "%A" (makeDocument document) - let results = (makeDocument document).Descendants("altcover.file".X) - |> Seq.toList - Assert.That (results |> List.length, Is.EqualTo 9) + let results = + (makeDocument document) + .Descendants("altcover.file".X) + |> Seq.toList + + Assert.That(results |> List.length, Is.EqualTo 9) + results - |> Seq.iter (fun x -> let doc = x.Attribute("document".X) - Assert.That (doc, Is.Not.Null, x.ToString()) - let path = doc.Value - Assert.That(path |> File.Exists, Is.False, path)) + |> Seq.iter + (fun x -> + let doc = x.Attribute("document".X) + Assert.That(doc, Is.Not.Null, x.ToString()) + let path = doc.Value + Assert.That(path |> File.Exists, Is.False, path)) let lead = results |> Seq.head let prev = lead.PreviousNode :?> XElement Assert.That(prev, Is.Not.Null) - Assert.That(prev.Name, Is.EqualTo ("method".X)) + Assert.That(prev.Name, Is.EqualTo("method".X)) finally CoverageParameters.nameFilters.Clear() @@ -3282,7 +3381,9 @@ module AltCoverTests = [] let ShouldGenerateExpectedXmlReportWithPartials () = let visitor, document = Report.reportGenerator () - let path = Path.Combine(SolutionDir(), "AltCover.Tests/SimpleMix.exe") + + let path = + Path.Combine(SolutionDir(), "AltCover.Tests/SimpleMix.exe") try CoverageParameters.nameFilters.Clear() @@ -3292,46 +3393,64 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) //printfn "%A" (makeDocument document) let results = (makeDocument document) - let methods = results.Descendants("method".X) - |> Seq.toList - let classes = methods - |> List.groupBy (fun x -> x.Attribute("class".X).Value) - let documents = classes - |> List.map (fun (n,ml) -> n, ml - |> Seq.map (fun m -> m.Descendants("seqpnt".X) - |> Seq.map (fun s -> s.Attribute("document".X).Value) - |> Seq.distinct - |> Seq.toList)) - let classdocs = documents - |> List.map (fun (n,dl) -> (n, dl - |> Seq.concat - |> Seq.distinct - |> Seq.toList)) - let classcount = classdocs - |> List.map (fun (n,dl) -> (n, dl |> List.length)) - |> List.sortBy fst + + let methods = + results.Descendants("method".X) |> Seq.toList + + let classes = + methods + |> List.groupBy (fun x -> x.Attribute("class".X).Value) + + let documents = + classes + |> List.map + (fun (n, ml) -> + n, + ml + |> Seq.map + (fun m -> + m.Descendants("seqpnt".X) + |> Seq.map (fun s -> s.Attribute("document".X).Value) + |> Seq.distinct + |> Seq.toList)) + + let classdocs = + documents + |> List.map (fun (n, dl) -> (n, dl |> Seq.concat |> Seq.distinct |> Seq.toList)) + + let classcount = + classdocs + |> List.map (fun (n, dl) -> (n, dl |> List.length)) + |> List.sortBy fst // printfn "%A" classcount // snd > 1 => partial class at least - test <@ classcount = [(".ModuleLoadException", 1); - (".ModuleLoadExceptionHandlerException", 1); - (".ModuleUninitializer", 1); ("", 10); - ("Example", 2)] @> - - let mcount = documents - |> List.map (fun (n,ml) -> (n, ml |> Seq.maxBy List.length |> List.length)) - |> List.sortBy fst + test + <@ classcount = [ (".ModuleLoadException", 1) + (".ModuleLoadExceptionHandlerException", + 1) + (".ModuleUninitializer", 1) + ("", 10) + ("Example", 2) ] @> + + let mcount = + documents + |> List.map (fun (n, ml) -> (n, ml |> Seq.maxBy List.length |> List.length)) + |> List.sortBy fst // snd > 1 => inlined method at least - test <@ mcount = [(".ModuleLoadException", 1); - (".ModuleLoadExceptionHandlerException", 1); - (".ModuleUninitializer", 1); ("", 2); - ("Example", 2)] @> + test + <@ mcount = [ (".ModuleLoadException", 1) + (".ModuleLoadExceptionHandlerException", 1) + (".ModuleUninitializer", 1) + ("", 2) + ("Example", 2) ] @> finally CoverageParameters.nameFilters.Clear() @@ -3369,6 +3488,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) Assert.That( @@ -3394,9 +3514,12 @@ module AltCoverTests = let expected = reader .ReadToEnd() - .Replace("/_//Samples/Sample4/Tests.fs", // Not compiled deterministic - (Path.Combine(SolutionDir(), "Samples/Sample4/Tests.fs") - |> canonicalPath).Replace("\\","\\\\")) + .Replace( + "/_//Samples/Sample4/Tests.fs", // Not compiled deterministic + (Path.Combine(SolutionDir(), "Samples/Sample4/Tests.fs") + |> canonicalPath) + .Replace("\\", "\\\\") + ) .Replace('\r', '\u00FF') .Replace('\n', '\u00FF') .Replace("\u00FF\u00FF", "\u00FF") @@ -3419,7 +3542,10 @@ module AltCoverTests = [] let ShouldGenerateExpectedJsonReportWithPartials () = let visitor, document = OpenCover.reportGenerator () - let path = Path.Combine(SolutionDir(), "AltCover.Tests/SimpleMix.exe") + + let path = + Path.Combine(SolutionDir(), "AltCover.Tests/SimpleMix.exe") + try CoverageParameters.nameFilters.Clear() CoverageParameters.theReportFormat <- Some ReportFormat.NativeJson @@ -3429,56 +3555,72 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let result = makeJson document //printfn "%A" result let json = NativeJson.fromJsonText result - Assert.That (json.Count, Is.EqualTo 1) + Assert.That(json.Count, Is.EqualTo 1) let documents = json.Values |> Seq.head Assert.That(documents.Count, Is.EqualTo 10) - let classdocs = documents - |> Seq.collect (fun kvp -> kvp.Value.Keys - |> Seq.map (fun k -> (k, kvp.Key))) - |> Seq.groupBy fst - |> Seq.toList - let classcount = classdocs - |> List.map (fun (n,dl) -> (n, dl |> Seq.length)) - |> List.sortBy fst + let classdocs = + documents + |> Seq.collect (fun kvp -> kvp.Value.Keys |> Seq.map (fun k -> (k, kvp.Key))) + |> Seq.groupBy fst + |> Seq.toList + + let classcount = + classdocs + |> List.map (fun (n, dl) -> (n, dl |> Seq.length)) + |> List.sortBy fst // printfn "%A" classcount // snd > 1 => partial class at least - test <@ classcount = [(".ModuleLoadException", 1); - (".ModuleLoadExceptionHandlerException", 1); - (".ModuleUninitializer", 1); ("", 10); - ("Example", 2)] @> - - let mcount = documents - |> Seq.collect (fun kvp -> kvp.Value - |> Seq.collect (fun kv -> kv.Value.Keys - |> Seq.map (fun k -> kv.Key, (k, kvp.Key)))) - - |> Seq.groupBy fst - |> Seq.map (fun (n,l) -> n,(l |> Seq.map snd - |> Seq.groupBy fst - |> Seq.map (fun (_, dl) -> dl |> Seq.map snd - |> Seq.distinct - |> Seq.length)) - |> Seq.max) - |> Seq.toList - |> List.sortBy fst + test + <@ classcount = [ (".ModuleLoadException", 1) + (".ModuleLoadExceptionHandlerException", + 1) + (".ModuleUninitializer", 1) + ("", 10) + ("Example", 2) ] @> + + let mcount = + documents + |> Seq.collect + (fun kvp -> + kvp.Value + |> Seq.collect + (fun kv -> + kv.Value.Keys + |> Seq.map (fun k -> kv.Key, (k, kvp.Key)))) + + |> Seq.groupBy fst + |> Seq.map + (fun (n, l) -> + n, + (l + |> Seq.map snd + |> Seq.groupBy fst + |> Seq.map + (fun (_, dl) -> dl |> Seq.map snd |> Seq.distinct |> Seq.length)) + |> Seq.max) + |> Seq.toList + |> List.sortBy fst //mcount //|> Seq.iter (printfn "%A") // snd > 1 => inlined method at least - test <@ mcount = [(".ModuleLoadException", 1); - (".ModuleLoadExceptionHandlerException", 1); - (".ModuleUninitializer", 1); ("", 2); - ("Example", 2)] @> + test + <@ mcount = [ (".ModuleLoadException", 1) + (".ModuleLoadExceptionHandlerException", 1) + (".ModuleUninitializer", 1) + ("", 2) + ("Example", 2) ] @> finally CoverageParameters.nameFilters.Clear() CoverageParameters.theReportFormat <- None @@ -3486,7 +3628,14 @@ module AltCoverTests = [] let ShouldGenerateExpectedJsonReportWithEmbeds () = let visitor, document = OpenCover.reportGenerator () - let path = Path.Combine(SolutionDir(), "Samples/Sample28/GeneratedDemo/bin/Debug/netcoreapp3.1/CSharpGeneratedDemo.dll") + + let path = + Path.Combine( + SolutionDir(), + "_Binaries/CSharpGeneratedDemo/Debug+AnyCPU/netcoreapp3.1/CSharpGeneratedDemo.dll" + ) + + maybeIgnore (fun () -> path |> File.Exists |> not) try CoverageParameters.nameFilters.Clear() @@ -3497,22 +3646,46 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let result = makeJson document //printfn "%A" result let json = NativeJson.fromJsonText result - Assert.That (json.Count, Is.EqualTo 1) - Assert.That (json.["CSharpGeneratedDemo.dll"].Count, Is.EqualTo 16) + Assert.That(json.Count, Is.EqualTo 1) + Assert.That(json.["CSharpGeneratedDemo.dll"].Count, Is.EqualTo 16) let dict = json.["CSharpGeneratedDemo.dll"] - let embeds = dict.Keys - |> Seq.map (fun k -> let file = k |> File.Exists |> not - let embed = dict.[k].ContainsKey "\u00ABAltCover.embed\u00BB" - Assert.That (file, Is.EqualTo embed, k) - if file then 1 else 0) - |> Seq.toList - test <@ embeds = [1; 1; 1; 1; 1; 1; 1; 1; 1; 0; 0; 0; 0; 0; 0; 0] @> + let embeds = + dict.Keys + |> Seq.map + (fun k -> + let file = k |> File.Exists |> not + + let embed = + dict.[k].ContainsKey "\u00ABAltCover.embed\u00BB" + + Assert.That(file, Is.EqualTo embed, k) + if file then 1 else 0) + |> Seq.toList + + test + <@ embeds = [ 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 ] @> finally CoverageParameters.nameFilters.Clear() @@ -3530,6 +3703,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) (makeDocument document) @@ -3566,6 +3740,7 @@ module AltCoverTests = [ visitor1 ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let names1 = @@ -3596,6 +3771,7 @@ module AltCoverTests = [ visitor2 ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let names2 = @@ -3632,6 +3808,7 @@ module AltCoverTests = [ visitor3 ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let names3 = @@ -3667,6 +3844,7 @@ module AltCoverTests = [ visitor5 ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let names5 = @@ -3708,6 +3886,7 @@ module AltCoverTests = [ visitor6 ] (Visitor.I.toSeq { AssemblyPath = path6 + Identity = Hallmark.Build() Destinations = [] }) let names6 = @@ -3744,6 +3923,7 @@ module AltCoverTests = [ visitor7 ] (Visitor.I.toSeq { AssemblyPath = path6 + Identity = Hallmark.Build() Destinations = [] }) let names7 = @@ -3788,6 +3968,7 @@ module AltCoverTests = [ visitor8 ] (Visitor.I.toSeq { AssemblyPath = path5 + Identity = Hallmark.Build() Destinations = [] }) let names8 = @@ -3823,6 +4004,7 @@ module AltCoverTests = [ visitor9 ] (Visitor.I.toSeq { AssemblyPath = path5 + Identity = Hallmark.Build() Destinations = [] }) let names9 = @@ -3849,6 +4031,7 @@ module AltCoverTests = [ visitor4 ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let names4 = @@ -3887,6 +4070,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) (makeDocument document) @@ -3916,6 +4100,8 @@ module AltCoverTests = let path = Path.Combine(here, "_SourceLink/Sample14.dll") + maybeIgnore (fun () -> path |> File.Exists |> not) + try CoverageParameters.sourcelink.Value <- true CoverageParameters.staticFilter <- Some StaticFilter.NoFilter @@ -3924,6 +4110,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) Assert.That( @@ -3995,6 +4182,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) use def = @@ -4040,12 +4228,14 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) use def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - let xml = " + let xml = + " @@ -4087,12 +4277,14 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) use def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - let xml = " + let xml = + " @@ -4130,7 +4322,7 @@ module AltCoverTests = let target = def .MainModule - .GetType("Sample3.Class2") + .GetType("AltCover.Sample3.Class2") .GetMethods() |> Seq.filter (fun m -> m.Name = "set_Property") |> Seq.head @@ -4169,7 +4361,7 @@ module AltCoverTests = let target = def .MainModule - .GetType("Sample3.Class3") + .GetType("AltCover.Sample3.Class3") .GetMethods() |> Seq.filter (fun m -> m.Name = "GetOperandType") |> Seq.head @@ -4329,37 +4521,37 @@ module AltCoverTests = | "crapScore" | "hash" -> () | "fullPath" -> - Assert.That( - a1 + Assert.That( + a1 + .Value + .Replace("\\", "/") + .Replace("Samples/", String.Empty) + .Replace("altcover", "AltCover"), + Does.EndWith( + a2 .Value .Replace("\\", "/") - .Replace("Samples/", String.Empty) - .Replace("altcover", "AltCover"), - Does.EndWith( - a2 - .Value - .Replace("\\", "/") - .Replace("altcover", "AltCover") - ), - a1.Name.ToString() - + " : " - + r.ToString() - + " -> document" - ) + .Replace("altcover", "AltCover") + ), + a1.Name.ToString() + + " : " + + r.ToString() + + " -> document" + ) | "vc" -> - let expected = Maybe zero "0" a2.Value + let expected = Maybe zero "0" a2.Value - Assert.That( - a1.Value, - Is.EqualTo(expected), - r.ToString() + " -> visitcount" - ) + Assert.That( + a1.Value, + Is.EqualTo(expected), + r.ToString() + " -> visitcount" + ) | _ -> - Assert.That( - a1.Value, - Is.EqualTo(a2.Value), - r.ToString() + " -> " + a1.Name.ToString() - )) + Assert.That( + a1.Value, + Is.EqualTo(a2.Value), + r.ToString() + " -> " + a1.Name.ToString() + )) recursiveValidateOpenCover (r.Elements()) @@ -4378,6 +4570,8 @@ module AltCoverTests = let path = Path.Combine(here, "_SourceLink/Sample14.dll") + maybeIgnore (fun () -> path |> File.Exists |> not) + try CoverageParameters.theReportFormat <- Some ReportFormat.NCover CoverageParameters.sourcelink.Value <- true @@ -4386,6 +4580,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) Assert.That( @@ -4440,6 +4635,7 @@ module AltCoverTests = let ShouldGenerateExpectedXmlReportFromDotNetOpenCoverStyle () = let visitor, document = OpenCover.reportGenerator () let path = sample1path + maybeIgnore (fun () -> path |> File.Exists |> not) try CoverageParameters.nameFilters.Clear() @@ -4449,6 +4645,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let resource = @@ -4474,7 +4671,14 @@ module AltCoverTests = [] let ShouldGenerateExpectedXmlReportWithEmbedsOpenCoverStyle () = let visitor, document = OpenCover.reportGenerator () - let path = Path.Combine(SolutionDir(), "Samples/Sample28/GeneratedDemo/bin/Debug/netcoreapp3.1/CSharpGeneratedDemo.dll") + + let path = + Path.Combine( + SolutionDir(), + "_Binaries/CSharpGeneratedDemo/Debug+AnyCPU/netcoreapp3.1/CSharpGeneratedDemo.dll" + ) + + maybeIgnore (fun () -> path |> File.Exists |> not) try CoverageParameters.nameFilters.Clear() @@ -4484,23 +4688,53 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) - let expected = [1; 1; 1; 1; 1; 1; 1; 1; 0; 1; 0; 0; 0; 0; 0; 0] + let expected = + [ 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 ] //printfn "%A" (makeDocument document) - let result = (makeDocument document).Descendants("File".X) - |> Seq.map(fun f -> if f.Attribute("fullPath".X).Value |> File.Exists |> not - then 1 else 0) - |> Seq.toList + let result = + (makeDocument document).Descendants("File".X) + |> Seq.map + (fun f -> + if f.Attribute("fullPath".X).Value + |> File.Exists + |> not then + 1 + else + 0) + |> Seq.toList // Generated source does not exist at the specified path -- a check on the MSFT inputs test <@ result = expected @> // but we should have picked up the embedded source - let embeds = (makeDocument document).Descendants("File".X) - |> Seq.map (fun f -> if f.Attribute("altcover.embed".X).IsNotNull - then 1 else 0) - |> Seq.toList - test <@ embeds = expected @> + let embeds = + (makeDocument document).Descendants("File".X) + |> Seq.map + (fun f -> + if f.Attribute("altcover.embed".X).IsNotNull then + 1 + else + 0) + |> Seq.toList + + test <@ embeds = expected @> finally CoverageParameters.nameFilters.Clear() @@ -4509,7 +4743,9 @@ module AltCoverTests = [] let ShouldGenerateExpectedXmlReportWithPartialsOpenCoverStyle () = let visitor, document = OpenCover.reportGenerator () - let path = Path.Combine(SolutionDir(), "AltCover.Tests/SimpleMix.exe") + + let path = + Path.Combine(SolutionDir(), "AltCover.Tests/SimpleMix.exe") try CoverageParameters.nameFilters.Clear() @@ -4519,48 +4755,66 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) // printfn "%A" (makeDocument document) let results = (makeDocument document) - let classes = results.Descendants("Class".X) - |> Seq.map (fun c -> (c.Element("FullName".X).Value, - c.Descendants("Method".X) |> Seq.toList)) - |> Seq.toList - - let documents = classes - |> List.map (fun (n,ml) -> (n, ml |> Seq.map (fun m -> [ m.Descendants("SequencePoint".X); - m.Descendants("Branch".X)] - |> Seq.concat - |> Seq.map (fun x -> x.Attribute("fileid".X).Value) - |> Seq.distinct - |> Seq.toList))) - let classdocs = documents - |> List.map (fun (n,dl) -> (n, dl - |> Seq.concat - |> Seq.distinct - |> Seq.toList)) - let classcount = classdocs - |> List.map (fun (n,dl) -> (n, dl |> List.length)) - |> List.sortBy fst + + let classes = + results.Descendants("Class".X) + |> Seq.map + (fun c -> + (c.Element("FullName".X).Value, c.Descendants("Method".X) |> Seq.toList)) + |> Seq.toList + + let documents = + classes + |> List.map + (fun (n, ml) -> + (n, + ml + |> Seq.map + (fun m -> + [ m.Descendants("SequencePoint".X) + m.Descendants("Branch".X) ] + |> Seq.concat + |> Seq.map (fun x -> x.Attribute("fileid".X).Value) + |> Seq.distinct + |> Seq.toList))) + + let classdocs = + documents + |> List.map (fun (n, dl) -> (n, dl |> Seq.concat |> Seq.distinct |> Seq.toList)) + + let classcount = + classdocs + |> List.map (fun (n, dl) -> (n, dl |> List.length)) + |> List.sortBy fst // printfn "%A" classcount // snd > 1 => partial class at least - test <@ classcount = [(".ModuleLoadException", 1); - (".ModuleLoadExceptionHandlerException", 1); - (".ModuleUninitializer", 1); ("", 10); - ("Example", 2)] @> - - let mcount = documents - |> List.map (fun (n,ml) -> (n, ml |> Seq.maxBy List.length |> List.length)) - |> List.sortBy fst + test + <@ classcount = [ (".ModuleLoadException", 1) + (".ModuleLoadExceptionHandlerException", + 1) + (".ModuleUninitializer", 1) + ("", 10) + ("Example", 2) ] @> + + let mcount = + documents + |> List.map (fun (n, ml) -> (n, ml |> Seq.maxBy List.length |> List.length)) + |> List.sortBy fst // snd > 1 => inlined method at least - test <@ mcount = [(".ModuleLoadException", 1); - (".ModuleLoadExceptionHandlerException", 1); - (".ModuleUninitializer", 1); ("", 2); - ("Example", 2)] @> + test + <@ mcount = [ (".ModuleLoadException", 1) + (".ModuleLoadExceptionHandlerException", 1) + (".ModuleUninitializer", 1) + ("", 2) + ("Example", 2) ] @> finally CoverageParameters.nameFilters.Clear() @@ -4583,6 +4837,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let resource = @@ -4638,6 +4893,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let resource = @@ -4723,6 +4979,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let baseline = @@ -4754,9 +5011,11 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) - let raw = " + let raw = + " @@ -4800,9 +5059,11 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) - let raw = " + let raw = + " @@ -4849,6 +5110,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let resource = @@ -4898,6 +5160,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let baseline = @@ -4929,6 +5192,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let resource = @@ -4968,6 +5232,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let resource = @@ -5028,6 +5293,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let baseline = @@ -5046,7 +5312,7 @@ module AltCoverTests = let visitor, document = OpenCover.reportGenerator () let sample21trad = - Path.Combine(SolutionDir(), "./Samples/Sample21/bin/Debug/net472/Sample21.dll") + Path.Combine(SolutionDir(), "./_Binaries/Sample21/Debug+AnyCPU/net472/Sample21.dll") Assert.That(File.Exists sample21trad, "Test file Sample21 for net47 not built") @@ -5061,6 +5327,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = sample21trad + Identity = Hallmark.Build() Destinations = [] }) let doc = makeDocument document @@ -5098,7 +5365,7 @@ module AltCoverTests = let visitor, document = OpenCover.reportGenerator () let sample21 = - Path.Combine(SolutionDir(), "./Samples/Sample21/bin/Debug/net6.0/Sample21.dll") + Path.Combine(SolutionDir(), "./_Binaries/Sample21/Debug+AnyCPU/net6.0/Sample21.dll") Assert.That(File.Exists sample21, "Test file Sample21 for net6.0 not built") @@ -5113,6 +5380,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = sample21 + Identity = Hallmark.Build() Destinations = [] }) let doc = makeDocument document @@ -5175,6 +5443,7 @@ module AltCoverTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let doc = makeDocument document diff --git a/AltCover.Tests/Tests2.fs b/AltCover.Tests/Tests2.fs index b49043b18..8a3a37367 100644 --- a/AltCover.Tests/Tests2.fs +++ b/AltCover.Tests/Tests2.fs @@ -41,12 +41,34 @@ module AltCoverTests2 = Assembly .GetExecutingAssembly() .GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("AltCover.Recorder.net20.dll", StringComparison.Ordinal)) + |> Seq.find + (fun n -> n.EndsWith("AltCover.Recorder.net20.dll", StringComparison.Ordinal)) + Assembly .GetExecutingAssembly() .GetManifestResourceStream(recorder) // Instrument.I.fs +#if IDEMPOTENT_INSTRUMENT + [] + let ShouldGetAbandonedMutex () = + use testMutex = new System.Threading.Mutex() + let abandon () = Instrument.I.safeWait testMutex + + let t = + Threading.Thread(Threading.ThreadStart(abandon)) + + t.Start() + t.Join() + + try + abandon () + finally + testMutex.ReleaseMutex() + + test <@ "Didn't lock!" |> String.IsNullOrWhiteSpace |> not @> +#endif + [] let ShouldBeAbleToGetTheVisitReportMethod () = use recstream = recorderStream () @@ -146,7 +168,7 @@ module AltCoverTests2 = use def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - provideKeyPair() |> CoverageParameters.add + provideKeyPair () |> CoverageParameters.add Assert.That(Option.isSome (Instrument.I.knownKey def.Name)) finally CoverageParameters.keys.Clear() @@ -162,7 +184,7 @@ module AltCoverTests2 = use def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - provideKeyPair() |> CoverageParameters.add + provideKeyPair () |> CoverageParameters.add Assert.That(Option.isNone (Instrument.I.knownKey def.Name)) finally CoverageParameters.keys.Clear() @@ -205,7 +227,7 @@ module AltCoverTests2 = Mono.Cecil.AssemblyDefinition.ReadAssembly path AltCover.Instrument.I.updateStrongNaming def None - provideKeyPair() |> CoverageParameters.add + provideKeyPair () |> CoverageParameters.add Assert.That(Option.isNone (Instrument.I.knownKey def.Name)) finally CoverageParameters.keys.Clear() @@ -238,7 +260,7 @@ module AltCoverTests2 = use def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - provideKeyPair() |> CoverageParameters.add + provideKeyPair () |> CoverageParameters.add Assert.That(Option.isSome (Instrument.I.knownToken def.Name)) finally CoverageParameters.keys.Clear() @@ -256,7 +278,7 @@ module AltCoverTests2 = Mono.Cecil.AssemblyDefinition.ReadAssembly path AltCover.Instrument.I.updateStrongNaming def None - provideKeyPair() |> CoverageParameters.add + provideKeyPair () |> CoverageParameters.add Assert.That(Option.isNone (Instrument.I.knownToken def.Name)) finally CoverageParameters.keys.Clear() @@ -265,7 +287,7 @@ module AltCoverTests2 = let ForeignTokenIsNotMatchedInIndex () = try CoverageParameters.keys.Clear() - provideKeyPair() |> CoverageParameters.add + provideKeyPair () |> CoverageParameters.add let path = typeof.Assembly.Location @@ -477,7 +499,8 @@ module AltCoverTests2 = let path = Path.Combine(AltCoverTests.dir, "Sample3.dll") - let prepared = Instrument.I.prepareAssembly (File.OpenRead path) + let prepared = + Instrument.I.prepareAssembly (File.OpenRead path) use raw = Mono.Cecil.AssemblyDefinition.ReadAssembly path @@ -496,6 +519,14 @@ module AltCoverTests2 = Assert.That(token', Is.EqualTo("4ebffcaabf10ce6a")) + Assert.True( + prepared.CustomAttributes + |> Seq.exists + (fun a -> + a.AttributeType.FullName = "AltCover.Recorder.InstrumentationAttribute"), + "Hallmark missing" + ) + let before = raw.MainModule.GetTypes() |> Seq.filter (fun t -> t.Name = "Class4") @@ -666,7 +697,8 @@ module AltCoverTests2 = "Unexpected sampling" ) - let prepared = Instrument.I.prepareAssembly (File.OpenRead path) + let prepared = + Instrument.I.prepareAssembly (File.OpenRead path) let traces = System.Collections.Generic.List() @@ -694,19 +726,6 @@ module AltCoverTests2 = let expectedSymbols = Maybe ("Mono.Runtime" |> Type.GetType).IsNotNull ".dll.mdb" ".pdb" - let isSymbols = -#if NET472 - System.Environment.GetEnvironmentVariable("OS") = "Windows_NT" -#else - false // recorder symbols not read here -#endif - Assert.That( - (isSymbols |> not) - || // HACK HACK HACK - File.Exists(outputdll.Replace(".dll", expectedSymbols)), - "unexpected symbols" - ) - use raw = Mono.Cecil.AssemblyDefinition.ReadAssembly outputdll @@ -735,7 +754,7 @@ module AltCoverTests2 = try let proxyObject = alc.CreateObject() - proxyObject.InstantiateObject(outputdll, "Sample3.Class3+Class4", [||]) + proxyObject.InstantiateObject(outputdll, "AltCover.Sample3.Class3+Class4", [||]) let report = proxyObject @@ -796,6 +815,71 @@ module AltCoverTests2 = finally CoverageParameters.keys.Clear() + [] + let ShouldRescopeMonoMethodOK () = + // Workround for Cecil 11.4 + let path = // Use a known good (bad) build rather than a local new one each time + // Path.Combine(SolutionRoot.location, "_Mono/Sample31/Sample31.dll") + Path.Combine(SolutionRoot.location, "AltCover.Tests/Sample31.dll") + + use ``module`` = + Mono.Cecil.AssemblyDefinition.ReadAssembly path + + ProgramDatabase.readSymbols ``module`` + + let pathGetterDef = + ``module``.MainModule.GetTypes() + |> Seq.collect (fun t -> t.Methods) + |> Seq.find (fun m -> m.Name.Equals("get_Defer")) + + let body = pathGetterDef.Body + let worker = body.GetILProcessor() + let initialBody = body.Instructions |> Seq.toList + let head = initialBody |> Seq.head + let opcode = worker.Create(OpCodes.Ldc_I4_1) + worker.InsertBefore(head, opcode) + + Assert.That( + pathGetterDef.DebugInformation.Scope.Start.IsEndOfMethod, + Is.False, + "Scope.Start.IsEndOfMethod" + ) + + Assert.True( + pathGetterDef.DebugInformation.Scope.Scopes + |> Seq.exists (fun subscope -> subscope.Start.IsEndOfMethod), + "subscope.Start.IsEndOfMethod" + ) // this one needs the home-built Sample31 + + // big test -- if we can write w/o crashing when the previous asserts are removed + let output = Path.GetTempFileName() + let outputdll = output + ".dll" + + let writer = WriterParameters() + writer.SymbolWriterProvider <- Mono.Cecil.Mdb.MdbWriterProvider() + writer.WriteSymbols <- true + + use sink = + File.Open(outputdll, FileMode.Create, FileAccess.ReadWrite) + + Assert.Throws(fun () -> ``module``.Write(sink, writer)) + |> ignore + + pruneLocalScopes pathGetterDef + ``module``.Write(sink, writer) + + Assert.That( + pathGetterDef.DebugInformation.Scope.Start.IsEndOfMethod, + Is.False, + "pruned Scope.Start.IsEndOfMethod" + ) + + Assert.True( + pathGetterDef.DebugInformation.Scope.Scopes + |> Seq.isEmpty, + "pruned subscope.Start.IsEndOfMethod" + ) + [] let ShouldWriteMonoAssemblyOK () = try @@ -824,7 +908,10 @@ module AltCoverTests2 = try CoverageParameters.theReportPath <- Some unique - let prepared = Instrument.I.prepareAssembly (File.OpenRead path) + + let prepared = + Instrument.I.prepareAssembly (File.OpenRead path) + Instrument.I.writeAssembly prepared outputdll // TODO -- see Instrument.I.WriteAssembly Assert.That (File.Exists (outputdll + ".mdb")) use raw = @@ -846,7 +933,7 @@ module AltCoverTests2 = try let proxyObject = alc.CreateObject() - proxyObject.InstantiateObject(outputdll, "Sample3.Class3+Class4", [||]) + proxyObject.InstantiateObject(outputdll, "AltCover.Sample3.Class3+Class4", [||]) let report = proxyObject @@ -886,13 +973,16 @@ module AltCoverTests2 = Mono.Cecil.AssemblyDefinition.ReadAssembly path ProgramDatabase.readSymbols def - let clazz = def.MainModule.GetType("Sample3.Class1") + + let clazz = + def.MainModule.GetType("AltCover.Sample3.Class1") let func = clazz.GetMethods() |> Seq.find (fun x -> x.Name = "get_Property") - let clazz' = def.MainModule.GetType("Sample3.Class3") + let clazz' = + def.MainModule.GetType("AltCover.Sample3.Class3") let func' = clazz'.GetMethods() @@ -911,7 +1001,7 @@ module AltCoverTests2 = Instrument.I.writeAssembly def outputdll let expectedSymbols = - Maybe ("Mono.Runtime" |> Type.GetType |> isNull |> not) ".dll.mdb" ".pdb" + Maybe("Mono.Runtime" |> Type.GetType |> isNull |> not) ".dll.mdb" ".pdb" let isSymbols = #if !NET472 @@ -923,8 +1013,8 @@ module AltCoverTests2 = (isSymbols |> not) || // HACK HACK HACK File.Exists(outputdll.Replace(".dll", expectedSymbols)), - "bad symbols" - ) + "bad symbols" + ) use raw = Mono.Cecil.AssemblyDefinition.ReadAssembly outputdll @@ -946,7 +1036,7 @@ module AltCoverTests2 = try let proxyObject = alc.CreateObject() - proxyObject.InstantiateObject(outputdll, "Sample3.Class1", [||]) + proxyObject.InstantiateObject(outputdll, "AltCover.Sample3.Class1", [||]) let setting = proxyObject.InvokeMethod("set_Property", [| 17 |]) @@ -965,7 +1055,7 @@ module AltCoverTests2 = System.Environment.GetEnvironmentVariable("OS") = "Windows_NT" #endif let proxyObject' = alc.CreateObject() - proxyObject'.InstantiateObject(outputdll, "Sample3.Class3", [||]) + proxyObject'.InstantiateObject(outputdll, "AltCover.Sample3.Class3", [||]) let log = proxyObject'.InvokeMethod("get_Visits", [||]) :?> seq> @@ -1610,12 +1700,7 @@ module AltCoverTests2 = AltCover.Instrument.I.recordingMethod rdef let target = - def - .MainModule - .GetType( - "Sample27.Tests" - ) - .Methods + def.MainModule.GetType("Sample27.Tests").Methods |> Seq.find (fun m -> m.Name = "AddAsync") let raw = AltCover.InstrumentContext.Build([]) @@ -1667,6 +1752,79 @@ module AltCoverTests2 = // add 2 extra nop now and replace rather than remove .tails Assert.That(nopsAfter, Is.EqualTo(nopsBefore + tailsBefore + 2)) + [] + let ShouldBeAbleToTrackAnFSTaskMethod () = + use recstream = recorderStream () + + let sample30 = + Path.Combine( + Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName, + "Sample30.dll" + ) + + use def = + Mono.Cecil.AssemblyDefinition.ReadAssembly sample30 + + use rdef = + Mono.Cecil.AssemblyDefinition.ReadAssembly recstream + + let recorder = + AltCover.Instrument.I.recordingMethod rdef + + let target = + def.MainModule.GetType("Sample30.Tests").Methods + |> Seq.find (fun m -> m.Name = "AddTaskReturnsTheSumOfXAndY") + + let raw = AltCover.InstrumentContext.Build([]) + + let state = + { raw with + RecordingMethodRef = + { raw.RecordingMethodRef with + Visit = null + Push = recorder.[1] + Pop = recorder.[2] } } + + let countBefore = target.Body.Instructions.Count + + let tailsBefore = + target.Body.Instructions + |> Seq.filter (fun i -> i.OpCode = OpCodes.Tail) + |> Seq.length + + let nopsBefore = + target.Body.Instructions + |> Seq.filter (fun i -> i.OpCode = OpCodes.Nop) + |> Seq.length + + let handlersBefore = target.Body.ExceptionHandlers.Count + + let state2 = + AltCover.Instrument.I.doTrack + state + { Method = target + VisibleMethod = target + Inspection = Inspections.Track + Track = Some(42, "hello") + DefaultVisitCount = Exemption.None } + + Assert.That(state2.AsyncSupport |> Option.isSome) + + Assert.That( // Adding the return value, too + target.Body.Instructions.Count, + Is.EqualTo(countBefore + 9 + 6) + ) + + Assert.That(target.Body.ExceptionHandlers.Count, Is.EqualTo(handlersBefore + 1)) + + let nopsAfter = + target.Body.Instructions + |> Seq.filter (fun i -> i.OpCode = OpCodes.Nop) + |> Seq.length + // add 2 extra nop now and replace rather than remove .tails + Assert.That(nopsAfter, Is.EqualTo(nopsBefore + tailsBefore + 2)) + [] let ShouldBeAbleToInstrumentASwitchForNCover () = use recstream = recorderStream () @@ -1869,9 +2027,9 @@ module AltCoverTests2 = match branches with | [ b1; b2 ] -> - Assert.That(b1.Start.OpCode, Is.EqualTo OpCodes.Switch) - Assert.That(b2.Start.OpCode, Is.EqualTo OpCodes.Switch) - Assert.That(b1.Start.Offset, Is.EqualTo b2.Start.Offset) + Assert.That(b1.Start.OpCode, Is.EqualTo OpCodes.Switch) + Assert.That(b2.Start.OpCode, Is.EqualTo OpCodes.Switch) + Assert.That(b1.Start.Offset, Is.EqualTo b2.Start.Offset) let raw = AltCover.InstrumentContext.Build([]) @@ -1968,10 +2126,10 @@ module AltCoverTests2 = match branches with | [ b1; b2 ] -> - //Assert.That(b1.Start.OpCode, Is.EqualTo OpCodes.Brfalse_S) - //Assert.That(b2.Start.OpCode, Is.EqualTo OpCodes.Brfalse_S) + //Assert.That(b1.Start.OpCode, Is.EqualTo OpCodes.Brfalse_S) + //Assert.That(b2.Start.OpCode, Is.EqualTo OpCodes.Brfalse_S) - Assert.That(b1.Start.Offset, Is.EqualTo b2.Start.Offset) + Assert.That(b1.Start.Offset, Is.EqualTo b2.Start.Offset) let raw = AltCover.InstrumentContext.Build([]) @@ -2553,6 +2711,7 @@ module AltCoverTests2 = Node.Assembly { Assembly = def Inspection = Inspections.Ignore + Identity = Hallmark.Build() Destinations = [] } let result = @@ -2562,6 +2721,10 @@ module AltCoverTests2 = [] let IncludedAssemblyRefsAreUpdated () = + // do trivial coverage here where the type's absence is felt + let dummy = + AltCover.Recorder.InstrumentationAttribute() + let path = Path.Combine(AltCoverTests.dir, "Sample2.dll") @@ -2593,6 +2756,7 @@ module AltCoverTests2 = Node.Assembly { Assembly = def Inspection = Inspections.Instrument + Identity = Hallmark.Build() Destinations = [] } let result = @@ -3078,12 +3242,12 @@ module AltCoverTests2 = use reader = new StreamReader(stream) let expected = reader.ReadToEnd() - let recorderVersion() = + let recorderVersion () = use stream = recorderStream () use def = AssemblyDefinition.ReadAssembly stream def.Name.Version.ToString() - let version = recorderVersion() + let version = recorderVersion () let result = expected @@ -3116,10 +3280,12 @@ module AltCoverTests2 = Assert.Throws (fun () -> - ignore (Instrument.I.instrumentationVisitorWrapper - (fun _ _ -> InvalidOperationException("Bang") |> raise) - state - AfterType)) + ignore ( + Instrument.I.instrumentationVisitorWrapper + (fun _ _ -> InvalidOperationException("Bang") |> raise) + state + AfterType + )) |> ignore let output = Path.GetTempFileName() @@ -3146,7 +3312,7 @@ module AltCoverTests2 = let md = prepared.MainModule.Types - |> Seq.filter (fun t -> t.FullName = "Sample3.Class3") + |> Seq.filter (fun t -> t.FullName = "AltCover.Sample3.Class3") |> Seq.collect (fun t -> t.Methods) |> Seq.filter (fun m -> m.Name = "Log") |> Seq.head @@ -3160,10 +3326,12 @@ module AltCoverTests2 = Assert.Throws (fun () -> - ignore (Instrument.I.instrumentationVisitorWrapper - (fun _ _ -> InvalidOperationException("Bang") |> raise) - state - AfterType)) + ignore ( + Instrument.I.instrumentationVisitorWrapper + (fun _ _ -> InvalidOperationException("Bang") |> raise) + state + AfterType + )) |> ignore Assert.That(support.TaskAssembly.FullName, Is.Not.Null) // nothing to raise an object disposed exception with @@ -3192,10 +3360,12 @@ module AltCoverTests2 = // Would be NullreferenceException if we tried it Assert.Throws (fun () -> - ignore (Instrument.I.instrumentationVisitorWrapper - (fun _ _ -> InvalidOperationException("Bang") |> raise) - state - AfterType)) + ignore ( + Instrument.I.instrumentationVisitorWrapper + (fun _ _ -> InvalidOperationException("Bang") |> raise) + state + AfterType + )) |> ignore [] @@ -3212,10 +3382,12 @@ module AltCoverTests2 = Assert.Throws (fun () -> - ignore (Instrument.I.instrumentationVisitorWrapper - (fun _ _ -> InvalidOperationException("Bang") |> raise) - state - Finish)) + ignore ( + Instrument.I.instrumentationVisitorWrapper + (fun _ _ -> InvalidOperationException("Bang") |> raise) + state + Finish + )) |> ignore let output = Path.GetTempFileName() @@ -3408,12 +3580,12 @@ module AltCoverTests2 = let c0 = c |> Seq.head let p = c0.GetParameters().Length - let o = c0.Invoke(Maybe (p = 0) null [| sink |]) + let o = c0.Invoke(Maybe(p = 0) null [| sink |]) let invoke = t.GetMethod("Invoke") let param = invoke.GetParameters() |> Seq.head - let arg : obj = + let arg: obj = if param.ParameterType = typeof then String.Empty :> obj else diff --git a/AltCover.Tests/Tests3.fs b/AltCover.Tests/Tests3.fs index 78718e51d..5eff0ba28 100644 --- a/AltCover.Tests/Tests3.fs +++ b/AltCover.Tests/Tests3.fs @@ -285,8 +285,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(x, Is.EqualTo "UsageError") - Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) [] let ParsingJunkBeforeSeparatorIsAnError () = @@ -302,8 +302,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(x, Is.EqualTo "UsageError") - Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) [] let ParsingJunkAfterSeparatorIsExpected () = @@ -320,8 +320,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(x, Is.EquivalentTo(input |> Seq.skip 1)) - Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EquivalentTo(input |> Seq.skip 1)) + Assert.That(y, Is.SameAs options) [] let ParsingHelpGivesHelp () = @@ -337,14 +337,15 @@ module AltCoverTests3 = match CommandLine.processHelpOption parse with | Left (x, y) -> - Assert.That(x, Is.EqualTo "HelpText") - Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "HelpText") + Assert.That(y, Is.SameAs options) // a "not sticky" test match CommandLine.parseCommandLine [| "/t"; "x" |] options - |> CommandLine.processHelpOption with + |> CommandLine.processHelpOption + with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) [] let ParsingErrorHelpGivesHelp () = @@ -360,19 +361,20 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(x, Is.EqualTo "UsageError") - Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) match CommandLine.processHelpOption parse with | Left (x, y) -> - Assert.That(x, Is.EqualTo "UsageError") - Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) // a "not sticky" test match CommandLine.parseCommandLine [| "/t"; "x" |] options - |> CommandLine.processHelpOption with + |> CommandLine.processHelpOption + with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) [] let ParsingAttributesGivesAttributes () = @@ -398,8 +400,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.nameFilters.Count, Is.EqualTo 7) @@ -457,8 +459,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.topLevel.Count, Is.EqualTo 7) @@ -502,8 +504,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.nameFilters.Count, Is.EqualTo 8) @@ -565,8 +567,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.nameFilters.Count, Is.EqualTo 9) @@ -629,8 +631,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.nameFilters.Count, Is.EqualTo 8) @@ -693,8 +695,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.nameFilters.Count, Is.EqualTo 7) @@ -755,8 +757,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.nameFilters.Count, Is.EqualTo 8) @@ -818,8 +820,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.nameFilters.Count, Is.EqualTo 8) @@ -881,8 +883,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.nameFilters.Count, Is.EqualTo 8) @@ -940,8 +942,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match CoverageParameters.theReportPath with | Some x -> Assert.That(Path.GetFileName x, Is.EqualTo unique) @@ -968,13 +970,13 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--report : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--report : specify this only once" + ) finally CoverageParameters.theReportPath <- None @@ -996,8 +998,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.theReportPath <- None @@ -1016,8 +1018,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.theReportPath <- None @@ -1036,8 +1038,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.theReportPath <- None @@ -1056,12 +1058,13 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match CoverageParameters.theInputDirectories - |> Seq.toList with - | [ x ] -> Assert.That(x, Is.EqualTo (canonicalDirectory unique)) + |> Seq.toList + with + | [ x ] -> Assert.That(x, Is.EqualTo(canonicalDirectory unique)) finally CoverageParameters.theInputDirectories.Clear() @@ -1076,37 +1079,34 @@ module AltCoverTests3 = let options = Main.I.declareOptions () - let input = - [| "-i" - "." - "/i" - ".." |] + let input = [| "-i"; "."; "/i"; ".." |] let parse = CommandLine.parseCommandLine input options - let pcom a b = Path.Combine(b, a) |> canonicalDirectory + let pcom a b = + Path.Combine(b, a) |> canonicalDirectory match parse with | Right _ -> - CoverageParameters.inputDirectories () - |> Seq.toList - |> List.zip ([ "."; ".." ] |> List.map canonicalDirectory) - |> List.iter Assert.AreEqual + CoverageParameters.inputDirectories () + |> Seq.toList + |> List.zip ([ "."; ".." ] |> List.map canonicalDirectory) + |> List.iter Assert.AreEqual - CoverageParameters.outputDirectories () - |> Seq.toList - |> List.zip ([ "."; ".." ] |> List.map (pcom "__Instrumented")) - |> List.iter Assert.AreEqual + CoverageParameters.outputDirectories () + |> Seq.toList + |> List.zip ([ "."; ".." ] |> List.map (pcom "__Instrumented")) + |> List.iter Assert.AreEqual - CoverageParameters.inplace.Value <- true - CoverageParameters.theOutputDirectories.Add "maybe" + CoverageParameters.inplace.Value <- true + CoverageParameters.theOutputDirectories.Add "maybe" - CoverageParameters.outputDirectories () - |> Seq.toList - |> List.zip [ canonicalDirectory "maybe" - ".." |> (pcom "__Saved") ] - |> List.iter Assert.AreEqual + CoverageParameters.outputDirectories () + |> Seq.toList + |> List.zip [ canonicalDirectory "maybe" + ".." |> (pcom "__Saved") ] + |> List.iter Assert.AreEqual finally CoverageParameters.theOutputDirectories.Clear() @@ -1128,16 +1128,16 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") - - Assert.That( - CommandLine.error, - Is.EquivalentTo( - [ (canonicalDirectory here) - + " was already specified for --inputDirectory" ] - ) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") + + Assert.That( + CommandLine.error, + Is.EquivalentTo( + [ (canonicalDirectory here) + + " was already specified for --inputDirectory" ] ) + ) finally CoverageParameters.theInputDirectories.Clear() @@ -1159,8 +1159,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.theInputDirectories.Clear() @@ -1178,8 +1178,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.theInputDirectories.Clear() @@ -1198,12 +1198,13 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match CoverageParameters.outputDirectories () - |> Seq.toList with - | [ x ] -> Assert.That(canonicalDirectory x, Is.EqualTo (canonicalDirectory unique)) + |> Seq.toList + with + | [ x ] -> Assert.That(canonicalDirectory x, Is.EqualTo(canonicalDirectory unique)) finally CoverageParameters.theOutputDirectories.Clear() @@ -1222,16 +1223,16 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") - - Assert.That( - CommandLine.error, - Is.EquivalentTo( - [ (canonicalDirectory unique) - + " was already specified for --outputDirectory" ] - ) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") + + Assert.That( + CommandLine.error, + Is.EquivalentTo( + [ (canonicalDirectory unique) + + " was already specified for --outputDirectory" ] ) + ) finally CoverageParameters.theOutputDirectories.Clear() @@ -1257,12 +1258,12 @@ module AltCoverTests3 = match parse with | Right _ -> - Assert.That(CoverageParameters.theOutputDirectories, Is.EquivalentTo outs) + Assert.That(CoverageParameters.theOutputDirectories, Is.EquivalentTo outs) - Assert.That( - CoverageParameters.outputDirectories (), - Is.EquivalentTo(outs |> Seq.take 1) - ) + Assert.That( + CoverageParameters.outputDirectories (), + Is.EquivalentTo(outs |> Seq.take 1) + ) finally CoverageParameters.theOutputDirectories.Clear() @@ -1284,8 +1285,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.theOutputDirectories.Clear() @@ -1303,8 +1304,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.theOutputDirectories.Clear() @@ -1322,8 +1323,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.theOutputDirectories.Clear() @@ -1342,8 +1343,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match ProgramDatabase.symbolFolders.Count with | 1 -> Assert.That(ProgramDatabase.symbolFolders, Is.EquivalentTo [ unique ]) @@ -1369,15 +1370,15 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match ProgramDatabase.symbolFolders.Count with | 2 -> - Assert.That( - ProgramDatabase.symbolFolders, - Is.EquivalentTo(symbol |> Seq.filter (fun x -> x.Length > 2)) - ) + Assert.That( + ProgramDatabase.symbolFolders, + Is.EquivalentTo(symbol |> Seq.filter (fun x -> x.Length > 2)) + ) finally ProgramDatabase.symbolFolders.Clear() @@ -1399,8 +1400,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally ProgramDatabase.symbolFolders.Clear() @@ -1418,8 +1419,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally ProgramDatabase.symbolFolders.Clear() @@ -1442,8 +1443,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) let expected = Instrument.resolutionTable.Keys @@ -1489,8 +1490,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally Instrument.resolutionTable.Clear() @@ -1514,8 +1515,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.defaultStrongNameKey <- None CoverageParameters.keys.Clear() @@ -1539,17 +1540,17 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match CoverageParameters.defaultStrongNameKey with | Some x -> - let token = - x - |> KeyStore.tokenOfKey - |> List.map (fun x -> x.ToString("x2")) + let token = + x + |> KeyStore.tokenOfKey + |> List.map (fun x -> x.ToString("x2")) - Assert.That(String.Join(String.Empty, token), Is.EqualTo("c02b1a9f5b7cade8")) + Assert.That(String.Join(String.Empty, token), Is.EqualTo("c02b1a9f5b7cade8")) finally CoverageParameters.defaultStrongNameKey <- None CoverageParameters.keys.Clear() @@ -1576,13 +1577,13 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--strongNameKey : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--strongNameKey : specify this only once" + ) finally CoverageParameters.defaultStrongNameKey <- None CoverageParameters.keys.Clear() @@ -1607,8 +1608,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.defaultStrongNameKey <- None CoverageParameters.keys.Clear() @@ -1630,8 +1631,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.defaultStrongNameKey <- None CoverageParameters.keys.Clear() @@ -1652,8 +1653,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.defaultStrongNameKey <- None CoverageParameters.keys.Clear() @@ -1680,8 +1681,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) let expected = CoverageParameters.keys.Keys @@ -1718,8 +1719,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.defaultStrongNameKey <- None CoverageParameters.keys.Clear() @@ -1744,8 +1745,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.defaultStrongNameKey <- None CoverageParameters.keys.Clear() @@ -1767,8 +1768,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.defaultStrongNameKey <- None CoverageParameters.keys.Clear() @@ -1787,8 +1788,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.local.Value, Is.True) finally @@ -1808,13 +1809,13 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--localSource : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--localSource : specify this only once" + ) finally CoverageParameters.local.Value <- false @@ -1832,8 +1833,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.coalesceBranches.Value, Is.True) finally @@ -1853,13 +1854,13 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--visibleBranches : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--visibleBranches : specify this only once" + ) finally CoverageParameters.coalesceBranches.Value <- false @@ -1874,8 +1875,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That( CoverageParameters.staticFilter, @@ -1893,8 +1894,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That( CoverageParameters.staticFilter, @@ -1912,8 +1913,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That( CoverageParameters.staticFilter, @@ -1931,8 +1932,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That( CoverageParameters.staticFilter, @@ -1953,18 +1954,18 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--showstatic : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--showstatic : specify this only once" + ) - Assert.That( - CoverageParameters.staticFilter, - StaticFilter.NoFilter |> Some |> Is.EqualTo - ) + Assert.That( + CoverageParameters.staticFilter, + StaticFilter.NoFilter |> Some |> Is.EqualTo + ) [] let ParsingJunkStaticGivesFailure () = @@ -1978,13 +1979,13 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo("--showstatic : cannot be '" + tag + "'") - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo("--showstatic : cannot be '" + tag + "'") + ) [] let ParsingTimeGivesTime () = @@ -2002,8 +2003,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.interval (), Is.EqualTo 100) finally @@ -2026,8 +2027,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") Assert.That(CoverageParameters.interval (), Is.EqualTo 0) finally @@ -2051,14 +2052,14 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") - Assert.That(CoverageParameters.interval (), Is.EqualTo 10000) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") + Assert.That(CoverageParameters.interval (), Is.EqualTo 10000) - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--callContext : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--callContext : specify this only once" + ) finally CoverageParameters.theInterval <- None CoverageParameters.trackingNames.Clear() @@ -2087,8 +2088,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.interval (), Is.EqualTo 10000) @@ -2120,8 +2121,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.interval (), Is.EqualTo 0) finally @@ -2145,8 +2146,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.theInterval <- None CoverageParameters.trackingNames.Clear() @@ -2167,8 +2168,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.theInterval <- None CoverageParameters.trackingNames.Clear() @@ -2187,8 +2188,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match CoverageParameters.theReportFormat with | Some x -> Assert.That(x, Is.EqualTo AltCover.ReportFormat.NCover) @@ -2209,8 +2210,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match CoverageParameters.theReportFormat with | Some x -> Assert.That(x, Is.EqualTo AltCover.ReportFormat.NativeJson) @@ -2231,8 +2232,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) match CoverageParameters.theReportFormat with | Some x -> Assert.That(x, Is.EqualTo AltCover.ReportFormat.OpenCover) @@ -2256,13 +2257,13 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--reportFormat : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--reportFormat : specify this only once" + ) finally CoverageParameters.theReportFormat <- None @@ -2280,8 +2281,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.inplace.Value, Is.True) finally @@ -2301,13 +2302,13 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--inplace : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--inplace : specify this only once" + ) finally CoverageParameters.inplace.Value <- false @@ -2325,9 +2326,9 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) - Assert.That(CoverageParameters.collect.Value, Is.True) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) + Assert.That(CoverageParameters.collect.Value, Is.True) finally CoverageParameters.collect.Value <- false @@ -2345,13 +2346,13 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--save : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--save : specify this only once" + ) finally CoverageParameters.collect.Value <- false @@ -2369,8 +2370,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.single, Is.True) finally @@ -2390,13 +2391,13 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--single : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--single : specify this only once" + ) finally CoverageParameters.single <- false @@ -2414,8 +2415,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.coverstyle, Is.EqualTo CoverStyle.LineOnly) @@ -2445,8 +2446,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.coverstyle, Is.EqualTo CoverStyle.LineOnly) @@ -2475,8 +2476,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.coverstyle, Is.EqualTo CoverStyle.LineOnly) @@ -2500,13 +2501,13 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--linecover : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--linecover : specify this only once" + ) finally CoverageParameters.coverstyle <- CoverStyle.All @@ -2524,8 +2525,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.coverstyle <- CoverStyle.All @@ -2543,8 +2544,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.coverstyle, Is.EqualTo CoverStyle.BranchOnly) @@ -2574,8 +2575,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.coverstyle, Is.EqualTo CoverStyle.BranchOnly) @@ -2604,8 +2605,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.coverstyle, Is.EqualTo CoverStyle.BranchOnly) @@ -2629,13 +2630,13 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--branchcover : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--branchcover : specify this only once" + ) finally CoverageParameters.coverstyle <- CoverStyle.All @@ -2653,8 +2654,8 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") finally CoverageParameters.coverstyle <- CoverStyle.All @@ -2672,8 +2673,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CommandLine.dropReturnCode.Value, Is.True) finally @@ -2696,13 +2697,13 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--dropReturnCode : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--dropReturnCode : specify this only once" + ) finally CommandLine.dropReturnCode.Value <- false @@ -2719,8 +2720,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CoverageParameters.defer.Value) Assert.That(CoverageParameters.deferOpCode (), Is.EqualTo OpCodes.Ldc_I4_1) @@ -2740,13 +2741,13 @@ module AltCoverTests3 = match parse with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") - Assert.That( - CommandLine.error |> Seq.head, - Is.EqualTo "--defer : specify this only once" - ) + Assert.That( + CommandLine.error |> Seq.head, + Is.EqualTo "--defer : specify this only once" + ) finally CoverageParameters.defer.Value <- false @@ -2764,8 +2765,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CommandLine.verbosity, Is.EqualTo 1) finally @@ -2784,8 +2785,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CommandLine.verbosity, Is.EqualTo 3) finally @@ -2804,8 +2805,8 @@ module AltCoverTests3 = match parse with | Right (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.Empty) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.Empty) Assert.That(CommandLine.verbosity, Is.EqualTo 2) finally @@ -2851,18 +2852,18 @@ module AltCoverTests3 = match Main.I.processOutputLocation fail with | Left (x, y) -> - Assert.That(y, Is.SameAs options) - Assert.That(x, Is.EqualTo "UsageError") - Assert.That(stderr.ToString(), Is.Empty) - - Assert.That( - CommandLine.error, - Is.EquivalentTo [ "From and to directories " - + here - + " are identical" ] - ) + Assert.That(y, Is.SameAs options) + Assert.That(x, Is.EqualTo "UsageError") + Assert.That(stderr.ToString(), Is.Empty) + + Assert.That( + CommandLine.error, + Is.EquivalentTo [ "From and to directories " + + here + + " are identical" ] + ) - Assert.That(stdout.ToString(), Is.Empty) + Assert.That(stdout.ToString(), Is.Empty) finally Console.SetOut(fst saved) Console.SetError(snd saved) @@ -2894,32 +2895,40 @@ module AltCoverTests3 = match Main.I.processOutputLocation ok with | Right (x, y, z, t) -> - Assert.That(x, Is.SameAs rest) - - y - |> Seq.iter (fun y' -> Assert.That(y'.FullName |> canonicalDirectory, Is.EqualTo (canonicalDirectory here))) - - z - |> Seq.iter - (fun z' -> - Assert.That(z'.FullName |> canonicalDirectory, Is.EqualTo(canonicalDirectory (Path.GetDirectoryName here)))) - - t - |> Seq.zip y - |> Seq.iter (fun (t', y') -> Assert.That(t'.FullName, Is.EqualTo y'.FullName)) - - Assert.That( - stdout.ToString().Replace("\r", String.Empty), - Is.EqualTo( - "Instrumenting files from " - + here - + "\nWriting files to " - + (canonicalDirectory (Path.GetDirectoryName here)) - + "\n" - ) + Assert.That(x, Is.SameAs rest) + + y + |> Seq.iter + (fun y' -> + Assert.That( + y'.FullName |> canonicalDirectory, + Is.EqualTo(canonicalDirectory here) + )) + + z + |> Seq.iter + (fun z' -> + Assert.That( + z'.FullName |> canonicalDirectory, + Is.EqualTo(canonicalDirectory (Path.GetDirectoryName here)) + )) + + t + |> Seq.zip y + |> Seq.iter (fun (t', y') -> Assert.That(t'.FullName, Is.EqualTo y'.FullName)) + + Assert.That( + stdout.ToString().Replace("\r", String.Empty), + Is.EqualTo( + "Instrumenting files from " + + here + + "\nWriting files to " + + (canonicalDirectory (Path.GetDirectoryName here)) + + "\n" ) + ) - Assert.That(stderr.ToString(), Is.Empty) + Assert.That(stderr.ToString(), Is.Empty) finally Console.SetOut(fst saved) Console.SetError(snd saved) @@ -2956,32 +2965,33 @@ module AltCoverTests3 = match Main.I.processOutputLocation ok with | Right (x, y, z, t) -> - Assert.That(x, Is.SameAs rest) - - y - |> Seq.iter (fun y' -> Assert.That(y'.FullName, Is.EqualTo here)) - - z - |> Seq.iter (fun z' -> Assert.That(z'.FullName, Is.EqualTo (canonicalDirectory there))) - - t - |> Seq.iter (fun t' -> Assert.That(t'.FullName, Is.EqualTo here)) - - Assert.That( - stdout.ToString().Replace("\r", String.Empty), - Is.EqualTo( - "Creating folder " - + (canonicalDirectory there) - + "\nInstrumenting files from " - + here - + "\nWriting files to " - + (canonicalDirectory there) - + "\n" - ) + Assert.That(x, Is.SameAs rest) + + y + |> Seq.iter (fun y' -> Assert.That(y'.FullName, Is.EqualTo here)) + + z + |> Seq.iter + (fun z' -> Assert.That(z'.FullName, Is.EqualTo(canonicalDirectory there))) + + t + |> Seq.iter (fun t' -> Assert.That(t'.FullName, Is.EqualTo here)) + + Assert.That( + stdout.ToString().Replace("\r", String.Empty), + Is.EqualTo( + "Creating folder " + + (canonicalDirectory there) + + "\nInstrumenting files from " + + here + + "\nWriting files to " + + (canonicalDirectory there) + + "\n" ) + ) - Assert.That(stderr.ToString(), Is.Empty) - Assert.That(Directory.Exists there) + Assert.That(stderr.ToString(), Is.Empty) + Assert.That(Directory.Exists there) finally Console.SetOut(fst saved) Console.SetError(snd saved) @@ -3013,16 +3023,16 @@ module AltCoverTests3 = match Main.I.processOutputLocation ok with | Left _ -> - Assert.That(stdout.ToString(), Is.Empty) - Assert.That(stderr.ToString(), Is.Empty) - - Assert.That( - CommandLine.error, - Is.EquivalentTo [ "Output directory for saved files " - + (CoverageParameters.outputDirectories () - |> Seq.head) - + " already exists" ] - ) + Assert.That(stdout.ToString(), Is.Empty) + Assert.That(stderr.ToString(), Is.Empty) + + Assert.That( + CommandLine.error, + Is.EquivalentTo [ "Output directory for saved files " + + (CoverageParameters.outputDirectories () + |> Seq.head) + + " already exists" ] + ) finally CoverageParameters.inplace.Value <- false Console.SetOut(fst saved) @@ -3062,44 +3072,44 @@ module AltCoverTests3 = match Main.I.processOutputLocation ok with | Right (x, y, z, t) -> - Assert.That(x, Is.SameAs rest) - - y - |> Seq.iter (fun y' -> Assert.That(y'.FullName, Is.EqualTo here)) - - z - |> Seq.iter (fun z' -> Assert.That(z'.FullName, Is.EqualTo there)) - - t - |> Seq.iter (fun t' -> Assert.That(t'.FullName, Is.EqualTo there)) - - Assert.That( - stdout.ToString().Replace("\r", String.Empty), - Is.EqualTo( - "Creating folder " - + there - + "\nSaving files to " - + there - + "\nInstrumenting files in " - + here - + "\n" - ) - ) + Assert.That(x, Is.SameAs rest) - Assert.That(stderr.ToString(), Is.Empty) - Assert.That(Directory.Exists there) + y + |> Seq.iter (fun y' -> Assert.That(y'.FullName, Is.EqualTo here)) - Assert.That( - CoverageParameters.sourceDirectories () - |> Seq.head, - Is.EqualTo there - ) + z + |> Seq.iter (fun z' -> Assert.That(z'.FullName, Is.EqualTo there)) - Assert.That( - CoverageParameters.instrumentDirectories () - |> Seq.head, - Is.EqualTo here + t + |> Seq.iter (fun t' -> Assert.That(t'.FullName, Is.EqualTo there)) + + Assert.That( + stdout.ToString().Replace("\r", String.Empty), + Is.EqualTo( + "Creating folder " + + there + + "\nSaving files to " + + there + + "\nInstrumenting files in " + + here + + "\n" ) + ) + + Assert.That(stderr.ToString(), Is.Empty) + Assert.That(Directory.Exists there) + + Assert.That( + CoverageParameters.sourceDirectories () + |> Seq.head, + Is.EqualTo there + ) + + Assert.That( + CoverageParameters.instrumentDirectories () + |> Seq.head, + Is.EqualTo here + ) finally CoverageParameters.inplace.Value <- false Console.SetOut(fst saved) @@ -3175,20 +3185,132 @@ module AltCoverTests3 = [] let FolderNestingIsDetectedCorrectly () = let dir = canonicalDirectory "some/path/" - let file1 = Path.Combine (canonicalDirectory "different", "path") + + let file1 = + Path.Combine(canonicalDirectory "different", "path") + test <@ (Main.I.isInDirectory file1 dir) |> not @> - let file2 = Path.Combine (canonicalDirectory "some/pathway", "a.b") + + let file2 = + Path.Combine(canonicalDirectory "some/pathway", "a.b") + test <@ (Main.I.isInDirectory file2 dir) |> not @> - let file3 = Path.Combine (canonicalDirectory "some/path/nested", "a.b") + + let file3 = + Path.Combine(canonicalDirectory "some/path/nested", "a.b") + test <@ (Main.I.isInDirectory file3 dir) @> + [] + let ScreeningFilesShouldRejectTheInstrumentedOnes () = + Main.init () + // because mono symbol-writing is broken, work around trying to + // examine the instrumented files in a self-test run. + let here = + Path.Combine( + SolutionRoot.location, + "_Binaries/Sample4LongForm/Debug+AnyCPU/legacy/net472" + ) + + maybeIgnore (fun () -> here |> Directory.Exists |> not) + + //let there = + // Path.Combine( + // Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), + // Guid.NewGuid().ToString() + // ) + + let save = Output.warn + + try + let sb = System.Text.StringBuilder() + let warn (s: String) = s |> sb.Append |> ignore + Output.warn <- warn + + here + |> Directory.GetFiles + |> Seq.filter + (fun f -> + match Path.GetExtension f with + | ".dll" + | ".exe" -> true + | _ -> false) + |> Seq.iter + (fun f -> + use stream = File.OpenRead(f) + + use def = + Mono.Cecil.AssemblyDefinition.ReadAssembly(stream) + + ProgramDatabase.readSymbols def + + let result = + Main.I.screenAssembly (Path.GetFileName f) def + + Assert.True(result |> Option.isSome, f)) + + Assert.That(sb.ToString(), Is.Empty) + + let path = + Path.Combine(AltCoverTests.dir, "Sample3.dll") + + let prepared = + Instrument.I.prepareAssembly (File.OpenRead path) + + //Instrument.I.writeAssembly prepared (Path.Combine(there, "Sample3.dll")) + + let second = Path.Combine(here, "Sample4.dll") + + use assembly = + Mono.Cecil.AssemblyDefinition.ReadAssembly second + + assembly.MainModule.AssemblyReferences.Add(prepared.Name) + + let entry = + { Assembly = assembly + Inspection = Inspections.Ignore + Destinations = [] + Identity = + { Assembly = "Sample4.dll" + Configuration = "ScreeningFilesShouldRejectTheInstrumentedOnes" } } + + Instrument.I.injectInstrumentation prepared entry + //Instrument.I.writeAssembly assembly (Path.Combine(there, "Sample4.dll") + + let s1 = + Main.I.screenAssembly "Sample3.dll" prepared + + Assert.True(s1 |> Option.isNone, "Sample3.dll") + + Environment.NewLine |> sb.Append |> ignore + + let s1 = + Main.I.screenAssembly "Sample4.dll" assembly + + Assert.True(s1 |> Option.isNone, "Sample4.dll") + + let expected = + "Skipping Sample3.dll as it has already been instrumented." + + Environment.NewLine + + "Skipping Sample4.dll as it has already been instrumented." + + Assert.That(sb.ToString(), Is.EqualTo expected) + + finally + Output.warn <- save + [] let PreparingNewPlaceShouldCopyEverything () = Main.init () // because mono symbol-writing is broken, work around trying to // examine the instrumented files in a self-test run. let here = - Path.Combine(SolutionRoot.location, "_Binaries/Sample4/Debug+AnyCPU/legacy/net472") + Path.Combine( + SolutionRoot.location, + "_Binaries/Sample4LongForm/Debug+AnyCPU/legacy/net472" + ) + + maybeIgnore (fun () -> here |> Directory.Exists |> not) let there = Path.Combine( @@ -3208,8 +3330,12 @@ module AltCoverTests3 = let tlen = there.Length Assert.That( - t.EnumerateFiles("*", SearchOption.AllDirectories) |> Seq.map (fun x -> x.FullName.Substring(tlen)), - Is.EquivalentTo(f.EnumerateFiles("*", SearchOption.AllDirectories) |> Seq.map (fun x -> x.FullName.Substring(flen))), + t.EnumerateFiles("*", SearchOption.AllDirectories) + |> Seq.map (fun x -> x.FullName.Substring(tlen)), + Is.EquivalentTo( + f.EnumerateFiles("*", SearchOption.AllDirectories) + |> Seq.map (fun x -> x.FullName.Substring(flen)) + ), "Simple to-from comparison failed" ) @@ -3218,8 +3344,15 @@ module AltCoverTests3 = //f.EnumerateFiles("*", SearchOption.AllDirectories) |> Seq.map (fun x -> x.FullName.Substring(flen)) //|> Seq.iter (printfn "%A") - Assert.That (File.Exists <| Path.Combine(here, "eo/Sample4.resources.dll")) - Assert.That (File.Exists <| Path.Combine(there, "eo/Sample4.resources.dll")) + Assert.That( + File.Exists + <| Path.Combine(here, "eo/Sample4.resources.dll") + ) + + Assert.That( + File.Exists + <| Path.Combine(there, "eo/Sample4.resources.dll") + ) Assert.That( y, @@ -3496,9 +3629,11 @@ module AltCoverTests3 = test <@ stdout .ToString() - .Equals(expected.Replace("\\\\", "\\") - + Environment.NewLine, - StringComparison.Ordinal) @> + .Equals( + expected.Replace("\\\\", "\\") + + Environment.NewLine, + StringComparison.Ordinal + ) @> finally Console.SetOut(fst saved) Console.SetError(snd saved) @@ -3610,8 +3745,13 @@ module AltCoverTests3 = test <@ synthetic = helptext @> #if !MONO // Mono won't play nicely with Esperanto placeholder locale // remove for fantomas - let dir = System.Reflection.Assembly.GetExecutingAssembly().Location - |> Path.GetDirectoryName + let dir = + System + .Reflection + .Assembly + .GetExecutingAssembly() + .Location + |> Path.GetDirectoryName let eo = Path.Combine(dir, "./eo/AltCover.Engine.resources.dll") @@ -3896,8 +4036,7 @@ module AltCoverTests3 = let x = Assert.Throws - (fun () -> - ignore (message.Invoke(subject, [| "x" :> obj |]))) + (fun () -> ignore (message.Invoke(subject, [| "x" :> obj |]))) Assert.That( x.InnerException, @@ -4049,8 +4188,7 @@ module AltCoverTests3 = let x = Assert.Throws - (fun () -> - ignore (message.Invoke(subject, [| "x" :> obj |]))) + (fun () -> ignore (message.Invoke(subject, [| "x" :> obj |]))) Assert.That( x.InnerException, @@ -4249,7 +4387,8 @@ module AltCoverTests3 = Assert.That(subject.Execute(), Is.False) Assert.That(subject.Extended, Is.Empty) - let template = """ + let template = + """ {1} @@ -4498,22 +4637,32 @@ module AltCoverTests3 = test <@ target |> File.Exists @> subject.FileName <- "Foo.txt" - let projectdir = Path.Combine(SolutionRoot.location, - "Samples/Sample4") - let builddir = Path.Combine(SolutionRoot.location, + + let projectdir = + Path.Combine(SolutionRoot.location, "Samples/Sample4") + + let builddir = + Path.Combine( + SolutionRoot.location, #if !NET472 - "_Binaries/Sample4/Debug+AnyCPU/netcoreapp2.1") + "_Binaries/Sample4/Debug+AnyCPU/netcoreapp2.1" + ) #else - "_Binaries/Sample4/Debug+AnyCPU/net472") + "_Binaries/Sample4/Debug+AnyCPU/net472" + ) #endif - subject.RelativeDir <- Path.Combine (projectdir, "Data/Deeper") + subject.RelativeDir <- Path.Combine(projectdir, "Data/Deeper") subject.BuildOutputDirectory <- builddir subject.ProjectDir <- projectdir + let target2 = Path.Combine(subject.InstrumentDirectory, "Data/Deeper/Foo.txt") - test <@ Path.Combine (builddir, "Data/Deeper/Foo.txt") |> File.Exists @> + test + <@ Path.Combine(builddir, "Data/Deeper/Foo.txt") + |> File.Exists @> + test <@ target2 |> File.Exists |> not @> test <@ subject.Execute() @> test <@ target2 |> File.Exists @> @@ -4557,7 +4706,7 @@ module AltCoverTests3 = .StartsWith(ex.GetType().FullName, StringComparison.Ordinal) @>) let builder = System.Text.StringBuilder() - let monitor (s:string) = s |> builder.Append |> ignore + let monitor (s: string) = s |> builder.Append |> ignore Assert.Throws (fun () -> diff --git a/AltCover.Tests/XTests.fs b/AltCover.Tests/XTests.fs index 1ea991021..13a426656 100644 --- a/AltCover.Tests/XTests.fs +++ b/AltCover.Tests/XTests.fs @@ -19,7 +19,8 @@ module AltCoverXTests = let monoSample1path = Path.Combine(SolutionDir(), "_Mono/Sample1/Sample1.exe") - let MonoBaseline = " + let MonoBaseline = + " @@ -66,22 +67,22 @@ module AltCoverXTests = | "startTime" | "measureTime" -> () | "document" -> - test' - <@ a1 - .Value - .Replace("\\", "/") - .EndsWith(a2.Value.Replace("\\", "/")) @> - (a1.Name.ToString() - + " : " - + r.ToString() - + " -> document") + test' + <@ a1 + .Value + .Replace("\\", "/") + .EndsWith(a2.Value.Replace("\\", "/")) @> + (a1.Name.ToString() + + " : " + + r.ToString() + + " -> document") | "visitcount" -> - let expected = Maybe zero "0" a2.Value - test' <@ expected = a1.Value @> (r.ToString() + " -> visitcount") + let expected = Maybe zero "0" a2.Value + test' <@ expected = a1.Value @> (r.ToString() + " -> visitcount") | _ -> - test' - <@ a1.Value.Replace("\\", "/") = a2.Value.Replace("\\", "/") @> - (r.ToString() + " -> " + a1.Name.ToString())) + test' + <@ a1.Value.Replace("\\", "/") = a2.Value.Replace("\\", "/") @> + (r.ToString() + " -> " + a1.Name.ToString())) RecursiveValidate(r.Elements()) (e.Elements()) (depth + 1) zero) @@ -139,26 +140,29 @@ module AltCoverXTests = | "crapScore" | "hash" -> () | "fullPath" -> - test' - <@ a1 - .Value - .Replace("\\", "/") - .Replace("altcover", "AltCover") - .Replace("Samples/", String.Empty) - .EndsWith(a2.Value - .Replace("\\", "/") - .Replace("altcover", "AltCover")) @> - (a1.Name.ToString() - + " : " - + r.ToString() - + " -> document") + test' + <@ a1 + .Value + .Replace("\\", "/") + .Replace("altcover", "AltCover") + .Replace("Samples/", String.Empty) + .EndsWith( + a2 + .Value + .Replace("\\", "/") + .Replace("altcover", "AltCover") + ) @> + (a1.Name.ToString() + + " : " + + r.ToString() + + " -> document") | "vc" -> - let expected = Maybe zero "0" a2.Value - test' <@ expected = a1.Value @> (r.ToString() + " -> visitcount") + let expected = Maybe zero "0" a2.Value + test' <@ expected = a1.Value @> (r.ToString() + " -> visitcount") | _ -> - test' - <@ a1.Value = a2.Value @> - (r.ToString() + " -> " + a1.Name.ToString())) + test' + <@ a1.Value = a2.Value @> + (r.ToString() + " -> " + a1.Name.ToString())) RecursiveValidateOpenCover (r.Elements()) @@ -774,7 +778,7 @@ module AltCoverXTests = System.Environment.GetEnvironmentVariable("OS") = "Windows_NT" let theFiles = - ( Maybe isWindows ("AltCover.Recorder.g.pdb" :: expected) expected) + expected |> List.sortBy (fun f -> f.ToUpperInvariant()) let actualFiles = @@ -851,9 +855,9 @@ module AltCoverXTests = let reset = match existingDependencies with | Some p -> - (p.Value :?> JObject).Properties() - |> Seq.map (fun p -> p.Name) - |> Set.ofSeq + (p.Value :?> JObject).Properties() + |> Seq.map (fun p -> p.Name) + |> Set.ofSeq test <@ reset |> Set.contains "AltCover.Recorder.g" @> @@ -1009,7 +1013,7 @@ module AltCoverXTests = System.Environment.GetEnvironmentVariable("OS") = "Windows_NT" let expected = - (Maybe isWindows ("AltCover.Recorder.g.pdb" :: theFiles) theFiles) + theFiles |> List.sortBy (fun f -> f.ToUpperInvariant()) test <@ actual = expected @> @@ -1046,7 +1050,7 @@ module AltCoverXTests = let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - use recstream = AltCoverTests2.recorderStream() + use recstream = AltCoverTests2.recorderStream () use recdef = Mono.Cecil.AssemblyDefinition.ReadAssembly recstream @@ -1071,6 +1075,7 @@ module AltCoverXTests = Node.AfterAssembly { Assembly = def Inspection = Inspections.Instrument + Identity = Hallmark.Build() Destinations = CoverageParameters.outputDirectories () } let input = @@ -1105,7 +1110,7 @@ module AltCoverXTests = let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - use recstream = AltCoverTests2.recorderStream() + use recstream = AltCoverTests2.recorderStream () use recdef = Mono.Cecil.AssemblyDefinition.ReadAssembly recstream @@ -1130,6 +1135,7 @@ module AltCoverXTests = Node.AfterAssembly { Assembly = def Inspection = Inspections.Instrument + Identity = Hallmark.Build() Destinations = CoverageParameters.outputDirectories () } let input = @@ -1266,6 +1272,7 @@ module AltCoverXTests = if create |> File.Exists |> not then try CoverageParameters.theReportFormat <- Some ReportFormat.NCover + use from = Assembly .GetExecutingAssembly() @@ -1355,6 +1362,7 @@ module AltCoverXTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let expectedText = @@ -1390,6 +1398,7 @@ module AltCoverXTests = [ visitor ] (Visitor.I.toSeq { AssemblyPath = path + Identity = Hallmark.Build() Destinations = [] }) let resource = diff --git a/AltCover.Toolkit/AltCover.Toolkit.fsproj b/AltCover.Toolkit/AltCover.Toolkit.fsproj index 336deabd9..fb25b0ba4 100644 --- a/AltCover.Toolkit/AltCover.Toolkit.fsproj +++ b/AltCover.Toolkit/AltCover.Toolkit.fsproj @@ -5,34 +5,13 @@ netstandard2.0 AltCover.Toolkit AltCover.Toolkit - false - true RUNNER - $(ProjectDir)../ - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk - - - - false - false - - - true - true TRACE;DEBUG;CODE_ANALYSIS;$(GlobalDefineConstants) - 4 - true - - true - true TRACE;$(GlobalDefineConstants) diff --git a/AltCover.Toolkit/CoverageFormats.fs b/AltCover.Toolkit/CoverageFormats.fs index f412cc4c7..b346d6469 100644 --- a/AltCover.Toolkit/CoverageFormats.fs +++ b/AltCover.Toolkit/CoverageFormats.fs @@ -64,7 +64,13 @@ module CoverageFormats = assemblies |> Seq.map Path.GetFullPath |> Seq.filter (fun p -> identities.ContainsKey paths.[p]) - |> Seq.map (fun p -> { AssemblyPath = p; Destinations = [] }) + |> Seq.map + (fun p -> + { AssemblyPath = p + Destinations = [] + Identity = + { Assembly = String.Empty + Configuration = String.Empty } }) // ensure default state AltCover.Main.init () @@ -106,7 +112,9 @@ module CoverageFormats = |> Seq.iter (fun f -> files.Add( - f.Attribute(XName.Get "fullPath").Value.Replace('\\', '/'), + f + .Attribute(XName.Get "fullPath") + .Value.Replace('\\', '/'), f.Attribute(XName.Get "uid").Value )) @@ -118,8 +126,14 @@ module CoverageFormats = let sc = s.Attribute(XName.Get "column").Value let el = s.Attribute(XName.Get "endline").Value let ec = s.Attribute(XName.Get "endcolumn").Value - let key = s.Attribute(XName.Get "document").Value.Replace('\\', '/') + + let key = + s + .Attribute(XName.Get "document") + .Value.Replace('\\', '/') + let uid = files.[key] + let vc = parse <| s.Attribute(XName.Get "visitcount").Value diff --git a/AltCover.Toolkit/OpenCover.fs b/AltCover.Toolkit/OpenCover.fs index d392b2ccf..3733a506b 100644 --- a/AltCover.Toolkit/OpenCover.fs +++ b/AltCover.Toolkit/OpenCover.fs @@ -50,87 +50,87 @@ module OpenCover = (fun (s: XElement, bs: XElement list) x -> match x.Name.LocalName with | "SequencePoint" -> - let bx = - if withinSequencePoint then - let next = - x.Attribute(XName.Get "offset").Value - |> Int32.TryParse - |> snd - - let (kill, keep) = - bs - |> List.partition - (fun b -> - b.Attribute(XName.Get "offsetend").Value - |> Int32.TryParse - |> snd < next) - - kill |> Seq.iter (fun b -> b.Remove()) - keep - else + let bx = + if withinSequencePoint then + let next = + x.Attribute(XName.Get "offset").Value + |> Int32.TryParse + |> snd + + let (kill, keep) = bs - - let by = - if sameSpan then - let (kill, keep) = - bx - |> List.groupBy - (fun b -> - (b.Attribute(XName.Get "offset").Value, - b.Attribute(XName.Get "offsetchain").Value, - b.Attribute(XName.Get "offsetend").Value)) - |> List.fold - (fun (ki, ke) (_, bz) -> - let totalVisits = - bz - |> Seq.sumBy - (fun b -> - b.Attribute(XName.Get "vc").Value - |> Int32.TryParse - |> snd) - - let h = bz |> Seq.head - - h.SetAttribute( - "vc", - totalVisits.ToString(CultureInfo.InvariantCulture) - ) - - (List.concat [ ki - bz |> Seq.tail |> Seq.toList ], - h :: ke)) - ([], []) - - kill |> Seq.iter (fun b -> b.Remove()) - keep - else + |> List.partition + (fun b -> + b.Attribute(XName.Get "offsetend").Value + |> Int32.TryParse + |> snd < next) + + kill |> Seq.iter (fun b -> b.Remove()) + keep + else + bs + + let by = + if sameSpan then + let (kill, keep) = bx - - // Fix up what remains - by - |> List.rev // because the list will have been built up in reverse order - |> Seq.mapi (fun i b -> (i, b)) - |> Seq.groupBy (fun (_, b) -> b.Attribute(XName.Get "offset").Value) - |> Seq.iter - (fun (_, paths) -> - paths // assume likely ranges for these numbers! - |> Seq.sortBy - (fun (n, p) -> - n - + 100 - * (p.Attribute(XName.Get "offsetend").Value - |> Int32.TryParse - |> snd)) - |> Seq.iteri - (fun i (_, p) -> - p.SetAttribute( - "path", - (i + 1).ToString(CultureInfo.InvariantCulture) - ))) - - s.SetAttribute("bec", by.Length.ToString(CultureInfo.InvariantCulture)) - s.SetAttribute("bev", "0") - (x, []) + |> List.groupBy + (fun b -> + (b.Attribute(XName.Get "offset").Value, + b.Attribute(XName.Get "offsetchain").Value, + b.Attribute(XName.Get "offsetend").Value)) + |> List.fold + (fun (ki, ke) (_, bz) -> + let totalVisits = + bz + |> Seq.sumBy + (fun b -> + b.Attribute(XName.Get "vc").Value + |> Int32.TryParse + |> snd) + + let h = bz |> Seq.head + + h.SetAttribute( + "vc", + totalVisits.ToString(CultureInfo.InvariantCulture) + ) + + (List.concat [ ki + bz |> Seq.tail |> Seq.toList ], + h :: ke)) + ([], []) + + kill |> Seq.iter (fun b -> b.Remove()) + keep + else + bx + + // Fix up what remains + by + |> List.rev // because the list will have been built up in reverse order + |> Seq.mapi (fun i b -> (i, b)) + |> Seq.groupBy (fun (_, b) -> b.Attribute(XName.Get "offset").Value) + |> Seq.iter + (fun (_, paths) -> + paths // assume likely ranges for these numbers! + |> Seq.sortBy + (fun (n, p) -> + n + + 100 + * (p.Attribute(XName.Get "offsetend").Value + |> Int32.TryParse + |> snd)) + |> Seq.iteri + (fun i (_, p) -> + p.SetAttribute( + "path", + (i + 1).ToString(CultureInfo.InvariantCulture) + ))) + + s.SetAttribute("bec", by.Length.ToString(CultureInfo.InvariantCulture)) + s.SetAttribute("bev", "0") + (x, []) | _ -> (s, x :: bs)) (sp.Head, []) |> ignore @@ -279,9 +279,11 @@ module OpenCover = x.Attribute(XName.Get "sc").Value <- s.StartColumn.ToString( CultureInfo.InvariantCulture ) + x.Attribute(XName.Get "ec").Value <- s.EndColumn.ToString( CultureInfo.InvariantCulture ) + x.Attribute(XName.Get "offset").Value <- s.Offset.ToString( CultureInfo.InvariantCulture )))) @@ -349,7 +351,7 @@ module OpenCover = ) if ok then - let line = f.[index - 1] + let line = f.[index - 1] // or Array.get f (index - 1) let cols = line.Length + 1 point.SetAttribute( @@ -365,8 +367,7 @@ module OpenCover = ))) - let private hash = - sha1Hash() + let private hash = sha1Hash () let internal fixFormatModule (m: XElement) (files: string array) = // supply empty module level @@ -763,14 +764,14 @@ coverlet on Tests.AltCoverRunnerTests/PostprocessShouldRestoreDegenerateOpenCove (fun (bev, sq: XElement) x -> match x.Name.LocalName with | "SequencePoint" -> - sq.SetAttributeValue(XName.Get "bev", bev) - (0, x) + sq.SetAttributeValue(XName.Get "bev", bev) + (0, x) | _ -> - let visited = - attributeOrEmpty "vc" x |> Int32.TryParse |> snd + let visited = + attributeOrEmpty "vc" x |> Int32.TryParse |> snd - let delta = if visited > 0 then 1 else 0 - (bev + delta, sq)) + let delta = if visited > 0 then 1 else 0 + (bev + delta, sq)) (0, interleave |> Seq.head) |> ignore @@ -781,81 +782,85 @@ coverlet on Tests.AltCoverRunnerTests/PostprocessShouldRestoreDegenerateOpenCove : (Summary * XElement array) = let metadataToken (group: string * XElement seq) = let mt = XElement(XName.Get "MetadataToken") + group |> snd |> Seq.map (fun m -> m.Element(XName.Get "MetadataToken").Value) |> Seq.tryFind (String.IsNullOrWhiteSpace >> not) |> Option.iter (fun t -> mt.Value <- t) + mt let fileRef modu (group: string * XElement seq) = - group - |> snd - |> Seq.collect (fun x -> x.Elements(XName.Get "FileRef")) - |> Seq.map (fun f -> f.Attribute(XName.Get "uid")) - |> Seq.filter (isNull >> not) - |> Seq.tryHead - |> Option.map - (fun a -> - let fr0 = XElement(XName.Get "FileRef") - let newfile = mapFile files a modu - fr0.SetAttributeValue(XName.Get "uid", newfile) - fr0) + group + |> snd + |> Seq.collect (fun x -> x.Elements(XName.Get "FileRef")) + |> Seq.map (fun f -> f.Attribute(XName.Get "uid")) + |> Seq.filter (isNull >> not) + |> Seq.tryHead + |> Option.map + (fun a -> + let fr0 = XElement(XName.Get "FileRef") + let newfile = mapFile files a modu + fr0.SetAttributeValue(XName.Get "uid", newfile) + fr0) let sequencePoints modu (group: string * XElement seq) = let sp = XElement(XName.Get "SequencePoints") + let sps = group |> snd |> Seq.collect (fun m -> m.Descendants(XName.Get "SequencePoint")) |> Seq.groupBy - (fun s -> - s - |> attributeOrEmpty "sl" - |> Int32.TryParse - |> snd, - s - |> attributeOrEmpty "sc" - |> Int32.TryParse - |> snd) + (fun s -> + s + |> attributeOrEmpty "sl" + |> Int32.TryParse + |> snd, + s + |> attributeOrEmpty "sc" + |> Int32.TryParse + |> snd) let (vs, newsps) = mergePoints files modu tracked sps + newsps |> Seq.iter - (fun s -> - s.SetAttributeValue(XName.Get "bec", 0) - s.SetAttributeValue(XName.Get "bev", 0)) + (fun s -> + s.SetAttributeValue(XName.Get "bec", 0) + s.SetAttributeValue(XName.Get "bev", 0)) sp.Add newsps (sp, newsps, vs) let branchPoints modu (group: string * XElement seq) = - let bp = XElement(XName.Get "BranchPoints") - - let bps = - group - |> snd - |> Seq.collect (fun m -> m.Descendants(XName.Get "BranchPoint")) - |> Seq.groupBy - (fun s -> - (s - |> attributeOrEmpty "sl" - |> Int32.TryParse - |> snd, - s - |> attributeOrEmpty "offset" - |> Int32.TryParse - |> snd), + let bp = XElement(XName.Get "BranchPoints") + + let bps = + group + |> snd + |> Seq.collect (fun m -> m.Descendants(XName.Get "BranchPoint")) + |> Seq.groupBy + (fun s -> + (s + |> attributeOrEmpty "sl" + |> Int32.TryParse + |> snd, s - |> attributeOrEmpty "endoffset" + |> attributeOrEmpty "offset" |> Int32.TryParse - |> snd) + |> snd), + s + |> attributeOrEmpty "endoffset" + |> Int32.TryParse + |> snd) - let (vb, newbps) = mergePoints files modu tracked bps - bp.Add newbps - (bp, newbps, vb) + let (vb, newbps) = mergePoints files modu tracked bps + bp.Add newbps + (bp, newbps, vb) - let methodPoints modu (group: string * XElement seq) = + let methodPoints modu (group: string * XElement seq) = let mpn = XName.Get "MethodPoint" let methodPoints = @@ -869,18 +874,19 @@ coverlet on Tests.AltCoverRunnerTests/PostprocessShouldRestoreDegenerateOpenCove methodPoints |> Seq.tryHead |> Option.map - (fun r -> - let mp0 = XElement r - mp0.SetAttributeValue(XName.Get "vc", mpv) + (fun r -> + let mp0 = XElement r + mp0.SetAttributeValue(XName.Get "vc", mpv) - r.Attribute(XName.Get "fileid") - |> Option.ofObj - |> Option.iter + r.Attribute(XName.Get "fileid") + |> Option.ofObj + |> Option.iter (fun a -> let newfile = mapFile files a modu mp0.SetAttributeValue(XName.Get "fileid", newfile)) - mp0) + mp0) + (mp, mpv) let s, x = @@ -1025,7 +1031,7 @@ coverlet on Tests.AltCoverRunnerTests/PostprocessShouldRestoreDegenerateOpenCove (tracked: Map) (modules: XElement seq) = - let findFiles (f:XElement) = + let findFiles (f: XElement) = let foundFiles = modules |> Seq.collect (fun m -> m.Descendants(XName.Get "File")) @@ -1036,15 +1042,15 @@ coverlet on Tests.AltCoverRunnerTests/PostprocessShouldRestoreDegenerateOpenCove foundFiles |> Seq.iter - (fun file -> - XElement( - XName.Get "File", - XAttribute(XName.Get "uid", Map.find file files), - XAttribute(XName.Get "fullPath", file) - ) - |> f.Add) - - let findClasses (c:XElement) = + (fun file -> + XElement( + XName.Get "File", + XAttribute(XName.Get "uid", Map.find file files), + XAttribute(XName.Get "fullPath", file) + ) + |> f.Add) + + let findClasses (c: XElement) = let classes = modules |> Seq.collect (fun m -> m.Descendants(XName.Get "Class")) @@ -1209,7 +1215,8 @@ coverlet on Tests.AltCoverRunnerTests/PostprocessShouldRestoreDegenerateOpenCove try let format = XmlUtilities.discoverFormat x format = ReportFormat.OpenCover - with :? XmlSchemaValidationException -> false) + with + | :? XmlSchemaValidationException -> false) |> Seq.toList match inputs with @@ -1219,23 +1226,31 @@ coverlet on Tests.AltCoverRunnerTests/PostprocessShouldRestoreDegenerateOpenCove [] let JsonToXml (document: string) = - let json = - document - |> NativeJson.fromJsonText + let json = document |> NativeJson.fromJsonText + let xml = json |> NativeJson.jsonToXml |> NativeJson.orderXml // heuristic for coverlet vs altcover - let sp = json.Values - |> Seq.collect (fun m -> m.Values) - |> Seq.collect (fun d -> d.Values) - |> Seq.collect (fun c -> c.Values) - |> Seq.filter (fun m -> m.SeqPnts.IsNotNull) - |> Seq.collect (fun m -> m.SeqPnts) - |> Seq.isEmpty |> not - PostProcess xml (if sp then BranchOrdinal.Offset else BranchOrdinal.SL) + let sp = + json.Values + |> Seq.collect (fun m -> m.Values) + |> Seq.collect (fun d -> d.Values) + |> Seq.collect (fun c -> c.Values) + |> Seq.filter (fun m -> m.SeqPnts.IsNotNull) + |> Seq.collect (fun m -> m.SeqPnts) + |> Seq.isEmpty + |> not + + PostProcess + xml + (if sp then + BranchOrdinal.Offset + else + BranchOrdinal.SL) + xml [() + cn.OfType() |> Seq.tryHead - |> Option.iter (fun doctype -> - let xDoctype = document.DocumentType + |> Option.iter + (fun doctype -> + let xDoctype = document.DocumentType - let newDoctype = - xmlDocument.CreateDocumentType( - nullIfEmpty xDoctype.Name, - nullIfEmpty xDoctype.PublicId, - nullIfEmpty xDoctype.SystemId, - nullIfEmpty xDoctype.InternalSubset - ) + let newDoctype = + xmlDocument.CreateDocumentType( + nullIfEmpty xDoctype.Name, + nullIfEmpty xDoctype.PublicId, + nullIfEmpty xDoctype.SystemId, + nullIfEmpty xDoctype.InternalSubset + ) - xmlDocument.ReplaceChild(newDoctype, doctype) - |> ignore) + xmlDocument.ReplaceChild(newDoctype, doctype) + |> ignore) document.Declaration |> Option.ofObj - |> Option.iter (fun xDeclaration -> - let xmlDeclaration = - xmlDocument.CreateXmlDeclaration( - xDeclaration.Version, - xDeclaration.Encoding, - xDeclaration.Standalone - ) + |> Option.iter + (fun xDeclaration -> + let xmlDeclaration = + xmlDocument.CreateXmlDeclaration( + xDeclaration.Version, + xDeclaration.Encoding, + xDeclaration.Standalone + ) - xmlDocument.InsertBefore(xmlDeclaration, xmlDocument.FirstChild) - |> ignore) + xmlDocument.InsertBefore(xmlDeclaration, xmlDocument.FirstChild) + |> ignore) xmlDocument @@ -70,21 +72,23 @@ module XmlTypes = let cn = xmlDocument.ChildNodes cn.OfType() - |> Seq.tryHead - |> Option.iter (fun doctype -> - xdoc.AddFirst( - XDocumentType( - nullIfEmpty doctype.Name, - nullIfEmpty doctype.PublicId, - nullIfEmpty doctype.SystemId, - nullIfEmpty doctype.InternalSubset - ) - )) + |> Seq.tryHead + |> Option.iter + (fun doctype -> + xdoc.AddFirst( + XDocumentType( + nullIfEmpty doctype.Name, + nullIfEmpty doctype.PublicId, + nullIfEmpty doctype.SystemId, + nullIfEmpty doctype.InternalSubset + ) + )) cn.OfType() |> Seq.tryHead - |> Option.iter (fun decl -> - xdoc.Declaration <- XDeclaration(decl.Version, decl.Encoding, decl.Standalone)) + |> Option.iter + (fun decl -> + xdoc.Declaration <- XDeclaration(decl.Version, decl.Encoding, decl.Standalone)) cn.OfType() |> Seq.rev diff --git a/AltCover.UICommon/AltCover.UICommon.fsproj b/AltCover.UICommon/AltCover.UICommon.fsproj index 1a1446293..8d3fef4a0 100644 --- a/AltCover.UICommon/AltCover.UICommon.fsproj +++ b/AltCover.UICommon/AltCover.UICommon.fsproj @@ -5,34 +5,14 @@ netstandard2.0 AltCover.UICommon AltCover.UICommon - false - true - GUI;LITEVERSION - $(ProjectDir)../ - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk + GUI;LITEVERSION;$(TOGGLE) false - - false - false - - - true - true - - TRACE;DEBUG;CODE_ANALYSIS;$(GlobalDefineConstants) - 4 - true - - true - true TRACE;$(GlobalDefineConstants) @@ -90,7 +70,7 @@ - + diff --git a/AltCover.UICommon/Compatibility.fs b/AltCover.UICommon/Compatibility.fs deleted file mode 100644 index 51253a300..000000000 --- a/AltCover.UICommon/Compatibility.fs +++ /dev/null @@ -1,35 +0,0 @@ -namespace AltCover - -open System -open System.Diagnostics.CodeAnalysis -open System.Net -open System.Security.Cryptography - -// netstandard 2.0 APIs obsoleted at net 6.0+ - -[] -[] -module Compatibility = -#if !GUI - [] - let internal sha1Hash () : SHA1 = - new SHA1CryptoServiceProvider() :> SHA1 -#endif - - [] - let internal createHttp (path:Uri) = - WebRequest.CreateHttp(path) :> WebRequest - -#if GUI - [] - let internal readAllText (path:Uri) = - use client = new System.Net.WebClient() - client.DownloadString(path) -#endif \ No newline at end of file diff --git a/AltCover.UICommon/Configuration.fs b/AltCover.UICommon/Configuration.fs index 4137c5087..ecd76791c 100644 --- a/AltCover.UICommon/Configuration.fs +++ b/AltCover.UICommon/Configuration.fs @@ -61,11 +61,13 @@ module Configuration = schemas.Add(String.Empty, xsd) |> ignore doc.Validate(schemas, null) (file, doc) - with xx -> // DoNotSwallowErrorsCatchingNonSpecificExceptionsRule + with + | xx -> // DoNotSwallowErrorsCatchingNonSpecificExceptionsRule let nl = Environment.NewLine printfn "%A%s%s%A" xx nl nl doc (file, defaultDocument ()) - with x -> // DoNotSwallowErrorsCatchingNonSpecificExceptionsRule + with + | x -> // DoNotSwallowErrorsCatchingNonSpecificExceptionsRule printfn "%A" x (file, defaultDocument ()) @@ -80,17 +82,18 @@ module Configuration = |> Seq.toList |> Seq.head - if (match (node.Attribute(XName.Get "GSettingsSchemaDir"), String.IsNullOrWhiteSpace s) with + if (match (node.Attribute(XName.Get "GSettingsSchemaDir"), String.IsNullOrWhiteSpace s) + with | (null, false) -> - node.Add(XAttribute(XName.Get "GSettingsSchemaDir", s)) - true + node.Add(XAttribute(XName.Get "GSettingsSchemaDir", s)) + true | (a, false) -> - a.Value <- s - true + a.Value <- s + true | (null, true) -> false | (a, true) -> - a.Remove() - true) then + a.Remove() + true) then config.Save file let SaveFont (font: string) = @@ -102,8 +105,10 @@ module Configuration = let inject = XElement(XName.Get "Font", font) - match config.XPathSelectElements("//CoveragePath") - |> Seq.toList with + match + config.XPathSelectElements("//CoveragePath") + |> Seq.toList + with | [] -> (config.FirstNode :?> XElement).AddFirst(inject) | x :: _ -> inject |> x.AddAfterSelf @@ -134,22 +139,26 @@ module Configuration = let SaveFolder (path: string) = let file, config = ensureFile () - match config.XPathSelectElements("//CoveragePath") - |> Seq.toList with + match + config.XPathSelectElements("//CoveragePath") + |> Seq.toList + with | [] -> - (config.FirstNode :?> XElement) - .AddFirst(XElement(XName.Get "CoveragePath", path)) + (config.FirstNode :?> XElement) + .AddFirst(XElement(XName.Get "CoveragePath", path)) | x :: _ -> - x.RemoveAll() - x.Add path + x.RemoveAll() + x.Add path config.Save file let ReadFolder () = let _, config = ensureFile () - match config.XPathSelectElements("//CoveragePath") - |> Seq.toList with + match + config.XPathSelectElements("//CoveragePath") + |> Seq.toList + with | [] -> System.IO.Directory.GetCurrentDirectory() | x :: _ -> x.FirstNode.ToString() @@ -201,8 +210,10 @@ module Configuration = XAttribute(XName.Get "height", height) ) - match config.XPathSelectElements("//RecentlyOpened") - |> Seq.toList with + match + config.XPathSelectElements("//RecentlyOpened") + |> Seq.toList + with | [] -> (config.FirstNode :?> XElement).Add element | x :: _ -> x.AddBeforeSelf element diff --git a/AltCover.UICommon/CoverageFile.fs b/AltCover.UICommon/CoverageFile.fs index 027240d8d..48158fc42 100644 --- a/AltCover.UICommon/CoverageFile.fs +++ b/AltCover.UICommon/CoverageFile.fs @@ -35,7 +35,8 @@ module Transformer = [] - [] let internal defaultHelper (_: XDocument) (document: XDocument) = document @@ -150,8 +151,11 @@ module Transformer = let private processOpenCover (helper: XmlCoverageType -> XDocument -> XDocument -> XDocument) - (schemas:XmlSchemaSet) (document:XDocument) - (ocreader:XmlReader) (ncreader:XmlReader) : Either = + (schemas: XmlSchemaSet) + (document: XDocument) + (ocreader: XmlReader) + (ncreader: XmlReader) + : Either = schemas.Add(String.Empty, ocreader) |> ignore document.Validate(schemas, null) @@ -168,16 +172,15 @@ module Transformer = let lineOnly = fixedup.Descendants(XName.Get "seqpnt") |> Seq.forall - (fun s -> - let columns = (s.Attribute(XName.Get "column").Value, - s.Attribute(XName.Get "endcolumn").Value) - s.Attribute(XName.Get "line").Value = s - .Attribute( - XName.Get "endline" - ) - .Value - && (columns = ("1", "2") || // For coverlet derived OpenCover (either from coverlet XML or via JsonToXml) - columns = ("0", "0"))) // For OpenCover on C++/CLI + (fun s -> + let columns = + (s.Attribute(XName.Get "column").Value, + s.Attribute(XName.Get "endcolumn").Value) + + s.Attribute(XName.Get "line").Value = s.Attribute(XName.Get "endline").Value + && (columns = ("1", "2") + || // For coverlet derived OpenCover (either from coverlet XML or via JsonToXml) + columns = ("0", "0"))) // For OpenCover on C++/CLI if lineOnly then fixedup.Root.Add(XAttribute(XName.Get "lineonly", "true")) @@ -186,8 +189,10 @@ module Transformer = let private processCobertura (helper: XmlCoverageType -> XDocument -> XDocument -> XDocument) - (schemas:XmlSchemaSet) (document:XDocument) - (ncreader:XmlReader) : Either = + (schemas: XmlSchemaSet) + (document: XDocument) + (ncreader: XmlReader) + : Either = use cr = new StreamReader( Assembly @@ -215,30 +220,34 @@ module Transformer = = let schemas = XmlSchemaSet() - use sr1 = resourceStream "AltCover.UICommon.OpenCover.xsd" + use sr1 = + resourceStream "AltCover.UICommon.OpenCover.xsd" + use ocreader = XmlReader.Create(sr1) - use sr2 = resourceStream "AltCover.UICommon.NCoverEmbedded.xsd" + use sr2 = + resourceStream "AltCover.UICommon.NCoverEmbedded.xsd" + use ncreader = XmlReader.Create(sr2) try // identify coverage type match document.Root.Name.LocalName with | x when x = "CoverageSession" -> - // Assume OpenCover - processOpenCover helper schemas document ocreader ncreader + // Assume OpenCover + processOpenCover helper schemas document ocreader ncreader | _ -> - let root = document.Root - - if root.Name.LocalName = "coverage" - && root.Attribute(XName.Get "line-rate").IsNotNull then - // Cobertura - processCobertura helper schemas document ocreader - else - // Assume NCover - schemas.Add(String.Empty, ncreader) |> ignore - document.Validate(schemas, null) - Right document + let root = document.Root + + if root.Name.LocalName = "coverage" + && root.Attribute(XName.Get "line-rate").IsNotNull then + // Cobertura + processCobertura helper schemas document ocreader + else + // Assume NCover + schemas.Add(String.Empty, ncreader) |> ignore + document.Validate(schemas, null) + Right document with | :? ArgumentNullException as x -> Left(x :> Exception) | :? NullReferenceException as x -> Left(x :> Exception) @@ -287,9 +296,9 @@ type CoverageFile = let rawDocument = match filetype with | Json -> - name - |> NativeJson.fileToJson - |> NativeJson.jsonToXml + name + |> NativeJson.fileToJson + |> NativeJson.jsonToXml | LCov -> Lcov.toXml name | _ -> XDocument.Load name // let invalid files throw XML parse errors @@ -301,7 +310,7 @@ type CoverageFile = | :? XmlException as e -> Left { Fault = e; File = file } | :? Manatee.Json.JsonSyntaxException as e -> Left { Fault = e; File = file } | :? Manatee.Json.JsonValueIncorrectTypeException as e -> - Left { Fault = e; File = file } + Left { Fault = e; File = file } | :? Lcov.LcovParseException as e -> Left { Fault = e; File = file } | :? IOException as e -> Left { Fault = e; File = file } diff --git a/AltCover.UICommon/CoverageFileTree.fs b/AltCover.UICommon/CoverageFileTree.fs index f7f102d0b..d349db24f 100644 --- a/AltCover.UICommon/CoverageFileTree.fs +++ b/AltCover.UICommon/CoverageFileTree.fs @@ -23,40 +23,81 @@ type CoverageModelDisplay<'TModel, 'TRow, 'TIcon> = GetFileInfo: int -> FileInfo UpdateMRUFailure: FileInfo -> unit UpdateUISuccess: FileInfo -> unit - SetXmlNode: String -> Lazy<'TIcon> -> String -> CoverageTreeContext<'TModel, 'TRow> - AddNode: CoverageTreeContext<'TModel, 'TRow> -> Lazy<'TIcon> -> String -> String option -> CoverageTreeContext<'TModel, 'TRow> - AddLeafNode: CoverageTreeContext<'TModel, 'TRow> -> Lazy<'TIcon> -> String -> String option -> CoverageTreeContext<'TModel, 'TRow> + SetXmlNode: String + -> String + -> Lazy<'TIcon> + -> String + -> CoverageTreeContext<'TModel, 'TRow> + AddNode: CoverageTreeContext<'TModel, 'TRow> + -> Lazy<'TIcon> + -> String + -> String + -> String option + -> CoverageTreeContext<'TModel, 'TRow> + AddLeafNode: CoverageTreeContext<'TModel, 'TRow> + -> Lazy<'TIcon> + -> String + -> String + -> String option + -> CoverageTreeContext<'TModel, 'TRow> Map: CoverageTreeContext<'TModel, 'TRow> -> XPathNavigator -> unit } module CoverageFileTree = [] - type SourceFile<'TIcon> = { - FullName : string - FileName : string - Navigator : XPathNavigator - Icon : Lazy<'TIcon> - Exists : bool - Stale : bool - } + type SourceFile<'TIcon> = + { FullName: string + FileName: string + Navigator: XPathNavigator + Icon: Lazy<'TIcon> + Exists: bool + Stale: bool } [] - let rec private scan (s:string) index depth = + "ReviewSelfAssignmentRule", + Justification = "Final line is a self-assignment for 'depth' -- compiler fault")>] + let rec private scan (s: string) index depth = match s.[index] with | '<' -> scan s (index + 1) (depth + 1) - | '>' -> let d = depth - 1 - if d = 0 - then index - else scan s (index + 1) d + | '>' -> + let d = depth - 1 + + if d = 0 then + index + else + scan s (index + 1) d | _ -> scan s (index + 1) depth +#if VIS_PERCENT + let private coverPoints (points: XPathNavigator seq) = + let visited = + points + |> Seq.filter (fun p -> p.GetAttribute("visitcount", String.Empty) <> "0") + + (100.0 * (visited |> Seq.length |> float) + / (points |> Seq.length |> float)) + |> Math.Floor + |> int + + let private cover (navigator: XPathNavigator seq) = + let points = + navigator + |> Seq.collect + (fun n -> + n.SelectDescendants("seqpnt", String.Empty, false) + |> Seq.cast) + + coverPoints points + + let private coverText pc = sprintf "%3i%%" pc + + let private pcCover (navigator: XPathNavigator seq) = navigator |> cover |> coverText +#endif let private populateClassNode (environment: CoverageModelDisplay<'TModel, 'TRow, 'TIcon>) (model: CoverageTreeContext<'TModel, 'TRow>) (nodes: seq) - (epoch : DateTime) + (epoch: DateTime) = let applyToModel (theModel: CoverageTreeContext<'TModel, 'TRow>) @@ -65,44 +106,59 @@ module CoverageFileTree = let ((display, special), keys) = item // C++/CLI fixups -- probably more will be needed - let modopt s = System.Text.RegularExpressions.Regex.Replace(s, - @"modopt\(System\.Runtime\.\w+\.(\w+)?\)", "[$1]") + let modopt s = + System.Text.RegularExpressions.Regex.Replace( + s, + @"modopt\(System\.Runtime\.\w+\.(\w+)?\)", + "[$1]" + ) let gcroot (s: string) = - let rec step (s: string) (i:int) = - let next = s.IndexOf("gcroot<", i, StringComparison.Ordinal) - if next < 0 - then s + let rec step (s: string) (i: int) = + let next = + s.IndexOf("gcroot<", i, StringComparison.Ordinal) + + if next < 0 then + s else let index = next + 7 let stop = scan s index 1 let start = s.Substring(0, index) - let middle = s.Substring(index, stop - index).Replace("::", ".") + + let middle = + s + .Substring(index, stop - index) + .Replace("::", ".") + let finish = s.Substring(stop) step (start + middle + finish) index + step s 0 let fixup = modopt >> gcroot + let extractArgs name fullname = + if + String.IsNullOrEmpty(fullname) + || charIndexOf name '(' > 0 + then + String.Empty + else + let bracket = charIndexOf fullname '(' + + if bracket < 0 then + String.Empty + else + fullname.Substring(bracket) + let applyMethod (mmodel: CoverageTreeContext<'TModel, 'TRow>) (x: MethodKey) = let fullname = - fixup <| x.Navigator.GetAttribute("fullname", String.Empty) + fixup + <| x.Navigator.GetAttribute("fullname", String.Empty) let name = fixup x.Name - //printfn "%s ||| %s" name fullname - - let args = - if String.IsNullOrEmpty(fullname) - || charIndexOf name '(' > 0 then - String.Empty - else - let bracket = charIndexOf fullname '(' - - if bracket < 0 then - String.Empty - else - fullname.Substring(bracket) + let args = extractArgs name fullname let displayname = name + args @@ -112,88 +168,103 @@ module CoverageFileTree = | o -> o + 2 // multi-source?? - let upcase (s:string) = s.ToUpperInvariant() - let getFileName (s:string) = + let upcase (s: string) = s.ToUpperInvariant() + + let getFileName (s: string) = if s.StartsWith("http://", StringComparison.Ordinal) - || s.StartsWith - ( - "https://", - StringComparison.Ordinal - ) + || s.StartsWith("https://", StringComparison.Ordinal) then - { - FullName = s + { FullName = s FileName = System.Uri(s).LocalPath |> Path.GetFileName Navigator = null Icon = environment.Icons.SourceLink Exists = true - Stale = false - } + Stale = false } else let info = GetSource(s) let x = info.Exists let stale = info.Outdated epoch - { - FullName = s + + { FullName = s FileName = Path.GetFileName s Navigator = null - Icon = match (x, stale) with - | (false, _) -> environment.Icons.NoSource - | (_, true) -> environment.Icons.SourceDated - | _ -> environment.Icons.Source + Icon = + match (x, stale) with + | (false, _) -> environment.Icons.NoSource + | (_, true) -> environment.Icons.SourceDated + | _ -> environment.Icons.Source Exists = x - Stale = stale - } + Stale = stale } let sources = x.Navigator.SelectDescendants("seqpnt", String.Empty, false) |> Seq.cast |> Seq.map - (fun s -> - let d = s.GetAttribute("document", String.Empty) - let state = { (d |> getFileName) with Navigator = s } - // get any embed and tweak state and icon accordingly - match GuiCommon.Embed s d with - | None -> state - | Some _ -> { state with Exists = true - Stale = false - Icon = environment.Icons.Source } - ) + (fun s -> + let d = s.GetAttribute("document", String.Empty) + + let state = + { (d |> getFileName) with + Navigator = s } + // get any embed and tweak state and icon accordingly + match GuiCommon.Embed s d with + | None -> state + | Some _ -> + { state with + Exists = true + Stale = false + Icon = environment.Icons.Source }) |> Seq.distinctBy (fun s -> s.FullName) // allows for same name, different path |> Seq.sortBy (fun s -> s.FileName |> upcase) |> Seq.toList - let hasSource = sources - |> List.exists (fun s -> s.Exists) - let icon = if hasSource - then environment.Icons.Method - else environment.Icons.MethodMissingSource + let hasSource = + sources |> List.exists (fun s -> s.Exists) + + let icon = + if hasSource then + environment.Icons.Method + else + environment.Icons.MethodMissingSource match sources with | [] -> environment.AddLeafNode mmodel environment.Icons.MethodNoSource + String.Empty // TODO maybe 0 or 100% ?? (displayname.Substring(offset)) - None |> ignore + None + |> ignore - | [source] -> + | [ source ] -> let newrow = environment.AddLeafNode mmodel - (if source.Stale then environment.Icons.MethodDated else icon) + (if source.Stale then + environment.Icons.MethodDated + else + icon) +#if VIS_PERCENT + (pcCover [ x.Navigator ]) +#else + String.Empty +#endif (displayname.Substring(offset)) - (if hasSource - then - if source.Stale - then Some <| Resource.Format("FileNewerThanReport", [| source.FullName |]) - else None - else Some <| Resource.Format("FileNotFound", [| source.FullName |])) + (if hasSource then + if source.Stale then + Some + <| Resource.Format("FileNewerThanReport", [| source.FullName |]) + else + None + else + Some + <| Resource.Format("FileNotFound", [| source.FullName |])) - if hasSource && (not source.Stale) - then environment.Map newrow x.Navigator + if hasSource && (not source.Stale) then + environment.Map newrow x.Navigator | _ -> // If multi-source (has inlines), add the source file nodes to the hittable map @@ -201,22 +272,52 @@ module CoverageFileTree = environment.AddNode mmodel icon +#if VIS_PERCENT + (pcCover [ x.Navigator ]) +#else + String.Empty +#endif (displayname.Substring(offset)) None + sources - |> List.iter (fun s -> - let srow = - environment.AddLeafNode - newrow - (if s.Stale then environment.Icons.SourceDated else icon) - s.FileName - (if s.Exists - then None - else Some <| Resource.Format("FileNotFound", [| s.FullName |])) - if s.Exists && (not s.Stale) then environment.Map srow s.Navigator - ) + |> List.iter + (fun s -> + let srow = + environment.AddLeafNode + newrow + (if s.Stale then + environment.Icons.SourceDated + else + icon) +#if VIS_PERCENT + (x.Navigator.SelectDescendants("seqpnt", String.Empty, false) + |> Seq.cast + |> Seq.filter + (fun n -> + n.GetAttribute("document", String.Empty) = s.FullName) + |> coverPoints + |> coverText) +#else + String.Empty +#endif + s.FileName + (if s.Exists then + None + else + Some + <| Resource.Format("FileNotFound", [| s.FullName |])) + + if s.Exists && (not s.Stale) then + environment.Map srow s.Navigator) if special <> MethodType.Normal then +#if VIS_PERCENT + let pc = + keys |> Seq.map (fun x -> x.Navigator) |> pcCover +#else + let pc = String.Empty +#endif let newrow = environment.AddNode theModel @@ -224,6 +325,7 @@ module CoverageFileTree = environment.Icons.Property else environment.Icons.Event) + pc display None @@ -266,7 +368,7 @@ module CoverageFileTree = (environment: CoverageModelDisplay<'TModel, 'TRow, 'TIcon>) (model: CoverageTreeContext<'TModel, 'TRow>) (nodes: seq) - (epoch : DateTime) + (epoch: DateTime) = let applyToModel (theModel: CoverageTreeContext<'TModel, 'TRow>) @@ -276,24 +378,33 @@ module CoverageFileTree = let icon = if group |> snd |> Seq.isEmpty then - environment.Icons.Module + (environment.Icons.Module, String.Empty) // TODO maybe else - let names = group - |> snd - |> Seq.map - (fun key -> key.Name |> DisplayName) - |> Seq.filter (fun d -> d.[0] <> '.') - |> Seq.toList - - if names |> List.isEmpty || - names |> List.exists - (fun d -> d.Equals("Invoke") |> not ) - then - environment.Icons.Class +#if VIS_PERCENT + let pc = + group + |> snd + |> Seq.map (fun x -> x.Navigator) + |> pcCover +#else + let pc = String.Empty +#endif + let names = + group + |> snd + |> Seq.map (fun key -> key.Name |> DisplayName) + |> Seq.filter (fun d -> d.[0] <> '.') + |> Seq.toList + + if names |> List.isEmpty + || names + |> List.exists (fun d -> d.Equals("Invoke") |> not) then + (environment.Icons.Class, pc) else - environment.Icons.Effect + (environment.Icons.Effect, pc) - let newrow = environment.AddNode theModel icon name None + let newrow = + environment.AddNode theModel (fst icon) (snd icon) name None populateClassNode environment newrow (snd group) epoch newrow @@ -361,7 +472,7 @@ module CoverageFileTree = (environment: CoverageModelDisplay<'TModel, 'TRow, 'TIcon>) (model: CoverageTreeContext<'TModel, 'TRow>) (node: XPathNavigator) - (epoch : DateTime) + (epoch: DateTime) = // within the we have nodes with name="get_module" class="AltCover.Coverage.CoverageSchema.coverage" let applyToModel @@ -369,9 +480,18 @@ module CoverageFileTree = (group: string * seq) = let name = fst group +#if VIS_PERCENT + let pc = + group + |> snd + |> Seq.map (fun x -> x.Navigator) + |> pcCover +#else + let pc = String.Empty +#endif let newrow = - environment.AddNode theModel environment.Icons.Namespace name None + environment.AddNode theModel environment.Icons.Namespace pc name None populateNamespaceNode environment newrow (snd group) epoch @@ -405,74 +525,83 @@ module CoverageFileTree = match CoverageFile.LoadCoverageFile current with | Left failed -> - Messages.InvalidCoverageFileMessage environment.Display failed - environment.UpdateMRUFailure current + Messages.InvalidCoverageFileMessage environment.Display failed + environment.UpdateMRUFailure current | Right coverage -> - // check if coverage is newer that the source files - let sourceFiles = - coverage - .Document - .CreateNavigator() - .Select("//seqpnt/@document") - |> Seq.cast - |> Seq.map (fun x -> x.Value) - |> Seq.distinct - - let missing = - sourceFiles - |> Seq.map GetSource - |> Seq.filter (fun f -> not f.Exists) - - let newer = - sourceFiles - |> Seq.map GetSource - |> Seq.filter (fun f -> f.Exists && f.Outdated current.LastWriteTimeUtc) - - let message = [ - (missing, "NotAllSourcePresent") - (newer, "SomeSourceModified") - ] - |> Seq.filter (fun (x,y) -> x |> Seq.isEmpty |> not) - |> Seq.map (fun (x,y) -> Resource.Format(y, [| |])) - - let model = environment.SetXmlNode - current.Name - (if Seq.isEmpty missing - then - if Seq.isEmpty newer - then environment.Icons.Report - else environment.Icons.ReportDated - else - environment.Icons.ReportWarning) - (String.Join(Environment.NewLine, message)) - - let applyToModel - (theModel: CoverageTreeContext<'TModel, 'TRow>) - (group: XPathNavigator * string) - = - let name = snd group - - let newModel = - environment.AddNode theModel environment.Icons.Assembly name None - - populateAssemblyNode environment newModel (fst group) current.LastWriteTimeUtc - - let assemblies = - coverage - .Document - .CreateNavigator() - .Select("//module") - |> Seq.cast - - assemblies - |> Seq.map - (fun node -> - (node, - node - .GetAttribute("assemblyIdentity", String.Empty) - .Split(',') - |> Seq.head)) - |> Seq.sortBy snd - |> Seq.iter (applyToModel model) - - environment.UpdateUISuccess current \ No newline at end of file + let navigator = coverage.Document.CreateNavigator() + + // check if coverage is newer that the source files + let sourceFiles = + navigator.Select("//seqpnt/@document") + |> Seq.cast + |> Seq.map (fun x -> x.Value) + |> Seq.distinct + + let missing = + sourceFiles + |> Seq.map GetSource + |> Seq.filter (fun f -> not f.Exists) + + let newer = + sourceFiles + |> Seq.map GetSource + |> Seq.filter (fun f -> f.Exists && f.Outdated current.LastWriteTimeUtc) + + let message = + [ (missing, "NotAllSourcePresent") + (newer, "SomeSourceModified") ] + |> Seq.filter (fun (x, y) -> x |> Seq.isEmpty |> not) + |> Seq.map (fun (x, y) -> Resource.Format(y, [||])) + + let model = + environment.SetXmlNode +#if VIS_PERCENT + (pcCover [ navigator ]) +#else + String.Empty +#endif + current.Name + (if Seq.isEmpty missing then + if Seq.isEmpty newer then + environment.Icons.Report + else + environment.Icons.ReportDated + else + environment.Icons.ReportWarning) + (String.Join(Environment.NewLine, message)) + + let applyToModel + (theModel: CoverageTreeContext<'TModel, 'TRow>) + (group: XPathNavigator * string) + = + let name = snd group +#if VIS_PERCENT + let pc = ([ group |> fst ] |> pcCover) +#else + let pc = String.Empty +#endif + + let newModel = + environment.AddNode theModel environment.Icons.Assembly pc name None + + populateAssemblyNode environment newModel (fst group) current.LastWriteTimeUtc + + let assemblies = + coverage + .Document + .CreateNavigator() + .Select("//module") + |> Seq.cast + + assemblies + |> Seq.map + (fun node -> + (node, + node + .GetAttribute("assemblyIdentity", String.Empty) + .Split(',') + |> Seq.head)) + |> Seq.sortBy snd + |> Seq.iter (applyToModel model) + + environment.UpdateUISuccess current \ No newline at end of file diff --git a/AltCover.UICommon/GuiCommon.fs b/AltCover.UICommon/GuiCommon.fs index 4b46f6f84..8346851e4 100644 --- a/AltCover.UICommon/GuiCommon.fs +++ b/AltCover.UICommon/GuiCommon.fs @@ -44,11 +44,7 @@ module GuiCommon = let HandleSpecialName (name: string) = if name.StartsWith("get_", StringComparison.Ordinal) - || name.StartsWith - ( - "set_", - StringComparison.Ordinal - ) + || name.StartsWith("set_", StringComparison.Ordinal) then (name.Substring(4), MethodType.Property) else if name.StartsWith("add_", StringComparison.Ordinal) then @@ -59,11 +55,13 @@ module GuiCommon = (name, MethodType.Normal) // -------------------------- Source file Handling --------------------------- - let Embed (node:XPathNavigator) (document: string) = + let Embed (node: XPathNavigator) (document: string) = node.SelectAncestors("module", String.Empty, false) |> Seq.cast - |> Seq.collect(fun n -> n.SelectDescendants("altcover.file", String.Empty, false) - |> Seq.cast) + |> Seq.collect + (fun n -> + n.SelectDescendants("altcover.file", String.Empty, false) + |> Seq.cast) |> Seq.filter (fun n -> n.GetAttribute("document", String.Empty) = document) |> Seq.map (fun n -> n.GetAttribute("embed", String.Empty)) |> Seq.filter (String.IsNullOrWhiteSpace >> not) @@ -83,61 +81,63 @@ module GuiCommon = | File info -> info.Exists | Embed (_, s) -> s |> String.IsNullOrWhiteSpace |> not | Url u -> - let request = createHttp(u) - request.Method <- "HEAD" + let request = createHttp (u) + request.Method <- "HEAD" - try - use response = request.GetResponse() + try + use response = request.GetResponse() - response.ContentLength > 0L - && (response :?> HttpWebResponse).StatusCode |> int < 400 - with :? WebException -> false + response.ContentLength > 0L + && (response :?> HttpWebResponse).StatusCode |> int < 400 + with + | :? WebException -> false member internal self.FullName = match self with | Embed (name, _) -> name | File info -> - if info |> isNull then - String.Empty - else - info.FullName + if info |> isNull then + String.Empty + else + info.FullName | Url u -> u.AbsoluteUri member internal self.Outdated epoch = match self with - | File info -> if info.Exists - then info.LastWriteTimeUtc > epoch - else false // can't tell; should show as non-existing + | File info -> + if info.Exists then + info.LastWriteTimeUtc > epoch + else + false // can't tell; should show as non-existing | _ -> false // Embed or ensible SourceLink assumed member self.ReadAllText() = match self with | File info -> info.FullName |> File.ReadAllText | Url u -> readAllText u - | Embed (_,source) -> let data = Convert.FromBase64String source - use raw = new MemoryStream(data) - use expanded = new MemoryStream() - // Get deflation working with this one weird trick - // Dispose the deflate stream w/o closing the one it points at! - do - use expand = new DeflateStream(raw, CompressionMode.Decompress, true) - expand.CopyTo expanded - System.Text.Encoding.UTF8.GetString(expanded.GetBuffer(), - 0, int expanded.Length) + | Embed (_, source) -> + let data = Convert.FromBase64String source + use raw = new MemoryStream(data) + use expanded = new MemoryStream() + // Get deflation working with this one weird trick + // Dispose the deflate stream w/o closing the one it points at! + do + use expand = + new DeflateStream(raw, CompressionMode.Decompress, true) + + expand.CopyTo expanded + + System.Text.Encoding.UTF8.GetString(expanded.GetBuffer(), 0, int expanded.Length) member internal self.MakeEmbedded (filename: string) (source: string option) = match (self, source) with - | (File info, Some _) -> Embed (filename, source.Value) + | (File info, Some _) -> Embed(filename, source.Value) | _ -> self let GetSource (document: string) = if document.StartsWith("http://", StringComparison.Ordinal) - || document.StartsWith - ( - "https://", - StringComparison.Ordinal - ) + || document.StartsWith("https://", StringComparison.Ordinal) then System.Uri(document) |> Url else diff --git a/AltCover.UICommon/HandlerCommon.fs b/AltCover.UICommon/HandlerCommon.fs index 07786dab9..fbf017bdd 100644 --- a/AltCover.UICommon/HandlerCommon.fs +++ b/AltCover.UICommon/HandlerCommon.fs @@ -45,10 +45,12 @@ module HandlerCommon = window.Title <- "AltCover.Visualizer - " + filename // get embed if any & fold it in here let embed = GuiCommon.Embed methodPath filename - let info = GetSource(filename).MakeEmbedded filename embed + + let info = + GetSource(filename).MakeEmbedded filename embed let lineNumber = - Int32.TryParse(line |> Option.get) |> snd + Int32.TryParse(line |> Option.get) |> snd showSource info lineNumber @@ -61,11 +63,7 @@ module HandlerCommon = let private (|Select|_|) (pattern: String) offered = if (fst offered) |> String.IsNullOrWhiteSpace |> not - && pattern.StartsWith - ( - fst offered, - StringComparison.Ordinal - ) + && pattern.StartsWith(fst offered, StringComparison.Ordinal) then Some offered else diff --git a/AltCover.UICommon/IVisualizerWindow.fs b/AltCover.UICommon/IVisualizerWindow.fs index 71017688a..a63e0c3bf 100644 --- a/AltCover.UICommon/IVisualizerWindow.fs +++ b/AltCover.UICommon/IVisualizerWindow.fs @@ -4,11 +4,11 @@ open System.Diagnostics.CodeAnalysis type IVisualizerWindow = interface - abstract member Title : string with get, set - abstract member CoverageFiles : string list with get, set + abstract member Title: string with get, set + abstract member CoverageFiles: string list with get, set [] - abstract ShowMessageOnGuiThread : MessageType -> string -> unit - end \ No newline at end of file + abstract ShowMessageOnGuiThread: MessageType -> string -> unit + end diff --git a/AltCover.UICommon/Icons.fs b/AltCover.UICommon/Icons.fs index 2d031ec99..5199d3288 100644 --- a/AltCover.UICommon/Icons.fs +++ b/AltCover.UICommon/Icons.fs @@ -13,14 +13,14 @@ open System.Reflection type Icons<'TIcon>(toIcon: System.IO.Stream -> 'TIcon) = let makeIcon name = lazy - //try + //try (toIcon ( Assembly .GetExecutingAssembly() .GetManifestResourceStream("AltCover.UICommon." + name + ".png") )) - //with - //| x -> System.InvalidOperationException(name, x) |> raise + //with + //| x -> System.InvalidOperationException(name, x) |> raise member self.Report = makeIcon "Report_16x" member self.ReportDated = makeIcon "ReportDated_16x" @@ -49,8 +49,7 @@ type Icons<'TIcon>(toIcon: System.IO.Stream -> 'TIcon) = member self.SourceLink = makeIcon "TextFileWeb_16x" member self.NoSource = makeIcon "TextFileMissing_16x" - member self.MRUInactive = - makeIcon "ExpandDown_lightGray_16x" + member self.MRUInactive = makeIcon "ExpandDown_lightGray_16x" member self.RefreshActive = makeIcon "Refresh_16x" member self.Refresh = makeIcon "Refresh_greyThin_16x" diff --git a/AltCover.UICommon/Lcov.fs b/AltCover.UICommon/Lcov.fs index c324c2c9f..2fa1604c8 100644 --- a/AltCover.UICommon/Lcov.fs +++ b/AltCover.UICommon/Lcov.fs @@ -47,19 +47,19 @@ module internal Lcov = (fun r -> match r with | SF name -> - let fn = Path.GetFileNameWithoutExtension name + let fn = Path.GetFileNameWithoutExtension name - [| XAttribute(XName.Get "moduleId", fn) - XAttribute(XName.Get "name", fn) - XAttribute(XName.Get "assembly", name) - XAttribute(XName.Get "assemblyIdentity", name) |] - |> result.Add + [| XAttribute(XName.Get "moduleId", fn) + XAttribute(XName.Get "name", fn) + XAttribute(XName.Get "assembly", name) + XAttribute(XName.Get "assemblyIdentity", name) |] + |> result.Add - false + false | FN _ | DA _ | BRDA _ -> true - | _ -> raise (r |> sprintf "%A" |> InvalidDataException )) + | _ -> raise (r |> sprintf "%A" |> InvalidDataException)) |> Seq.sortBy (fun r -> match r with @@ -71,72 +71,72 @@ module internal Lcov = (fun x r -> // match r with | FN (_, n) -> // - let endclass = - n.IndexOf("::", StringComparison.Ordinal) - - let startclass = n.LastIndexOf(' ', endclass) + 1 - - let c = - n.Substring(startclass, endclass - startclass) - - let endname = n.IndexOf('(', endclass) - - let name = - n.Substring(endclass + 2, endname - endclass - 2) - - let mt = - XElement( - XName.Get "method", - XAttribute(XName.Get "excluded", "false"), - XAttribute(XName.Get "instrumented", "true"), - XAttribute(XName.Get "name", name), - XAttribute(XName.Get "class", c), - XAttribute(XName.Get "fullname", n), - XAttribute( - XName.Get "document", - result.Attribute(XName.Get "assembly").Value - ) + let endclass = + n.IndexOf("::", StringComparison.Ordinal) + + let startclass = n.LastIndexOf(' ', endclass) + 1 + + let c = + n.Substring(startclass, endclass - startclass) + + let endname = n.IndexOf('(', endclass) + + let name = + n.Substring(endclass + 2, endname - endclass - 2) + + let mt = + XElement( + XName.Get "method", + XAttribute(XName.Get "excluded", "false"), + XAttribute(XName.Get "instrumented", "true"), + XAttribute(XName.Get "name", name), + XAttribute(XName.Get "class", c), + XAttribute(XName.Get "fullname", n), + XAttribute( + XName.Get "document", + result.Attribute(XName.Get "assembly").Value ) + ) - result.Add mt - mt + result.Add mt + mt | DA (l, n) -> - let sp = - XElement( - XName.Get "seqpnt", - XAttribute(XName.Get "visitcount", n), - XAttribute(XName.Get "line", l), - XAttribute(XName.Get "column", 1), - XAttribute(XName.Get "endline", l), - XAttribute(XName.Get "endcolumn", 2), - XAttribute(XName.Get "offset", l), - XAttribute(XName.Get "excluded", "false"), - XAttribute( - XName.Get "document", - result.Attribute(XName.Get "assembly").Value - ) + let sp = + XElement( + XName.Get "seqpnt", + XAttribute(XName.Get "visitcount", n), + XAttribute(XName.Get "line", l), + XAttribute(XName.Get "column", 1), + XAttribute(XName.Get "endline", l), + XAttribute(XName.Get "endcolumn", 2), + XAttribute(XName.Get "offset", l), + XAttribute(XName.Get "excluded", "false"), + XAttribute( + XName.Get "document", + result.Attribute(XName.Get "assembly").Value ) + ) - x.Add sp - x + x.Add sp + x // BRDA:,,, | BRDA (l, _, n, v) -> - let br = - XElement( - XName.Get "branch", - XAttribute(XName.Get "visitcount", v), - XAttribute(XName.Get "line", l), - XAttribute(XName.Get "path", n), - XAttribute(XName.Get "offset", l), - XAttribute(XName.Get "offsetend", l), - XAttribute( - XName.Get "document", - result.Attribute(XName.Get "assembly").Value - ) + let br = + XElement( + XName.Get "branch", + XAttribute(XName.Get "visitcount", v), + XAttribute(XName.Get "line", l), + XAttribute(XName.Get "path", n), + XAttribute(XName.Get "offset", l), + XAttribute(XName.Get "offsetend", l), + XAttribute( + XName.Get "document", + result.Attribute(XName.Get "assembly").Value ) + ) - x.Add br - x + x.Add br + x | _ -> raise (r |> sprintf "%A" |> InvalidDataException)) null |> ignore @@ -154,32 +154,25 @@ module internal Lcov = match line with | l when l.StartsWith("SF:", StringComparison.Ordinal) -> SF(l.Substring 3) | l when l.StartsWith("FN:", StringComparison.Ordinal) -> - let trim = l.Substring 3 - let comma = trim.IndexOf ',' - let n = trim.Substring(0, comma) - let name = trim.Substring(comma + 1) - FN(n |> Int32.TryParse |> snd, name) + let trim = l.Substring 3 + let comma = trim.IndexOf ',' + let n = trim.Substring(0, comma) + let name = trim.Substring(comma + 1) + FN(n |> Int32.TryParse |> snd, name) | l when l.StartsWith("DA:", StringComparison.Ordinal) -> - match (l.Substring 3).Split(',') |> Array.toList with - | n :: v :: _ -> - DA(n |> Int32.TryParse |> snd, v |> Int32.TryParse |> snd) - | _ -> - raise (line - |> sprintf "%A" - |> InvalidDataException) + match (l.Substring 3).Split(',') |> Array.toList with + | n :: v :: _ -> DA(n |> Int32.TryParse |> snd, v |> Int32.TryParse |> snd) + | _ -> raise (line |> sprintf "%A" |> InvalidDataException) | l when l.StartsWith("BRDA:", StringComparison.Ordinal) -> - match (l.Substring 5).Split(',') |> Array.toList with - | n :: v :: x :: y :: _ -> - BRDA( - n |> Int32.TryParse |> snd, - v |> Int32.TryParse |> snd, - x |> Int32.TryParse |> snd, - y |> Int32.TryParse |> snd - ) - | _ -> - raise (line - |> sprintf "%A" - |> InvalidDataException) + match (l.Substring 5).Split(',') |> Array.toList with + | n :: v :: x :: y :: _ -> + BRDA( + n |> Int32.TryParse |> snd, + v |> Int32.TryParse |> snd, + x |> Int32.TryParse |> snd, + y |> Int32.TryParse |> snd + ) + | _ -> raise (line |> sprintf "%A" |> InvalidDataException) | _ -> Other) |> Seq.fold (fun (i, l) r -> @@ -194,7 +187,8 @@ module internal Lcov = |> Seq.groupBy fst |> Seq.map (fun (_, l) -> buildModule l) |> Seq.toArray - with x -> raise <| LcovParseException(x) + with + | x -> raise <| LcovParseException(x) let toXml file = let root = diff --git a/AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj b/AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj index 2e63187fe..a703614c2 100644 --- a/AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj +++ b/AltCover.ValidateGendarmeEmulation/AltCover.ValidateGendarmeEmulation.fsproj @@ -10,16 +10,17 @@ $(NuGetCache)/altcode.gendarme-tool/$(GendarmeVersion)/tools/netcoreapp2.1/any/ false AltCover.ValidateGendarmeEmulation - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - Major + + false + TRACE;DEBUG;CODE_ANALYSIS;ValidateGendarmeEmulation TRACE;ValidateGendarmeEmulation + @@ -48,6 +49,7 @@ + AssemblyInfo.fs @@ -63,6 +65,7 @@ + all @@ -75,8 +78,9 @@ runtime; build; native; contentfiles; analyzers - + + diff --git a/AltCover.ValidateGendarmeEmulation/Tests.fs b/AltCover.ValidateGendarmeEmulation/Tests.fs index b5668be49..8c5f7e738 100644 --- a/AltCover.ValidateGendarmeEmulation/Tests.fs +++ b/AltCover.ValidateGendarmeEmulation/Tests.fs @@ -16,7 +16,7 @@ module Rocks = |> Seq.toList)) module ValidateGendarmeEmulation = - let importantItems (n, e, r) = Maybe (r <> e) (Some(n, e, r)) None + let importantItems (n, e, r) = Maybe(r <> e) (Some(n, e, r)) None let stringify x = match x with diff --git a/AltCover.Visualizer.Tests/AltCover.Visualizer.Tests.fsproj b/AltCover.Visualizer.Tests/AltCover.Visualizer.Tests.fsproj index dfe3a99c9..98c8281d3 100644 --- a/AltCover.Visualizer.Tests/AltCover.Visualizer.Tests.fsproj +++ b/AltCover.Visualizer.Tests/AltCover.Visualizer.Tests.fsproj @@ -6,20 +6,15 @@ false AltCover.Tests.Visualizer GUI - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ - Major TRACE;DEBUG;CODE_ANALYSIS;$(GlobalDefineConstants) - --tailcalls+ --keyfile:$(ProjectDir)..\Build\Infrastructure.snk TRACE;$(GlobalDefineConstants) - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk - + 988 @@ -37,7 +32,7 @@ - + diff --git a/AltCover.Visualizer/AltCover.Visualizer.fsproj b/AltCover.Visualizer/AltCover.Visualizer.fsproj index 0ea3295b7..ca06cf2f3 100644 --- a/AltCover.Visualizer/AltCover.Visualizer.fsproj +++ b/AltCover.Visualizer/AltCover.Visualizer.fsproj @@ -5,42 +5,20 @@ netcoreapp2.1;net472 AltCover.Visualizer AltCover.Visualizer - false x86 True altcover.visualizer AltCover.Visualizer - true - GUI - $(ProjectDir)../ - $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ - $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ + GUI;$(TOGGLE) True $(ProjectDir)Resource.res - Major - false - - - - false - false - - - true - true TRACE;DEBUG;CODE_ANALYSIS;$(GlobalDefineConstants) - --tailcalls+ --keyfile:$(ProjectDir)..\Build\Infrastructure.snk - 4 - true - - true TRACE;$(GlobalDefineConstants) - --keyfile:$(ProjectDir)..\Build\Infrastructure.snk diff --git a/AltCover.Visualizer/Visualizer.fs b/AltCover.Visualizer/Visualizer.fs index 711a0f795..c0c1b763e 100644 --- a/AltCover.Visualizer/Visualizer.fs +++ b/AltCover.Visualizer/Visualizer.fs @@ -94,21 +94,19 @@ module private Gui = [] - [] - let private urlHook _ link = - Browser.ShowUrl(Uri link) + let private urlHook _ link = Browser.ShowUrl(Uri link) #endif let private prepareAboutDialog (handler: Handler) = #if !NET472 handler.aboutVisualizer.TransientFor <- handler.mainWindow #else - AboutDialog.SetUrlHook(urlHook) - |> ignore + AboutDialog.SetUrlHook(urlHook) |> ignore - LinkButton.SetUriHook(urlHook) - |> ignore + LinkButton.SetUriHook(urlHook) |> ignore handler.aboutVisualizer.ActionArea.Children.OfType