From fd92158cf7fd9801e91b077259586624baf31fc2 Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Mon, 2 Dec 2019 15:50:28 +0100 Subject: [PATCH 1/5] expose coverlet.core.dll --- .../Calculator/Calculator.csproj | 13 + .../Calculator/CalculatorRuntime.cs | 25 + .../StandaloneUsage/Calculator/Program.cs | 101 ++++ .../Calculator/RealTimeCoverageAnalysis.cs | 56 +++ .../StandaloneUsage/Directory.Build.props | 10 + .../Instrumentor/Instrumentor.csproj | 13 + .../StandaloneUsage/Instrumentor/Program.cs | 34 ++ .../Examples/StandaloneUsage/Readme.md | 69 +++ .../StandaloneUsage/StandaloneUsage.sln | 60 +++ .../Examples/StandaloneUsage/nuget.config | 8 + .../Examples/StandaloneUsage/run_app.cmd | 1 + .../StandaloneUsage/run_instrumentor.cmd | 2 + coverlet.sln | 16 +- .../DataCollection/CoverageManager.cs | 3 +- .../DataCollection/CoverageWrapper.cs | 1 + .../Utilities/Interfaces/ICoverageWrapper.cs | 1 + src/coverlet.console/Program.cs | 2 +- .../Abstracts/IInstrumentationHelper.cs | 2 +- src/coverlet.core/Abstracts/IInstrumenter.cs | 42 ++ src/coverlet.core/Abstracts/IReporter.cs | 32 ++ src/coverlet.core/Coverage.cs | 48 +- src/coverlet.core/CoverageDetails.cs | 18 - src/coverlet.core/CoverageResult.cs | 201 -------- src/coverlet.core/CoverageSummary.cs | 227 --------- src/coverlet.core/Enums/ThresholdStatistic.cs | 2 +- src/coverlet.core/Enums/ThresholdTypeFlags.cs | 2 +- .../Helpers/InstrumentationHelper.cs | 3 +- .../Instrumentation/CoverageEngine.cs | 340 ++++++++++++++ src/coverlet.core/ObjectModel.cs | 435 ++++++++++++++++++ .../Reporters/CoberturaReporter.cs | 4 +- src/coverlet.core/Reporters/IReporter.cs | 16 - src/coverlet.core/Reporters/JsonReporter.cs | 3 +- src/coverlet.core/Reporters/LcovReporter.cs | 3 +- .../Reporters/OpenCoverReporter.cs | 3 +- .../Reporters/ReporterFactory.cs | 22 +- .../Reporters/TeamCityReporter.cs | 6 +- src/coverlet.core/coverlet.core.csproj | 17 +- src/coverlet.core/version.json | 7 + .../CoverageResultTask.cs | 3 +- .../CoverletCoverageDataCollectorTests.cs | 7 +- .../coverlet.core.standalone.sample/Sample.cs | 10 + .../coverlet.core.standalone.sample.csproj | 9 + .../BaseTest.cs | 51 ++ .../StandaloneInstrumentation.cs | 108 +++++ .../coverlet.core.standalone.tests.csproj | 29 ++ .../CoverageSummaryTests.cs | 5 +- test/coverlet.core.tests/CoverageTests.cs | 1 + .../coverlet.core.tests/InstrumenterHelper.cs | 2 +- .../Reporters/CoberturaReporterTests.cs | 6 +- .../Reporters/JsonReporterTests.cs | 4 +- .../Reporters/LcovReporterTests.cs | 5 +- .../Reporters/OpenCoverReporterTests.cs | 5 +- .../Reporters/ReporterFactoryTests.cs | 4 +- .../Reporters/TeamCityReporter.cs | 5 +- 54 files changed, 1577 insertions(+), 525 deletions(-) create mode 100644 Documentation/Examples/StandaloneUsage/Calculator/Calculator.csproj create mode 100644 Documentation/Examples/StandaloneUsage/Calculator/CalculatorRuntime.cs create mode 100644 Documentation/Examples/StandaloneUsage/Calculator/Program.cs create mode 100644 Documentation/Examples/StandaloneUsage/Calculator/RealTimeCoverageAnalysis.cs create mode 100644 Documentation/Examples/StandaloneUsage/Directory.Build.props create mode 100644 Documentation/Examples/StandaloneUsage/Instrumentor/Instrumentor.csproj create mode 100644 Documentation/Examples/StandaloneUsage/Instrumentor/Program.cs create mode 100644 Documentation/Examples/StandaloneUsage/Readme.md create mode 100644 Documentation/Examples/StandaloneUsage/StandaloneUsage.sln create mode 100644 Documentation/Examples/StandaloneUsage/nuget.config create mode 100644 Documentation/Examples/StandaloneUsage/run_app.cmd create mode 100644 Documentation/Examples/StandaloneUsage/run_instrumentor.cmd create mode 100644 src/coverlet.core/Abstracts/IInstrumenter.cs create mode 100644 src/coverlet.core/Abstracts/IReporter.cs delete mode 100644 src/coverlet.core/CoverageDetails.cs delete mode 100644 src/coverlet.core/CoverageResult.cs delete mode 100644 src/coverlet.core/CoverageSummary.cs create mode 100644 src/coverlet.core/Instrumentation/CoverageEngine.cs create mode 100644 src/coverlet.core/ObjectModel.cs delete mode 100644 src/coverlet.core/Reporters/IReporter.cs create mode 100644 src/coverlet.core/version.json create mode 100644 test/coverlet.core.standalone.sample/Sample.cs create mode 100644 test/coverlet.core.standalone.sample/coverlet.core.standalone.sample.csproj create mode 100644 test/coverlet.core.standalone.tests/BaseTest.cs create mode 100644 test/coverlet.core.standalone.tests/StandaloneInstrumentation.cs create mode 100644 test/coverlet.core.standalone.tests/coverlet.core.standalone.tests.csproj diff --git a/Documentation/Examples/StandaloneUsage/Calculator/Calculator.csproj b/Documentation/Examples/StandaloneUsage/Calculator/Calculator.csproj new file mode 100644 index 000000000..8cd52edce --- /dev/null +++ b/Documentation/Examples/StandaloneUsage/Calculator/Calculator.csproj @@ -0,0 +1,13 @@ + + + + Exe + netcoreapp2.2 + + + + + ..\..\..\..\src\coverlet.core\bin\Debug\netstandard2.0\coverlet.core.dll + + + diff --git a/Documentation/Examples/StandaloneUsage/Calculator/CalculatorRuntime.cs b/Documentation/Examples/StandaloneUsage/Calculator/CalculatorRuntime.cs new file mode 100644 index 000000000..ca19365d8 --- /dev/null +++ b/Documentation/Examples/StandaloneUsage/Calculator/CalculatorRuntime.cs @@ -0,0 +1,25 @@ +namespace Calculator +{ + public class CalculatorRuntime + { + public double Add(double a, double b) + { + return a + b; + } + + public double Subtrac(double a, double b) + { + return a - b; + } + + public double Divide(double a, double b) + { + return a / b; + } + + public double Multiply(double a, double b) + { + return a * b; + } + } +} diff --git a/Documentation/Examples/StandaloneUsage/Calculator/Program.cs b/Documentation/Examples/StandaloneUsage/Calculator/Program.cs new file mode 100644 index 000000000..549e062d1 --- /dev/null +++ b/Documentation/Examples/StandaloneUsage/Calculator/Program.cs @@ -0,0 +1,101 @@ +#nullable enable + +using System; +using System.IO; + +namespace Calculator +{ + class Program + { + static void Main(string[] args) + { + if (args.Length == 0 || !File.Exists(args[0])) + { + Console.WriteLine("Instrumentation result file not found"); + } + + + RealTimeCoverageAnalysis inProc = new RealTimeCoverageAnalysis(args[0]); + CalculatorRuntime runtime = new CalculatorRuntime(); + double? operanda = null; + double? operandb = null; + for (; ; ) + { + if (operanda is null) + { + Console.WriteLine("Insert operand a"); + double operand; + while (!double.TryParse(Console.ReadLine(), out operand)) + { + Console.WriteLine("Invalid value, insert operand a"); + } + operanda = operand; + } + if (operandb is null) + { + Console.WriteLine("Insert operand b"); + double operand; + while (!double.TryParse(Console.ReadLine(), out operand)) + { + Console.WriteLine("Invalid value, insert operand b"); + } + operandb = operand; + } + + + for (; ; ) + { + Console.WriteLine("Insert operation"); + ConsoleKeyInfo consoleKeyInfo = Console.ReadKey(); + if (consoleKeyInfo.Key != ConsoleKey.Add && consoleKeyInfo.Key != ConsoleKey.Subtract && + consoleKeyInfo.Key != ConsoleKey.Divide && consoleKeyInfo.Key != ConsoleKey.Multiply) + { + Console.WriteLine("Invalid operation, allowed operation, +-*/"); + } + else + { + Console.WriteLine(); + switch (consoleKeyInfo.Key) + { + case ConsoleKey.Add: + { + Console.WriteLine($"Result: {runtime.Add(operanda.Value, operandb.Value)}"); + break; + } + case ConsoleKey.Subtract: + { + Console.WriteLine($"Result: {runtime.Subtrac(operanda.Value, operandb.Value)}"); + break; + } + case ConsoleKey.Multiply: + { + Console.WriteLine($"Result: {runtime.Multiply(operanda.Value, operandb.Value)}"); + break; + } + case ConsoleKey.Divide: + { + Console.WriteLine($"Result: {runtime.Divide(operanda.Value, operandb.Value)}"); + break; + } + default: + break; + } + operanda = operandb = null; + + inProc.PrintCoverageCurrentState(); + + Console.WriteLine(); + Console.WriteLine("Exit(press E)? Any other button to another loop"); + if (Console.ReadKey().Key == ConsoleKey.E) + { + return; + } + Console.Clear(); + break; + } + } + } + } + } +} + diff --git a/Documentation/Examples/StandaloneUsage/Calculator/RealTimeCoverageAnalysis.cs b/Documentation/Examples/StandaloneUsage/Calculator/RealTimeCoverageAnalysis.cs new file mode 100644 index 000000000..6de3abbf4 --- /dev/null +++ b/Documentation/Examples/StandaloneUsage/Calculator/RealTimeCoverageAnalysis.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; +using System.Reflection; + +using Coverlet.Core.Abstracts; +using Coverlet.Core.Instrumentation; +using Coverlet.Core.ObjectModel; + +namespace Calculator +{ + public class RealTimeCoverageAnalysis + { + readonly IInProcessCoverageEngine inProcessEngine; + + public RealTimeCoverageAnalysis(string instrumentationResult) + { + ICoverageEngineFactory coverageFactory = new BuildInCoverageEngineFactory(); + inProcessEngine = coverageFactory.CreateInProcessEngine(File.OpenRead(instrumentationResult)); + } + + public void PrintCoverageCurrentState() + { + Console.WriteLine(); + Console.WriteLine("***Start live coverage analysis***"); + Console.WriteLine("---List of instrumented assemblies---"); + foreach (Assembly asm in inProcessEngine.GetInstrumentedAssemblies()) + { + Console.WriteLine(asm); + } + Console.WriteLine("---Method lines coverage---"); + CoverageResult? coverageResult = inProcessEngine.ReadCurrentCoverage(); + if (coverageResult != null) + { + CoverageSummary summary = new CoverageSummary(); + foreach (var module in coverageResult.Modules) + { + foreach (var document in module.Value) + { + foreach (var @class in document.Value) + { + foreach (var method in @class.Value) + { + var methodLineDetails = summary.CalculateMethodCoverage(method.Value.Lines); + Console.WriteLine($"Method '{method.Key}' {methodLineDetails.Percent}%"); + } + } + } + } + ConsoleColor tmp = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine($"Total modules method lines covered '{summary.CalculateMethodCoverage(coverageResult.Modules).Percent}'"); + Console.ForegroundColor = tmp; + } + } + } +} diff --git a/Documentation/Examples/StandaloneUsage/Directory.Build.props b/Documentation/Examples/StandaloneUsage/Directory.Build.props new file mode 100644 index 000000000..b6216655d --- /dev/null +++ b/Documentation/Examples/StandaloneUsage/Directory.Build.props @@ -0,0 +1,10 @@ + + + + enable + preview + + + + + diff --git a/Documentation/Examples/StandaloneUsage/Instrumentor/Instrumentor.csproj b/Documentation/Examples/StandaloneUsage/Instrumentor/Instrumentor.csproj new file mode 100644 index 000000000..8cd52edce --- /dev/null +++ b/Documentation/Examples/StandaloneUsage/Instrumentor/Instrumentor.csproj @@ -0,0 +1,13 @@ + + + + Exe + netcoreapp2.2 + + + + + ..\..\..\..\src\coverlet.core\bin\Debug\netstandard2.0\coverlet.core.dll + + + diff --git a/Documentation/Examples/StandaloneUsage/Instrumentor/Program.cs b/Documentation/Examples/StandaloneUsage/Instrumentor/Program.cs new file mode 100644 index 000000000..de5d75aeb --- /dev/null +++ b/Documentation/Examples/StandaloneUsage/Instrumentor/Program.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; +using Coverlet.Core.Abstracts; +using Coverlet.Core.Instrumentation; + +namespace Instrumentor +{ + class Program + { + static void Main(string[] args) + { + if (args.Length == 0 || !File.Exists(args[0])) + { + Console.WriteLine("Invalid lib to instrument"); + return; + } + + ICoverageEngineFactory coverageFactory = new BuildInCoverageEngineFactory(); + InstrumentationOptions options = new InstrumentationOptions(); + options.Module = args[0]; + options.IncludeTestAssembly = true; + ICoverageEngine coverageEngine = coverageFactory.CreateEngine(options); + using (Stream stream = coverageEngine.PrepareModules(), + fs = File.OpenWrite("instrumentationResult")) + { + stream.CopyTo(fs); + } + + Console.WriteLine($"Instrumentation result saved '{Path.GetFullPath("instrumentationResult")}'"); + Console.WriteLine("Instrumentor active, click any button to restore instrumented libraries"); + Console.ReadKey(); + } + } +} diff --git a/Documentation/Examples/StandaloneUsage/Readme.md b/Documentation/Examples/StandaloneUsage/Readme.md new file mode 100644 index 000000000..7e3c0e483 --- /dev/null +++ b/Documentation/Examples/StandaloneUsage/Readme.md @@ -0,0 +1,69 @@ +### Run sample + +1) Go to root coverlet folder and generate packages +``` +dotnet pack +... +Successfully created package 'C:\git\coverlet\bin\Debug\Packages\coverlet.core.1.0.4-gac3e48b424.nupkg' +``` +2) Update `run_instrumentor.cmd` with correct package version(in this case *1.0.4-gac3e48b424*) +``` +... +dotnet build /p:coverletCoreVersion=1.0.4-gac3e48b424 +... +``` +3) Open fresh new command line and run `run_instrumentor.cmd` +``` +run_instrumentor.cmd + +dotnet build /p:coverletCoreVersion=1.0.2-g1df3e82a5b +Microsoft (R) Build Engine version 16.2.32702+c4012a063 for .NET Core +Copyright (C) Microsoft Corporation. All rights reserved. + + Restore completed in 54,96 ms for C:\git\coverlet\Documentation\Examples\StandaloneUsage\Calculator\Calculator.csproj. + Restore completed in 54,96 ms for C:\git\coverlet\Documentation\Examples\StandaloneUsage\Instrumentor\Instrumentor.csproj. + Instrumentor -> C:\git\coverlet\Documentation\Examples\StandaloneUsage\Instrumentor\bin\Debug\netcoreapp2.2\Instrumentor.dll + Calculator -> C:\git\coverlet\Documentation\Examples\StandaloneUsage\Calculator\bin\Debug\netcoreapp2.2\Calculator.dll + +Build succeeded. + 0 Warning(s) + 0 Error(s) + +Time Elapsed 00:00:01.25 + +dotnet Instrumentor/bin/Debug/netcoreapp2.2/Instrumentor.dll Calculator/bin/Debug/netcoreapp2.2/Calculator.dll +[LogVerbose] Instrumented module: 'Calculator\bin\Debug\netcoreapp2.2\Calculator.dll' +Instrumentation result saved 'C:\git\coverlet\Documentation\Examples\StandaloneUsage\instrumentationResult' +Instrumentor active, click any button to restore instrumented libraries +``` +This process instruments "Calculator" app dll, you need to keep this process alive until end of app usage because when +instrumentor process shutdown coverlet restores old "non instrumented" libraries. + +4) Open another fresh new command line and run `run_app.cmd` and play with it +``` +run_app.cmd + +dotnet Calculator/bin/Debug/netcoreapp2.2/Calculator.dll instrumentationResult +Insert operand a +10 +Insert operand b +20 +Insert operation ++ +Result: 30 + +***Start live coverage analysis*** +---List of instrumented assemblies--- +Calculator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +---Method lines coverage--- +Method 'System.Double Calculator.CalculatorRuntime::Add(System.Double,System.Double)' 100% +Method 'System.Double Calculator.CalculatorRuntime::Subtrac(System.Double,System.Double)' 0% +Method 'System.Double Calculator.CalculatorRuntime::Divide(System.Double,System.Double)' 0% +Method 'System.Double Calculator.CalculatorRuntime::Multiply(System.Double,System.Double)' 0% +Method 'System.Void Calculator.Program::Main(System.String[])' 100% +Method 'System.Void Calculator.RealTimeCoverageAnalysis::PrintCoverageCurrentState()' 100% +Method 'System.Void Calculator.RealTimeCoverageAnalysis::.ctor(System.String)' 100% +Total modules method lines covered '57,14' + +Exit(press E)? Any other button to another loop +``` \ No newline at end of file diff --git a/Documentation/Examples/StandaloneUsage/StandaloneUsage.sln b/Documentation/Examples/StandaloneUsage/StandaloneUsage.sln new file mode 100644 index 000000000..1ea3b3c44 --- /dev/null +++ b/Documentation/Examples/StandaloneUsage/StandaloneUsage.sln @@ -0,0 +1,60 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29519.161 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{280AB950-6C74-493D-B4BD-0BA355511561}" + ProjectSection(SolutionItems) = preProject + Directory.Build.props = Directory.Build.props + nuget.config = nuget.config + Readme.md = Readme.md + run_app.cmd = run_app.cmd + run_instrumentor.cmd = run_instrumentor.cmd + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calculator", "Calculator\Calculator.csproj", "{06FD3D7A-AD30-4FF1-8E39-CEA6384B33AD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Instrumentor", "Instrumentor\Instrumentor.csproj", "{DCD64A1A-8BE9-4475-AE56-3BA44AB2ED2A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {06FD3D7A-AD30-4FF1-8E39-CEA6384B33AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {06FD3D7A-AD30-4FF1-8E39-CEA6384B33AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {06FD3D7A-AD30-4FF1-8E39-CEA6384B33AD}.Debug|x64.ActiveCfg = Debug|Any CPU + {06FD3D7A-AD30-4FF1-8E39-CEA6384B33AD}.Debug|x64.Build.0 = Debug|Any CPU + {06FD3D7A-AD30-4FF1-8E39-CEA6384B33AD}.Debug|x86.ActiveCfg = Debug|Any CPU + {06FD3D7A-AD30-4FF1-8E39-CEA6384B33AD}.Debug|x86.Build.0 = Debug|Any CPU + {06FD3D7A-AD30-4FF1-8E39-CEA6384B33AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {06FD3D7A-AD30-4FF1-8E39-CEA6384B33AD}.Release|Any CPU.Build.0 = Release|Any CPU + {06FD3D7A-AD30-4FF1-8E39-CEA6384B33AD}.Release|x64.ActiveCfg = Release|Any CPU + {06FD3D7A-AD30-4FF1-8E39-CEA6384B33AD}.Release|x64.Build.0 = Release|Any CPU + {06FD3D7A-AD30-4FF1-8E39-CEA6384B33AD}.Release|x86.ActiveCfg = Release|Any CPU + {06FD3D7A-AD30-4FF1-8E39-CEA6384B33AD}.Release|x86.Build.0 = Release|Any CPU + {DCD64A1A-8BE9-4475-AE56-3BA44AB2ED2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DCD64A1A-8BE9-4475-AE56-3BA44AB2ED2A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DCD64A1A-8BE9-4475-AE56-3BA44AB2ED2A}.Debug|x64.ActiveCfg = Debug|Any CPU + {DCD64A1A-8BE9-4475-AE56-3BA44AB2ED2A}.Debug|x64.Build.0 = Debug|Any CPU + {DCD64A1A-8BE9-4475-AE56-3BA44AB2ED2A}.Debug|x86.ActiveCfg = Debug|Any CPU + {DCD64A1A-8BE9-4475-AE56-3BA44AB2ED2A}.Debug|x86.Build.0 = Debug|Any CPU + {DCD64A1A-8BE9-4475-AE56-3BA44AB2ED2A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DCD64A1A-8BE9-4475-AE56-3BA44AB2ED2A}.Release|Any CPU.Build.0 = Release|Any CPU + {DCD64A1A-8BE9-4475-AE56-3BA44AB2ED2A}.Release|x64.ActiveCfg = Release|Any CPU + {DCD64A1A-8BE9-4475-AE56-3BA44AB2ED2A}.Release|x64.Build.0 = Release|Any CPU + {DCD64A1A-8BE9-4475-AE56-3BA44AB2ED2A}.Release|x86.ActiveCfg = Release|Any CPU + {DCD64A1A-8BE9-4475-AE56-3BA44AB2ED2A}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {91E885C2-56D5-41E4-AA91-015650029ECA} + EndGlobalSection +EndGlobal diff --git a/Documentation/Examples/StandaloneUsage/nuget.config b/Documentation/Examples/StandaloneUsage/nuget.config new file mode 100644 index 000000000..168cadce8 --- /dev/null +++ b/Documentation/Examples/StandaloneUsage/nuget.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Documentation/Examples/StandaloneUsage/run_app.cmd b/Documentation/Examples/StandaloneUsage/run_app.cmd new file mode 100644 index 000000000..3207f5e71 --- /dev/null +++ b/Documentation/Examples/StandaloneUsage/run_app.cmd @@ -0,0 +1 @@ +dotnet Calculator/bin/Debug/netcoreapp2.2/Calculator.dll instrumentationResult \ No newline at end of file diff --git a/Documentation/Examples/StandaloneUsage/run_instrumentor.cmd b/Documentation/Examples/StandaloneUsage/run_instrumentor.cmd new file mode 100644 index 000000000..f1ada3f9d --- /dev/null +++ b/Documentation/Examples/StandaloneUsage/run_instrumentor.cmd @@ -0,0 +1,2 @@ +dotnet build /p:coverletCoreVersion=1.0.2-g1df3e82a5b +dotnet Instrumentor/bin/Debug/netcoreapp2.2/Instrumentor.dll Calculator/bin/Debug/netcoreapp2.2/Calculator.dll \ No newline at end of file diff --git a/coverlet.sln b/coverlet.sln index c4975b7a9..c4d33a965 100644 --- a/coverlet.sln +++ b/coverlet.sln @@ -41,7 +41,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution nuget.config = nuget.config EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "coverlet.tests.projectsample.excludedbyattribute", "test\coverlet.tests.projectsample.excludedbyattribute\coverlet.tests.projectsample.excludedbyattribute.csproj", "{D6B14F2F-9E7D-4D2C-BAC8-48834F853ED6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "coverlet.tests.projectsample.excludedbyattribute", "test\coverlet.tests.projectsample.excludedbyattribute\coverlet.tests.projectsample.excludedbyattribute.csproj", "{D6B14F2F-9E7D-4D2C-BAC8-48834F853ED6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "coverlet.core.standalone.tests", "test\coverlet.core.standalone.tests\coverlet.core.standalone.tests.csproj", "{D324E73F-69DB-41BA-BF54-A79FD292114C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "coverlet.core.standalone.sample", "test\coverlet.core.standalone.sample\coverlet.core.standalone.sample.csproj", "{F1617303-0F38-4D98-9BFA-370B57F3A154}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -93,6 +97,14 @@ Global {D6B14F2F-9E7D-4D2C-BAC8-48834F853ED6}.Debug|Any CPU.Build.0 = Debug|Any CPU {D6B14F2F-9E7D-4D2C-BAC8-48834F853ED6}.Release|Any CPU.ActiveCfg = Release|Any CPU {D6B14F2F-9E7D-4D2C-BAC8-48834F853ED6}.Release|Any CPU.Build.0 = Release|Any CPU + {D324E73F-69DB-41BA-BF54-A79FD292114C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D324E73F-69DB-41BA-BF54-A79FD292114C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D324E73F-69DB-41BA-BF54-A79FD292114C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D324E73F-69DB-41BA-BF54-A79FD292114C}.Release|Any CPU.Build.0 = Release|Any CPU + {F1617303-0F38-4D98-9BFA-370B57F3A154}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1617303-0F38-4D98-9BFA-370B57F3A154}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1617303-0F38-4D98-9BFA-370B57F3A154}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1617303-0F38-4D98-9BFA-370B57F3A154}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -109,6 +121,8 @@ Global {3E0F9E47-A1D7-4DF5-841D-A633486E2475} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134} {085A3AFB-C086-4E98-86F1-1B481446EC5E} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134} {D6B14F2F-9E7D-4D2C-BAC8-48834F853ED6} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134} + {D324E73F-69DB-41BA-BF54-A79FD292114C} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134} + {F1617303-0F38-4D98-9BFA-370B57F3A154} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {9CA57C02-97B0-4C38-A027-EA61E8741F10} diff --git a/src/coverlet.collector/DataCollection/CoverageManager.cs b/src/coverlet.collector/DataCollection/CoverageManager.cs index 5dd59e2f6..a46f47452 100644 --- a/src/coverlet.collector/DataCollection/CoverageManager.cs +++ b/src/coverlet.collector/DataCollection/CoverageManager.cs @@ -2,12 +2,13 @@ using System.Collections.Generic; using System.IO; using System.Linq; + using coverlet.collector.Resources; using Coverlet.Collector.Utilities; using Coverlet.Collector.Utilities.Interfaces; using Coverlet.Core; using Coverlet.Core.Abstracts; -using Coverlet.Core.Reporters; +using Coverlet.Core.ObjectModel; namespace Coverlet.Collector.DataCollection { diff --git a/src/coverlet.collector/DataCollection/CoverageWrapper.cs b/src/coverlet.collector/DataCollection/CoverageWrapper.cs index 990274af3..e7dd800f8 100644 --- a/src/coverlet.collector/DataCollection/CoverageWrapper.cs +++ b/src/coverlet.collector/DataCollection/CoverageWrapper.cs @@ -2,6 +2,7 @@ using Coverlet.Core; using Coverlet.Core.Abstracts; using Coverlet.Core.Extensions; +using Coverlet.Core.ObjectModel; namespace Coverlet.Collector.DataCollection { diff --git a/src/coverlet.collector/Utilities/Interfaces/ICoverageWrapper.cs b/src/coverlet.collector/Utilities/Interfaces/ICoverageWrapper.cs index 59cab7c04..d24f6dea8 100644 --- a/src/coverlet.collector/Utilities/Interfaces/ICoverageWrapper.cs +++ b/src/coverlet.collector/Utilities/Interfaces/ICoverageWrapper.cs @@ -1,6 +1,7 @@ using Coverlet.Collector.DataCollection; using Coverlet.Core; using Coverlet.Core.Abstracts; +using Coverlet.Core.ObjectModel; namespace Coverlet.Collector.Utilities.Interfaces { diff --git a/src/coverlet.console/Program.cs b/src/coverlet.console/Program.cs index 608786fcb..628e11d3d 100644 --- a/src/coverlet.console/Program.cs +++ b/src/coverlet.console/Program.cs @@ -11,7 +11,7 @@ using Coverlet.Core.Abstracts; using Coverlet.Core.Enums; using Coverlet.Core.Extensions; -using Coverlet.Core.Reporters; +using Coverlet.Core.ObjectModel; using McMaster.Extensions.CommandLineUtils; namespace Coverlet.Console diff --git a/src/coverlet.core/Abstracts/IInstrumentationHelper.cs b/src/coverlet.core/Abstracts/IInstrumentationHelper.cs index 42bab81f3..e3b17e473 100644 --- a/src/coverlet.core/Abstracts/IInstrumentationHelper.cs +++ b/src/coverlet.core/Abstracts/IInstrumentationHelper.cs @@ -3,7 +3,7 @@ internal interface IInstrumentationHelper { void BackupOriginalModule(string module, string identifier); - void DeleteHitsFile(string path); + bool DeleteHitsFile(string path); string[] GetCoverableModules(string module, string[] directories, bool includeTestAssembly); bool HasPdb(string module, out bool embedded); bool IsModuleExcluded(string module, string[] excludeFilters); diff --git a/src/coverlet.core/Abstracts/IInstrumenter.cs b/src/coverlet.core/Abstracts/IInstrumenter.cs new file mode 100644 index 000000000..470d4aa43 --- /dev/null +++ b/src/coverlet.core/Abstracts/IInstrumenter.cs @@ -0,0 +1,42 @@ +#nullable enable + +using System.IO; +using System.Reflection; + +using Coverlet.Core.ObjectModel; + +namespace Coverlet.Core.Abstracts +{ + public class InstrumentationOptions + { + public string? Module { get; set; } + public string[]? IncludeFilters { get; set; } + public string[]? ExcludeFilters { get; set; } + public string[]? ExcludeSourceFiles { get; set; } + public string[]? ExcludeAttributes { get; set; } + public string[]? IncludeDirectories { get; set; } + public bool IncludeTestAssembly { get; set; } + public bool SingleHit { get; set; } + public bool UseSourceLink { get; set; } + public string? MergeWith { get; set; } + } + + public interface ICoverageEngineFactory + { + ICoverageEngine CreateEngine(InstrumentationOptions options); + IReporter CreateReporter(string format); + IInProcessCoverageEngine CreateInProcessEngine(Stream instrumentationResultStream); + } + + public interface ICoverageEngine + { + Stream PrepareModules(); + CoverageResult GetCoverageResult(Stream instrumentationResultStream); + } + + public interface IInProcessCoverageEngine + { + Assembly[] GetInstrumentedAssemblies(); + CoverageResult? ReadCurrentCoverage(); + } +} diff --git a/src/coverlet.core/Abstracts/IReporter.cs b/src/coverlet.core/Abstracts/IReporter.cs new file mode 100644 index 000000000..09096c15b --- /dev/null +++ b/src/coverlet.core/Abstracts/IReporter.cs @@ -0,0 +1,32 @@ +using Coverlet.Core.ObjectModel; + +namespace Coverlet.Core.Abstracts +{ + public static class Reporters + { + public readonly static string Cobertura = "cobertura"; + public readonly static string Json = "json"; + public readonly static string Lcov = "lcov"; + public readonly static string OpenCover = "opencover"; + public readonly static string TeamCity = "teamcity"; + } + + internal interface IReporterFactory + { + IReporter Create(string format); + } + + public interface IReporter + { + ReporterOutputType OutputType { get; } + string Format { get; } + string Extension { get; } + string Report(CoverageResult result); + } + + public enum ReporterOutputType + { + File, + Console + } +} \ No newline at end of file diff --git a/src/coverlet.core/Coverage.cs b/src/coverlet.core/Coverage.cs index 13779e2ff..7ce12fcf5 100644 --- a/src/coverlet.core/Coverage.cs +++ b/src/coverlet.core/Coverage.cs @@ -2,9 +2,10 @@ using System.Collections.Generic; using System.IO; using System.Linq; + using Coverlet.Core.Abstracts; using Coverlet.Core.Instrumentation; - +using Coverlet.Core.ObjectModel; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -132,10 +133,15 @@ public CoveragePrepareResult PrepareModules() public CoverageResult GetCoverageResult() { - CalculateCoverage(); + return GetCoverageResult(_results, _useSourceLink, _logger, _fileSystem, _instrumentationHelper, _identifier, _mergeWith); + } + + public static CoverageResult GetCoverageResult(IEnumerable results, bool useSourceLink, ILogger logger, IFileSystem fileSystem, IInstrumentationHelper instrumentationHelper, string identifier, string mergeWith) + { + CalculateCoverage(results, useSourceLink, logger, fileSystem, instrumentationHelper); Modules modules = new Modules(); - foreach (var result in _results) + foreach (var result in results) { Documents documents = new Documents(); foreach (var doc in result.Documents.Values) @@ -216,7 +222,7 @@ public CoverageResult GetCoverageResult() } modules.Add(Path.GetFileName(result.ModulePath), documents); - _instrumentationHelper.RestoreOriginalModule(result.ModulePath, _identifier); + instrumentationHelper.RestoreOriginalModule(result.ModulePath, identifier); } // In case of anonymous delegate compiler generate a custom class and passes it as type.method delegate. @@ -234,7 +240,7 @@ public CoverageResult GetCoverageResult() { foreach (var branch in method.Value.Branches) { - if (BranchInCompilerGeneratedClass(method.Key)) + if (BranchInCompilerGeneratedClass(method.Key, results)) { Method actualMethod = GetMethodWithSameLineInSameDocument(document.Value, @class.Key, branch.Line); @@ -276,20 +282,20 @@ public CoverageResult GetCoverageResult() } } - var coverageResult = new CoverageResult { Identifier = _identifier, Modules = modules, InstrumentedResults = _results }; + var coverageResult = new CoverageResult { Identifier = identifier, Modules = modules, InstrumentedResults = results.ToList() }; - if (!string.IsNullOrEmpty(_mergeWith) && !string.IsNullOrWhiteSpace(_mergeWith) && _fileSystem.Exists(_mergeWith)) + if (!string.IsNullOrEmpty(mergeWith) && !string.IsNullOrWhiteSpace(mergeWith) && fileSystem.Exists(mergeWith)) { - string json = _fileSystem.ReadAllText(_mergeWith); + string json = fileSystem.ReadAllText(mergeWith); coverageResult.Merge(JsonConvert.DeserializeObject(json)); } return coverageResult; } - private bool BranchInCompilerGeneratedClass(string methodName) + private static bool BranchInCompilerGeneratedClass(string methodName, IEnumerable results) { - foreach (var instrumentedResult in _results) + foreach (var instrumentedResult in results) { if (instrumentedResult.BranchesInCompiledGeneratedClass.Contains(methodName)) { @@ -299,7 +305,7 @@ private bool BranchInCompilerGeneratedClass(string methodName) return false; } - private Method GetMethodWithSameLineInSameDocument(Classes documentClasses, string compilerGeneratedClassName, int branchLine) + private static Method GetMethodWithSameLineInSameDocument(Classes documentClasses, string compilerGeneratedClassName, int branchLine) { foreach (var @class in documentClasses) { @@ -322,22 +328,22 @@ private Method GetMethodWithSameLineInSameDocument(Classes documentClasses, stri return null; } - private void CalculateCoverage() + private static void CalculateCoverage(IEnumerable results, bool useSourceLink, ILogger logger, IFileSystem fileSystem, IInstrumentationHelper instrumentationHelper) { - foreach (var result in _results) + foreach (var result in results) { - if (!_fileSystem.Exists(result.HitsFilePath)) + if (!fileSystem.Exists(result.HitsFilePath)) { // Hits file could be missed mainly for two reason // 1) Issue during module Unload() // 2) Instrumented module is never loaded or used so we don't have any hit to register and // module tracker is never used - _logger.LogVerbose($"Hits file:'{result.HitsFilePath}' not found for module: '{result.Module}'"); + logger.LogVerbose($"Hits file:'{result.HitsFilePath}' not found for module: '{result.Module}'"); continue; } List documents = result.Documents.Values.ToList(); - if (_useSourceLink && result.SourceLink != null) + if (useSourceLink && result.SourceLink != null) { var jObject = JObject.Parse(result.SourceLink)["documents"]; var sourceLinkDocuments = JsonConvert.DeserializeObject>(jObject.ToString()); @@ -349,7 +355,7 @@ private void CalculateCoverage() List<(int docIndex, int line)> zeroHitsLines = new List<(int docIndex, int line)>(); var documentsList = result.Documents.Values.ToList(); - using (var fs = _fileSystem.NewFileStream(result.HitsFilePath, FileMode.Open)) + using (var fs = fileSystem.NewFileStream(result.HitsFilePath, FileMode.Open)) using (var br = new BinaryReader(fs)) { int hitCandidatesCount = br.ReadInt32(); @@ -396,12 +402,14 @@ private void CalculateCoverage() } } - _instrumentationHelper.DeleteHitsFile(result.HitsFilePath); - _logger.LogVerbose($"Hit file '{result.HitsFilePath}' deleted"); + if (instrumentationHelper.DeleteHitsFile(result.HitsFilePath)) + { + logger.LogVerbose($"Hit file '{result.HitsFilePath}' deleted"); + } } } - private string GetSourceLinkUrl(Dictionary sourceLinkDocuments, string document) + private static string GetSourceLinkUrl(Dictionary sourceLinkDocuments, string document) { if (sourceLinkDocuments.TryGetValue(document, out string url)) { diff --git a/src/coverlet.core/CoverageDetails.cs b/src/coverlet.core/CoverageDetails.cs deleted file mode 100644 index 69d20f54c..000000000 --- a/src/coverlet.core/CoverageDetails.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace Coverlet.Core -{ - internal class CoverageDetails - { - private double _averageModulePercent; - public double Covered { get; internal set; } - public int Total { get; internal set; } - public double AverageModulePercent - { - get { return Math.Floor(_averageModulePercent * 100) / 100; } - internal set { _averageModulePercent = value; } - } - - public double Percent => Total == 0 ? 100D : Math.Floor((Covered / Total) * 10000) / 100; - } -} \ No newline at end of file diff --git a/src/coverlet.core/CoverageResult.cs b/src/coverlet.core/CoverageResult.cs deleted file mode 100644 index 33fca874f..000000000 --- a/src/coverlet.core/CoverageResult.cs +++ /dev/null @@ -1,201 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Coverlet.Core.Enums; -using Coverlet.Core.Instrumentation; -using Coverlet.Core.Symbols; - -namespace Coverlet.Core -{ - internal class BranchInfo - { - public int Line { get; set; } - public int Offset { get; set; } - public int EndOffset { get; set; } - public int Path { get; set; } - public uint Ordinal { get; set; } - public int Hits { get; set; } - } - - internal class Lines : SortedDictionary { } - - internal class Branches : List { } - - internal class Method - { - internal Method() - { - Lines = new Lines(); - Branches = new Branches(); - } - public Lines Lines; - public Branches Branches; - } - internal class Methods : Dictionary { } - internal class Classes : Dictionary { } - internal class Documents : Dictionary { } - internal class Modules : Dictionary { } - - internal class CoverageResult - { - public string Identifier; - public Modules Modules; - internal List InstrumentedResults; - - internal CoverageResult() { } - - internal void Merge(Modules modules) - { - foreach (var module in modules) - { - if (!this.Modules.Keys.Contains(module.Key)) - { - this.Modules.Add(module.Key, module.Value); - } - else - { - foreach (var document in module.Value) - { - if (!this.Modules[module.Key].ContainsKey(document.Key)) - { - this.Modules[module.Key].Add(document.Key, document.Value); - } - else - { - foreach (var @class in document.Value) - { - if (!this.Modules[module.Key][document.Key].ContainsKey(@class.Key)) - { - this.Modules[module.Key][document.Key].Add(@class.Key, @class.Value); - } - else - { - foreach (var method in @class.Value) - { - if (!this.Modules[module.Key][document.Key][@class.Key].ContainsKey(method.Key)) - { - this.Modules[module.Key][document.Key][@class.Key].Add(method.Key, method.Value); - } - else - { - foreach (var line in method.Value.Lines) - { - if (!this.Modules[module.Key][document.Key][@class.Key][method.Key].Lines.ContainsKey(line.Key)) - { - this.Modules[module.Key][document.Key][@class.Key][method.Key].Lines.Add(line.Key, line.Value); - } - else - { - this.Modules[module.Key][document.Key][@class.Key][method.Key].Lines[line.Key] += line.Value; - } - } - - foreach (var branch in method.Value.Branches) - { - var branches = this.Modules[module.Key][document.Key][@class.Key][method.Key].Branches; - var branchInfo = branches.FirstOrDefault(b => b.EndOffset == branch.EndOffset && b.Line == branch.Line && b.Offset == branch.Offset && b.Ordinal == branch.Ordinal && b.Path == branch.Path); - if (branchInfo == null) - branches.Add(branch); - else - branchInfo.Hits += branch.Hits; - } - } - } - } - } - } - } - } - } - } - - public ThresholdTypeFlags GetThresholdTypesBelowThreshold(CoverageSummary summary, double threshold, ThresholdTypeFlags thresholdTypes, ThresholdStatistic thresholdStat) - { - var thresholdTypeFlags = ThresholdTypeFlags.None; - switch (thresholdStat) - { - case ThresholdStatistic.Minimum: - { - foreach (var module in Modules) - { - double line = summary.CalculateLineCoverage(module.Value).Percent; - double branch = summary.CalculateBranchCoverage(module.Value).Percent; - double method = summary.CalculateMethodCoverage(module.Value).Percent; - - if ((thresholdTypes & ThresholdTypeFlags.Line) != ThresholdTypeFlags.None) - { - if (line < threshold) - thresholdTypeFlags |= ThresholdTypeFlags.Line; - } - - if ((thresholdTypes & ThresholdTypeFlags.Branch) != ThresholdTypeFlags.None) - { - if (branch < threshold) - thresholdTypeFlags |= ThresholdTypeFlags.Branch; - } - - if ((thresholdTypes & ThresholdTypeFlags.Method) != ThresholdTypeFlags.None) - { - if (method < threshold) - thresholdTypeFlags |= ThresholdTypeFlags.Method; - } - } - } - break; - case ThresholdStatistic.Average: - { - double line = summary.CalculateLineCoverage(Modules).AverageModulePercent; - double branch = summary.CalculateBranchCoverage(Modules).AverageModulePercent; - double method = summary.CalculateMethodCoverage(Modules).AverageModulePercent; - - if ((thresholdTypes & ThresholdTypeFlags.Line) != ThresholdTypeFlags.None) - { - if (line < threshold) - thresholdTypeFlags |= ThresholdTypeFlags.Line; - } - - if ((thresholdTypes & ThresholdTypeFlags.Branch) != ThresholdTypeFlags.None) - { - if (branch < threshold) - thresholdTypeFlags |= ThresholdTypeFlags.Branch; - } - - if ((thresholdTypes & ThresholdTypeFlags.Method) != ThresholdTypeFlags.None) - { - if (method < threshold) - thresholdTypeFlags |= ThresholdTypeFlags.Method; - } - } - break; - case ThresholdStatistic.Total: - { - double line = summary.CalculateLineCoverage(Modules).Percent; - double branch = summary.CalculateBranchCoverage(Modules).Percent; - double method = summary.CalculateMethodCoverage(Modules).Percent; - - if ((thresholdTypes & ThresholdTypeFlags.Line) != ThresholdTypeFlags.None) - { - if (line < threshold) - thresholdTypeFlags |= ThresholdTypeFlags.Line; - } - - if ((thresholdTypes & ThresholdTypeFlags.Branch) != ThresholdTypeFlags.None) - { - if (branch < threshold) - thresholdTypeFlags |= ThresholdTypeFlags.Branch; - } - - if ((thresholdTypes & ThresholdTypeFlags.Method) != ThresholdTypeFlags.None) - { - if (method < threshold) - thresholdTypeFlags |= ThresholdTypeFlags.Method; - } - } - break; - } - - return thresholdTypeFlags; - } - } -} \ No newline at end of file diff --git a/src/coverlet.core/CoverageSummary.cs b/src/coverlet.core/CoverageSummary.cs deleted file mode 100644 index 5a64e0b93..000000000 --- a/src/coverlet.core/CoverageSummary.cs +++ /dev/null @@ -1,227 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Coverlet.Core -{ - internal class CoverageSummary - { - public CoverageDetails CalculateLineCoverage(Lines lines) - { - var details = new CoverageDetails(); - details.Covered = lines.Where(l => l.Value > 0).Count(); - details.Total = lines.Count; - return details; - } - - public CoverageDetails CalculateLineCoverage(Methods methods) - { - var details = new CoverageDetails(); - foreach (var method in methods) - { - var methodCoverage = CalculateLineCoverage(method.Value.Lines); - details.Covered += methodCoverage.Covered; - details.Total += methodCoverage.Total; - } - return details; - } - - public CoverageDetails CalculateLineCoverage(Classes classes) - { - var details = new CoverageDetails(); - foreach (var @class in classes) - { - var classCoverage = CalculateLineCoverage(@class.Value); - details.Covered += classCoverage.Covered; - details.Total += classCoverage.Total; - } - return details; - } - - public CoverageDetails CalculateLineCoverage(Documents documents) - { - var details = new CoverageDetails(); - foreach (var document in documents) - { - var documentCoverage = CalculateLineCoverage(document.Value); - details.Covered += documentCoverage.Covered; - details.Total += documentCoverage.Total; - } - return details; - } - - public CoverageDetails CalculateLineCoverage(Modules modules) - { - var details = new CoverageDetails(); - var accumPercent = 0.0D; - foreach (var module in modules) - { - var moduleCoverage = CalculateLineCoverage(module.Value); - details.Covered += moduleCoverage.Covered; - details.Total += moduleCoverage.Total; - accumPercent += moduleCoverage.Percent; - } - details.AverageModulePercent = accumPercent / modules.Count; - return details; - } - - public CoverageDetails CalculateBranchCoverage(IList branches) - { - var details = new CoverageDetails(); - details.Covered = branches.Count(bi => bi.Hits > 0); - details.Total = branches.Count; - return details; - } - - public int CalculateCyclomaticComplexity(IList branches) - { - return Math.Max(1, branches.Count); - } - - public int CalculateCyclomaticComplexity(Methods methods) - { - return methods.Values.Select(m => CalculateCyclomaticComplexity(m.Branches)).Sum(); - } - - public int CalculateMaxCyclomaticComplexity(Methods methods) - { - return methods.Values.Select(m => CalculateCyclomaticComplexity(m.Branches)).DefaultIfEmpty(1).Max(); - } - - public int CalculateMinCyclomaticComplexity(Methods methods) - { - return methods.Values.Select(m => CalculateCyclomaticComplexity(m.Branches)).DefaultIfEmpty(1).Min(); - } - - public int CalculateCyclomaticComplexity(Modules modules) - { - return modules.Values.Select(CalculateCyclomaticComplexity).Sum(); - } - - public int CalculateMaxCyclomaticComplexity(Modules modules) - { - return modules.Values.Select(CalculateCyclomaticComplexity).DefaultIfEmpty(1).Max(); - } - - public int CalculateMinCyclomaticComplexity(Modules modules) - { - return modules.Values.Select(CalculateCyclomaticComplexity).DefaultIfEmpty(1).Min(); - } - - public int CalculateCyclomaticComplexity(Documents documents) - { - return documents.Values.SelectMany(c => c.Values.Select(CalculateCyclomaticComplexity)).Sum(); - } - - public CoverageDetails CalculateBranchCoverage(Methods methods) - { - var details = new CoverageDetails(); - foreach (var method in methods) - { - var methodCoverage = CalculateBranchCoverage(method.Value.Branches); - details.Covered += methodCoverage.Covered; - details.Total += methodCoverage.Total; - } - return details; - } - - public CoverageDetails CalculateBranchCoverage(Classes classes) - { - var details = new CoverageDetails(); - foreach (var @class in classes) - { - var classCoverage = CalculateBranchCoverage(@class.Value); - details.Covered += classCoverage.Covered; - details.Total += classCoverage.Total; - } - return details; - } - - public CoverageDetails CalculateBranchCoverage(Documents documents) - { - var details = new CoverageDetails(); - foreach (var document in documents) - { - var documentCoverage = CalculateBranchCoverage(document.Value); - details.Covered += documentCoverage.Covered; - details.Total += documentCoverage.Total; - } - return details; - } - - public CoverageDetails CalculateBranchCoverage(Modules modules) - { - var details = new CoverageDetails(); - var accumPercent = 0.0D; - foreach (var module in modules) - { - var moduleCoverage = CalculateBranchCoverage(module.Value); - details.Covered += moduleCoverage.Covered; - details.Total += moduleCoverage.Total; - accumPercent += moduleCoverage.Percent; - } - details.AverageModulePercent = accumPercent / modules.Count; - return details; - } - - public CoverageDetails CalculateMethodCoverage(Lines lines) - { - var details = new CoverageDetails(); - details.Covered = lines.Any(l => l.Value > 0) ? 1 : 0; - details.Total = 1; - return details; - } - - public CoverageDetails CalculateMethodCoverage(Methods methods) - { - var details = new CoverageDetails(); - var methodsWithLines = methods.Where(m => m.Value.Lines.Count > 0); - foreach (var method in methodsWithLines) - { - var methodCoverage = CalculateMethodCoverage(method.Value.Lines); - details.Covered += methodCoverage.Covered; - } - details.Total = methodsWithLines.Count(); - return details; - } - - public CoverageDetails CalculateMethodCoverage(Classes classes) - { - var details = new CoverageDetails(); - foreach (var @class in classes) - { - var classCoverage = CalculateMethodCoverage(@class.Value); - details.Covered += classCoverage.Covered; - details.Total += classCoverage.Total; - } - return details; - } - - public CoverageDetails CalculateMethodCoverage(Documents documents) - { - var details = new CoverageDetails(); - foreach (var document in documents) - { - var documentCoverage = CalculateMethodCoverage(document.Value); - details.Covered += documentCoverage.Covered; - details.Total += documentCoverage.Total; - } - return details; - } - - public CoverageDetails CalculateMethodCoverage(Modules modules) - { - var details = new CoverageDetails(); - var accumPercent = 0.0D; - foreach (var module in modules) - { - var moduleCoverage = CalculateMethodCoverage(module.Value); - details.Covered += moduleCoverage.Covered; - details.Total += moduleCoverage.Total; - accumPercent += moduleCoverage.Percent; - } - details.AverageModulePercent = accumPercent / modules.Count; - return details; - } - } -} \ No newline at end of file diff --git a/src/coverlet.core/Enums/ThresholdStatistic.cs b/src/coverlet.core/Enums/ThresholdStatistic.cs index 9b7dd18ba..1bafe3dd8 100644 --- a/src/coverlet.core/Enums/ThresholdStatistic.cs +++ b/src/coverlet.core/Enums/ThresholdStatistic.cs @@ -1,6 +1,6 @@ namespace Coverlet.Core.Enums { - internal enum ThresholdStatistic + public enum ThresholdStatistic { Minimum, Average, diff --git a/src/coverlet.core/Enums/ThresholdTypeFlags.cs b/src/coverlet.core/Enums/ThresholdTypeFlags.cs index 11a082178..fbc719186 100644 --- a/src/coverlet.core/Enums/ThresholdTypeFlags.cs +++ b/src/coverlet.core/Enums/ThresholdTypeFlags.cs @@ -3,7 +3,7 @@ namespace Coverlet.Core.Enums { [Flags] - internal enum ThresholdTypeFlags + public enum ThresholdTypeFlags { None = 0, Line = 2, diff --git a/src/coverlet.core/Helpers/InstrumentationHelper.cs b/src/coverlet.core/Helpers/InstrumentationHelper.cs index 09b6a31fd..77622c4a5 100644 --- a/src/coverlet.core/Helpers/InstrumentationHelper.cs +++ b/src/coverlet.core/Helpers/InstrumentationHelper.cs @@ -245,12 +245,13 @@ public virtual void RestoreOriginalModules() } } - public void DeleteHitsFile(string path) + public bool DeleteHitsFile(string path) { // Retry hitting the hits file - retry up to 10 times, since the file could be locked // See: https://github.com/tonerdo/coverlet/issues/25 var retryStrategy = CreateRetryStrategy(); _retryHelper.Retry(() => _fileSystem.Delete(path), retryStrategy, 10); + return true; } public bool IsValidFilterExpression(string filter) diff --git a/src/coverlet.core/Instrumentation/CoverageEngine.cs b/src/coverlet.core/Instrumentation/CoverageEngine.cs new file mode 100644 index 000000000..17115c696 --- /dev/null +++ b/src/coverlet.core/Instrumentation/CoverageEngine.cs @@ -0,0 +1,340 @@ +#nullable enable + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using Coverlet.Core.Abstracts; +using Coverlet.Core.Helpers; +using Coverlet.Core.ObjectModel; +using Microsoft.Extensions.DependencyInjection; + +namespace Coverlet.Core.Instrumentation +{ + public class BuildInCoverageEngineFactory : ICoverageEngineFactory + { + private readonly IServiceProvider _serviceProvider; + + public BuildInCoverageEngineFactory() + { + _serviceProvider = GetServiceProvider(); + } + + protected virtual IServiceProvider GetServiceProvider() + { + IServiceCollection serviceCollection = new ServiceCollection(); + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + // We need to keep singleton/static semantics + serviceCollection.AddSingleton(); + + return serviceCollection.BuildServiceProvider(); + } + + public ICoverageEngine CreateEngine(InstrumentationOptions options) + { + return new CoverageEngine(options, _serviceProvider); + } + + public IReporter CreateReporter(string format) + { + return _serviceProvider.GetService().Create(format); + } + + public IInProcessCoverageEngine CreateInProcessEngine(Stream instrumentationResultStream) + { + return new InProcessCoverageEngine(instrumentationResultStream); + } + } + + class CoverageEngine : ICoverageEngine + { + private readonly InstrumentationOptions _options; + private readonly IServiceProvider _serviceProvider; + + public CoverageEngine(InstrumentationOptions? options, IServiceProvider? serviceProvider) + { + _options = options ?? throw new ArgumentNullException(nameof(options)); + _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + } + + public CoverageResult GetCoverageResult(Stream stream) + { + Coverage coverage = new Coverage( + CoveragePrepareResult.Deserialize(stream), + _serviceProvider.GetService(), + _serviceProvider.GetService(), + _serviceProvider.GetService()); + + return coverage.GetCoverageResult(); + } + + public Stream PrepareModules() + { + if (string.IsNullOrEmpty(_options.Module)) + { + throw new ArgumentException("Module cannot be empty"); + } + + if (!File.Exists(_options.Module)) + { + throw new FileNotFoundException($"Invalid module '{_options.Module}'"); + } + + Coverage coverage = new Coverage( + _options.Module, + _options.IncludeFilters, + _options.IncludeDirectories, + _options.ExcludeFilters, + _options.ExcludeSourceFiles, + _options.ExcludeAttributes, + _options.IncludeTestAssembly, + _options.SingleHit, + _options.MergeWith, + _options.UseSourceLink, + _serviceProvider.GetService(), + _serviceProvider.GetService(), + _serviceProvider.GetService()); + + CoveragePrepareResult result = coverage.PrepareModules(); + + if (result.Results.Length == 0) + { + throw new InvalidOperationException("No module instrumented"); + } + + return CoveragePrepareResult.Serialize(result); + } + } + + class InProcessCoverageEngine : IInProcessCoverageEngine + { + private readonly Stream _instrumentationResultStream; + + public InProcessCoverageEngine(Stream instrumentationResultStream) => _instrumentationResultStream = instrumentationResultStream; + + public Assembly[] GetInstrumentedAssemblies() + { + HashSet instrumentedAssemblies = new HashSet(); + foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + foreach (Type type in assembly.GetTypes()) + { + if (type.Namespace == "Coverlet.Core.Instrumentation.Tracker" + && type.Name.StartsWith(assembly.GetName().Name + "_")) + { + instrumentedAssemblies.Add(assembly); + } + } + } + return instrumentedAssemblies.ToArray(); + } + + public CoverageResult? ReadCurrentCoverage() + { + CoveragePrepareResult prepareResult = CoveragePrepareResult.Deserialize(_instrumentationResultStream); + _instrumentationResultStream.Seek(0, SeekOrigin.Begin); + + Dictionary asmList = new Dictionary(); + foreach (Assembly asm in GetInstrumentedAssemblies()) + { + asmList.Add(Path.GetFileNameWithoutExtension(asm.ManifestModule.ScopeName), asm); + } + + return Coverage.GetCoverageResult( + prepareResult.Results, + prepareResult.UseSourceLink, + new ConsoleLogger(), + new InProcessFileSystem(prepareResult, asmList), + new InProcessInstrumentationHelper(), + prepareResult.Identifier, + prepareResult.MergeWith); + } + + // InProcess custom services + + class InProcessFileSystem : IFileSystem + { + private readonly Dictionary _asmList; + private readonly CoveragePrepareResult _coveragePrepareResult; + + + public InProcessFileSystem(CoveragePrepareResult coveragePrepareResult, Dictionary asmList) => (_asmList, _coveragePrepareResult) = (asmList, coveragePrepareResult); + + public void Copy(string sourceFileName, string destFileName, bool overwrite) + { + throw new NotImplementedException(); + } + + public void Delete(string path) + { + throw new NotImplementedException(); + } + + public bool Exists(string path) + { + // File does't exists until end of process or until flush + return true; + } + + public Stream NewFileStream(string path, FileMode mode) + { + foreach (InstrumenterResult result in _coveragePrepareResult.Results) + { + if (result.HitsFilePath == path) + { + Assembly asm = _asmList[result.Module]; + foreach (Type type in asm.GetTypes()) + { + if (type.Namespace == "Coverlet.Core.Instrumentation.Tracker" + && type.Name.StartsWith(asm.GetName().Name + "_")) + { + + Debug.Assert((string)type.GetField("HitsFilePath").GetValue(null) == path); + + int[] hitsArray = (int[])type.GetField("HitsArray").GetValue(null); + MemoryStream ms = new MemoryStream(); + using BinaryWriter bw = new BinaryWriter(ms, Encoding.UTF8, true); + bw.Write(hitsArray.Length); + for (int i = 0; i < hitsArray.Length; i++) + { + bw.Write(hitsArray[i]); + } + ms.Seek(0, SeekOrigin.Begin); + return ms; + } + } + } + } + throw new InvalidOperationException($"Hits file '{path}' not found in results list"); + } + + public Stream NewFileStream(string path, FileMode mode, FileAccess access) + { + throw new NotImplementedException(); + } + + public Stream OpenRead(string path) + { + throw new NotImplementedException(); + } + + public string ReadAllText(string path) + { + throw new NotImplementedException(); + } + + public void WriteAllText(string path, string contents) + { + throw new NotImplementedException(); + } + } + + class InProcessInstrumentationHelper : IInstrumentationHelper + { + public void BackupOriginalModule(string module, string identifier) + { + throw new NotImplementedException(); + } + + public bool DeleteHitsFile(string path) + { + // In process we don't remove files + return false; + } + + public bool EmbeddedPortablePdbHasLocalSource(string module, out string firstNotFoundDocument) + { + throw new NotImplementedException(); + } + + public string[] GetCoverableModules(string module, string[] directories, bool includeTestAssembly) + { + throw new NotImplementedException(); + } + + public bool HasPdb(string module, out bool embedded) + { + throw new NotImplementedException(); + } + + public bool IsLocalMethod(string method) + { + throw new NotImplementedException(); + } + + public bool IsModuleExcluded(string module, string[] excludeFilters) + { + throw new NotImplementedException(); + } + + public bool IsModuleIncluded(string module, string[] includeFilters) + { + throw new NotImplementedException(); + } + + public bool IsTypeExcluded(string module, string type, string[] excludeFilters) + { + throw new NotImplementedException(); + } + + public bool IsTypeIncluded(string module, string type, string[] includeFilters) + { + throw new NotImplementedException(); + } + + public bool IsValidFilterExpression(string filter) + { + throw new NotImplementedException(); + } + + public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDocument) + { + throw new NotImplementedException(); + } + + public void RestoreOriginalModule(string module, string identifier) + { + // In process we don't restore nothing + } + } + } + + // Plain vanilla console logger + class ConsoleLogger : ILogger + { + public void LogError(string message) + { + Console.WriteLine($"[Error] {message}"); + } + + public void LogError(Exception exception) + { + Console.WriteLine($"[Error] {exception.ToString()}"); + } + + public void LogInformation(string message, bool important = false) + { + Console.WriteLine($"[LogInformation] {message}"); + } + + public void LogVerbose(string message) + { + Console.WriteLine($"[LogVerbose] {message}"); + } + + public void LogWarning(string message) + { + Console.WriteLine($"[LogWarning] {message}"); + } + } +} + diff --git a/src/coverlet.core/ObjectModel.cs b/src/coverlet.core/ObjectModel.cs new file mode 100644 index 000000000..d580d76ec --- /dev/null +++ b/src/coverlet.core/ObjectModel.cs @@ -0,0 +1,435 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using Coverlet.Core.Enums; +using Coverlet.Core.Instrumentation; + +namespace Coverlet.Core.ObjectModel +{ + public class BranchInfo + { + public int Line { get; set; } + public int Offset { get; set; } + public int EndOffset { get; set; } + public int Path { get; set; } + public uint Ordinal { get; set; } + public int Hits { get; set; } + } + + public class Lines : SortedDictionary { } + + public class Branches : List { } + + public class Method + { + internal Method() + { + Lines = new Lines(); + Branches = new Branches(); + } + public Lines Lines; + public Branches Branches; + } + public class Methods : Dictionary { } + public class Classes : Dictionary { } + public class Documents : Dictionary { } + public class Modules : Dictionary { } + + public class CoverageResult + { + public string Identifier; + public Modules Modules; + internal List InstrumentedResults; + + internal CoverageResult() { } + + internal void Merge(Modules modules) + { + foreach (var module in modules) + { + if (!this.Modules.Keys.Contains(module.Key)) + { + this.Modules.Add(module.Key, module.Value); + } + else + { + foreach (var document in module.Value) + { + if (!this.Modules[module.Key].ContainsKey(document.Key)) + { + this.Modules[module.Key].Add(document.Key, document.Value); + } + else + { + foreach (var @class in document.Value) + { + if (!this.Modules[module.Key][document.Key].ContainsKey(@class.Key)) + { + this.Modules[module.Key][document.Key].Add(@class.Key, @class.Value); + } + else + { + foreach (var method in @class.Value) + { + if (!this.Modules[module.Key][document.Key][@class.Key].ContainsKey(method.Key)) + { + this.Modules[module.Key][document.Key][@class.Key].Add(method.Key, method.Value); + } + else + { + foreach (var line in method.Value.Lines) + { + if (!this.Modules[module.Key][document.Key][@class.Key][method.Key].Lines.ContainsKey(line.Key)) + { + this.Modules[module.Key][document.Key][@class.Key][method.Key].Lines.Add(line.Key, line.Value); + } + else + { + this.Modules[module.Key][document.Key][@class.Key][method.Key].Lines[line.Key] += line.Value; + } + } + + foreach (var branch in method.Value.Branches) + { + var branches = this.Modules[module.Key][document.Key][@class.Key][method.Key].Branches; + var branchInfo = branches.FirstOrDefault(b => b.EndOffset == branch.EndOffset && b.Line == branch.Line && b.Offset == branch.Offset && b.Ordinal == branch.Ordinal && b.Path == branch.Path); + if (branchInfo == null) + branches.Add(branch); + else + branchInfo.Hits += branch.Hits; + } + } + } + } + } + } + } + } + } + } + + public ThresholdTypeFlags GetThresholdTypesBelowThreshold(CoverageSummary summary, double threshold, ThresholdTypeFlags thresholdTypes, ThresholdStatistic thresholdStat) + { + var thresholdTypeFlags = ThresholdTypeFlags.None; + switch (thresholdStat) + { + case ThresholdStatistic.Minimum: + { + foreach (var module in Modules) + { + double line = summary.CalculateLineCoverage(module.Value).Percent; + double branch = summary.CalculateBranchCoverage(module.Value).Percent; + double method = summary.CalculateMethodCoverage(module.Value).Percent; + + if ((thresholdTypes & ThresholdTypeFlags.Line) != ThresholdTypeFlags.None) + { + if (line < threshold) + thresholdTypeFlags |= ThresholdTypeFlags.Line; + } + + if ((thresholdTypes & ThresholdTypeFlags.Branch) != ThresholdTypeFlags.None) + { + if (branch < threshold) + thresholdTypeFlags |= ThresholdTypeFlags.Branch; + } + + if ((thresholdTypes & ThresholdTypeFlags.Method) != ThresholdTypeFlags.None) + { + if (method < threshold) + thresholdTypeFlags |= ThresholdTypeFlags.Method; + } + } + } + break; + case ThresholdStatistic.Average: + { + double line = summary.CalculateLineCoverage(Modules).AverageModulePercent; + double branch = summary.CalculateBranchCoverage(Modules).AverageModulePercent; + double method = summary.CalculateMethodCoverage(Modules).AverageModulePercent; + + if ((thresholdTypes & ThresholdTypeFlags.Line) != ThresholdTypeFlags.None) + { + if (line < threshold) + thresholdTypeFlags |= ThresholdTypeFlags.Line; + } + + if ((thresholdTypes & ThresholdTypeFlags.Branch) != ThresholdTypeFlags.None) + { + if (branch < threshold) + thresholdTypeFlags |= ThresholdTypeFlags.Branch; + } + + if ((thresholdTypes & ThresholdTypeFlags.Method) != ThresholdTypeFlags.None) + { + if (method < threshold) + thresholdTypeFlags |= ThresholdTypeFlags.Method; + } + } + break; + case ThresholdStatistic.Total: + { + double line = summary.CalculateLineCoverage(Modules).Percent; + double branch = summary.CalculateBranchCoverage(Modules).Percent; + double method = summary.CalculateMethodCoverage(Modules).Percent; + + if ((thresholdTypes & ThresholdTypeFlags.Line) != ThresholdTypeFlags.None) + { + if (line < threshold) + thresholdTypeFlags |= ThresholdTypeFlags.Line; + } + + if ((thresholdTypes & ThresholdTypeFlags.Branch) != ThresholdTypeFlags.None) + { + if (branch < threshold) + thresholdTypeFlags |= ThresholdTypeFlags.Branch; + } + + if ((thresholdTypes & ThresholdTypeFlags.Method) != ThresholdTypeFlags.None) + { + if (method < threshold) + thresholdTypeFlags |= ThresholdTypeFlags.Method; + } + } + break; + } + + return thresholdTypeFlags; + } + } + + public class CoverageSummary + { + public CoverageDetails CalculateLineCoverage(Lines lines) + { + var details = new CoverageDetails(); + details.Covered = lines.Where(l => l.Value > 0).Count(); + details.Total = lines.Count; + return details; + } + + public CoverageDetails CalculateLineCoverage(Methods methods) + { + var details = new CoverageDetails(); + foreach (var method in methods) + { + var methodCoverage = CalculateLineCoverage(method.Value.Lines); + details.Covered += methodCoverage.Covered; + details.Total += methodCoverage.Total; + } + return details; + } + + public CoverageDetails CalculateLineCoverage(Classes classes) + { + var details = new CoverageDetails(); + foreach (var @class in classes) + { + var classCoverage = CalculateLineCoverage(@class.Value); + details.Covered += classCoverage.Covered; + details.Total += classCoverage.Total; + } + return details; + } + + public CoverageDetails CalculateLineCoverage(Documents documents) + { + var details = new CoverageDetails(); + foreach (var document in documents) + { + var documentCoverage = CalculateLineCoverage(document.Value); + details.Covered += documentCoverage.Covered; + details.Total += documentCoverage.Total; + } + return details; + } + + public CoverageDetails CalculateLineCoverage(Modules modules) + { + var details = new CoverageDetails(); + var accumPercent = 0.0D; + foreach (var module in modules) + { + var moduleCoverage = CalculateLineCoverage(module.Value); + details.Covered += moduleCoverage.Covered; + details.Total += moduleCoverage.Total; + accumPercent += moduleCoverage.Percent; + } + details.AverageModulePercent = accumPercent / modules.Count; + return details; + } + + public CoverageDetails CalculateBranchCoverage(IList branches) + { + var details = new CoverageDetails(); + details.Covered = branches.Count(bi => bi.Hits > 0); + details.Total = branches.Count; + return details; + } + + public int CalculateCyclomaticComplexity(IList branches) + { + return Math.Max(1, branches.Count); + } + + public int CalculateCyclomaticComplexity(Methods methods) + { + return methods.Values.Select(m => CalculateCyclomaticComplexity(m.Branches)).Sum(); + } + + public int CalculateMaxCyclomaticComplexity(Methods methods) + { + return methods.Values.Select(m => CalculateCyclomaticComplexity(m.Branches)).DefaultIfEmpty(1).Max(); + } + + public int CalculateMinCyclomaticComplexity(Methods methods) + { + return methods.Values.Select(m => CalculateCyclomaticComplexity(m.Branches)).DefaultIfEmpty(1).Min(); + } + + public int CalculateCyclomaticComplexity(Modules modules) + { + return modules.Values.Select(CalculateCyclomaticComplexity).Sum(); + } + + public int CalculateMaxCyclomaticComplexity(Modules modules) + { + return modules.Values.Select(CalculateCyclomaticComplexity).DefaultIfEmpty(1).Max(); + } + + public int CalculateMinCyclomaticComplexity(Modules modules) + { + return modules.Values.Select(CalculateCyclomaticComplexity).DefaultIfEmpty(1).Min(); + } + + public int CalculateCyclomaticComplexity(Documents documents) + { + return documents.Values.SelectMany(c => c.Values.Select(CalculateCyclomaticComplexity)).Sum(); + } + + public CoverageDetails CalculateBranchCoverage(Methods methods) + { + var details = new CoverageDetails(); + foreach (var method in methods) + { + var methodCoverage = CalculateBranchCoverage(method.Value.Branches); + details.Covered += methodCoverage.Covered; + details.Total += methodCoverage.Total; + } + return details; + } + + public CoverageDetails CalculateBranchCoverage(Classes classes) + { + var details = new CoverageDetails(); + foreach (var @class in classes) + { + var classCoverage = CalculateBranchCoverage(@class.Value); + details.Covered += classCoverage.Covered; + details.Total += classCoverage.Total; + } + return details; + } + + public CoverageDetails CalculateBranchCoverage(Documents documents) + { + var details = new CoverageDetails(); + foreach (var document in documents) + { + var documentCoverage = CalculateBranchCoverage(document.Value); + details.Covered += documentCoverage.Covered; + details.Total += documentCoverage.Total; + } + return details; + } + + public CoverageDetails CalculateBranchCoverage(Modules modules) + { + var details = new CoverageDetails(); + var accumPercent = 0.0D; + foreach (var module in modules) + { + var moduleCoverage = CalculateBranchCoverage(module.Value); + details.Covered += moduleCoverage.Covered; + details.Total += moduleCoverage.Total; + accumPercent += moduleCoverage.Percent; + } + details.AverageModulePercent = accumPercent / modules.Count; + return details; + } + + public CoverageDetails CalculateMethodCoverage(Lines lines) + { + var details = new CoverageDetails(); + details.Covered = lines.Any(l => l.Value > 0) ? 1 : 0; + details.Total = 1; + return details; + } + + public CoverageDetails CalculateMethodCoverage(Methods methods) + { + var details = new CoverageDetails(); + var methodsWithLines = methods.Where(m => m.Value.Lines.Count > 0); + foreach (var method in methodsWithLines) + { + var methodCoverage = CalculateMethodCoverage(method.Value.Lines); + details.Covered += methodCoverage.Covered; + } + details.Total = methodsWithLines.Count(); + return details; + } + + public CoverageDetails CalculateMethodCoverage(Classes classes) + { + var details = new CoverageDetails(); + foreach (var @class in classes) + { + var classCoverage = CalculateMethodCoverage(@class.Value); + details.Covered += classCoverage.Covered; + details.Total += classCoverage.Total; + } + return details; + } + + public CoverageDetails CalculateMethodCoverage(Documents documents) + { + var details = new CoverageDetails(); + foreach (var document in documents) + { + var documentCoverage = CalculateMethodCoverage(document.Value); + details.Covered += documentCoverage.Covered; + details.Total += documentCoverage.Total; + } + return details; + } + + public CoverageDetails CalculateMethodCoverage(Modules modules) + { + var details = new CoverageDetails(); + var accumPercent = 0.0D; + foreach (var module in modules) + { + var moduleCoverage = CalculateMethodCoverage(module.Value); + details.Covered += moduleCoverage.Covered; + details.Total += moduleCoverage.Total; + accumPercent += moduleCoverage.Percent; + } + details.AverageModulePercent = accumPercent / modules.Count; + return details; + } + } + + public class CoverageDetails + { + private double _averageModulePercent; + public double Covered { get; internal set; } + public int Total { get; internal set; } + public double AverageModulePercent + { + get { return Math.Floor(_averageModulePercent * 100) / 100; } + internal set { _averageModulePercent = value; } + } + + public double Percent => Total == 0 ? 100D : Math.Floor((Covered / Total) * 10000) / 100; + } +} \ No newline at end of file diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs index 8cffac299..53cb8390d 100644 --- a/src/coverlet.core/Reporters/CoberturaReporter.cs +++ b/src/coverlet.core/Reporters/CoberturaReporter.cs @@ -5,7 +5,9 @@ using System.Text; using System.Xml.Linq; -namespace Coverlet.Core.Reporters +using Coverlet.Core.ObjectModel; + +namespace Coverlet.Core.Abstracts { internal class CoberturaReporter : IReporter { diff --git a/src/coverlet.core/Reporters/IReporter.cs b/src/coverlet.core/Reporters/IReporter.cs deleted file mode 100644 index ab3e8f99d..000000000 --- a/src/coverlet.core/Reporters/IReporter.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Coverlet.Core.Reporters -{ - internal interface IReporter - { - ReporterOutputType OutputType { get; } - string Format { get; } - string Extension { get; } - string Report(CoverageResult result); - } - - internal enum ReporterOutputType - { - File, - Console, - } -} \ No newline at end of file diff --git a/src/coverlet.core/Reporters/JsonReporter.cs b/src/coverlet.core/Reporters/JsonReporter.cs index 09e23e83f..f355dde23 100644 --- a/src/coverlet.core/Reporters/JsonReporter.cs +++ b/src/coverlet.core/Reporters/JsonReporter.cs @@ -1,6 +1,7 @@ +using Coverlet.Core.ObjectModel; using Newtonsoft.Json; -namespace Coverlet.Core.Reporters +namespace Coverlet.Core.Abstracts { internal class JsonReporter : IReporter { diff --git a/src/coverlet.core/Reporters/LcovReporter.cs b/src/coverlet.core/Reporters/LcovReporter.cs index e8e94b68d..3f068584f 100644 --- a/src/coverlet.core/Reporters/LcovReporter.cs +++ b/src/coverlet.core/Reporters/LcovReporter.cs @@ -1,8 +1,9 @@ using System; using System.Linq; using System.Collections.Generic; +using Coverlet.Core.ObjectModel; -namespace Coverlet.Core.Reporters +namespace Coverlet.Core.Abstracts { internal class LcovReporter : IReporter { diff --git a/src/coverlet.core/Reporters/OpenCoverReporter.cs b/src/coverlet.core/Reporters/OpenCoverReporter.cs index 4a5c61005..f0a9e06ab 100644 --- a/src/coverlet.core/Reporters/OpenCoverReporter.cs +++ b/src/coverlet.core/Reporters/OpenCoverReporter.cs @@ -1,3 +1,4 @@ +using Coverlet.Core.ObjectModel; using System; using System.Collections.Generic; using System.Globalization; @@ -6,7 +7,7 @@ using System.Text; using System.Xml.Linq; -namespace Coverlet.Core.Reporters +namespace Coverlet.Core.Abstracts { internal class OpenCoverReporter : IReporter { diff --git a/src/coverlet.core/Reporters/ReporterFactory.cs b/src/coverlet.core/Reporters/ReporterFactory.cs index 7ac72337b..c2223e0a1 100644 --- a/src/coverlet.core/Reporters/ReporterFactory.cs +++ b/src/coverlet.core/Reporters/ReporterFactory.cs @@ -1,16 +1,15 @@ using System; using System.Linq; -namespace Coverlet.Core.Reporters +namespace Coverlet.Core.Abstracts { - internal class ReporterFactory + internal class ReporterFactory : IReporterFactory { private string _format; private IReporter[] _reporters; - public ReporterFactory(string format) + public ReporterFactory() { - _format = format; _reporters = new IReporter[] { new JsonReporter(), new LcovReporter(), new OpenCoverReporter(), new CoberturaReporter(), @@ -18,6 +17,11 @@ public ReporterFactory(string format) }; } + public ReporterFactory(string format) : this() + { + _format = format; + } + public bool IsValidFormat() { return CreateReporter() != null; @@ -25,5 +29,15 @@ public bool IsValidFormat() public IReporter CreateReporter() => _reporters.FirstOrDefault(r => string.Equals(r.Format, _format, StringComparison.OrdinalIgnoreCase)); + + public IReporter Create(string format) + { + ReporterFactory reporterFactory = new ReporterFactory(format); + if (!reporterFactory.IsValidFormat()) + { + throw new ArgumentException($"Format not supported '{format}'"); + } + return reporterFactory.CreateReporter(); + } } } \ No newline at end of file diff --git a/src/coverlet.core/Reporters/TeamCityReporter.cs b/src/coverlet.core/Reporters/TeamCityReporter.cs index a12a8f96c..a86777d63 100644 --- a/src/coverlet.core/Reporters/TeamCityReporter.cs +++ b/src/coverlet.core/Reporters/TeamCityReporter.cs @@ -1,9 +1,9 @@ using System.Globalization; -using Coverlet.Core; -using Coverlet.Core.Reporters; using System.Text; -namespace Coverlet.Core.Reporters +using Coverlet.Core.ObjectModel; + +namespace Coverlet.Core.Abstracts { internal class TeamCityReporter : IReporter { diff --git a/src/coverlet.core/coverlet.core.csproj b/src/coverlet.core/coverlet.core.csproj index 0a7649292..0eeeb8170 100644 --- a/src/coverlet.core/coverlet.core.csproj +++ b/src/coverlet.core/coverlet.core.csproj @@ -3,9 +3,21 @@ Library netstandard2.0 - 5.2.0 - false + coverlet.core + coverlet.core + coverlet.core + tonerdo + MIT + http://github.com/tonerdo/coverlet + https://raw.githubusercontent.com/tonerdo/coverlet/master/_assets/coverlet-icon.svg?sanitize=true + false + Coverlet is a cross platform code coverage library for .NET, with support for line, branch and method coverage. + coverage testing unit-test lcov opencover quality + git + true + snupkg preview + 5.2.0 @@ -16,5 +28,4 @@ - diff --git a/src/coverlet.core/version.json b/src/coverlet.core/version.json new file mode 100644 index 000000000..80a4e476c --- /dev/null +++ b/src/coverlet.core/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "1.0", + "publicReleaseRefSpec": [ + "^refs/heads/master$" + ] +} diff --git a/src/coverlet.msbuild.tasks/CoverageResultTask.cs b/src/coverlet.msbuild.tasks/CoverageResultTask.cs index c37e59859..b67a62b5d 100644 --- a/src/coverlet.msbuild.tasks/CoverageResultTask.cs +++ b/src/coverlet.msbuild.tasks/CoverageResultTask.cs @@ -2,12 +2,13 @@ using System.IO; using System.Linq; using System.Text; + using ConsoleTables; using Coverlet.Core; using Coverlet.Core.Abstracts; using Coverlet.Core.Enums; using Coverlet.Core.Extensions; -using Coverlet.Core.Reporters; +using Coverlet.Core.ObjectModel; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; diff --git a/test/coverlet.collector.tests/CoverletCoverageDataCollectorTests.cs b/test/coverlet.collector.tests/CoverletCoverageDataCollectorTests.cs index 8f19a95f2..a71073595 100644 --- a/test/coverlet.collector.tests/CoverletCoverageDataCollectorTests.cs +++ b/test/coverlet.collector.tests/CoverletCoverageDataCollectorTests.cs @@ -8,13 +8,12 @@ using Moq; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Coverlet.Core; +using Coverlet.Core.Abstracts; +using Coverlet.Core.Extensions; +using Coverlet.Collector.DataCollection; using Coverlet.Collector.Utilities.Interfaces; using Coverlet.Collector.Utilities; using Xunit; -using Coverlet.Collector.DataCollection; -using Coverlet.Core.Reporters; -using Coverlet.Core.Abstracts; -using Coverlet.Core.Extensions; namespace Coverlet.Collector.Tests { diff --git a/test/coverlet.core.standalone.sample/Sample.cs b/test/coverlet.core.standalone.sample/Sample.cs new file mode 100644 index 000000000..312cbe2c7 --- /dev/null +++ b/test/coverlet.core.standalone.sample/Sample.cs @@ -0,0 +1,10 @@ +namespace Coverlet.Core.Standalone.Sample +{ + public class Calculator + { + public int Add(int a, int b) + { + return a + b; + } + } +} diff --git a/test/coverlet.core.standalone.sample/coverlet.core.standalone.sample.csproj b/test/coverlet.core.standalone.sample/coverlet.core.standalone.sample.csproj new file mode 100644 index 000000000..939b54a16 --- /dev/null +++ b/test/coverlet.core.standalone.sample/coverlet.core.standalone.sample.csproj @@ -0,0 +1,9 @@ + + + + netcoreapp2.2 + false + false + + + diff --git a/test/coverlet.core.standalone.tests/BaseTest.cs b/test/coverlet.core.standalone.tests/BaseTest.cs new file mode 100644 index 000000000..cc5efca3a --- /dev/null +++ b/test/coverlet.core.standalone.tests/BaseTest.cs @@ -0,0 +1,51 @@ +#nullable enable + +using System; +using System.Diagnostics; +using System.IO; +using System.Reflection; + +namespace Coverlet.Core.Standalone.Tests +{ + public abstract class BaseTest + { + protected string GetLibToInstrument() + { + string moduleToInstrument = "coverlet.core.standalone.sample.dll"; + string location = Path.GetFullPath(moduleToInstrument); + string newPath = Path.Combine(Path.GetDirectoryName(location), Guid.NewGuid().ToString("N"), moduleToInstrument); + Directory.CreateDirectory(Path.GetDirectoryName(newPath)); + File.Copy(location, newPath); + File.Copy(Path.ChangeExtension(location, ".pdb"), Path.ChangeExtension(newPath, ".pdb")); + return newPath; + } + } + + public class SampleWrapper + { + readonly dynamic? _object; + readonly Assembly _asm; + + public SampleWrapper(string asmFile) + { + _asm = Assembly.Load(File.ReadAllBytes(asmFile)); + foreach (Type type in _asm.GetTypes()) + { + if (type.Name == "Calculator") + { + _object = Activator.CreateInstance(type); + } + } + } + + public int Add(int a, int b) + { + if (_object is null) + { + throw new NullReferenceException("_object is null"); + } + + return _object.Add(a, b); + } + } +} diff --git a/test/coverlet.core.standalone.tests/StandaloneInstrumentation.cs b/test/coverlet.core.standalone.tests/StandaloneInstrumentation.cs new file mode 100644 index 000000000..744e5e218 --- /dev/null +++ b/test/coverlet.core.standalone.tests/StandaloneInstrumentation.cs @@ -0,0 +1,108 @@ +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Threading.Tasks; + +using Coverlet.Core.Abstracts; +using Coverlet.Core.Instrumentation; +using Coverlet.Core.ObjectModel; +using Coverlet.Tests.RemoteExecutor; +using Xunit; + +namespace Coverlet.Core.Standalone.Tests +{ + public class StandaloneInstrumentation : BaseTest + { + readonly ICoverageEngineFactory _coverageFactory = new BuildInCoverageEngineFactory(); + + [Fact] + async public Task Instrument_Run_GetResult() + { + // Copy file to instrument to avoid lock + string fileToInstrument = GetLibToInstrument(); + + // Create engine + InstrumentationOptions options = new InstrumentationOptions(); + options.Module = fileToInstrument; + options.IncludeTestAssembly = true; + options.IncludeFilters = new string[] { $"[{Path.GetFileNameWithoutExtension(options.Module)}*]*" }; + ICoverageEngine coverageEngine = _coverageFactory.CreateEngine(options); + + // Instrument modules + Stream instrumentationResult = coverageEngine.PrepareModules(); + // Persist stream + string instrumentationResultPath = Path.GetTempFileName(); + using (var fs = File.OpenWrite(instrumentationResultPath)) + { + await instrumentationResult.CopyToAsync(fs); + } + instrumentationResult.Seek(0, SeekOrigin.Begin); + + // Run in new process + RemoteExecutor.Invoke(assets => + { + string[] assetsPath = assets.Split("|"); + ICoverageEngineFactory coverageFactory = new BuildInCoverageEngineFactory(); + + // We need to pass instrumentation result to engine + IInProcessCoverageEngine inProcessEngine = coverageFactory.CreateInProcessEngine(File.OpenRead(assetsPath[1])); + + // Use object + var sampleWrapper = new SampleWrapper(assetsPath[0]); + + // Get app domain loaded instrumented assemblies + Assembly[] assemblies = inProcessEngine.GetInstrumentedAssemblies(); + Assert.NotEmpty(assemblies); + + Assert.Equal(3, sampleWrapper.Add(1, 2)); + + // Read current coverage state + CoverageResult result = inProcessEngine.ReadCurrentCoverage(); + AssertCoverage(result, 1); + + Assert.Equal(3, sampleWrapper.Add(1, 2)); + + // Read current coverage state + result = inProcessEngine.ReadCurrentCoverage(); + AssertCoverage(result, 2); + + return Task.FromResult(0); + }, $"{fileToInstrument}|{instrumentationResultPath}").Dispose(); + + // Get results + CoverageResult result = coverageEngine.GetCoverageResult(instrumentationResult); + AssertCoverage(result, 2); + + // Create report + IReporter reporter = _coverageFactory.CreateReporter(Reporters.Cobertura); + string reportResult = reporter.Report(result); + Assert.NotEmpty(reportResult); + + return; + + // Assertion helper + static void AssertCoverage(CoverageResult result, int coverageValue) + { + foreach (var module in result.Modules) + { + foreach (var document in module.Value) + { + foreach (var @class in document.Value) + { + foreach (var method in @class.Value) + { + if (method.Key == "System.Int32 Coverlet.Core.Standalone.Sample.Calculator::Add(System.Int32,System.Int32)") + { + foreach (var line in method.Value.Lines) + { + Assert.Equal(coverageValue, line.Value); + } + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/test/coverlet.core.standalone.tests/coverlet.core.standalone.tests.csproj b/test/coverlet.core.standalone.tests/coverlet.core.standalone.tests.csproj new file mode 100644 index 000000000..566e14081 --- /dev/null +++ b/test/coverlet.core.standalone.tests/coverlet.core.standalone.tests.csproj @@ -0,0 +1,29 @@ + + + + + netcoreapp2.2 + false + Coverlet.Core.Standalone.Tests + preview + + + + + + + + + + + + + + + + + + + + + diff --git a/test/coverlet.core.tests/CoverageSummaryTests.cs b/test/coverlet.core.tests/CoverageSummaryTests.cs index 9dc9bf5a4..152b4595a 100644 --- a/test/coverlet.core.tests/CoverageSummaryTests.cs +++ b/test/coverlet.core.tests/CoverageSummaryTests.cs @@ -1,9 +1,6 @@ -using System; -using System.Collections.Generic; using System.Linq; -using Coverlet.Core; -using Moq; +using Coverlet.Core.ObjectModel; using Xunit; namespace Coverlet.Core.Tests diff --git a/test/coverlet.core.tests/CoverageTests.cs b/test/coverlet.core.tests/CoverageTests.cs index 4bfcfec67..22bb22ab8 100644 --- a/test/coverlet.core.tests/CoverageTests.cs +++ b/test/coverlet.core.tests/CoverageTests.cs @@ -5,6 +5,7 @@ using Coverlet.Core.Abstracts; using Coverlet.Core.Helpers; +using Coverlet.Core.ObjectModel; using Coverlet.Core.Samples.Tests; using Coverlet.Tests.RemoteExecutor; using Moq; diff --git a/test/coverlet.core.tests/InstrumenterHelper.cs b/test/coverlet.core.tests/InstrumenterHelper.cs index 35b4ff1d5..85f9afb4d 100644 --- a/test/coverlet.core.tests/InstrumenterHelper.cs +++ b/test/coverlet.core.tests/InstrumenterHelper.cs @@ -11,7 +11,7 @@ using Coverlet.Core.Abstracts; using Coverlet.Core.Helpers; using Coverlet.Core.Instrumentation; -using Coverlet.Core.Reporters; +using Coverlet.Core.ObjectModel; using Microsoft.Extensions.DependencyInjection; using Moq; using Palmmedia.ReportGenerator.Core; diff --git a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs index 913aaa08d..692de7274 100644 --- a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs @@ -1,15 +1,15 @@ using System; -using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading; -using System.Xml; using System.Xml.Linq; + +using Coverlet.Core.ObjectModel; using Xunit; -namespace Coverlet.Core.Reporters.Tests +namespace Coverlet.Core.Abstracts.Tests { public class CoberturaReporterTests { diff --git a/test/coverlet.core.tests/Reporters/JsonReporterTests.cs b/test/coverlet.core.tests/Reporters/JsonReporterTests.cs index 2bfc2ca43..81e0fbd55 100644 --- a/test/coverlet.core.tests/Reporters/JsonReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/JsonReporterTests.cs @@ -1,7 +1,9 @@ using System; + +using Coverlet.Core.ObjectModel; using Xunit; -namespace Coverlet.Core.Reporters.Tests +namespace Coverlet.Core.Abstracts.Tests { public class JsonReporterTests { diff --git a/test/coverlet.core.tests/Reporters/LcovReporterTests.cs b/test/coverlet.core.tests/Reporters/LcovReporterTests.cs index f5c888bf1..532559407 100644 --- a/test/coverlet.core.tests/Reporters/LcovReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/LcovReporterTests.cs @@ -1,8 +1,9 @@ using System; -using System.Collections.Generic; + +using Coverlet.Core.ObjectModel; using Xunit; -namespace Coverlet.Core.Reporters.Tests +namespace Coverlet.Core.Abstracts.Tests { public class LcovReporterTests { diff --git a/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs b/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs index 7d3e520bd..aa4066c70 100644 --- a/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs @@ -1,12 +1,13 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Xml.Linq; + +using Coverlet.Core.ObjectModel; using Xunit; -namespace Coverlet.Core.Reporters.Tests +namespace Coverlet.Core.Abstracts.Tests { public class OpenCoverReporterTests { diff --git a/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs b/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs index e148fa378..7116d1f5f 100644 --- a/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs +++ b/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs @@ -1,7 +1,7 @@ -using Coverlet.Core.Reporters; +using Coverlet.Core.Abstracts; using Xunit; -namespace Coverlet.Core.Reporters.Tests +namespace Coverlet.Core.Abstracts.Tests { public class ReporterFactoryTests { diff --git a/test/coverlet.core.tests/Reporters/TeamCityReporter.cs b/test/coverlet.core.tests/Reporters/TeamCityReporter.cs index 8328dd90e..38d80ed14 100644 --- a/test/coverlet.core.tests/Reporters/TeamCityReporter.cs +++ b/test/coverlet.core.tests/Reporters/TeamCityReporter.cs @@ -1,8 +1,9 @@ using System; -using Coverlet.Core.Reporters; + +using Coverlet.Core.ObjectModel; using Xunit; -namespace Coverlet.Core.Reporters.Tests +namespace Coverlet.Core.Abstracts.Tests { public class TestCreateReporterTests { From 53867ac8faeeaa64848485c00583c287d6b7c44d Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Mon, 2 Dec 2019 16:02:05 +0100 Subject: [PATCH 2/5] fix typo --- .../Examples/StandaloneUsage/Calculator/CalculatorRuntime.cs | 2 +- Documentation/Examples/StandaloneUsage/Calculator/Program.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/Examples/StandaloneUsage/Calculator/CalculatorRuntime.cs b/Documentation/Examples/StandaloneUsage/Calculator/CalculatorRuntime.cs index ca19365d8..1fe0eb3d0 100644 --- a/Documentation/Examples/StandaloneUsage/Calculator/CalculatorRuntime.cs +++ b/Documentation/Examples/StandaloneUsage/Calculator/CalculatorRuntime.cs @@ -7,7 +7,7 @@ public double Add(double a, double b) return a + b; } - public double Subtrac(double a, double b) + public double Subtract(double a, double b) { return a - b; } diff --git a/Documentation/Examples/StandaloneUsage/Calculator/Program.cs b/Documentation/Examples/StandaloneUsage/Calculator/Program.cs index 549e062d1..b5ae3db35 100644 --- a/Documentation/Examples/StandaloneUsage/Calculator/Program.cs +++ b/Documentation/Examples/StandaloneUsage/Calculator/Program.cs @@ -64,7 +64,7 @@ static void Main(string[] args) } case ConsoleKey.Subtract: { - Console.WriteLine($"Result: {runtime.Subtrac(operanda.Value, operandb.Value)}"); + Console.WriteLine($"Result: {runtime.Subtract(operanda.Value, operandb.Value)}"); break; } case ConsoleKey.Multiply: From cd8d473c0c0c8184af329d3cc76362e682e1b83b Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Mon, 2 Dec 2019 16:56:37 +0100 Subject: [PATCH 3/5] remove assertion --- src/coverlet.core/Instrumentation/CoverageEngine.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/coverlet.core/Instrumentation/CoverageEngine.cs b/src/coverlet.core/Instrumentation/CoverageEngine.cs index 17115c696..8994ce662 100644 --- a/src/coverlet.core/Instrumentation/CoverageEngine.cs +++ b/src/coverlet.core/Instrumentation/CoverageEngine.cs @@ -197,9 +197,6 @@ public Stream NewFileStream(string path, FileMode mode) if (type.Namespace == "Coverlet.Core.Instrumentation.Tracker" && type.Name.StartsWith(asm.GetName().Name + "_")) { - - Debug.Assert((string)type.GetField("HitsFilePath").GetValue(null) == path); - int[] hitsArray = (int[])type.GetField("HitsArray").GetValue(null); MemoryStream ms = new MemoryStream(); using BinaryWriter bw = new BinaryWriter(ms, Encoding.UTF8, true); From cb9437832a80fb431dbd60181bc99d7163965b31 Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Thu, 12 Dec 2019 11:01:32 +0100 Subject: [PATCH 4/5] fix build --- coverlet.sln | 14 ++++++++++++-- .../DataCollection/CoverageManager.cs | 1 + src/coverlet.console/Program.cs | 1 + src/coverlet.core/Abstracts/IReporter.cs | 9 --------- src/coverlet.core/Coverage.cs | 2 +- .../Instrumentation/CoverageEngine.cs | 5 ++--- src/coverlet.core/ObjectModel.cs | 1 + src/coverlet.core/Reporters/CoberturaReporter.cs | 3 ++- src/coverlet.core/Reporters/JsonReporter.cs | 3 ++- src/coverlet.core/Reporters/LcovReporter.cs | 4 +++- src/coverlet.core/Reporters/OpenCoverReporter.cs | 7 ++++--- src/coverlet.core/Reporters/ReporterFactory.cs | 13 ++++++++++++- src/coverlet.core/Reporters/TeamCityReporter.cs | 3 ++- src/coverlet.msbuild.tasks/CoverageResultTask.cs | 1 + src/coverlet.msbuild.tasks/ReportWriter.cs | 2 +- .../CoverletCoverageDataCollectorTests.cs | 1 + .../StandaloneInstrumentation.cs | 4 ++-- .../Coverage/InstrumenterHelper.cs | 1 + .../Reporters/CoberturaReporterTests.cs | 2 ++ .../Reporters/JsonReporterTests.cs | 1 + .../Reporters/LcovReporterTests.cs | 1 + .../Reporters/OpenCoverReporterTests.cs | 1 + .../Reporters/ReporterFactoryTests.cs | 2 +- test/coverlet.core.tests/Reporters/Reporters.cs | 1 + .../Reporters/TeamCityReporter.cs | 1 + test/coverlet.integration.tests/AssertHelper.cs | 2 +- test/coverlet.integration.tests/BaseTest.cs | 2 +- 27 files changed, 59 insertions(+), 29 deletions(-) diff --git a/coverlet.sln b/coverlet.sln index 88241b6a8..92a2aa516 100644 --- a/coverlet.sln +++ b/coverlet.sln @@ -46,9 +46,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "coverlet.integration.tests" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "coverlet.integration.template", "test\coverlet.integration.template\coverlet.integration.template.csproj", "{F6FE7678-C662-43D3-AC6A-64F6AC5A5935}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "coverlet.core.standalone.tests", "test\coverlet.core.standalone.tests\coverlet.core.standalone.tests.csproj", "{D324E73F-69DB-41BA-BF54-A79FD292114C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "coverlet.core.standalone.tests", "test\coverlet.core.standalone.tests\coverlet.core.standalone.tests.csproj", "{D324E73F-69DB-41BA-BF54-A79FD292114C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "coverlet.core.standalone.sample", "test\coverlet.core.standalone.sample\coverlet.core.standalone.sample.csproj", "{F1617303-0F38-4D98-9BFA-370B57F3A154}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "coverlet.core.standalone.sample", "test\coverlet.core.standalone.sample\coverlet.core.standalone.sample.csproj", "{F1617303-0F38-4D98-9BFA-370B57F3A154}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -108,6 +108,14 @@ Global {F6FE7678-C662-43D3-AC6A-64F6AC5A5935}.Debug|Any CPU.Build.0 = Debug|Any CPU {F6FE7678-C662-43D3-AC6A-64F6AC5A5935}.Release|Any CPU.ActiveCfg = Release|Any CPU {F6FE7678-C662-43D3-AC6A-64F6AC5A5935}.Release|Any CPU.Build.0 = Release|Any CPU + {D324E73F-69DB-41BA-BF54-A79FD292114C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D324E73F-69DB-41BA-BF54-A79FD292114C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D324E73F-69DB-41BA-BF54-A79FD292114C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D324E73F-69DB-41BA-BF54-A79FD292114C}.Release|Any CPU.Build.0 = Release|Any CPU + {F1617303-0F38-4D98-9BFA-370B57F3A154}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1617303-0F38-4D98-9BFA-370B57F3A154}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1617303-0F38-4D98-9BFA-370B57F3A154}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1617303-0F38-4D98-9BFA-370B57F3A154}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -126,6 +134,8 @@ Global {D6B14F2F-9E7D-4D2C-BAC8-48834F853ED6} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134} {99B4059C-B25C-4B82-8117-A0E9DC9B0949} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134} {F6FE7678-C662-43D3-AC6A-64F6AC5A5935} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134} + {D324E73F-69DB-41BA-BF54-A79FD292114C} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134} + {F1617303-0F38-4D98-9BFA-370B57F3A154} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {9CA57C02-97B0-4C38-A027-EA61E8741F10} diff --git a/src/coverlet.collector/DataCollection/CoverageManager.cs b/src/coverlet.collector/DataCollection/CoverageManager.cs index a46f47452..85d79b14b 100644 --- a/src/coverlet.collector/DataCollection/CoverageManager.cs +++ b/src/coverlet.collector/DataCollection/CoverageManager.cs @@ -9,6 +9,7 @@ using Coverlet.Core; using Coverlet.Core.Abstracts; using Coverlet.Core.ObjectModel; +using Coverlet.Core.Reporters; namespace Coverlet.Collector.DataCollection { diff --git a/src/coverlet.console/Program.cs b/src/coverlet.console/Program.cs index 628e11d3d..5f0771a4d 100644 --- a/src/coverlet.console/Program.cs +++ b/src/coverlet.console/Program.cs @@ -12,6 +12,7 @@ using Coverlet.Core.Enums; using Coverlet.Core.Extensions; using Coverlet.Core.ObjectModel; +using Coverlet.Core.Reporters; using McMaster.Extensions.CommandLineUtils; namespace Coverlet.Console diff --git a/src/coverlet.core/Abstracts/IReporter.cs b/src/coverlet.core/Abstracts/IReporter.cs index 09096c15b..116c7d882 100644 --- a/src/coverlet.core/Abstracts/IReporter.cs +++ b/src/coverlet.core/Abstracts/IReporter.cs @@ -2,15 +2,6 @@ namespace Coverlet.Core.Abstracts { - public static class Reporters - { - public readonly static string Cobertura = "cobertura"; - public readonly static string Json = "json"; - public readonly static string Lcov = "lcov"; - public readonly static string OpenCover = "opencover"; - public readonly static string TeamCity = "teamcity"; - } - internal interface IReporterFactory { IReporter Create(string format); diff --git a/src/coverlet.core/Coverage.cs b/src/coverlet.core/Coverage.cs index bf5eb48fb..990d52d79 100644 --- a/src/coverlet.core/Coverage.cs +++ b/src/coverlet.core/Coverage.cs @@ -282,7 +282,7 @@ public static CoverageResult GetCoverageResult(IEnumerable r } } - var coverageResult = new CoverageResult { Identifier = _identifier, Modules = modules, InstrumentedResults = _results, UseSourceLink = _useSourceLink }; + var coverageResult = new CoverageResult { Identifier = identifier, Modules = modules, InstrumentedResults = results.ToList(), UseSourceLink = useSourceLink }; if (!string.IsNullOrEmpty(mergeWith) && !string.IsNullOrWhiteSpace(mergeWith) && fileSystem.Exists(mergeWith)) { diff --git a/src/coverlet.core/Instrumentation/CoverageEngine.cs b/src/coverlet.core/Instrumentation/CoverageEngine.cs index 8994ce662..31593c149 100644 --- a/src/coverlet.core/Instrumentation/CoverageEngine.cs +++ b/src/coverlet.core/Instrumentation/CoverageEngine.cs @@ -1,17 +1,16 @@ #nullable enable using System; -using System.Collections.Concurrent; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; -using System.Runtime.InteropServices; using System.Text; + using Coverlet.Core.Abstracts; using Coverlet.Core.Helpers; using Coverlet.Core.ObjectModel; +using Coverlet.Core.Reporters; using Microsoft.Extensions.DependencyInjection; namespace Coverlet.Core.Instrumentation diff --git a/src/coverlet.core/ObjectModel.cs b/src/coverlet.core/ObjectModel.cs index d580d76ec..aeed0eda8 100644 --- a/src/coverlet.core/ObjectModel.cs +++ b/src/coverlet.core/ObjectModel.cs @@ -40,6 +40,7 @@ public class CoverageResult { public string Identifier; public Modules Modules; + public bool UseSourceLink; internal List InstrumentedResults; internal CoverageResult() { } diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs index 41fc01010..3528888e1 100644 --- a/src/coverlet.core/Reporters/CoberturaReporter.cs +++ b/src/coverlet.core/Reporters/CoberturaReporter.cs @@ -7,9 +7,10 @@ using System.Text; using System.Xml.Linq; +using Coverlet.Core.Abstracts; using Coverlet.Core.ObjectModel; -namespace Coverlet.Core.Abstracts +namespace Coverlet.Core.Reporters { internal class CoberturaReporter : IReporter { diff --git a/src/coverlet.core/Reporters/JsonReporter.cs b/src/coverlet.core/Reporters/JsonReporter.cs index f355dde23..dc27c2648 100644 --- a/src/coverlet.core/Reporters/JsonReporter.cs +++ b/src/coverlet.core/Reporters/JsonReporter.cs @@ -1,7 +1,8 @@ +using Coverlet.Core.Abstracts; using Coverlet.Core.ObjectModel; using Newtonsoft.Json; -namespace Coverlet.Core.Abstracts +namespace Coverlet.Core.Reporters { internal class JsonReporter : IReporter { diff --git a/src/coverlet.core/Reporters/LcovReporter.cs b/src/coverlet.core/Reporters/LcovReporter.cs index 3f068584f..c333d8baa 100644 --- a/src/coverlet.core/Reporters/LcovReporter.cs +++ b/src/coverlet.core/Reporters/LcovReporter.cs @@ -1,9 +1,11 @@ using System; using System.Linq; using System.Collections.Generic; + using Coverlet.Core.ObjectModel; +using Coverlet.Core.Abstracts; -namespace Coverlet.Core.Abstracts +namespace Coverlet.Core.Reporters { internal class LcovReporter : IReporter { diff --git a/src/coverlet.core/Reporters/OpenCoverReporter.cs b/src/coverlet.core/Reporters/OpenCoverReporter.cs index f0a9e06ab..ebde70dcc 100644 --- a/src/coverlet.core/Reporters/OpenCoverReporter.cs +++ b/src/coverlet.core/Reporters/OpenCoverReporter.cs @@ -1,13 +1,14 @@ -using Coverlet.Core.ObjectModel; using System; -using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Xml.Linq; -namespace Coverlet.Core.Abstracts +using Coverlet.Core.Abstracts; +using Coverlet.Core.ObjectModel; + +namespace Coverlet.Core.Reporters { internal class OpenCoverReporter : IReporter { diff --git a/src/coverlet.core/Reporters/ReporterFactory.cs b/src/coverlet.core/Reporters/ReporterFactory.cs index c2223e0a1..4d2f97b3c 100644 --- a/src/coverlet.core/Reporters/ReporterFactory.cs +++ b/src/coverlet.core/Reporters/ReporterFactory.cs @@ -1,8 +1,19 @@ using System; using System.Linq; -namespace Coverlet.Core.Abstracts +using Coverlet.Core.Abstracts; + +namespace Coverlet.Core.Reporters { + public static class ReporterTypes + { + public readonly static string Cobertura = "cobertura"; + public readonly static string Json = "json"; + public readonly static string Lcov = "lcov"; + public readonly static string OpenCover = "opencover"; + public readonly static string TeamCity = "teamcity"; + } + internal class ReporterFactory : IReporterFactory { private string _format; diff --git a/src/coverlet.core/Reporters/TeamCityReporter.cs b/src/coverlet.core/Reporters/TeamCityReporter.cs index a86777d63..e62048f7d 100644 --- a/src/coverlet.core/Reporters/TeamCityReporter.cs +++ b/src/coverlet.core/Reporters/TeamCityReporter.cs @@ -1,9 +1,10 @@ using System.Globalization; using System.Text; +using Coverlet.Core.Abstracts; using Coverlet.Core.ObjectModel; -namespace Coverlet.Core.Abstracts +namespace Coverlet.Core.Reporters { internal class TeamCityReporter : IReporter { diff --git a/src/coverlet.msbuild.tasks/CoverageResultTask.cs b/src/coverlet.msbuild.tasks/CoverageResultTask.cs index 5e099e485..2d1e15e97 100644 --- a/src/coverlet.msbuild.tasks/CoverageResultTask.cs +++ b/src/coverlet.msbuild.tasks/CoverageResultTask.cs @@ -9,6 +9,7 @@ using Coverlet.Core.Enums; using Coverlet.Core.Extensions; using Coverlet.Core.ObjectModel; +using Coverlet.Core.Reporters; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; diff --git a/src/coverlet.msbuild.tasks/ReportWriter.cs b/src/coverlet.msbuild.tasks/ReportWriter.cs index 346822a56..f22a3dc7a 100644 --- a/src/coverlet.msbuild.tasks/ReportWriter.cs +++ b/src/coverlet.msbuild.tasks/ReportWriter.cs @@ -1,7 +1,7 @@ using System.IO; -using Coverlet.Core; using Coverlet.Core.Abstracts; +using Coverlet.Core.ObjectModel; using Coverlet.Core.Reporters; namespace Coverlet.MSbuild.Tasks diff --git a/test/coverlet.collector.tests/CoverletCoverageDataCollectorTests.cs b/test/coverlet.collector.tests/CoverletCoverageDataCollectorTests.cs index a71073595..87a4248ab 100644 --- a/test/coverlet.collector.tests/CoverletCoverageDataCollectorTests.cs +++ b/test/coverlet.collector.tests/CoverletCoverageDataCollectorTests.cs @@ -14,6 +14,7 @@ using Coverlet.Collector.Utilities.Interfaces; using Coverlet.Collector.Utilities; using Xunit; +using Coverlet.Core.Reporters; namespace Coverlet.Collector.Tests { diff --git a/test/coverlet.core.standalone.tests/StandaloneInstrumentation.cs b/test/coverlet.core.standalone.tests/StandaloneInstrumentation.cs index 744e5e218..16222430f 100644 --- a/test/coverlet.core.standalone.tests/StandaloneInstrumentation.cs +++ b/test/coverlet.core.standalone.tests/StandaloneInstrumentation.cs @@ -1,4 +1,3 @@ -using System.Diagnostics; using System.IO; using System.Reflection; using System.Threading.Tasks; @@ -6,6 +5,7 @@ using Coverlet.Core.Abstracts; using Coverlet.Core.Instrumentation; using Coverlet.Core.ObjectModel; +using Coverlet.Core.Reporters; using Coverlet.Tests.RemoteExecutor; using Xunit; @@ -74,7 +74,7 @@ async public Task Instrument_Run_GetResult() AssertCoverage(result, 2); // Create report - IReporter reporter = _coverageFactory.CreateReporter(Reporters.Cobertura); + IReporter reporter = _coverageFactory.CreateReporter(ReporterTypes.Cobertura); string reportResult = reporter.Report(result); Assert.NotEmpty(reportResult); diff --git a/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs b/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs index 85f9afb4d..29ab62e8c 100644 --- a/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs +++ b/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs @@ -12,6 +12,7 @@ using Coverlet.Core.Helpers; using Coverlet.Core.Instrumentation; using Coverlet.Core.ObjectModel; +using Coverlet.Core.Reporters; using Microsoft.Extensions.DependencyInjection; using Moq; using Palmmedia.ReportGenerator.Core; diff --git a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs index 38b5d6bd1..9053c5580 100644 --- a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; @@ -8,6 +9,7 @@ using System.Xml.Linq; using Coverlet.Core.ObjectModel; +using Coverlet.Core.Reporters; using Xunit; namespace Coverlet.Core.Abstracts.Tests diff --git a/test/coverlet.core.tests/Reporters/JsonReporterTests.cs b/test/coverlet.core.tests/Reporters/JsonReporterTests.cs index 81e0fbd55..be33246d9 100644 --- a/test/coverlet.core.tests/Reporters/JsonReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/JsonReporterTests.cs @@ -1,6 +1,7 @@ using System; using Coverlet.Core.ObjectModel; +using Coverlet.Core.Reporters; using Xunit; namespace Coverlet.Core.Abstracts.Tests diff --git a/test/coverlet.core.tests/Reporters/LcovReporterTests.cs b/test/coverlet.core.tests/Reporters/LcovReporterTests.cs index 532559407..e6f369ee3 100644 --- a/test/coverlet.core.tests/Reporters/LcovReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/LcovReporterTests.cs @@ -1,6 +1,7 @@ using System; using Coverlet.Core.ObjectModel; +using Coverlet.Core.Reporters; using Xunit; namespace Coverlet.Core.Abstracts.Tests diff --git a/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs b/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs index aa4066c70..0f5d02bd0 100644 --- a/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs @@ -5,6 +5,7 @@ using System.Xml.Linq; using Coverlet.Core.ObjectModel; +using Coverlet.Core.Reporters; using Xunit; namespace Coverlet.Core.Abstracts.Tests diff --git a/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs b/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs index 7116d1f5f..42b8cd302 100644 --- a/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs +++ b/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs @@ -1,4 +1,4 @@ -using Coverlet.Core.Abstracts; +using Coverlet.Core.Reporters; using Xunit; namespace Coverlet.Core.Abstracts.Tests diff --git a/test/coverlet.core.tests/Reporters/Reporters.cs b/test/coverlet.core.tests/Reporters/Reporters.cs index 6ddaf7cdd..a031eb7b0 100644 --- a/test/coverlet.core.tests/Reporters/Reporters.cs +++ b/test/coverlet.core.tests/Reporters/Reporters.cs @@ -1,6 +1,7 @@ using System.IO; using Coverlet.Core.Abstracts; +using Coverlet.Core.ObjectModel; using Coverlet.MSbuild.Tasks; using Moq; using Xunit; diff --git a/test/coverlet.core.tests/Reporters/TeamCityReporter.cs b/test/coverlet.core.tests/Reporters/TeamCityReporter.cs index 38d80ed14..a5d399dbd 100644 --- a/test/coverlet.core.tests/Reporters/TeamCityReporter.cs +++ b/test/coverlet.core.tests/Reporters/TeamCityReporter.cs @@ -1,6 +1,7 @@ using System; using Coverlet.Core.ObjectModel; +using Coverlet.Core.Reporters; using Xunit; namespace Coverlet.Core.Abstracts.Tests diff --git a/test/coverlet.integration.tests/AssertHelper.cs b/test/coverlet.integration.tests/AssertHelper.cs index 4fa6e0658..d3629db05 100644 --- a/test/coverlet.integration.tests/AssertHelper.cs +++ b/test/coverlet.integration.tests/AssertHelper.cs @@ -3,7 +3,7 @@ using System.IO; using System.Linq; -using Coverlet.Core; +using Coverlet.Core.ObjectModel; using Xunit.Sdk; namespace Coverlet.Integration.Tests diff --git a/test/coverlet.integration.tests/BaseTest.cs b/test/coverlet.integration.tests/BaseTest.cs index 739ebbf42..932a233dc 100644 --- a/test/coverlet.integration.tests/BaseTest.cs +++ b/test/coverlet.integration.tests/BaseTest.cs @@ -5,7 +5,7 @@ using System.Reflection; using System.Xml.Linq; -using Coverlet.Core; +using Coverlet.Core.ObjectModel; using Newtonsoft.Json; using NuGet.Packaging; using Xunit; From a50062770daf139989be7549ea0b2f04bf172f31 Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Thu, 12 Dec 2019 11:11:11 +0100 Subject: [PATCH 5/5] fix namespaces --- src/coverlet.core/Reporters/LcovReporter.cs | 2 +- test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs | 3 +-- test/coverlet.core.tests/Reporters/JsonReporterTests.cs | 3 +-- test/coverlet.core.tests/Reporters/LcovReporterTests.cs | 3 +-- test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs | 3 +-- test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs | 3 +-- test/coverlet.core.tests/Reporters/TeamCityReporter.cs | 5 ++--- 7 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/coverlet.core/Reporters/LcovReporter.cs b/src/coverlet.core/Reporters/LcovReporter.cs index c333d8baa..576a7b15e 100644 --- a/src/coverlet.core/Reporters/LcovReporter.cs +++ b/src/coverlet.core/Reporters/LcovReporter.cs @@ -2,8 +2,8 @@ using System.Linq; using System.Collections.Generic; -using Coverlet.Core.ObjectModel; using Coverlet.Core.Abstracts; +using Coverlet.Core.ObjectModel; namespace Coverlet.Core.Reporters { diff --git a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs index 9053c5580..5ae42d3b8 100644 --- a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs @@ -9,10 +9,9 @@ using System.Xml.Linq; using Coverlet.Core.ObjectModel; -using Coverlet.Core.Reporters; using Xunit; -namespace Coverlet.Core.Abstracts.Tests +namespace Coverlet.Core.Reporters.Tests { public class CoberturaReporterTests { diff --git a/test/coverlet.core.tests/Reporters/JsonReporterTests.cs b/test/coverlet.core.tests/Reporters/JsonReporterTests.cs index be33246d9..75c7e020b 100644 --- a/test/coverlet.core.tests/Reporters/JsonReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/JsonReporterTests.cs @@ -1,10 +1,9 @@ using System; using Coverlet.Core.ObjectModel; -using Coverlet.Core.Reporters; using Xunit; -namespace Coverlet.Core.Abstracts.Tests +namespace Coverlet.Core.Reporters.Tests { public class JsonReporterTests { diff --git a/test/coverlet.core.tests/Reporters/LcovReporterTests.cs b/test/coverlet.core.tests/Reporters/LcovReporterTests.cs index e6f369ee3..048ac7b4a 100644 --- a/test/coverlet.core.tests/Reporters/LcovReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/LcovReporterTests.cs @@ -1,10 +1,9 @@ using System; using Coverlet.Core.ObjectModel; -using Coverlet.Core.Reporters; using Xunit; -namespace Coverlet.Core.Abstracts.Tests +namespace Coverlet.Core.Reporters.Tests { public class LcovReporterTests { diff --git a/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs b/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs index 0f5d02bd0..2c0e754c8 100644 --- a/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs @@ -5,10 +5,9 @@ using System.Xml.Linq; using Coverlet.Core.ObjectModel; -using Coverlet.Core.Reporters; using Xunit; -namespace Coverlet.Core.Abstracts.Tests +namespace Coverlet.Core.Reporters.Tests { public class OpenCoverReporterTests { diff --git a/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs b/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs index 42b8cd302..058ee4be3 100644 --- a/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs +++ b/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs @@ -1,7 +1,6 @@ -using Coverlet.Core.Reporters; using Xunit; -namespace Coverlet.Core.Abstracts.Tests +namespace Coverlet.Core.Reporters.Tests { public class ReporterFactoryTests { diff --git a/test/coverlet.core.tests/Reporters/TeamCityReporter.cs b/test/coverlet.core.tests/Reporters/TeamCityReporter.cs index a5d399dbd..30ed99b94 100644 --- a/test/coverlet.core.tests/Reporters/TeamCityReporter.cs +++ b/test/coverlet.core.tests/Reporters/TeamCityReporter.cs @@ -1,10 +1,9 @@ using System; - +using Coverlet.Core.Abstracts; using Coverlet.Core.ObjectModel; -using Coverlet.Core.Reporters; using Xunit; -namespace Coverlet.Core.Abstracts.Tests +namespace Coverlet.Core.Reporters.Tests { public class TestCreateReporterTests {