Add editorconfig with tuned configuration (#1300)
Add editorconfig with tuned configuration
This commit is contained in:
+197
@@ -0,0 +1,197 @@
|
||||
# To learn more about .editorconfig see https://aka.ms/editorconfigdocs
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
###############################
|
||||
# Core EditorConfig Options #
|
||||
###############################
|
||||
# All files
|
||||
[*]
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# XML project files
|
||||
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
|
||||
# XML config files
|
||||
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
|
||||
indent_size = 2
|
||||
|
||||
# Xml build files
|
||||
[*.builds]
|
||||
indent_size = 2
|
||||
|
||||
# Xml files
|
||||
[*.{xml,stylecop,resx,ruleset}]
|
||||
indent_size = 2
|
||||
|
||||
# YAML config files
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
# Shell scripts
|
||||
[*.sh]
|
||||
end_of_line = lf
|
||||
[*.{cmd,bat}]
|
||||
end_of_line = crlf
|
||||
|
||||
# Code files
|
||||
[*.{cs,csx,vb,vbx}]
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
charset = utf-8-bom
|
||||
###############################
|
||||
# .NET Coding Conventions #
|
||||
###############################
|
||||
[*.{cs,vb}]
|
||||
# Organize usings
|
||||
dotnet_sort_system_directives_first = true
|
||||
## IDE0005: Using directive is unnecessary.
|
||||
dotnet_diagnostic.IDE0005.severity = warning
|
||||
# License header
|
||||
file_header_template = Copyright (c) Toni Solarin-Sodara\nLicensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
## IDE0073: The file header is missing or not located at the top of the file
|
||||
dotnet_diagnostic.IDE0073.severity = warning
|
||||
# this. preferences
|
||||
dotnet_style_qualification_for_field = false:warning
|
||||
dotnet_style_qualification_for_property = false:warning
|
||||
dotnet_style_qualification_for_method = false:warning
|
||||
dotnet_style_qualification_for_event = false:warning
|
||||
# Language keywords vs BCL types preferences
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
|
||||
dotnet_style_predefined_type_for_member_access = true:silent
|
||||
# Parentheses preferences
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
|
||||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
|
||||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
|
||||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
|
||||
# Modifier preferences
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
|
||||
dotnet_style_readonly_field = true:warning
|
||||
## IDE0044: Add readonly modifier
|
||||
dotnet_diagnostic.IDE0044.severity = warning
|
||||
# Expression-level preferences
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
dotnet_style_collection_initializer = true:suggestion
|
||||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
|
||||
dotnet_style_prefer_inferred_tuple_names = true:suggestion
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||
dotnet_style_prefer_auto_properties = true:warning
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
|
||||
dotnet_style_prefer_conditional_expression_over_return = true:silent
|
||||
###############################
|
||||
# Naming Conventions #
|
||||
###############################
|
||||
# Name all constant fields using PascalCase
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
|
||||
dotnet_naming_symbols.constant_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.constant_fields.required_modifiers = const
|
||||
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
|
||||
# Static fields should have s_ prefix
|
||||
dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion
|
||||
dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
|
||||
dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
|
||||
dotnet_naming_symbols.static_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.static_fields.required_modifiers = static
|
||||
dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected
|
||||
dotnet_naming_style.static_prefix_style.required_prefix = s_
|
||||
dotnet_naming_style.static_prefix_style.capitalization = camel_case
|
||||
# Internal and private fields should be _camelCase
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
|
||||
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
|
||||
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
|
||||
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
|
||||
###############################
|
||||
# C# Coding Conventions #
|
||||
###############################
|
||||
[*.cs]
|
||||
# Organize usings
|
||||
csharp_using_directive_placement = outside_namespace:warning
|
||||
# var preferences - use keywords instead of BCL types, and permit var only when the type is clear
|
||||
csharp_style_var_for_built_in_types = false:warning
|
||||
csharp_style_var_when_type_is_apparent = true:warning
|
||||
csharp_style_var_elsewhere = false:warning
|
||||
# Expression-bodied members
|
||||
csharp_style_expression_bodied_methods = false:silent
|
||||
csharp_style_expression_bodied_constructors = false:silent
|
||||
csharp_style_expression_bodied_operators = false:silent
|
||||
csharp_style_expression_bodied_properties = true:silent
|
||||
csharp_style_expression_bodied_indexers = true:silent
|
||||
csharp_style_expression_bodied_accessors = true:silent
|
||||
# Pattern matching preferences
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:warning
|
||||
csharp_style_prefer_not_pattern = true
|
||||
## IDE0083: Use pattern matching
|
||||
dotnet_diagnostic.IDE0083.severity = warning
|
||||
# Null-checking preferences
|
||||
csharp_style_throw_expression = true:warning
|
||||
csharp_style_conditional_delegate_call = true:warning
|
||||
# Modifier preferences
|
||||
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning
|
||||
# Expression-level preferences
|
||||
csharp_prefer_braces = true:silent
|
||||
csharp_style_deconstructed_variable_declaration = true:suggestion
|
||||
csharp_prefer_simple_default_expression = true:warning
|
||||
## IDE0034: Simplify 'default' expression
|
||||
dotnet_diagnostic.IDE0034.severity = warning
|
||||
csharp_style_pattern_local_over_anonymous_function = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:warning
|
||||
###############################
|
||||
# C# Formatting Rules #
|
||||
###############################
|
||||
# New line preferences
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
dotnet_style_allow_multiple_blank_lines_experimental=false:warning
|
||||
# Indentation preferences
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents_when_block = true
|
||||
csharp_indent_labels = one_less_than_current
|
||||
# Space preferences
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_after_comma = true
|
||||
csharp_space_after_dot = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_after_semicolon_in_for_statement = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_around_declaration_statements = do_not_ignore
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_before_dot = false
|
||||
csharp_space_before_open_square_brackets = false
|
||||
csharp_space_before_semicolon_in_for_statement = false
|
||||
csharp_space_between_empty_square_brackets = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_between_square_brackets = false
|
||||
# Wrapping preferences
|
||||
csharp_preserve_single_line_statements = true
|
||||
csharp_preserve_single_line_blocks = true
|
||||
@@ -9,8 +9,11 @@
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<MSBuildTreatWarningsAsErrors>true</MSBuildTreatWarningsAsErrors>
|
||||
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||
<AnalysisLevel>preview</AnalysisLevel>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<NoWarn>$(NoWarn);NU5105</NoWarn>
|
||||
<NoWarn>$(NoWarn);NU5105</NoWarn>
|
||||
<RestoreSources>
|
||||
https://api.nuget.org/v3/index.json;
|
||||
</RestoreSources>
|
||||
|
||||
+5
-4
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.28902.138
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.2.32208.508
|
||||
MinimumVisualStudioVersion = 15.0.26124.0
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E877EBA4-E78B-4F7D-A2D3-1E070FED04CD}"
|
||||
EndProject
|
||||
@@ -27,6 +27,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "coverlet.tests.projectsampl
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{77A15177-8262-488F-AF2B-91B9055715DA}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
.gitignore = .gitignore
|
||||
eng\azure-pipelines-nightly.yml = eng\azure-pipelines-nightly.yml
|
||||
eng\azure-pipelines.yml = eng\azure-pipelines.yml
|
||||
@@ -53,9 +54,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{9A8B19D4
|
||||
test\Directory.Build.targets = test\Directory.Build.targets
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "coverlet.tests.projectsample.fsharp", "test\coverlet.tests.projectsample.fsharp\coverlet.tests.projectsample.fsharp.fsproj", "{1CBF6966-2A67-4D2C-8598-D174B83072F4}"
|
||||
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "coverlet.tests.projectsample.fsharp", "test\coverlet.tests.projectsample.fsharp\coverlet.tests.projectsample.fsharp.fsproj", "{1CBF6966-2A67-4D2C-8598-D174B83072F4}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "coverlet.tests.projectsample.netframework", "test\coverlet.tests.projectsample.netframework\coverlet.tests.projectsample.netframework.csproj", "{E69D68C9-78ED-4076-A14B-D07295A4B2A5}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "coverlet.tests.projectsample.netframework", "test\coverlet.tests.projectsample.netframework\coverlet.tests.projectsample.netframework.csproj", "{E69D68C9-78ED-4076-A14B-D07295A4B2A5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
|
||||
using coverlet.collector.Resources;
|
||||
using Coverlet.Collector.Utilities;
|
||||
using Coverlet.Collector.Utilities.Interfaces;
|
||||
@@ -50,7 +52,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
_reportDirectory = Path.Combine(Path.GetTempPath(), reportDirectoryName);
|
||||
|
||||
// Register events
|
||||
_dataSink.SendFileCompleted += this.OnSendFileCompleted;
|
||||
_dataSink.SendFileCompleted += OnSendFileCompleted;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -61,10 +63,10 @@ namespace Coverlet.Collector.DataCollection
|
||||
public void SendCoverageReport(string coverageReport, string coverageReportFileName)
|
||||
{
|
||||
// Save coverage report to file
|
||||
string coverageReportPath = this.SaveCoverageReport(coverageReport, coverageReportFileName);
|
||||
string coverageReportPath = SaveCoverageReport(coverageReport, coverageReportFileName);
|
||||
|
||||
// Send coverage attachment to test platform.
|
||||
this.SendAttachment(coverageReportPath);
|
||||
SendAttachment(coverageReportPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -78,9 +80,9 @@ namespace Coverlet.Collector.DataCollection
|
||||
_countDownEvent.Wait();
|
||||
if (_dataSink != null)
|
||||
{
|
||||
_dataSink.SendFileCompleted -= this.OnSendFileCompleted;
|
||||
_dataSink.SendFileCompleted -= OnSendFileCompleted;
|
||||
}
|
||||
this.CleanupReportDirectory();
|
||||
CleanupReportDirectory();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -77,8 +80,8 @@ namespace Coverlet.Collector.DataCollection
|
||||
public IEnumerable<(string report, string fileName)> GetCoverageReports()
|
||||
{
|
||||
// Get coverage result
|
||||
CoverageResult coverageResult = this.GetCoverageResult();
|
||||
return this.GetCoverageReports(coverageResult);
|
||||
CoverageResult coverageResult = GetCoverageResult();
|
||||
return GetCoverageReports(coverageResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Coverlet.Collector.Utilities.Interfaces;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Coverlet.Collector.Utilities.Interfaces;
|
||||
using Coverlet.Core;
|
||||
using Coverlet.Core.Abstractions;
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
@@ -124,7 +127,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
try
|
||||
{
|
||||
// Get coverlet settings
|
||||
IEnumerable<string> testModules = this.GetTestModules(sessionStartEventArgs);
|
||||
IEnumerable<string> testModules = GetTestModules(sessionStartEventArgs);
|
||||
var coverletSettingsParser = new CoverletSettingsParser(_eqtTrace);
|
||||
CoverletSettings coverletSettings = coverletSettingsParser.Parse(_configurationElement, testModules);
|
||||
|
||||
@@ -142,7 +145,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex.ToString());
|
||||
this.Dispose(true);
|
||||
Dispose(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +182,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex.ToString());
|
||||
this.Dispose(true);
|
||||
Dispose(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Coverlet.Collector.Utilities;
|
||||
using Coverlet.Core.Abstractions;
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Linq;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Coverlet.Collector.DataCollection
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
@@ -89,7 +92,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
if (configurationElement != null)
|
||||
{
|
||||
XmlElement reportFormatElement = configurationElement[CoverletConstants.ReportFormatElementName];
|
||||
formats = this.SplitElement(reportFormatElement);
|
||||
formats = SplitElement(reportFormatElement);
|
||||
}
|
||||
|
||||
return formats is null || formats.Length == 0 ? new[] { CoverletConstants.DefaultReportFormat } : formats;
|
||||
@@ -103,7 +106,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
private string[] ParseIncludeFilters(XmlElement configurationElement)
|
||||
{
|
||||
XmlElement includeFiltersElement = configurationElement[CoverletConstants.IncludeFiltersElementName];
|
||||
return this.SplitElement(includeFiltersElement);
|
||||
return SplitElement(includeFiltersElement);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -114,7 +117,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
private string[] ParseIncludeDirectories(XmlElement configurationElement)
|
||||
{
|
||||
XmlElement includeDirectoriesElement = configurationElement[CoverletConstants.IncludeDirectoriesElementName];
|
||||
return this.SplitElement(includeDirectoriesElement);
|
||||
return SplitElement(includeDirectoriesElement);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -124,12 +127,12 @@ namespace Coverlet.Collector.DataCollection
|
||||
/// <returns>Filters to exclude</returns>
|
||||
private string[] ParseExcludeFilters(XmlElement configurationElement)
|
||||
{
|
||||
List<string> excludeFilters = new List<string> { CoverletConstants.DefaultExcludeFilter };
|
||||
var excludeFilters = new List<string> { CoverletConstants.DefaultExcludeFilter };
|
||||
|
||||
if (configurationElement != null)
|
||||
{
|
||||
XmlElement excludeFiltersElement = configurationElement[CoverletConstants.ExcludeFiltersElementName];
|
||||
string[] filters = this.SplitElement(excludeFiltersElement);
|
||||
string[] filters = SplitElement(excludeFiltersElement);
|
||||
if (filters != null)
|
||||
{
|
||||
excludeFilters.AddRange(filters);
|
||||
@@ -147,7 +150,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
private string[] ParseExcludeSourceFiles(XmlElement configurationElement)
|
||||
{
|
||||
XmlElement excludeSourceFilesElement = configurationElement[CoverletConstants.ExcludeSourceFilesElementName];
|
||||
return this.SplitElement(excludeSourceFilesElement);
|
||||
return SplitElement(excludeSourceFilesElement);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -158,7 +161,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
private string[] ParseExcludeAttributes(XmlElement configurationElement)
|
||||
{
|
||||
XmlElement excludeAttributesElement = configurationElement[CoverletConstants.ExcludeAttributesElementName];
|
||||
return this.SplitElement(excludeAttributesElement);
|
||||
return SplitElement(excludeAttributesElement);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -240,7 +243,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
private string[] ParseDoesNotReturnAttributes(XmlElement configurationElement)
|
||||
{
|
||||
XmlElement doesNotReturnAttributesElement = configurationElement[CoverletConstants.DoesNotReturnAttributesElementName];
|
||||
return this.SplitElement(doesNotReturnAttributesElement);
|
||||
return SplitElement(doesNotReturnAttributesElement);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
using coverlet.collector.Resources;
|
||||
using Coverlet.Collector.Utilities;
|
||||
using Coverlet.Core.Instrumentation;
|
||||
@@ -53,7 +55,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
|
||||
public void TestSessionEnd(TestSessionEndArgs testSessionEndArgs)
|
||||
{
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
Type injectedInstrumentationClass = GetInstrumentationClass(assembly);
|
||||
if (injectedInstrumentationClass is null)
|
||||
@@ -64,7 +66,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
try
|
||||
{
|
||||
_eqtTrace.Verbose($"Calling ModuleTrackerTemplate.UnloadModule for '{injectedInstrumentationClass.Assembly.FullName}'");
|
||||
var unloadModule = injectedInstrumentationClass.GetMethod(nameof(ModuleTrackerTemplate.UnloadModule), new[] { typeof(object), typeof(EventArgs) });
|
||||
MethodInfo unloadModule = injectedInstrumentationClass.GetMethod(nameof(ModuleTrackerTemplate.UnloadModule), new[] { typeof(object), typeof(EventArgs) });
|
||||
unloadModule.Invoke(null, new[] { (object)this, EventArgs.Empty });
|
||||
injectedInstrumentationClass.GetField("FlushHitFile", BindingFlags.Static | BindingFlags.Public).SetValue(null, false);
|
||||
_eqtTrace.Verbose($"Called ModuleTrackerTemplate.UnloadModule for '{injectedInstrumentationClass.Assembly.FullName}'");
|
||||
@@ -89,7 +91,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var type in assembly.GetTypes())
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
{
|
||||
if (type.Namespace == "Coverlet.Core.Instrumentation.Tracker"
|
||||
&& type.Name.StartsWith(assembly.GetName().Name + "_"))
|
||||
@@ -104,7 +106,7 @@ namespace Coverlet.Collector.DataCollection
|
||||
{
|
||||
if (_enableExceptionLog)
|
||||
{
|
||||
StringBuilder exceptionString = new StringBuilder();
|
||||
var exceptionString = new StringBuilder();
|
||||
exceptionString.AppendFormat("{0}: Failed to get Instrumentation class for assembly '{1}' with error: {2}",
|
||||
CoverletConstants.InProcDataCollectorName, assembly, ex);
|
||||
exceptionString.AppendLine();
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Coverlet.Collector.Utilities.Interfaces;
|
||||
|
||||
namespace Coverlet.Collector.Utilities
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace Coverlet.Collector.Utilities
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Coverlet.Collector.Utilities
|
||||
{
|
||||
internal static class CoverletConstants
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Coverlet.Collector.Utilities
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.IO;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using Coverlet.Collector.Utilities.Interfaces;
|
||||
|
||||
namespace Coverlet.Collector.Utilities
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.IO;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using Coverlet.Collector.Utilities.Interfaces;
|
||||
|
||||
namespace Coverlet.Collector.Utilities
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Coverlet.Collector.Utilities.Interfaces
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Coverlet.Collector.DataCollection;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Coverlet.Collector.DataCollection;
|
||||
using Coverlet.Core;
|
||||
using Coverlet.Core.Abstractions;
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace Coverlet.Collector.Utilities.Interfaces
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Coverlet.Collector.Utilities.Interfaces
|
||||
{
|
||||
interface IDirectoryHelper
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace Coverlet.Collector.Utilities.Interfaces
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Coverlet.Collector.Utilities.Interfaces
|
||||
{
|
||||
internal interface IFileHelper
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
|
||||
|
||||
namespace Coverlet.Collector.Utilities
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection;
|
||||
|
||||
namespace Coverlet.Collector.Utilities
|
||||
{
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# top-most EditorConfig file
|
||||
# We don't want to import other EditorConfig files and we want
|
||||
# to ensure no rules are enabled for these asset source files.
|
||||
root = true
|
||||
|
||||
[*.cs]
|
||||
# Default severity for all analyzer diagnostics
|
||||
dotnet_analyzer_diagnostic.severity = none
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Exit Codes returned from Coverlet console process.
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Coverlet.Core.Abstractions;
|
||||
using static System.Console;
|
||||
@@ -39,4 +42,4 @@ namespace Coverlet.Console.Logging
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Coverlet.Console.Logging
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
@@ -6,7 +9,6 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using ConsoleTables;
|
||||
using Coverlet.Console.Logging;
|
||||
using Coverlet.Core;
|
||||
@@ -37,7 +39,7 @@ namespace Coverlet.Console
|
||||
ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
|
||||
var logger = (ConsoleLogger)serviceProvider.GetService<ILogger>();
|
||||
var fileSystem = serviceProvider.GetService<IFileSystem>();
|
||||
IFileSystem fileSystem = serviceProvider.GetService<IFileSystem>();
|
||||
|
||||
var app = new CommandLineApplication
|
||||
{
|
||||
@@ -134,15 +136,15 @@ namespace Coverlet.Console
|
||||
|
||||
process.WaitForExit();
|
||||
|
||||
var dOutput = output.HasValue() ? output.Value() : Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar.ToString();
|
||||
var dThresholdTypes = thresholdTypes.HasValue() ? thresholdTypes.Values : new List<string>(new string[] { "line", "branch", "method" });
|
||||
var dThresholdStat = thresholdStat.HasValue() ? Enum.Parse<ThresholdStatistic>(thresholdStat.Value(), true) : Enum.Parse<ThresholdStatistic>("minimum", true);
|
||||
string dOutput = output.HasValue() ? output.Value() : Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar.ToString();
|
||||
List<string> dThresholdTypes = thresholdTypes.HasValue() ? thresholdTypes.Values : new List<string>(new string[] { "line", "branch", "method" });
|
||||
ThresholdStatistic dThresholdStat = thresholdStat.HasValue() ? Enum.Parse<ThresholdStatistic>(thresholdStat.Value(), true) : Enum.Parse<ThresholdStatistic>("minimum", true);
|
||||
|
||||
logger.LogInformation("\nCalculating coverage result...");
|
||||
|
||||
var result = coverage.GetCoverageResult();
|
||||
|
||||
var directory = Path.GetDirectoryName(dOutput);
|
||||
CoverageResult result = coverage.GetCoverageResult();
|
||||
|
||||
string directory = Path.GetDirectoryName(dOutput);
|
||||
if (directory == string.Empty)
|
||||
{
|
||||
directory = Directory.GetCurrentDirectory();
|
||||
@@ -152,9 +154,9 @@ namespace Coverlet.Console
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
foreach (var format in formats.HasValue() ? formats.Values : new List<string>(new string[] { "json" }))
|
||||
foreach (string format in formats.HasValue() ? formats.Values : new List<string>(new string[] { "json" }))
|
||||
{
|
||||
var reporter = new ReporterFactory(format).CreateReporter();
|
||||
Core.Abstractions.IReporter reporter = new ReporterFactory(format).CreateReporter();
|
||||
if (reporter == null)
|
||||
{
|
||||
throw new Exception($"Specified output format '{format}' is not supported");
|
||||
@@ -169,19 +171,19 @@ namespace Coverlet.Console
|
||||
else
|
||||
{
|
||||
// Output to file
|
||||
var filename = Path.GetFileName(dOutput);
|
||||
string filename = Path.GetFileName(dOutput);
|
||||
filename = (filename == string.Empty) ? $"coverage.{reporter.Extension}" : filename;
|
||||
filename = Path.HasExtension(filename) ? filename : $"{filename}.{reporter.Extension}";
|
||||
|
||||
var report = Path.Combine(directory, filename);
|
||||
string report = Path.Combine(directory, filename);
|
||||
logger.LogInformation($" Generating report '{report}'", important: true);
|
||||
fileSystem.WriteAllText(report, reporter.Report(result, sourceRootTranslator));
|
||||
}
|
||||
}
|
||||
|
||||
var thresholdTypeFlagQueue = new Queue<ThresholdTypeFlags>();
|
||||
|
||||
foreach (var thresholdType in dThresholdTypes)
|
||||
|
||||
foreach (string thresholdType in dThresholdTypes)
|
||||
{
|
||||
if (thresholdType.Equals("line", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -196,19 +198,19 @@ namespace Coverlet.Console
|
||||
thresholdTypeFlagQueue.Enqueue(ThresholdTypeFlags.Method);
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<ThresholdTypeFlags, double> thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>();
|
||||
|
||||
var thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>();
|
||||
if (threshold.HasValue() && threshold.Value().Contains(','))
|
||||
{
|
||||
var thresholdValues = threshold.Value().Split(',', StringSplitOptions.RemoveEmptyEntries).Select(t => t.Trim());
|
||||
if (thresholdValues.Count() != thresholdTypeFlagQueue.Count())
|
||||
IEnumerable<string> thresholdValues = threshold.Value().Split(',', StringSplitOptions.RemoveEmptyEntries).Select(t => t.Trim());
|
||||
if (thresholdValues.Count() != thresholdTypeFlagQueue.Count)
|
||||
{
|
||||
throw new Exception($"Threshold type flag count ({thresholdTypeFlagQueue.Count()}) and values count ({thresholdValues.Count()}) doesn't match");
|
||||
throw new Exception($"Threshold type flag count ({thresholdTypeFlagQueue.Count}) and values count ({thresholdValues.Count()}) doesn't match");
|
||||
}
|
||||
|
||||
foreach (var thresholdValue in thresholdValues)
|
||||
foreach (string thresholdValue in thresholdValues)
|
||||
{
|
||||
if (double.TryParse(thresholdValue, out var value))
|
||||
if (double.TryParse(thresholdValue, out double value))
|
||||
{
|
||||
thresholdTypeFlagValues[thresholdTypeFlagQueue.Dequeue()] = value;
|
||||
}
|
||||
@@ -231,23 +233,23 @@ namespace Coverlet.Console
|
||||
var coverageTable = new ConsoleTable("Module", "Line", "Branch", "Method");
|
||||
var summary = new CoverageSummary();
|
||||
|
||||
var linePercentCalculation = summary.CalculateLineCoverage(result.Modules);
|
||||
var branchPercentCalculation = summary.CalculateBranchCoverage(result.Modules);
|
||||
var methodPercentCalculation = summary.CalculateMethodCoverage(result.Modules);
|
||||
CoverageDetails linePercentCalculation = summary.CalculateLineCoverage(result.Modules);
|
||||
CoverageDetails branchPercentCalculation = summary.CalculateBranchCoverage(result.Modules);
|
||||
CoverageDetails methodPercentCalculation = summary.CalculateMethodCoverage(result.Modules);
|
||||
|
||||
var totalLinePercent = linePercentCalculation.Percent;
|
||||
var totalBranchPercent = branchPercentCalculation.Percent;
|
||||
var totalMethodPercent = methodPercentCalculation.Percent;
|
||||
double totalLinePercent = linePercentCalculation.Percent;
|
||||
double totalBranchPercent = branchPercentCalculation.Percent;
|
||||
double totalMethodPercent = methodPercentCalculation.Percent;
|
||||
|
||||
var averageLinePercent = linePercentCalculation.AverageModulePercent;
|
||||
var averageBranchPercent = branchPercentCalculation.AverageModulePercent;
|
||||
var averageMethodPercent = methodPercentCalculation.AverageModulePercent;
|
||||
double averageLinePercent = linePercentCalculation.AverageModulePercent;
|
||||
double averageBranchPercent = branchPercentCalculation.AverageModulePercent;
|
||||
double averageMethodPercent = methodPercentCalculation.AverageModulePercent;
|
||||
|
||||
foreach (var _module in result.Modules)
|
||||
foreach (KeyValuePair<string, Documents> _module in result.Modules)
|
||||
{
|
||||
var linePercent = summary.CalculateLineCoverage(_module.Value).Percent;
|
||||
var branchPercent = summary.CalculateBranchCoverage(_module.Value).Percent;
|
||||
var methodPercent = summary.CalculateMethodCoverage(_module.Value).Percent;
|
||||
double linePercent = summary.CalculateLineCoverage(_module.Value).Percent;
|
||||
double branchPercent = summary.CalculateBranchCoverage(_module.Value).Percent;
|
||||
double methodPercent = summary.CalculateMethodCoverage(_module.Value).Percent;
|
||||
|
||||
coverageTable.AddRow(Path.GetFileNameWithoutExtension(_module.Key), $"{InvariantFormat(linePercent)}%", $"{InvariantFormat(branchPercent)}%", $"{InvariantFormat(methodPercent)}%");
|
||||
}
|
||||
@@ -266,15 +268,15 @@ namespace Coverlet.Console
|
||||
{
|
||||
exitCode += (int)CommandExitCodes.TestFailed;
|
||||
}
|
||||
|
||||
var thresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, thresholdTypeFlagValues, dThresholdStat);
|
||||
|
||||
ThresholdTypeFlags thresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, thresholdTypeFlagValues, dThresholdStat);
|
||||
if (thresholdTypeFlags != ThresholdTypeFlags.None)
|
||||
{
|
||||
exitCode += (int)CommandExitCodes.CoverageBelowThreshold;
|
||||
var exceptionMessageBuilder = new StringBuilder();
|
||||
if ((thresholdTypeFlags & ThresholdTypeFlags.Line) != ThresholdTypeFlags.None)
|
||||
{
|
||||
exceptionMessageBuilder.AppendLine($"The {dThresholdStat.ToString().ToLower()} line coverage is below the specified {thresholdTypeFlagValues[ThresholdTypeFlags.Line]}");
|
||||
exceptionMessageBuilder.AppendLine($"The {dThresholdStat.ToString().ToLower()} line coverage is below the specified {thresholdTypeFlagValues[ThresholdTypeFlags.Line]}");
|
||||
}
|
||||
|
||||
if ((thresholdTypeFlags & ThresholdTypeFlags.Branch) != ThresholdTypeFlags.None)
|
||||
@@ -284,7 +286,7 @@ namespace Coverlet.Console
|
||||
|
||||
if ((thresholdTypeFlags & ThresholdTypeFlags.Method) != ThresholdTypeFlags.None)
|
||||
{
|
||||
exceptionMessageBuilder.AppendLine($"The {dThresholdStat.ToString().ToLower()} method coverage is below the specified {thresholdTypeFlagValues[ThresholdTypeFlags.Method]}");
|
||||
exceptionMessageBuilder.AppendLine($"The {dThresholdStat.ToString().ToLower()} method coverage is below the specified {thresholdTypeFlagValues[ThresholdTypeFlags.Method]}");
|
||||
}
|
||||
throw new Exception(exceptionMessageBuilder.ToString());
|
||||
}
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
[assembly: System.Reflection.AssemblyKeyFileAttribute("coverlet.console.snk")]
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Coverlet.Core.Symbols;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace Coverlet.Core.Abstractions
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Coverlet.Core.Abstractions
|
||||
{
|
||||
internal interface IConsole
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.IO;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace Coverlet.Core.Abstractions
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace Coverlet.Core.Abstractions
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Coverlet.Core.Abstractions
|
||||
{
|
||||
internal interface IInstrumentationHelper
|
||||
{
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Coverlet.Core.Abstractions
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Coverlet.Core.Abstractions
|
||||
{
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Coverlet.Core.Abstractions
|
||||
{
|
||||
internal interface IReporter
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Coverlet.Core.Abstractions
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Coverlet.Core.Helpers;
|
||||
|
||||
namespace Coverlet.Core.Abstractions
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Coverlet.Core.Attributes
|
||||
{
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Coverlet.Core.Attributes
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -6,7 +9,6 @@ using System.Runtime.Serialization;
|
||||
using Coverlet.Core.Abstractions;
|
||||
using Coverlet.Core.Helpers;
|
||||
using Coverlet.Core.Instrumentation;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
@@ -45,20 +47,16 @@ namespace Coverlet.Core
|
||||
|
||||
internal class Coverage
|
||||
{
|
||||
private string _moduleOrAppDirectory;
|
||||
private string _identifier;
|
||||
private ILogger _logger;
|
||||
private IInstrumentationHelper _instrumentationHelper;
|
||||
private IFileSystem _fileSystem;
|
||||
private ISourceRootTranslator _sourceRootTranslator;
|
||||
private ICecilSymbolHelper _cecilSymbolHelper;
|
||||
private List<InstrumenterResult> _results;
|
||||
private CoverageParameters _parameters;
|
||||
private readonly string _moduleOrAppDirectory;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IInstrumentationHelper _instrumentationHelper;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly ISourceRootTranslator _sourceRootTranslator;
|
||||
private readonly ICecilSymbolHelper _cecilSymbolHelper;
|
||||
private readonly List<InstrumenterResult> _results;
|
||||
private readonly CoverageParameters _parameters;
|
||||
|
||||
public string Identifier
|
||||
{
|
||||
get { return _identifier; }
|
||||
}
|
||||
public string Identifier { get; }
|
||||
|
||||
public Coverage(string moduleOrDirectory,
|
||||
CoverageParameters parameters,
|
||||
@@ -76,7 +74,7 @@ namespace Coverlet.Core
|
||||
_fileSystem = fileSystem;
|
||||
_sourceRootTranslator = sourceRootTranslator;
|
||||
_cecilSymbolHelper = cecilSymbolHelper;
|
||||
_identifier = Guid.NewGuid().ToString();
|
||||
Identifier = Guid.NewGuid().ToString();
|
||||
_results = new List<InstrumenterResult>();
|
||||
}
|
||||
|
||||
@@ -86,7 +84,7 @@ namespace Coverlet.Core
|
||||
IFileSystem fileSystem,
|
||||
ISourceRootTranslator sourceRootTranslator)
|
||||
{
|
||||
_identifier = prepareResult.Identifier;
|
||||
Identifier = prepareResult.Identifier;
|
||||
_moduleOrAppDirectory = prepareResult.ModuleOrDirectory;
|
||||
_parameters = prepareResult.Parameters;
|
||||
_results = new List<InstrumenterResult>(prepareResult.Results);
|
||||
@@ -107,7 +105,7 @@ namespace Coverlet.Core
|
||||
_parameters.ExcludeFilters = _parameters.ExcludeFilters?.Where(f => _instrumentationHelper.IsValidFilterExpression(f)).ToArray();
|
||||
_parameters.IncludeFilters = _parameters.IncludeFilters?.Where(f => _instrumentationHelper.IsValidFilterExpression(f)).ToArray();
|
||||
|
||||
foreach (var module in modules)
|
||||
foreach (string module in modules)
|
||||
{
|
||||
if (_instrumentationHelper.IsModuleExcluded(module, _parameters.ExcludeFilters) ||
|
||||
!_instrumentationHelper.IsModuleIncluded(module, _parameters.IncludeFilters))
|
||||
@@ -117,7 +115,7 @@ namespace Coverlet.Core
|
||||
}
|
||||
|
||||
var instrumenter = new Instrumenter(module,
|
||||
_identifier,
|
||||
Identifier,
|
||||
_parameters,
|
||||
_logger,
|
||||
_instrumentationHelper,
|
||||
@@ -127,7 +125,7 @@ namespace Coverlet.Core
|
||||
|
||||
if (instrumenter.CanInstrument())
|
||||
{
|
||||
_instrumentationHelper.BackupOriginalModule(module, _identifier);
|
||||
_instrumentationHelper.BackupOriginalModule(module, Identifier);
|
||||
|
||||
// Guard code path and restore if instrumentation fails.
|
||||
try
|
||||
@@ -142,14 +140,14 @@ namespace Coverlet.Core
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning($"Unable to instrument module: {module}\n{ex}");
|
||||
_instrumentationHelper.RestoreOriginalModule(module, _identifier);
|
||||
_instrumentationHelper.RestoreOriginalModule(module, Identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new CoveragePrepareResult()
|
||||
{
|
||||
Identifier = _identifier,
|
||||
Identifier = Identifier,
|
||||
ModuleOrDirectory = _moduleOrAppDirectory,
|
||||
Parameters = _parameters,
|
||||
Results = _results.ToArray()
|
||||
@@ -160,14 +158,14 @@ namespace Coverlet.Core
|
||||
{
|
||||
CalculateCoverage();
|
||||
|
||||
Modules modules = new Modules();
|
||||
foreach (var result in _results)
|
||||
var modules = new Modules();
|
||||
foreach (InstrumenterResult result in _results)
|
||||
{
|
||||
Documents documents = new Documents();
|
||||
foreach (var doc in result.Documents.Values)
|
||||
var documents = new Documents();
|
||||
foreach (Document doc in result.Documents.Values)
|
||||
{
|
||||
// Construct Line Results
|
||||
foreach (var line in doc.Lines.Values)
|
||||
foreach (Line line in doc.Lines.Values)
|
||||
{
|
||||
if (documents.TryGetValue(doc.Path, out Classes classes))
|
||||
{
|
||||
@@ -200,7 +198,7 @@ namespace Coverlet.Core
|
||||
}
|
||||
|
||||
// Construct Branch Results
|
||||
foreach (var branch in doc.Branches.Values)
|
||||
foreach (Branch branch in doc.Branches.Values)
|
||||
{
|
||||
if (documents.TryGetValue(doc.Path, out Classes classes))
|
||||
{
|
||||
@@ -242,7 +240,7 @@ namespace Coverlet.Core
|
||||
}
|
||||
|
||||
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.
|
||||
@@ -250,11 +248,11 @@ namespace Coverlet.Core
|
||||
// We search "method" with same "Line" of closure class method and add missing branches to it,
|
||||
// in this way we correctly report missing branch inside compiled generated anonymous delegate.
|
||||
List<string> compileGeneratedClassToRemove = null;
|
||||
foreach (var module in modules)
|
||||
foreach (KeyValuePair<string, Documents> module in modules)
|
||||
{
|
||||
foreach (var document in module.Value)
|
||||
foreach (KeyValuePair<string, Classes> document in module.Value)
|
||||
{
|
||||
foreach (var @class in document.Value)
|
||||
foreach (KeyValuePair<string, Methods> @class in document.Value)
|
||||
{
|
||||
// We fix only lamda generated class
|
||||
// https://github.com/dotnet/roslyn/blob/master/src/Compilers/CSharp/Portable/Symbols/Synthesized/GeneratedNameKind.cs#L18
|
||||
@@ -263,9 +261,9 @@ namespace Coverlet.Core
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var method in @class.Value)
|
||||
foreach (KeyValuePair<string, Method> method in @class.Value)
|
||||
{
|
||||
foreach (var branch in method.Value.Branches)
|
||||
foreach (BranchInfo branch in method.Value.Branches)
|
||||
{
|
||||
if (BranchInCompilerGeneratedClass(method.Key))
|
||||
{
|
||||
@@ -295,13 +293,13 @@ namespace Coverlet.Core
|
||||
}
|
||||
|
||||
// After method/branches analysis of compiled generated class we can remove noise from reports
|
||||
if (!(compileGeneratedClassToRemove is null))
|
||||
if (compileGeneratedClassToRemove is not null)
|
||||
{
|
||||
foreach (var module in modules)
|
||||
foreach (KeyValuePair<string, Documents> module in modules)
|
||||
{
|
||||
foreach (var document in module.Value)
|
||||
foreach (KeyValuePair<string, Classes> document in module.Value)
|
||||
{
|
||||
foreach (var classToRemove in compileGeneratedClassToRemove)
|
||||
foreach (string classToRemove in compileGeneratedClassToRemove)
|
||||
{
|
||||
document.Value.Remove(classToRemove);
|
||||
}
|
||||
@@ -309,7 +307,7 @@ namespace Coverlet.Core
|
||||
}
|
||||
}
|
||||
|
||||
var coverageResult = new CoverageResult { Identifier = _identifier, Modules = modules, InstrumentedResults = _results, Parameters = _parameters };
|
||||
var coverageResult = new CoverageResult { Identifier = Identifier, Modules = modules, InstrumentedResults = _results, Parameters = _parameters };
|
||||
|
||||
if (!string.IsNullOrEmpty(_parameters.MergeWith) && !string.IsNullOrWhiteSpace(_parameters.MergeWith) && _fileSystem.Exists(_parameters.MergeWith))
|
||||
{
|
||||
@@ -322,7 +320,7 @@ namespace Coverlet.Core
|
||||
|
||||
private bool BranchInCompilerGeneratedClass(string methodName)
|
||||
{
|
||||
foreach (var instrumentedResult in _results)
|
||||
foreach (InstrumenterResult instrumentedResult in _results)
|
||||
{
|
||||
if (instrumentedResult.BranchesInCompiledGeneratedClass.Contains(methodName))
|
||||
{
|
||||
@@ -334,16 +332,16 @@ namespace Coverlet.Core
|
||||
|
||||
private Method GetMethodWithSameLineInSameDocument(Classes documentClasses, string compilerGeneratedClassName, int branchLine)
|
||||
{
|
||||
foreach (var @class in documentClasses)
|
||||
foreach (KeyValuePair<string, Methods> @class in documentClasses)
|
||||
{
|
||||
if (@class.Key == compilerGeneratedClassName)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var method in @class.Value)
|
||||
foreach (KeyValuePair<string, Method> method in @class.Value)
|
||||
{
|
||||
foreach (var line in method.Value.Lines)
|
||||
foreach (KeyValuePair<int, int> line in method.Value.Lines)
|
||||
{
|
||||
if (line.Key == branchLine)
|
||||
{
|
||||
@@ -357,7 +355,7 @@ namespace Coverlet.Core
|
||||
|
||||
private void CalculateCoverage()
|
||||
{
|
||||
foreach (var result in _results)
|
||||
foreach (InstrumenterResult result in _results)
|
||||
{
|
||||
if (!_fileSystem.Exists(result.HitsFilePath))
|
||||
{
|
||||
@@ -369,12 +367,12 @@ namespace Coverlet.Core
|
||||
continue;
|
||||
}
|
||||
|
||||
List<Document> documents = result.Documents.Values.ToList();
|
||||
var documents = result.Documents.Values.ToList();
|
||||
if (_parameters.UseSourceLink && result.SourceLink != null)
|
||||
{
|
||||
var jObject = JObject.Parse(result.SourceLink)["documents"];
|
||||
var sourceLinkDocuments = JsonConvert.DeserializeObject<Dictionary<string, string>>(jObject.ToString());
|
||||
foreach (var document in documents)
|
||||
JToken jObject = JObject.Parse(result.SourceLink)["documents"];
|
||||
Dictionary<string, string> sourceLinkDocuments = JsonConvert.DeserializeObject<Dictionary<string, string>>(jObject.ToString());
|
||||
foreach (Document document in documents)
|
||||
{
|
||||
document.Path = GetSourceLinkUrl(sourceLinkDocuments, document.Path);
|
||||
}
|
||||
@@ -408,7 +406,7 @@ namespace Coverlet.Core
|
||||
}
|
||||
|
||||
var documentsList = result.Documents.Values.ToList();
|
||||
using (var fs = _fileSystem.NewFileStream(result.HitsFilePath, FileMode.Open, FileAccess.Read))
|
||||
using (Stream fs = _fileSystem.NewFileStream(result.HitsFilePath, FileMode.Open, FileAccess.Read))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
int hitCandidatesCount = br.ReadInt32();
|
||||
@@ -417,8 +415,8 @@ namespace Coverlet.Core
|
||||
|
||||
for (int i = 0; i < hitCandidatesCount; ++i)
|
||||
{
|
||||
var hitLocation = result.HitCandidates[i];
|
||||
var document = documentsList[hitLocation.docIndex];
|
||||
HitCandidate hitLocation = result.HitCandidates[i];
|
||||
Document document = documentsList[hitLocation.docIndex];
|
||||
int hits = br.ReadInt32();
|
||||
|
||||
if (hits == 0)
|
||||
@@ -428,7 +426,7 @@ namespace Coverlet.Core
|
||||
|
||||
if (hitLocation.isBranch)
|
||||
{
|
||||
var branch = document.Branches[new BranchKey(hitLocation.start, hitLocation.end)];
|
||||
Branch branch = document.Branches[new BranchKey(hitLocation.start, hitLocation.end)];
|
||||
branch.Hits += hits;
|
||||
|
||||
if (branch.Hits < 0)
|
||||
@@ -443,7 +441,7 @@ namespace Coverlet.Core
|
||||
continue;
|
||||
}
|
||||
|
||||
var line = document.Lines[j];
|
||||
Line line = document.Lines[j];
|
||||
line.Hits += hits;
|
||||
|
||||
if (line.Hits < 0)
|
||||
@@ -472,10 +470,10 @@ namespace Coverlet.Core
|
||||
return url;
|
||||
}
|
||||
|
||||
var keyWithBestMatch = string.Empty;
|
||||
var relativePathOfBestMatch = string.Empty;
|
||||
string keyWithBestMatch = string.Empty;
|
||||
string relativePathOfBestMatch = string.Empty;
|
||||
|
||||
foreach (var sourceLinkDocument in sourceLinkDocuments)
|
||||
foreach (KeyValuePair<string, string> sourceLinkDocument in sourceLinkDocuments)
|
||||
{
|
||||
string key = sourceLinkDocument.Key;
|
||||
if (Path.GetFileName(key) != "*") continue;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Coverlet.Core
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.IO;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using Coverlet.Core.Instrumentation;
|
||||
|
||||
@@ -30,7 +33,7 @@ namespace Coverlet.Core
|
||||
|
||||
public static Stream Serialize(CoveragePrepareResult instrumentState)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
var ms = new MemoryStream();
|
||||
new DataContractSerializer(typeof(CoveragePrepareResult)).WriteObject(ms, instrumentState);
|
||||
ms.Position = 0;
|
||||
return ms;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
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
|
||||
{
|
||||
@@ -48,54 +48,54 @@ namespace Coverlet.Core
|
||||
|
||||
public void Merge(Modules modules)
|
||||
{
|
||||
foreach (var module in modules)
|
||||
foreach (KeyValuePair<string, Documents> module in modules)
|
||||
{
|
||||
if (!this.Modules.Keys.Contains(module.Key))
|
||||
if (!Modules.Keys.Contains(module.Key))
|
||||
{
|
||||
this.Modules.Add(module.Key, module.Value);
|
||||
Modules.Add(module.Key, module.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var document in module.Value)
|
||||
foreach (KeyValuePair<string, Classes> document in module.Value)
|
||||
{
|
||||
if (!this.Modules[module.Key].ContainsKey(document.Key))
|
||||
if (!Modules[module.Key].ContainsKey(document.Key))
|
||||
{
|
||||
this.Modules[module.Key].Add(document.Key, document.Value);
|
||||
Modules[module.Key].Add(document.Key, document.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var @class in document.Value)
|
||||
foreach (KeyValuePair<string, Methods> @class in document.Value)
|
||||
{
|
||||
if (!this.Modules[module.Key][document.Key].ContainsKey(@class.Key))
|
||||
if (!Modules[module.Key][document.Key].ContainsKey(@class.Key))
|
||||
{
|
||||
this.Modules[module.Key][document.Key].Add(@class.Key, @class.Value);
|
||||
Modules[module.Key][document.Key].Add(@class.Key, @class.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var method in @class.Value)
|
||||
foreach (KeyValuePair<string, Method> method in @class.Value)
|
||||
{
|
||||
if (!this.Modules[module.Key][document.Key][@class.Key].ContainsKey(method.Key))
|
||||
if (!Modules[module.Key][document.Key][@class.Key].ContainsKey(method.Key))
|
||||
{
|
||||
this.Modules[module.Key][document.Key][@class.Key].Add(method.Key, method.Value);
|
||||
Modules[module.Key][document.Key][@class.Key].Add(method.Key, method.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var line in method.Value.Lines)
|
||||
foreach (KeyValuePair<int, int> line in method.Value.Lines)
|
||||
{
|
||||
if (!this.Modules[module.Key][document.Key][@class.Key][method.Key].Lines.ContainsKey(line.Key))
|
||||
if (!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);
|
||||
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;
|
||||
Modules[module.Key][document.Key][@class.Key][method.Key].Lines[line.Key] += line.Value;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var branch in method.Value.Branches)
|
||||
foreach (BranchInfo 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);
|
||||
Branches branches = Modules[module.Key][document.Key][@class.Key][method.Key].Branches;
|
||||
BranchInfo 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
|
||||
@@ -113,7 +113,7 @@ namespace Coverlet.Core
|
||||
|
||||
public ThresholdTypeFlags GetThresholdTypesBelowThreshold(CoverageSummary summary, Dictionary<ThresholdTypeFlags, double> thresholdTypeFlagValues, ThresholdStatistic thresholdStat)
|
||||
{
|
||||
var thresholdTypeFlags = ThresholdTypeFlags.None;
|
||||
ThresholdTypeFlags thresholdTypeFlags = ThresholdTypeFlags.None;
|
||||
switch (thresholdStat)
|
||||
{
|
||||
case ThresholdStatistic.Minimum:
|
||||
@@ -121,7 +121,7 @@ namespace Coverlet.Core
|
||||
if (!Modules.Any())
|
||||
thresholdTypeFlags = CompareThresholdValues(thresholdTypeFlagValues, thresholdTypeFlags, 0, 0, 0);
|
||||
|
||||
foreach (var module in Modules)
|
||||
foreach (KeyValuePair<string, Documents> module in Modules)
|
||||
{
|
||||
double line = summary.CalculateLineCoverage(module.Value).Percent;
|
||||
double branch = summary.CalculateBranchCoverage(module.Value).Percent;
|
||||
@@ -158,19 +158,19 @@ namespace Coverlet.Core
|
||||
Dictionary<ThresholdTypeFlags, double> thresholdTypeFlagValues, ThresholdTypeFlags thresholdTypeFlags,
|
||||
double line, double branch, double method)
|
||||
{
|
||||
if (thresholdTypeFlagValues.TryGetValue(ThresholdTypeFlags.Line, out var lineThresholdValue) &&
|
||||
if (thresholdTypeFlagValues.TryGetValue(ThresholdTypeFlags.Line, out double lineThresholdValue) &&
|
||||
lineThresholdValue > line)
|
||||
{
|
||||
thresholdTypeFlags |= ThresholdTypeFlags.Line;
|
||||
}
|
||||
|
||||
if (thresholdTypeFlagValues.TryGetValue(ThresholdTypeFlags.Branch, out var branchThresholdValue) &&
|
||||
if (thresholdTypeFlagValues.TryGetValue(ThresholdTypeFlags.Branch, out double branchThresholdValue) &&
|
||||
branchThresholdValue > branch)
|
||||
{
|
||||
thresholdTypeFlags |= ThresholdTypeFlags.Branch;
|
||||
}
|
||||
|
||||
if (thresholdTypeFlagValues.TryGetValue(ThresholdTypeFlags.Method, out var methodThresholdValue) &&
|
||||
if (thresholdTypeFlagValues.TryGetValue(ThresholdTypeFlags.Method, out double methodThresholdValue) &&
|
||||
methodThresholdValue > method)
|
||||
{
|
||||
thresholdTypeFlags |= ThresholdTypeFlags.Method;
|
||||
@@ -179,4 +179,4 @@ namespace Coverlet.Core
|
||||
return thresholdTypeFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -17,9 +20,9 @@ namespace Coverlet.Core
|
||||
public CoverageDetails CalculateLineCoverage(Methods methods)
|
||||
{
|
||||
var details = new CoverageDetails();
|
||||
foreach (var method in methods)
|
||||
foreach (KeyValuePair<string, Method> method in methods)
|
||||
{
|
||||
var methodCoverage = CalculateLineCoverage(method.Value.Lines);
|
||||
CoverageDetails methodCoverage = CalculateLineCoverage(method.Value.Lines);
|
||||
details.Covered += methodCoverage.Covered;
|
||||
details.Total += methodCoverage.Total;
|
||||
}
|
||||
@@ -29,9 +32,9 @@ namespace Coverlet.Core
|
||||
public CoverageDetails CalculateLineCoverage(Classes classes)
|
||||
{
|
||||
var details = new CoverageDetails();
|
||||
foreach (var @class in classes)
|
||||
foreach (KeyValuePair<string, Methods> @class in classes)
|
||||
{
|
||||
var classCoverage = CalculateLineCoverage(@class.Value);
|
||||
CoverageDetails classCoverage = CalculateLineCoverage(@class.Value);
|
||||
details.Covered += classCoverage.Covered;
|
||||
details.Total += classCoverage.Total;
|
||||
}
|
||||
@@ -41,9 +44,9 @@ namespace Coverlet.Core
|
||||
public CoverageDetails CalculateLineCoverage(Documents documents)
|
||||
{
|
||||
var details = new CoverageDetails();
|
||||
foreach (var document in documents)
|
||||
foreach (KeyValuePair<string, Classes> document in documents)
|
||||
{
|
||||
var documentCoverage = CalculateLineCoverage(document.Value);
|
||||
CoverageDetails documentCoverage = CalculateLineCoverage(document.Value);
|
||||
details.Covered += documentCoverage.Covered;
|
||||
details.Total += documentCoverage.Total;
|
||||
}
|
||||
@@ -52,15 +55,15 @@ namespace Coverlet.Core
|
||||
|
||||
public CoverageDetails CalculateLineCoverage(Modules modules)
|
||||
{
|
||||
var details = new CoverageDetails{Modules = modules};
|
||||
var accumPercent = 0.0D;
|
||||
var details = new CoverageDetails { Modules = modules };
|
||||
double accumPercent = 0.0D;
|
||||
|
||||
if (modules.Count == 0)
|
||||
return details;
|
||||
|
||||
foreach (var module in modules)
|
||||
foreach (KeyValuePair<string, Documents> module in modules)
|
||||
{
|
||||
var moduleCoverage = CalculateLineCoverage(module.Value);
|
||||
CoverageDetails moduleCoverage = CalculateLineCoverage(module.Value);
|
||||
details.Covered += moduleCoverage.Covered;
|
||||
details.Total += moduleCoverage.Total;
|
||||
accumPercent += moduleCoverage.Percent;
|
||||
@@ -86,7 +89,7 @@ namespace Coverlet.Core
|
||||
}
|
||||
|
||||
var paths = new Dictionary<int, int>();
|
||||
foreach (var branch in branches)
|
||||
foreach (BranchInfo branch in branches)
|
||||
{
|
||||
if (!paths.TryGetValue(branch.Offset, out int count))
|
||||
{
|
||||
@@ -96,7 +99,7 @@ namespace Coverlet.Core
|
||||
}
|
||||
|
||||
int npath = 1;
|
||||
foreach (var branchPoints in paths.Values)
|
||||
foreach (int branchPoints in paths.Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -154,9 +157,9 @@ namespace Coverlet.Core
|
||||
public CoverageDetails CalculateBranchCoverage(Methods methods)
|
||||
{
|
||||
var details = new CoverageDetails();
|
||||
foreach (var method in methods)
|
||||
foreach (KeyValuePair<string, Method> method in methods)
|
||||
{
|
||||
var methodCoverage = CalculateBranchCoverage(method.Value.Branches);
|
||||
CoverageDetails methodCoverage = CalculateBranchCoverage(method.Value.Branches);
|
||||
details.Covered += methodCoverage.Covered;
|
||||
details.Total += methodCoverage.Total;
|
||||
}
|
||||
@@ -166,9 +169,9 @@ namespace Coverlet.Core
|
||||
public CoverageDetails CalculateBranchCoverage(Classes classes)
|
||||
{
|
||||
var details = new CoverageDetails();
|
||||
foreach (var @class in classes)
|
||||
foreach (KeyValuePair<string, Methods> @class in classes)
|
||||
{
|
||||
var classCoverage = CalculateBranchCoverage(@class.Value);
|
||||
CoverageDetails classCoverage = CalculateBranchCoverage(@class.Value);
|
||||
details.Covered += classCoverage.Covered;
|
||||
details.Total += classCoverage.Total;
|
||||
}
|
||||
@@ -178,9 +181,9 @@ namespace Coverlet.Core
|
||||
public CoverageDetails CalculateBranchCoverage(Documents documents)
|
||||
{
|
||||
var details = new CoverageDetails();
|
||||
foreach (var document in documents)
|
||||
foreach (KeyValuePair<string, Classes> document in documents)
|
||||
{
|
||||
var documentCoverage = CalculateBranchCoverage(document.Value);
|
||||
CoverageDetails documentCoverage = CalculateBranchCoverage(document.Value);
|
||||
details.Covered += documentCoverage.Covered;
|
||||
details.Total += documentCoverage.Total;
|
||||
}
|
||||
@@ -189,15 +192,15 @@ namespace Coverlet.Core
|
||||
|
||||
public CoverageDetails CalculateBranchCoverage(Modules modules)
|
||||
{
|
||||
var details = new CoverageDetails{ Modules = modules };
|
||||
var accumPercent = 0.0D;
|
||||
var details = new CoverageDetails { Modules = modules };
|
||||
double accumPercent = 0.0D;
|
||||
|
||||
if (modules.Count == 0)
|
||||
return details;
|
||||
|
||||
foreach (var module in modules)
|
||||
foreach (KeyValuePair<string, Documents> module in modules)
|
||||
{
|
||||
var moduleCoverage = CalculateBranchCoverage(module.Value);
|
||||
CoverageDetails moduleCoverage = CalculateBranchCoverage(module.Value);
|
||||
details.Covered += moduleCoverage.Covered;
|
||||
details.Total += moduleCoverage.Total;
|
||||
accumPercent += moduleCoverage.Percent;
|
||||
@@ -217,10 +220,10 @@ namespace Coverlet.Core
|
||||
public CoverageDetails CalculateMethodCoverage(Methods methods)
|
||||
{
|
||||
var details = new CoverageDetails();
|
||||
var methodsWithLines = methods.Where(m => m.Value.Lines.Count > 0);
|
||||
foreach (var method in methodsWithLines)
|
||||
IEnumerable<KeyValuePair<string, Method>> methodsWithLines = methods.Where(m => m.Value.Lines.Count > 0);
|
||||
foreach (KeyValuePair<string, Method> method in methodsWithLines)
|
||||
{
|
||||
var methodCoverage = CalculateMethodCoverage(method.Value.Lines);
|
||||
CoverageDetails methodCoverage = CalculateMethodCoverage(method.Value.Lines);
|
||||
details.Covered += methodCoverage.Covered;
|
||||
}
|
||||
details.Total = methodsWithLines.Count();
|
||||
@@ -230,9 +233,9 @@ namespace Coverlet.Core
|
||||
public CoverageDetails CalculateMethodCoverage(Classes classes)
|
||||
{
|
||||
var details = new CoverageDetails();
|
||||
foreach (var @class in classes)
|
||||
foreach (KeyValuePair<string, Methods> @class in classes)
|
||||
{
|
||||
var classCoverage = CalculateMethodCoverage(@class.Value);
|
||||
CoverageDetails classCoverage = CalculateMethodCoverage(@class.Value);
|
||||
details.Covered += classCoverage.Covered;
|
||||
details.Total += classCoverage.Total;
|
||||
}
|
||||
@@ -242,9 +245,9 @@ namespace Coverlet.Core
|
||||
public CoverageDetails CalculateMethodCoverage(Documents documents)
|
||||
{
|
||||
var details = new CoverageDetails();
|
||||
foreach (var document in documents)
|
||||
foreach (KeyValuePair<string, Classes> document in documents)
|
||||
{
|
||||
var documentCoverage = CalculateMethodCoverage(document.Value);
|
||||
CoverageDetails documentCoverage = CalculateMethodCoverage(document.Value);
|
||||
details.Covered += documentCoverage.Covered;
|
||||
details.Total += documentCoverage.Total;
|
||||
}
|
||||
@@ -253,15 +256,15 @@ namespace Coverlet.Core
|
||||
|
||||
public CoverageDetails CalculateMethodCoverage(Modules modules)
|
||||
{
|
||||
var details = new CoverageDetails{ Modules = modules };
|
||||
var accumPercent = 0.0D;
|
||||
var details = new CoverageDetails { Modules = modules };
|
||||
double accumPercent = 0.0D;
|
||||
|
||||
if (modules.Count == 0)
|
||||
return details;
|
||||
|
||||
foreach (var module in modules)
|
||||
foreach (KeyValuePair<string, Documents> module in modules)
|
||||
{
|
||||
var moduleCoverage = CalculateMethodCoverage(module.Value);
|
||||
CoverageDetails moduleCoverage = CalculateMethodCoverage(module.Value);
|
||||
details.Covered += moduleCoverage.Covered;
|
||||
details.Total += moduleCoverage.Total;
|
||||
accumPercent += moduleCoverage.Percent;
|
||||
@@ -270,4 +273,4 @@ namespace Coverlet.Core
|
||||
return details;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Coverlet.Core.Enums
|
||||
{
|
||||
internal enum ThresholdStatistic
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Coverlet.Core.Enums
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Coverlet.Core.Exceptions
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Coverlet.Core.Attributes;
|
||||
@@ -7,10 +9,10 @@ namespace Coverlet.Core.Extensions
|
||||
internal static class HelperExtensions
|
||||
{
|
||||
[ExcludeFromCoverage]
|
||||
public static TRet Maybe<T, TRet>(this T value, Func<T, TRet> action, TRet defValue = default(TRet))
|
||||
public static TRet Maybe<T, TRet>(this T value, Func<T, TRet> action, TRet defValue = default)
|
||||
where T : class
|
||||
{
|
||||
return (value != null) ? action(value) : defValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Coverlet.Core.Abstractions;
|
||||
|
||||
namespace Coverlet.Core.Helpers
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using Coverlet.Core.Abstractions;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using Coverlet.Core.Abstractions;
|
||||
|
||||
namespace Coverlet.Core.Helpers
|
||||
{
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -8,7 +11,6 @@ using System.Reflection;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Reflection.PortableExecutable;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using Coverlet.Core.Abstractions;
|
||||
|
||||
namespace Coverlet.Core.Helpers
|
||||
@@ -81,14 +83,14 @@ namespace Coverlet.Core.Helpers
|
||||
public bool HasPdb(string module, out bool embedded)
|
||||
{
|
||||
embedded = false;
|
||||
using (var moduleStream = _fileSystem.OpenRead(module))
|
||||
using (Stream moduleStream = _fileSystem.OpenRead(module))
|
||||
using (var peReader = new PEReader(moduleStream))
|
||||
{
|
||||
foreach (var entry in peReader.ReadDebugDirectory())
|
||||
foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory())
|
||||
{
|
||||
if (entry.Type == DebugDirectoryEntryType.CodeView)
|
||||
{
|
||||
var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry);
|
||||
CodeViewDebugDirectoryData codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry);
|
||||
if (_sourceRootTranslator.ResolveFilePath(codeViewData.Path) == $"{Path.GetFileNameWithoutExtension(module)}.pdb")
|
||||
{
|
||||
// PDB is embedded
|
||||
@@ -117,12 +119,12 @@ namespace Coverlet.Core.Helpers
|
||||
using (MetadataReaderProvider embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(entry))
|
||||
{
|
||||
MetadataReader metadataReader = embeddedMetadataProvider.GetMetadataReader();
|
||||
|
||||
var matchingResult = MatchDocumentsWithSources(metadataReader);
|
||||
|
||||
if (!matchingResult.allDocumentsMatch)
|
||||
(bool allDocumentsMatch, string notFoundDocument) = MatchDocumentsWithSources(metadataReader);
|
||||
|
||||
if (!allDocumentsMatch)
|
||||
{
|
||||
firstNotFoundDocument = matchingResult.notFoundDocument;
|
||||
firstNotFoundDocument = notFoundDocument;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -138,16 +140,16 @@ namespace Coverlet.Core.Helpers
|
||||
public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDocument)
|
||||
{
|
||||
firstNotFoundDocument = "";
|
||||
using (var moduleStream = _fileSystem.OpenRead(module))
|
||||
using (Stream moduleStream = _fileSystem.OpenRead(module))
|
||||
using (var peReader = new PEReader(moduleStream))
|
||||
{
|
||||
foreach (var entry in peReader.ReadDebugDirectory())
|
||||
foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory())
|
||||
{
|
||||
if (entry.Type == DebugDirectoryEntryType.CodeView)
|
||||
{
|
||||
var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry);
|
||||
CodeViewDebugDirectoryData codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry);
|
||||
using Stream pdbStream = _fileSystem.OpenRead(_sourceRootTranslator.ResolveFilePath(codeViewData.Path));
|
||||
using MetadataReaderProvider metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
|
||||
using var metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
|
||||
MetadataReader metadataReader = null;
|
||||
try
|
||||
{
|
||||
@@ -159,11 +161,11 @@ namespace Coverlet.Core.Helpers
|
||||
return true;
|
||||
}
|
||||
|
||||
var matchingResult = MatchDocumentsWithSources(metadataReader);
|
||||
(bool allDocumentsMatch, string notFoundDocument) = MatchDocumentsWithSources(metadataReader);
|
||||
|
||||
if (!matchingResult.allDocumentsMatch)
|
||||
if (!allDocumentsMatch)
|
||||
{
|
||||
firstNotFoundDocument = matchingResult.notFoundDocument;
|
||||
firstNotFoundDocument = notFoundDocument;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -196,15 +198,15 @@ namespace Coverlet.Core.Helpers
|
||||
|
||||
public void BackupOriginalModule(string module, string identifier)
|
||||
{
|
||||
var backupPath = GetBackupPath(module, identifier);
|
||||
var backupSymbolPath = Path.ChangeExtension(backupPath, ".pdb");
|
||||
string backupPath = GetBackupPath(module, identifier);
|
||||
string backupSymbolPath = Path.ChangeExtension(backupPath, ".pdb");
|
||||
_fileSystem.Copy(module, backupPath, true);
|
||||
if (!_backupList.TryAdd(module, backupPath))
|
||||
{
|
||||
throw new ArgumentException($"Key already added '{module}'");
|
||||
}
|
||||
|
||||
var symbolFile = Path.ChangeExtension(module, ".pdb");
|
||||
string symbolFile = Path.ChangeExtension(module, ".pdb");
|
||||
if (_fileSystem.Exists(symbolFile))
|
||||
{
|
||||
_fileSystem.Copy(symbolFile, backupSymbolPath, true);
|
||||
@@ -217,12 +219,12 @@ namespace Coverlet.Core.Helpers
|
||||
|
||||
public virtual void RestoreOriginalModule(string module, string identifier)
|
||||
{
|
||||
var backupPath = GetBackupPath(module, identifier);
|
||||
var backupSymbolPath = Path.ChangeExtension(backupPath, ".pdb");
|
||||
string backupPath = GetBackupPath(module, identifier);
|
||||
string backupSymbolPath = Path.ChangeExtension(backupPath, ".pdb");
|
||||
|
||||
// Restore the original module - retry up to 10 times, since the destination file could be locked
|
||||
// See: https://github.com/tonerdo/coverlet/issues/25
|
||||
var retryStrategy = CreateRetryStrategy();
|
||||
Func<TimeSpan> retryStrategy = CreateRetryStrategy();
|
||||
|
||||
_retryHelper.Retry(() =>
|
||||
{
|
||||
@@ -247,7 +249,7 @@ namespace Coverlet.Core.Helpers
|
||||
{
|
||||
// Restore the original module - retry up to 10 times, since the destination file could be locked
|
||||
// See: https://github.com/tonerdo/coverlet/issues/25
|
||||
var retryStrategy = CreateRetryStrategy();
|
||||
Func<TimeSpan> retryStrategy = CreateRetryStrategy();
|
||||
|
||||
foreach (string key in _backupList.Keys.ToList())
|
||||
{
|
||||
@@ -263,7 +265,7 @@ namespace Coverlet.Core.Helpers
|
||||
|
||||
public void DeleteHitsFile(string path)
|
||||
{
|
||||
var retryStrategy = CreateRetryStrategy();
|
||||
Func<TimeSpan> retryStrategy = CreateRetryStrategy();
|
||||
_retryHelper.Retry(() => _fileSystem.Delete(path), retryStrategy, RetryAttempts);
|
||||
}
|
||||
|
||||
@@ -308,7 +310,7 @@ namespace Coverlet.Core.Helpers
|
||||
if (module == null)
|
||||
return false;
|
||||
|
||||
foreach (var filter in excludeFilters)
|
||||
foreach (string filter in excludeFilters)
|
||||
{
|
||||
string typePattern = filter.Substring(filter.IndexOf(']') + 1);
|
||||
|
||||
@@ -336,7 +338,7 @@ namespace Coverlet.Core.Helpers
|
||||
if (module == null)
|
||||
return false;
|
||||
|
||||
foreach (var filter in includeFilters)
|
||||
foreach (string filter in includeFilters)
|
||||
{
|
||||
string modulePattern = filter.Substring(1, filter.IndexOf(']') - 1);
|
||||
|
||||
@@ -391,7 +393,7 @@ namespace Coverlet.Core.Helpers
|
||||
Debug.Assert(module != null);
|
||||
Debug.Assert(filters != null);
|
||||
|
||||
foreach (var filter in filters)
|
||||
foreach (string filter in filters)
|
||||
{
|
||||
string typePattern = filter.Substring(filter.IndexOf(']') + 1);
|
||||
string modulePattern = filter.Substring(1, filter.IndexOf(']') - 1);
|
||||
@@ -454,8 +456,8 @@ namespace Coverlet.Core.Helpers
|
||||
private bool IsUnknownModuleInFSharpAssembly(Guid languageGuid, string docName)
|
||||
{
|
||||
// https://github.com/dotnet/runtime/blob/main/docs/design/specs/PortablePdb-Metadata.md#document-table-0x30
|
||||
return languageGuid.Equals(new Guid("ab4f38c9-b6e6-43ba-be3b-58080b2ccce3"))
|
||||
return languageGuid.Equals(new Guid("ab4f38c9-b6e6-43ba-be3b-58080b2ccce3"))
|
||||
&& docName.EndsWith("unknown");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Coverlet.Core.Abstractions;
|
||||
|
||||
namespace Coverlet.Core.Helpers
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using Coverlet.Core.Abstractions;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Coverlet.Core.Abstractions;
|
||||
|
||||
namespace Coverlet.Core.Helpers
|
||||
{
|
||||
@@ -59,4 +62,4 @@ namespace Coverlet.Core.Helpers
|
||||
throw new AggregateException(exceptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
using Coverlet.Core.Abstractions;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Coverlet.Core.Abstractions;
|
||||
|
||||
namespace Coverlet.Core.Helpers
|
||||
{
|
||||
@@ -52,7 +55,7 @@ namespace Coverlet.Core.Helpers
|
||||
throw new ArgumentNullException(nameof(sourceRootMapping));
|
||||
}
|
||||
|
||||
Dictionary<string, List<string>> sourceToDeterministicPathMapping = new Dictionary<string, List<string>>();
|
||||
var sourceToDeterministicPathMapping = new Dictionary<string, List<string>>();
|
||||
foreach (KeyValuePair<string, List<SourceRootMapping>> sourceRootMappingEntry in sourceRootMapping)
|
||||
{
|
||||
foreach (SourceRootMapping originalPath in sourceRootMappingEntry.Value)
|
||||
@@ -70,7 +73,7 @@ namespace Coverlet.Core.Helpers
|
||||
|
||||
private Dictionary<string, List<SourceRootMapping>> LoadSourceRootMapping(string directory)
|
||||
{
|
||||
Dictionary<string, List<SourceRootMapping>> mapping = new Dictionary<string, List<SourceRootMapping>>();
|
||||
var mapping = new Dictionary<string, List<SourceRootMapping>>();
|
||||
|
||||
string mappingFilePath = Path.Combine(directory, MappingFileName);
|
||||
if (!_fileSystem.Exists(mappingFilePath))
|
||||
@@ -138,7 +141,7 @@ namespace Coverlet.Core.Helpers
|
||||
|
||||
public string ResolveDeterministicPath(string originalFileName)
|
||||
{
|
||||
foreach (var originalPath in _sourceToDeterministicPathMapping)
|
||||
foreach (KeyValuePair<string, List<string>> originalPath in _sourceToDeterministicPathMapping)
|
||||
{
|
||||
if (originalFileName.StartsWith(originalPath.Key))
|
||||
{
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using Coverlet.Core.Abstractions;
|
||||
using Coverlet.Core.Exceptions;
|
||||
using Microsoft.Extensions.DependencyModel;
|
||||
@@ -167,8 +169,8 @@ namespace Coverlet.Core.Instrumentation
|
||||
throw new AssemblyResolutionException(name);
|
||||
}
|
||||
|
||||
using DependencyContextJsonReader contextJsonReader = new DependencyContextJsonReader();
|
||||
Dictionary<string, Lazy<AssemblyDefinition>> libraries = new Dictionary<string, Lazy<AssemblyDefinition>>();
|
||||
using var contextJsonReader = new DependencyContextJsonReader();
|
||||
var libraries = new Dictionary<string, Lazy<AssemblyDefinition>>();
|
||||
|
||||
foreach (string fileName in Directory.GetFiles(Path.GetDirectoryName(_modulePath), "*.deps.json"))
|
||||
{
|
||||
@@ -248,7 +250,7 @@ namespace Coverlet.Core.Instrumentation
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var file in Directory.GetFiles(sharedFrameworkPath))
|
||||
foreach (string file in Directory.GetFiles(sharedFrameworkPath))
|
||||
{
|
||||
if (Path.GetFileName(file).Equals(dllName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@@ -5,11 +8,10 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using Coverlet.Core.Instrumentation.Reachability;
|
||||
using Coverlet.Core.Abstractions;
|
||||
using Coverlet.Core.Attributes;
|
||||
using Coverlet.Core.Helpers;
|
||||
using Coverlet.Core.Instrumentation.Reachability;
|
||||
using Coverlet.Core.Symbols;
|
||||
using Microsoft.Extensions.FileSystemGlobbing;
|
||||
using Mono.Cecil;
|
||||
@@ -183,7 +185,7 @@ namespace Coverlet.Core.Instrumentation
|
||||
// locking issues if we do it while writing.
|
||||
private void CreateReachabilityHelper()
|
||||
{
|
||||
using (var stream = _fileSystem.NewFileStream(_module, FileMode.Open, FileAccess.Read))
|
||||
using (Stream stream = _fileSystem.NewFileStream(_module, FileMode.Open, FileAccess.Read))
|
||||
using (var resolver = new NetstandardAwareAssemblyResolver(_module, _logger))
|
||||
{
|
||||
resolver.AddSearchDirectory(Path.GetDirectoryName(_module));
|
||||
@@ -204,7 +206,7 @@ namespace Coverlet.Core.Instrumentation
|
||||
{
|
||||
CreateReachabilityHelper();
|
||||
|
||||
using (var stream = _fileSystem.NewFileStream(_module, FileMode.Open, FileAccess.ReadWrite))
|
||||
using (Stream stream = _fileSystem.NewFileStream(_module, FileMode.Open, FileAccess.ReadWrite))
|
||||
using (var resolver = new NetstandardAwareAssemblyResolver(_module, _logger))
|
||||
{
|
||||
resolver.AddSearchDirectory(Path.GetDirectoryName(_module));
|
||||
@@ -226,11 +228,11 @@ namespace Coverlet.Core.Instrumentation
|
||||
}
|
||||
}
|
||||
|
||||
var containsAppContext = module.GetType(nameof(System), nameof(AppContext)) != null;
|
||||
var types = module.GetTypes();
|
||||
bool containsAppContext = module.GetType(nameof(System), nameof(AppContext)) != null;
|
||||
IEnumerable<TypeDefinition> types = module.GetTypes();
|
||||
AddCustomModuleTrackerToModule(module);
|
||||
|
||||
var sourceLinkDebugInfo = module.CustomDebugInformations.FirstOrDefault(c => c.Kind == CustomDebugInformationKind.SourceLink);
|
||||
CustomDebugInformation sourceLinkDebugInfo = module.CustomDebugInformations.FirstOrDefault(c => c.Kind == CustomDebugInformationKind.SourceLink);
|
||||
if (sourceLinkDebugInfo != null)
|
||||
{
|
||||
_result.SourceLink = ((SourceLinkDebugInformation)sourceLinkDebugInfo).Content;
|
||||
@@ -294,11 +296,11 @@ namespace Coverlet.Core.Instrumentation
|
||||
customTrackerUnloadModule.Parameters.Add(new ParameterDefinition(eventArgsType));
|
||||
|
||||
var appContextType = new TypeReference(nameof(System), nameof(AppContext), module, module.TypeSystem.CoreLibrary);
|
||||
var onProcessExitMethod = new MethodReference("OnProcessExit", module.TypeSystem.Void, appContextType).Resolve();
|
||||
var onProcessExitIl = onProcessExitMethod.Body.GetILProcessor();
|
||||
MethodDefinition onProcessExitMethod = new MethodReference("OnProcessExit", module.TypeSystem.Void, appContextType).Resolve();
|
||||
ILProcessor onProcessExitIl = onProcessExitMethod.Body.GetILProcessor();
|
||||
|
||||
// Put the OnProcessExit body inside try/finally to ensure the call to the UnloadModule.
|
||||
var lastInst = onProcessExitMethod.Body.Instructions.Last();
|
||||
Instruction lastInst = onProcessExitMethod.Body.Instructions.Last();
|
||||
var firstNullParam = Instruction.Create(OpCodes.Ldnull);
|
||||
var secondNullParam = Instruction.Create(OpCodes.Ldnull);
|
||||
var callUnload = Instruction.Create(OpCodes.Call, customTrackerUnloadModule);
|
||||
@@ -307,16 +309,16 @@ namespace Coverlet.Core.Instrumentation
|
||||
onProcessExitIl.InsertAfter(secondNullParam, callUnload);
|
||||
var endFinally = Instruction.Create(OpCodes.Endfinally);
|
||||
onProcessExitIl.InsertAfter(callUnload, endFinally);
|
||||
var ret = onProcessExitIl.Create(OpCodes.Ret);
|
||||
var leaveAfterFinally = onProcessExitIl.Create(OpCodes.Leave, ret);
|
||||
Instruction ret = onProcessExitIl.Create(OpCodes.Ret);
|
||||
Instruction leaveAfterFinally = onProcessExitIl.Create(OpCodes.Leave, ret);
|
||||
onProcessExitIl.InsertAfter(endFinally, ret);
|
||||
foreach (var inst in onProcessExitMethod.Body.Instructions.ToArray())
|
||||
foreach (Instruction inst in onProcessExitMethod.Body.Instructions.ToArray())
|
||||
{
|
||||
// Patch ret to leave after the finally
|
||||
if (inst.OpCode == OpCodes.Ret && inst != ret)
|
||||
{
|
||||
var leaveBodyInstAfterFinally = onProcessExitIl.Create(OpCodes.Leave, ret);
|
||||
var prevInst = inst.Previous;
|
||||
Instruction leaveBodyInstAfterFinally = onProcessExitIl.Create(OpCodes.Leave, ret);
|
||||
Instruction prevInst = inst.Previous;
|
||||
onProcessExitMethod.Body.Instructions.Remove(inst);
|
||||
onProcessExitIl.InsertAfter(prevInst, leaveBodyInstAfterFinally);
|
||||
}
|
||||
@@ -339,7 +341,7 @@ namespace Coverlet.Core.Instrumentation
|
||||
|
||||
private void AddCustomModuleTrackerToModule(ModuleDefinition module)
|
||||
{
|
||||
using (AssemblyDefinition coverletInstrumentationAssembly = AssemblyDefinition.ReadAssembly(typeof(ModuleTrackerTemplate).Assembly.Location))
|
||||
using (var coverletInstrumentationAssembly = AssemblyDefinition.ReadAssembly(typeof(ModuleTrackerTemplate).Assembly.Location))
|
||||
{
|
||||
TypeDefinition moduleTrackerTemplate = coverletInstrumentationAssembly.MainModule.GetType(
|
||||
"Coverlet.Core.Instrumentation", nameof(ModuleTrackerTemplate));
|
||||
@@ -367,14 +369,14 @@ namespace Coverlet.Core.Instrumentation
|
||||
|
||||
foreach (MethodDefinition methodDef in moduleTrackerTemplate.Methods)
|
||||
{
|
||||
MethodDefinition methodOnCustomType = new MethodDefinition(methodDef.Name, methodDef.Attributes, methodDef.ReturnType);
|
||||
var methodOnCustomType = new MethodDefinition(methodDef.Name, methodDef.Attributes, methodDef.ReturnType);
|
||||
|
||||
foreach (var parameter in methodDef.Parameters)
|
||||
foreach (ParameterDefinition parameter in methodDef.Parameters)
|
||||
{
|
||||
methodOnCustomType.Parameters.Add(new ParameterDefinition(module.ImportReference(parameter.ParameterType)));
|
||||
}
|
||||
|
||||
foreach (var variable in methodDef.Body.Variables)
|
||||
foreach (VariableDefinition variable in methodDef.Body.Variables)
|
||||
{
|
||||
methodOnCustomType.Body.Variables.Add(new VariableDefinition(module.ImportReference(variable.VariableType)));
|
||||
}
|
||||
@@ -398,7 +400,7 @@ namespace Coverlet.Core.Instrumentation
|
||||
{
|
||||
// Move to the custom type
|
||||
var updatedMethodReference = new MethodReference(methodReference.Name, methodReference.ReturnType, _customTrackerTypeDef);
|
||||
foreach (var parameter in methodReference.Parameters)
|
||||
foreach (ParameterDefinition parameter in methodReference.Parameters)
|
||||
updatedMethodReference.Parameters.Add(new ParameterDefinition(parameter.Name, parameter.Attributes, module.ImportReference(parameter.ParameterType)));
|
||||
|
||||
instr.Operand = updatedMethodReference;
|
||||
@@ -416,7 +418,7 @@ namespace Coverlet.Core.Instrumentation
|
||||
ilProcessor.Append(instr);
|
||||
}
|
||||
|
||||
foreach (var handler in methodDef.Body.ExceptionHandlers)
|
||||
foreach (ExceptionHandler handler in methodDef.Body.ExceptionHandlers)
|
||||
{
|
||||
if (handler.CatchType != null)
|
||||
{
|
||||
@@ -469,12 +471,12 @@ namespace Coverlet.Core.Instrumentation
|
||||
|
||||
private void InstrumentType(TypeDefinition type)
|
||||
{
|
||||
var methods = type.GetMethods();
|
||||
IEnumerable<MethodDefinition> methods = type.GetMethods();
|
||||
|
||||
// We keep ordinal index because it's the way used by compiler for generated types/methods to
|
||||
// avoid ambiguity
|
||||
int ordinal = -1;
|
||||
foreach (var method in methods)
|
||||
foreach (MethodDefinition method in methods)
|
||||
{
|
||||
MethodDefinition actualMethod = method;
|
||||
IEnumerable<CustomAttribute> customAttributes = method.CustomAttributes;
|
||||
@@ -516,8 +518,8 @@ namespace Coverlet.Core.Instrumentation
|
||||
}
|
||||
}
|
||||
|
||||
var ctors = type.GetConstructors();
|
||||
foreach (var ctor in ctors)
|
||||
IEnumerable<MethodDefinition> ctors = type.GetConstructors();
|
||||
foreach (MethodDefinition ctor in ctors)
|
||||
{
|
||||
if (!ctor.CustomAttributes.Any(IsExcludeAttribute))
|
||||
{
|
||||
@@ -528,7 +530,7 @@ namespace Coverlet.Core.Instrumentation
|
||||
|
||||
private void InstrumentMethod(MethodDefinition method)
|
||||
{
|
||||
var sourceFile = method.DebugInformation.SequencePoints.Select(s => _sourceRootTranslator.ResolveFilePath(s.Document.Url)).FirstOrDefault();
|
||||
string sourceFile = method.DebugInformation.SequencePoints.Select(s => _sourceRootTranslator.ResolveFilePath(s.Document.Url)).FirstOrDefault();
|
||||
if (!string.IsNullOrEmpty(sourceFile) && _excludedFilesHelper.Exclude(sourceFile))
|
||||
{
|
||||
if (!(_excludedSourceFiles ??= new List<string>()).Contains(sourceFile))
|
||||
@@ -538,7 +540,7 @@ namespace Coverlet.Core.Instrumentation
|
||||
return;
|
||||
}
|
||||
|
||||
var methodBody = GetMethodBody(method);
|
||||
MethodBody methodBody = GetMethodBody(method);
|
||||
if (methodBody == null)
|
||||
return;
|
||||
|
||||
@@ -563,29 +565,29 @@ namespace Coverlet.Core.Instrumentation
|
||||
{
|
||||
method.Body.SimplifyMacros();
|
||||
ILProcessor processor = method.Body.GetILProcessor();
|
||||
var index = 0;
|
||||
var count = processor.Body.Instructions.Count;
|
||||
var branchPoints = _cecilSymbolHelper.GetBranchPoints(method);
|
||||
var unreachableRanges = _reachabilityHelper.FindUnreachableIL(processor.Body.Instructions, processor.Body.ExceptionHandlers);
|
||||
var currentUnreachableRangeIx = 0;
|
||||
int index = 0;
|
||||
int count = processor.Body.Instructions.Count;
|
||||
IReadOnlyList<BranchPoint> branchPoints = _cecilSymbolHelper.GetBranchPoints(method);
|
||||
System.Collections.Immutable.ImmutableArray<ReachabilityHelper.UnreachableRange> unreachableRanges = _reachabilityHelper.FindUnreachableIL(processor.Body.Instructions, processor.Body.ExceptionHandlers);
|
||||
int currentUnreachableRangeIx = 0;
|
||||
for (int n = 0; n < count; n++)
|
||||
{
|
||||
var currentInstruction = processor.Body.Instructions[index];
|
||||
var sequencePoint = method.DebugInformation.GetSequencePoint(currentInstruction);
|
||||
var targetedBranchPoints = branchPoints.Where(p => p.EndOffset == currentInstruction.Offset);
|
||||
Instruction currentInstruction = processor.Body.Instructions[index];
|
||||
SequencePoint sequencePoint = method.DebugInformation.GetSequencePoint(currentInstruction);
|
||||
IEnumerable<BranchPoint> targetedBranchPoints = branchPoints.Where(p => p.EndOffset == currentInstruction.Offset);
|
||||
|
||||
// make sure we're looking at the correct unreachable range (if any)
|
||||
var instrOffset = currentInstruction.Offset;
|
||||
int instrOffset = currentInstruction.Offset;
|
||||
while (currentUnreachableRangeIx < unreachableRanges.Length && instrOffset > unreachableRanges[currentUnreachableRangeIx].EndOffset)
|
||||
{
|
||||
currentUnreachableRangeIx++;
|
||||
}
|
||||
|
||||
// determine if the unreachable
|
||||
var isUnreachable = false;
|
||||
bool isUnreachable = false;
|
||||
if (currentUnreachableRangeIx < unreachableRanges.Length)
|
||||
{
|
||||
var range = unreachableRanges[currentUnreachableRangeIx];
|
||||
ReachabilityHelper.UnreachableRange range = unreachableRanges[currentUnreachableRangeIx];
|
||||
isUnreachable = instrOffset >= range.StartOffset && instrOffset <= range.EndOffset;
|
||||
}
|
||||
|
||||
@@ -604,8 +606,8 @@ namespace Coverlet.Core.Instrumentation
|
||||
continue;
|
||||
}
|
||||
|
||||
var firstInjectedInstrumentedOpCode = AddInstrumentationCode(method, processor, currentInstruction, sequencePoint);
|
||||
foreach (var bodyInstruction in processor.Body.Instructions)
|
||||
Instruction firstInjectedInstrumentedOpCode = AddInstrumentationCode(method, processor, currentInstruction, sequencePoint);
|
||||
foreach (Instruction bodyInstruction in processor.Body.Instructions)
|
||||
ReplaceInstructionTarget(bodyInstruction, currentInstruction, firstInjectedInstrumentedOpCode);
|
||||
|
||||
foreach (ExceptionHandler handler in processor.Body.ExceptionHandlers)
|
||||
@@ -614,7 +616,7 @@ namespace Coverlet.Core.Instrumentation
|
||||
index += 2;
|
||||
}
|
||||
|
||||
foreach (var branchTarget in targetedBranchPoints)
|
||||
foreach (BranchPoint branchTarget in targetedBranchPoints)
|
||||
{
|
||||
/*
|
||||
* Skip branches with no sequence point reference for now.
|
||||
@@ -625,8 +627,8 @@ namespace Coverlet.Core.Instrumentation
|
||||
if (branchTarget.StartLine == -1 || branchTarget.Document == null)
|
||||
continue;
|
||||
|
||||
var firstInjectedInstrumentedOpCode = AddInstrumentationCode(method, processor, currentInstruction, branchTarget);
|
||||
foreach (var bodyInstruction in processor.Body.Instructions)
|
||||
Instruction firstInjectedInstrumentedOpCode = AddInstrumentationCode(method, processor, currentInstruction, branchTarget);
|
||||
foreach (Instruction bodyInstruction in processor.Body.Instructions)
|
||||
ReplaceInstructionTarget(bodyInstruction, currentInstruction, firstInjectedInstrumentedOpCode);
|
||||
|
||||
foreach (ExceptionHandler handler in processor.Body.ExceptionHandlers)
|
||||
@@ -643,7 +645,7 @@ namespace Coverlet.Core.Instrumentation
|
||||
|
||||
private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor processor, Instruction instruction, SequencePoint sequencePoint)
|
||||
{
|
||||
if (!_result.Documents.TryGetValue(_sourceRootTranslator.ResolveFilePath(sequencePoint.Document.Url), out var document))
|
||||
if (!_result.Documents.TryGetValue(_sourceRootTranslator.ResolveFilePath(sequencePoint.Document.Url), out Document document))
|
||||
{
|
||||
document = new Document { Path = _sourceRootTranslator.ResolveFilePath(sequencePoint.Document.Url) };
|
||||
document.Index = _result.Documents.Count;
|
||||
@@ -663,14 +665,14 @@ namespace Coverlet.Core.Instrumentation
|
||||
|
||||
private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor processor, Instruction instruction, BranchPoint branchPoint)
|
||||
{
|
||||
if (!_result.Documents.TryGetValue(_sourceRootTranslator.ResolveFilePath(branchPoint.Document), out var document))
|
||||
if (!_result.Documents.TryGetValue(_sourceRootTranslator.ResolveFilePath(branchPoint.Document), out Document document))
|
||||
{
|
||||
document = new Document { Path = _sourceRootTranslator.ResolveFilePath(branchPoint.Document) };
|
||||
document.Index = _result.Documents.Count;
|
||||
_result.Documents.Add(document.Path, document);
|
||||
}
|
||||
|
||||
BranchKey key = new BranchKey(branchPoint.StartLine, (int)branchPoint.Ordinal);
|
||||
var key = new BranchKey(branchPoint.StartLine, (int)branchPoint.Ordinal);
|
||||
if (!document.Branches.ContainsKey(key))
|
||||
{
|
||||
document.Branches.Add(
|
||||
@@ -815,7 +817,7 @@ namespace Coverlet.Core.Instrumentation
|
||||
}
|
||||
|
||||
// Check methods members and compiler generated types
|
||||
foreach (var excludedMethods in _excludedMethods)
|
||||
foreach ((MethodDefinition, int) excludedMethods in _excludedMethods)
|
||||
{
|
||||
// Exclude this member if declaring type is the same of the excluded method and
|
||||
// the name is synthesized from the name of the excluded method.
|
||||
@@ -868,34 +870,34 @@ namespace Coverlet.Core.Instrumentation
|
||||
public CoreLibMetadataImporter(ModuleDefinition module)
|
||||
{
|
||||
this.module = module;
|
||||
this.defaultMetadataImporter = new DefaultMetadataImporter(module);
|
||||
defaultMetadataImporter = new DefaultMetadataImporter(module);
|
||||
}
|
||||
|
||||
public AssemblyNameReference ImportReference(AssemblyNameReference reference)
|
||||
{
|
||||
return this.defaultMetadataImporter.ImportReference(reference);
|
||||
return defaultMetadataImporter.ImportReference(reference);
|
||||
}
|
||||
|
||||
public TypeReference ImportReference(TypeReference type, IGenericParameterProvider context)
|
||||
{
|
||||
var importedRef = this.defaultMetadataImporter.ImportReference(type, context);
|
||||
TypeReference importedRef = defaultMetadataImporter.ImportReference(type, context);
|
||||
importedRef.GetElementType().Scope = module.TypeSystem.CoreLibrary;
|
||||
return importedRef;
|
||||
}
|
||||
|
||||
public FieldReference ImportReference(FieldReference field, IGenericParameterProvider context)
|
||||
{
|
||||
var importedRef = this.defaultMetadataImporter.ImportReference(field, context);
|
||||
FieldReference importedRef = defaultMetadataImporter.ImportReference(field, context);
|
||||
importedRef.FieldType.GetElementType().Scope = module.TypeSystem.CoreLibrary;
|
||||
return importedRef;
|
||||
}
|
||||
|
||||
public MethodReference ImportReference(MethodReference method, IGenericParameterProvider context)
|
||||
{
|
||||
var importedRef = this.defaultMetadataImporter.ImportReference(method, context);
|
||||
MethodReference importedRef = defaultMetadataImporter.ImportReference(method, context);
|
||||
importedRef.DeclaringType.GetElementType().Scope = module.TypeSystem.CoreLibrary;
|
||||
|
||||
foreach (var parameter in importedRef.Parameters)
|
||||
foreach (ParameterDefinition parameter in importedRef.Parameters)
|
||||
{
|
||||
if (parameter.ParameterType.Scope == module.TypeSystem.CoreLibrary)
|
||||
{
|
||||
@@ -919,14 +921,14 @@ namespace Coverlet.Core.Instrumentation
|
||||
// Exclude files helper https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.filesystemglobbing.matcher?view=aspnetcore-2.2
|
||||
internal class ExcludedFilesHelper
|
||||
{
|
||||
Matcher _matcher;
|
||||
readonly Matcher _matcher;
|
||||
|
||||
public ExcludedFilesHelper(string[] excludes, ILogger logger)
|
||||
{
|
||||
if (excludes != null && excludes.Length > 0)
|
||||
{
|
||||
_matcher = new Matcher();
|
||||
foreach (var excludeRule in excludes)
|
||||
foreach (string excludeRule in excludes)
|
||||
{
|
||||
if (excludeRule is null)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@@ -47,11 +50,11 @@ namespace Coverlet.Core.Instrumentation
|
||||
|
||||
public override bool Equals(object obj) => Equals(obj);
|
||||
|
||||
public bool Equals(BranchKey other) => other is BranchKey branchKey && branchKey.Line == this.Line && branchKey.Ordinal == this.Ordinal;
|
||||
public bool Equals(BranchKey other) => other is BranchKey branchKey && branchKey.Line == Line && branchKey.Ordinal == Ordinal;
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (this.Line, this.Ordinal).GetHashCode();
|
||||
return (Line, Ordinal).GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
@@ -25,7 +27,7 @@ namespace Coverlet.Core.Instrumentation
|
||||
public static bool SingleHit;
|
||||
public static bool FlushHitFile;
|
||||
private static readonly bool _enableLog = int.TryParse(Environment.GetEnvironmentVariable("COVERLET_ENABLETRACKERLOG"), out int result) ? result == 1 : false;
|
||||
private static string _sessionId = Guid.NewGuid().ToString();
|
||||
private static readonly string _sessionId = Guid.NewGuid().ToString();
|
||||
|
||||
static ModuleTrackerTemplate()
|
||||
{
|
||||
@@ -171,8 +173,8 @@ namespace Coverlet.Core.Instrumentation
|
||||
{
|
||||
if (_enableLog)
|
||||
{
|
||||
Assembly currentAssembly = Assembly.GetExecutingAssembly();
|
||||
DirectoryInfo location = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(currentAssembly.Location), "TrackersHitsLog"));
|
||||
var currentAssembly = Assembly.GetExecutingAssembly();
|
||||
var location = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(currentAssembly.Location), "TrackersHitsLog"));
|
||||
location.Create();
|
||||
string logFile = Path.Combine(location.FullName, $"{Path.GetFileName(currentAssembly.Location)}_{DateTime.UtcNow.Ticks}_{_sessionId}.txt");
|
||||
using (var fs = new FileStream(HitsFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using Coverlet.Core.Abstractions;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using Mono.Collections.Generic;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Coverlet.Core.Abstractions;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Coverlet.Core.Instrumentation.Reachability
|
||||
{
|
||||
@@ -252,11 +255,11 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
return new ReachabilityHelper(ImmutableHashSet<MetadataToken>.Empty);
|
||||
}
|
||||
|
||||
var processedMethods = ImmutableHashSet<MetadataToken>.Empty;
|
||||
var doNotReturn = ImmutableHashSet.CreateBuilder<MetadataToken>();
|
||||
foreach (var type in module.Types)
|
||||
ImmutableHashSet<MetadataToken> processedMethods = ImmutableHashSet<MetadataToken>.Empty;
|
||||
ImmutableHashSet<MetadataToken>.Builder doNotReturn = ImmutableHashSet.CreateBuilder<MetadataToken>();
|
||||
foreach (TypeDefinition type in module.Types)
|
||||
{
|
||||
foreach (var mtd in type.Methods)
|
||||
foreach (MethodDefinition mtd in type.Methods)
|
||||
{
|
||||
if (mtd.IsNative)
|
||||
{
|
||||
@@ -278,14 +281,14 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var instr in body.Instructions)
|
||||
foreach (Instruction instr in body.Instructions)
|
||||
{
|
||||
if (!IsCall(instr, out var calledMtd))
|
||||
if (!IsCall(instr, out MethodReference calledMtd))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var token = calledMtd.MetadataToken;
|
||||
MetadataToken token = calledMtd.MetadataToken;
|
||||
if (processedMethods.Contains(token))
|
||||
{
|
||||
continue;
|
||||
@@ -314,8 +317,8 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
continue;
|
||||
}
|
||||
|
||||
var hasDoesNotReturnAttribute = false;
|
||||
foreach (var attr in mtdDef.CustomAttributes)
|
||||
bool hasDoesNotReturnAttribute = false;
|
||||
foreach (CustomAttribute attr in mtdDef.CustomAttributes)
|
||||
{
|
||||
if (Array.IndexOf(doesNotReturnAttributes, attr.AttributeType.Name) != -1)
|
||||
{
|
||||
@@ -333,7 +336,7 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
}
|
||||
}
|
||||
|
||||
var doNoReturnTokens = doNotReturn.ToImmutable();
|
||||
ImmutableHashSet<MetadataToken> doNoReturnTokens = doNotReturn.ToImmutable();
|
||||
|
||||
return new ReachabilityHelper(doNoReturnTokens);
|
||||
}
|
||||
@@ -374,7 +377,7 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
return ImmutableArray<UnreachableRange>.Empty;
|
||||
}
|
||||
|
||||
var (mayContainUnreachableCode, branches) = AnalyzeInstructions(instrs, exceptionHandlers);
|
||||
(bool mayContainUnreachableCode, ImmutableArray<BranchInstruction> branches) = AnalyzeInstructions(instrs, exceptionHandlers);
|
||||
|
||||
// no need to do any more work, nothing unreachable here
|
||||
if (!mayContainUnreachableCode)
|
||||
@@ -382,9 +385,9 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
return ImmutableArray<UnreachableRange>.Empty;
|
||||
}
|
||||
|
||||
var lastInstr = instrs[instrs.Count - 1];
|
||||
Instruction lastInstr = instrs[instrs.Count - 1];
|
||||
|
||||
var blocks = CreateBasicBlocks(instrs, exceptionHandlers, branches);
|
||||
ImmutableArray<BasicBlock> blocks = CreateBasicBlocks(instrs, exceptionHandlers, branches);
|
||||
|
||||
DetermineHeadReachability(blocks);
|
||||
return DetermineUnreachableRanges(blocks, lastInstr.Offset);
|
||||
@@ -396,16 +399,16 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
/// </summary>
|
||||
private (bool MayContainUnreachableCode, ImmutableArray<BranchInstruction> Branches) AnalyzeInstructions(Collection<Instruction> instrs, Collection<ExceptionHandler> exceptionHandlers)
|
||||
{
|
||||
var containsDoesNotReturnCall = false;
|
||||
bool containsDoesNotReturnCall = false;
|
||||
|
||||
var ret = ImmutableArray.CreateBuilder<BranchInstruction>();
|
||||
foreach (var i in instrs)
|
||||
ImmutableArray<BranchInstruction>.Builder ret = ImmutableArray.CreateBuilder<BranchInstruction>();
|
||||
foreach (Instruction i in instrs)
|
||||
{
|
||||
containsDoesNotReturnCall = containsDoesNotReturnCall || DoesNotReturn(i);
|
||||
|
||||
if (BRANCH_OPCODES.Contains(i.OpCode))
|
||||
{
|
||||
var (singleTargetOffset, multiTargetOffsets) = GetInstructionTargets(i, exceptionHandlers);
|
||||
(int? singleTargetOffset, ImmutableArray<int> multiTargetOffsets) = GetInstructionTargets(i, exceptionHandlers);
|
||||
|
||||
if (singleTargetOffset != null)
|
||||
{
|
||||
@@ -435,7 +438,7 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
singleTargetOffset = null;
|
||||
|
||||
multiTargetOffsets = ImmutableArray.Create(i.Next.Offset);
|
||||
foreach (var instr in multiTarget)
|
||||
foreach (Instruction instr in multiTarget)
|
||||
{
|
||||
// in practice these are small arrays, so a scan should be fine
|
||||
if (multiTargetOffsets.Contains(instr.Offset))
|
||||
@@ -467,15 +470,15 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
// flow is allowed so we can scan backwards to see find the block
|
||||
|
||||
ExceptionHandler filterForHandler = null;
|
||||
foreach (var handler in exceptionHandlers)
|
||||
foreach (ExceptionHandler handler in exceptionHandlers)
|
||||
{
|
||||
if (handler.FilterStart == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var startsAt = handler.FilterStart;
|
||||
var cur = startsAt;
|
||||
Instruction startsAt = handler.FilterStart;
|
||||
Instruction cur = startsAt;
|
||||
while (cur != null && cur.Offset < i.Offset)
|
||||
{
|
||||
cur = cur.Next;
|
||||
@@ -526,13 +529,13 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
/// </summary>
|
||||
private ImmutableArray<UnreachableRange> DetermineUnreachableRanges(ImmutableArray<BasicBlock> blocks, int lastInstructionOffset)
|
||||
{
|
||||
var ret = ImmutableArray.CreateBuilder<UnreachableRange>();
|
||||
ImmutableArray<UnreachableRange>.Builder ret = ImmutableArray.CreateBuilder<UnreachableRange>();
|
||||
|
||||
var endOfMethodOffset = lastInstructionOffset + 1; // add 1 so we point _past_ the end of the method
|
||||
int endOfMethodOffset = lastInstructionOffset + 1; // add 1 so we point _past_ the end of the method
|
||||
|
||||
for (var curBlockIx = 0; curBlockIx < blocks.Length; curBlockIx++)
|
||||
for (int curBlockIx = 0; curBlockIx < blocks.Length; curBlockIx++)
|
||||
{
|
||||
var curBlock = blocks[curBlockIx];
|
||||
BasicBlock curBlock = blocks[curBlockIx];
|
||||
|
||||
int endOfCurBlockOffset;
|
||||
if (curBlockIx == blocks.Length - 1)
|
||||
@@ -553,11 +556,11 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
}
|
||||
|
||||
// tail isn't reachable, which means there's a call to something that doesn't return...
|
||||
var doesNotReturnInstr = curBlock.UnreachableAfter;
|
||||
Instruction doesNotReturnInstr = curBlock.UnreachableAfter;
|
||||
|
||||
// and it's everything _after_ the following instruction that is unreachable
|
||||
// so record the following instruction through the end of the block
|
||||
var followingInstr = doesNotReturnInstr.Next;
|
||||
Instruction followingInstr = doesNotReturnInstr.Next;
|
||||
|
||||
ret.Add(new UnreachableRange(followingInstr.Offset, endOfCurBlockOffset));
|
||||
}
|
||||
@@ -581,13 +584,13 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
{
|
||||
var blockLookup = blocks.ToImmutableDictionary(b => b.StartOffset);
|
||||
|
||||
var headBlock = blockLookup[0];
|
||||
BasicBlock headBlock = blockLookup[0];
|
||||
|
||||
var knownLive = ImmutableStack.Create(headBlock);
|
||||
|
||||
while (!knownLive.IsEmpty)
|
||||
{
|
||||
knownLive = knownLive.Pop(out var block);
|
||||
knownLive = knownLive.Pop(out BasicBlock block);
|
||||
|
||||
if (block.HeadReachable)
|
||||
{
|
||||
@@ -601,18 +604,18 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
if (block.TailReachable)
|
||||
{
|
||||
// we can reach all the blocks it might flow to
|
||||
foreach (var reachableOffset in block.BranchesTo)
|
||||
foreach (int reachableOffset in block.BranchesTo)
|
||||
{
|
||||
var reachableBlock = blockLookup[reachableOffset];
|
||||
BasicBlock reachableBlock = blockLookup[reachableOffset];
|
||||
knownLive = knownLive.Push(reachableBlock);
|
||||
}
|
||||
}
|
||||
|
||||
// if the block is covered by an exception handler, then executing _any_ instruction in it
|
||||
// could conceivably cause those handlers to be visited
|
||||
foreach (var exceptionHandlerOffset in block.ExceptionBranchesTo)
|
||||
foreach (int exceptionHandlerOffset in block.ExceptionBranchesTo)
|
||||
{
|
||||
var reachableHandler = blockLookup[exceptionHandlerOffset];
|
||||
BasicBlock reachableHandler = blockLookup[exceptionHandlerOffset];
|
||||
knownLive = knownLive.Push(reachableHandler);
|
||||
}
|
||||
}
|
||||
@@ -629,16 +632,16 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
private ImmutableArray<BasicBlock> CreateBasicBlocks(Collection<Instruction> instrs, Collection<ExceptionHandler> exceptionHandlers, ImmutableArray<BranchInstruction> branches)
|
||||
{
|
||||
// every branch-like instruction starts or stops a block
|
||||
var branchInstrLocs = branches.ToLookup(i => i.Offset);
|
||||
ILookup<int, BranchInstruction> branchInstrLocs = branches.ToLookup(i => i.Offset);
|
||||
var branchInstrOffsets = branchInstrLocs.Select(k => k.Key).ToImmutableHashSet();
|
||||
|
||||
// every target that might be branched to starts or stops a block
|
||||
var branchTargetOffsetsBuilder = ImmutableHashSet.CreateBuilder<int>();
|
||||
foreach (var branch in branches)
|
||||
ImmutableHashSet<int>.Builder branchTargetOffsetsBuilder = ImmutableHashSet.CreateBuilder<int>();
|
||||
foreach (BranchInstruction branch in branches)
|
||||
{
|
||||
if (branch.HasMultiTargets)
|
||||
{
|
||||
foreach (var target in branch.TargetOffsets)
|
||||
foreach (int target in branch.TargetOffsets)
|
||||
{
|
||||
branchTargetOffsetsBuilder.Add(target);
|
||||
}
|
||||
@@ -651,7 +654,7 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
|
||||
// every exception handler an entry point
|
||||
// either it's handler, or it's filter (if present)
|
||||
foreach (var handler in exceptionHandlers)
|
||||
foreach (ExceptionHandler handler in exceptionHandlers)
|
||||
{
|
||||
if (handler.FilterStart != null)
|
||||
{
|
||||
@@ -663,18 +666,18 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
}
|
||||
}
|
||||
|
||||
var branchTargetOffsets = branchTargetOffsetsBuilder.ToImmutable();
|
||||
ImmutableHashSet<int> branchTargetOffsets = branchTargetOffsetsBuilder.ToImmutable();
|
||||
|
||||
// ending the method is also important
|
||||
var endOfMethodOffset = instrs[instrs.Count - 1].Offset;
|
||||
int endOfMethodOffset = instrs[instrs.Count - 1].Offset;
|
||||
|
||||
var blocks = ImmutableArray<BasicBlock>.Empty;
|
||||
ImmutableArray<BasicBlock> blocks = ImmutableArray<BasicBlock>.Empty;
|
||||
int? blockStartedAt = null;
|
||||
Instruction unreachableAfter = null;
|
||||
foreach (var i in instrs)
|
||||
foreach (Instruction i in instrs)
|
||||
{
|
||||
var offset = i.Offset;
|
||||
var branchesAtLoc = branchInstrLocs[offset];
|
||||
int offset = i.Offset;
|
||||
System.Collections.Generic.IEnumerable<BranchInstruction> branchesAtLoc = branchInstrLocs[offset];
|
||||
|
||||
if (blockStartedAt == null)
|
||||
{
|
||||
@@ -682,19 +685,19 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
unreachableAfter = null;
|
||||
}
|
||||
|
||||
var isBranch = branchInstrOffsets.Contains(offset);
|
||||
var isFollowedByBranchTarget = i.Next != null && branchTargetOffsets.Contains(i.Next.Offset);
|
||||
var isEndOfMtd = endOfMethodOffset == offset;
|
||||
bool isBranch = branchInstrOffsets.Contains(offset);
|
||||
bool isFollowedByBranchTarget = i.Next != null && branchTargetOffsets.Contains(i.Next.Offset);
|
||||
bool isEndOfMtd = endOfMethodOffset == offset;
|
||||
|
||||
if (unreachableAfter == null && DoesNotReturn(i))
|
||||
{
|
||||
unreachableAfter = i;
|
||||
}
|
||||
|
||||
var blockEnds = isBranch || isFollowedByBranchTarget || isEndOfMtd;
|
||||
bool blockEnds = isBranch || isFollowedByBranchTarget || isEndOfMtd;
|
||||
if (blockEnds)
|
||||
{
|
||||
var nextInstr = i.Next;
|
||||
Instruction nextInstr = i.Next;
|
||||
|
||||
// figure out all the different places the basic block could lead to
|
||||
ImmutableArray<int> goesTo;
|
||||
@@ -702,7 +705,7 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
{
|
||||
// it ends in a branch, where all does it branch?
|
||||
goesTo = ImmutableArray<int>.Empty;
|
||||
foreach (var branch in branchesAtLoc)
|
||||
foreach (BranchInstruction branch in branchesAtLoc)
|
||||
{
|
||||
if (branch.HasMultiTargets)
|
||||
{
|
||||
@@ -725,30 +728,30 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
goesTo = ImmutableArray<int>.Empty;
|
||||
}
|
||||
|
||||
var exceptionSwitchesTo = ImmutableArray<int>.Empty;
|
||||
ImmutableArray<int> exceptionSwitchesTo = ImmutableArray<int>.Empty;
|
||||
|
||||
// if the block is covered by any exception handlers then
|
||||
// it is possible that it will branch to its handler block
|
||||
foreach (var handler in exceptionHandlers)
|
||||
foreach (ExceptionHandler handler in exceptionHandlers)
|
||||
{
|
||||
var tryStart = handler.TryStart.Offset;
|
||||
var tryEnd = handler.TryEnd.Offset;
|
||||
int tryStart = handler.TryStart.Offset;
|
||||
int tryEnd = handler.TryEnd.Offset;
|
||||
|
||||
var containsStartOfTry =
|
||||
bool containsStartOfTry =
|
||||
tryStart >= blockStartedAt.Value &&
|
||||
tryStart <= i.Offset;
|
||||
|
||||
var containsEndOfTry =
|
||||
bool containsEndOfTry =
|
||||
tryEnd >= blockStartedAt.Value &&
|
||||
tryEnd <= i.Offset;
|
||||
|
||||
var blockInsideTry = blockStartedAt.Value >= tryStart && i.Offset <= tryEnd;
|
||||
bool blockInsideTry = blockStartedAt.Value >= tryStart && i.Offset <= tryEnd;
|
||||
|
||||
// blocks do not necessarily align to the TRY part of exception handlers, so we need to handle three cases:
|
||||
// - the try _starts_ in the block
|
||||
// - the try _ends_ in the block
|
||||
// - the try complete covers the block, but starts and ends before and after it (respectively)
|
||||
var tryOverlapsBlock = containsStartOfTry || containsEndOfTry || blockInsideTry;
|
||||
bool tryOverlapsBlock = containsStartOfTry || containsEndOfTry || blockInsideTry;
|
||||
|
||||
if (!tryOverlapsBlock)
|
||||
{
|
||||
@@ -783,7 +786,7 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
/// </summary>
|
||||
private bool DoesNotReturn(Instruction instr)
|
||||
{
|
||||
if (!IsCall(instr, out var mtd))
|
||||
if (!IsCall(instr, out MethodReference mtd))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -798,7 +801,7 @@ namespace Coverlet.Core.Instrumentation.Reachability
|
||||
/// </summary>
|
||||
private static bool IsCall(Instruction instr, out MethodReference mtd)
|
||||
{
|
||||
var opcode = instr.OpCode;
|
||||
OpCode opcode = instr.OpCode;
|
||||
if (opcode != OpCodes.Call && opcode != OpCodes.Callvirt)
|
||||
{
|
||||
mtd = null;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@@ -21,42 +24,42 @@ namespace Coverlet.Core.Reporters
|
||||
|
||||
public string Report(CoverageResult result, ISourceRootTranslator sourceRootTranslator)
|
||||
{
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
var summary = new CoverageSummary();
|
||||
|
||||
var lineCoverage = summary.CalculateLineCoverage(result.Modules);
|
||||
var branchCoverage = summary.CalculateBranchCoverage(result.Modules);
|
||||
CoverageDetails lineCoverage = summary.CalculateLineCoverage(result.Modules);
|
||||
CoverageDetails branchCoverage = summary.CalculateBranchCoverage(result.Modules);
|
||||
|
||||
XDocument xml = new XDocument();
|
||||
XElement coverage = new XElement("coverage");
|
||||
var xml = new XDocument();
|
||||
var coverage = new XElement("coverage");
|
||||
coverage.Add(new XAttribute("line-rate", (summary.CalculateLineCoverage(result.Modules).Percent / 100).ToString(CultureInfo.InvariantCulture)));
|
||||
coverage.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(result.Modules).Percent / 100).ToString(CultureInfo.InvariantCulture)));
|
||||
coverage.Add(new XAttribute("version", "1.9"));
|
||||
coverage.Add(new XAttribute("timestamp", (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds));
|
||||
|
||||
XElement sources = new XElement("sources");
|
||||
var sources = new XElement("sources");
|
||||
|
||||
List<string> absolutePaths = new List<string>();
|
||||
var absolutePaths = new List<string>();
|
||||
if (!result.Parameters.DeterministicReport)
|
||||
{
|
||||
absolutePaths = GetBasePaths(result.Modules, result.Parameters.UseSourceLink).ToList();
|
||||
absolutePaths.ForEach(x => sources.Add(new XElement("source", x)));
|
||||
}
|
||||
|
||||
XElement packages = new XElement("packages");
|
||||
foreach (var module in result.Modules)
|
||||
var packages = new XElement("packages");
|
||||
foreach (KeyValuePair<string, Documents> module in result.Modules)
|
||||
{
|
||||
XElement package = new XElement("package");
|
||||
var package = new XElement("package");
|
||||
package.Add(new XAttribute("name", Path.GetFileNameWithoutExtension(module.Key)));
|
||||
package.Add(new XAttribute("line-rate", (summary.CalculateLineCoverage(module.Value).Percent / 100).ToString(CultureInfo.InvariantCulture)));
|
||||
package.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(module.Value).Percent / 100).ToString(CultureInfo.InvariantCulture)));
|
||||
package.Add(new XAttribute("complexity", summary.CalculateCyclomaticComplexity(module.Value)));
|
||||
|
||||
XElement classes = new XElement("classes");
|
||||
foreach (var document in module.Value)
|
||||
var classes = new XElement("classes");
|
||||
foreach (KeyValuePair<string, Classes> document in module.Value)
|
||||
{
|
||||
foreach (var cls in document.Value)
|
||||
foreach (KeyValuePair<string, Methods> cls in document.Value)
|
||||
{
|
||||
XElement @class = new XElement("class");
|
||||
var @class = new XElement("class");
|
||||
@class.Add(new XAttribute("name", cls.Key));
|
||||
string fileName;
|
||||
if (!result.Parameters.DeterministicReport)
|
||||
@@ -72,27 +75,27 @@ namespace Coverlet.Core.Reporters
|
||||
@class.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(cls.Value).Percent / 100).ToString(CultureInfo.InvariantCulture)));
|
||||
@class.Add(new XAttribute("complexity", summary.CalculateCyclomaticComplexity(cls.Value)));
|
||||
|
||||
XElement classLines = new XElement("lines");
|
||||
XElement methods = new XElement("methods");
|
||||
var classLines = new XElement("lines");
|
||||
var methods = new XElement("methods");
|
||||
|
||||
foreach (var meth in cls.Value)
|
||||
foreach (KeyValuePair<string, Method> meth in cls.Value)
|
||||
{
|
||||
// Skip all methods with no lines
|
||||
if (meth.Value.Lines.Count == 0)
|
||||
continue;
|
||||
|
||||
XElement method = new XElement("method");
|
||||
var method = new XElement("method");
|
||||
method.Add(new XAttribute("name", meth.Key.Split(':').Last().Split('(').First()));
|
||||
method.Add(new XAttribute("signature", "(" + meth.Key.Split(':').Last().Split('(').Last()));
|
||||
method.Add(new XAttribute("line-rate", (summary.CalculateLineCoverage(meth.Value.Lines).Percent / 100).ToString(CultureInfo.InvariantCulture)));
|
||||
method.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(meth.Value.Branches).Percent / 100).ToString(CultureInfo.InvariantCulture)));
|
||||
method.Add(new XAttribute("complexity", summary.CalculateCyclomaticComplexity(meth.Value.Branches)));
|
||||
|
||||
XElement lines = new XElement("lines");
|
||||
foreach (var ln in meth.Value.Lines)
|
||||
var lines = new XElement("lines");
|
||||
foreach (KeyValuePair<int, int> ln in meth.Value.Lines)
|
||||
{
|
||||
bool isBranchPoint = meth.Value.Branches.Any(b => b.Line == ln.Key);
|
||||
XElement line = new XElement("line");
|
||||
var line = new XElement("line");
|
||||
line.Add(new XAttribute("number", ln.Key.ToString()));
|
||||
line.Add(new XAttribute("hits", ln.Value.ToString()));
|
||||
line.Add(new XAttribute("branch", isBranchPoint.ToString()));
|
||||
@@ -100,13 +103,13 @@ namespace Coverlet.Core.Reporters
|
||||
if (isBranchPoint)
|
||||
{
|
||||
var branches = meth.Value.Branches.Where(b => b.Line == ln.Key).ToList();
|
||||
var branchInfoCoverage = summary.CalculateBranchCoverage(branches);
|
||||
CoverageDetails branchInfoCoverage = summary.CalculateBranchCoverage(branches);
|
||||
line.Add(new XAttribute("condition-coverage", $"{branchInfoCoverage.Percent.ToString(CultureInfo.InvariantCulture)}% ({branchInfoCoverage.Covered.ToString(CultureInfo.InvariantCulture)}/{branchInfoCoverage.Total.ToString(CultureInfo.InvariantCulture)})"));
|
||||
XElement conditions = new XElement("conditions");
|
||||
var conditions = new XElement("conditions");
|
||||
var byOffset = branches.GroupBy(b => b.Offset).ToDictionary(b => b.Key, b => b.ToList());
|
||||
foreach (var entry in byOffset)
|
||||
foreach (KeyValuePair<int, List<BranchInfo>> entry in byOffset)
|
||||
{
|
||||
XElement condition = new XElement("condition");
|
||||
var condition = new XElement("condition");
|
||||
condition.Add(new XAttribute("number", entry.Key));
|
||||
condition.Add(new XAttribute("type", entry.Value.Count() > 2 ? "switch" : "jump")); // Just guessing here
|
||||
condition.Add(new XAttribute("coverage", $"{summary.CalculateBranchCoverage(entry.Value).Percent.ToString(CultureInfo.InvariantCulture)}%"));
|
||||
@@ -218,7 +221,7 @@ namespace Coverlet.Core.Reporters
|
||||
return path;
|
||||
}
|
||||
|
||||
foreach (var basePath in basePaths)
|
||||
foreach (string basePath in basePaths)
|
||||
{
|
||||
if (path.StartsWith(basePath))
|
||||
{
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using Newtonsoft.Json;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Coverlet.Core.Abstractions;
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Coverlet.Core.Reporters
|
||||
{
|
||||
@@ -18,4 +19,4 @@ namespace Coverlet.Core.Reporters
|
||||
return JsonConvert.SerializeObject(result.Modules, Formatting.Indented);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Coverlet.Core.Abstractions;
|
||||
|
||||
namespace Coverlet.Core.Reporters
|
||||
@@ -21,21 +23,21 @@ namespace Coverlet.Core.Reporters
|
||||
throw new NotSupportedException("Deterministic report not supported by lcov reporter");
|
||||
}
|
||||
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
List<string> lcov = new List<string>();
|
||||
var summary = new CoverageSummary();
|
||||
var lcov = new List<string>();
|
||||
|
||||
foreach (var module in result.Modules)
|
||||
foreach (KeyValuePair<string, Documents> module in result.Modules)
|
||||
{
|
||||
foreach (var doc in module.Value)
|
||||
foreach (KeyValuePair<string, Classes> doc in module.Value)
|
||||
{
|
||||
var docLineCoverage = summary.CalculateLineCoverage(doc.Value);
|
||||
var docBranchCoverage = summary.CalculateBranchCoverage(doc.Value);
|
||||
var docMethodCoverage = summary.CalculateMethodCoverage(doc.Value);
|
||||
CoverageDetails docLineCoverage = summary.CalculateLineCoverage(doc.Value);
|
||||
CoverageDetails docBranchCoverage = summary.CalculateBranchCoverage(doc.Value);
|
||||
CoverageDetails docMethodCoverage = summary.CalculateMethodCoverage(doc.Value);
|
||||
|
||||
lcov.Add("SF:" + doc.Key);
|
||||
foreach (var @class in doc.Value)
|
||||
foreach (KeyValuePair<string, Methods> @class in doc.Value)
|
||||
{
|
||||
foreach (var method in @class.Value)
|
||||
foreach (KeyValuePair<string, Method> method in @class.Value)
|
||||
{
|
||||
// Skip all methods with no lines
|
||||
if (method.Value.Lines.Count == 0)
|
||||
@@ -44,10 +46,10 @@ namespace Coverlet.Core.Reporters
|
||||
lcov.Add($"FN:{method.Value.Lines.First().Key - 1},{method.Key}");
|
||||
lcov.Add($"FNDA:{method.Value.Lines.First().Value},{method.Key}");
|
||||
|
||||
foreach (var line in method.Value.Lines)
|
||||
foreach (KeyValuePair<int, int> line in method.Value.Lines)
|
||||
lcov.Add($"DA:{line.Key},{line.Value}");
|
||||
|
||||
foreach (var branch in method.Value.Branches)
|
||||
foreach (BranchInfo branch in method.Value.Branches)
|
||||
{
|
||||
lcov.Add($"BRDA:{branch.Line},{branch.Offset},{branch.Path},{branch.Hits}");
|
||||
}
|
||||
@@ -70,4 +72,4 @@ namespace Coverlet.Core.Reporters
|
||||
return string.Join(Environment.NewLine, lcov);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
using Coverlet.Core.Abstractions;
|
||||
|
||||
namespace Coverlet.Core.Reporters
|
||||
@@ -24,63 +26,63 @@ namespace Coverlet.Core.Reporters
|
||||
throw new NotSupportedException("Deterministic report not supported by openCover reporter");
|
||||
}
|
||||
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
XDocument xml = new XDocument();
|
||||
XElement coverage = new XElement("CoverageSession");
|
||||
XElement coverageSummary = new XElement("Summary");
|
||||
XElement modules = new XElement("Modules");
|
||||
var summary = new CoverageSummary();
|
||||
var xml = new XDocument();
|
||||
var coverage = new XElement("CoverageSession");
|
||||
var coverageSummary = new XElement("Summary");
|
||||
var modules = new XElement("Modules");
|
||||
|
||||
int numClasses = 0, numMethods = 0;
|
||||
int visitedClasses = 0, visitedMethods = 0;
|
||||
|
||||
int i = 1;
|
||||
|
||||
foreach (var mod in result.Modules)
|
||||
foreach (System.Collections.Generic.KeyValuePair<string, Documents> mod in result.Modules)
|
||||
{
|
||||
XElement module = new XElement("Module");
|
||||
var module = new XElement("Module");
|
||||
module.Add(new XAttribute("hash", Guid.NewGuid().ToString().ToUpper()));
|
||||
|
||||
XElement path = new XElement("ModulePath", mod.Key);
|
||||
XElement time = new XElement("ModuleTime", DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ss"));
|
||||
XElement name = new XElement("ModuleName", Path.GetFileNameWithoutExtension(mod.Key));
|
||||
var path = new XElement("ModulePath", mod.Key);
|
||||
var time = new XElement("ModuleTime", DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ss"));
|
||||
var name = new XElement("ModuleName", Path.GetFileNameWithoutExtension(mod.Key));
|
||||
|
||||
module.Add(path);
|
||||
module.Add(time);
|
||||
module.Add(name);
|
||||
|
||||
XElement files = new XElement("Files");
|
||||
XElement classes = new XElement("Classes");
|
||||
var files = new XElement("Files");
|
||||
var classes = new XElement("Classes");
|
||||
|
||||
foreach (var doc in mod.Value)
|
||||
foreach (System.Collections.Generic.KeyValuePair<string, Classes> doc in mod.Value)
|
||||
{
|
||||
XElement file = new XElement("File");
|
||||
var file = new XElement("File");
|
||||
file.Add(new XAttribute("uid", i.ToString()));
|
||||
file.Add(new XAttribute("fullPath", doc.Key));
|
||||
files.Add(file);
|
||||
|
||||
foreach (var cls in doc.Value)
|
||||
foreach (System.Collections.Generic.KeyValuePair<string, Methods> cls in doc.Value)
|
||||
{
|
||||
XElement @class = new XElement("Class");
|
||||
XElement classSummary = new XElement("Summary");
|
||||
var @class = new XElement("Class");
|
||||
var classSummary = new XElement("Summary");
|
||||
|
||||
XElement className = new XElement("FullName", cls.Key);
|
||||
var className = new XElement("FullName", cls.Key);
|
||||
|
||||
XElement methods = new XElement("Methods");
|
||||
var methods = new XElement("Methods");
|
||||
int j = 0;
|
||||
var classVisited = false;
|
||||
bool classVisited = false;
|
||||
|
||||
foreach (var meth in cls.Value)
|
||||
foreach (System.Collections.Generic.KeyValuePair<string, Method> meth in cls.Value)
|
||||
{
|
||||
// Skip all methods with no lines
|
||||
if (meth.Value.Lines.Count == 0)
|
||||
continue;
|
||||
|
||||
var methLineCoverage = summary.CalculateLineCoverage(meth.Value.Lines);
|
||||
var methBranchCoverage = summary.CalculateBranchCoverage(meth.Value.Branches);
|
||||
var methCyclomaticComplexity = summary.CalculateCyclomaticComplexity(meth.Value.Branches);
|
||||
var methNpathComplexity = summary.CalculateNpathComplexity(meth.Value.Branches);
|
||||
CoverageDetails methLineCoverage = summary.CalculateLineCoverage(meth.Value.Lines);
|
||||
CoverageDetails methBranchCoverage = summary.CalculateBranchCoverage(meth.Value.Branches);
|
||||
int methCyclomaticComplexity = summary.CalculateCyclomaticComplexity(meth.Value.Branches);
|
||||
int methNpathComplexity = summary.CalculateNpathComplexity(meth.Value.Branches);
|
||||
|
||||
XElement method = new XElement("Method");
|
||||
var method = new XElement("Method");
|
||||
|
||||
method.Add(new XAttribute("cyclomaticComplexity", methCyclomaticComplexity.ToString()));
|
||||
method.Add(new XAttribute("nPathComplexity", methCyclomaticComplexity.ToString()));
|
||||
@@ -91,12 +93,12 @@ namespace Coverlet.Core.Reporters
|
||||
method.Add(new XAttribute("isSetter", meth.Key.Contains("set_").ToString()));
|
||||
method.Add(new XAttribute("isStatic", (!meth.Key.Contains("get_") || !meth.Key.Contains("set_")).ToString()));
|
||||
|
||||
XElement methodName = new XElement("Name", meth.Key);
|
||||
var methodName = new XElement("Name", meth.Key);
|
||||
|
||||
XElement fileRef = new XElement("FileRef");
|
||||
var fileRef = new XElement("FileRef");
|
||||
fileRef.Add(new XAttribute("uid", i.ToString()));
|
||||
|
||||
XElement methodPoint = new XElement("MethodPoint");
|
||||
var methodPoint = new XElement("MethodPoint");
|
||||
methodPoint.Add(new XAttribute("vc", methLineCoverage.Covered.ToString()));
|
||||
methodPoint.Add(new XAttribute("uspid", "0"));
|
||||
methodPoint.Add(new XAttribute(XName.Get("type", "xsi"), "SequencePoint"));
|
||||
@@ -111,19 +113,19 @@ namespace Coverlet.Core.Reporters
|
||||
methodPoint.Add(new XAttribute("fileid", i.ToString()));
|
||||
|
||||
// They're really just lines
|
||||
XElement sequencePoints = new XElement("SequencePoints");
|
||||
XElement branchPoints = new XElement("BranchPoints");
|
||||
XElement methodSummary = new XElement("Summary");
|
||||
var sequencePoints = new XElement("SequencePoints");
|
||||
var branchPoints = new XElement("BranchPoints");
|
||||
var methodSummary = new XElement("Summary");
|
||||
int k = 0;
|
||||
int kBr = 0;
|
||||
var methodVisited = false;
|
||||
bool methodVisited = false;
|
||||
|
||||
foreach (var lines in meth.Value.Lines)
|
||||
foreach (System.Collections.Generic.KeyValuePair<int, int> lines in meth.Value.Lines)
|
||||
{
|
||||
var lineBranches = meth.Value.Branches.Where(branchInfo => branchInfo.Line == lines.Key).ToArray();
|
||||
var branchCoverage = summary.CalculateBranchCoverage(lineBranches);
|
||||
|
||||
XElement sequencePoint = new XElement("SequencePoint");
|
||||
BranchInfo[] lineBranches = meth.Value.Branches.Where(branchInfo => branchInfo.Line == lines.Key).ToArray();
|
||||
CoverageDetails branchCoverage = summary.CalculateBranchCoverage(lineBranches);
|
||||
|
||||
var sequencePoint = new XElement("SequencePoint");
|
||||
sequencePoint.Add(new XAttribute("vc", lines.Value.ToString()));
|
||||
sequencePoint.Add(new XAttribute("uspid", lines.Key.ToString()));
|
||||
sequencePoint.Add(new XAttribute("ordinal", k.ToString()));
|
||||
@@ -145,9 +147,9 @@ namespace Coverlet.Core.Reporters
|
||||
k++;
|
||||
}
|
||||
|
||||
foreach (var branche in meth.Value.Branches)
|
||||
foreach (BranchInfo branche in meth.Value.Branches)
|
||||
{
|
||||
XElement branchPoint = new XElement("BranchPoint");
|
||||
var branchPoint = new XElement("BranchPoint");
|
||||
branchPoint.Add(new XAttribute("vc", branche.Hits.ToString()));
|
||||
branchPoint.Add(new XAttribute("uspid", branche.Line.ToString()));
|
||||
branchPoint.Add(new XAttribute("ordinal", branche.Ordinal.ToString()));
|
||||
@@ -192,11 +194,11 @@ namespace Coverlet.Core.Reporters
|
||||
if (classVisited)
|
||||
visitedClasses++;
|
||||
|
||||
var classLineCoverage = summary.CalculateLineCoverage(cls.Value);
|
||||
var classBranchCoverage = summary.CalculateBranchCoverage(cls.Value);
|
||||
var classMethodCoverage = summary.CalculateMethodCoverage(cls.Value);
|
||||
var classMaxCyclomaticComplexity = summary.CalculateMaxCyclomaticComplexity(cls.Value);
|
||||
var classMinCyclomaticComplexity = summary.CalculateMinCyclomaticComplexity(cls.Value);
|
||||
CoverageDetails classLineCoverage = summary.CalculateLineCoverage(cls.Value);
|
||||
CoverageDetails classBranchCoverage = summary.CalculateBranchCoverage(cls.Value);
|
||||
CoverageDetails classMethodCoverage = summary.CalculateMethodCoverage(cls.Value);
|
||||
int classMaxCyclomaticComplexity = summary.CalculateMaxCyclomaticComplexity(cls.Value);
|
||||
int classMinCyclomaticComplexity = summary.CalculateMinCyclomaticComplexity(cls.Value);
|
||||
|
||||
classSummary.Add(new XAttribute("numSequencePoints", classLineCoverage.Total.ToString()));
|
||||
classSummary.Add(new XAttribute("visitedSequencePoints", classLineCoverage.Covered.ToString()));
|
||||
@@ -224,10 +226,10 @@ namespace Coverlet.Core.Reporters
|
||||
modules.Add(module);
|
||||
}
|
||||
|
||||
var moduleLineCoverage = summary.CalculateLineCoverage(result.Modules);
|
||||
var moduleBranchCoverage = summary.CalculateBranchCoverage(result.Modules);
|
||||
var moduleMaxCyclomaticComplexity = summary.CalculateMaxCyclomaticComplexity(result.Modules);
|
||||
var moduleMinCyclomaticComplexity = summary.CalculateMinCyclomaticComplexity(result.Modules);
|
||||
CoverageDetails moduleLineCoverage = summary.CalculateLineCoverage(result.Modules);
|
||||
CoverageDetails moduleBranchCoverage = summary.CalculateBranchCoverage(result.Modules);
|
||||
int moduleMaxCyclomaticComplexity = summary.CalculateMaxCyclomaticComplexity(result.Modules);
|
||||
int moduleMinCyclomaticComplexity = summary.CalculateMinCyclomaticComplexity(result.Modules);
|
||||
|
||||
coverageSummary.Add(new XAttribute("numSequencePoints", moduleLineCoverage.Total.ToString()));
|
||||
coverageSummary.Add(new XAttribute("visitedSequencePoints", moduleLineCoverage.Covered.ToString()));
|
||||
@@ -252,4 +254,4 @@ namespace Coverlet.Core.Reporters
|
||||
return Encoding.UTF8.GetString(stream.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
using Coverlet.Core.Abstractions;
|
||||
|
||||
namespace Coverlet.Core.Reporters
|
||||
{
|
||||
internal class ReporterFactory
|
||||
{
|
||||
private string _format;
|
||||
private IReporter[] _reporters;
|
||||
private readonly string _format;
|
||||
private readonly IReporter[] _reporters;
|
||||
|
||||
public ReporterFactory(string format)
|
||||
{
|
||||
@@ -28,4 +30,4 @@ namespace Coverlet.Core.Reporters
|
||||
public IReporter CreateReporter()
|
||||
=> _reporters.FirstOrDefault(r => string.Equals(r.Format, _format, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
using Coverlet.Core.Abstractions;
|
||||
|
||||
namespace Coverlet.Core.Reporters
|
||||
@@ -23,9 +25,9 @@ namespace Coverlet.Core.Reporters
|
||||
|
||||
// Calculate coverage
|
||||
var summary = new CoverageSummary();
|
||||
var overallLineCoverage = summary.CalculateLineCoverage(result.Modules);
|
||||
var overallBranchCoverage = summary.CalculateBranchCoverage(result.Modules);
|
||||
var overallMethodCoverage = summary.CalculateMethodCoverage(result.Modules);
|
||||
CoverageDetails overallLineCoverage = summary.CalculateLineCoverage(result.Modules);
|
||||
CoverageDetails overallBranchCoverage = summary.CalculateBranchCoverage(result.Modules);
|
||||
CoverageDetails overallMethodCoverage = summary.CalculateMethodCoverage(result.Modules);
|
||||
|
||||
// Report coverage
|
||||
var stringBuilder = new StringBuilder();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Coverlet.Core.Symbols
|
||||
{
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//
|
||||
// This class is based heavily on the work of the OpenCover
|
||||
// team in OpenCover.Framework.Symbols.CecilSymbolManager
|
||||
//
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using Coverlet.Core.Abstractions;
|
||||
using Coverlet.Core.Extensions;
|
||||
|
||||
@@ -272,10 +272,10 @@ namespace Coverlet.Core.Symbols
|
||||
|
||||
int branchIndex = instructions.BinarySearch(instruction, new InstructionByOffsetComparer());
|
||||
|
||||
return new[] {2,3}.Any(x => branchIndex >= x &&
|
||||
instructions[branchIndex - x].OpCode == OpCodes.Isinst &&
|
||||
instructions[branchIndex - x].Operand is TypeReference tr &&
|
||||
tr.FullName == "System.Exception")
|
||||
return new[] { 2, 3 }.Any(x => branchIndex >= x &&
|
||||
instructions[branchIndex - x].OpCode == OpCodes.Isinst &&
|
||||
instructions[branchIndex - x].Operand is TypeReference tr &&
|
||||
tr.FullName == "System.Exception")
|
||||
&&
|
||||
// check for throw opcode after branch
|
||||
instructions.Count - branchIndex >= 3 &&
|
||||
@@ -399,11 +399,11 @@ namespace Coverlet.Core.Symbols
|
||||
*/
|
||||
if (!_compilerGeneratedBranchesToExclude.ContainsKey(methodDefinition.FullName))
|
||||
{
|
||||
List<int> detectedBranches = new List<int>();
|
||||
var detectedBranches = new List<int>();
|
||||
Collection<ExceptionHandler> handlers = methodDefinition.Body.ExceptionHandlers;
|
||||
|
||||
int numberOfCatchBlocks = 1;
|
||||
foreach (var handler in handlers)
|
||||
foreach (ExceptionHandler handler in handlers)
|
||||
{
|
||||
if (handlers.Any(h => h.HandlerStart == handler.HandlerEnd))
|
||||
{
|
||||
@@ -663,7 +663,7 @@ namespace Coverlet.Core.Symbols
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool isFollowedByDisposeAsync = false;
|
||||
|
||||
if (instructions[currentIndex - 1].OpCode == OpCodes.Ldfld &&
|
||||
@@ -1021,13 +1021,13 @@ namespace Coverlet.Core.Symbols
|
||||
continue;
|
||||
}
|
||||
|
||||
var pathCounter = 0;
|
||||
int pathCounter = 0;
|
||||
|
||||
// store branch origin offset
|
||||
var branchOffset = instruction.Offset;
|
||||
var closestSeqPt = FindClosestInstructionWithSequencePoint(methodDefinition.Body, instruction).Maybe(i => methodDefinition.DebugInformation.GetSequencePoint(i));
|
||||
var branchingInstructionLine = closestSeqPt.Maybe(x => x.StartLine, -1);
|
||||
var document = closestSeqPt.Maybe(x => x.Document.Url);
|
||||
int branchOffset = instruction.Offset;
|
||||
SequencePoint closestSeqPt = FindClosestInstructionWithSequencePoint(methodDefinition.Body, instruction).Maybe(i => methodDefinition.DebugInformation.GetSequencePoint(i));
|
||||
int branchingInstructionLine = closestSeqPt.Maybe(x => x.StartLine, -1);
|
||||
string document = closestSeqPt.Maybe(x => x.Document.Url);
|
||||
|
||||
if (instruction.Next == null)
|
||||
{
|
||||
@@ -1054,9 +1054,9 @@ namespace Coverlet.Core.Symbols
|
||||
// Add Default branch (Path=0)
|
||||
|
||||
// Follow else/default instruction
|
||||
var @else = instruction.Next;
|
||||
Instruction @else = instruction.Next;
|
||||
|
||||
var pathOffsetList = GetBranchPath(@else);
|
||||
List<int> pathOffsetList = GetBranchPath(@else);
|
||||
|
||||
// add Path 0
|
||||
var path0 = new BranchPoint
|
||||
@@ -1077,8 +1077,7 @@ namespace Coverlet.Core.Symbols
|
||||
if (instruction.OpCode.Code != Code.Switch)
|
||||
{
|
||||
// Follow instruction at operand
|
||||
var @then = instruction.Operand as Instruction;
|
||||
if (@then == null)
|
||||
if (instruction.Operand is not Instruction @then)
|
||||
return false;
|
||||
|
||||
ordinal = BuildPointsForBranch(list, then, branchingInstructionLine, document, branchOffset,
|
||||
@@ -1086,8 +1085,7 @@ namespace Coverlet.Core.Symbols
|
||||
}
|
||||
else // instruction.OpCode.Code == Code.Switch
|
||||
{
|
||||
var branchInstructions = instruction.Operand as Instruction[];
|
||||
if (branchInstructions == null || branchInstructions.Length == 0)
|
||||
if (instruction.Operand is not Instruction[] branchInstructions || branchInstructions.Length == 0)
|
||||
return false;
|
||||
|
||||
ordinal = BuildPointsForSwitchCases(list, path0, branchInstructions, branchingInstructionLine,
|
||||
@@ -1099,7 +1097,7 @@ namespace Coverlet.Core.Symbols
|
||||
private static uint BuildPointsForBranch(List<BranchPoint> list, Instruction then, int branchingInstructionLine, string document,
|
||||
int branchOffset, uint ordinal, int pathCounter, BranchPoint path0, List<Instruction> instructions, MethodDefinition methodDefinition)
|
||||
{
|
||||
var pathOffsetList1 = GetBranchPath(@then);
|
||||
List<int> pathOffsetList1 = GetBranchPath(@then);
|
||||
|
||||
// Add path 1
|
||||
var path1 = new BranchPoint
|
||||
@@ -1119,7 +1117,7 @@ namespace Coverlet.Core.Symbols
|
||||
// only add branch if branch does not match a known sequence
|
||||
// e.g. auto generated field assignment
|
||||
// or encapsulates at least one sequence point
|
||||
var offsets = new[]
|
||||
int[] offsets = new[]
|
||||
{
|
||||
path0.Offset,
|
||||
path0.EndOffset,
|
||||
@@ -1127,22 +1125,22 @@ namespace Coverlet.Core.Symbols
|
||||
path1.EndOffset
|
||||
};
|
||||
|
||||
var ignoreSequences = new[]
|
||||
Code[][] ignoreSequences = new[]
|
||||
{
|
||||
// we may need other samples
|
||||
new[] {Code.Brtrue_S, Code.Pop, Code.Ldsfld, Code.Ldftn, Code.Newobj, Code.Dup, Code.Stsfld, Code.Newobj}, // CachedAnonymousMethodDelegate field allocation
|
||||
};
|
||||
|
||||
var bs = offsets.Min();
|
||||
var be = offsets.Max();
|
||||
int bs = offsets.Min();
|
||||
int be = offsets.Max();
|
||||
|
||||
var range = instructions.Where(i => (i.Offset >= bs) && (i.Offset <= be)).ToList();
|
||||
|
||||
var match = ignoreSequences
|
||||
bool match = ignoreSequences
|
||||
.Where(ignoreSequence => range.Count >= ignoreSequence.Length)
|
||||
.Any(ignoreSequence => range.Zip(ignoreSequence, (instruction, code) => instruction.OpCode.Code == code).All(x => x));
|
||||
|
||||
var count = range
|
||||
int count = range
|
||||
.Count(i => methodDefinition.DebugInformation.GetSequencePoint(i) != null);
|
||||
|
||||
if (!match || count > 0)
|
||||
@@ -1156,7 +1154,7 @@ namespace Coverlet.Core.Symbols
|
||||
private static uint BuildPointsForSwitchCases(List<BranchPoint> list, BranchPoint path0, Instruction[] branchInstructions,
|
||||
int branchingInstructionLine, string document, int branchOffset, uint ordinal, ref int pathCounter)
|
||||
{
|
||||
var counter = pathCounter;
|
||||
int counter = pathCounter;
|
||||
list.Add(path0);
|
||||
// Add Conditional Branches (Path>0)
|
||||
list.AddRange(branchInstructions.Select(GetBranchPath)
|
||||
@@ -1342,7 +1340,7 @@ namespace Coverlet.Core.Symbols
|
||||
}
|
||||
...
|
||||
*/
|
||||
var autogeneratedBackingFields = methodDefinition.DeclaringType.Fields.Where(x =>
|
||||
IEnumerable<FieldDefinition> autogeneratedBackingFields = methodDefinition.DeclaringType.Fields.Where(x =>
|
||||
x.CustomAttributes.Any(ca => ca.AttributeType.FullName.Equals(typeof(CompilerGeneratedAttribute).FullName)) &&
|
||||
x.FullName.EndsWith("k__BackingField"));
|
||||
|
||||
@@ -1354,15 +1352,15 @@ namespace Coverlet.Core.Symbols
|
||||
|
||||
private static bool SkipDefaultInitializationSystemObject(Instruction instruction)
|
||||
{
|
||||
/*
|
||||
A type always has a constructor with a default instantiation of System.Object. For record types these
|
||||
instructions can have a own sequence point. This means that even the default constructor would be instrumented.
|
||||
To skip this we search for call instructions with a method reference that declares System.Object.
|
||||
/*
|
||||
A type always has a constructor with a default instantiation of System.Object. For record types these
|
||||
instructions can have a own sequence point. This means that even the default constructor would be instrumented.
|
||||
To skip this we search for call instructions with a method reference that declares System.Object.
|
||||
|
||||
IL_0000: ldarg.0
|
||||
IL_0001: call instance void [System.Runtime]System.Object::.ctor()
|
||||
IL_0006: ret
|
||||
*/
|
||||
IL_0000: ldarg.0
|
||||
IL_0001: call instance void [System.Runtime]System.Object::.ctor()
|
||||
IL_0006: ret
|
||||
*/
|
||||
return instruction.OpCode == OpCodes.Ldarg &&
|
||||
instruction.Next?.OpCode == OpCodes.Call &&
|
||||
instruction.Next?.Operand is MethodReference mr && mr.DeclaringType.FullName.Equals(typeof(System.Object).FullName);
|
||||
@@ -1378,7 +1376,7 @@ namespace Coverlet.Core.Symbols
|
||||
.Where(e => e.HandlerType == ExceptionHandlerType.Filter)
|
||||
.ToList();
|
||||
|
||||
foreach (var exceptionHandler in handlers)
|
||||
foreach (ExceptionHandler exceptionHandler in handlers)
|
||||
{
|
||||
Instruction startFilter = exceptionHandler.FilterStart;
|
||||
Instruction endFilter = startFilter;
|
||||
@@ -1418,7 +1416,7 @@ namespace Coverlet.Core.Symbols
|
||||
|
||||
private static int GetOffsetOfNextEndfinally(MethodBody body, int startOffset)
|
||||
{
|
||||
var lastOffset = body.Instructions.LastOrDefault().Maybe(i => i.Offset, int.MaxValue);
|
||||
int lastOffset = body.Instructions.LastOrDefault().Maybe(i => i.Offset, int.MaxValue);
|
||||
return body.Instructions.FirstOrDefault(i => i.Offset >= startOffset && i.OpCode.Code == Code.Endfinally).Maybe(i => i.Offset, lastOffset);
|
||||
}
|
||||
|
||||
@@ -1428,12 +1426,11 @@ namespace Coverlet.Core.Symbols
|
||||
|
||||
if (instruction != null)
|
||||
{
|
||||
var point = instruction;
|
||||
Instruction point = instruction;
|
||||
offsetList.Add(point.Offset);
|
||||
while (point.OpCode == OpCodes.Br || point.OpCode == OpCodes.Br_S)
|
||||
{
|
||||
var nextPoint = point.Operand as Instruction;
|
||||
if (nextPoint != null)
|
||||
if (point.Operand is Instruction nextPoint)
|
||||
{
|
||||
point = nextPoint;
|
||||
offsetList.Add(point.Offset);
|
||||
@@ -1453,12 +1450,12 @@ namespace Coverlet.Core.Symbols
|
||||
var sequencePointsInMethod = methodBody.Instructions.Where(i => HasValidSequencePoint(i, methodBody.Method)).ToList();
|
||||
if (!sequencePointsInMethod.Any())
|
||||
return null;
|
||||
var idx = sequencePointsInMethod.BinarySearch(instruction, new InstructionByOffsetComparer());
|
||||
int idx = sequencePointsInMethod.BinarySearch(instruction, new InstructionByOffsetComparer());
|
||||
Instruction prev;
|
||||
if (idx < 0)
|
||||
{
|
||||
// no exact match, idx corresponds to the next, larger element
|
||||
var lower = Math.Max(~idx - 1, 0);
|
||||
int lower = Math.Max(~idx - 1, 0);
|
||||
prev = sequencePointsInMethod[lower];
|
||||
}
|
||||
else
|
||||
@@ -1472,7 +1469,7 @@ namespace Coverlet.Core.Symbols
|
||||
|
||||
private static bool HasValidSequencePoint(Instruction instruction, MethodDefinition methodDefinition)
|
||||
{
|
||||
var sp = methodDefinition.DebugInformation.GetSequencePoint(instruction);
|
||||
SequencePoint sp = methodDefinition.DebugInformation.GetSequencePoint(instruction);
|
||||
return sp != null && sp.StartLine != StepOverLineCode;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Coverlet.MSbuild.Tasks
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
@@ -17,7 +20,7 @@ namespace Coverlet.MSbuild.Tasks
|
||||
{
|
||||
public class CoverageResultTask : BaseTask
|
||||
{
|
||||
private MSBuildLogger _logger;
|
||||
private readonly MSBuildLogger _logger;
|
||||
|
||||
[Required]
|
||||
public string Output { get; set; }
|
||||
@@ -63,11 +66,11 @@ namespace Coverlet.MSbuild.Tasks
|
||||
Coverage coverage = null;
|
||||
using (Stream instrumenterStateStream = fileSystem.NewFileStream(InstrumenterState.ItemSpec, FileMode.Open))
|
||||
{
|
||||
var instrumentationHelper = ServiceProvider.GetService<IInstrumentationHelper>();
|
||||
IInstrumentationHelper instrumentationHelper = ServiceProvider.GetService<IInstrumentationHelper>();
|
||||
// Task.Log is teared down after a task and thus the new MSBuildLogger must be passed to the InstrumentationHelper
|
||||
// https://github.com/microsoft/msbuild/issues/5153
|
||||
instrumentationHelper.SetLogger(_logger);
|
||||
coverage = new Coverage(CoveragePrepareResult.Deserialize(instrumenterStateStream), this._logger, ServiceProvider.GetService<IInstrumentationHelper>(), fileSystem, ServiceProvider.GetService<ISourceRootTranslator>());
|
||||
coverage = new Coverage(CoveragePrepareResult.Deserialize(instrumenterStateStream), _logger, ServiceProvider.GetService<IInstrumentationHelper>(), fileSystem, ServiceProvider.GetService<ISourceRootTranslator>());
|
||||
}
|
||||
|
||||
try
|
||||
@@ -82,7 +85,7 @@ namespace Coverlet.MSbuild.Tasks
|
||||
|
||||
CoverageResult result = coverage.GetCoverageResult();
|
||||
|
||||
var directory = Path.GetDirectoryName(Output);
|
||||
string directory = Path.GetDirectoryName(Output);
|
||||
if (directory == string.Empty)
|
||||
{
|
||||
directory = Directory.GetCurrentDirectory();
|
||||
@@ -92,12 +95,12 @@ namespace Coverlet.MSbuild.Tasks
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
var formats = OutputFormat.Split(',');
|
||||
string[] formats = OutputFormat.Split(',');
|
||||
var coverageReportPaths = new List<ITaskItem>(formats.Length);
|
||||
ISourceRootTranslator sourceRootTranslator = ServiceProvider.GetService<ISourceRootTranslator>();
|
||||
foreach (var format in formats)
|
||||
foreach (string format in formats)
|
||||
{
|
||||
var reporter = new ReporterFactory(format).CreateReporter();
|
||||
IReporter reporter = new ReporterFactory(format).CreateReporter();
|
||||
if (reporter == null)
|
||||
{
|
||||
throw new Exception($"Specified output format '{format}' is not supported");
|
||||
@@ -119,7 +122,7 @@ namespace Coverlet.MSbuild.Tasks
|
||||
ServiceProvider.GetService<IConsole>(),
|
||||
result,
|
||||
sourceRootTranslator);
|
||||
var path = writer.WriteReport();
|
||||
string path = writer.WriteReport();
|
||||
var metadata = new Dictionary<string, string> { ["Format"] = format };
|
||||
coverageReportPaths.Add(new TaskItem(path, metadata));
|
||||
}
|
||||
@@ -129,7 +132,7 @@ namespace Coverlet.MSbuild.Tasks
|
||||
|
||||
var thresholdTypeFlagQueue = new Queue<ThresholdTypeFlags>();
|
||||
|
||||
foreach (var thresholdType in ThresholdType.Split(',').Select(t => t.Trim()))
|
||||
foreach (string thresholdType in ThresholdType.Split(',').Select(t => t.Trim()))
|
||||
{
|
||||
if (thresholdType.Equals("line", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -144,19 +147,19 @@ namespace Coverlet.MSbuild.Tasks
|
||||
thresholdTypeFlagQueue.Enqueue(ThresholdTypeFlags.Method);
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<ThresholdTypeFlags, double> thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>();
|
||||
|
||||
var thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>();
|
||||
if (Threshold.Contains(','))
|
||||
{
|
||||
var thresholdValues = Threshold.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries).Select(t => t.Trim());
|
||||
if(thresholdValues.Count() != thresholdTypeFlagQueue.Count())
|
||||
IEnumerable<string> thresholdValues = Threshold.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(t => t.Trim());
|
||||
if (thresholdValues.Count() != thresholdTypeFlagQueue.Count())
|
||||
{
|
||||
throw new Exception($"Threshold type flag count ({thresholdTypeFlagQueue.Count()}) and values count ({thresholdValues.Count()}) doesn't match");
|
||||
}
|
||||
|
||||
foreach (var threshold in thresholdValues)
|
||||
foreach (string threshold in thresholdValues)
|
||||
{
|
||||
if (double.TryParse(threshold, out var value))
|
||||
if (double.TryParse(threshold, out double value))
|
||||
{
|
||||
thresholdTypeFlagValues[thresholdTypeFlagQueue.Dequeue()] = value;
|
||||
}
|
||||
@@ -175,8 +178,8 @@ namespace Coverlet.MSbuild.Tasks
|
||||
thresholdTypeFlagValues[thresholdTypeFlagQueue.Dequeue()] = thresholdValue;
|
||||
}
|
||||
}
|
||||
|
||||
var thresholdStat = ThresholdStatistic.Minimum;
|
||||
|
||||
ThresholdStatistic thresholdStat = ThresholdStatistic.Minimum;
|
||||
if (ThresholdStat.Equals("average", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
thresholdStat = ThresholdStatistic.Average;
|
||||
@@ -189,23 +192,23 @@ namespace Coverlet.MSbuild.Tasks
|
||||
var coverageTable = new ConsoleTable("Module", "Line", "Branch", "Method");
|
||||
var summary = new CoverageSummary();
|
||||
|
||||
var linePercentCalculation = summary.CalculateLineCoverage(result.Modules);
|
||||
var branchPercentCalculation = summary.CalculateBranchCoverage(result.Modules);
|
||||
var methodPercentCalculation = summary.CalculateMethodCoverage(result.Modules);
|
||||
CoverageDetails linePercentCalculation = summary.CalculateLineCoverage(result.Modules);
|
||||
CoverageDetails branchPercentCalculation = summary.CalculateBranchCoverage(result.Modules);
|
||||
CoverageDetails methodPercentCalculation = summary.CalculateMethodCoverage(result.Modules);
|
||||
|
||||
var totalLinePercent = linePercentCalculation.Percent;
|
||||
var totalBranchPercent = branchPercentCalculation.Percent;
|
||||
var totalMethodPercent = methodPercentCalculation.Percent;
|
||||
double totalLinePercent = linePercentCalculation.Percent;
|
||||
double totalBranchPercent = branchPercentCalculation.Percent;
|
||||
double totalMethodPercent = methodPercentCalculation.Percent;
|
||||
|
||||
var averageLinePercent = linePercentCalculation.AverageModulePercent;
|
||||
var averageBranchPercent = branchPercentCalculation.AverageModulePercent;
|
||||
var averageMethodPercent = methodPercentCalculation.AverageModulePercent;
|
||||
double averageLinePercent = linePercentCalculation.AverageModulePercent;
|
||||
double averageBranchPercent = branchPercentCalculation.AverageModulePercent;
|
||||
double averageMethodPercent = methodPercentCalculation.AverageModulePercent;
|
||||
|
||||
foreach (var module in result.Modules)
|
||||
foreach (KeyValuePair<string, Documents> module in result.Modules)
|
||||
{
|
||||
var linePercent = summary.CalculateLineCoverage(module.Value).Percent;
|
||||
var branchPercent = summary.CalculateBranchCoverage(module.Value).Percent;
|
||||
var methodPercent = summary.CalculateMethodCoverage(module.Value).Percent;
|
||||
double linePercent = summary.CalculateLineCoverage(module.Value).Percent;
|
||||
double branchPercent = summary.CalculateBranchCoverage(module.Value).Percent;
|
||||
double methodPercent = summary.CalculateMethodCoverage(module.Value).Percent;
|
||||
|
||||
coverageTable.AddRow(Path.GetFileNameWithoutExtension(module.Key), $"{InvariantFormat(linePercent)}%", $"{InvariantFormat(branchPercent)}%", $"{InvariantFormat(methodPercent)}%");
|
||||
}
|
||||
@@ -222,7 +225,7 @@ namespace Coverlet.MSbuild.Tasks
|
||||
|
||||
Console.WriteLine(coverageTable.ToStringAlternative());
|
||||
|
||||
var thresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, thresholdTypeFlagValues, thresholdStat);
|
||||
ThresholdTypeFlags thresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, thresholdTypeFlagValues, thresholdStat);
|
||||
if (thresholdTypeFlags != ThresholdTypeFlags.None)
|
||||
{
|
||||
var exceptionMessageBuilder = new StringBuilder();
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
using Coverlet.Core;
|
||||
using Coverlet.Core.Abstractions;
|
||||
using Coverlet.Core.Helpers;
|
||||
@@ -9,6 +11,7 @@ using Coverlet.Core.Symbols;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
using ILogger = Coverlet.Core.Abstractions.ILogger;
|
||||
|
||||
namespace Coverlet.MSbuild.Tasks
|
||||
@@ -81,9 +84,9 @@ namespace Coverlet.MSbuild.Tasks
|
||||
|
||||
try
|
||||
{
|
||||
var fileSystem = ServiceProvider.GetService<IFileSystem>();
|
||||
IFileSystem fileSystem = ServiceProvider.GetService<IFileSystem>();
|
||||
|
||||
CoverageParameters parameters = new CoverageParameters
|
||||
var parameters = new CoverageParameters
|
||||
{
|
||||
IncludeFilters = Include?.Split(','),
|
||||
IncludeDirectories = IncludeDirectory?.Split(','),
|
||||
@@ -99,7 +102,7 @@ namespace Coverlet.MSbuild.Tasks
|
||||
DoesNotReturnAttributes = DoesNotReturnAttribute?.Split(',')
|
||||
};
|
||||
|
||||
Coverage coverage = new Coverage(Path,
|
||||
var coverage = new Coverage(Path,
|
||||
parameters,
|
||||
_logger,
|
||||
ServiceProvider.GetService<IInstrumentationHelper>(),
|
||||
@@ -109,7 +112,7 @@ namespace Coverlet.MSbuild.Tasks
|
||||
|
||||
CoveragePrepareResult prepareResult = coverage.PrepareModules();
|
||||
InstrumenterState = new TaskItem(System.IO.Path.GetTempFileName());
|
||||
using (var instrumentedStateFile = fileSystem.NewFileStream(InstrumenterState.ItemSpec, FileMode.Open, FileAccess.Write))
|
||||
using (Stream instrumentedStateFile = fileSystem.NewFileStream(InstrumenterState.ItemSpec, FileMode.Open, FileAccess.Write))
|
||||
{
|
||||
using (Stream serializedState = CoveragePrepareResult.Serialize(prepareResult))
|
||||
{
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using ILogger = Coverlet.Core.Abstractions.ILogger;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System.IO;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using Coverlet.Core;
|
||||
using Coverlet.Core.Abstractions;
|
||||
using Coverlet.Core.Reporters;
|
||||
|
||||
namespace Coverlet.MSbuild.Tasks
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
|
||||
@@ -14,14 +17,14 @@ namespace Coverlet.Collector.Tests
|
||||
public class AttachmentManagerTests
|
||||
{
|
||||
private AttachmentManager _attachmentManager;
|
||||
private Mock<DataCollectionSink> _mockDataCollectionSink;
|
||||
private DataCollectionContext _dataCollectionContext;
|
||||
private TestPlatformLogger _testPlatformLogger;
|
||||
private TestPlatformEqtTrace _eqtTrace;
|
||||
private Mock<IFileHelper> _mockFileHelper;
|
||||
private Mock<IDirectoryHelper> _mockDirectoryHelper;
|
||||
private Mock<ICountDownEvent> _mockCountDownEvent;
|
||||
private Mock<DataCollectionLogger> _mockDataCollectionLogger;
|
||||
private readonly Mock<DataCollectionSink> _mockDataCollectionSink;
|
||||
private readonly DataCollectionContext _dataCollectionContext;
|
||||
private readonly TestPlatformLogger _testPlatformLogger;
|
||||
private readonly TestPlatformEqtTrace _eqtTrace;
|
||||
private readonly Mock<IFileHelper> _mockFileHelper;
|
||||
private readonly Mock<IDirectoryHelper> _mockDirectoryHelper;
|
||||
private readonly Mock<ICountDownEvent> _mockCountDownEvent;
|
||||
private readonly Mock<DataCollectionLogger> _mockDataCollectionLogger;
|
||||
|
||||
public AttachmentManagerTests()
|
||||
{
|
||||
@@ -71,7 +74,7 @@ namespace Coverlet.Collector.Tests
|
||||
[Fact]
|
||||
public void SendCoverageReportShouldSendAttachmentToTestPlatform()
|
||||
{
|
||||
var directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
|
||||
DirectoryInfo directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
|
||||
_attachmentManager = new AttachmentManager(_mockDataCollectionSink.Object, _dataCollectionContext, _testPlatformLogger,
|
||||
_eqtTrace, directory.ToString(), new FileHelper(), _mockDirectoryHelper.Object, _mockCountDownEvent.Object);
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
|
||||
using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection;
|
||||
using Moq;
|
||||
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
|
||||
@@ -22,15 +24,15 @@ namespace Coverlet.Collector.Tests
|
||||
{
|
||||
public class CoverletCoverageDataCollectorTests
|
||||
{
|
||||
private DataCollectionEnvironmentContext _context;
|
||||
private readonly DataCollectionEnvironmentContext _context;
|
||||
private CoverletCoverageCollector _coverletCoverageDataCollector;
|
||||
private DataCollectionContext _dataCollectionContext;
|
||||
private Mock<DataCollectionEvents> _mockDataColectionEvents;
|
||||
private Mock<DataCollectionSink> _mockDataCollectionSink;
|
||||
private Mock<ICoverageWrapper> _mockCoverageWrapper;
|
||||
private Mock<ICountDownEventFactory> _mockCountDownEventFactory;
|
||||
private readonly DataCollectionContext _dataCollectionContext;
|
||||
private readonly Mock<DataCollectionEvents> _mockDataColectionEvents;
|
||||
private readonly Mock<DataCollectionSink> _mockDataCollectionSink;
|
||||
private readonly Mock<ICoverageWrapper> _mockCoverageWrapper;
|
||||
private readonly Mock<ICountDownEventFactory> _mockCountDownEventFactory;
|
||||
private XmlElement _configurationElement;
|
||||
private Mock<DataCollectionLogger> _mockLogger;
|
||||
private readonly Mock<DataCollectionLogger> _mockLogger;
|
||||
|
||||
public CoverletCoverageDataCollectorTests()
|
||||
{
|
||||
@@ -39,7 +41,7 @@ namespace Coverlet.Collector.Tests
|
||||
_mockLogger = new Mock<DataCollectionLogger>();
|
||||
_configurationElement = null;
|
||||
|
||||
TestCase testcase = new TestCase { Id = Guid.NewGuid() };
|
||||
var testcase = new TestCase { Id = Guid.NewGuid() };
|
||||
_dataCollectionContext = new DataCollectionContext(testcase);
|
||||
_context = new DataCollectionEnvironmentContext(_dataCollectionContext);
|
||||
_mockCoverageWrapper = new Mock<ICoverageWrapper>();
|
||||
@@ -53,7 +55,7 @@ namespace Coverlet.Collector.Tests
|
||||
Func<TestPlatformEqtTrace, TestPlatformLogger, string, IServiceCollection> serviceCollectionFactory = (TestPlatformEqtTrace eqtTrace, TestPlatformLogger logger, string testModule) =>
|
||||
{
|
||||
IServiceCollection serviceCollection = new ServiceCollection();
|
||||
Mock<IFileSystem> fileSystem = new Mock<IFileSystem>();
|
||||
var fileSystem = new Mock<IFileSystem>();
|
||||
fileSystem.Setup(f => f.Exists(It.IsAny<string>())).Returns((string testLib) => testLib == "abc.dll");
|
||||
serviceCollection.AddTransient(_ => fileSystem.Object);
|
||||
|
||||
@@ -87,7 +89,7 @@ namespace Coverlet.Collector.Tests
|
||||
Func<TestPlatformEqtTrace, TestPlatformLogger, string, IServiceCollection> serviceCollectionFactory = (TestPlatformEqtTrace eqtTrace, TestPlatformLogger logger, string testModule) =>
|
||||
{
|
||||
IServiceCollection serviceCollection = new ServiceCollection();
|
||||
Mock<IFileSystem> fileSystem = new Mock<IFileSystem>();
|
||||
var fileSystem = new Mock<IFileSystem>();
|
||||
fileSystem.Setup(f => f.Exists(It.IsAny<string>())).Returns((string testLib) => testLib == "abc.dll");
|
||||
serviceCollection.AddTransient(_ => fileSystem.Object);
|
||||
|
||||
@@ -114,7 +116,7 @@ namespace Coverlet.Collector.Tests
|
||||
new Mock<ILogger>().Object,
|
||||
new Mock<ISourceRootTranslator>().Object);
|
||||
|
||||
CoverageParameters parameters = new CoverageParameters
|
||||
var parameters = new CoverageParameters
|
||||
{
|
||||
IncludeFilters = null,
|
||||
IncludeDirectories = null,
|
||||
@@ -126,7 +128,7 @@ namespace Coverlet.Collector.Tests
|
||||
UseSourceLink = true
|
||||
};
|
||||
|
||||
Coverage coverage = new Coverage("abc.dll", parameters, It.IsAny<ILogger>(), instrumentationHelper, new Mock<IFileSystem>().Object, new Mock<ISourceRootTranslator>().Object, new Mock<ICecilSymbolHelper>().Object);
|
||||
var coverage = new Coverage("abc.dll", parameters, It.IsAny<ILogger>(), instrumentationHelper, new Mock<IFileSystem>().Object, new Mock<ISourceRootTranslator>().Object, new Mock<ICecilSymbolHelper>().Object);
|
||||
|
||||
sessionStartProperties.Add("TestSources", new List<string> { "abc.dll" });
|
||||
_mockCoverageWrapper.Setup(x => x.CreateCoverage(It.IsAny<CoverletSettings>(), It.IsAny<ILogger>(), It.IsAny<IInstrumentationHelper>(), It.IsAny<IFileSystem>(), It.IsAny<ISourceRootTranslator>(), It.IsAny<ICecilSymbolHelper>())).Returns(coverage);
|
||||
@@ -163,7 +165,7 @@ namespace Coverlet.Collector.Tests
|
||||
string module = GetType().Assembly.Location;
|
||||
string pdb = Path.Combine(Path.GetDirectoryName(module), Path.GetFileNameWithoutExtension(module) + ".pdb");
|
||||
|
||||
var directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
|
||||
DirectoryInfo directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
|
||||
|
||||
File.Copy(module, Path.Combine(directory.FullName, Path.GetFileName(module)), true);
|
||||
File.Copy(pdb, Path.Combine(directory.FullName, Path.GetFileName(pdb)), true);
|
||||
@@ -188,7 +190,7 @@ namespace Coverlet.Collector.Tests
|
||||
Func<TestPlatformEqtTrace, TestPlatformLogger, string, IServiceCollection> serviceCollectionFactory = (TestPlatformEqtTrace eqtTrace, TestPlatformLogger logger, string testModule) =>
|
||||
{
|
||||
IServiceCollection serviceCollection = new ServiceCollection();
|
||||
Mock<IFileSystem> fileSystem = new Mock<IFileSystem>();
|
||||
var fileSystem = new Mock<IFileSystem>();
|
||||
fileSystem.Setup(f => f.Exists(It.IsAny<string>())).Returns((string testLib) => testLib == "Test");
|
||||
serviceCollection.AddTransient(_ => fileSystem.Object);
|
||||
|
||||
@@ -203,7 +205,7 @@ namespace Coverlet.Collector.Tests
|
||||
_coverletCoverageDataCollector = new CoverletCoverageCollector(new TestPlatformEqtTrace(), new CoverageWrapper(), _mockCountDownEventFactory.Object, serviceCollectionFactory);
|
||||
|
||||
IList<IReporter> reporters = formats.Split(',').Select(f => new ReporterFactory(f).CreateReporter()).Where(x => x != null).ToList();
|
||||
Mock<DataCollectionSink> mockDataCollectionSink = new Mock<DataCollectionSink>();
|
||||
var mockDataCollectionSink = new Mock<DataCollectionSink>();
|
||||
mockDataCollectionSink.Setup(m => m.SendFileAsync(It.IsAny<FileTransferInformation>())).Callback<FileTransferInformation>(fti =>
|
||||
{
|
||||
reporters.Remove(reporters.First(x =>
|
||||
@@ -212,8 +214,8 @@ namespace Coverlet.Collector.Tests
|
||||
});
|
||||
|
||||
var doc = new XmlDocument();
|
||||
var root = doc.CreateElement("Configuration");
|
||||
var element = doc.CreateElement("Format");
|
||||
XmlElement root = doc.CreateElement("Configuration");
|
||||
XmlElement element = doc.CreateElement("Format");
|
||||
element.AppendChild(doc.CreateTextNode(formats));
|
||||
root.AppendChild(element);
|
||||
|
||||
@@ -241,7 +243,7 @@ namespace Coverlet.Collector.Tests
|
||||
Func<TestPlatformEqtTrace, TestPlatformLogger, string, IServiceCollection> serviceCollectionFactory = (TestPlatformEqtTrace eqtTrace, TestPlatformLogger logger, string testModule) =>
|
||||
{
|
||||
IServiceCollection serviceCollection = new ServiceCollection();
|
||||
Mock<IFileSystem> fileSystem = new Mock<IFileSystem>();
|
||||
var fileSystem = new Mock<IFileSystem>();
|
||||
fileSystem.Setup(f => f.Exists(It.IsAny<string>())).Returns((string testLib) => testLib == "abc.dll");
|
||||
serviceCollection.AddTransient(_ => fileSystem.Object);
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Coverlet.Collector.DataCollection;
|
||||
@@ -9,7 +12,7 @@ namespace Coverlet.Collector.Tests
|
||||
{
|
||||
public class CoverletSettingsParserTests
|
||||
{
|
||||
private CoverletSettingsParser _coverletSettingsParser;
|
||||
private readonly CoverletSettingsParser _coverletSettingsParser;
|
||||
|
||||
public CoverletSettingsParserTests()
|
||||
{
|
||||
@@ -64,19 +67,19 @@ namespace Coverlet.Collector.Tests
|
||||
{
|
||||
var testModules = new List<string> { "abc.dll" };
|
||||
var doc = new XmlDocument();
|
||||
var configElement = doc.CreateElement("Configuration");
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.IncludeFiltersElementName, includeFilters);
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.ExcludeFiltersElementName, excludeFilters);
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.IncludeDirectoriesElementName, includeDirectories);
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.ExcludeSourceFilesElementName, excludeSourceFiles);
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.ExcludeAttributesElementName, excludeAttributes);
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.MergeWithElementName, "/path/to/result.json");
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.UseSourceLinkElementName, "false");
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.SingleHitElementName, "true");
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.IncludeTestAssemblyElementName, "true");
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.SkipAutoProps, "true");
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.DeterministicReport, "true");
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.DoesNotReturnAttributesElementName, doesNotReturnAttributes);
|
||||
XmlElement configElement = doc.CreateElement("Configuration");
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.IncludeFiltersElementName, includeFilters);
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.ExcludeFiltersElementName, excludeFilters);
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.IncludeDirectoriesElementName, includeDirectories);
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.ExcludeSourceFilesElementName, excludeSourceFiles);
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.ExcludeAttributesElementName, excludeAttributes);
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.MergeWithElementName, "/path/to/result.json");
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.UseSourceLinkElementName, "false");
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.SingleHitElementName, "true");
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.IncludeTestAssemblyElementName, "true");
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.SkipAutoProps, "true");
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.DeterministicReport, "true");
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.DoesNotReturnAttributesElementName, doesNotReturnAttributes);
|
||||
|
||||
CoverletSettings coverletSettings = _coverletSettingsParser.Parse(configElement, testModules);
|
||||
|
||||
@@ -109,12 +112,12 @@ namespace Coverlet.Collector.Tests
|
||||
{
|
||||
var testModules = new List<string> { "abc.dll" };
|
||||
var doc = new XmlDocument();
|
||||
var configElement = doc.CreateElement("Configuration");
|
||||
this.CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.IncludeFiltersElementName);
|
||||
this.CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.ExcludeFiltersElementName);
|
||||
this.CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.IncludeDirectoriesElementName);
|
||||
this.CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.ExcludeSourceFilesElementName);
|
||||
this.CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.ExcludeAttributesElementName);
|
||||
XmlElement configElement = doc.CreateElement("Configuration");
|
||||
CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.IncludeFiltersElementName);
|
||||
CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.ExcludeFiltersElementName);
|
||||
CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.IncludeDirectoriesElementName);
|
||||
CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.ExcludeSourceFilesElementName);
|
||||
CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.ExcludeAttributesElementName);
|
||||
|
||||
CoverletSettings coverletSettings = _coverletSettingsParser.Parse(configElement, testModules);
|
||||
|
||||
@@ -131,7 +134,7 @@ namespace Coverlet.Collector.Tests
|
||||
{
|
||||
var testModules = new List<string> { "abc.dll" };
|
||||
var doc = new XmlDocument();
|
||||
var configElement = doc.CreateElement("Configuration");
|
||||
XmlElement configElement = doc.CreateElement("Configuration");
|
||||
|
||||
CoverletSettings coverletSettings = _coverletSettingsParser.Parse(configElement, testModules);
|
||||
|
||||
@@ -160,8 +163,8 @@ namespace Coverlet.Collector.Tests
|
||||
{
|
||||
var testModules = new List<string> { "abc.dll" };
|
||||
var doc = new XmlDocument();
|
||||
var configElement = doc.CreateElement("Configuration");
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.ReportFormatElementName, formats);
|
||||
XmlElement configElement = doc.CreateElement("Configuration");
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.ReportFormatElementName, formats);
|
||||
|
||||
CoverletSettings coverletSettings = _coverletSettingsParser.Parse(configElement, testModules);
|
||||
|
||||
@@ -175,10 +178,10 @@ namespace Coverlet.Collector.Tests
|
||||
public void ParseShouldUseDefaultFormatWhenNoFormatSpecified(string formats)
|
||||
{
|
||||
var testModules = new List<string> { "abc.dll" };
|
||||
var defaultFormat = CoverletConstants.DefaultReportFormat;
|
||||
string defaultFormat = CoverletConstants.DefaultReportFormat;
|
||||
var doc = new XmlDocument();
|
||||
var configElement = doc.CreateElement("Configuration");
|
||||
this.CreateCoverletNodes(doc, configElement, CoverletConstants.ReportFormatElementName, formats);
|
||||
XmlElement configElement = doc.CreateElement("Configuration");
|
||||
CreateCoverletNodes(doc, configElement, CoverletConstants.ReportFormatElementName, formats);
|
||||
|
||||
CoverletSettings coverletSettings = _coverletSettingsParser.Parse(configElement, testModules);
|
||||
|
||||
@@ -187,14 +190,14 @@ namespace Coverlet.Collector.Tests
|
||||
|
||||
private void CreateCoverletNodes(XmlDocument doc, XmlElement configElement, string nodeSetting, string nodeValue)
|
||||
{
|
||||
var node = doc.CreateNode("element", nodeSetting, string.Empty);
|
||||
XmlNode node = doc.CreateNode("element", nodeSetting, string.Empty);
|
||||
node.InnerText = nodeValue;
|
||||
configElement.AppendChild(node);
|
||||
}
|
||||
|
||||
private void CreateCoverletNullInnerTextNodes(XmlDocument doc, XmlElement configElement, string nodeSetting)
|
||||
{
|
||||
var node = doc.CreateNode("element", nodeSetting, string.Empty);
|
||||
XmlNode node = doc.CreateNode("element", nodeSetting, string.Empty);
|
||||
node.InnerText = null;
|
||||
configElement.AppendChild(node);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyKeyFile("coverlet.collector.tests.snk")]
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# top-most EditorConfig file
|
||||
# We don't want to import other EditorConfig files and we want
|
||||
# to ensure no rules are enabled for these asset source files.
|
||||
root = true
|
||||
|
||||
[*.cs]
|
||||
# Default severity for all analyzer diagnostics
|
||||
dotnet_analyzer_diagnostic.severity = none
|
||||
@@ -0,0 +1,8 @@
|
||||
# top-most EditorConfig file
|
||||
# We don't want to import other EditorConfig files and we want
|
||||
# to ensure no rules are enabled for these asset source files.
|
||||
root = true
|
||||
|
||||
[*.cs]
|
||||
# Default severity for all analyzer diagnostics
|
||||
dotnet_analyzer_diagnostic.severity = none
|
||||
@@ -1,9 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Coverlet.Core;
|
||||
using Moq;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Coverlet.Core.Tests
|
||||
@@ -23,29 +21,29 @@ namespace Coverlet.Core.Tests
|
||||
|
||||
private void SetupDataForArithmeticPrecision()
|
||||
{
|
||||
Lines lines = new Lines();
|
||||
var lines = new Lines();
|
||||
lines.Add(1, 1);
|
||||
for (int i = 2; i <= 6; i++)
|
||||
{
|
||||
lines.Add(i, 0);
|
||||
}
|
||||
Branches branches = new Branches();
|
||||
var branches = new Branches();
|
||||
branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 0, Ordinal = 1 });
|
||||
for (int i = 2; i <= 6; i++)
|
||||
{
|
||||
branches.Add(new BranchInfo { Line = 1, Hits = 0, Offset = 1, Path = 1, Ordinal = (uint)i });
|
||||
}
|
||||
|
||||
Methods methods = new Methods();
|
||||
var methodString = "System.Void Coverlet.Core.Tests.CoverageSummaryTests::TestCalculateSummary()";
|
||||
var methods = new Methods();
|
||||
string methodString = "System.Void Coverlet.Core.Tests.CoverageSummaryTests::TestCalculateSummary()";
|
||||
methods.Add(methodString, new Method());
|
||||
methods[methodString].Lines = lines;
|
||||
methods[methodString].Branches = branches;
|
||||
|
||||
Classes classes = new Classes();
|
||||
var classes = new Classes();
|
||||
classes.Add("Coverlet.Core.Tests.CoverageSummaryTests", methods);
|
||||
|
||||
Documents documents = new Documents();
|
||||
var documents = new Documents();
|
||||
documents.Add("doc.cs", classes);
|
||||
|
||||
_moduleArithmeticPrecision = new Modules();
|
||||
@@ -54,23 +52,23 @@ namespace Coverlet.Core.Tests
|
||||
|
||||
private void SetupDataSingleModule()
|
||||
{
|
||||
Lines lines = new Lines();
|
||||
var lines = new Lines();
|
||||
lines.Add(1, 1);
|
||||
lines.Add(2, 0);
|
||||
Branches branches = new Branches();
|
||||
var branches = new Branches();
|
||||
branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 0, Ordinal = 1 });
|
||||
branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 1, Ordinal = 2 });
|
||||
|
||||
Methods methods = new Methods();
|
||||
var methodString = "System.Void Coverlet.Core.Tests.CoverageSummaryTests::TestCalculateSummary()";
|
||||
var methods = new Methods();
|
||||
string methodString = "System.Void Coverlet.Core.Tests.CoverageSummaryTests::TestCalculateSummary()";
|
||||
methods.Add(methodString, new Method());
|
||||
methods[methodString].Lines = lines;
|
||||
methods[methodString].Branches = branches;
|
||||
|
||||
Classes classes = new Classes();
|
||||
var classes = new Classes();
|
||||
classes.Add("Coverlet.Core.Tests.CoverageSummaryTests", methods);
|
||||
|
||||
Documents documents = new Documents();
|
||||
var documents = new Documents();
|
||||
documents.Add("doc.cs", classes);
|
||||
|
||||
_averageCalculationSingleModule = new Modules();
|
||||
@@ -79,21 +77,21 @@ namespace Coverlet.Core.Tests
|
||||
|
||||
private void SetupDataMultipleModule()
|
||||
{
|
||||
Lines lines = new Lines
|
||||
var lines = new Lines
|
||||
{
|
||||
{ 1, 1 }, // covered
|
||||
{ 2, 0 }, // not covered
|
||||
{ 3, 0 } // not covered
|
||||
};
|
||||
|
||||
Branches branches = new Branches
|
||||
var branches = new Branches
|
||||
{
|
||||
new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 0, Ordinal = 1 }, // covered
|
||||
new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 1, Ordinal = 2 }, // covered
|
||||
new BranchInfo { Line = 1, Hits = 0, Offset = 1, Path = 1, Ordinal = 2 } // not covered
|
||||
};
|
||||
|
||||
Methods methods = new Methods();
|
||||
var methods = new Methods();
|
||||
string[] methodString = {
|
||||
"System.Void Coverlet.Core.Tests.CoverageSummaryTests::TestCalculateSummary()", // covered
|
||||
"System.Void Coverlet.Core.Tests.CoverageSummaryTests::TestAditionalCalculateSummary()" // not covered
|
||||
@@ -108,12 +106,12 @@ namespace Coverlet.Core.Tests
|
||||
{ 1, 0 } // not covered
|
||||
};
|
||||
|
||||
Classes classes = new Classes
|
||||
var classes = new Classes
|
||||
{
|
||||
{ "Coverlet.Core.Tests.CoverageSummaryTests", methods }
|
||||
};
|
||||
|
||||
Documents documents = new Documents
|
||||
var documents = new Documents
|
||||
{
|
||||
{ "doc.cs", classes }
|
||||
};
|
||||
@@ -128,7 +126,7 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestCalculateLineCoverage_NoModules()
|
||||
{
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
var summary = new CoverageSummary();
|
||||
var modules = new Modules();
|
||||
|
||||
Assert.Equal(0, summary.CalculateLineCoverage(modules).Percent);
|
||||
@@ -142,12 +140,12 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestCalculateLineCoverage_SingleModule()
|
||||
{
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
var summary = new CoverageSummary();
|
||||
|
||||
var module = _averageCalculationSingleModule.First();
|
||||
var document = module.Value.First();
|
||||
var @class = document.Value.First();
|
||||
var method = @class.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Documents> module = _averageCalculationSingleModule.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Classes> document = module.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Methods> @class = document.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Method> method = @class.Value.First();
|
||||
|
||||
Assert.Equal(50, summary.CalculateLineCoverage(_averageCalculationSingleModule).AverageModulePercent);
|
||||
Assert.Equal(50, summary.CalculateLineCoverage(module.Value).Percent);
|
||||
@@ -159,9 +157,9 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestCalculateLineCoverage_MultiModule()
|
||||
{
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
var documentsFirstModule = _averageCalculationMultiModule["module"];
|
||||
var documentsSecondModule = _averageCalculationMultiModule["aditionalModule"];
|
||||
var summary = new CoverageSummary();
|
||||
Documents documentsFirstModule = _averageCalculationMultiModule["module"];
|
||||
Documents documentsSecondModule = _averageCalculationMultiModule["aditionalModule"];
|
||||
|
||||
Assert.Equal(37.5, summary.CalculateLineCoverage(_averageCalculationMultiModule).AverageModulePercent);
|
||||
Assert.Equal(50, summary.CalculateLineCoverage(documentsFirstModule.First().Value).Percent);
|
||||
@@ -174,12 +172,12 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestCalculateBranchCoverage_SingleModule()
|
||||
{
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
var summary = new CoverageSummary();
|
||||
|
||||
var module = _averageCalculationSingleModule.First();
|
||||
var document = module.Value.First();
|
||||
var @class = document.Value.First();
|
||||
var method = @class.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Documents> module = _averageCalculationSingleModule.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Classes> document = module.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Methods> @class = document.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Method> method = @class.Value.First();
|
||||
|
||||
Assert.Equal(100, summary.CalculateBranchCoverage(_averageCalculationSingleModule).AverageModulePercent);
|
||||
Assert.Equal(100, summary.CalculateBranchCoverage(module.Value).Percent);
|
||||
@@ -191,9 +189,9 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestCalculateBranchCoverage_MultiModule()
|
||||
{
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
var documentsFirstModule = _averageCalculationMultiModule["module"];
|
||||
var documentsSecondModule = _averageCalculationMultiModule["aditionalModule"];
|
||||
var summary = new CoverageSummary();
|
||||
Documents documentsFirstModule = _averageCalculationMultiModule["module"];
|
||||
Documents documentsSecondModule = _averageCalculationMultiModule["aditionalModule"];
|
||||
|
||||
Assert.Equal(83.33, summary.CalculateBranchCoverage(_averageCalculationMultiModule).AverageModulePercent);
|
||||
Assert.Equal(100, summary.CalculateBranchCoverage(documentsFirstModule.First().Value).Percent);
|
||||
@@ -203,12 +201,12 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestCalculateMethodCoverage_SingleModule()
|
||||
{
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
var summary = new CoverageSummary();
|
||||
|
||||
var module = _averageCalculationSingleModule.First();
|
||||
var document = module.Value.First();
|
||||
var @class = document.Value.First();
|
||||
var method = @class.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Documents> module = _averageCalculationSingleModule.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Classes> document = module.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Methods> @class = document.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Method> method = @class.Value.First();
|
||||
|
||||
Assert.Equal(100, summary.CalculateMethodCoverage(_averageCalculationSingleModule).AverageModulePercent);
|
||||
Assert.Equal(100, summary.CalculateMethodCoverage(module.Value).Percent);
|
||||
@@ -220,9 +218,9 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestCalculateMethodCoverage_MultiModule()
|
||||
{
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
var documentsFirstModule = _averageCalculationMultiModule["module"];
|
||||
var documentsSecondModule = _averageCalculationMultiModule["aditionalModule"];
|
||||
var summary = new CoverageSummary();
|
||||
Documents documentsFirstModule = _averageCalculationMultiModule["module"];
|
||||
Documents documentsSecondModule = _averageCalculationMultiModule["aditionalModule"];
|
||||
|
||||
Assert.Equal(75, summary.CalculateMethodCoverage(_averageCalculationMultiModule).AverageModulePercent);
|
||||
Assert.Equal(100, summary.CalculateMethodCoverage(documentsFirstModule.First().Value).Percent);
|
||||
@@ -232,12 +230,12 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestCalculateLineCoveragePercentage_ArithmeticPrecisionCheck()
|
||||
{
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
var summary = new CoverageSummary();
|
||||
|
||||
var module = _moduleArithmeticPrecision.First();
|
||||
var document = module.Value.First();
|
||||
var @class = document.Value.First();
|
||||
var method = @class.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Documents> module = _moduleArithmeticPrecision.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Classes> document = module.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Methods> @class = document.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Method> method = @class.Value.First();
|
||||
|
||||
Assert.Equal(16.66, summary.CalculateLineCoverage(_moduleArithmeticPrecision).AverageModulePercent);
|
||||
Assert.Equal(16.66, summary.CalculateLineCoverage(module.Value).Percent);
|
||||
@@ -249,12 +247,12 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestCalculateBranchCoveragePercentage_ArithmeticPrecisionCheck()
|
||||
{
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
var summary = new CoverageSummary();
|
||||
|
||||
var module = _moduleArithmeticPrecision.First();
|
||||
var document = module.Value.First();
|
||||
var @class = document.Value.First();
|
||||
var method = @class.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Documents> module = _moduleArithmeticPrecision.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Classes> document = module.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Methods> @class = document.Value.First();
|
||||
System.Collections.Generic.KeyValuePair<string, Method> method = @class.Value.First();
|
||||
|
||||
Assert.Equal(16.66, summary.CalculateBranchCoverage(_moduleArithmeticPrecision).AverageModulePercent);
|
||||
Assert.Equal(16.66, summary.CalculateBranchCoverage(module.Value).Percent);
|
||||
@@ -263,4 +261,4 @@ namespace Coverlet.Core.Tests
|
||||
Assert.Equal(16.66, summary.CalculateBranchCoverage(method.Value.Branches).Percent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Coverlet.Core.Samples.Tests;
|
||||
using Coverlet.Tests.Xunit.Extensions;
|
||||
using Xunit;
|
||||
|
||||
namespace Coverlet.Core.Tests
|
||||
@@ -146,7 +146,7 @@ namespace Coverlet.Core.Tests
|
||||
return 0;
|
||||
}, new string[] { path });
|
||||
|
||||
var document = TestInstrumentationHelper.GetCoverageResult(path).Document("Instrumentation.AsyncAwait.cs");
|
||||
Core.Instrumentation.Document document = TestInstrumentationHelper.GetCoverageResult(path).Document("Instrumentation.AsyncAwait.cs");
|
||||
document.AssertLinesCovered(BuildConfiguration.Debug, (133, 1), (134, 1), (135, 1), (136, 1), (137, 1));
|
||||
Assert.DoesNotContain(document.Branches, x => x.Key.Line == 134);
|
||||
}
|
||||
@@ -174,7 +174,7 @@ namespace Coverlet.Core.Tests
|
||||
return 0;
|
||||
}, new string[] { path });
|
||||
|
||||
var document = TestInstrumentationHelper.GetCoverageResult(path).Document("Instrumentation.AsyncAwait.cs");
|
||||
Core.Instrumentation.Document document = TestInstrumentationHelper.GetCoverageResult(path).Document("Instrumentation.AsyncAwait.cs");
|
||||
document.AssertLinesCovered(BuildConfiguration.Debug, (150, 1));
|
||||
Assert.DoesNotContain(document.Branches, x => x.Key.Line == 150);
|
||||
}
|
||||
@@ -203,7 +203,7 @@ namespace Coverlet.Core.Tests
|
||||
return 0;
|
||||
}, new string[] { path });
|
||||
|
||||
var document = TestInstrumentationHelper.GetCoverageResult(path).Document("Instrumentation.AsyncAwait.cs");
|
||||
Core.Instrumentation.Document document = TestInstrumentationHelper.GetCoverageResult(path).Document("Instrumentation.AsyncAwait.cs");
|
||||
document.AssertLinesCoveredFromTo(BuildConfiguration.Debug, 170, 176);
|
||||
document.AssertBranchesCovered(BuildConfiguration.Debug, (171, 0, 1), (171, 1, 1));
|
||||
Assert.DoesNotContain(document.Branches, x => x.Key.Line == 176);
|
||||
@@ -214,4 +214,4 @@ namespace Coverlet.Core.Tests
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Coverlet.Core.Samples.Tests;
|
||||
using Coverlet.Tests.Xunit.Extensions;
|
||||
using Xunit;
|
||||
|
||||
namespace Coverlet.Core.Tests
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Coverlet.Core.Samples.Tests;
|
||||
using Coverlet.Tests.Xunit.Extensions;
|
||||
using Xunit;
|
||||
|
||||
namespace Coverlet.Core.Tests
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Coverlet.Core.Samples.Tests;
|
||||
using Coverlet.Tests.Xunit.Extensions;
|
||||
using Xunit;
|
||||
|
||||
namespace Coverlet.Core.Tests
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.IO;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Coverlet.Core.Samples.Tests;
|
||||
using Xunit;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Coverlet.Core.Samples.Tests;
|
||||
using Coverlet.Tests.Xunit.Extensions;
|
||||
using Xunit;
|
||||
|
||||
namespace Coverlet.Core.Tests
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Coverlet.Core.Samples.Tests;
|
||||
using Coverlet.Tests.Xunit.Extensions;
|
||||
using Xunit;
|
||||
|
||||
namespace Coverlet.Core.Tests
|
||||
@@ -64,7 +65,7 @@ namespace Coverlet.Core.Tests
|
||||
return 0;
|
||||
}, new string[] { path });
|
||||
|
||||
var res = TestInstrumentationHelper.GetCoverageResult(path);
|
||||
CoverageResult res = TestInstrumentationHelper.GetCoverageResult(path);
|
||||
res.Document("Instrumentation.CatchBlock.cs")
|
||||
.AssertLinesCoveredAllBut(BuildConfiguration.Debug, 45, 59, 113, 127, 137, 138, 139, 153, 154, 155, 156, 175, 189, 199, 200, 201, 222, 223, 224, 225, 252, 266, 335, 349)
|
||||
.ExpectedTotalNumberOfBranches(BuildConfiguration.Debug, 6)
|
||||
@@ -76,4 +77,4 @@ namespace Coverlet.Core.Tests
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Coverlet.Core.Samples.Tests;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Coverlet.Core.Abstractions;
|
||||
using Coverlet.Core.Helpers;
|
||||
using Coverlet.Core.Samples.Tests;
|
||||
using Coverlet.Core.Symbols;
|
||||
using Coverlet.Tests.Xunit.Extensions;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestCoverageSkipModule__AssemblyMarkedAsExcludeFromCodeCoverage()
|
||||
{
|
||||
Mock<FileSystem> partialMockFileSystem = new Mock<FileSystem>();
|
||||
var partialMockFileSystem = new Mock<FileSystem>();
|
||||
partialMockFileSystem.CallBase = true;
|
||||
partialMockFileSystem.Setup(fs => fs.NewFileStream(It.IsAny<string>(), It.IsAny<FileMode>(), It.IsAny<FileAccess>())).Returns((string path, FileMode mode, FileAccess access) =>
|
||||
{
|
||||
@@ -29,11 +29,11 @@ namespace Coverlet.Core.Tests
|
||||
|
||||
string excludedbyattributeDll = Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), "TestAssets"), "coverlet.tests.projectsample.excludedbyattribute.dll").First();
|
||||
|
||||
InstrumentationHelper instrumentationHelper =
|
||||
var instrumentationHelper =
|
||||
new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock<ILogger>().Object,
|
||||
new SourceRootTranslator(excludedbyattributeDll, new Mock<ILogger>().Object, new FileSystem()));
|
||||
|
||||
CoverageParameters parameters = new CoverageParameters
|
||||
var parameters = new CoverageParameters
|
||||
{
|
||||
IncludeFilters = new string[] { "[coverlet.tests.projectsample.excludedbyattribute*]*" },
|
||||
IncludeDirectories = Array.Empty<string>(),
|
||||
@@ -74,7 +74,7 @@ namespace Coverlet.Core.Tests
|
||||
|
||||
CoverageResult result = TestInstrumentationHelper.GetCoverageResult(path);
|
||||
|
||||
var document = result.Document("Instrumentation.ExcludeFromCoverage.cs");
|
||||
Core.Instrumentation.Document document = result.Document("Instrumentation.ExcludeFromCoverage.cs");
|
||||
|
||||
// Invoking method "Test" of class "MethodsWithExcludeFromCodeCoverageAttr" we expect to cover 100% lines for MethodsWithExcludeFromCodeCoverageAttr
|
||||
Assert.DoesNotContain(document.Lines, l =>
|
||||
@@ -278,4 +278,4 @@ namespace Coverlet.Core.Tests
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Coverlet.Core.Samples.Tests;
|
||||
using Coverlet.Tests.Xunit.Extensions;
|
||||
using Xunit;
|
||||
|
||||
namespace Coverlet.Core.Tests
|
||||
@@ -128,4 +129,4 @@ namespace Coverlet.Core.Tests
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.IO;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using Coverlet.Core.Abstractions;
|
||||
using Coverlet.Core.Instrumentation;
|
||||
using Moq;
|
||||
@@ -11,7 +14,7 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void CoverageResult_NegativeLineCoverage_TranslatedToMaxValueOfInt32()
|
||||
{
|
||||
InstrumenterResult instrumenterResult = new InstrumenterResult
|
||||
var instrumenterResult = new InstrumenterResult
|
||||
{
|
||||
HitsFilePath = "HitsFilePath",
|
||||
SourceLink = "SourceLink",
|
||||
@@ -36,7 +39,7 @@ namespace Coverlet.Core.Tests
|
||||
|
||||
instrumenterResult.Documents.Add("document", document);
|
||||
|
||||
CoveragePrepareResult coveragePrepareResult = new CoveragePrepareResult
|
||||
var coveragePrepareResult = new CoveragePrepareResult
|
||||
{
|
||||
UseSourceLink = true,
|
||||
Results = new[] {instrumenterResult},
|
||||
@@ -44,7 +47,7 @@ namespace Coverlet.Core.Tests
|
||||
};
|
||||
|
||||
Stream memoryStream = new MemoryStream();
|
||||
BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
|
||||
var binaryWriter = new BinaryWriter(memoryStream);
|
||||
binaryWriter.Write(1);
|
||||
binaryWriter.Write(-1);
|
||||
memoryStream.Position = 0;
|
||||
@@ -57,7 +60,7 @@ namespace Coverlet.Core.Tests
|
||||
var coverage = new Coverage(coveragePrepareResult, new Mock<ILogger>().Object, new Mock<IInstrumentationHelper>().Object,
|
||||
fileSystemMock.Object, new Mock<ISourceRootTranslator>().Object);
|
||||
|
||||
var coverageResult = coverage.GetCoverageResult();
|
||||
CoverageResult coverageResult = coverage.GetCoverageResult();
|
||||
coverageResult.Document("document").AssertLinesCovered(BuildConfiguration.Debug, (1, int.MaxValue));
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Coverlet.Core.Samples.Tests;
|
||||
using Coverlet.Tests.Xunit.Extensions;
|
||||
using Xunit;
|
||||
|
||||
namespace Coverlet.Core.Tests
|
||||
@@ -138,4 +139,4 @@ namespace Coverlet.Core.Tests
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Coverlet.Core.Samples.Tests;
|
||||
using Coverlet.Tests.Xunit.Extensions;
|
||||
using Tmds.Utils;
|
||||
using Xunit;
|
||||
|
||||
@@ -150,4 +151,4 @@ namespace Coverlet.Core.Tests
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Coverlet.Core.Samples.Tests;
|
||||
using Tmds.Utils;
|
||||
using Xunit;
|
||||
@@ -19,7 +21,7 @@ namespace Coverlet.Core.Tests
|
||||
{
|
||||
CoveragePrepareResult coveragePrepareResult = await TestInstrumentationHelper.Run<Yield>(instance =>
|
||||
{
|
||||
foreach (var _ in instance.One()) ;
|
||||
foreach (dynamic _ in instance.One()) ;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, persistPrepareResultToFile: pathSerialize[0]);
|
||||
@@ -50,7 +52,7 @@ namespace Coverlet.Core.Tests
|
||||
{
|
||||
CoveragePrepareResult coveragePrepareResult = await TestInstrumentationHelper.Run<Yield>(instance =>
|
||||
{
|
||||
foreach (var _ in instance.Two()) ;
|
||||
foreach (dynamic _ in instance.Two()) ;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, persistPrepareResultToFile: pathSerialize[0]);
|
||||
@@ -80,7 +82,7 @@ namespace Coverlet.Core.Tests
|
||||
{
|
||||
CoveragePrepareResult coveragePrepareResult = await TestInstrumentationHelper.Run<Yield>(instance =>
|
||||
{
|
||||
foreach (var _ in instance.OneWithSwitch(2)) ;
|
||||
foreach (dynamic _ in instance.OneWithSwitch(2)) ;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, persistPrepareResultToFile: pathSerialize[0]);
|
||||
@@ -111,7 +113,7 @@ namespace Coverlet.Core.Tests
|
||||
{
|
||||
CoveragePrepareResult coveragePrepareResult = await TestInstrumentationHelper.Run<Yield>(instance =>
|
||||
{
|
||||
foreach (var _ in instance.Three()) ;
|
||||
foreach (dynamic _ in instance.Three()) ;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, persistPrepareResultToFile: pathSerialize[0]);
|
||||
@@ -141,7 +143,7 @@ namespace Coverlet.Core.Tests
|
||||
{
|
||||
CoveragePrepareResult coveragePrepareResult = await TestInstrumentationHelper.Run<Yield>(instance =>
|
||||
{
|
||||
foreach (var _ in instance.Enumerable(new[] { "one", "two", "three", "four" })) ;
|
||||
foreach (dynamic _ in instance.Enumerable(new[] { "one", "two", "three", "four" })) ;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, persistPrepareResultToFile: pathSerialize[0]);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using Coverlet.Core.Abstractions;
|
||||
using Coverlet.Core.Helpers;
|
||||
using Coverlet.Core.Symbols;
|
||||
@@ -19,17 +21,17 @@ namespace Coverlet.Core.Tests
|
||||
string module = GetType().Assembly.Location;
|
||||
string pdb = Path.Combine(Path.GetDirectoryName(module), Path.GetFileNameWithoutExtension(module) + ".pdb");
|
||||
|
||||
var directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
|
||||
DirectoryInfo directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
|
||||
|
||||
File.Copy(module, Path.Combine(directory.FullName, Path.GetFileName(module)), true);
|
||||
File.Copy(pdb, Path.Combine(directory.FullName, Path.GetFileName(pdb)), true);
|
||||
|
||||
// TODO: Find a way to mimick hits
|
||||
InstrumentationHelper instrumentationHelper =
|
||||
var instrumentationHelper =
|
||||
new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock<ILogger>().Object,
|
||||
new SourceRootTranslator(module, new Mock<ILogger>().Object, new FileSystem()));
|
||||
|
||||
CoverageParameters parameters = new CoverageParameters
|
||||
var parameters = new CoverageParameters
|
||||
{
|
||||
IncludeFilters = new string[] { "[coverlet.tests.projectsample.excludedbyattribute*]*" },
|
||||
IncludeDirectories = Array.Empty<string>(),
|
||||
@@ -45,7 +47,7 @@ namespace Coverlet.Core.Tests
|
||||
var coverage = new Coverage(Path.Combine(directory.FullName, Path.GetFileName(module)), parameters, _mockLogger.Object, instrumentationHelper, new FileSystem(), new SourceRootTranslator(_mockLogger.Object, new FileSystem()), new CecilSymbolHelper());
|
||||
coverage.PrepareModules();
|
||||
|
||||
var result = coverage.GetCoverageResult();
|
||||
CoverageResult result = coverage.GetCoverageResult();
|
||||
|
||||
Assert.Empty(result.Modules);
|
||||
|
||||
@@ -58,16 +60,16 @@ namespace Coverlet.Core.Tests
|
||||
string module = GetType().Assembly.Location;
|
||||
string pdb = Path.Combine(Path.GetDirectoryName(module), Path.GetFileNameWithoutExtension(module) + ".pdb");
|
||||
|
||||
var directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
|
||||
DirectoryInfo directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
|
||||
|
||||
File.Copy(module, Path.Combine(directory.FullName, Path.GetFileName(module)), true);
|
||||
File.Copy(pdb, Path.Combine(directory.FullName, Path.GetFileName(pdb)), true);
|
||||
|
||||
InstrumentationHelper instrumentationHelper =
|
||||
var instrumentationHelper =
|
||||
new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock<ILogger>().Object,
|
||||
new SourceRootTranslator(module, new Mock<ILogger>().Object, new FileSystem()));
|
||||
|
||||
CoverageParameters parameters = new CoverageParameters
|
||||
var parameters = new CoverageParameters
|
||||
{
|
||||
IncludeFilters = Array.Empty<string>(),
|
||||
IncludeDirectories = Array.Empty<string>(),
|
||||
@@ -84,11 +86,11 @@ namespace Coverlet.Core.Tests
|
||||
new SourceRootTranslator(module, _mockLogger.Object, new FileSystem()), new CecilSymbolHelper());
|
||||
coverage.PrepareModules();
|
||||
|
||||
var result = coverage.GetCoverageResult();
|
||||
CoverageResult result = coverage.GetCoverageResult();
|
||||
|
||||
Assert.NotEmpty(result.Modules);
|
||||
|
||||
directory.Delete(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using Coverlet.Core.Instrumentation;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Coverlet.Core.Instrumentation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Xunit.Sdk;
|
||||
@@ -90,18 +92,18 @@ namespace Coverlet.Core.Tests
|
||||
|
||||
if (document.Lines.Values.All(l => l.Method != methodName) && document.Branches.Values.All(l => l.Method != methodName))
|
||||
{
|
||||
var methods = document.Lines.Values.Select(l => $"'{l.Method}'")
|
||||
IEnumerable<string> methods = document.Lines.Values.Select(l => $"'{l.Method}'")
|
||||
.Concat(document.Branches.Values.Select(b => $"'{b.Method}'"))
|
||||
.Distinct();
|
||||
throw new XunitException($"Method '{methodName}' not found. Methods in document: {string.Join(", ", methods)}");
|
||||
}
|
||||
|
||||
foreach (var line in document.Lines.Where(l => l.Value.Method == methodName))
|
||||
foreach (KeyValuePair<int, Line> line in document.Lines.Where(l => l.Value.Method == methodName))
|
||||
{
|
||||
methodDoc.Lines[line.Key] = line.Value;
|
||||
}
|
||||
|
||||
foreach (var branch in document.Branches.Where(b => b.Value.Method == methodName))
|
||||
foreach (KeyValuePair<BranchKey, Branch> branch in document.Branches.Where(b => b.Value.Method == methodName))
|
||||
{
|
||||
methodDoc.Branches[branch.Key] = branch.Value;
|
||||
}
|
||||
@@ -150,7 +152,7 @@ namespace Coverlet.Core.Tests
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
var builder = new StringBuilder();
|
||||
foreach (KeyValuePair<BranchKey, Branch> branch in document.Branches)
|
||||
{
|
||||
builder.AppendLine($"({branch.Value.Number}, {branch.Value.Ordinal}, {branch.Value.Hits}),");
|
||||
@@ -172,7 +174,7 @@ namespace Coverlet.Core.Tests
|
||||
return document;
|
||||
}
|
||||
|
||||
List<string> branchesToCover = new List<string>(lines.Select(b => $"[line {b.line} ordinal {b.ordinal}]"));
|
||||
var branchesToCover = new List<string>(lines.Select(b => $"[line {b.line} ordinal {b.ordinal}]"));
|
||||
foreach (KeyValuePair<BranchKey, Branch> branch in document.Branches)
|
||||
{
|
||||
foreach ((int lineToCheck, int ordinalToCheck, int expectedHits) in lines)
|
||||
@@ -270,7 +272,7 @@ namespace Coverlet.Core.Tests
|
||||
throw new ArgumentException("to cannot be lower than from");
|
||||
}
|
||||
|
||||
List<int> lines = new List<int>();
|
||||
var lines = new List<int>();
|
||||
foreach (KeyValuePair<int, Line> line in document.Lines)
|
||||
{
|
||||
if (line.Value.Number >= from && line.Value.Number <= to && line.Value.Hits > 0)
|
||||
@@ -301,7 +303,7 @@ namespace Coverlet.Core.Tests
|
||||
return document;
|
||||
}
|
||||
|
||||
List<int> linesToCover = new List<int>(lines.Select(l => l.line));
|
||||
var linesToCover = new List<int>(lines.Select(l => l.line));
|
||||
foreach (KeyValuePair<int, Line> line in document.Lines)
|
||||
{
|
||||
foreach ((int lineToCheck, int expectedHits) in lines)
|
||||
@@ -349,7 +351,7 @@ namespace Coverlet.Core.Tests
|
||||
return document;
|
||||
}
|
||||
|
||||
List<int> linesToCover = new List<int>(lines);
|
||||
var linesToCover = new List<int>(lines);
|
||||
foreach (KeyValuePair<int, Line> line in document.Lines)
|
||||
{
|
||||
foreach (int lineToCheck in lines)
|
||||
@@ -409,7 +411,7 @@ namespace Coverlet.Core.Tests
|
||||
return document;
|
||||
}
|
||||
|
||||
var unexpectedlyInstrumented = document.Lines.Select(l => l.Value.Number).Intersect(lines);
|
||||
IEnumerable<int> unexpectedlyInstrumented = document.Lines.Select(l => l.Value.Number).Intersect(lines);
|
||||
|
||||
if (unexpectedlyInstrumented.Any())
|
||||
{
|
||||
@@ -435,7 +437,7 @@ namespace Coverlet.Core.Tests
|
||||
|
||||
var instrumentedLines = document.Lines.Select(l => l.Value.Number).ToHashSet();
|
||||
|
||||
var missing = lines.Where(l => !instrumentedLines.Contains(l));
|
||||
IEnumerable<int> missing = lines.Where(l => !instrumentedLines.Contains(l));
|
||||
|
||||
if (missing.Any())
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -28,7 +31,7 @@ namespace Coverlet.Core.Tests
|
||||
/// </summary>
|
||||
public static void GenerateHtmlReport(CoverageResult coverageResult, IReporter reporter = null, string sourceFileFilter = "", [CallerMemberName] string directory = "")
|
||||
{
|
||||
JsonReporter defaultReporter = new JsonReporter();
|
||||
var defaultReporter = new JsonReporter();
|
||||
reporter ??= new CoberturaReporter();
|
||||
DirectoryInfo dir = Directory.CreateDirectory(directory);
|
||||
dir.Delete(true);
|
||||
@@ -62,12 +65,12 @@ namespace Coverlet.Core.Tests
|
||||
Assert.DoesNotContain("not found for module: ", message);
|
||||
});
|
||||
_processWideContainer.GetRequiredService<IInstrumentationHelper>().SetLogger(logger.Object);
|
||||
CoveragePrepareResult coveragePrepareResultLoaded = CoveragePrepareResult.Deserialize(result);
|
||||
Coverage coverage = new Coverage(coveragePrepareResultLoaded, logger.Object, _processWideContainer.GetService<IInstrumentationHelper>(), new FileSystem(), new SourceRootTranslator(new Mock<ILogger>().Object, new FileSystem()));
|
||||
var coveragePrepareResultLoaded = CoveragePrepareResult.Deserialize(result);
|
||||
var coverage = new Coverage(coveragePrepareResultLoaded, logger.Object, _processWideContainer.GetService<IInstrumentationHelper>(), new FileSystem(), new SourceRootTranslator(new Mock<ILogger>().Object, new FileSystem()));
|
||||
return coverage.GetCoverageResult();
|
||||
}
|
||||
|
||||
async public static Task<CoveragePrepareResult> Run<T>(Func<dynamic, Task> callMethod,
|
||||
public static async Task<CoveragePrepareResult> Run<T>(Func<dynamic, Task> callMethod,
|
||||
Func<string, string[]> includeFilter = null,
|
||||
Func<string, string[]> excludeFilter = null,
|
||||
Func<string, string[]> doesNotReturnAttributes = null,
|
||||
@@ -93,7 +96,7 @@ namespace Coverlet.Core.Tests
|
||||
|
||||
static string[] defaultFilters(string _) => Array.Empty<string>();
|
||||
|
||||
CoverageParameters parameters = new CoverageParameters
|
||||
var parameters = new CoverageParameters
|
||||
{
|
||||
IncludeFilters = (includeFilter is null ? defaultFilters(fileName) : includeFilter(fileName)).Concat(
|
||||
new string[]
|
||||
@@ -117,14 +120,14 @@ namespace Coverlet.Core.Tests
|
||||
};
|
||||
|
||||
// Instrument module
|
||||
Coverage coverage = new Coverage(newPath, parameters, new Logger(logFile),
|
||||
var coverage = new Coverage(newPath, parameters, new Logger(logFile),
|
||||
_processWideContainer.GetService<IInstrumentationHelper>(), _processWideContainer.GetService<IFileSystem>(), _processWideContainer.GetService<ISourceRootTranslator>(), _processWideContainer.GetService<ICecilSymbolHelper>());
|
||||
CoveragePrepareResult prepareResult = coverage.PrepareModules();
|
||||
|
||||
Assert.Single(prepareResult.Results);
|
||||
|
||||
// Load new assembly
|
||||
Assembly asm = Assembly.LoadFile(newPath);
|
||||
var asm = Assembly.LoadFile(newPath);
|
||||
|
||||
// Instance type and call method
|
||||
await callMethod(Activator.CreateInstance(asm.GetType(typeof(T).FullName)));
|
||||
@@ -140,7 +143,7 @@ namespace Coverlet.Core.Tests
|
||||
tracker.GetTypeInfo().GetMethod("UnloadModule").Invoke(null, new object[2] { null, null });
|
||||
|
||||
// Persist CoveragePrepareResult
|
||||
using (FileStream fs = new FileStream(persistPrepareResultToFile, FileMode.Open))
|
||||
using (var fs = new FileStream(persistPrepareResultToFile, FileMode.Open))
|
||||
{
|
||||
await CoveragePrepareResult.Serialize(prepareResult).CopyToAsync(fs);
|
||||
}
|
||||
@@ -237,7 +240,7 @@ namespace Coverlet.Core.Tests
|
||||
// We log to files for debugging pourpose, we can check if instrumentation is ok
|
||||
class Logger : ILogger
|
||||
{
|
||||
string _logFile;
|
||||
readonly string _logFile;
|
||||
|
||||
public Logger(string logFile) => _logFile = logFile;
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Toni Solarin-Sodara
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Coverlet.Core.Enums;
|
||||
using Xunit;
|
||||
|
||||
@@ -6,22 +9,22 @@ namespace Coverlet.Core.Tests
|
||||
{
|
||||
public class CoverageResultTests
|
||||
{
|
||||
private Modules _modules;
|
||||
private readonly Modules _modules;
|
||||
|
||||
public CoverageResultTests()
|
||||
{
|
||||
Lines lines = new Lines();
|
||||
var lines = new Lines();
|
||||
lines.Add(1, 1);
|
||||
lines.Add(2, 1);
|
||||
lines.Add(3, 1);
|
||||
Branches branches = new Branches();
|
||||
var branches = new Branches();
|
||||
branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 0, Ordinal = 1 });
|
||||
branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 1, Ordinal = 2 });
|
||||
branches.Add(new BranchInfo { Line = 2, Hits = 0, Offset = 1, Path = 0, Ordinal = 1 });
|
||||
|
||||
// System.Void Coverlet.Core.Tests.CoverageResultTests::CoverageResultTests - 3/3 100% line 2/3 66.7% branch coverage
|
||||
Methods methods = new Methods();
|
||||
var methodString = "System.Void Coverlet.Core.Tests.CoverageResultTests::CoverageResultTests()";
|
||||
var methods = new Methods();
|
||||
string methodString = "System.Void Coverlet.Core.Tests.CoverageResultTests::CoverageResultTests()";
|
||||
methods.Add(methodString, new Method());
|
||||
methods[methodString].Lines = lines;
|
||||
methods[methodString].Branches = branches;
|
||||
@@ -35,13 +38,13 @@ namespace Coverlet.Core.Tests
|
||||
{2, 0},
|
||||
};
|
||||
|
||||
Classes classes = new Classes();
|
||||
var classes = new Classes();
|
||||
classes.Add("Coverlet.Core.Tests.CoverageResultTests", methods);
|
||||
// Methods - 1/2 (50%)
|
||||
// Lines - 3/5 (60%)
|
||||
// Branches - 2/3 (66.67%)
|
||||
|
||||
Documents documents = new Documents();
|
||||
var documents = new Documents();
|
||||
documents.Add("doc.cs", classes);
|
||||
|
||||
_modules = new Modules();
|
||||
@@ -51,11 +54,11 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestGetThresholdTypesBelowThresholdLine()
|
||||
{
|
||||
CoverageResult result = new CoverageResult();
|
||||
var result = new CoverageResult();
|
||||
result.Modules = _modules;
|
||||
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
Dictionary<ThresholdTypeFlags, double> thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>()
|
||||
var summary = new CoverageSummary();
|
||||
var thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>()
|
||||
{
|
||||
{ ThresholdTypeFlags.Line, 90 },
|
||||
{ ThresholdTypeFlags.Method, 10 },
|
||||
@@ -71,11 +74,11 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestGetThresholdTypesBelowThresholdMethod()
|
||||
{
|
||||
CoverageResult result = new CoverageResult();
|
||||
var result = new CoverageResult();
|
||||
result.Modules = _modules;
|
||||
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
Dictionary<ThresholdTypeFlags, double> thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>()
|
||||
var summary = new CoverageSummary();
|
||||
var thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>()
|
||||
{
|
||||
{ ThresholdTypeFlags.Line, 50 },
|
||||
{ ThresholdTypeFlags.Method, 75 },
|
||||
@@ -91,11 +94,11 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestGetThresholdTypesBelowThresholdBranch()
|
||||
{
|
||||
CoverageResult result = new CoverageResult();
|
||||
var result = new CoverageResult();
|
||||
result.Modules = _modules;
|
||||
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
Dictionary<ThresholdTypeFlags, double> thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>()
|
||||
var summary = new CoverageSummary();
|
||||
var thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>()
|
||||
{
|
||||
{ ThresholdTypeFlags.Line, 50 },
|
||||
{ ThresholdTypeFlags.Method, 50 },
|
||||
@@ -111,11 +114,11 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestGetThresholdTypesBelowThresholdAllGood()
|
||||
{
|
||||
CoverageResult result = new CoverageResult();
|
||||
var result = new CoverageResult();
|
||||
result.Modules = _modules;
|
||||
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
Dictionary<ThresholdTypeFlags, double> thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>()
|
||||
var summary = new CoverageSummary();
|
||||
var thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>()
|
||||
{
|
||||
{ ThresholdTypeFlags.Line, 50 },
|
||||
{ ThresholdTypeFlags.Method, 50 },
|
||||
@@ -131,11 +134,11 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestGetThresholdTypesBelowThresholdAllFail()
|
||||
{
|
||||
CoverageResult result = new CoverageResult();
|
||||
var result = new CoverageResult();
|
||||
result.Modules = _modules;
|
||||
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
Dictionary<ThresholdTypeFlags, double> thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>()
|
||||
var summary = new CoverageSummary();
|
||||
var thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>()
|
||||
{
|
||||
{ ThresholdTypeFlags.Line, 100 },
|
||||
{ ThresholdTypeFlags.Method, 100 },
|
||||
@@ -152,11 +155,11 @@ namespace Coverlet.Core.Tests
|
||||
[Fact]
|
||||
public void TestGetThresholdTypesBelowThresholdWhenNoModuleInstrumented()
|
||||
{
|
||||
CoverageResult result = new CoverageResult();
|
||||
var result = new CoverageResult();
|
||||
result.Modules = new Modules();
|
||||
|
||||
CoverageSummary summary = new CoverageSummary();
|
||||
Dictionary<ThresholdTypeFlags, double> thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>()
|
||||
var summary = new CoverageSummary();
|
||||
var thresholdTypeFlagValues = new Dictionary<ThresholdTypeFlags, double>()
|
||||
{
|
||||
{ ThresholdTypeFlags.Line, 80 },
|
||||
{ ThresholdTypeFlags.Method, 80 },
|
||||
@@ -170,4 +173,4 @@ namespace Coverlet.Core.Tests
|
||||
Assert.Equal(thresholdTypeFlags, resThresholdTypeFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user