From f4b99d73daaa7a9d558c7055cf3e511541488e43 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Tue, 13 Mar 2018 13:24:47 +0000 Subject: [PATCH 01/67] Bump the build number --- ReleaseNotes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index e3594a814..11d184c4c 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,6 +1,6 @@ **NOTE:** The main executable links the still in beta (after more than a year) Mono.Cecil 0.10 version. The binary injected into the instrumented code does not. Rather than hold my releases on the Mono.Cecil schedule, I make this disclaimer instead. -# 2.0.### (Byakko series release 4) +# 2.0.330 (Byakko series release 4) * "y|symbolDirectory=" option to provide other locations to find symbols for the instrumented assemblies. The search order goes -- location in the debug header, co-located (.pdb than .mdb), then supplied locations tested in order for .pdb than .mdb # 2.0.324 (Byakko series release 3) From 3c261aa52809e84b470ba6b16053b40c7bb0798f Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Tue, 13 Mar 2018 18:21:50 +0000 Subject: [PATCH 02/67] Fix typo in release notes --- ReleaseNotes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 11d184c4c..3ff030701 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,7 +1,7 @@ **NOTE:** The main executable links the still in beta (after more than a year) Mono.Cecil 0.10 version. The binary injected into the instrumented code does not. Rather than hold my releases on the Mono.Cecil schedule, I make this disclaimer instead. # 2.0.330 (Byakko series release 4) -* "y|symbolDirectory=" option to provide other locations to find symbols for the instrumented assemblies. The search order goes -- location in the debug header, co-located (.pdb than .mdb), then supplied locations tested in order for .pdb than .mdb +* "y|symbolDirectory=" option to provide other locations to find symbols for the instrumented assemblies. The search order goes -- location in the debug header, co-located (.pdb then .mdb), then supplied locations tested in order for .pdb then .mdb # 2.0.324 (Byakko series release 3) * Option `--opencover` now generates values for MethodPoint tags when collecting the coverage data in "runner" mode From bbfe643386866938da2cc61a8a0a61557b6634da Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Tue, 13 Mar 2018 18:55:08 +0000 Subject: [PATCH 03/67] Rename the files used to communicate visit information between instrumented code and the runner from .bin to .acv --- AltCover.Recorder/Recorder.fs | 2 +- AltCover.Recorder/Tracer.fs | 4 ++-- AltCover/Runner.fs | 8 ++++---- Shadow.Tests/Tracer.fs | 8 ++++---- Tests/Runner.Tests.fs | 10 +++++----- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/AltCover.Recorder/Recorder.fs b/AltCover.Recorder/Recorder.fs index 4d2d875ce..d02a29ffc 100644 --- a/AltCover.Recorder/Recorder.fs +++ b/AltCover.Recorder/Recorder.fs @@ -76,7 +76,7 @@ module Instance = /// /// Reporting back to the mother-ship /// - let mutable internal trace = Tracer.Create (ReportFile + ".bin") + let mutable internal trace = Tracer.Create (ReportFile + ".acv") let internal WithMutex (f : bool -> 'a) = let own = mutex.WaitOne(1000) diff --git a/AltCover.Recorder/Tracer.fs b/AltCover.Recorder/Tracer.fs index 158b1d1bd..e01719483 100644 --- a/AltCover.Recorder/Tracer.fs +++ b/AltCover.Recorder/Tracer.fs @@ -30,7 +30,7 @@ type Tracer = { member this.Connect () = if File.Exists this.Tracer then Seq.initInfinite (fun i -> Path.ChangeExtension(this.Tracer, - sprintf ".%d.bin" i)) + sprintf ".%d.acv" i)) |> Seq.filter (File.Exists >> not) |> Seq.map (fun f -> let fs = File.OpenWrite f { this with Stream = new DeflateStream(fs, CompressionMode.Compress) }) @@ -54,7 +54,7 @@ type Tracer = { visits.Clear() member this.OnStart () = - if this.Tracer <> "Coverage.Default.xml.bin" then + if this.Tracer <> "Coverage.Default.xml.acv" then this.Connect () else this diff --git a/AltCover/Runner.fs b/AltCover/Runner.fs index 3a4406e4e..f997b9197 100644 --- a/AltCover/Runner.fs +++ b/AltCover/Runner.fs @@ -115,7 +115,7 @@ module Runner = Console.WriteLine (s |> CommandLine.resources.GetString, x) let MonitorBase (hits:ICollection<(string*int)>) report (payload: string list -> int) (args : string list) = - let binpath = report + ".bin" + let binpath = report + ".acv" do use stream = File.Create(binpath) () @@ -128,7 +128,7 @@ module Runner = formatter.Binder <- MonoTypeBinder(typeof<(string*int)>) // anything else is an error Directory.GetFiles( Path.GetDirectoryName(report), - Path.GetFileName(report) + ".*.bin") + Path.GetFileName(report) + ".*.acv") |> Seq.iter (fun f -> printfn "... %s" f use results = new DeflateStream(File.OpenRead f, CompressionMode.Decompress) @@ -286,8 +286,8 @@ module Runner = WriteResourceWithFormatItems "Coverage statistics flushing took {0:N} seconds" [|delta.TotalSeconds|] // And tidy up after everything's done - File.Delete (report + ".bin") + File.Delete (report + ".acv") Directory.GetFiles( Path.GetDirectoryName(report), - Path.GetFileName(report) + ".*.bin") + Path.GetFileName(report) + ".*.acv") |> Seq.iter File.Delete result \ No newline at end of file diff --git a/Shadow.Tests/Tracer.fs b/Shadow.Tests/Tracer.fs index 4b8415925..ed685a556 100644 --- a/Shadow.Tests/Tracer.fs +++ b/Shadow.Tests/Tracer.fs @@ -79,7 +79,7 @@ type AltCoverCoreTests() = class let save = Instance.trace let where = Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName let unique = Path.Combine(where, Guid.NewGuid().ToString()) - let tag = unique + ".bin" + let tag = unique + ".acv" let expected = [("name", 23); ("name", 23)] do @@ -100,7 +100,7 @@ type AltCoverCoreTests() = class Instance.trace.Close() Instance.trace <- save - use stream = new DeflateStream(File.OpenRead (unique + ".0.bin"), CompressionMode.Decompress) + use stream = new DeflateStream(File.OpenRead (unique + ".0.acv"), CompressionMode.Decompress) let results = self.ReadResults stream Assert.That (Instance.Visits, Is.Empty, "unexpected local write") Assert.That (results, Is.EquivalentTo expected, "unexpected result") @@ -113,7 +113,7 @@ type AltCoverCoreTests() = class let save = Instance.trace let where = Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName let root = Path.Combine(where, Guid.NewGuid().ToString()) - let unique = root + ".bin" + let unique = root + ".acv" do use stream = File.Create unique @@ -138,7 +138,7 @@ type AltCoverCoreTests() = class System.Threading.Thread.Sleep 100 Instance.trace <- save - use stream = new DeflateStream(File.OpenRead (root + ".0.bin"), CompressionMode.Decompress) + use stream = new DeflateStream(File.OpenRead (root + ".0.acv"), CompressionMode.Decompress) let results = self.ReadResults stream Assert.That (Instance.Visits, Is.Empty, "unexpected local write") Assert.That (results, Is.EquivalentTo expected, "unexpected result") diff --git a/Tests/Runner.Tests.fs b/Tests/Runner.Tests.fs index 92865ad8b..fdbfd0e7c 100644 --- a/Tests/Runner.Tests.fs +++ b/Tests/Runner.Tests.fs @@ -820,7 +820,7 @@ or Runner.DoReport <- write let empty = OptionSet() - let dummy = report + ".xx.bin" + let dummy = report + ".xx.acv" do use temp = File.Create dummy dummy |> File.Exists |> Assert.That @@ -897,11 +897,11 @@ or let where = Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName let unique = Path.Combine(where, Guid.NewGuid().ToString()) do - use s = File.Create (unique + ".0.bin") + use s = File.Create (unique + ".0.acv") s.Close() let r = Runner.GetMonitor hits unique List.length [] Assert.That(r, Is.EqualTo 0) - Assert.That (File.Exists (unique + ".bin")) + Assert.That (File.Exists (unique + ".acv")) Assert.That(hits, Is.Empty) [] @@ -911,11 +911,11 @@ or let unique = Path.Combine(where, Guid.NewGuid().ToString()) let formatter = System.Runtime.Serialization.Formatters.Binary.BinaryFormatter() let r = Runner.GetMonitor hits unique (fun l -> - use sink = new DeflateStream(File.OpenWrite (unique + ".0.bin"), CompressionMode.Compress) + use sink = new DeflateStream(File.OpenWrite (unique + ".0.acv"), CompressionMode.Compress) l |> List.mapi (fun i x -> formatter.Serialize(sink, (x,i)); x) |> List.length ) ["a"; "b"; String.Empty; "c"] Assert.That(r, Is.EqualTo 4) - Assert.That (File.Exists (unique + ".bin")) + Assert.That (File.Exists (unique + ".acv")) Assert.That(hits, Is.EquivalentTo [("a",0); ("b",1)]) [] From bd3dade3bafd0c17d56789352b101442763152d1 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Thu, 15 Mar 2018 15:07:46 +0000 Subject: [PATCH 04/67] Track "-e" excluded assemblies in the coverage file, so we will have somewhere to put tracked methods if so required. --- AltCover/OpenCover.fs | 10 ++++++---- AltCover/Report.fs | 7 ++++--- AltCover/Visitor.fs | 8 ++++---- Build/targets.fsx | 8 ++++---- Tests/Tests.fs | 43 ++++++++++++++++++++++++++++++++++++------- 5 files changed, 54 insertions(+), 22 deletions(-) diff --git a/AltCover/OpenCover.fs b/AltCover/OpenCover.fs index b37e27a46..8c350e530 100644 --- a/AltCover/OpenCover.fs +++ b/AltCover/OpenCover.fs @@ -89,15 +89,17 @@ module OpenCover = {s with Stack = modules :: s.Stack } let VisitModule (s : Context) (moduleDef:ModuleDefinition) included = - let element = XElement(X "Module", - XAttribute(X "hash", KeyStore.HashFile moduleDef.FileName)) + let element = XElement(X "Module") + if not included then element.SetAttributeValue(X "skippedDueTo", "Filter") + else element.Add(Summary()) + element.SetAttributeValue(X "hash", KeyStore.HashFile moduleDef.FileName) let head = s.Stack |> Seq.head head.Add(element) - element.Add(Summary()) + element.Add(XElement(X "ModulePath", moduleDef.FileName)) element.Add(XElement(X "ModuleTime", File.GetLastWriteTimeUtc moduleDef.FileName)) element.Add(XElement(X "ModuleName", moduleDef.Assembly.Name.Name)) - element.Add(XElement(X "Files")) + if included then element.Add(XElement(X "Files")) let classes = XElement(X "Classes") element.Add(classes) {s with Stack = classes :: s.Stack diff --git a/AltCover/Report.fs b/AltCover/Report.fs index a32ba0723..0c25316d2 100644 --- a/AltCover/Report.fs +++ b/AltCover/Report.fs @@ -29,12 +29,13 @@ module Report = document.Add(element) element :: s - let VisitModule (s : list) (head:XElement) (moduleDef:ModuleDefinition) = + let VisitModule (s : list) (head:XElement) (moduleDef:ModuleDefinition) included = let element = XElement(X "module", XAttribute(X "moduleId", moduleDef.Mvid.ToString()), XAttribute(X "name", moduleDef.Name), XAttribute(X "assembly", moduleDef.Assembly.Name.Name), - XAttribute(X "assemblyIdentity", moduleDef.Assembly.Name.FullName)) + XAttribute(X "assemblyIdentity", moduleDef.Assembly.Name.FullName), + XAttribute(X "excluded", if included then "false" else "true")) head.Add(element) element :: s @@ -77,7 +78,7 @@ module Report = let tail = if List.isEmpty s then [] else s.Tail match node with | Start _ -> StartVisit s - | Module (moduleDef,_, _) -> VisitModule s head moduleDef + | Module (moduleDef,_, included) -> VisitModule s head moduleDef included | Method (methodDef, _, included) -> VisitMethod s head methodDef included | MethodPoint (_, codeSegment, _, included) -> VisitMethodPoint s head codeSegment included diff --git a/AltCover/Visitor.fs b/AltCover/Visitor.fs index 24cff4083..2030869ad 100644 --- a/AltCover/Visitor.fs +++ b/AltCover/Visitor.fs @@ -146,13 +146,13 @@ module Visitor = let private VisitAssembly (a:AssemblyDefinition) reader included buildSequence = a.Modules |> Seq.cast - |> Seq.filter IsIncluded - |> Seq.collect ((fun x -> Module (x, reader, included)) >> buildSequence) + |> Seq.collect ((fun x -> Module (x, reader, included && IsIncluded x)) >> buildSequence) let private VisitModule (x:ModuleDefinition) reader included buildSequence = PointNumber <- 0 - x.GetAllTypes() - |> Seq.cast + [x] + |> Seq.takeWhile (fun _ -> included) + |> Seq.collect(fun x -> x.GetAllTypes() |> Seq.cast) |> Seq.collect ((fun t -> Type (t, reader, included && IsIncluded t)) >> buildSequence) let private VisitType (t:TypeDefinition) (reader:ISymbolReader option) included buildSequence = diff --git a/Build/targets.fsx b/Build/targets.fsx index 52eb7af33..4b21ec23e 100644 --- a/Build/targets.fsx +++ b/Build/targets.fsx @@ -355,7 +355,7 @@ Target "UnitTestWithAltCover" (fun _ -> { info with FileName = altcover WorkingDirectory = testDirectory - Arguments = ("--opencover /sn=" + keyfile + AltCoverFilterX + @"/o=./__UnitTestWithAltCover -x=" + altReport)}) + Arguments = (" /sn=" + keyfile + AltCoverFilter + @"/o=./__UnitTestWithAltCover -x=" + altReport)}) "Re-instrument returned with a non-zero exit code" printfn "Unit test the instrumented code" @@ -378,7 +378,7 @@ Target "UnitTestWithAltCover" (fun _ -> { info with FileName = altcover WorkingDirectory = weakDir - Arguments = ("--opencover /sn=" + keyfile + AltCoverFilterX + " /o=./__WeakNameTestWithAltCover -x=" + weakReport)}) + Arguments = ("--opencover /sn=" + keyfile + AltCoverFilter + " /o=./__WeakNameTestWithAltCover -x=" + weakReport)}) "Instrumenting the weakname tests failed" printfn "Execute the weakname tests" @@ -394,7 +394,7 @@ Target "UnitTestWithAltCover" (fun _ -> { info with FileName = altcover WorkingDirectory = shadowDir - Arguments = ("--opencover /sn=" + keyfile + AltCoverFilterX + @"/o=./__ShadowTestWithAltCover -x=" + shadowReport)}) + Arguments = ("--opencover /sn=" + keyfile + AltCoverFilter + @"/o=./__ShadowTestWithAltCover -x=" + shadowReport)}) "Instrumenting the shadow tests failed" printfn "Execute the shadow tests" @@ -1334,7 +1334,7 @@ ActivateFinal "ResetConsoleColours" "Compilation" ==> "UnitTestWithAltCover" -// ==> "UnitTest" +==> "UnitTest" "Compilation" ==> "UnitTestWithAltCoverRunner" diff --git a/Tests/Tests.fs b/Tests/Tests.fs index 8107e0e8b..c90820676 100644 --- a/Tests/Tests.fs +++ b/Tests/Tests.fs @@ -765,7 +765,7 @@ type AltCoverTests() = class let assembly = Node.Assembly (def, None, false) let expected = List.concat [ [assembly]; (Visitor.Deeper >> Seq.toList) assembly; [AfterAssembly def]] - Assert.That (deeper.Length, Is.EqualTo 12) + Assert.That (deeper.Length, Is.EqualTo 4) Assert.That (deeper, Is.EquivalentTo expected) finally Visitor.NameFilters.Clear() @@ -1082,7 +1082,7 @@ type AltCoverTests() = class let m = MethodDefinition("dummy", MethodAttributes.Abstract, TypeDefinition("System", "Void", TypeAttributes.Public)) Assert.That (Gendarme.CyclomaticComplexity m, Is.EqualTo 1) - static member private RecursiveValidateOpenCover result expected' depth zero = + static member private RecursiveValidateOpenCover result expected' depth zero expectSkipped = let X name = XName.Get(name) @@ -1090,6 +1090,7 @@ type AltCoverTests() = class let expected = expected' |> Seq.filter (fun (el:XElement) -> el.Name.LocalName <> "Module" || + expectSkipped || "skippedDueTo" |> X |> el.Attributes |> Seq.isEmpty) |> Seq.filter (fun (el:XElement) -> "BranchPoint" <> el.Name.LocalName) |> Seq.toList @@ -1126,7 +1127,7 @@ type AltCoverTests() = class | _ -> Assert.That(a1.Value, Is.EqualTo(a2.Value), r.ToString() + " -> " + a1.Name.ToString()) ) - AltCoverTests.RecursiveValidateOpenCover (r.Elements()) (e.Elements()) (depth+1) zero) + AltCoverTests.RecursiveValidateOpenCover (r.Elements()) (e.Elements()) (depth+1) zero expectSkipped) [] member self.ShouldGenerateExpectedXmlReportFromDotNetOpenCoverStyle() = @@ -1145,7 +1146,35 @@ type AltCoverTests() = class let baseline = XDocument.Load(stream) let result = document.Elements() let expected = baseline.Elements() - AltCoverTests.RecursiveValidateOpenCover result expected 0 true + AltCoverTests.RecursiveValidateOpenCover result expected 0 true false + finally + Visitor.NameFilters.Clear() + + [] + member self.ShouldGenerateExpectedXmlReportWithModuleExclusionOpenCoverStyle() = + let visitor, document = OpenCover.ReportGenerator() + // Hack for running while instrumented + let where = Assembly.GetExecutingAssembly().Location + let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), sample1) + + try + "Sample" |> (Regex >> FilterClass.Module >> Visitor.NameFilters.Add) + Visitor.Visit [ visitor ] (Visitor.ToSeq path) + let raw = " + + + + _Binaries\\AltCover.Tests\\Debug+AnyCPU\\Sample1.exe + 2018-03-15T14:00:17.3385938Z + Sample1 + + + + " + let baseline = XDocument.Load(new System.IO.StringReader(raw)) + let result = document.Elements() + let expected = baseline.Elements() + AltCoverTests.RecursiveValidateOpenCover result expected 0 true true finally Visitor.NameFilters.Clear() @@ -1166,7 +1195,7 @@ type AltCoverTests() = class let baseline = XDocument.Load(stream) let result = document.Elements() let expected = baseline.Elements() - AltCoverTests.RecursiveValidateOpenCover result expected 0 true + AltCoverTests.RecursiveValidateOpenCover result expected 0 true false finally Visitor.NameFilters.Clear() @@ -1187,7 +1216,7 @@ type AltCoverTests() = class let baseline = XDocument.Load(stream) let result = document.Elements() let expected = baseline.Elements() - AltCoverTests.RecursiveValidateOpenCover result expected 0 true + AltCoverTests.RecursiveValidateOpenCover result expected 0 true false finally Visitor.NameFilters.Clear() @@ -1215,7 +1244,7 @@ type AltCoverTests() = class let baseline = XDocument.Load(stream) let result = document.Elements() let expected = baseline.Elements() - AltCoverTests.RecursiveValidateOpenCover result expected 0 true + AltCoverTests.RecursiveValidateOpenCover result expected 0 true false finally Visitor.NameFilters.Clear() From 35f472f31bb1b2cce133aa228ee54892f0a36709 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Thu, 15 Mar 2018 16:05:34 +0000 Subject: [PATCH 05/67] Use the new Cecil APIs properly -- no need to re-read the symbols. --- AltCover/Instrument.fs | 10 +-- AltCover/OpenCover.fs | 8 +-- AltCover/ProgramDatabase.fs | 5 +- AltCover/Report.fs | 4 +- AltCover/Visitor.fs | 57 ++++++++-------- Tests/Tests.fs | 125 +++++++++++++++++------------------- 6 files changed, 98 insertions(+), 111 deletions(-) diff --git a/AltCover/Instrument.fs b/AltCover/Instrument.fs index 0861fbd99..1ff45b3e7 100644 --- a/AltCover/Instrument.fs +++ b/AltCover/Instrument.fs @@ -143,7 +143,7 @@ module Instrument = /// A representation of the assembly used to record all coverage visits. let internal PrepareAssembly (location:string) = let definition = AssemblyDefinition.ReadAssembly(location) - ProgramDatabase.ReadSymbols definition |> ignore + ProgramDatabase.ReadSymbols definition definition.Name.Name <- (extractName definition) + ".g" #if NETCOREAPP2_0 let pair = None @@ -404,12 +404,12 @@ module Instrument = match node with | Start _ -> let recorder = typeof { state with RecordingAssembly = PrepareAssembly(recorder.Assembly.Location) } - | Assembly (assembly, _, included) -> if included then + | Assembly (assembly, included) -> if included then assembly.MainModule.AssemblyReferences.Add(state.RecordingAssembly.Name) - state - | Module (m, _, included) -> VisitModule state m included + state + | Module (m, included) -> VisitModule state m included | Type _ -> state - | Method (m, _, included) -> VisitMethod state m included + | Method (m, included) -> VisitMethod state m included | MethodPoint (instruction, _, point, included) -> VisitMethodPoint state instruction point included diff --git a/AltCover/OpenCover.fs b/AltCover/OpenCover.fs index 8c350e530..7b9164741 100644 --- a/AltCover/OpenCover.fs +++ b/AltCover/OpenCover.fs @@ -95,7 +95,7 @@ module OpenCover = element.SetAttributeValue(X "hash", KeyStore.HashFile moduleDef.FileName) let head = s.Stack |> Seq.head head.Add(element) - + element.Add(XElement(X "ModulePath", moduleDef.FileName)) element.Add(XElement(X "ModuleTime", File.GetLastWriteTimeUtc moduleDef.FileName)) element.Add(XElement(X "ModuleName", moduleDef.Assembly.Name.Name)) @@ -295,9 +295,9 @@ module OpenCover = let ReportVisitor (s : Context) (node:Node) = match node with | Start _ -> StartVisit s - | Node.Module (moduleDef, _ , included) -> VisitModule s moduleDef included - | Node.Type (typeDef, _, included) -> VisitType s typeDef included - | Node.Method (methodDef, _, included) -> VisitMethod s methodDef included + | Node.Module (moduleDef, included) -> VisitModule s moduleDef included + | Node.Type (typeDef, included) -> VisitType s typeDef included + | Node.Method (methodDef, included) -> VisitMethod s methodDef included | MethodPoint (_, codeSegment, i, included) -> VisitMethodPoint' s codeSegment i included | AfterMethod _ -> VisitAfterMethod s | AfterType _ -> VisitAfterType s diff --git a/AltCover/ProgramDatabase.fs b/AltCover/ProgramDatabase.fs index 8b508778f..c769d4b77 100644 --- a/AltCover/ProgramDatabase.fs +++ b/AltCover/ProgramDatabase.fs @@ -53,11 +53,10 @@ module ProgramDatabase = // Will fail with InvalidOperationException if there is a malformed file with the expected name let ReadSymbols (assembly:AssemblyDefinition) = GetPdbWithFallback assembly - |> Option.map (fun pdbpath -> + |> Option.iter (fun pdbpath -> let provider : ISymbolReaderProvider = if pdbpath.EndsWith(".pdb", StringComparison.OrdinalIgnoreCase) then PdbReaderProvider() :> ISymbolReaderProvider else MdbReaderProvider() :> ISymbolReaderProvider let reader = provider.GetSymbolReader(assembly.MainModule, pdbpath) - assembly.MainModule.ReadSymbols(reader) - reader) \ No newline at end of file + assembly.MainModule.ReadSymbols(reader)) \ No newline at end of file diff --git a/AltCover/Report.fs b/AltCover/Report.fs index 0c25316d2..abb205664 100644 --- a/AltCover/Report.fs +++ b/AltCover/Report.fs @@ -78,8 +78,8 @@ module Report = let tail = if List.isEmpty s then [] else s.Tail match node with | Start _ -> StartVisit s - | Module (moduleDef,_, included) -> VisitModule s head moduleDef included - | Method (methodDef, _, included) -> VisitMethod s head methodDef included + | Module (moduleDef, included) -> VisitModule s head moduleDef included + | Method (methodDef, included) -> VisitMethod s head methodDef included | MethodPoint (_, codeSegment, _, included) -> VisitMethodPoint s head codeSegment included diff --git a/AltCover/Visitor.fs b/AltCover/Visitor.fs index 2030869ad..a3a1df896 100644 --- a/AltCover/Visitor.fs +++ b/AltCover/Visitor.fs @@ -22,10 +22,10 @@ open Mono.Cecil.Rocks [] type internal Node = | Start of seq - | Assembly of AssemblyDefinition * ISymbolReader option * bool - | Module of ModuleDefinition * ISymbolReader option * bool - | Type of TypeDefinition * ISymbolReader option * bool - | Method of MethodDefinition * MethodDebugInformation option * bool + | Assembly of AssemblyDefinition * bool + | Module of ModuleDefinition * bool + | Type of TypeDefinition * bool + | Method of MethodDefinition * bool | MethodPoint of Instruction * SequencePoint option * int * bool | AfterMethod of bool | AfterType @@ -118,10 +118,10 @@ module Visitor = let internal After node = match node with | Start _ -> ToSeq Finish - | Assembly (a,_,_) -> AfterAssembly a |> ToSeq + | Assembly (a, _) -> AfterAssembly a |> ToSeq | Module _ -> AfterModule |> ToSeq | Type _ -> AfterType |> ToSeq - | Method (_,_,included) -> AfterMethod included |> ToSeq + | Method (_,included) -> AfterMethod included |> ToSeq | _ -> Seq.empty let mutable private PointNumber : int = 0 @@ -139,45 +139,40 @@ module Visitor = paths |> Seq.collect (AssemblyDefinition.ReadAssembly >> (fun x -> let included = IsIncluded x - let reader = if included then ProgramDatabase.ReadSymbols(x) - else None - Assembly(x, reader, included)) >> buildSequence) + ProgramDatabase.ReadSymbols(x) + Assembly(x, included)) >> buildSequence) - let private VisitAssembly (a:AssemblyDefinition) reader included buildSequence = + let private VisitAssembly (a:AssemblyDefinition) included buildSequence = a.Modules |> Seq.cast - |> Seq.collect ((fun x -> Module (x, reader, included && IsIncluded x)) >> buildSequence) + |> Seq.collect ((fun x -> Module (x, included && IsIncluded x)) >> buildSequence) - let private VisitModule (x:ModuleDefinition) reader included buildSequence = + let private VisitModule (x:ModuleDefinition) included buildSequence = PointNumber <- 0 [x] |> Seq.takeWhile (fun _ -> included) |> Seq.collect(fun x -> x.GetAllTypes() |> Seq.cast) - |> Seq.collect ((fun t -> Type (t, reader, included && IsIncluded t)) >> buildSequence) + |> Seq.collect ((fun t -> Type (t, included && IsIncluded t)) >> buildSequence) - let private VisitType (t:TypeDefinition) (reader:ISymbolReader option) included buildSequence = + let private VisitType (t:TypeDefinition) included buildSequence = t.Methods |> Seq.cast |> Seq.filter (fun (m : MethodDefinition) -> not m.IsAbstract && not m.IsRuntime && not m.IsPInvokeImpl && significant m) - |> Seq.collect ((fun m -> let dbg = reader - |> Option.map (fun r -> r.Read m) - |> Option.bind Option.nullable - Method (m, dbg, included && IsIncluded m)) >> buildSequence) + |> Seq.collect ((fun m -> Method (m, included && IsIncluded m)) >> buildSequence) - let private VisitMethod (m:MethodDefinition) (dbg:MethodDebugInformation option) included = + let private VisitMethod (m:MethodDefinition) included = let rawInstructions = m.Body.Instructions + let dbg = m.DebugInformation let instructions = rawInstructions |> Seq.cast - |> Seq.filter (fun (x:Instruction) -> match dbg with - | None -> false - | Some d -> - if d.HasSequencePoints then - let s = d.GetSequencePoint x - (not << isNull) s && s.StartLine <> 0xfeefee - else false) + |> Seq.filter (fun (x:Instruction) -> dbg |> isNull |> not) + |> Seq.filter (fun (x:Instruction) -> if dbg.HasSequencePoints then + let s = dbg.GetSequencePoint x + (not << isNull) s && s.StartLine <> 0xfeefee + else false) |> Seq.toList let number = instructions.Length @@ -190,17 +185,17 @@ module Visitor = |> Seq.map (fun i -> MethodPoint (i, None, m.MetadataToken.ToInt32(), included)) else instructions.OrderByDescending(fun (x:Instruction) -> x.Offset) - |> Seq.mapi (fun i x -> let s = (Option.get dbg).GetSequencePoint(x) + |> Seq.mapi (fun i x -> let s = dbg.GetSequencePoint(x) MethodPoint (x, Some s, i+point, included && (IsIncluded s.Document.Url))) let rec internal Deeper node = // The pattern here is map x |> map y |> map x |> concat => collect (x >> y >> z) match node with | Start paths -> StartVisit paths BuildSequence - | Assembly (a, reader, included) -> VisitAssembly a reader included BuildSequence - | Module (x, reader, included) -> VisitModule x reader included BuildSequence - | Type (t, reader, included) -> VisitType t reader included BuildSequence - | Method (m, dbg, included) -> VisitMethod m dbg included + | Assembly (a, included) -> VisitAssembly a included BuildSequence + | Module (x, included) -> VisitModule x included BuildSequence + | Type (t, included) -> VisitType t included BuildSequence + | Method (m, included) -> VisitMethod m included | _ -> Seq.empty and internal BuildSequence node = diff --git a/Tests/Tests.fs b/Tests/Tests.fs index c90820676..9341e2c14 100644 --- a/Tests/Tests.fs +++ b/Tests/Tests.fs @@ -205,7 +205,7 @@ type AltCoverTests() = class let dll = Path.Combine(output, Path.GetFileName dll0) System.IO.File.Copy (dll0, dll) ProgramDatabase.SymbolFolders.Clear() - p |> Path.GetDirectoryName |> ProgramDatabase.SymbolFolders.Add + p |> Path.GetDirectoryName |> ProgramDatabase.SymbolFolders.Add try let def = Mono.Cecil.AssemblyDefinition.ReadAssembly dll let pdb = AltCover.ProgramDatabase.GetPdbWithFallback(def) @@ -213,16 +213,14 @@ type AltCoverTests() = class match pdb with | None -> Assert.Fail("Not found " + p) | Some name -> Assert.That(name, Is.EqualTo normalized) - let reader = AltCover.ProgramDatabase.ReadSymbols def + AltCover.ProgramDatabase.ReadSymbols def Assert.That (def.MainModule.HasSymbols, def.MainModule.FileName) - Assert.That (Option.isSome reader, def.MainModule.FileName) with | :? BadImageFormatException -> () ) finally ProgramDatabase.SymbolFolders.Clear() - [] member self.ShouldGetMdbWithFallback() = // Hack for running while instrumented @@ -263,9 +261,8 @@ type AltCoverTests() = class |> Seq.map Mono.Cecil.AssemblyDefinition.ReadAssembly |> Seq.filter (fun x -> x.FullName.EndsWith("PublicKeyToken=c02b1a9f5b7cade8", StringComparison.OrdinalIgnoreCase)) |> Seq.iter (fun def -> - let reader = AltCover.ProgramDatabase.ReadSymbols def + AltCover.ProgramDatabase.ReadSymbols def Assert.That (def.MainModule.HasSymbols, def.MainModule.FileName) - Assert.That (Option.isSome reader, def.MainModule.FileName) ) [] @@ -280,9 +277,8 @@ type AltCoverTests() = class |> Seq.map Mono.Cecil.AssemblyDefinition.ReadAssembly |> Seq.filter (fun x -> not <| x.FullName.EndsWith("PublicKeyToken=c02b1a9f5b7cade8", StringComparison.OrdinalIgnoreCase)) |> Seq.iter (fun def -> - let reader = AltCover.ProgramDatabase.ReadSymbols def + AltCover.ProgramDatabase.ReadSymbols def Assert.That (not def.MainModule.HasSymbols, def.MainModule.FileName) - Assert.That (Option.isNone reader, def.MainModule.FileName) ) [] @@ -303,7 +299,7 @@ type AltCoverTests() = class || x.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) |> Seq.iter( fun x -> let def = Mono.Cecil.AssemblyDefinition.ReadAssembly x - AltCover.ProgramDatabase.ReadSymbols def |> ignore + AltCover.ProgramDatabase.ReadSymbols def Assert.That (def.MainModule.HasSymbols, def.MainModule.FileName) ) @@ -604,8 +600,8 @@ type AltCoverTests() = class [] member self.AfterProcessingYieldsAnExpectedValue() = let def = Mono.Cecil.AssemblyDefinition.ReadAssembly (Assembly.GetExecutingAssembly().Location) - let inputs = [ Node.Start [] ; Node.Assembly (def, None, true) ; Node.Module (null, None, false) ; Node.Type (null, None, true) ; - Node.Method (null, None, false) ; Node.MethodPoint (null, None, 0, true ) ; + let inputs = [ Node.Start [] ; Node.Assembly (def, true) ; Node.Module (null, false) ; Node.Type (null, true) ; + Node.Method (null, false) ; Node.MethodPoint (null, None, 0, true ) ; Node.AfterMethod false ; Node.AfterModule ; Node.AfterAssembly def; Node.Finish ] let outputs = inputs |> Seq.map (Visitor.After >> Seq.toList) let expected = [ [Finish]; [AfterAssembly def]; [AfterModule]; [AfterType]; [AfterMethod false]; []; []; []; []; []] @@ -645,14 +641,12 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), sample1) let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - let reader = ProgramDatabase.ReadSymbols def + ProgramDatabase.ReadSymbols def let method = (def.MainModule.Types |> Seq.skipWhile (fun t -> t.Name.StartsWith("<"))|> Seq.head).Methods |> Seq.head Visitor.Visit [] [] // cheat reset try "Program" |> (Regex >> FilterClass.File >> Visitor.NameFilters.Add) let deeper = Visitor.Deeper <| Node.Method (method, - reader - |> Option.map (fun r -> r.Read method), true) |> Seq.toList Assert.That (deeper.Length, Is.EqualTo 10) @@ -670,18 +664,17 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), sample1) let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - let rdr = ProgramDatabase.ReadSymbols def + ProgramDatabase.ReadSymbols def let type' = (def.MainModule.Types |> Seq.skipWhile (fun t -> t.Name.StartsWith("<"))|> Seq.head) Visitor.Visit [] [] // cheat reset try "Main" |> (Regex >> FilterClass.Method >> Visitor.NameFilters.Add) - let deeper = Visitor.Deeper <| Node.Type (type', rdr, true) + let deeper = Visitor.Deeper <| Node.Type (type', true) |> Seq.toList Visitor.Visit [] [] // cheat reset - let dbg = Option.get rdr let expected = type'.Methods |> Seq.map (fun m -> let flag = m.Name = ".ctor" - let node = Node.Method (m, Option.nullable (dbg.Read m), flag) + let node = Node.Method (m, flag) List.concat [ [node]; (Visitor.Deeper >> Seq.toList) node; [Node.AfterMethod flag]]) |> List.concat Assert.That (deeper.Length, Is.EqualTo 15) @@ -695,17 +688,17 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), sample1) let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - let rdr = ProgramDatabase.ReadSymbols def + ProgramDatabase.ReadSymbols def let module' = def.MainModule Visitor.Visit [] [] // cheat reset try "Program" |> (Regex >> FilterClass.Type >> Visitor.NameFilters.Add) - let deeper = Visitor.Deeper <| Node.Module (module', rdr, true) + let deeper = Visitor.Deeper <| Node.Module (module', true) |> Seq.toList Visitor.Visit [] [] // cheat reset let expected = module'.Types // we have no nested types in this test |> Seq.map (fun t -> let flag = t.Name <> "Program" - let node = Node.Type (t, rdr, flag) + let node = Node.Type (t, flag) List.concat [ [node]; (Visitor.Deeper >> Seq.toList) node; [Node.AfterType]]) |> List.concat Assert.That (deeper.Length, Is.EqualTo 18) @@ -719,13 +712,13 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), sample1) let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - let rdr = ProgramDatabase.ReadSymbols def + ProgramDatabase.ReadSymbols def Visitor.Visit [] [] // cheat reset - let deeper = Visitor.Deeper <| Node.Assembly (def, rdr, true) + let deeper = Visitor.Deeper <| Node.Assembly (def, true) |> Seq.toList Visitor.Visit [] [] // cheat reset let expected = def.Modules // we have no nested types in this test - |> Seq.map (fun t -> let node = Node.Module (t, rdr, true) + |> Seq.map (fun t -> let node = Node.Module (t, true) List.concat [ [node]; (Visitor.Deeper >> Seq.toList) node; [AfterModule]]) |> List.concat Assert.That (deeper.Length, Is.EqualTo 21) @@ -740,11 +733,11 @@ type AltCoverTests() = class let deeper = Visitor.Deeper <| Node.Start [path] |> Seq.toList // assembly definitions care about being separate references in equality tests - let (def, rdr) = match Seq.head deeper with - | Node.Assembly (def', Some rdr', true) -> (def', rdr') - | _ -> Assert.Fail(); (null, null) + let def = match Seq.head deeper with + | Node.Assembly (def', true) -> def' + | _ -> Assert.Fail(); null - let assembly = Node.Assembly (def, Some rdr, true) + let assembly = Node.Assembly (def, true) let expected = List.concat [ [assembly]; (Visitor.Deeper >> Seq.toList) assembly; [AfterAssembly def]] Assert.That (deeper.Length, Is.EqualTo 23) Assert.That (deeper |> Seq.map string, @@ -760,10 +753,10 @@ type AltCoverTests() = class |> Seq.toList // assembly definitions care about being separate references in equality tests let def = match Seq.head deeper with - | Node.Assembly (def', None, false) -> def' + | Node.Assembly (def', false) -> def' | _ -> Assert.Fail(); null - let assembly = Node.Assembly (def, None, false) + let assembly = Node.Assembly (def, false) let expected = List.concat [ [assembly]; (Visitor.Deeper >> Seq.toList) assembly; [AfterAssembly def]] Assert.That (deeper.Length, Is.EqualTo 4) Assert.That (deeper, Is.EquivalentTo expected) @@ -808,11 +801,11 @@ type AltCoverTests() = class let fix = Visitor.EncloseState (fun (x:System.Collections.Generic.List) t -> x.Add t; x) accumulator Visitor.Visit [fix] [path] // assembly definitions care about being separate references in equality tests - let (def, rdr) = match accumulator.[1] with - | Node.Assembly (def', Some rdr', true) -> (def', rdr') - | _ -> Assert.Fail(); (null, null) + let def = match accumulator.[1] with + | Node.Assembly (def', true) -> def' + | _ -> Assert.Fail(); null - let assembly = Node.Assembly (def, Some rdr, true) + let assembly = Node.Assembly (def, true) let expected = List.concat [ [Start[path]; assembly]; (Visitor.Deeper >> Seq.toList) assembly; [AfterAssembly def; Finish]] Assert.That (accumulator |> Seq.map string, Is.EquivalentTo (expected |> Seq.map string)) @@ -1481,7 +1474,7 @@ type AltCoverTests() = class let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample3.dll") let prepared = Instrument.PrepareAssembly path let raw = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols raw |> ignore + ProgramDatabase.ReadSymbols raw Assert.That (prepared.Name.Name, Is.EqualTo (raw.Name.Name + ".g")) #if NETCOREAPP2_0 Assert.That (prepared.Name.HasPublicKey, Is.False) @@ -1642,7 +1635,7 @@ type AltCoverTests() = class let save = Visitor.reportPath try let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let clazz = def.MainModule.GetType("Sample3.Class1") let func = clazz.GetMethods() |> Seq.find (fun x -> x.Name = "get_Property") @@ -1707,7 +1700,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), sample1) let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let program = def.MainModule.GetType("TouchTest.Program") let main = program.GetMethods() |> Seq.find (fun x -> x.Name = "Main") @@ -1739,7 +1732,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let module' = def.MainModule.GetType("N.DU") let du = module'.NestedTypes |> Seq.filter (fun t -> t.Name = "MyUnion") |> Seq.head @@ -1760,7 +1753,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let module' = def.MainModule.GetType("N.DU") let du = module'.NestedTypes |> Seq.filter (fun t -> t.Name = "MyUnion") |> Seq.head @@ -1790,7 +1783,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let module' = def.MainModule.GetType("N.DU") let du = module'.NestedTypes |> Seq.filter (fun t -> t.Name = "MyUnion") |> Seq.head @@ -1816,7 +1809,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let module' = def.MainModule.GetType("N.DU") let du = module'.NestedTypes |> Seq.filter (fun t -> t.Name = "MyUnion") |> Seq.head @@ -1840,7 +1833,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let module' = def.MainModule.GetType("N.DU") let du = module'.NestedTypes |> Seq.filter (fun t -> t.Name = "MyUnion") |> Seq.head @@ -1868,13 +1861,13 @@ type AltCoverTests() = class [] member self.TypeShouldNotChangeState () = let input = Instrument.Context.Build [] - let output = Instrument.InstrumentationVisitor input (Node.Type (null, None, false)) + let output = Instrument.InstrumentationVisitor input (Node.Type (null, false)) Assert.That (output, Is.SameAs input) [] member self.ExcludedMethodShouldNotChangeState () = let input = Instrument.Context.Build [] - let output = Instrument.InstrumentationVisitor input (Node.Method (null, None, false)) + let output = Instrument.InstrumentationVisitor input (Node.Method (null, false)) Assert.That (output, Is.SameAs input) [] @@ -1882,13 +1875,13 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let module' = def.MainModule.GetType("N.DU") let du = module'.NestedTypes |> Seq.filter (fun t -> t.Name = "MyUnion") |> Seq.head let func = du.GetMethods() |> Seq.find (fun x -> x.Name = "as_bar") let input = Instrument.Context.Build [] - let output = Instrument.InstrumentationVisitor input (Node.Method (func, None, true)) + let output = Instrument.InstrumentationVisitor input (Node.Method (func, true)) Assert.That (output.MethodBody, Is.SameAs func.Body) [] @@ -1896,7 +1889,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let module' = def.MainModule.GetType("N.DU") let du = module'.NestedTypes |> Seq.filter (fun t -> t.Name = "MyUnion") |> Seq.head @@ -1923,7 +1916,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let module' = def.MainModule.GetType("N.DU") let du = module'.NestedTypes |> Seq.filter (fun t -> t.Name = "MyUnion") |> Seq.head @@ -1948,7 +1941,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let token0 = def.Name.PublicKeyToken #if NETCOREAPP2_0 @@ -1980,7 +1973,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let token0 = def.Name.PublicKeyToken Visitor.defaultStrongNameKey <- None @@ -2008,7 +2001,7 @@ type AltCoverTests() = class let path' = path #endif let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path' - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def #if NETCOREAPP2_0 use stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(infrastructureSnk) @@ -2028,7 +2021,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let refs = def.MainModule.AssemblyReferences |> Seq.toList #if NETCOREAPP2_0 @@ -2041,7 +2034,7 @@ type AltCoverTests() = class Visitor.defaultStrongNameKey <- Some (StrongNameKeyPair(buffer.ToArray())) let fake = Mono.Cecil.AssemblyDefinition.ReadAssembly (Assembly.GetExecutingAssembly().Location) let state = Instrument.Context.Build ["nunit.framework"; "nonesuch"] - let visited = Node.Assembly (def, None, false) + let visited = Node.Assembly (def, false) let result = Instrument.InstrumentationVisitor {state with RecordingAssembly = fake } visited Assert.That (def.MainModule.AssemblyReferences, Is.EquivalentTo refs) @@ -2051,7 +2044,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let refs = def.MainModule.AssemblyReferences |> Seq.toList #if NETCOREAPP2_0 @@ -2064,7 +2057,7 @@ type AltCoverTests() = class Visitor.defaultStrongNameKey <- Some (StrongNameKeyPair(buffer.ToArray())) let fake = Mono.Cecil.AssemblyDefinition.ReadAssembly (Assembly.GetExecutingAssembly().Location) let state = Instrument.Context.Build ["nunit.framework"; "nonesuch"] - let visited = Node.Assembly (def, None, true) + let visited = Node.Assembly (def, true) let result = Instrument.InstrumentationVisitor {state with RecordingAssembly = fake } visited Assert.That (def.MainModule.AssemblyReferences, Is.EquivalentTo (refs @ [fake.Name])) @@ -2074,8 +2067,8 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore - let visited = Node.Module (def.MainModule, None, false) + ProgramDatabase.ReadSymbols def + let visited = Node.Module (def.MainModule, false) let state = Instrument.Context.Build ["nunit.framework"; "nonesuch"] let result = Instrument.InstrumentationVisitor state visited Assert.That (result, Is.EqualTo { state with ModuleId = def.MainModule.Mvid.ToString() }) @@ -2085,8 +2078,8 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore - let visited = Node.Module (def.MainModule, None, true) + ProgramDatabase.ReadSymbols def + let visited = Node.Module (def.MainModule, true) let state = Instrument.Context.Build ["nunit.framework"; "nonesuch"] let path' = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), @@ -2113,7 +2106,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let visited = Node.MethodPoint (null, None, 0, false) let state = Instrument.Context.Build [] let result = Instrument.InstrumentationVisitor state visited @@ -2126,12 +2119,12 @@ type AltCoverTests() = class if File.Exists(pdb) then // skip when we don't have symbols on travis let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - let reader = ProgramDatabase.ReadSymbols def + ProgramDatabase.ReadSymbols def let module' = def.MainModule.GetType("N.DU") let du = module'.NestedTypes |> Seq.filter (fun t -> t.Name = "MyUnion") |> Seq.head let main = du.GetMethods() |> Seq.find (fun x -> x.Name = "as_bar") let proc = main.Body.GetILProcessor() - let dbg = (Option.get reader).Read main + let dbg = main.DebugInformation let target = main.Body.Instructions |> Seq.filter (dbg.GetSequencePoint >> isNull >> not) |> Seq.head @@ -2149,8 +2142,8 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore - let visited = Node.Module (def.MainModule, None, true) + ProgramDatabase.ReadSymbols def + let visited = Node.Module (def.MainModule, true) let state = Instrument.Context.Build ["nunit.framework"; "nonesuch"] let path' = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), @@ -2188,7 +2181,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let unique = Guid.NewGuid().ToString() let output = Path.Combine(Path.GetDirectoryName(where), unique) @@ -2216,7 +2209,7 @@ type AltCoverTests() = class let where = Assembly.GetExecutingAssembly().Location let path = Path.Combine(Path.GetDirectoryName(where) + AltCoverTests.Hack(), "Sample2.dll") let def = Mono.Cecil.AssemblyDefinition.ReadAssembly path - ProgramDatabase.ReadSymbols def |> ignore + ProgramDatabase.ReadSymbols def let unique = Guid.NewGuid().ToString() let output = Path.Combine(Path.GetDirectoryName(where), unique) From f5ebe85a8a380c412af9035d9b8ff8b07f862600 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Thu, 15 Mar 2018 16:21:22 +0000 Subject: [PATCH 06/67] Make the symbol test once and for all --- AltCover/Visitor.fs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/AltCover/Visitor.fs b/AltCover/Visitor.fs index a3a1df896..71d11902a 100644 --- a/AltCover/Visitor.fs +++ b/AltCover/Visitor.fs @@ -166,13 +166,13 @@ module Visitor = let private VisitMethod (m:MethodDefinition) included = let rawInstructions = m.Body.Instructions let dbg = m.DebugInformation - let instructions = rawInstructions - |> Seq.cast - |> Seq.filter (fun (x:Instruction) -> dbg |> isNull |> not) + let instructions = [rawInstructions |> Seq.cast] + |> Seq.filter (fun _ -> dbg |> isNull |> not) + |> Seq.concat |> Seq.filter (fun (x:Instruction) -> if dbg.HasSequencePoints then let s = dbg.GetSequencePoint x (not << isNull) s && s.StartLine <> 0xfeefee - else false) + else false) |> Seq.toList let number = instructions.Length From f6848abf74f78bf4034bba94ba78278e71e6e4b7 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Thu, 15 Mar 2018 16:53:31 +0000 Subject: [PATCH 07/67] NUnit version bump --- Sample2/Sample2.fsproj | 3 ++- Sample2/packages.config | 2 +- Shadow.Tests/Shadow.Tests.fsproj | 5 ++--- Shadow.Tests/packages.config | 2 +- Shadow.Tests2/Shadow.Tests2.fsproj | 7 +++---- Shadow.Tests2/packages.config | 2 +- Tests/Tests.fsproj | 3 ++- Tests/packages.config | 2 +- WeakNameTests/WeakNameTests.fsproj | 4 +++- WeakNameTests/packages.config | 4 ++++ 10 files changed, 20 insertions(+), 14 deletions(-) create mode 100644 WeakNameTests/packages.config diff --git a/Sample2/Sample2.fsproj b/Sample2/Sample2.fsproj index fa66b68c8..ed9f66431 100644 --- a/Sample2/Sample2.fsproj +++ b/Sample2/Sample2.fsproj @@ -1,5 +1,6 @@ + Debug @@ -64,7 +65,7 @@ ..\packages\FSharp.Core.4.3.4\lib\net45\FSharp.Core.dll - ..\packages\NUnit.3.9.0\lib\net45\nunit.framework.dll + ..\packages\NUnit.3.10.1\lib\net45\nunit.framework.dll diff --git a/Sample2/packages.config b/Sample2/packages.config index b93fa214c..ebeb58fba 100644 --- a/Sample2/packages.config +++ b/Sample2/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/Shadow.Tests/Shadow.Tests.fsproj b/Shadow.Tests/Shadow.Tests.fsproj index 30e9e1b17..0e9b01083 100644 --- a/Shadow.Tests/Shadow.Tests.fsproj +++ b/Shadow.Tests/Shadow.Tests.fsproj @@ -1,5 +1,6 @@ + Debug @@ -78,15 +79,13 @@ - ..\packages\NUnit.3.9.0\lib\net45\nunit.framework.dll + ..\packages\NUnit.3.10.1\lib\net45\nunit.framework.dll - - AltCover.Shadow {62480be3-4479-4a47-a23f-50858ecd74b3} diff --git a/Shadow.Tests/packages.config b/Shadow.Tests/packages.config index b93fa214c..36927ff05 100644 --- a/Shadow.Tests/packages.config +++ b/Shadow.Tests/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/Shadow.Tests2/Shadow.Tests2.fsproj b/Shadow.Tests2/Shadow.Tests2.fsproj index b11a49b50..764f7c80e 100644 --- a/Shadow.Tests2/Shadow.Tests2.fsproj +++ b/Shadow.Tests2/Shadow.Tests2.fsproj @@ -1,5 +1,6 @@ + Debug @@ -86,15 +87,13 @@ - ..\packages\NUnit.3.9.0\lib\net20\nunit.framework.dll + ..\packages\NUnit.3.10.1\lib\net20\nunit.framework.dll - ..\packages\NUnit.3.9.0\lib\net20\NUnit.System.Linq.dll + ..\packages\NUnit.3.10.1\lib\net20\NUnit.System.Linq.dll - - AltCover.Shadow {62480be3-4479-4a47-a23f-50858ecd74b3} diff --git a/Shadow.Tests2/packages.config b/Shadow.Tests2/packages.config index 80f1e20f8..124fd1df5 100644 --- a/Shadow.Tests2/packages.config +++ b/Shadow.Tests2/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/Tests/Tests.fsproj b/Tests/Tests.fsproj index eaf054759..a26f68e78 100644 --- a/Tests/Tests.fsproj +++ b/Tests/Tests.fsproj @@ -1,5 +1,6 @@ + Debug @@ -108,7 +109,7 @@ ..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll - ..\packages\NUnit.3.9.0\lib\net45\nunit.framework.dll + ..\packages\NUnit.3.10.1\lib\net45\nunit.framework.dll diff --git a/Tests/packages.config b/Tests/packages.config index 34640764d..69836597f 100644 --- a/Tests/packages.config +++ b/Tests/packages.config @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/WeakNameTests/WeakNameTests.fsproj b/WeakNameTests/WeakNameTests.fsproj index fbbf9fe7d..f3ece7bbe 100644 --- a/WeakNameTests/WeakNameTests.fsproj +++ b/WeakNameTests/WeakNameTests.fsproj @@ -1,5 +1,6 @@  + Debug @@ -77,6 +78,7 @@ Gendarme.fs + @@ -105,7 +107,7 @@ ..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll - ..\packages\NUnit.3.9.0\lib\net45\nunit.framework.dll + ..\packages\NUnit.3.10.1\lib\net45\nunit.framework.dll diff --git a/WeakNameTests/packages.config b/WeakNameTests/packages.config new file mode 100644 index 000000000..36927ff05 --- /dev/null +++ b/WeakNameTests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From 23cfbdb6d3b1c386cfd81ecbdf5644509b3e1536 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Thu, 15 Mar 2018 17:31:41 +0000 Subject: [PATCH 08/67] This was needed now, for some reason --- Build/targets.fsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Build/targets.fsx b/Build/targets.fsx index 4b21ec23e..46bc720e7 100644 --- a/Build/targets.fsx +++ b/Build/targets.fsx @@ -664,7 +664,7 @@ Target "FSharpTypes" ( fun _ -> { info with FileName = binRoot @@ "AltCover.exe" WorkingDirectory = sampleRoot - Arguments = ("-t=System\. -t=Microsoft\. -x=" + simpleReport + " /o=./" + instrumented)}) + Arguments = ("-s=nunit -t=System\. -t=Microsoft\. -x=" + simpleReport + " /o=./" + instrumented)}) "FSharpTypes" Actions.ValidateFSharpTypes simpleReport [] else From acf733015668c1547ddb08a436f3988d98893488 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Thu, 15 Mar 2018 20:40:05 +0000 Subject: [PATCH 09/67] Refactor duplicated code --- AltCover/Report.fs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/AltCover/Report.fs b/AltCover/Report.fs index abb205664..94ab54c8f 100644 --- a/AltCover/Report.fs +++ b/AltCover/Report.fs @@ -19,6 +19,9 @@ module Report = let X name = XName.Get(name) + let ToExcluded included = + if included then "false" else "true" + let StartVisit (s : list) = let element = XElement(X "coverage", XAttribute(X "profilerVersion", "AltCover " + @@ -35,7 +38,7 @@ module Report = XAttribute(X "name", moduleDef.Name), XAttribute(X "assembly", moduleDef.Assembly.Name.Name), XAttribute(X "assemblyIdentity", moduleDef.Assembly.Name.FullName), - XAttribute(X "excluded", if included then "false" else "true")) + XAttribute(X "excluded", ToExcluded included)) head.Add(element) element :: s @@ -45,7 +48,7 @@ module Report = //// Mono.Cecil emits names in the form outer/inner rather than outer+inner XAttribute(X "class", Naming.FullTypeName methodDef.DeclaringType), XAttribute(X "metadataToken", methodDef.MetadataToken.ToUInt32().ToString()), - XAttribute(X "excluded", if included then "false" else "true"), + XAttribute(X "excluded", ToExcluded included), XAttribute(X "instrumented", if included then "true" else "false"), XAttribute(X "fullname", Naming.FullMethodName methodDef) ) @@ -66,7 +69,7 @@ module Report = XAttribute(X "column", codeSegment.StartColumn), XAttribute(X "endline", fst end'), XAttribute(X "endcolumn", snd end'), - XAttribute(X "excluded", if included then "false" else "true"), + XAttribute(X "excluded", ToExcluded included), XAttribute(X "document", codeSegment.Document.Url)) if head.IsEmpty then head.Add(element) else head.FirstNode.AddBeforeSelf(element) From 2eff5cc28a8df49b1a6b9dfa9337debae7a64138 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Fri, 16 Mar 2018 10:43:20 +0000 Subject: [PATCH 10/67] Initial sketch of least-possible-cost extension of the stored payload. -- only negative tests so far. --- AltCover.Recorder/Base.fs | 17 ++++--- AltCover.Recorder/Recorder.fs | 30 +++++------ AltCover.Recorder/Tracer.fs | 16 +++--- AltCover/Runner.fs | 29 ++++++----- Shadow.Tests/Shadow.Tests.fs | 94 ++++++++++++++++------------------- Shadow.Tests/Tracer.fs | 11 ++-- Tests/Runner.Tests.fs | 54 ++++++++++---------- 7 files changed, 126 insertions(+), 125 deletions(-) diff --git a/AltCover.Recorder/Base.fs b/AltCover.Recorder/Base.fs index f18ef587c..2cadc7ca8 100644 --- a/AltCover.Recorder/Base.fs +++ b/AltCover.Recorder/Base.fs @@ -56,7 +56,7 @@ module Counter = /// /// The coverage results to incorporate /// The coverage file to update as a stream - let internal UpdateReport (postProcess:XmlDocument -> unit) own (counts:Dictionary>) format coverageFile = + let internal UpdateReport (postProcess:XmlDocument -> unit) own (counts:Dictionary>) format coverageFile = let flushStart = DateTime.UtcNow let coverageDocument = ReadXDocument coverageFile let root = coverageDocument.DocumentElement @@ -98,7 +98,7 @@ module Counter = |> Seq.cast |> Seq.toList |> List.rev) |> Seq.mapi (fun counter pt -> ((match format with - | ReportFormat.OpenCover -> "uspid" |> pt.GetAttribute |> FindIndexFromUspid + | ReportFormat.OpenCover -> "uspid" |> pt.GetAttribute |> FindIndexFromUspid | _ -> counter), pt)) |> Seq.filter (fst >> moduleHits.ContainsKey) @@ -109,7 +109,7 @@ module Counter = System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture) |> snd // Treat -ve visit counts (an exemption added in analysis) as zero - let visits = moduleHits.[counter] + (max 0 vc) + let visits = (fst moduleHits.[counter]) + (max 0 vc) pt.SetAttribute(v, visits.ToString(CultureInfo.InvariantCulture)))) postProcess coverageDocument @@ -125,9 +125,10 @@ module Counter = let flushStart = UpdateReport postProcess own counts format coverageFile TimeSpan(DateTime.UtcNow.Ticks - flushStart.Ticks) - let AddVisit (counts:Dictionary>) moduleId hitPointId = - if not (counts.ContainsKey moduleId) then counts.[moduleId] <- Dictionary() + let AddVisit (counts:Dictionary>) moduleId hitPointId context = + if not (counts.ContainsKey moduleId) then counts.[moduleId] <- Dictionary() if not (counts.[moduleId].ContainsKey hitPointId) then - counts.[moduleId].Add(hitPointId, 1) - else - counts.[moduleId].[hitPointId] <- 1 + counts.[moduleId].[hitPointId] \ No newline at end of file + counts.[moduleId].Add(hitPointId, (0,[])) + counts.[moduleId].[hitPointId] <- match context with + | (None, None) -> (1 + fst counts.[moduleId].[hitPointId], snd counts.[moduleId].[hitPointId]) + | something -> (1 + fst counts.[moduleId].[hitPointId], something :: snd counts.[moduleId].[hitPointId]) \ No newline at end of file diff --git a/AltCover.Recorder/Recorder.fs b/AltCover.Recorder/Recorder.fs index d02a29ffc..b2204968d 100644 --- a/AltCover.Recorder/Recorder.fs +++ b/AltCover.Recorder/Recorder.fs @@ -16,7 +16,7 @@ type internal Close = [] type internal Carrier = - | SequencePoint of String*int + | SequencePoint of String*int*(int64 option * int option) [] type internal Message = @@ -52,7 +52,7 @@ module Instance = /// /// Accumulation of visit records /// - let internal Visits = new Dictionary>(); + let internal Visits = new Dictionary>(); /// /// Gets the unique token for this instance @@ -93,7 +93,7 @@ module Instance = (fun () -> match Visits.Count with | 0 -> () - | _ -> let counts = Dictionary> Visits + | _ -> let counts = Dictionary> Visits Visits.Clear() WithMutex (fun own -> let delta = Counter.DoFlush ignore own counts CoverageFormat ReportFile @@ -101,18 +101,18 @@ module Instance = |> Option.iter (fun s -> Console.Out.WriteLine(s, delta.TotalSeconds)) )) - let internal TraceVisit moduleId hitPointId = - trace.OnVisit Visits moduleId hitPointId + let internal TraceVisit moduleId hitPointId context = + trace.OnVisit Visits moduleId hitPointId context /// /// This method is executed from instrumented assemblies. /// /// Assembly being visited /// Sequence Point identifier - let internal VisitImpl moduleId hitPointId = + let internal VisitImpl moduleId hitPointId context = if not <| String.IsNullOrEmpty(moduleId) then - trace.OnConnected (fun () -> TraceVisit moduleId hitPointId) - (fun () -> Counter.AddVisit Visits moduleId hitPointId) + trace.OnConnected (fun () -> TraceVisit moduleId hitPointId context) + (fun () -> Counter.AddVisit Visits moduleId hitPointId (None, None)) let rec private loop (inbox:MailboxProcessor) = async { @@ -122,11 +122,11 @@ module Instance = | None -> return! loop inbox | Some msg -> match msg with - | AsyncItem (SequencePoint (moduleId, hitPointId)) -> - VisitImpl moduleId hitPointId + | AsyncItem (SequencePoint (moduleId, hitPointId, context)) -> + VisitImpl moduleId hitPointId context return! loop inbox - | Item (SequencePoint (moduleId, hitPointId), channel)-> - VisitImpl moduleId hitPointId + | Item (SequencePoint (moduleId, hitPointId, context), channel)-> + VisitImpl moduleId hitPointId context channel.Reply () return! loop inbox | Finish (mode, channel) -> @@ -142,20 +142,20 @@ module Instance = let internal Backlog () = mailbox.CurrentQueueLength - let internal VisitSelection (f: unit -> bool) moduleId hitPointId = + let internal VisitSelection (f: unit -> bool) moduleId hitPointId context = // When writing to file for the runner to process, // make this semi-synchronous to avoid choking the mailbox // Backlogs of over 90,000 items were observed in self-test // which failed to drain during the ProcessExit grace period // when sending only async messages. - let message = SequencePoint (moduleId, hitPointId) + let message = SequencePoint (moduleId, hitPointId, context) if f() then mailbox.TryPostAndReply ((fun c -> Item (message, c)), 10) |> ignore else message |> AsyncItem |> mailbox.Post let Visit moduleId hitPointId = VisitSelection (fun () -> trace.IsConnected() || Backlog() > 10) - moduleId hitPointId + moduleId hitPointId (None, None) let internal FlushCounter (finish:Close) _ = mailbox.PostAndReply (fun c -> Finish (finish, c)) diff --git a/AltCover.Recorder/Tracer.fs b/AltCover.Recorder/Tracer.fs index e01719483..d9a89203f 100644 --- a/AltCover.Recorder/Tracer.fs +++ b/AltCover.Recorder/Tracer.fs @@ -41,16 +41,16 @@ type Tracer = { member this.Close() = this.Stream.Dispose() - member this.Push (moduleId:string) hitPointId = + member this.Push (moduleId:string) hitPointId context = let stream = this.Stream - this.Formatter.Serialize(stream, (moduleId, hitPointId)) + this.Formatter.Serialize(stream, (moduleId, hitPointId, context)) - member this.CatchUp (visits:Dictionary>) = + member this.CatchUp (visits:Dictionary>) = visits.Keys |> Seq.iter (fun moduleId -> visits.[moduleId].Keys - |> Seq.iter (fun hitPointId -> for i = 1 to visits.[moduleId].[hitPointId] do - this.Push moduleId hitPointId)) + |> Seq.iter (fun hitPointId -> for i = 1 to fst visits.[moduleId].[hitPointId] do + this.Push moduleId hitPointId (None, None))) visits.Clear() member this.OnStart () = @@ -64,10 +64,10 @@ type Tracer = { member this.OnFinish visits = this.CatchUp visits - this.Push null -1 + this.Push null -1 (None, None) this.Stream.Flush() this.Close() - member this.OnVisit visits moduleId hitPointId = + member this.OnVisit visits moduleId hitPointId context = this.CatchUp visits - this.Push moduleId hitPointId \ No newline at end of file + this.Push moduleId hitPointId context \ No newline at end of file diff --git a/AltCover/Runner.fs b/AltCover/Runner.fs index f997b9197..25f872b2d 100644 --- a/AltCover/Runner.fs +++ b/AltCover/Runner.fs @@ -154,28 +154,31 @@ module Runner = |> Seq.collect (fun p -> p.Attributes |> Seq.cast) |> Seq.iter (fun a -> m.SetAttribute(a.Name, a.Value))) - let internal LookUpVisitsByToken token (dict:Dictionary) = - let (ok, index) = Int32.TryParse( token, + let internal LookUpVisitsByToken token (dict:Dictionary) = + let (ok, index) = Int32.TryParse(token, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture) - dict.TryGetValue(if ok then index else -1) + match dict.TryGetValue(if ok then index else -1) with + | (false, _) -> (0, []) + | (_, pair) -> pair - let internal FillMethodPoint (mp:XmlElement seq) (``method``:XmlElement) (dict:Dictionary) = + let internal FillMethodPoint (mp:XmlElement seq) (``method``:XmlElement) (dict:Dictionary) = let token = ``method``.GetElementsByTagName("MetadataToken") |> Seq.cast |> Seq.map(fun m -> m.InnerText) |> Seq.head - let (_, vc) = LookUpVisitsByToken token dict + let (vc, _) = LookUpVisitsByToken token dict + mp |> Seq.iter (fun m -> m.SetAttribute("vc", vc.ToString(System.Globalization.CultureInfo.InvariantCulture)) m.SetAttribute("uspid", token) m.SetAttribute("ordinal", "0") m.SetAttribute("offset", "0")) - let internal PostProcess (counts:Dictionary>) format (document:XmlDocument) = + let internal PostProcess (counts:Dictionary>) format (document:XmlDocument) = match format with | Base.ReportFormat.OpenCover -> - let updateMethod (dict:Dictionary) (vs, vm, pt) (``method``:XmlElement) = + let updateMethod (dict:Dictionary) (vs, vm, pt) (``method``:XmlElement) = let sp = ``method``.GetElementsByTagName("SequencePoint") let count = sp.Count let mp = ``method``.GetElementsByTagName("MethodPoint") @@ -204,7 +207,7 @@ module Runner = (vs + visitPoints, vm + 1, pt + count) else (vs, vm, pt + count) - let updateClass (dict:Dictionary) (vs, vm, vc, pt) (``class``:XmlElement) = + let updateClass (dict:Dictionary) (vs, vm, vc, pt) (``class``:XmlElement) = let (cvs, cvm, cpt) = ``class``.GetElementsByTagName("Method") |> Seq.cast |> Seq.fold (updateMethod dict) (0,0,0) @@ -219,13 +222,13 @@ module Runner = csum.SetAttribute("sequenceCoverage", cover) (vs + cvs, vm + cvm, vc + cvc, pt + cpt) - let updateModule (counts:Dictionary>) (vs, vm, vc, pt) (``module``:XmlElement) = + let updateModule (counts:Dictionary>) (vs, vm, vc, pt) (``module``:XmlElement) = let dict = match counts.TryGetValue <| ``module``.GetAttribute("hash") with - | (false, _) -> Dictionary() + | (false, _) -> Dictionary() | (true, d) -> d let (cvs, cvm, cvc, cpt) = ``module``.GetElementsByTagName("Class") |> Seq.cast - |> Seq.fold (updateClass dict) (0,0,0,0) + |> Seq.fold (dict |> updateClass) (0,0,0,0) let cover = if cpt = 0 then "0" else (sprintf "%.2f" ((float (cvs * 100))/(float cpt))).TrimEnd([| '0' |]).TrimEnd([|'.'|]) ``module``.GetElementsByTagName("Summary") @@ -251,9 +254,9 @@ module Runner = | _ -> () let WriteReportBase (hits:ICollection<(string*int)>) report = - let counts = Dictionary>() + let counts = Dictionary>() hits |> Seq.iter(fun (moduleId, hitPointId) -> - AltCover.Base.Counter.AddVisit counts moduleId hitPointId) + AltCover.Base.Counter.AddVisit counts moduleId hitPointId (None,None)) AltCover.Base.Counter.DoFlush (PostProcess counts report) true counts report // mocking points diff --git a/Shadow.Tests/Shadow.Tests.fs b/Shadow.Tests/Shadow.Tests.fs index 69c6594cf..e2e1b6597 100644 --- a/Shadow.Tests/Shadow.Tests.fs +++ b/Shadow.Tests/Shadow.Tests.fs @@ -43,6 +43,18 @@ type AltCoverTests() = class // printfn "%s %s" tag //#endif + member self.resource = Assembly.GetExecutingAssembly().GetManifestResourceNames() + |> Seq.find (fun n -> n.EndsWith("SimpleCoverage.xml", StringComparison.Ordinal)) + + member private self.UpdateReport a b = + Counter.UpdateReport ignore true a ReportFormat.NCover b + |> ignore + + member self.resource2 = Assembly.GetExecutingAssembly().GetManifestResourceNames() + |> Seq.find (fun n -> n.EndsWith("Sample1WithModifiedOpenCover.xml", StringComparison.Ordinal)) +#if NET4 + // passing F# types across the CLR divide doesn't work +#else [] member self.ShouldBeLinkingTheCorrectCopyOfThisCode() = self.GetMyMethodName "=>" @@ -60,7 +72,7 @@ type AltCoverTests() = class lock Instance.Visits (fun () -> try Instance.Visits.Clear() - Instance.VisitImpl null 23 + Instance.VisitImpl null 23 (None,None) Assert.That (Instance.Visits, Is.Empty) finally Instance.Visits.Clear()) @@ -72,7 +84,7 @@ type AltCoverTests() = class lock Instance.Visits (fun () -> try Instance.Visits.Clear() - Instance.VisitImpl String.Empty 23 + Instance.VisitImpl String.Empty 23 (None,None) Assert.That (Instance.Visits, Is.Empty) finally Instance.Visits.Clear()) @@ -97,15 +109,12 @@ type AltCoverTests() = class Thread.Sleep 100 Assert.That (Instance.Visits.Count, Is.EqualTo 1) Assert.That (Instance.Visits.[key].Count, Is.EqualTo 1) - Assert.That (Instance.Visits.[key].[23], Is.EqualTo 1) + Assert.That (Instance.Visits.[key].[23], Is.EqualTo (1,[])) finally Instance.Visits.Clear() Instance.trace <- save) self.GetMyMethodName "<=" -#if NET4 - // passing lambdas across the CLR divide doesn't work -#else [] member self.RealIdShouldIncrementCountSynchronously() = self.GetMyMethodName "=>" @@ -115,16 +124,15 @@ type AltCoverTests() = class Instance.Visits.Clear() Instance.trace <- { Tracer=null; Stream=null; Formatter=null } let key = " " - Instance.VisitSelection (fun () -> true) key 23 + Instance.VisitSelection (fun () -> true) key 23 (None,None) Thread.Sleep 100 Assert.That (Instance.Visits.Count, Is.EqualTo 1, "A visit happened") Assert.That (Instance.Visits.[key].Count, Is.EqualTo 1, "keys = " + String.Join("; ", Instance.Visits.Keys|> Seq.toArray)) - Assert.That (Instance.Visits.[key].[23], Is.EqualTo 1) + Assert.That (Instance.Visits.[key].[23], Is.EqualTo (1, [])) finally Instance.Visits.Clear() Instance.trace <- save) self.GetMyMethodName "<=" -#endif [] member self.DistinctIdShouldBeDistinct() = @@ -133,8 +141,8 @@ type AltCoverTests() = class try Instance.Visits.Clear() let key = " " - Instance.VisitImpl key 23 - Instance.VisitImpl "key" 42 + Instance.VisitImpl key 23 (None,None) + Instance.VisitImpl "key" 42 (None,None) Assert.That (Instance.Visits.Count, Is.EqualTo 2) finally Instance.Visits.Clear()) @@ -147,8 +155,8 @@ type AltCoverTests() = class try Instance.Visits.Clear() let key = " " - Instance.VisitImpl key 23 - Instance.VisitImpl key 42 + Instance.VisitImpl key 23 (None,None) + Instance.VisitImpl key 42 (None,None) Assert.That (Instance.Visits.Count, Is.EqualTo 1) Assert.That (Instance.Visits.[key].Count, Is.EqualTo 2) finally @@ -162,25 +170,13 @@ type AltCoverTests() = class try Instance.Visits.Clear() let key = " " - Instance.VisitImpl key 23 - Instance.VisitImpl key 23 - Assert.That (Instance.Visits.[key].[23], Is.EqualTo 2) + Instance.VisitImpl key 23 (None,None) + Instance.VisitImpl key 23 (None,None) + Assert.That (Instance.Visits.[key].[23], Is.EqualTo (2, [])) finally Instance.Visits.Clear()) self.GetMyMethodName "<=" - member self.resource = Assembly.GetExecutingAssembly().GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("SimpleCoverage.xml", StringComparison.Ordinal)) - -#if NET4 -#else - member private self.UpdateReport a b = - Counter.UpdateReport ignore true a ReportFormat.NCover b - |> ignore - - member self.resource2 = Assembly.GetExecutingAssembly().GetManifestResourceNames() - |> Seq.find (fun n -> n.EndsWith("Sample1WithModifiedOpenCover.xml", StringComparison.Ordinal)) - [] member self.OldDocumentStartIsNotUpdated() = self.GetMyMethodName "=>" @@ -196,7 +192,7 @@ type AltCoverTests() = class worker.Position <- 0L let before = XmlDocument() before.Load (Assembly.GetExecutingAssembly().GetManifestResourceStream(self.resource)) - self.UpdateReport (Dictionary>()) worker + self.UpdateReport (Dictionary>()) worker worker.Position <- 0L let after = XmlDocument() after.Load worker @@ -221,7 +217,7 @@ type AltCoverTests() = class worker.Position <- 0L let before = XmlDocument() before.Load (Assembly.GetExecutingAssembly().GetManifestResourceStream(self.resource)) - self.UpdateReport (Dictionary>()) worker + self.UpdateReport (Dictionary>()) worker worker.Position <- 0L let after = XmlDocument() after.Load worker @@ -246,7 +242,7 @@ type AltCoverTests() = class worker.Position <- 0L let before = XmlDocument() before.Load (Assembly.GetExecutingAssembly().GetManifestResourceStream(self.resource)) - self.UpdateReport (Dictionary>()) worker + self.UpdateReport (Dictionary>()) worker worker.Position <- 0L let after = XmlDocument() after.Load worker @@ -271,7 +267,7 @@ type AltCoverTests() = class worker.Position <- 0L let before = XmlDocument() before.Load (Assembly.GetExecutingAssembly().GetManifestResourceStream(self.resource)) - self.UpdateReport (Dictionary>()) worker + self.UpdateReport (Dictionary>()) worker worker.Position <- 0L let after = XmlDocument() after.Load worker @@ -294,7 +290,7 @@ type AltCoverTests() = class worker.Write (buffer, 0, size) worker.Position <- 0L use before = new StreamReader (Assembly.GetExecutingAssembly().GetManifestResourceStream(self.resource)) - let item = Dictionary>() + let item = Dictionary>() item.Add ("not a guid", null) self.UpdateReport item worker worker.Position <- 0L @@ -320,8 +316,8 @@ type AltCoverTests() = class worker.Write (buffer, 0, size) worker.Position <- 0L use before = new StreamReader (Assembly.GetExecutingAssembly().GetManifestResourceStream(self.resource)) - let item = Dictionary>() - item.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", Dictionary()) + let item = Dictionary>() + item.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", Dictionary()) self.UpdateReport item worker worker.Position <- 0L let after = new StreamReader(worker) @@ -346,10 +342,10 @@ type AltCoverTests() = class worker.Write (buffer, 0, size) worker.Position <- 0L use before = new StreamReader (Assembly.GetExecutingAssembly().GetManifestResourceStream(self.resource)) - let payload = Dictionary() - payload.[-1] <- 10 - payload.[100] <- 10 - let item = Dictionary>() + let payload = Dictionary() + payload.[-1] <- (10, []) + payload.[100] <- (10, []) + let item = Dictionary>() item.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", payload) self.UpdateReport item worker worker.Position <- 0L @@ -374,10 +370,10 @@ type AltCoverTests() = class use worker = new MemoryStream() worker.Write (buffer, 0, size) worker.Position <- 0L - let payload = Dictionary() + let payload = Dictionary() [0..9 ] - |> Seq.iter(fun i -> payload.[i] <- (i+1)) - let item = Dictionary>() + |> Seq.iter(fun i -> payload.[i] <- (i+1, [])) + let item = Dictionary>() item.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", payload) self.UpdateReport item worker worker.Position <- 0L @@ -401,10 +397,10 @@ type AltCoverTests() = class use worker = new MemoryStream() worker.Write (buffer, 0, size) worker.Position <- 0L - let payload = Dictionary() + let payload = Dictionary() [0..9 ] - |> Seq.iter(fun i -> payload.[10 - i] <- (i+1)) - let item = Dictionary>() + |> Seq.iter(fun i -> payload.[10 - i] <- (i+1,[])) + 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) Counter.UpdateReport ignore true item ReportFormat.OpenCover worker |> ignore worker.Position <- 0L @@ -415,7 +411,7 @@ type AltCoverTests() = class |> Seq.map (fun x -> x.GetAttribute("vc")), Is.EquivalentTo [ "11"; "10"; "9"; "8"; "7"; "6"; "4"; "3"; "2"; "1"])) self.GetMyMethodName "<=" -#endif + [] member self.EmptyFlushLeavesNoTrace() = @@ -461,9 +457,9 @@ type AltCoverTests() = class worker.Write(buffer, 0, size) () - let payload = Dictionary() + let payload = Dictionary() [0..9 ] - |> Seq.iter(fun i -> payload.[i] <- (i+1)) + |> Seq.iter(fun i -> payload.[i] <- (i+1, [])) Instance.Visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload Instance.FlushCounter ProcessExit () @@ -500,8 +496,6 @@ type AltCoverTests() = class self.GetMyMethodName "<=" -#if NET2 -#else // Dead simple sequential operation // run only once in Framework mode to avoid contention [] diff --git a/Shadow.Tests/Tracer.fs b/Shadow.Tests/Tracer.fs index ed685a556..89d272664 100644 --- a/Shadow.Tests/Tracer.fs +++ b/Shadow.Tests/Tracer.fs @@ -74,6 +74,9 @@ type AltCoverCoreTests() = class sink() hits +#if NET4 + // passing F# types across the CLR divide doesn't work +#else [] member self.VisitShouldSignal() = let save = Instance.trace @@ -89,13 +92,13 @@ type AltCoverCoreTests() = class let mutable client = Tracer.Create tag try Instance.Visits.Clear() - let entry = Dictionary() - entry.Add(23, 1) + let entry = Dictionary() + entry.Add(23, (1, [])) Instance.Visits.Add("name", entry) Instance.trace <- client.OnStart() Assert.That (Instance.trace.IsConnected(), "connection failed") - Instance.VisitImpl "name" 23 + Instance.VisitImpl "name" 23 (None,None) finally Instance.trace.Close() Instance.trace <- save @@ -145,7 +148,7 @@ type AltCoverCoreTests() = class finally Instance.Visits.Clear() - +#endif #if NETCOREAPP2_0 [] member self.CoreFindsThePlace() = diff --git a/Tests/Runner.Tests.fs b/Tests/Runner.Tests.fs index fdbfd0e7c..2526b18c4 100644 --- a/Tests/Runner.Tests.fs +++ b/Tests/Runner.Tests.fs @@ -27,37 +27,37 @@ type AltCoverTests() = class [] member self.RealIdShouldIncrementCount() = - let visits = new Dictionary>() + let visits = new Dictionary>() let key = " " - Counter.AddVisit visits key 23 + Counter.AddVisit visits key 23 (None,None) Assert.That (visits.Count, Is.EqualTo 1) Assert.That (visits.[key].Count, Is.EqualTo 1) - Assert.That (visits.[key].[23], Is.EqualTo 1) + Assert.That (visits.[key].[23], Is.EqualTo (1,[])) [] member self.DistinctIdShouldBeDistinct() = - let visits = new Dictionary>() + let visits = new Dictionary>() let key = " " - Counter.AddVisit visits key 23 - Counter.AddVisit visits "key" 42 + Counter.AddVisit visits key 23 (None,None) + Counter.AddVisit visits "key" 42 (None,None) Assert.That (visits.Count, Is.EqualTo 2) [] member self.DistinctLineShouldBeDistinct() = - let visits = new Dictionary>() + let visits = new Dictionary>() let key = " " - Counter.AddVisit visits key 23 - Counter.AddVisit visits key 42 + Counter.AddVisit visits key 23 (None,None) + Counter.AddVisit visits key 42 (None,None) Assert.That (visits.Count, Is.EqualTo 1) Assert.That (visits.[key].Count, Is.EqualTo 2) [] member self.RepeatVisitsShouldIncrementCount() = - let visits = new Dictionary>() + let visits = new Dictionary>() let key = " " - Counter.AddVisit visits key 23 - Counter.AddVisit visits key 23 - Assert.That (visits.[key].[23], Is.EqualTo 2) + Counter.AddVisit visits key 23 (None,None) + Counter.AddVisit visits key 23 (None,None) + Assert.That (visits.[key].[23], Is.EqualTo (2, [])) member self.resource = Assembly.GetExecutingAssembly().GetManifestResourceNames() |> Seq.find (fun n -> n.EndsWith("SimpleCoverage.xml", StringComparison.Ordinal)) @@ -74,10 +74,10 @@ type AltCoverTests() = class use worker = new MemoryStream() worker.Write (buffer, 0, size) worker.Position <- 0L - let payload = Dictionary() + let payload = Dictionary() [0..9 ] - |> Seq.iter(fun i -> payload.[10 - i] <- (i+1)) - let item = Dictionary>() + |> Seq.iter(fun i -> payload.[10 - i] <- (i+1, [])) + 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) Counter.UpdateReport ignore true item ReportFormat.OpenCover worker |> ignore worker.Position <- 0L @@ -96,7 +96,7 @@ type AltCoverTests() = class let unique = Path.Combine(where, Guid.NewGuid().ToString()) let reportFile = Path.Combine(unique, "FlushLeavesExpectedTraces.xml") try - let visits = new Dictionary>() + let visits = new Dictionary>() use stdout = new StringWriter() Console.SetOut stdout Directory.CreateDirectory(unique) |> ignore @@ -112,9 +112,9 @@ type AltCoverTests() = class worker.Write(buffer, 0, size) () - let payload = Dictionary() + let payload = Dictionary() [0..9 ] - |> Seq.iter(fun i -> payload.[i] <- (i+1)) + |> Seq.iter(fun i -> payload.[i] <- (i+1, [])) visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload Counter.DoFlush ignore true visits AltCover.Base.ReportFormat.NCover reportFile |> ignore @@ -940,7 +940,7 @@ or el.SetAttribute("sequenceCoverage", "0") ) - let empty = Dictionary>() + let empty = Dictionary>() Runner.PostProcess empty Base.ReportFormat.OpenCover after Assert.That(after.OuterXml.Replace("uspid=\"100663298", "uspid=\"13"), Is.EqualTo before, after.OuterXml) @@ -975,11 +975,11 @@ or |> Seq.toList |> List.iter(fun el -> el.RemoveAllAttributes()) - let visits = Dictionary>() - let visit = Dictionary() + let visits = Dictionary>() + let visit = Dictionary() visits.Add("6A-33-AA-93-82-ED-22-9D-F8-68-2C-39-5B-93-9F-74-01-76-00-9F", visit) - visit.Add(100663297, 1) // should fill in the expected non-zero value - visit.Add(100663298, 23) // should be ignored + visit.Add(100663297, (1,[])) // should fill in the expected non-zero value + visit.Add(100663298, (23,[])) // should be ignored Runner.PostProcess visits Base.ReportFormat.OpenCover after Assert.That(after.OuterXml.Replace("uspid=\"100663298", "uspid=\"13"), Is.EqualTo before, after.OuterXml) @@ -1017,18 +1017,18 @@ or let before = after.OuterXml.Replace("uspid=\"13", "uspid=\"100663298") - let empty = Dictionary>() + let empty = Dictionary>() Runner.PostProcess empty Base.ReportFormat.OpenCover after Assert.That(after.OuterXml, Is.EqualTo before, after.OuterXml) [] member self.JunkTokenShouldDefaultZero() = - let visits = Dictionary() + let visits = Dictionary() let key = " " let result = Runner.LookUpVisitsByToken key visits match result with - | (false, 0) -> () + | (0, []) -> () | _ -> Assert.Fail(sprintf "%A" result) end \ No newline at end of file From 22d4bf2ed824f07bc7a63706723e92b604c0abd9 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Fri, 16 Mar 2018 18:33:16 +0000 Subject: [PATCH 11/67] Refactor the tests to re-enable the new cross-CLR calls. --- AltCover.Recorder/Recorder.fs | 2 +- AltCover.sln | 5 + Build/actions.fsx | 3 + Build/targets.fsx | 6 +- Shadow.Adapter/Adapter.fs | 20 ++++ Shadow.Adapter/Shadow.Adapter.fsproj | 93 ++++++++++++++++ Shadow.Adapter/altcover.adapter.core.fsproj | 31 ++++++ Shadow.Tests/Shadow.Tests.fs | 101 +++++++++--------- Shadow.Tests/Shadow.Tests.fsproj | 5 + Shadow.Tests/Tracer.fs | 24 ++--- .../altcover.recorder.tests.core.fsproj | 1 + Shadow.Tests2/Shadow.Tests2.fsproj | 5 + altcover.core.sln | 18 ++-- 13 files changed, 240 insertions(+), 74 deletions(-) create mode 100644 Shadow.Adapter/Adapter.fs create mode 100644 Shadow.Adapter/Shadow.Adapter.fsproj create mode 100644 Shadow.Adapter/altcover.adapter.core.fsproj diff --git a/AltCover.Recorder/Recorder.fs b/AltCover.Recorder/Recorder.fs index b2204968d..155c3a1bf 100644 --- a/AltCover.Recorder/Recorder.fs +++ b/AltCover.Recorder/Recorder.fs @@ -93,7 +93,7 @@ module Instance = (fun () -> match Visits.Count with | 0 -> () - | _ -> let counts = Dictionary> Visits + | _ -> let counts = Dictionary> Visits Visits.Clear() WithMutex (fun own -> let delta = Counter.DoFlush ignore own counts CoverageFormat ReportFile diff --git a/AltCover.sln b/AltCover.sln index 155384b04..487b98b38 100644 --- a/AltCover.sln +++ b/AltCover.sln @@ -49,6 +49,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Shadow.Tests2", "Shadow.Tes EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "WeakNameTests", "WeakNameTests\WeakNameTests.fsproj", "{57B8EF6F-1EE4-473B-B5B8-7C2D8213637A}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Shadow.Adapter", "Shadow.Adapter\Shadow.Adapter.fsproj", "{24BFB835-2DAC-45D4-AFDA-F9C2F13B41DD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -92,6 +94,9 @@ Global {57B8EF6F-1EE4-473B-B5B8-7C2D8213637A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {57B8EF6F-1EE4-473B-B5B8-7C2D8213637A}.Debug|Any CPU.Build.0 = Debug|Any CPU {57B8EF6F-1EE4-473B-B5B8-7C2D8213637A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {24BFB835-2DAC-45D4-AFDA-F9C2F13B41DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {24BFB835-2DAC-45D4-AFDA-F9C2F13B41DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {24BFB835-2DAC-45D4-AFDA-F9C2F13B41DD}.Release|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Build/actions.fsx b/Build/actions.fsx index ffa1ea6b3..7b086f2f4 100644 --- a/Build/actions.fsx +++ b/Build/actions.fsx @@ -57,6 +57,7 @@ open System.Runtime.CompilerServices [] #endif #if NETSTANDARD2_0 +[] [] #else #if NETCOREAPP2_0 @@ -65,6 +66,8 @@ open System.Runtime.CompilerServices #else [] [] +[] +[] [] [] [] diff --git a/Build/targets.fsx b/Build/targets.fsx index 46bc720e7..3b2423c6a 100644 --- a/Build/targets.fsx +++ b/Build/targets.fsx @@ -25,9 +25,9 @@ let Copyright = ref String.Empty let Version = ref String.Empty let OpenCoverFilter = "+[AltCove*]* -[*]Microsoft.* -[*]System.* +[*]N.*" -let AltCoverFilter= @" -s=Mono -s=\.Recorder -s=Sample -s=nunit -e=Tests -t=System. -t=Sample3\.Class2 " -let AltCoverFilterX= @" -s=Mono -s=\.Recorder -s=Sample -s=nunit -t=System\. -t=Sample3\.Class2 " -let AltCoverFilterG= @" -s=Mono -s=\.Recorder\.g -s=Sample -s=nunit -e=Tests -t=System. -t=Sample3\.Class2 " +let AltCoverFilter= @" -s=Adapter -s=Mono -s=\.Recorder -s=Sample -s=nunit -e=Tests -t=System. -t=Sample3\.Class2 " +let AltCoverFilterX= @" -s=Adapter --s=Mono -s=\.Recorder -s=Sample -s=nunit -t=System\. -t=Sample3\.Class2 " +let AltCoverFilterG= @" -s=Adapter --s=Mono -s=\.Recorder\.g -s=Sample -s=nunit -e=Tests -t=System. -t=Sample3\.Class2 " let programFiles = environVar "ProgramFiles" let programFiles86 = environVar "ProgramFiles(x86)" diff --git a/Shadow.Adapter/Adapter.fs b/Shadow.Adapter/Adapter.fs new file mode 100644 index 000000000..2d30cf26e --- /dev/null +++ b/Shadow.Adapter/Adapter.fs @@ -0,0 +1,20 @@ +namespace AltCover.Shadow + +open System.Collections.Generic +open AltCover.Recorder + +module Adapter = + let VisitsClear () = Instance.Visits.Clear() + let VisitsAdd name line number = + if name |> Instance.Visits.ContainsKey |> not then + let entry = Dictionary() + Instance.Visits.Add(name, entry) + + Instance.Visits.[name].Add(line, (number, [])) + + let VisitsSeq() = Instance.Visits |> Seq.cast + let VisitsEntrySeq key = Instance.Visits.[key] |> Seq.cast + let VisitCount key key2 = Instance.Visits.[key].[key2] |> fst + let Lock = Instance.Visits :> obj + + let VisitImplNone moduleId hitPointId = Instance.VisitImpl moduleId hitPointId (None,None) diff --git a/Shadow.Adapter/Shadow.Adapter.fsproj b/Shadow.Adapter/Shadow.Adapter.fsproj new file mode 100644 index 000000000..77504c4d9 --- /dev/null +++ b/Shadow.Adapter/Shadow.Adapter.fsproj @@ -0,0 +1,93 @@ + + + + + Debug + AnyCPU + 2.0 + 24bfb835-2dac-45d4-afda-f9c2f13b41dd + Library + Shadow.Adapter + AltCover.Shadow.Adapter + true + v2.0 + v4.7 + NET2 + MONO + true + Shadow.Adapter + + + true + full + false + false + $(SolutionDir)_Binaries\$(AssemblyName)\$(Configuration)+$(Platform)\ + $(SolutionDir)_Intermediate\$(AssemblyName)\$(Configuration)+$(Platform)\ + true + + + --keyfile:$(SolutionDir)Build\Infrastructure.snk + TRACE;DEBUG;CODE_ANALYSIS;$(ExtraDefines) + 4 + + + pdbonly + true + true + $(SolutionDir)_Binaries\$(AssemblyName)\$(Configuration)+$(Platform)\ + $(SolutionDir)_Intermediate\$(AssemblyName)\$(Configuration)+$(Platform)\ + true + + + --keyfile:$(SolutionDir)Build\Infrastructure.snk + TRACE;$(ExtraDefines) + 4 + + + + + True + + + ..\packages\FSharp.Core.4.3.4\lib\net45\FSharp.Core.dll + + + + + + + VisibleToTest.fs + + + + + AltCover.Shadow + {62480be3-4479-4a47-a23f-50858ecd74b3} + True + + + + 11 + + + + + $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets + + + + + + \ No newline at end of file diff --git a/Shadow.Adapter/altcover.adapter.core.fsproj b/Shadow.Adapter/altcover.adapter.core.fsproj new file mode 100644 index 000000000..e58c85204 --- /dev/null +++ b/Shadow.Adapter/altcover.adapter.core.fsproj @@ -0,0 +1,31 @@ + + + + netstandard2.0 + AltCover.Shadow.Adapter + + + + $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ + $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ + TRACE;DEBUG;NETCOREAPP2_0;ALTCOVER_TEST + + + $(SolutionDir)_Binaries/$(AssemblyName)/$(Configuration)+$(Platform)/ + $(SolutionDir)_Intermediate/$(AssemblyName)/$(Configuration)+$(Platform)/ + TRACE;RELEASE;NETCOREAPP2_0;ALTCOVER_TEST + + + + + + + + + + + + + + + diff --git a/Shadow.Tests/Shadow.Tests.fs b/Shadow.Tests/Shadow.Tests.fs index e2e1b6597..93e3732aa 100644 --- a/Shadow.Tests/Shadow.Tests.fs +++ b/Shadow.Tests/Shadow.Tests.fs @@ -25,6 +25,7 @@ open System.Runtime.CompilerServices open System.Xml open AltCover.Recorder +open AltCover.Shadow open NUnit.Framework open System.Threading open System @@ -52,9 +53,8 @@ type AltCoverTests() = class member self.resource2 = Assembly.GetExecutingAssembly().GetManifestResourceNames() |> Seq.find (fun n -> n.EndsWith("Sample1WithModifiedOpenCover.xml", StringComparison.Ordinal)) -#if NET4 - // passing F# types across the CLR divide doesn't work -#else + + [] member self.ShouldBeLinkingTheCorrectCopyOfThisCode() = self.GetMyMethodName "=>" @@ -69,33 +69,33 @@ type AltCoverTests() = class [] member self.NullIdShouldNotGiveACount() = self.GetMyMethodName "=>" - lock Instance.Visits (fun () -> + lock Adapter.Lock (fun () -> try - Instance.Visits.Clear() - Instance.VisitImpl null 23 (None,None) - Assert.That (Instance.Visits, Is.Empty) + Adapter.VisitsClear() + Adapter.VisitImplNone null 23 + Assert.That (Adapter.VisitsSeq(), Is.Empty) finally - Instance.Visits.Clear()) + Adapter.VisitsClear()) self.GetMyMethodName "<=" [] member self.EmptyIdShouldNotGiveACount() = self.GetMyMethodName "=>" - lock Instance.Visits (fun () -> + lock Adapter.Lock (fun () -> try - Instance.Visits.Clear() - Instance.VisitImpl String.Empty 23 (None,None) - Assert.That (Instance.Visits, Is.Empty) + Adapter.VisitsClear() + Adapter.VisitImplNone String.Empty 23 + Assert.That (Adapter.VisitsSeq(), Is.Empty) finally - Instance.Visits.Clear()) + Adapter.VisitsClear()) self.GetMyMethodName "<=" member self.RealIdShouldIncrementCount() = self.GetMyMethodName "=>" - lock Instance.Visits (fun () -> + lock Adapter.Lock (fun () -> let save = Instance.trace try - Instance.Visits.Clear() + Adapter.VisitsClear() Instance.trace <- { Tracer=null; Stream=null; Formatter=null } let key = " " Assert.That (Instance.Backlog(), Is.EqualTo 0) @@ -107,14 +107,17 @@ type AltCoverTests() = class Assert.That(Instance.Backlog(), Is.LessThan 2) Thread.Sleep 100 - Assert.That (Instance.Visits.Count, Is.EqualTo 1) - Assert.That (Instance.Visits.[key].Count, Is.EqualTo 1) - Assert.That (Instance.Visits.[key].[23], Is.EqualTo (1,[])) + Assert.That (Adapter.VisitsSeq() |> Seq.length, Is.EqualTo 1) + Assert.That (Adapter.VisitsEntrySeq key |> Seq.length, Is.EqualTo 1) + Assert.That (Adapter.VisitCount key 23, Is.EqualTo 1) finally - Instance.Visits.Clear() + Adapter.VisitsClear() Instance.trace <- save) self.GetMyMethodName "<=" +#if NET4 + // passing lambdas across the CLR divide doesn't work +#else [] member self.RealIdShouldIncrementCountSynchronously() = self.GetMyMethodName "=>" @@ -124,7 +127,7 @@ type AltCoverTests() = class Instance.Visits.Clear() Instance.trace <- { Tracer=null; Stream=null; Formatter=null } let key = " " - Instance.VisitSelection (fun () -> true) key 23 (None,None) + Instance.VisitSelection (fun () -> true) key 23 (None, None) Thread.Sleep 100 Assert.That (Instance.Visits.Count, Is.EqualTo 1, "A visit happened") Assert.That (Instance.Visits.[key].Count, Is.EqualTo 1, "keys = " + String.Join("; ", Instance.Visits.Keys|> Seq.toArray)) @@ -141,8 +144,8 @@ type AltCoverTests() = class try Instance.Visits.Clear() let key = " " - Instance.VisitImpl key 23 (None,None) - Instance.VisitImpl "key" 42 (None,None) + Instance.VisitImpl key 23 (None, None) + Instance.VisitImpl "key" 42 (None, None) Assert.That (Instance.Visits.Count, Is.EqualTo 2) finally Instance.Visits.Clear()) @@ -155,12 +158,12 @@ type AltCoverTests() = class try Instance.Visits.Clear() let key = " " - Instance.VisitImpl key 23 (None,None) - Instance.VisitImpl key 42 (None,None) + Instance.VisitImpl key 23 (None, None) + Instance.VisitImpl key 42 (None, None) Assert.That (Instance.Visits.Count, Is.EqualTo 1) Assert.That (Instance.Visits.[key].Count, Is.EqualTo 2) finally - Instance.Visits.Clear()) + Adapter.VisitsClear()) self.GetMyMethodName "<=" [] @@ -170,9 +173,9 @@ type AltCoverTests() = class try Instance.Visits.Clear() let key = " " - Instance.VisitImpl key 23 (None,None) - Instance.VisitImpl key 23 (None,None) - Assert.That (Instance.Visits.[key].[23], Is.EqualTo (2, [])) + Instance.VisitImpl key 23 (None, None) + Instance.VisitImpl key 23 (None, None) + Assert.That (Instance.Visits.[key].[23], Is.EqualTo (2,[])) finally Instance.Visits.Clear()) self.GetMyMethodName "<=" @@ -192,7 +195,7 @@ type AltCoverTests() = class worker.Position <- 0L let before = XmlDocument() before.Load (Assembly.GetExecutingAssembly().GetManifestResourceStream(self.resource)) - self.UpdateReport (Dictionary>()) worker + self.UpdateReport (Dictionary>()) worker worker.Position <- 0L let after = XmlDocument() after.Load worker @@ -217,7 +220,7 @@ type AltCoverTests() = class worker.Position <- 0L let before = XmlDocument() before.Load (Assembly.GetExecutingAssembly().GetManifestResourceStream(self.resource)) - self.UpdateReport (Dictionary>()) worker + self.UpdateReport (Dictionary>()) worker worker.Position <- 0L let after = XmlDocument() after.Load worker @@ -242,7 +245,7 @@ type AltCoverTests() = class worker.Position <- 0L let before = XmlDocument() before.Load (Assembly.GetExecutingAssembly().GetManifestResourceStream(self.resource)) - self.UpdateReport (Dictionary>()) worker + self.UpdateReport (Dictionary>()) worker worker.Position <- 0L let after = XmlDocument() after.Load worker @@ -267,7 +270,7 @@ type AltCoverTests() = class worker.Position <- 0L let before = XmlDocument() before.Load (Assembly.GetExecutingAssembly().GetManifestResourceStream(self.resource)) - self.UpdateReport (Dictionary>()) worker + self.UpdateReport (Dictionary>()) worker worker.Position <- 0L let after = XmlDocument() after.Load worker @@ -290,7 +293,7 @@ type AltCoverTests() = class worker.Write (buffer, 0, size) worker.Position <- 0L use before = new StreamReader (Assembly.GetExecutingAssembly().GetManifestResourceStream(self.resource)) - let item = Dictionary>() + let item = Dictionary>() item.Add ("not a guid", null) self.UpdateReport item worker worker.Position <- 0L @@ -316,8 +319,8 @@ type AltCoverTests() = class worker.Write (buffer, 0, size) worker.Position <- 0L use before = new StreamReader (Assembly.GetExecutingAssembly().GetManifestResourceStream(self.resource)) - let item = Dictionary>() - item.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", Dictionary()) + let item = Dictionary>() + item.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", Dictionary()) self.UpdateReport item worker worker.Position <- 0L let after = new StreamReader(worker) @@ -345,7 +348,7 @@ type AltCoverTests() = class let payload = Dictionary() payload.[-1] <- (10, []) payload.[100] <- (10, []) - let item = Dictionary>() + let item = Dictionary>() item.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", payload) self.UpdateReport item worker worker.Position <- 0L @@ -370,10 +373,10 @@ type AltCoverTests() = class use worker = new MemoryStream() worker.Write (buffer, 0, size) worker.Position <- 0L - let payload = Dictionary() + let payload = Dictionary() [0..9 ] |> Seq.iter(fun i -> payload.[i] <- (i+1, [])) - let item = Dictionary>() + let item = Dictionary>() item.Add("f6e3edb3-fb20-44b3-817d-f69d1a22fc2f", payload) self.UpdateReport item worker worker.Position <- 0L @@ -399,7 +402,7 @@ type AltCoverTests() = class worker.Position <- 0L let payload = Dictionary() [0..9 ] - |> Seq.iter(fun i -> payload.[10 - i] <- (i+1,[])) + |> Seq.iter(fun i -> payload.[10 - i] <- (i+1, [])) 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) Counter.UpdateReport ignore true item ReportFormat.OpenCover worker |> ignore @@ -411,28 +414,28 @@ type AltCoverTests() = class |> Seq.map (fun x -> x.GetAttribute("vc")), Is.EquivalentTo [ "11"; "10"; "9"; "8"; "7"; "6"; "4"; "3"; "2"; "1"])) self.GetMyMethodName "<=" - +#endif [] member self.EmptyFlushLeavesNoTrace() = self.GetMyMethodName "=>" - lock Instance.Visits (fun () -> + lock Adapter.Lock (fun () -> let saved = Console.Out try - Instance.Visits.Clear() + Adapter.VisitsClear() use stdout = new StringWriter() Console.SetOut stdout Instance.FlushCounterImpl ProcessExit Assert.That (stdout.ToString(), Is.Empty) finally - Instance.Visits.Clear() + Adapter.VisitsClear() Console.SetOut saved) self.GetMyMethodName "<=" member self.FlushLeavesExpectedTraces() = self.GetMyMethodName "=>" - lock Instance.Visits (fun () -> + lock Adapter.Lock (fun () -> try let saved = Console.Out let here = Directory.GetCurrentDirectory() @@ -441,7 +444,7 @@ type AltCoverTests() = class let save = Instance.trace Instance.trace <- { Tracer=null; Stream=null; Formatter=null } try - Instance.Visits.Clear() + Adapter.VisitsClear() use stdout = new StringWriter() Console.SetOut stdout Directory.CreateDirectory(unique) |> ignore @@ -457,10 +460,8 @@ type AltCoverTests() = class worker.Write(buffer, 0, size) () - let payload = Dictionary() [0..9 ] - |> Seq.iter(fun i -> payload.[i] <- (i+1, [])) - Instance.Visits.["f6e3edb3-fb20-44b3-817d-f69d1a22fc2f"] <- payload + |> Seq.iter(fun i -> Adapter.VisitsAdd "f6e3edb3-fb20-44b3-817d-f69d1a22fc2f" i (i+1)) Instance.FlushCounter ProcessExit () while Instance.Backlog () > 0 do @@ -484,7 +485,7 @@ type AltCoverTests() = class finally Instance.trace <- save if File.Exists Instance.ReportFile then File.Delete Instance.ReportFile - Instance.Visits.Clear() + Adapter.VisitsClear() Console.SetOut saved Directory.SetCurrentDirectory(here) try @@ -496,6 +497,8 @@ type AltCoverTests() = class self.GetMyMethodName "<=" +#if NET2 +#else // Dead simple sequential operation // run only once in Framework mode to avoid contention [] diff --git a/Shadow.Tests/Shadow.Tests.fsproj b/Shadow.Tests/Shadow.Tests.fsproj index 0e9b01083..30835ebf8 100644 --- a/Shadow.Tests/Shadow.Tests.fsproj +++ b/Shadow.Tests/Shadow.Tests.fsproj @@ -91,6 +91,11 @@ {62480be3-4479-4a47-a23f-50858ecd74b3} True + + Shadow.Adapter + {24bfb835-2dac-45d4-afda-f9c2f13b41dd} + True + Shadow.Tests2 {d6ed39d2-ea21-4141-96d7-2b5f234fcd3e} diff --git a/Shadow.Tests/Tracer.fs b/Shadow.Tests/Tracer.fs index 89d272664..7ff909958 100644 --- a/Shadow.Tests/Tracer.fs +++ b/Shadow.Tests/Tracer.fs @@ -23,6 +23,7 @@ open System.IO.Compression open System.Reflection open AltCover.Recorder +open AltCover.Shadow open NUnit.Framework type UpdateBinder () = @@ -74,9 +75,6 @@ type AltCoverCoreTests() = class sink() hits -#if NET4 - // passing F# types across the CLR divide doesn't work -#else [] member self.VisitShouldSignal() = let save = Instance.trace @@ -91,25 +89,23 @@ type AltCoverCoreTests() = class try let mutable client = Tracer.Create tag try - Instance.Visits.Clear() - let entry = Dictionary() - entry.Add(23, (1, [])) - Instance.Visits.Add("name", entry) + Adapter.VisitsClear() + Adapter.VisitsAdd "name" 23 1 Instance.trace <- client.OnStart() Assert.That (Instance.trace.IsConnected(), "connection failed") - Instance.VisitImpl "name" 23 (None,None) + Adapter.VisitImplNone "name" 23 finally Instance.trace.Close() Instance.trace <- save use stream = new DeflateStream(File.OpenRead (unique + ".0.acv"), CompressionMode.Decompress) let results = self.ReadResults stream - Assert.That (Instance.Visits, Is.Empty, "unexpected local write") + Assert.That (Adapter.VisitsSeq(), Is.Empty, "unexpected local write") Assert.That (results, Is.EquivalentTo expected, "unexpected result") finally - Instance.Visits.Clear() + Adapter.VisitsClear() [] member self.FlushShouldTidyUp() = // also throw a bone to OpenCover 615 @@ -127,7 +123,7 @@ type AltCoverCoreTests() = class let expected = [("name", client.GetHashCode()); (null, -1)] try - Instance.Visits.Clear() + Adapter.VisitsClear() Instance.trace <- client.OnStart() Assert.That(Instance.trace.Equals client, Is.False) Assert.That(Instance.trace.Equals expected, Is.False) @@ -143,12 +139,12 @@ type AltCoverCoreTests() = class use stream = new DeflateStream(File.OpenRead (root + ".0.acv"), CompressionMode.Decompress) let results = self.ReadResults stream - Assert.That (Instance.Visits, Is.Empty, "unexpected local write") + Assert.That (Adapter.VisitsSeq(), Is.Empty, "unexpected local write") Assert.That (results, Is.EquivalentTo expected, "unexpected result") finally - Instance.Visits.Clear() -#endif + Adapter.VisitsClear() + #if NETCOREAPP2_0 [] member self.CoreFindsThePlace() = diff --git a/Shadow.Tests/altcover.recorder.tests.core.fsproj b/Shadow.Tests/altcover.recorder.tests.core.fsproj index 1e2e8bc34..4f7dca0cc 100644 --- a/Shadow.Tests/altcover.recorder.tests.core.fsproj +++ b/Shadow.Tests/altcover.recorder.tests.core.fsproj @@ -40,6 +40,7 @@ + diff --git a/Shadow.Tests2/Shadow.Tests2.fsproj b/Shadow.Tests2/Shadow.Tests2.fsproj index 764f7c80e..ab3444dd0 100644 --- a/Shadow.Tests2/Shadow.Tests2.fsproj +++ b/Shadow.Tests2/Shadow.Tests2.fsproj @@ -79,6 +79,11 @@ + + Shadow.Adapter + {24bfb835-2dac-45d4-afda-f9c2f13b41dd} + True + True diff --git a/altcover.core.sln b/altcover.core.sln index d26150742..4c07d89df 100644 --- a/altcover.core.sln +++ b/altcover.core.sln @@ -10,6 +10,8 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "altcover.shadow.core", "Alt EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "altcover.tests.core", "Tests/altcover.tests.core.fsproj", "{440A79BE-7038-44EA-B683-3ED8EFAEC39C}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "altcover.adapter.core", "Shadow.Adapter/altcover.adapter.core.fsproj", "{DDF0D5A2-370B-4827-B5D3-2A258E6677F1}" +EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "altcover.recorder.tests.core", "Shadow.Tests/altcover.recorder.tests.core.fsproj", "{CE0C9532-2D52-4225-8E23-98E70A3F2326}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sample1.core", "Sample1/sample1.core.csproj", "{B2591DB3-481E-4A79-A849-AD6C6547BA7F}" @@ -69,7 +71,6 @@ Global {1D249F47-8780-4431-8E95-2C3786607B63}.Debug|x64.ActiveCfg = Debug|Any CPU {1D249F47-8780-4431-8E95-2C3786607B63}.Debug|x86.ActiveCfg = Debug|Any CPU {1D249F47-8780-4431-8E95-2C3786607B63}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1D249F47-8780-4431-8E95-2C3786607B63}.Release|Any CPU.Build.0 = Release|Any CPU {1D249F47-8780-4431-8E95-2C3786607B63}.Release|x64.ActiveCfg = Release|Any CPU {1D249F47-8780-4431-8E95-2C3786607B63}.Release|x86.ActiveCfg = Release|Any CPU {440A79BE-7038-44EA-B683-3ED8EFAEC39C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -77,7 +78,6 @@ Global {440A79BE-7038-44EA-B683-3ED8EFAEC39C}.Debug|x64.ActiveCfg = Debug|Any CPU {440A79BE-7038-44EA-B683-3ED8EFAEC39C}.Debug|x86.ActiveCfg = Debug|Any CPU {440A79BE-7038-44EA-B683-3ED8EFAEC39C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {440A79BE-7038-44EA-B683-3ED8EFAEC39C}.Release|Any CPU.Build.0 = Release|Any CPU {440A79BE-7038-44EA-B683-3ED8EFAEC39C}.Release|x64.ActiveCfg = Release|Any CPU {440A79BE-7038-44EA-B683-3ED8EFAEC39C}.Release|x86.ActiveCfg = Release|Any CPU {CE0C9532-2D52-4225-8E23-98E70A3F2326}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -85,7 +85,6 @@ Global {CE0C9532-2D52-4225-8E23-98E70A3F2326}.Debug|x64.ActiveCfg = Debug|Any CPU {CE0C9532-2D52-4225-8E23-98E70A3F2326}.Debug|x86.ActiveCfg = Debug|Any CPU {CE0C9532-2D52-4225-8E23-98E70A3F2326}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CE0C9532-2D52-4225-8E23-98E70A3F2326}.Release|Any CPU.Build.0 = Release|Any CPU {CE0C9532-2D52-4225-8E23-98E70A3F2326}.Release|x64.ActiveCfg = Release|Any CPU {CE0C9532-2D52-4225-8E23-98E70A3F2326}.Release|x86.ActiveCfg = Release|Any CPU {B2591DB3-481E-4A79-A849-AD6C6547BA7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -93,7 +92,6 @@ Global {B2591DB3-481E-4A79-A849-AD6C6547BA7F}.Debug|x64.ActiveCfg = Debug|Any CPU {B2591DB3-481E-4A79-A849-AD6C6547BA7F}.Debug|x86.ActiveCfg = Debug|Any CPU {B2591DB3-481E-4A79-A849-AD6C6547BA7F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B2591DB3-481E-4A79-A849-AD6C6547BA7F}.Release|Any CPU.Build.0 = Release|Any CPU {B2591DB3-481E-4A79-A849-AD6C6547BA7F}.Release|x64.ActiveCfg = Release|Any CPU {B2591DB3-481E-4A79-A849-AD6C6547BA7F}.Release|x86.ActiveCfg = Release|Any CPU {FB3B5250-DF9C-478B-BAD4-1D28D89D437A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -101,7 +99,6 @@ Global {FB3B5250-DF9C-478B-BAD4-1D28D89D437A}.Debug|x64.ActiveCfg = Debug|Any CPU {FB3B5250-DF9C-478B-BAD4-1D28D89D437A}.Debug|x86.ActiveCfg = Debug|Any CPU {FB3B5250-DF9C-478B-BAD4-1D28D89D437A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FB3B5250-DF9C-478B-BAD4-1D28D89D437A}.Release|Any CPU.Build.0 = Release|Any CPU {FB3B5250-DF9C-478B-BAD4-1D28D89D437A}.Release|x64.ActiveCfg = Release|Any CPU {FB3B5250-DF9C-478B-BAD4-1D28D89D437A}.Release|x86.ActiveCfg = Release|Any CPU {D4FE2C23-980A-46B0-8ECC-DD27FDF11C28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -109,7 +106,6 @@ Global {D4FE2C23-980A-46B0-8ECC-DD27FDF11C28}.Debug|x64.ActiveCfg = Debug|Any CPU {D4FE2C23-980A-46B0-8ECC-DD27FDF11C28}.Debug|x86.ActiveCfg = Debug|Any CPU {D4FE2C23-980A-46B0-8ECC-DD27FDF11C28}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D4FE2C23-980A-46B0-8ECC-DD27FDF11C28}.Release|Any CPU.Build.0 = Release|Any CPU {D4FE2C23-980A-46B0-8ECC-DD27FDF11C28}.Release|x64.ActiveCfg = Release|Any CPU {D4FE2C23-980A-46B0-8ECC-DD27FDF11C28}.Release|x86.ActiveCfg = Release|Any CPU {358265A1-C7B3-48E8-9707-2F344ECAAE9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -117,9 +113,17 @@ Global {358265A1-C7B3-48E8-9707-2F344ECAAE9F}.Debug|x64.ActiveCfg = Debug|Any CPU {358265A1-C7B3-48E8-9707-2F344ECAAE9F}.Debug|x86.ActiveCfg = Debug|Any CPU {358265A1-C7B3-48E8-9707-2F344ECAAE9F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {358265A1-C7B3-48E8-9707-2F344ECAAE9F}.Release|Any CPU.Build.0 = Release|Any CPU {358265A1-C7B3-48E8-9707-2F344ECAAE9F}.Release|x64.ActiveCfg = Release|Any CPU {358265A1-C7B3-48E8-9707-2F344ECAAE9F}.Release|x86.ActiveCfg = Release|Any CPU + {DDF0D5A2-370B-4827-B5D3-2A258E6677F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DDF0D5A2-370B-4827-B5D3-2A258E6677F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DDF0D5A2-370B-4827-B5D3-2A258E6677F1}.Debug|x64.ActiveCfg = Debug|Any CPU + {DDF0D5A2-370B-4827-B5D3-2A258E6677F1}.Debug|x64.Build.0 = Debug|Any CPU + {DDF0D5A2-370B-4827-B5D3-2A258E6677F1}.Debug|x86.ActiveCfg = Debug|Any CPU + {DDF0D5A2-370B-4827-B5D3-2A258E6677F1}.Debug|x86.Build.0 = Debug|Any CPU + {DDF0D5A2-370B-4827-B5D3-2A258E6677F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DDF0D5A2-370B-4827-B5D3-2A258E6677F1}.Release|x64.ActiveCfg = Release|Any CPU + {DDF0D5A2-370B-4827-B5D3-2A258E6677F1}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 9716ea655122f636dc32a5989aef90276cf05e30 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Fri, 16 Mar 2018 18:51:39 +0000 Subject: [PATCH 12/67] Whitespace cleanup --- AltCover.Recorder/Base.fs | 2 +- Shadow.Adapter/Adapter.fs | 2 +- Shadow.Tests/Shadow.Tests.fs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/AltCover.Recorder/Base.fs b/AltCover.Recorder/Base.fs index 2cadc7ca8..6eb7d6ace 100644 --- a/AltCover.Recorder/Base.fs +++ b/AltCover.Recorder/Base.fs @@ -56,7 +56,7 @@ module Counter = /// /// The coverage results to incorporate /// The coverage file to update as a stream - let internal UpdateReport (postProcess:XmlDocument -> unit) own (counts:Dictionary>) format coverageFile = + let internal UpdateReport (postProcess:XmlDocument -> unit) own (counts:Dictionary>) format coverageFile = let flushStart = DateTime.UtcNow let coverageDocument = ReadXDocument coverageFile let root = coverageDocument.DocumentElement diff --git a/Shadow.Adapter/Adapter.fs b/Shadow.Adapter/Adapter.fs index 2d30cf26e..792c5df4a 100644 --- a/Shadow.Adapter/Adapter.fs +++ b/Shadow.Adapter/Adapter.fs @@ -17,4 +17,4 @@ module Adapter = let VisitCount key key2 = Instance.Visits.[key].[key2] |> fst let Lock = Instance.Visits :> obj - let VisitImplNone moduleId hitPointId = Instance.VisitImpl moduleId hitPointId (None,None) + let VisitImplNone moduleId hitPointId = Instance.VisitImpl moduleId hitPointId (None,None) \ No newline at end of file diff --git a/Shadow.Tests/Shadow.Tests.fs b/Shadow.Tests/Shadow.Tests.fs index 93e3732aa..56f14476e 100644 --- a/Shadow.Tests/Shadow.Tests.fs +++ b/Shadow.Tests/Shadow.Tests.fs @@ -54,7 +54,6 @@ type AltCoverTests() = class member self.resource2 = Assembly.GetExecutingAssembly().GetManifestResourceNames() |> Seq.find (fun n -> n.EndsWith("Sample1WithModifiedOpenCover.xml", StringComparison.Ordinal)) - [] member self.ShouldBeLinkingTheCorrectCopyOfThisCode() = self.GetMyMethodName "=>" From 2863697b3c1882602e5e2047aa0dd07789fd3cac Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Fri, 16 Mar 2018 20:02:04 +0000 Subject: [PATCH 13/67] Simplify the decision point for what to load, and collapse the (None,None) case properly. --- AltCover.Recorder/Base.fs | 5 +++-- AltCover.Recorder/Recorder.fs | 4 ++-- AltCover.Recorder/Tracer.fs | 9 +++++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/AltCover.Recorder/Base.fs b/AltCover.Recorder/Base.fs index 6eb7d6ace..21553ee67 100644 --- a/AltCover.Recorder/Base.fs +++ b/AltCover.Recorder/Base.fs @@ -129,6 +129,7 @@ module Counter = if not (counts.ContainsKey moduleId) then counts.[moduleId] <- Dictionary() if not (counts.[moduleId].ContainsKey hitPointId) then counts.[moduleId].Add(hitPointId, (0,[])) + let n, l = counts.[moduleId].[hitPointId] counts.[moduleId].[hitPointId] <- match context with - | (None, None) -> (1 + fst counts.[moduleId].[hitPointId], snd counts.[moduleId].[hitPointId]) - | something -> (1 + fst counts.[moduleId].[hitPointId], something :: snd counts.[moduleId].[hitPointId]) \ No newline at end of file + | (None, None) -> (1 + n, l) + | something -> (n, something :: l) \ No newline at end of file diff --git a/AltCover.Recorder/Recorder.fs b/AltCover.Recorder/Recorder.fs index 155c3a1bf..d98f76946 100644 --- a/AltCover.Recorder/Recorder.fs +++ b/AltCover.Recorder/Recorder.fs @@ -112,7 +112,7 @@ module Instance = let internal VisitImpl moduleId hitPointId context = if not <| String.IsNullOrEmpty(moduleId) then trace.OnConnected (fun () -> TraceVisit moduleId hitPointId context) - (fun () -> Counter.AddVisit Visits moduleId hitPointId (None, None)) + (fun () -> Counter.AddVisit Visits moduleId hitPointId context) let rec private loop (inbox:MailboxProcessor) = async { @@ -155,7 +155,7 @@ module Instance = let Visit moduleId hitPointId = VisitSelection (fun () -> trace.IsConnected() || Backlog() > 10) - moduleId hitPointId (None, None) + moduleId hitPointId (None, None) // update iff runner file exists and opencover and option set let internal FlushCounter (finish:Close) _ = mailbox.PostAndReply (fun c -> Finish (finish, c)) diff --git a/AltCover.Recorder/Tracer.fs b/AltCover.Recorder/Tracer.fs index d9a89203f..c8f8e3d0b 100644 --- a/AltCover.Recorder/Tracer.fs +++ b/AltCover.Recorder/Tracer.fs @@ -46,11 +46,16 @@ type Tracer = { this.Formatter.Serialize(stream, (moduleId, hitPointId, context)) member this.CatchUp (visits:Dictionary>) = + let empty = (None,None) visits.Keys |> Seq.iter (fun moduleId -> visits.[moduleId].Keys - |> Seq.iter (fun hitPointId -> for i = 1 to fst visits.[moduleId].[hitPointId] do - this.Push moduleId hitPointId (None, None))) + |> Seq.iter (fun hitPointId -> let n, l = visits.[moduleId].[hitPointId] + let push = this.Push moduleId hitPointId + [seq {1 .. n} |> Seq.map (fun _ -> empty ) + l |> List.toSeq] + |> Seq.concat |> Seq.iter push + )) visits.Clear() member this.OnStart () = From 6be78744580222b63b0c11a5f17c2ece1e91e771 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Fri, 16 Mar 2018 20:16:36 +0000 Subject: [PATCH 14/67] Nuget updates for .net core --- Sample2/sample2.core.fsproj | 6 +++--- Sample4/sample4.core.fsproj | 2 +- Shadow.Tests/altcover.recorder.tests.core.fsproj | 6 +++--- Tests/altcover.tests.core.fsproj | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Sample2/sample2.core.fsproj b/Sample2/sample2.core.fsproj index 2029098c9..0d0188249 100644 --- a/Sample2/sample2.core.fsproj +++ b/Sample2/sample2.core.fsproj @@ -21,9 +21,9 @@ - - - + + + diff --git a/Sample4/sample4.core.fsproj b/Sample4/sample4.core.fsproj index 24fd44a19..436f2ea5b 100644 --- a/Sample4/sample4.core.fsproj +++ b/Sample4/sample4.core.fsproj @@ -21,7 +21,7 @@ - + diff --git a/Shadow.Tests/altcover.recorder.tests.core.fsproj b/Shadow.Tests/altcover.recorder.tests.core.fsproj index 4f7dca0cc..59457332b 100644 --- a/Shadow.Tests/altcover.recorder.tests.core.fsproj +++ b/Shadow.Tests/altcover.recorder.tests.core.fsproj @@ -33,9 +33,9 @@ - - - + + + diff --git a/Tests/altcover.tests.core.fsproj b/Tests/altcover.tests.core.fsproj index d36f8e22c..e9525a846 100644 --- a/Tests/altcover.tests.core.fsproj +++ b/Tests/altcover.tests.core.fsproj @@ -51,12 +51,12 @@ - + - - + + From f486556717bef74f16ed1e30b6af83e3d1b02214 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Fri, 16 Mar 2018 20:53:07 +0000 Subject: [PATCH 15/67] Fix unit tests for the new NUnit test adapter which has bundled a .pdb --- Tests/Tests.fs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tests/Tests.fs b/Tests/Tests.fs index 9341e2c14..37424a5e7 100644 --- a/Tests/Tests.fs +++ b/Tests/Tests.fs @@ -3574,6 +3574,10 @@ type AltCoverTests() = class "Mono.Cecil.dll" "nunit.engine.netstandard.dll" "NUnit3.TestAdapter.dll" +#if NETCOREAPP2_0 + "NUnit3.TestAdapter.dll.mdb" +#endif + "NUnit3.TestAdapter.pdb" "Sample2.deps.json" "Sample2.dll" #if NETCOREAPP2_0 From f8cdeb63cbca8fb80b4cbaefadf37bae8475f57a Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Fri, 16 Mar 2018 20:53:59 +0000 Subject: [PATCH 16/67] Experiment -- explicitly point at the F# core assembly, as travis was still pulling 4.4.1 when it failed because it claimed that Option was not serializable --- AltCover.Recorder/altcover.recorder.core.fsproj | 4 +++- AltCover.Shadow/altcover.shadow.core.fsproj | 4 +++- AltCover/altcover.core.fsproj | 4 +++- Shadow.Adapter/altcover.adapter.core.fsproj | 4 +++- Shadow.Tests/altcover.recorder.tests.core.fsproj | 4 +++- Tests/altcover.tests.core.fsproj | 4 +++- 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/AltCover.Recorder/altcover.recorder.core.fsproj b/AltCover.Recorder/altcover.recorder.core.fsproj index e7df89624..9f8fca4b9 100644 --- a/AltCover.Recorder/altcover.recorder.core.fsproj +++ b/AltCover.Recorder/altcover.recorder.core.fsproj @@ -25,7 +25,9 @@ - + + ..\packages\FSharp.Core.4.3.4\lib\netstandard1.6\FSharp.Core.dll + diff --git a/AltCover.Shadow/altcover.shadow.core.fsproj b/AltCover.Shadow/altcover.shadow.core.fsproj index ffa1b15bf..42be88cc8 100644 --- a/AltCover.Shadow/altcover.shadow.core.fsproj +++ b/AltCover.Shadow/altcover.shadow.core.fsproj @@ -31,7 +31,9 @@ - + + ..\packages\FSharp.Core.4.3.4\lib\netstandard1.6\FSharp.Core.dll + diff --git a/AltCover/altcover.core.fsproj b/AltCover/altcover.core.fsproj index 8a1b0d726..44771b2f8 100644 --- a/AltCover/altcover.core.fsproj +++ b/AltCover/altcover.core.fsproj @@ -56,7 +56,9 @@ - + + ..\packages\FSharp.Core.4.3.4\lib\netstandard1.6\FSharp.Core.dll + diff --git a/Shadow.Adapter/altcover.adapter.core.fsproj b/Shadow.Adapter/altcover.adapter.core.fsproj index e58c85204..08deb824a 100644 --- a/Shadow.Adapter/altcover.adapter.core.fsproj +++ b/Shadow.Adapter/altcover.adapter.core.fsproj @@ -25,7 +25,9 @@ - + + ..\packages\FSharp.Core.4.3.4\lib\netstandard1.6\FSharp.Core.dll + diff --git a/Shadow.Tests/altcover.recorder.tests.core.fsproj b/Shadow.Tests/altcover.recorder.tests.core.fsproj index 59457332b..38218f200 100644 --- a/Shadow.Tests/altcover.recorder.tests.core.fsproj +++ b/Shadow.Tests/altcover.recorder.tests.core.fsproj @@ -44,7 +44,9 @@ - + + ..\packages\FSharp.Core.4.3.4\lib\netstandard1.6\FSharp.Core.dll + diff --git a/Tests/altcover.tests.core.fsproj b/Tests/altcover.tests.core.fsproj index e9525a846..890cb866a 100644 --- a/Tests/altcover.tests.core.fsproj +++ b/Tests/altcover.tests.core.fsproj @@ -68,7 +68,9 @@ - + + ..\packages\FSharp.Core.4.3.4\lib\netstandard1.6\FSharp.Core.dll + From afa16271680ab03679d1913a4ffae29c606c0099 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Sat, 17 Mar 2018 08:55:34 +0000 Subject: [PATCH 17/67] Fix Visual Studio build --- Shadow.Adapter/Shadow.Adapter.fsproj | 1 + 1 file changed, 1 insertion(+) diff --git a/Shadow.Adapter/Shadow.Adapter.fsproj b/Shadow.Adapter/Shadow.Adapter.fsproj index 77504c4d9..8719acc93 100644 --- a/Shadow.Adapter/Shadow.Adapter.fsproj +++ b/Shadow.Adapter/Shadow.Adapter.fsproj @@ -83,6 +83,7 @@ +