From 8ed3872a553472fb0cccbebd1472bd34114e3cbb Mon Sep 17 00:00:00 2001 From: William Kempf Date: Sun, 1 Oct 2023 10:09:29 -0400 Subject: [PATCH] feat(vnext): add Testify.Assertions project Add the Testify.Assertions project and the associated Testify.Assertions.Tests test project to the solution. Implement enough to prove the new design. --- .editorconfig | 388 +++++- .editorconfig.bak | 55 + Testify.sln | 30 +- src/Directory.packages.props | 5 +- .../Testify.Examples/packages.lock.json | 19 +- src/Testify.Assertions/ActualValue.cs | 26 + src/Testify.Assertions/Assertion.cs | 120 ++ src/Testify.Assertions/AssertionException.cs | 62 + src/Testify.Assertions/BooleanAssertions.cs | 43 + src/Testify.Assertions/ExceptionAssertions.cs | 174 +++ .../Formatting/DateTimeValueFormatter.cs | 51 + .../Formatting/DefaultValueFormatter.cs | 8 + .../Formatting/Formatter.cs | 72 ++ .../Formatting/GuidValueFormatter.cs | 6 + .../Formatting/IValueFormatter.cs | 25 + .../Formatting/NullValueFormatter.cs | 10 + .../Formatting/StringValueFormatter.cs | 6 + .../Formatting/ValueFormatter.cs | 23 + src/Testify.Assertions/GlobalUsings.cs | 4 + src/Testify.Assertions/Guard.cs | 34 + .../IAdditionalThrowExceptions.cs | 5 + .../Internal/AssertionScope.cs | 65 + .../Internal/FallbackFrameworkAdapter.cs | 16 + .../Internal/FrameworkAdapter.cs | 60 + .../Internal/MstestFrameworkAdapter.cs | 11 + .../Internal/NunitFrameworkAdapter.cs | 9 + .../Internal/XunitFrameworkAdapter.cs | 23 + .../Testify.Assertions.csproj | 16 + src/Testify.Assertions/packages.lock.json | 13 + .../AcceptanceTestAttribute.cs | 8 + src/Testify.xUnit.Traits/BugAttribute.cs | 13 + src/Testify.xUnit.Traits/CategoryAttribute.cs | 37 + src/Testify.xUnit.Traits/EpicAttribute.cs | 13 + .../ExploratoryAttribute.cs | 8 + src/Testify.xUnit.Traits/FeatureAttribute.cs | 13 + .../ITraitProviderAttribute.cs | 10 + .../IntegrationTestAttribute.cs | 8 + src/Testify.xUnit.Traits/IssueAttribute.cs | 16 + src/Testify.xUnit.Traits/SlowAttribute.cs | 8 + .../SmokeTestAttribute.cs | 8 + src/Testify.xUnit.Traits/TaskAttribute.cs | 13 + .../Testify - Backup.xUnit.Traits.csproj | 13 + .../Testify.xUnit.Traits.csproj | 14 + .../TraitProviderAttribute.cs | 13 + .../TraitProviderDiscoverer.cs | 19 + src/Testify.xUnit.Traits/UnitTestAttribute.cs | 6 + .../UserStoryAttribute.cs | 13 + src/Testify.xUnit.Traits/WorkItemAttribute.cs | 41 + src/Testify.xUnit.Traits/packages.lock.json | 920 +++++++++++++++ src/Testify/AssertionException.cs | 1 - .../AssertionsTests.cs | 161 +++ .../BooleanAssertionsTests.cs | 53 + .../ExceptionAssertionsTests.cs | 51 + .../Formatting/FormatterTests.cs | 137 +++ .../Testify.Assertions.Tests/GlobalUsings.cs | 8 + src/Tests/Testify.Assertions.Tests/Helpers.cs | 25 + .../Testify.Assertions.Tests.csproj | 30 + .../packages.lock.json | 1041 +++++++++++++++++ .../Testify.Moq.Tests/packages.lock.json | 19 +- src/Tests/Testify.Tests/packages.lock.json | 19 +- 60 files changed, 4048 insertions(+), 70 deletions(-) create mode 100644 .editorconfig.bak create mode 100644 src/Testify.Assertions/ActualValue.cs create mode 100644 src/Testify.Assertions/Assertion.cs create mode 100644 src/Testify.Assertions/AssertionException.cs create mode 100644 src/Testify.Assertions/BooleanAssertions.cs create mode 100644 src/Testify.Assertions/ExceptionAssertions.cs create mode 100644 src/Testify.Assertions/Formatting/DateTimeValueFormatter.cs create mode 100644 src/Testify.Assertions/Formatting/DefaultValueFormatter.cs create mode 100644 src/Testify.Assertions/Formatting/Formatter.cs create mode 100644 src/Testify.Assertions/Formatting/GuidValueFormatter.cs create mode 100644 src/Testify.Assertions/Formatting/IValueFormatter.cs create mode 100644 src/Testify.Assertions/Formatting/NullValueFormatter.cs create mode 100644 src/Testify.Assertions/Formatting/StringValueFormatter.cs create mode 100644 src/Testify.Assertions/Formatting/ValueFormatter.cs create mode 100644 src/Testify.Assertions/GlobalUsings.cs create mode 100644 src/Testify.Assertions/Guard.cs create mode 100644 src/Testify.Assertions/IAdditionalThrowExceptions.cs create mode 100644 src/Testify.Assertions/Internal/AssertionScope.cs create mode 100644 src/Testify.Assertions/Internal/FallbackFrameworkAdapter.cs create mode 100644 src/Testify.Assertions/Internal/FrameworkAdapter.cs create mode 100644 src/Testify.Assertions/Internal/MstestFrameworkAdapter.cs create mode 100644 src/Testify.Assertions/Internal/NunitFrameworkAdapter.cs create mode 100644 src/Testify.Assertions/Internal/XunitFrameworkAdapter.cs create mode 100644 src/Testify.Assertions/Testify.Assertions.csproj create mode 100644 src/Testify.Assertions/packages.lock.json create mode 100644 src/Testify.xUnit.Traits/AcceptanceTestAttribute.cs create mode 100644 src/Testify.xUnit.Traits/BugAttribute.cs create mode 100644 src/Testify.xUnit.Traits/CategoryAttribute.cs create mode 100644 src/Testify.xUnit.Traits/EpicAttribute.cs create mode 100644 src/Testify.xUnit.Traits/ExploratoryAttribute.cs create mode 100644 src/Testify.xUnit.Traits/FeatureAttribute.cs create mode 100644 src/Testify.xUnit.Traits/ITraitProviderAttribute.cs create mode 100644 src/Testify.xUnit.Traits/IntegrationTestAttribute.cs create mode 100644 src/Testify.xUnit.Traits/IssueAttribute.cs create mode 100644 src/Testify.xUnit.Traits/SlowAttribute.cs create mode 100644 src/Testify.xUnit.Traits/SmokeTestAttribute.cs create mode 100644 src/Testify.xUnit.Traits/TaskAttribute.cs create mode 100644 src/Testify.xUnit.Traits/Testify - Backup.xUnit.Traits.csproj create mode 100644 src/Testify.xUnit.Traits/Testify.xUnit.Traits.csproj create mode 100644 src/Testify.xUnit.Traits/TraitProviderAttribute.cs create mode 100644 src/Testify.xUnit.Traits/TraitProviderDiscoverer.cs create mode 100644 src/Testify.xUnit.Traits/UnitTestAttribute.cs create mode 100644 src/Testify.xUnit.Traits/UserStoryAttribute.cs create mode 100644 src/Testify.xUnit.Traits/WorkItemAttribute.cs create mode 100644 src/Testify.xUnit.Traits/packages.lock.json create mode 100644 src/Tests/Testify.Assertions.Tests/AssertionsTests.cs create mode 100644 src/Tests/Testify.Assertions.Tests/BooleanAssertionsTests.cs create mode 100644 src/Tests/Testify.Assertions.Tests/ExceptionAssertionsTests.cs create mode 100644 src/Tests/Testify.Assertions.Tests/Formatting/FormatterTests.cs create mode 100644 src/Tests/Testify.Assertions.Tests/GlobalUsings.cs create mode 100644 src/Tests/Testify.Assertions.Tests/Helpers.cs create mode 100644 src/Tests/Testify.Assertions.Tests/Testify.Assertions.Tests.csproj create mode 100644 src/Tests/Testify.Assertions.Tests/packages.lock.json diff --git a/.editorconfig b/.editorconfig index e6dbf64..f44f0d7 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,55 +1,365 @@ -# EditorConfig is awesome: -http://EditorConfig.org root = true +# All files [*] indent_style = space -# (Please don't specify an indent_size here; that has too many unintended consequences.) - -[*.cs,*.csx,*.vb,*.vbx] -trim_trailing_whitespace = true -insert_final_newline = true -max_line_length = 120 -spaces_around_operators = true -curly_bracket_next_line = true -spaces_around_brackets = both -indent_brace_style = Allman -indent_size = 4 -[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] +# Xml files +[*.xml] indent_size = 2 -[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] -indent_size = 2 +# C# files +[*.cs] -[*.json] -indent_size = 2 +#### Core EditorConfig Options #### -[*.{cs, vb}] -dotnet_style_qualification_for_field = false:suggestion -dotnet_style_qualification_for_property = false:suggestion -dotnet_style_qualification_for_method = false:suggestion -dotnet_style_qualification_for_event = false:suggestion -dotnet_style_predefined_type_for_locals_parameters_members = true:error -dotnet_style_predefined_type_for_member_access = true:error -dotnet_style_object_initializer = true:suggestion -dotnet_style_collection_initializer = true:suggestion +# Indentation and spacing +indent_size = 4 +tab_width = 4 + +# New line preferences +end_of_line = crlf +insert_final_newline = false + +#### .NET Coding Conventions #### +[*.{cs,vb}] + +# Organize usings +dotnet_separate_import_directive_groups = true +dotnet_sort_system_directives_first = true +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false:silent +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_property = false:silent + +# 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_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent + +# Expression-level preferences dotnet_style_coalesce_expression = true:suggestion -dotnet_style_null_propagation = true:suggestion +dotnet_style_collection_initializer = true:suggestion dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_object_initializer = true:suggestion +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_return = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion + +# Field preferences +dotnet_style_readonly_field = true:warning + +# Parameter preferences +dotnet_code_quality_unused_parameters = all:suggestion + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none +#### C# Coding Conventions #### [*.cs] -csharp_style_var_for_built_in_types = true:suggestion -csharp_style_var_when_type_is_apparent = true:suggestion -csharp_style_var_elsewhere = true:suggestion -csharp_style_expression_bodied_methods = true:suggestion -csharp_style_expression_bodied_constructors = true:suggestion -csharp_style_expression_bodied_operators = true:suggestion -csharp_style_expression_bodied_properties = true:suggestion -csharp_style_expression_bodied_indexers = true:suggestion -csharp_style_expression_bodied_accessors = true:suggestion -csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion + +# var preferences +csharp_style_var_elsewhere = false:silent +csharp_style_var_for_built_in_types = false:silent +csharp_style_var_when_type_is_apparent = false:silent + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_lambdas = true:suggestion +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent + +# Pattern matching preferences csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_prefer_switch_expression = true:suggestion + +# Null-checking preferences +csharp_style_conditional_delegate_call = true:suggestion + +# Modifier preferences +csharp_prefer_static_local_function = true:warning +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent + +# Code-block preferences +csharp_prefer_braces = true:silent +csharp_prefer_simple_using_statement = true:suggestion + +# Expression-level preferences +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion csharp_style_throw_expression = true:suggestion -csharp_style_conditional_delegate_call = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_expression_statement_preference = discard_variable:silent + +# 'using' directive preferences +csharp_style_namespace_declarations = file_scoped:silent +csharp_using_directive_placement = inside_namespace:silent + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# 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 = false +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_blocks = true +csharp_preserve_single_line_statements = true + +#### Naming styles #### +[*.{cs,vb}] + +# Naming rules + +dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.symbols = types_and_namespaces +dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.interfaces_should_be_ipascalcase.severity = suggestion +dotnet_naming_rule.interfaces_should_be_ipascalcase.symbols = interfaces +dotnet_naming_rule.interfaces_should_be_ipascalcase.style = ipascalcase + +dotnet_naming_rule.type_parameters_should_be_tpascalcase.severity = suggestion +dotnet_naming_rule.type_parameters_should_be_tpascalcase.symbols = type_parameters +dotnet_naming_rule.type_parameters_should_be_tpascalcase.style = tpascalcase + +dotnet_naming_rule.methods_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.methods_should_be_pascalcase.symbols = methods +dotnet_naming_rule.methods_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.properties_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.properties_should_be_pascalcase.symbols = properties +dotnet_naming_rule.properties_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.events_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.events_should_be_pascalcase.symbols = events +dotnet_naming_rule.events_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.local_variables_should_be_camelcase.severity = suggestion +dotnet_naming_rule.local_variables_should_be_camelcase.symbols = local_variables +dotnet_naming_rule.local_variables_should_be_camelcase.style = camelcase + +dotnet_naming_rule.local_constants_should_be_camelcase.severity = suggestion +dotnet_naming_rule.local_constants_should_be_camelcase.symbols = local_constants +dotnet_naming_rule.local_constants_should_be_camelcase.style = camelcase + +dotnet_naming_rule.parameters_should_be_camelcase.severity = suggestion +dotnet_naming_rule.parameters_should_be_camelcase.symbols = parameters +dotnet_naming_rule.parameters_should_be_camelcase.style = camelcase + +dotnet_naming_rule.public_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.public_fields_should_be_pascalcase.symbols = public_fields +dotnet_naming_rule.public_fields_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.private_fields_should_be__camelcase.severity = suggestion +dotnet_naming_rule.private_fields_should_be__camelcase.symbols = private_fields +dotnet_naming_rule.private_fields_should_be__camelcase.style = _camelcase + +dotnet_naming_rule.private_static_fields_should_be_s_camelcase.severity = suggestion +dotnet_naming_rule.private_static_fields_should_be_s_camelcase.symbols = private_static_fields +dotnet_naming_rule.private_static_fields_should_be_s_camelcase.style = s_camelcase + +dotnet_naming_rule.public_constant_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.public_constant_fields_should_be_pascalcase.symbols = public_constant_fields +dotnet_naming_rule.public_constant_fields_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.private_constant_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.private_constant_fields_should_be_pascalcase.symbols = private_constant_fields +dotnet_naming_rule.private_constant_fields_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.symbols = public_static_readonly_fields +dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.symbols = private_static_readonly_fields +dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.enums_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.enums_should_be_pascalcase.symbols = enums +dotnet_naming_rule.enums_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.local_functions_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.local_functions_should_be_pascalcase.symbols = local_functions +dotnet_naming_rule.local_functions_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.non_field_members_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascalcase.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascalcase.style = pascalcase + +# Symbol specifications + +dotnet_naming_symbols.interfaces.applicable_kinds = interface +dotnet_naming_symbols.interfaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interfaces.required_modifiers = + +dotnet_naming_symbols.enums.applicable_kinds = enum +dotnet_naming_symbols.enums.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.enums.required_modifiers = + +dotnet_naming_symbols.events.applicable_kinds = event +dotnet_naming_symbols.events.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.events.required_modifiers = + +dotnet_naming_symbols.methods.applicable_kinds = method +dotnet_naming_symbols.methods.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.methods.required_modifiers = + +dotnet_naming_symbols.properties.applicable_kinds = property +dotnet_naming_symbols.properties.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.properties.required_modifiers = + +dotnet_naming_symbols.public_fields.applicable_kinds = field +dotnet_naming_symbols.public_fields.applicable_accessibilities = public, internal +dotnet_naming_symbols.public_fields.required_modifiers = + +dotnet_naming_symbols.private_fields.applicable_kinds = field +dotnet_naming_symbols.private_fields.applicable_accessibilities = private, protected, protected_internal, private_protected +dotnet_naming_symbols.private_fields.required_modifiers = + +dotnet_naming_symbols.private_static_fields.applicable_kinds = field +dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private, protected, protected_internal, private_protected +dotnet_naming_symbols.private_static_fields.required_modifiers = static + +dotnet_naming_symbols.types_and_namespaces.applicable_kinds = namespace, class, struct, interface, enum +dotnet_naming_symbols.types_and_namespaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types_and_namespaces.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +dotnet_naming_symbols.type_parameters.applicable_kinds = namespace +dotnet_naming_symbols.type_parameters.applicable_accessibilities = * +dotnet_naming_symbols.type_parameters.required_modifiers = + +dotnet_naming_symbols.private_constant_fields.applicable_kinds = field +dotnet_naming_symbols.private_constant_fields.applicable_accessibilities = private, protected, protected_internal, private_protected +dotnet_naming_symbols.private_constant_fields.required_modifiers = const + +dotnet_naming_symbols.local_variables.applicable_kinds = local +dotnet_naming_symbols.local_variables.applicable_accessibilities = local +dotnet_naming_symbols.local_variables.required_modifiers = + +dotnet_naming_symbols.local_constants.applicable_kinds = local +dotnet_naming_symbols.local_constants.applicable_accessibilities = local +dotnet_naming_symbols.local_constants.required_modifiers = const + +dotnet_naming_symbols.parameters.applicable_kinds = parameter +dotnet_naming_symbols.parameters.applicable_accessibilities = * +dotnet_naming_symbols.parameters.required_modifiers = + +dotnet_naming_symbols.public_constant_fields.applicable_kinds = field +dotnet_naming_symbols.public_constant_fields.applicable_accessibilities = public, internal +dotnet_naming_symbols.public_constant_fields.required_modifiers = const + +dotnet_naming_symbols.public_static_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.public_static_readonly_fields.applicable_accessibilities = public, internal +dotnet_naming_symbols.public_static_readonly_fields.required_modifiers = readonly, static + +dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private, protected, protected_internal, private_protected +dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = readonly, static + +dotnet_naming_symbols.local_functions.applicable_kinds = local_function +dotnet_naming_symbols.local_functions.applicable_accessibilities = * +dotnet_naming_symbols.local_functions.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascalcase.required_prefix = +dotnet_naming_style.pascalcase.required_suffix = +dotnet_naming_style.pascalcase.word_separator = +dotnet_naming_style.pascalcase.capitalization = pascal_case + +dotnet_naming_style.ipascalcase.required_prefix = I +dotnet_naming_style.ipascalcase.required_suffix = +dotnet_naming_style.ipascalcase.word_separator = +dotnet_naming_style.ipascalcase.capitalization = pascal_case + +dotnet_naming_style.tpascalcase.required_prefix = T +dotnet_naming_style.tpascalcase.required_suffix = +dotnet_naming_style.tpascalcase.word_separator = +dotnet_naming_style.tpascalcase.capitalization = pascal_case + +dotnet_naming_style._camelcase.required_prefix = _ +dotnet_naming_style._camelcase.required_suffix = +dotnet_naming_style._camelcase.word_separator = +dotnet_naming_style._camelcase.capitalization = camel_case + +dotnet_naming_style.camelcase.required_prefix = +dotnet_naming_style.camelcase.required_suffix = +dotnet_naming_style.camelcase.word_separator = +dotnet_naming_style.camelcase.capitalization = camel_case + +dotnet_naming_style.s_camelcase.required_prefix = s_ +dotnet_naming_style.s_camelcase.required_suffix = +dotnet_naming_style.s_camelcase.word_separator = +dotnet_naming_style.s_camelcase.capitalization = camel_case + diff --git a/.editorconfig.bak b/.editorconfig.bak new file mode 100644 index 0000000..e6dbf64 --- /dev/null +++ b/.editorconfig.bak @@ -0,0 +1,55 @@ +# EditorConfig is awesome: +http://EditorConfig.org +root = true + +[*] +indent_style = space +# (Please don't specify an indent_size here; that has too many unintended consequences.) + +[*.cs,*.csx,*.vb,*.vbx] +trim_trailing_whitespace = true +insert_final_newline = true +max_line_length = 120 +spaces_around_operators = true +curly_bracket_next_line = true +spaces_around_brackets = both +indent_brace_style = Allman +indent_size = 4 + +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 2 + +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +indent_size = 2 + +[*.json] +indent_size = 2 + +[*.{cs, vb}] +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_event = false:suggestion +dotnet_style_predefined_type_for_locals_parameters_members = true:error +dotnet_style_predefined_type_for_member_access = true:error +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion + +[*.cs] +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:suggestion +csharp_style_expression_bodied_methods = true:suggestion +csharp_style_expression_bodied_constructors = true:suggestion +csharp_style_expression_bodied_operators = true:suggestion +csharp_style_expression_bodied_properties = true:suggestion +csharp_style_expression_bodied_indexers = true:suggestion +csharp_style_expression_bodied_accessors = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion diff --git a/Testify.sln b/Testify.sln index ab5e55a..af8f7da 100644 --- a/Testify.sln +++ b/Testify.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2036 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34024.191 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{469F900E-5D25-4CD0-A0CC-A255131F2D8F}" ProjectSection(SolutionItems) = preProject @@ -44,6 +44,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Testify.Moq.Tests", "src\Te EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Testify.Examples", "src\Examples\Testify.Examples\Testify.Examples.csproj", "{D0F601A2-DB9F-4BFE-88FE-8035D5130980}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5F33DA26-5155-4499-A990-5042CB725506}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Testify.Assertions", "src\Testify.Assertions\Testify.Assertions.csproj", "{5D45EAD5-5694-44A9-9BC5-E8D4EC223C72}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{38F9FCA7-EB52-400C-B9B9-8376AAB80C0F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Testify.Assertions.Tests", "src\tests\Testify.Assertions.Tests\Testify.Assertions.Tests.csproj", "{AC504586-CB6A-4355-84D4-D18BD2B76838}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testify.xUnit.Traits", "src\Testify.xUnit.Traits\Testify.xUnit.Traits.csproj", "{E08C2037-1FF1-486D-BA93-956605D7007A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -70,6 +80,18 @@ Global {D0F601A2-DB9F-4BFE-88FE-8035D5130980}.Debug|Any CPU.Build.0 = Debug|Any CPU {D0F601A2-DB9F-4BFE-88FE-8035D5130980}.Release|Any CPU.ActiveCfg = Release|Any CPU {D0F601A2-DB9F-4BFE-88FE-8035D5130980}.Release|Any CPU.Build.0 = Release|Any CPU + {5D45EAD5-5694-44A9-9BC5-E8D4EC223C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D45EAD5-5694-44A9-9BC5-E8D4EC223C72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D45EAD5-5694-44A9-9BC5-E8D4EC223C72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D45EAD5-5694-44A9-9BC5-E8D4EC223C72}.Release|Any CPU.Build.0 = Release|Any CPU + {AC504586-CB6A-4355-84D4-D18BD2B76838}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC504586-CB6A-4355-84D4-D18BD2B76838}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC504586-CB6A-4355-84D4-D18BD2B76838}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AC504586-CB6A-4355-84D4-D18BD2B76838}.Release|Any CPU.Build.0 = Release|Any CPU + {E08C2037-1FF1-486D-BA93-956605D7007A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E08C2037-1FF1-486D-BA93-956605D7007A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E08C2037-1FF1-486D-BA93-956605D7007A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E08C2037-1FF1-486D-BA93-956605D7007A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -78,6 +100,10 @@ Global {0E1E52AC-741D-4A4B-AB6A-BFE5AB44BF86} = {469F900E-5D25-4CD0-A0CC-A255131F2D8F} {64174681-1570-45E3-9965-18433F644EEC} = {469F900E-5D25-4CD0-A0CC-A255131F2D8F} {D0F601A2-DB9F-4BFE-88FE-8035D5130980} = {7F5EBA53-F3CE-42E8-AE96-35588E0EB67B} + {5D45EAD5-5694-44A9-9BC5-E8D4EC223C72} = {5F33DA26-5155-4499-A990-5042CB725506} + {38F9FCA7-EB52-400C-B9B9-8376AAB80C0F} = {5F33DA26-5155-4499-A990-5042CB725506} + {AC504586-CB6A-4355-84D4-D18BD2B76838} = {38F9FCA7-EB52-400C-B9B9-8376AAB80C0F} + {E08C2037-1FF1-486D-BA93-956605D7007A} = {5F33DA26-5155-4499-A990-5042CB725506} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {796564D4-DAEC-4717-ADD8-43C0947B2BBE} diff --git a/src/Directory.packages.props b/src/Directory.packages.props index 132a14f..1fb5d9b 100644 --- a/src/Directory.packages.props +++ b/src/Directory.packages.props @@ -1,13 +1,16 @@ + + - + + \ No newline at end of file diff --git a/src/Examples/Testify.Examples/packages.lock.json b/src/Examples/Testify.Examples/packages.lock.json index 88f0e3d..f743d10 100644 --- a/src/Examples/Testify.Examples/packages.lock.json +++ b/src/Examples/Testify.Examples/packages.lock.json @@ -993,15 +993,6 @@ "xunit.extensibility.execution": "[2.5.1]" } }, - "xunit.extensibility.core": { - "type": "Transitive", - "resolved": "2.5.1", - "contentHash": "XGPiWP7D/KIY/fzdmU9gx7eDt0QD0IAWOy54LI+ckLZCqFMupIFochC3dHRxykuAz+L0nYvz6PxDdR2UcgNmDw==", - "dependencies": { - "NETStandard.Library": "1.6.1", - "xunit.abstractions": "2.0.3" - } - }, "xunit.extensibility.execution": { "type": "Transitive", "resolved": "2.5.1", @@ -1022,6 +1013,16 @@ "requested": "[0.8.0, )", "resolved": "1.3.0", "contentHash": "gSk+8RC6UZ6Fzx1OHoB2bPyENeg3WHIeJhB/hb4oZNN0pW0dwOuplJay6OnqFIvW8T37re/RB4PWpEvayWIO1Q==" + }, + "xunit.extensibility.core": { + "type": "CentralTransitive", + "requested": "[2.5.1, )", + "resolved": "2.5.1", + "contentHash": "XGPiWP7D/KIY/fzdmU9gx7eDt0QD0IAWOy54LI+ckLZCqFMupIFochC3dHRxykuAz+L0nYvz6PxDdR2UcgNmDw==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.abstractions": "2.0.3" + } } } } diff --git a/src/Testify.Assertions/ActualValue.cs b/src/Testify.Assertions/ActualValue.cs new file mode 100644 index 0000000..88afa40 --- /dev/null +++ b/src/Testify.Assertions/ActualValue.cs @@ -0,0 +1,26 @@ +namespace Testify; + +using System; + +/// +/// Represents a record that holds actual value for an assertion and the +/// expression for it. +/// +/// The type of the actual value. +public record ActualValue(T? Value, string Expression) : IFormattable +{ + /// + public override string ToString() + { + return ToString(null, null); + } + + /// + public string ToString(string? format, IFormatProvider? formatProvider) + => format switch + { + "e" => FormatExpression(Expression), + "v" => Format(Value), + _ => Format(Value, Expression) + }; +} diff --git a/src/Testify.Assertions/Assertion.cs b/src/Testify.Assertions/Assertion.cs new file mode 100644 index 0000000..73b555e --- /dev/null +++ b/src/Testify.Assertions/Assertion.cs @@ -0,0 +1,120 @@ +namespace Testify; + +using System.Text.RegularExpressions; + +using Testify.Internal; + +/// +/// Provides methods used to start an assertion or for use within an assertion +/// implementation. +/// +public static partial class Assertion +{ + [GeneratedRegex("{because}", RegexOptions.Compiled)] + private static partial Regex BecauseHole(); + + /// + /// Begins a fluent assertion by providing the actual value being asserted + /// on. + /// + /// The type of the actual value. + /// The actual value. + /// The expression used when providing the actual + /// value. + /// An instance representing the + /// actual value being asserted on. + public static ActualValue Assert( + T? value, + [Expression("value")] string? expression = null) + => new(value, Guard.Against.Null(expression)); + + /// + /// Begins a fluent assertion by providing an as the + /// value being asserted on. + /// + /// The for the actual value. + /// + /// The expression used when providing the action. + /// + /// An instance representing the + /// actual value being asserted on. + public static ActualValue Assert( + Action action, + [Expression("action")] string? expression = null) + => Assert(action, expression); + + /// + /// Makes a "compound assertion" that fails with the specified message if any + /// wrapped assertions fail. + /// + /// The assertion failure message to report if any + /// wrapped assertions fail. + /// The to invoke which makes + /// assertions to be wrapped in the "compound assertions". + /// + /// This is a very low level assertion generally used in the implementation + /// of other "compound assertions" and not made directly within tests. The + /// behavior of assertions are temporarily changed within the scope of the + /// invoked to combine assertion failures, + /// rather than to immediately throw them. This allows multiple assertions + /// to be combined into a single assertion with a meaningful failure + /// message. Note that only assertion methods within Testify will be + /// combined this way, and any other exceptions thrown within the + /// will cause an immediate test failure. + /// + public static void Assert(string message, Action assertions) + { + AssertionScope.Push(message); + try + { + assertions.Invoke(); + } + catch + { + AssertionScope.Pop(false); + throw; + } + + AssertionScope.Pop(); + } + + /// + /// Asserts that the value should satisfy all of + /// the assertions made when invoking . + /// + /// The type of the actual value being asserted on. + /// + /// The actual value being asserted on. + /// An that makes multiple + /// assertions on the value. + public static void ShouldSatisfy(this ActualValue actual, Action> assertions) + => Assert("One or more assertions were not satisfied.", () => assertions.Invoke(actual)); + + /// + /// Generates a test platform specific failure exception. If the test + /// platform cannot be determined then raises the non-platform specific + /// . + /// + /// The assertion message, including the "{because}" + /// hole used to format the user specified reason for the failure. + /// + /// The user specified reason for the failure. + /// + public static void Fail(string message, string? because = null) + { + Guard.Against.NullOrWhiteSpace(message); + + if (!string.IsNullOrWhiteSpace(because)) + { + because = because.Trim(); + if (!because.StartsWith("because")) + { + because = $"because {because}"; + } + + message = BecauseHole().Replace(message, " " + because); + } + + AssertionScope.Fail(message); + } +} diff --git a/src/Testify.Assertions/AssertionException.cs b/src/Testify.Assertions/AssertionException.cs new file mode 100644 index 0000000..be9c3cd --- /dev/null +++ b/src/Testify.Assertions/AssertionException.cs @@ -0,0 +1,62 @@ +namespace Testify; + +using System; +using System.Runtime.Serialization; + +/// +/// Represents assertion failures that occur during test execution. +/// +/// +/// This is the exception type thrown by assertions in the Testify +/// framework when no unit test framework can be detected. +/// +[Serializable] +public class AssertionException : Exception +{ + /// + /// Initializes a new instance of the + /// class. + /// + public AssertionException() { } + + /// + /// Initializes a new instance of the class + /// with a specified failure message. + /// + /// The message that describes the reason for an + /// assertion failure. + public AssertionException(string message) : base(message) { } + + /// + /// Initializes a new instance of the class + /// with a specified failure message and a reference to the inner exception + /// that is the cause of this exception. + /// + /// The message that describes the reason for an + /// assertion failure. + /// The exception that is the cause of the current + /// exception, or a reference if no inner + /// exception is specified. + public AssertionException(string message, Exception inner) : base(message, inner) { } + + /// + /// Initializes a new instance of the class + /// with serialized data. + /// + /// The + /// that + /// holds the serialized object data about the exception being thrown. + /// + /// The + /// that + /// contains contextual information about the source or destination. + /// + /// is + /// . + /// The class name is + /// or is zero + /// (0). + protected AssertionException( + SerializationInfo info, + StreamingContext context) : base(info, context) { } +} \ No newline at end of file diff --git a/src/Testify.Assertions/BooleanAssertions.cs b/src/Testify.Assertions/BooleanAssertions.cs new file mode 100644 index 0000000..7157ab0 --- /dev/null +++ b/src/Testify.Assertions/BooleanAssertions.cs @@ -0,0 +1,43 @@ +namespace Testify; + +/// +/// Provides fluent assertions for values. +/// +public static class BooleanAssertions +{ + /// + /// Asserts that the value should be + /// . + /// + /// The instance that + /// represents the actual value being asserted on. + /// The user supplied "because phrase" describing why + /// the assertion is being made. + public static void ShouldBeTrue(this ActualValue actual, string? because = null) + { + Guard.Against.Null(actual); + + if (!actual.Value) + { + Fail($"Expected {actual:e} to be true{{because}}, but found false.", because); + } + } + + /// + /// Asserts that the value should be + /// . + /// + /// The instance that + /// represents the actual value being asserted on. + /// The user supplied "because phrase" describing why + /// the assertion is being made. + public static void ShouldBeFalse(this ActualValue actual, string? because = null) + { + Guard.Against.Null(actual); + + if (actual.Value) + { + Fail($"Expected {actual:e} to be false{{because}}, but found true.", because); + } + } +} diff --git a/src/Testify.Assertions/ExceptionAssertions.cs b/src/Testify.Assertions/ExceptionAssertions.cs new file mode 100644 index 0000000..d4d533a --- /dev/null +++ b/src/Testify.Assertions/ExceptionAssertions.cs @@ -0,0 +1,174 @@ +namespace Testify; +using System; + +/// +/// Provides fluent assertions for exceptions. +/// +public static class ExceptionAssertions +{ + /// + /// Asserts that the action, when invoked, should throw an . + /// + /// The instance that + /// represents the actual value being asserted on. + /// The user supplied "because phrase" describing why + /// the assertion is being made. + /// An instance which + /// can be used to make additional assertions about the exception + /// thrown. + public static IAdditionalThrowAssertions ShouldThrow(this ActualValue actual, string? because = null) + => ShouldThrow(actual, because); + + /// + /// Asserts that the action, when called, should throw the specified + /// exception type. + /// + /// The exception type expected to be thrown. + /// + /// The instance that + /// represents the actual value being asserted on. + /// The user supplied "because phrase" describing why + /// the assertion is being made. + /// An instance which + /// can be used to make additional assertions about the exception + /// thrown. + public static IAdditionalThrowAssertions ShouldThrow(this ActualValue actual, string? because = null) + where T : Exception + { + Guard.Against.Null(actual); + Guard.Against.Null(actual.Value); + + try + { + actual.Value.Invoke(); + } + catch (T e) + { + return new AdditionalThrowAssertions(e); + } + catch (Exception e) + { + Fail( + $"Expected {actual:e} to throw an exception of type {Format(typeof(T))}{{because}}, but it threw an exception of type {Format(e.GetType())} instead.", + because); + return new AdditionalThrowAssertions(); + } + + Fail( + $"Expected {actual:e} to throw an exception of type {Format(typeof(T))}{{because}}, but it did not throw.", + because); + return new AdditionalThrowAssertions(); + } + + /// + /// Asserts that the action, when invoked, should not throw any exceptions. + /// + /// The instance that + /// represents the actual value being asserted on. + /// The user supplied "because phrase" describing why + /// the assertion is being made. + /// + /// This assertion isn't strictly needed as code that throws will fail a + /// test. However, using + /// does a better + /// job describing the intent of the test code, as well as provides a better + /// test failure message. + /// + public static void ShouldNotThrow(this ActualValue actual, string? because) + { + Guard.Against.Null(actual); + Guard.Against.Null(actual.Value); + + try + { + actual.Value.Invoke(); + } + catch (Exception e) + { + Ignore(e); + Fail($"Expected {actual:e} to not throw an exception{{because}}, but it did.", because); + } + + static void Ignore(Exception _) { } + } + + /// + /// Asserts the , when invoked, should not throw the + /// specified exception type. + /// + /// The exception type not expected to be thrown. + /// + /// The instance that + /// represents the actual value being asserted on. + /// The user supplied "because phrase" describing why + /// the assertion is being made. + /// + /// This assertion isn't strictly needed as code that throws will fail a + /// test. However, using + /// does a better + /// job describing the intent of the test code, as well as provides a better + /// test failure message. + /// + public static void ShouldNotThrow(this ActualValue actual, string? because) + where T : Exception + { + Guard.Against.Null(actual); + Guard.Against.Null(actual.Value); + + try + { + actual.Value.Invoke(); + } + catch (T e) + { + Ignore(e); + Fail($"Expected {actual:e} to not throw an exception of type {Format(typeof(T))}{{because}}, but it did.", because); + } + + static void Ignore(Exception _) { } + } + + /// + /// Result from throw assertions that provides fluent method for making + /// additional assertions about the exception thrown. + /// + /// The exception type. + public interface IAdditionalThrowAssertions + where T : Exception + { + /// + /// Called to provide additional assertions about the exception that was + /// thrown. + /// + /// The action called to make additional assertions + /// about the exception that was thrown. + void AndShouldSatisfy(Action> action); + } + + private class AdditionalThrowAssertions : IAdditionalThrowAssertions + where T : Exception + { + private readonly bool _shouldInvoke; + private readonly T? _value; + + public AdditionalThrowAssertions() + { + _shouldInvoke = false; + } + + public AdditionalThrowAssertions(T value) + { + Guard.Against.Null(value); + _value = value; + _shouldInvoke = true; + } + + public void AndShouldSatisfy(Action> action) + { + if (_shouldInvoke) + { + Assert(_value, "exception").ShouldSatisfy(action); + } + } + } +} diff --git a/src/Testify.Assertions/Formatting/DateTimeValueFormatter.cs b/src/Testify.Assertions/Formatting/DateTimeValueFormatter.cs new file mode 100644 index 0000000..6bc3afb --- /dev/null +++ b/src/Testify.Assertions/Formatting/DateTimeValueFormatter.cs @@ -0,0 +1,51 @@ +using System; + +namespace Testify.Formatting; + +internal class DateTimeValueFormatter : IValueFormatter +{ + private const string DateFormat = "YYYY-MM-dd"; + private const string TimeFormat = "HH:mm:ss"; + private const string TimeSpanFormat = @"hh\:mm\:ss"; + + public bool CanFormat(object? value) + => value is DateTime or DateTimeOffset or DateOnly or TimeOnly or TimeSpan; + + public string Format(object? value) => $"<{FormatValue(value)}>"; + + private static string FormatValue(object? value) + => value switch + { + TimeSpan timeSpan => timeSpan.ToString(TimeSpanFormat), + DateOnly dateOnly => dateOnly.ToString(DateFormat), + TimeOnly timeOnly => timeOnly.ToString(TimeFormat), + _ => FormatDateTimeOffset(ToDateTimeOffset(value)) + }; + + private static DateTimeOffset ToDateTimeOffset(object? value) + => value switch + { + DateTimeOffset dateTimeOffset => dateTimeOffset, + DateTime dateTime => new(dateTime), + _ => throw new InvalidOperationException("This should never happen.") + }; + + private static string FormatDateTimeOffset(DateTimeOffset dateTimeOffset) + { + var dateTime = dateTimeOffset.DateTime; + var dateOnly = DateOnly.FromDateTime(dateTime); + var timeOnly = TimeOnly.FromDateTime(dateTime); + if (dateOnly == default) + { + return timeOnly.ToString(TimeFormat); + } + else if (timeOnly == default) + { + return dateOnly.ToString(DateFormat); + } + else + { + return dateTimeOffset.ToString("s"); + } + } +} diff --git a/src/Testify.Assertions/Formatting/DefaultValueFormatter.cs b/src/Testify.Assertions/Formatting/DefaultValueFormatter.cs new file mode 100644 index 0000000..35b93a0 --- /dev/null +++ b/src/Testify.Assertions/Formatting/DefaultValueFormatter.cs @@ -0,0 +1,8 @@ +namespace Testify.Formatting; + +internal class DefaultValueFormatter : IValueFormatter +{ + public bool CanFormat(object? value) => true; + + public string Format(object? value) => Guard.Against.Null(value).ToString()!; +} diff --git a/src/Testify.Assertions/Formatting/Formatter.cs b/src/Testify.Assertions/Formatting/Formatter.cs new file mode 100644 index 0000000..cc9164b --- /dev/null +++ b/src/Testify.Assertions/Formatting/Formatter.cs @@ -0,0 +1,72 @@ +namespace Testify.Formatting; + +/// +/// Provides methods to help with formatting of assertion failure messages. +/// +public static class Formatter +{ + private static readonly IValueFormatter NullFormatter = new NullValueFormatter(); + private static readonly IValueFormatter DefaultFormatter = new DefaultValueFormatter(); + + internal static readonly List Formatters = new(); + + static Formatter() + { + Formatters.Add(new GuidValueFormatter()); + Formatters.Add(new StringValueFormatter()); + Formatters.Add(new DateTimeValueFormatter()); + } + + /// + /// Formats the specified value in a manner appropriate for assertion + /// failure messages. + /// + /// The value to format. + /// The caller expression provided for the value. + /// + /// A formatted representation of the and + /// . + /// + /// Several types and values are formatted to provide better assertion + /// messages. You can extend special formatting to other types (TODO). + /// + public static string Format(object? value, string? expression = null) + { + var formatter = FindFormatter(value); + var formattedValue = formatter.Format(value); + + if (!string.IsNullOrWhiteSpace(expression)) + { + formattedValue = $"{FormatExpression(expression)} ({formattedValue})"; + } + + return formattedValue; + } + + /// + /// Formats the specified caller expression. + /// + /// The caller expression. + /// The formatted caller expression. + public static string FormatExpression(string expression) + => $"«{expression}»"; + + private static IValueFormatter FindFormatter(object? value) + { + if (value == null) + { + return NullFormatter; + } + + for (var i = Formatters.Count - 1; i >= 0; i--) + { + var formatter = Formatters[i]; + if (formatter.CanFormat(value)) + { + return formatter; + } + } + + return DefaultFormatter; + } +} diff --git a/src/Testify.Assertions/Formatting/GuidValueFormatter.cs b/src/Testify.Assertions/Formatting/GuidValueFormatter.cs new file mode 100644 index 0000000..ba53719 --- /dev/null +++ b/src/Testify.Assertions/Formatting/GuidValueFormatter.cs @@ -0,0 +1,6 @@ +namespace Testify.Formatting; + +internal class GuidValueFormatter : ValueFormatter +{ + public override string Format(Guid value) => $"<{value}>"; +} diff --git a/src/Testify.Assertions/Formatting/IValueFormatter.cs b/src/Testify.Assertions/Formatting/IValueFormatter.cs new file mode 100644 index 0000000..56d525e --- /dev/null +++ b/src/Testify.Assertions/Formatting/IValueFormatter.cs @@ -0,0 +1,25 @@ +namespace Testify.Formatting; + +/// +/// Provides a mechanism for controlling the formatting of values in assertion +/// failure messages. +/// +public interface IValueFormatter +{ + /// + /// Determines whether this instance can format the specified + /// . + /// + /// The value to be formatted. + /// true if this instance can format the specified value; + /// otherwise, false. + bool CanFormat(object? value); + + /// + /// Formats the specified . + /// + /// The value to be formatted. + /// The formatted string representation for the + /// . + string Format(object? value); +} diff --git a/src/Testify.Assertions/Formatting/NullValueFormatter.cs b/src/Testify.Assertions/Formatting/NullValueFormatter.cs new file mode 100644 index 0000000..8dd6f63 --- /dev/null +++ b/src/Testify.Assertions/Formatting/NullValueFormatter.cs @@ -0,0 +1,10 @@ +namespace Testify.Formatting; + +internal class NullValueFormatter : IValueFormatter +{ + private static readonly string FormattedNullValue = ""; + + public bool CanFormat(object? value) => value is null; + + public string Format(object? value) => FormattedNullValue; +} diff --git a/src/Testify.Assertions/Formatting/StringValueFormatter.cs b/src/Testify.Assertions/Formatting/StringValueFormatter.cs new file mode 100644 index 0000000..486d174 --- /dev/null +++ b/src/Testify.Assertions/Formatting/StringValueFormatter.cs @@ -0,0 +1,6 @@ +namespace Testify.Formatting; + +internal class StringValueFormatter : ValueFormatter +{ + public override string Format(string value) => $"\"{value}\""; +} diff --git a/src/Testify.Assertions/Formatting/ValueFormatter.cs b/src/Testify.Assertions/Formatting/ValueFormatter.cs new file mode 100644 index 0000000..d958f21 --- /dev/null +++ b/src/Testify.Assertions/Formatting/ValueFormatter.cs @@ -0,0 +1,23 @@ +namespace Testify.Formatting; + +/// +/// Base class for types that can format the specified type. +/// +/// The type to format. +/// +public abstract class ValueFormatter : IValueFormatter +{ + /// + public virtual bool CanFormat(object? value) => value is T; + + /// + /// Formats the specified . + /// + /// The value to be formatted. + /// The formatted string representation for the + /// . + public abstract string Format(T value); + + /// + string IValueFormatter.Format(object? value) => Format((T)value!); +} diff --git a/src/Testify.Assertions/GlobalUsings.cs b/src/Testify.Assertions/GlobalUsings.cs new file mode 100644 index 0000000..0b01c90 --- /dev/null +++ b/src/Testify.Assertions/GlobalUsings.cs @@ -0,0 +1,4 @@ +global using static Testify.Formatting.Formatter; +global using static Testify.Assertion; + +global using Expression = System.Runtime.CompilerServices.CallerArgumentExpressionAttribute; \ No newline at end of file diff --git a/src/Testify.Assertions/Guard.cs b/src/Testify.Assertions/Guard.cs new file mode 100644 index 0000000..8d75b2b --- /dev/null +++ b/src/Testify.Assertions/Guard.cs @@ -0,0 +1,34 @@ +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +using Microsoft; + +namespace Testify; + +#pragma warning disable CA1822 + +internal sealed class Guard +{ + private Guard() { } + + public static Guard Against { get; } = new(); + + public T Null( + [NotNull][ValidatedNotNull] T? input, + [CallerArgumentExpression(nameof(input))] string? parameterName = null) + => input ?? throw new ArgumentNullException(parameterName); + + public string NullOrEmpty( + [NotNull][ValidatedNotNull] string? input, + [CallerArgumentExpression(nameof(input))] string? parameterName = null) + => string.IsNullOrEmpty(Null(input, parameterName)) + ? throw new ArgumentException("Value cannot be an empty string.", parameterName) + : input; + + public string NullOrWhiteSpace( + [NotNull][ValidatedNotNull] string? input, + [CallerArgumentExpression(nameof(input))] string? parameterName = null) + => string.IsNullOrWhiteSpace(Null(input, parameterName)) + ? throw new ArgumentException("Value cannot be an empty string or contain only white space.", parameterName) + : input; +} diff --git a/src/Testify.Assertions/IAdditionalThrowExceptions.cs b/src/Testify.Assertions/IAdditionalThrowExceptions.cs new file mode 100644 index 0000000..4ba60b7 --- /dev/null +++ b/src/Testify.Assertions/IAdditionalThrowExceptions.cs @@ -0,0 +1,5 @@ +namespace Testify; + +internal interface IAdditionalThrowExceptions +{ +} \ No newline at end of file diff --git a/src/Testify.Assertions/Internal/AssertionScope.cs b/src/Testify.Assertions/Internal/AssertionScope.cs new file mode 100644 index 0000000..dbc9fd1 --- /dev/null +++ b/src/Testify.Assertions/Internal/AssertionScope.cs @@ -0,0 +1,65 @@ +namespace Testify.Internal; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +internal sealed class AssertionScope +{ + private static readonly AsyncLocal Current = new(); + private static readonly AssertionScope Root = new(); + + private readonly AssertionScope? _parent; + private readonly string? _message; + private readonly List _failureMessages = new(); + + private AssertionScope() + : this(null, null) + { + } + + private AssertionScope(AssertionScope? parent, string? message) + { + _parent = parent; + _message = message; + } + + public static void Fail(string message, AssertionScope? scope = null) + { + scope ??= Current.Value ?? Root; + if (scope._parent == null) + { + throw FrameworkAdapter.CreateException(message); + } + else + { + scope._failureMessages.Add(message); + } + } + + public static void Push(string message) + { + Current.Value = new(Current.Value ?? Root, message); + } + + public static void Pop(bool shouldThrow = true) + { + var scope = Current.Value ?? Root; + if (scope == Root) + { + throw new InvalidOperationException("Assertion scope stack is empty."); + } + + var (parent, message) = (scope._parent!, scope._message!); + if (shouldThrow && scope._failureMessages.Any()) + { + var lines = scope._failureMessages.SelectMany(f => f.Split(Environment.NewLine)); + var childFailures = string.Join(Environment.NewLine, lines.Select(line => $" {line}")); + Fail($"{scope._message}{Environment.NewLine}{childFailures}", parent); + } + + Current.Value = parent; + } +} diff --git a/src/Testify.Assertions/Internal/FallbackFrameworkAdapter.cs b/src/Testify.Assertions/Internal/FallbackFrameworkAdapter.cs new file mode 100644 index 0000000..fd84051 --- /dev/null +++ b/src/Testify.Assertions/Internal/FallbackFrameworkAdapter.cs @@ -0,0 +1,16 @@ +namespace Testify.Internal; + +using System; +using System.Reflection; + +internal class FallbackFrameworkAdapter : FrameworkAdapter +{ + public FallbackFrameworkAdapter() + : base("Tapestry.Assertions", "Tapestry.Testing.AssertFailedException") + { + } + + public override Exception CreateFrameworkException(string message) => new AssertionException(message); + + protected override Assembly? GetAssembly() => typeof(FallbackFrameworkAdapter).Assembly; +} diff --git a/src/Testify.Assertions/Internal/FrameworkAdapter.cs b/src/Testify.Assertions/Internal/FrameworkAdapter.cs new file mode 100644 index 0000000..fb8af7d --- /dev/null +++ b/src/Testify.Assertions/Internal/FrameworkAdapter.cs @@ -0,0 +1,60 @@ +namespace Testify.Internal; + +using System; +using System.Linq; +using System.Reflection; + +internal abstract class FrameworkAdapter +{ + private static readonly Type[] KnownAdapterTypes = new[] + { + typeof(XunitFrameworkAdapter), + typeof(FallbackFrameworkAdapter), + }; + + private static readonly Lazy Adapter = new(ProbeAdapter); + + private readonly Lazy _assembly; + + protected FrameworkAdapter(string assemblyName, string exceptionName) + { + ArgumentNullException.ThrowIfNull(assemblyName); + ArgumentNullException.ThrowIfNull(exceptionName); + + AssemblyName = assemblyName; + ExceptionName = exceptionName; + _assembly = new Lazy(() => GetAssembly()); + } + + public string AssemblyName { get; } + + public string ExceptionName { get; } + + public static Exception CreateException(string message) + { + ArgumentNullException.ThrowIfNull(message); + + return Adapter.Value.CreateFrameworkException(message); + } + + public virtual Exception CreateFrameworkException(string message) + { + ArgumentNullException.ThrowIfNull(message); + + Exception? result = null; + var exceptionType = _assembly.Value?.GetType(ExceptionName); + if (exceptionType != null) + { + result = (Exception?)Activator.CreateInstance(exceptionType, message); + } + + return result ?? new AssertionException(message); + } + + protected virtual Assembly? GetAssembly() + => Array.Find(AppDomain.CurrentDomain.GetAssemblies(), a => a.FullName == AssemblyName); + + private static FrameworkAdapter ProbeAdapter() + => KnownAdapterTypes.Select(t => (FrameworkAdapter?)Activator.CreateInstance(t)) + .First(a => a != null)!; +} diff --git a/src/Testify.Assertions/Internal/MstestFrameworkAdapter.cs b/src/Testify.Assertions/Internal/MstestFrameworkAdapter.cs new file mode 100644 index 0000000..3e5c752 --- /dev/null +++ b/src/Testify.Assertions/Internal/MstestFrameworkAdapter.cs @@ -0,0 +1,11 @@ +namespace Testify.Internal; + +internal class MstestFrameworkAdapter : FrameworkAdapter +{ + public MstestFrameworkAdapter() + : base( + "Microsoft.VisualStudio.TestPlatform.TestFramework", + "Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException") + { + } +} diff --git a/src/Testify.Assertions/Internal/NunitFrameworkAdapter.cs b/src/Testify.Assertions/Internal/NunitFrameworkAdapter.cs new file mode 100644 index 0000000..3323760 --- /dev/null +++ b/src/Testify.Assertions/Internal/NunitFrameworkAdapter.cs @@ -0,0 +1,9 @@ +namespace Testify.Internal; + +internal class NunitFrameworkAdapter : FrameworkAdapter +{ + public NunitFrameworkAdapter() + : base("nunit.framework", "NUnit.Framework.AssertionException") + { + } +} diff --git a/src/Testify.Assertions/Internal/XunitFrameworkAdapter.cs b/src/Testify.Assertions/Internal/XunitFrameworkAdapter.cs new file mode 100644 index 0000000..c60d883 --- /dev/null +++ b/src/Testify.Assertions/Internal/XunitFrameworkAdapter.cs @@ -0,0 +1,23 @@ +namespace Testify.Internal; + +using System.Reflection; + +internal class XunitFrameworkAdapter : FrameworkAdapter +{ + public XunitFrameworkAdapter() + : base("xunit.assert", "Xunit.Sdk.XunitException") + { + } + + protected override Assembly? GetAssembly() + { + try + { + return Assembly.Load(new AssemblyName(AssemblyName)); + } + catch + { + return null; + } + } +} diff --git a/src/Testify.Assertions/Testify.Assertions.csproj b/src/Testify.Assertions/Testify.Assertions.csproj new file mode 100644 index 0000000..c2b5f0e --- /dev/null +++ b/src/Testify.Assertions/Testify.Assertions.csproj @@ -0,0 +1,16 @@ + + + + net7.0 + enable + enable + Testify + True + True + + + + + + + diff --git a/src/Testify.Assertions/packages.lock.json b/src/Testify.Assertions/packages.lock.json new file mode 100644 index 0000000..b8ba206 --- /dev/null +++ b/src/Testify.Assertions/packages.lock.json @@ -0,0 +1,13 @@ +{ + "version": 2, + "dependencies": { + "net7.0": { + "Microsoft.VisualStudio.Validation": { + "type": "Direct", + "requested": "[17.6.11, )", + "resolved": "17.6.11", + "contentHash": "J+9L/iac6c8cwcgVSCMuoIYOlD1Jw4mbZ8XMe1IZVj8p8+3dJ46LnnkIkTRMjK7xs9UtU9MoUp1JGhWoN6fAEw==" + } + } + } +} \ No newline at end of file diff --git a/src/Testify.xUnit.Traits/AcceptanceTestAttribute.cs b/src/Testify.xUnit.Traits/AcceptanceTestAttribute.cs new file mode 100644 index 0000000..d12d63f --- /dev/null +++ b/src/Testify.xUnit.Traits/AcceptanceTestAttribute.cs @@ -0,0 +1,8 @@ +namespace Testify; + +using System; + +[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] +public class AcceptanceTestAttribute : CategoryAttribute +{ +} diff --git a/src/Testify.xUnit.Traits/BugAttribute.cs b/src/Testify.xUnit.Traits/BugAttribute.cs new file mode 100644 index 0000000..00a821a --- /dev/null +++ b/src/Testify.xUnit.Traits/BugAttribute.cs @@ -0,0 +1,13 @@ +namespace Testify; + +using System; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] +public class BugAttribute : WorkItemAttribute +{ + public BugAttribute() { } + + public BugAttribute(string id) : base(id) { } + + public BugAttribute(long id) : base(id) { } +} diff --git a/src/Testify.xUnit.Traits/CategoryAttribute.cs b/src/Testify.xUnit.Traits/CategoryAttribute.cs new file mode 100644 index 0000000..ce20a15 --- /dev/null +++ b/src/Testify.xUnit.Traits/CategoryAttribute.cs @@ -0,0 +1,37 @@ +namespace Testify; + +using System; +using System.Collections.Generic; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] +public class CategoryAttribute : TraitProviderAttribute +{ + private const string Category = "Category"; + private const string AttributeSuffix = "Attribute"; + + protected CategoryAttribute() + { + var name = this.GetType().Name; + if (name.EndsWith(AttributeSuffix)) + { + name = name[..^AttributeSuffix.Length]; + } + + Name = name; + } + + public CategoryAttribute(string name) + { + Name = name; + } + + public string Name { get; set; } + + public override IEnumerable> GetTraits() + { + yield return Trait(Category, Name); + } + + protected static KeyValuePair Trait(string key, string value) + => new(key, value); +} diff --git a/src/Testify.xUnit.Traits/EpicAttribute.cs b/src/Testify.xUnit.Traits/EpicAttribute.cs new file mode 100644 index 0000000..c218852 --- /dev/null +++ b/src/Testify.xUnit.Traits/EpicAttribute.cs @@ -0,0 +1,13 @@ +namespace Testify; + +using System; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] +public class EpicAttribute : WorkItemAttribute +{ + public EpicAttribute() { } + + public EpicAttribute(string id) : base(id) { } + + public EpicAttribute(long id) : base(id) { } +} diff --git a/src/Testify.xUnit.Traits/ExploratoryAttribute.cs b/src/Testify.xUnit.Traits/ExploratoryAttribute.cs new file mode 100644 index 0000000..36d40a4 --- /dev/null +++ b/src/Testify.xUnit.Traits/ExploratoryAttribute.cs @@ -0,0 +1,8 @@ +namespace Testify; + +using System; + +[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] +public class ExploratoryAttribute : CategoryAttribute +{ +} diff --git a/src/Testify.xUnit.Traits/FeatureAttribute.cs b/src/Testify.xUnit.Traits/FeatureAttribute.cs new file mode 100644 index 0000000..ca2e799 --- /dev/null +++ b/src/Testify.xUnit.Traits/FeatureAttribute.cs @@ -0,0 +1,13 @@ +namespace Testify; + +using System; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] +public class FeatureAttribute : WorkItemAttribute +{ + public FeatureAttribute() { } + + public FeatureAttribute(string id) : base(id) { } + + public FeatureAttribute(long id) : base(id) { } +} diff --git a/src/Testify.xUnit.Traits/ITraitProviderAttribute.cs b/src/Testify.xUnit.Traits/ITraitProviderAttribute.cs new file mode 100644 index 0000000..cc531fe --- /dev/null +++ b/src/Testify.xUnit.Traits/ITraitProviderAttribute.cs @@ -0,0 +1,10 @@ +namespace Testify; + +using System.Collections.Generic; + +using Xunit.Sdk; + +public interface ITraitProviderAttribute : ITraitAttribute +{ + IEnumerable> GetTraits(); +} diff --git a/src/Testify.xUnit.Traits/IntegrationTestAttribute.cs b/src/Testify.xUnit.Traits/IntegrationTestAttribute.cs new file mode 100644 index 0000000..92b7bc3 --- /dev/null +++ b/src/Testify.xUnit.Traits/IntegrationTestAttribute.cs @@ -0,0 +1,8 @@ +namespace Testify; + +using System; + +[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] +public class IntegrationTestAttribute : CategoryAttribute +{ +} diff --git a/src/Testify.xUnit.Traits/IssueAttribute.cs b/src/Testify.xUnit.Traits/IssueAttribute.cs new file mode 100644 index 0000000..a42759c --- /dev/null +++ b/src/Testify.xUnit.Traits/IssueAttribute.cs @@ -0,0 +1,16 @@ +namespace Testify; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] +public class IssueAttribute : WorkItemAttribute +{ + public IssueAttribute() { } + + public IssueAttribute(string id) : base(id) { } + + public IssueAttribute(long id) : base(id) { } +} diff --git a/src/Testify.xUnit.Traits/SlowAttribute.cs b/src/Testify.xUnit.Traits/SlowAttribute.cs new file mode 100644 index 0000000..ce815d5 --- /dev/null +++ b/src/Testify.xUnit.Traits/SlowAttribute.cs @@ -0,0 +1,8 @@ +namespace Testify; + +using System; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] +public class SlowAttribute : CategoryAttribute +{ +} diff --git a/src/Testify.xUnit.Traits/SmokeTestAttribute.cs b/src/Testify.xUnit.Traits/SmokeTestAttribute.cs new file mode 100644 index 0000000..42e4e6f --- /dev/null +++ b/src/Testify.xUnit.Traits/SmokeTestAttribute.cs @@ -0,0 +1,8 @@ +namespace Testify; + +using System; + +[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] +public class SmokeTestAttribute : CategoryAttribute +{ +} diff --git a/src/Testify.xUnit.Traits/TaskAttribute.cs b/src/Testify.xUnit.Traits/TaskAttribute.cs new file mode 100644 index 0000000..f683e9e --- /dev/null +++ b/src/Testify.xUnit.Traits/TaskAttribute.cs @@ -0,0 +1,13 @@ +namespace Testify; + +using System; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] +public class TaskAttribute : WorkItemAttribute +{ + public TaskAttribute() { } + + public TaskAttribute(string id) : base(id) { } + + public TaskAttribute(long id) : base(id) { } +} diff --git a/src/Testify.xUnit.Traits/Testify - Backup.xUnit.Traits.csproj b/src/Testify.xUnit.Traits/Testify - Backup.xUnit.Traits.csproj new file mode 100644 index 0000000..7e08a6c --- /dev/null +++ b/src/Testify.xUnit.Traits/Testify - Backup.xUnit.Traits.csproj @@ -0,0 +1,13 @@ + + + + net7.0 + enable + enable + + + + + + + diff --git a/src/Testify.xUnit.Traits/Testify.xUnit.Traits.csproj b/src/Testify.xUnit.Traits/Testify.xUnit.Traits.csproj new file mode 100644 index 0000000..48e9119 --- /dev/null +++ b/src/Testify.xUnit.Traits/Testify.xUnit.Traits.csproj @@ -0,0 +1,14 @@ + + + + net6.0 + enable + enable + Testify + + + + + + + diff --git a/src/Testify.xUnit.Traits/TraitProviderAttribute.cs b/src/Testify.xUnit.Traits/TraitProviderAttribute.cs new file mode 100644 index 0000000..fb4cc17 --- /dev/null +++ b/src/Testify.xUnit.Traits/TraitProviderAttribute.cs @@ -0,0 +1,13 @@ +namespace Testify; + +using System; +using System.Collections.Generic; + +using Xunit.Sdk; + +[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] +[TraitDiscoverer(TraitProviderDiscoverer.TypeName, TraitProviderDiscoverer.AssemblyName)] +public abstract class TraitProviderAttribute : Attribute, ITraitProviderAttribute +{ + public abstract IEnumerable> GetTraits(); +} diff --git a/src/Testify.xUnit.Traits/TraitProviderDiscoverer.cs b/src/Testify.xUnit.Traits/TraitProviderDiscoverer.cs new file mode 100644 index 0000000..80e2954 --- /dev/null +++ b/src/Testify.xUnit.Traits/TraitProviderDiscoverer.cs @@ -0,0 +1,19 @@ +namespace Testify; + +using System.Collections.Generic; + +using Xunit.Abstractions; +using Xunit.Sdk; + +public class TraitProviderDiscoverer : ITraitDiscoverer +{ + public const string TypeName = "Testify.TraitProviderDiscoverer"; + public const string AssemblyName = "Testify.xUnit.Traits"; + + public IEnumerable> GetTraits(IAttributeInfo traitAttribute) + { + var attributeInfo = traitAttribute as IReflectionAttributeInfo; + var traitProviderAttribute = attributeInfo?.Attribute as ITraitProviderAttribute; + return traitProviderAttribute?.GetTraits() ?? Enumerable.Empty>(); + } +} diff --git a/src/Testify.xUnit.Traits/UnitTestAttribute.cs b/src/Testify.xUnit.Traits/UnitTestAttribute.cs new file mode 100644 index 0000000..ae2d71c --- /dev/null +++ b/src/Testify.xUnit.Traits/UnitTestAttribute.cs @@ -0,0 +1,6 @@ +namespace Testify; + +[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] +public class UnitTestAttribute : CategoryAttribute +{ +} diff --git a/src/Testify.xUnit.Traits/UserStoryAttribute.cs b/src/Testify.xUnit.Traits/UserStoryAttribute.cs new file mode 100644 index 0000000..a72efa9 --- /dev/null +++ b/src/Testify.xUnit.Traits/UserStoryAttribute.cs @@ -0,0 +1,13 @@ +namespace Testify; + +using System; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] +public class UserStoryAttribute : WorkItemAttribute +{ + public UserStoryAttribute() { } + + public UserStoryAttribute(string id) : base(id) { } + + public UserStoryAttribute(long id) : base(id) { } +} diff --git a/src/Testify.xUnit.Traits/WorkItemAttribute.cs b/src/Testify.xUnit.Traits/WorkItemAttribute.cs new file mode 100644 index 0000000..8b6b530 --- /dev/null +++ b/src/Testify.xUnit.Traits/WorkItemAttribute.cs @@ -0,0 +1,41 @@ +namespace Testify; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] +public class WorkItemAttribute : CategoryAttribute +{ + public WorkItemAttribute() + : this(string.Empty) + { + } + + public WorkItemAttribute(string id) + { + Id = id; + } + + public WorkItemAttribute(long id) + : this(id.ToString(CultureInfo.InvariantCulture)) + { + } + + public string Id { get; } + + public override IEnumerable> GetTraits() + { + foreach (var trait in base.GetTraits()) + { + yield return trait; + } + + if (!string.IsNullOrEmpty(Id)) + { + yield return Trait(Name, Id); + } + } +} diff --git a/src/Testify.xUnit.Traits/packages.lock.json b/src/Testify.xUnit.Traits/packages.lock.json new file mode 100644 index 0000000..2504059 --- /dev/null +++ b/src/Testify.xUnit.Traits/packages.lock.json @@ -0,0 +1,920 @@ +{ + "version": 2, + "dependencies": { + "net6.0": { + "xunit.extensibility.core": { + "type": "Direct", + "requested": "[2.5.1, )", + "resolved": "2.5.1", + "contentHash": "XGPiWP7D/KIY/fzdmU9gx7eDt0QD0IAWOy54LI+ckLZCqFMupIFochC3dHRxykuAz+L0nYvz6PxDdR2UcgNmDw==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.abstractions": "2.0.3" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "npvJkVKl5rKXrtl1Kkm6OhOUaYGEiF9wFbppFRWSMoApKzt2PiPHT2Bb8a5sAWxprvdOAtvaARS9QYMznEUtug==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "xunit.abstractions": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" + } + } + } +} \ No newline at end of file diff --git a/src/Testify/AssertionException.cs b/src/Testify/AssertionException.cs index 2e04119..0e3c37c 100644 --- a/src/Testify/AssertionException.cs +++ b/src/Testify/AssertionException.cs @@ -62,7 +62,6 @@ public AssertionException(string message, params Exception[] innerExceptions) { } - [SuppressMessage("Rolynator", "RCS1213", Justification = "This is used by DebuggerDisplay.")] private int InnerExceptionCount => InnerExceptions.Count; } } \ No newline at end of file diff --git a/src/Tests/Testify.Assertions.Tests/AssertionsTests.cs b/src/Tests/Testify.Assertions.Tests/AssertionsTests.cs new file mode 100644 index 0000000..8048587 --- /dev/null +++ b/src/Tests/Testify.Assertions.Tests/AssertionsTests.cs @@ -0,0 +1,161 @@ +namespace Testify.Assertions.Tests; + +using Xunit.Sdk; + +public static class AssertionsTests +{ + public class Assert + { + [Fact] + public void SetsTheValue() + { + const int value = 42; + + var result = Assert(value); + + XAssert.Equal(42, result.Value); + } + + [Fact] + public void SetsTheExpression() + { + const int value = 42; + + var result = Assert(value); + + XAssert.Equal("value", result.Expression); + } + } + + public class AssertAction + { + [Fact] + public void SetsTheExpression() + { + const string expectedMessage = "() => 42"; + + var result = Assert(() => 42); + + XAssert.Equal(expectedMessage, result.Expression); + } + } + + public class AssertMessageAction + { + [Fact] + public void ShouldSucceedWithNoFailedAssertions() + { + var action = Act(() => Assert("Compound assertion.", () => { })); + + ShouldSucceed(action); + } + + [Fact] + public void ShouldFailWithCompoundMessage() + { + const string expectedMessage = """ + Compound assertion. + Message 1. + Message 2. + """; + + var action = Act(() => + Assert("Compound assertion.", () => + { + Fail("Message 1."); + Fail("Message 2."); + })); + + ShouldFail(action, expectedMessage); + } + + [Fact] + public void ShouldFailWhenNested() + { + const string expectedMessage = """ + Outer compound assertion. + Inner compound assertion 1. + Message 1. + Message 2. + Inner compound assertion 2. + Message 3. + Message 4. + """; + + var action = Act(() => + Assert("Outer compound assertion.", () => + { + Assert("Inner compound assertion 1.", () => + { + Fail("Message 1."); + Fail("Message 2."); + }); + Assert("Inner compound assertion 2.", () => + { + Fail("Message 3."); + Fail("Message 4."); + }); + })); + + ShouldFail(action, expectedMessage); + } + } + + public class ShouldSatisfy + { + [Fact] + public void ShouldSucceedWhenAssertionsSucceed() + { + const bool value = true; + + var action = Act(() => Assert(value).ShouldSatisfy(it => + { + it.ShouldBeTrue(); + it.ShouldBeTrue(); + })); + + ShouldSucceed(action); + } + + [Fact] + public void ShouldFailWithCompoundAssertion() + { + const bool value = false; + var expectedMessage = $""" + One or more assertions were not satisfied. + Expected {FormatExpression("value")} to be true because reason 1, but found false. + Expected {FormatExpression("value")} to be true because reason 2, but found false. + """; + + var action = Act(() => + Assert(value).ShouldSatisfy(it => + { + it.ShouldBeTrue("reason 1"); + it.ShouldBeTrue("reason 2"); + })); + + ShouldFail(action, expectedMessage); + } + } + + public class Fail + { + [Fact] + public void ThrowsFrameworkException() + { + var action = Act(() => Fail("Failure message.")); + + XAssert.Throws(action); + } + + [Fact] + public void SetsExceptionMessage() + { + const string expectedMessage = "Failure message."; + + var exception = Record.Exception(() => Fail(expectedMessage)); + + XAssert.Equal(expectedMessage, exception.Message); + } + } +} diff --git a/src/Tests/Testify.Assertions.Tests/BooleanAssertionsTests.cs b/src/Tests/Testify.Assertions.Tests/BooleanAssertionsTests.cs new file mode 100644 index 0000000..c3c2c12 --- /dev/null +++ b/src/Tests/Testify.Assertions.Tests/BooleanAssertionsTests.cs @@ -0,0 +1,53 @@ +namespace Testify.Tests; + +public static class BooleanAssertionsTests +{ + public class ShouldBeTrue + { + [Fact] + [Bug(12345)] + public void ShouldSucceedWhenTrue() + { + const bool value = true; + + var action = Act(() => Assert(value).ShouldBeTrue()); + + ShouldSucceed(action); + } + + [Fact] + public void ShouldFailWhenFalse() + { + const bool value = false; + const string because = "I say so"; + + var action = Act(() => Assert(value).ShouldBeTrue(because)); + + ShouldFail(action, $"Expected {FormatExpression("value")} to be true because I say so, but found false."); + } + } + + public class ShouldBeFalse + { + [Fact] + public void ShouldSucceedWhenFalse() + { + const bool value = false; + + var action = Act(() => Assert(value).ShouldBeFalse()); + + ShouldSucceed(action); + } + + [Fact] + public void ShouldFailWhenTrue() + { + const bool value = true; + const string because = "I say so"; + + var action = Act(() => Assert(value).ShouldBeFalse(because)); + + ShouldFail(action, $"Expected {FormatExpression("value")} to be false because I say so, but found true."); + } + } +} diff --git a/src/Tests/Testify.Assertions.Tests/ExceptionAssertionsTests.cs b/src/Tests/Testify.Assertions.Tests/ExceptionAssertionsTests.cs new file mode 100644 index 0000000..9056049 --- /dev/null +++ b/src/Tests/Testify.Assertions.Tests/ExceptionAssertionsTests.cs @@ -0,0 +1,51 @@ +namespace Testify.Assertions.Tests; + +public static class ExceptionAssertionsTests +{ + public class ShouldThrow + { + [Fact] + public void ShouldSucceedWhenActionThrows() + { + var action = Act(() => + Assert(() => throw new InvalidOperationException()) + .ShouldThrow()); + + ShouldSucceed(action); + } + + [Fact] + public void ShouldSucceedWhenActionThrowsDerivedException() + { + var action = Act(() => + Assert(() => throw new ArgumentNullException()) + .ShouldThrow()); + + ShouldSucceed(action); + } + + [Fact] + public void ShouldFailWhenActionDoesNotThrow() + { + var expectedMessage = $"Expected {FormatExpression("() => { }")} to throw an exception of type System.Exception because some reason, but it did not throw."; + + var action = Act(() => + Assert(() => { }) + .ShouldThrow("some reason")); + + ShouldFail(action, expectedMessage); + } + + [Fact] + public void ShouldFailWhenWrongExceptionThrown() + { + var expectedMessage = $"Expected {FormatExpression("() => throw new InvalidOperationException()")} to throw an exception of type System.ArgumentException because some reason, but it threw an exception of type System.InvalidOperationException instead."; + + var action = Act(() => + Assert(() => throw new InvalidOperationException()) + .ShouldThrow("some reason")); + + ShouldFail(action, expectedMessage); + } + } +} diff --git a/src/Tests/Testify.Assertions.Tests/Formatting/FormatterTests.cs b/src/Tests/Testify.Assertions.Tests/Formatting/FormatterTests.cs new file mode 100644 index 0000000..e255e1f --- /dev/null +++ b/src/Tests/Testify.Assertions.Tests/Formatting/FormatterTests.cs @@ -0,0 +1,137 @@ +namespace Testify.Tests.Formatting; + +public static class FormatterTests +{ + public class Format + { + [Fact] + public void ShouldFormatNullValue() + { + var expected = ""; + + var result = Formatter.Format(null); + + XAssert.Equal(expected, result); + } + + [Fact] + public void ShouldFormatExpression() + { + var expected = $"{FormatExpression("expr")} ()"; + + var result = Formatter.Format(null, "expr"); + + XAssert.Equal(expected, result); + } + + [Fact] + public void ShouldFormatInt() + { + var value = 42; + var expected = value.ToString(); + + var result = Formatter.Format(value); + + XAssert.Equal(expected, result); + } + + [Fact] + public void ShouldFormatGuid() + { + var value = Guid.NewGuid(); + var expected = $"<{value.ToString()}>"; + + var result = Formatter.Format(value); + + XAssert.Equal(expected, result); + } + + [Fact] + public void ShouldFormatString() + { + var value = "42"; + var expected = $"\"{value}\""; + + var result = Formatter.Format(value); + + XAssert.Equal(expected, result); + } + + [Fact] + public void ShouldFormatDateTime() + { + var value = DateTime.Now; + var expected = $"<{value.ToString("s")}>"; + + var result = Formatter.Format(value); + + XAssert.Equal(expected, result); + } + + [Fact] + public void ShouldFormatDateTimeOffset() + { + var value = DateTimeOffset.Now; + var expected = $"<{value.ToString("s")}>"; + + var result = Formatter.Format(value); + + XAssert.Equal(expected, result); + } + + [Fact] + public void ShouldFormatDateOnly() + { + var value = DateOnly.FromDateTime(DateTime.Now); + var expected = $"<{value.ToString("YYYY-MM-dd")}>"; + + var result = Formatter.Format(value); + + XAssert.Equal(expected, result); + } + + [Fact] + public void ShouldFormatTimeOnly() + { + var value = TimeOnly.FromDateTime(DateTime.Now); + var expected = $"<{value.ToString("HH:mm:ss")}>"; + + var result = Formatter.Format(value); + + XAssert.Equal(expected, result); + } + + [Fact] + public void ShouldFormatDateTimeDate() + { + var value = DateTime.Now.Date; + var expected = $"<{value.ToString("YYYY-MM-dd")}>"; + + var result = Formatter.Format(value); + + XAssert.Equal(expected, result); + } + + [Fact] + public void ShouldFormatDateTimeTime() + { + var value = new DateTime(0) + new TimeSpan(1, 2, 3); + var expected = $"<{value.ToString("HH:mm:ss")}>"; + + var result = Formatter.Format(value); + + XAssert.Equal(expected, result); + } + + [Fact] + public void ShouldFormatTimeSpan() + { + var value = DateTime.Now.TimeOfDay; + var expected = $"<{value.ToString(@"hh\:mm\:ss")}>"; + + var result = Formatter.Format(value); + + XAssert.Equal(expected, result); + } + } +} diff --git a/src/Tests/Testify.Assertions.Tests/GlobalUsings.cs b/src/Tests/Testify.Assertions.Tests/GlobalUsings.cs new file mode 100644 index 0000000..bdf0f36 --- /dev/null +++ b/src/Tests/Testify.Assertions.Tests/GlobalUsings.cs @@ -0,0 +1,8 @@ +global using Xunit; +global using Testify; +global using Testify.Formatting; + +global using XAssert = Xunit.Assert; +global using static Testify.Assertion; +global using static Testify.Formatting.Formatter; +global using static Testify.Tests.Helpers; \ No newline at end of file diff --git a/src/Tests/Testify.Assertions.Tests/Helpers.cs b/src/Tests/Testify.Assertions.Tests/Helpers.cs new file mode 100644 index 0000000..eb4acfd --- /dev/null +++ b/src/Tests/Testify.Assertions.Tests/Helpers.cs @@ -0,0 +1,25 @@ +namespace Testify.Tests; + +using Xunit.Sdk; + +internal static class Helpers +{ + public static Action Act(Action action) => action; + + public static void ShouldSucceed(Action action) + { + var exception = Record.Exception(action); + if (exception != null) + { + throw new XunitException($"Expected assertion to succeed, but failed with {exception.GetType().Name}."); + } + } + + public static void ShouldFail(Action action, string expectedMessage) + { + var exception = Record.Exception(action) + ?? throw new XunitException("Expected assertion to fail, but succeeded."); + + XAssert.Equal(expectedMessage, exception.Message); + } +} diff --git a/src/Tests/Testify.Assertions.Tests/Testify.Assertions.Tests.csproj b/src/Tests/Testify.Assertions.Tests/Testify.Assertions.Tests.csproj new file mode 100644 index 0000000..6395b4b --- /dev/null +++ b/src/Tests/Testify.Assertions.Tests/Testify.Assertions.Tests.csproj @@ -0,0 +1,30 @@ + + + + net7.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + diff --git a/src/Tests/Testify.Assertions.Tests/packages.lock.json b/src/Tests/Testify.Assertions.Tests/packages.lock.json new file mode 100644 index 0000000..37dd220 --- /dev/null +++ b/src/Tests/Testify.Assertions.Tests/packages.lock.json @@ -0,0 +1,1041 @@ +{ + "version": 2, + "dependencies": { + "net7.0": { + "coverlet.collector": { + "type": "Direct", + "requested": "[3.2.0, )", + "resolved": "3.2.0", + "contentHash": "xjY8xBigSeWIYs4I7DgUHqSNoGqnHi7Fv7/7RZD02rvZyG3hlsjnQKiVKVWKgr9kRKgmV+dEfu8KScvysiC0Wg==" + }, + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[17.7.2, )", + "resolved": "17.7.2", + "contentHash": "WOSF/GUYcnrLGkdvCbXDRig2rShtBwfQc5l7IxQE6PZI3CeXAqF1SpyzwlGA5vw+MdEAXs3niy+ZkGBBWna6tw==", + "dependencies": { + "Microsoft.CodeCoverage": "17.7.2", + "Microsoft.TestPlatform.TestHost": "17.7.2" + } + }, + "xunit": { + "type": "Direct", + "requested": "[2.5.1, )", + "resolved": "2.5.1", + "contentHash": "WJJ7Ruxv1INF4ySosVZ0fN1dGhzNBEdLLZoIVn4TPU8CbYgaxUebAL/VPaBneXGT3EDE2llsJ2cKzGkGeZSY4Q==", + "dependencies": { + "xunit.analyzers": "1.3.0", + "xunit.assert": "2.5.1", + "xunit.core": "[2.5.1]" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[2.5.1, )", + "resolved": "2.5.1", + "contentHash": "W5dQj2tysIY6MHaidZyqyiR7MGFEk+FrvHRapFyhe11HuR4A6aFGSVi8txi+kkXdY9FDjXffU/1PkNzRX52Caw==" + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.7.2", + "contentHash": "ntbkwIqwszkfCRjxVZOyEQiHauiYsY9NtYjw9ASsoxDSiG8YtV6AGcOAwrAk3TZv2UOq4MrpX+3MYEeMHSb03w==" + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.7.2", + "contentHash": "aHzQWgDMVBnk39HhQVmn06w+YxzF1h2V5/M4WgrNQAn7q97GR4Si3vLRTDlmJo9nK/Nknce+H4tXx4gqOKyLeg==", + "dependencies": { + "NuGet.Frameworks": "6.5.0", + "System.Reflection.Metadata": "1.6.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.7.2", + "contentHash": "pv9yVD7IKPLJV28zYjLsWFiM3j506I2ye+6NquG8vsbm/gR7lgyig8IgY6Vo57VMvGaAKwtUECzcj+C5tH271Q==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.7.2", + "Newtonsoft.Json": "13.0.1" + } + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "NuGet.Frameworks": { + "type": "Transitive", + "resolved": "6.5.0", + "contentHash": "QWINE2x3MbTODsWT1Gh71GaGb5icBz4chS8VYvTgsBnsi8esgN6wtHhydd7fvToWECYGq7T4cgBBDiKD/363fg==" + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "npvJkVKl5rKXrtl1Kkm6OhOUaYGEiF9wFbppFRWSMoApKzt2PiPHT2Bb8a5sAWxprvdOAtvaARS9QYMznEUtug==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "xunit.abstractions": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" + }, + "xunit.assert": { + "type": "Transitive", + "resolved": "2.5.1", + "contentHash": "eMvuz6PFdD3DDeaXkFVwMzNZ40zcRoM9Zz3siAyWgfiAucSNOWZnVgqC8hSHbdMd98Gy6o0yIYG6mq4Tg37rrQ==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "xunit.core": { + "type": "Transitive", + "resolved": "2.5.1", + "contentHash": "Tzuz//XwPJYAmC9FBIwgBgo5gb2kSoppDwkisyYhq0wtwxhv+gOJwtqUgkgk8Hr19B616Zol03LkD18r2e4AxA==", + "dependencies": { + "xunit.extensibility.core": "[2.5.1]", + "xunit.extensibility.execution": "[2.5.1]" + } + }, + "xunit.extensibility.execution": { + "type": "Transitive", + "resolved": "2.5.1", + "contentHash": "I5IUervdZoKLD66TUcqsJDXcB3ui9RxzKe0MQGzEi4Hsxkaoz0YylmvwqW2nd3nilyqqIAs0OUaZf/faKPxY6w==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.extensibility.core": "[2.5.1]" + } + }, + "testify.assertions": { + "type": "Project", + "dependencies": { + "Microsoft.VisualStudio.Validation": "[17.6.11, )" + } + }, + "testify.xunit.traits": { + "type": "Project", + "dependencies": { + "xunit.extensibility.core": "[2.5.1, )" + } + }, + "Microsoft.VisualStudio.Validation": { + "type": "CentralTransitive", + "requested": "[17.6.11, )", + "resolved": "17.6.11", + "contentHash": "J+9L/iac6c8cwcgVSCMuoIYOlD1Jw4mbZ8XMe1IZVj8p8+3dJ46LnnkIkTRMjK7xs9UtU9MoUp1JGhWoN6fAEw==" + }, + "xunit.analyzers": { + "type": "CentralTransitive", + "requested": "[0.8.0, )", + "resolved": "1.3.0", + "contentHash": "gSk+8RC6UZ6Fzx1OHoB2bPyENeg3WHIeJhB/hb4oZNN0pW0dwOuplJay6OnqFIvW8T37re/RB4PWpEvayWIO1Q==" + }, + "xunit.extensibility.core": { + "type": "CentralTransitive", + "requested": "[2.5.1, )", + "resolved": "2.5.1", + "contentHash": "XGPiWP7D/KIY/fzdmU9gx7eDt0QD0IAWOy54LI+ckLZCqFMupIFochC3dHRxykuAz+L0nYvz6PxDdR2UcgNmDw==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.abstractions": "2.0.3" + } + } + } + } +} \ No newline at end of file diff --git a/src/Tests/Testify.Moq.Tests/packages.lock.json b/src/Tests/Testify.Moq.Tests/packages.lock.json index 85e36d6..9f96c1c 100644 --- a/src/Tests/Testify.Moq.Tests/packages.lock.json +++ b/src/Tests/Testify.Moq.Tests/packages.lock.json @@ -1140,15 +1140,6 @@ "xunit.extensibility.execution": "[2.5.1]" } }, - "xunit.extensibility.core": { - "type": "Transitive", - "resolved": "2.5.1", - "contentHash": "XGPiWP7D/KIY/fzdmU9gx7eDt0QD0IAWOy54LI+ckLZCqFMupIFochC3dHRxykuAz+L0nYvz6PxDdR2UcgNmDw==", - "dependencies": { - "NETStandard.Library": "1.6.1", - "xunit.abstractions": "2.0.3" - } - }, "xunit.extensibility.execution": { "type": "Transitive", "resolved": "2.5.1", @@ -1194,6 +1185,16 @@ "requested": "[0.8.0, )", "resolved": "1.3.0", "contentHash": "gSk+8RC6UZ6Fzx1OHoB2bPyENeg3WHIeJhB/hb4oZNN0pW0dwOuplJay6OnqFIvW8T37re/RB4PWpEvayWIO1Q==" + }, + "xunit.extensibility.core": { + "type": "CentralTransitive", + "requested": "[2.5.1, )", + "resolved": "2.5.1", + "contentHash": "XGPiWP7D/KIY/fzdmU9gx7eDt0QD0IAWOy54LI+ckLZCqFMupIFochC3dHRxykuAz+L0nYvz6PxDdR2UcgNmDw==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.abstractions": "2.0.3" + } } } } diff --git a/src/Tests/Testify.Tests/packages.lock.json b/src/Tests/Testify.Tests/packages.lock.json index 266c36c..e59e79b 100644 --- a/src/Tests/Testify.Tests/packages.lock.json +++ b/src/Tests/Testify.Tests/packages.lock.json @@ -987,15 +987,6 @@ "xunit.extensibility.execution": "[2.5.1]" } }, - "xunit.extensibility.core": { - "type": "Transitive", - "resolved": "2.5.1", - "contentHash": "XGPiWP7D/KIY/fzdmU9gx7eDt0QD0IAWOy54LI+ckLZCqFMupIFochC3dHRxykuAz+L0nYvz6PxDdR2UcgNmDw==", - "dependencies": { - "NETStandard.Library": "1.6.1", - "xunit.abstractions": "2.0.3" - } - }, "xunit.extensibility.execution": { "type": "Transitive", "resolved": "2.5.1", @@ -1022,6 +1013,16 @@ "requested": "[0.8.0, )", "resolved": "1.3.0", "contentHash": "gSk+8RC6UZ6Fzx1OHoB2bPyENeg3WHIeJhB/hb4oZNN0pW0dwOuplJay6OnqFIvW8T37re/RB4PWpEvayWIO1Q==" + }, + "xunit.extensibility.core": { + "type": "CentralTransitive", + "requested": "[2.5.1, )", + "resolved": "2.5.1", + "contentHash": "XGPiWP7D/KIY/fzdmU9gx7eDt0QD0IAWOy54LI+ckLZCqFMupIFochC3dHRxykuAz+L0nYvz6PxDdR2UcgNmDw==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.abstractions": "2.0.3" + } } } }