From fc31ca757f2e5413ccff5b4e4908cfe1de31933f Mon Sep 17 00:00:00 2001 From: Benjamin Abt Date: Sat, 12 Apr 2025 12:41:30 +0200 Subject: [PATCH 1/2] Add unit tests for HttpUserAgentParser functionality - Implement tests for HttpUserAgentInformationExtensions to validate user agent type detection (browser, robot, unknown). - Create tests for HttpUserAgentInformation to ensure correct parsing and creation for browsers, robots, and unknown agents. - Add tests for HttpUserAgentPlatformInformation and HttpUserAgentPlatformType to verify constructor behavior and value mappings. - Develop comprehensive tests for HttpUserAgentParser to check various user agent strings across different browsers and bots. - Introduce caching provider tests for HttpUserAgentParserCachedProvider to confirm caching behavior and duplicate handling. - Implement default provider tests for HttpUserAgentParserDefaultProvider to ensure consistent parsing results. --- .editorconfig | 181 +++++++++--------- .github/workflows/ci.yml | 7 +- Directory.Build.props | 168 +++++++++++----- Directory.Packages.props | 43 +++-- MyCSharp.HttpUserAgentParser.sln | 16 +- global.json | 6 +- .../HttpUserAgentParser.Benchmarks.csproj} | 2 +- .../HttpUserAgentParserBenchmarks.cs | 0 .../LibraryComparisonBenchmarks.cs | 0 .../Program.cs | 1 - ...serDependencyInjectionOptionsExtensions.cs | 0 .../HttpContextExtensions.cs | 0 .../HttpUserAgentParser.AspNetCore.csproj | 27 +++ .../HttpUserAgentParserAccessor.cs | 0 .../IHttpUserAgentParserAccessor.cs | 0 .../LICENSE.txt | 0 .../readme.md | 0 ...rMemoryCacheServiceCollectionExtensions.cs | 0 .../HttpUserAgentParser.MemoryCache.csproj} | 17 +- ...HttpUserAgentParserMemoryCachedProvider.cs | 8 +- ...rAgentParserMemoryCachedProviderOptions.cs | 0 .../LICENSE.txt | 0 .../readme.md | 0 ...erAgentParserDependencyInjectionOptions.cs | 0 ...rAgentParserServiceCollectionExtensions.cs | 0 .../HttpUserAgentInformation.cs | 4 +- .../HttpUserAgentInformationExtensions.cs | 0 .../HttpUserAgentParser.cs | 3 + .../HttpUserAgentParser.csproj} | 15 -- .../HttpUserAgentPlatformInformation.cs | 0 .../HttpUserAgentPlatformType.cs | 0 .../HttpUserAgentStatics.cs | 11 +- .../HttpUserAgentType.cs | 0 .../LICENSE.txt | 0 .../HttpUserAgentParserCachedProvider.cs | 2 +- .../HttpUserAgentParserDefaultProvider.cs | 0 .../Providers/IHttpUserAgentParserProvider.cs | 0 .../readme.md | 0 ...harp.HttpUserAgentParser.AspNetCore.csproj | 42 ---- ...tParserServiceCollectionExtensionsTests.cs | 0 .../HttpContextTestHelpers.cs | 0 ...serAgentParser.AspNetCore.UnitTests.csproj | 16 ++ .../HttpUserAgentParserAccessorTests.cs | 0 ...yCacheServiceCollectionExtensionssTests.cs | 0 ...erAgentParser.MemoryCache.UnitTests.csproj | 16 ++ ...tParserMemoryCachedProviderOptionsTests.cs | 0 ...serAgentParserMemoryCachedProviderTests.cs | 0 .../HttpUserAgentParser.TestHelpers.csproj | 7 + ...erAgentParserDependencyInjectionOptions.cs | 0 ...tParserServiceCollectionExtensionsTests.cs | 2 +- ...HttpUserAgentInformationExtensionsTests.cs | 0 .../HttpUserAgentInformationTests.cs | 13 +- .../HttpUserAgentParser.UnitTests.csproj | 15 ++ .../HttpUserAgentParserTests.cs | 0 .../HttpUserAgentPlatformInformationTests.cs | 2 +- .../HttpUserAgentPlatformTypeTests.cs | 0 .../HttpUserAgentTypeTests.cs | 0 .../HttpUserAgentParserCachedProviderTests.cs | 0 ...HttpUserAgentParserDefaultProviderTests.cs | 0 ...serAgentParser.AspNetCore.UnitTests.csproj | 45 ----- ...erAgentParser.MemoryCache.UnitTests.csproj | 44 ----- ...arp.HttpUserAgentParser.TestHelpers.csproj | 26 --- ...Sharp.HttpUserAgentParser.UnitTests.csproj | 44 ----- version.json | 33 ++-- 64 files changed, 379 insertions(+), 437 deletions(-) rename perf/{MyCSharp.HttpUserAgentParser.Benchmarks/MyCSharp.HttpUserAgentParser.Benchmarks.csproj => HttpUserAgentParser.Benchmarks/HttpUserAgentParser.Benchmarks.csproj} (89%) rename perf/{MyCSharp.HttpUserAgentParser.Benchmarks => HttpUserAgentParser.Benchmarks}/HttpUserAgentParserBenchmarks.cs (100%) rename perf/{MyCSharp.HttpUserAgentParser.Benchmarks => HttpUserAgentParser.Benchmarks}/LibraryComparison/LibraryComparisonBenchmarks.cs (100%) rename perf/{MyCSharp.HttpUserAgentParser.Benchmarks => HttpUserAgentParser.Benchmarks}/Program.cs (99%) rename src/{MyCSharp.HttpUserAgentParser.AspNetCore => HttpUserAgentParser.AspNetCore}/DependencyInjection/HttpUserAgentParserDependencyInjectionOptionsExtensions.cs (100%) rename src/{MyCSharp.HttpUserAgentParser.AspNetCore => HttpUserAgentParser.AspNetCore}/HttpContextExtensions.cs (100%) create mode 100644 src/HttpUserAgentParser.AspNetCore/HttpUserAgentParser.AspNetCore.csproj rename src/{MyCSharp.HttpUserAgentParser.AspNetCore => HttpUserAgentParser.AspNetCore}/HttpUserAgentParserAccessor.cs (100%) rename src/{MyCSharp.HttpUserAgentParser.AspNetCore => HttpUserAgentParser.AspNetCore}/IHttpUserAgentParserAccessor.cs (100%) rename src/{MyCSharp.HttpUserAgentParser.AspNetCore => HttpUserAgentParser.AspNetCore}/LICENSE.txt (100%) rename src/{MyCSharp.HttpUserAgentParser.AspNetCore => HttpUserAgentParser.AspNetCore}/readme.md (100%) rename src/{MyCSharp.HttpUserAgentParser.MemoryCache => HttpUserAgentParser.MemoryCache}/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensions.cs (100%) rename src/{MyCSharp.HttpUserAgentParser.MemoryCache/MyCSharp.HttpUserAgentParser.MemoryCache.csproj => HttpUserAgentParser.MemoryCache/HttpUserAgentParser.MemoryCache.csproj} (50%) rename src/{MyCSharp.HttpUserAgentParser.MemoryCache => HttpUserAgentParser.MemoryCache}/HttpUserAgentParserMemoryCachedProvider.cs (83%) rename src/{MyCSharp.HttpUserAgentParser.MemoryCache => HttpUserAgentParser.MemoryCache}/HttpUserAgentParserMemoryCachedProviderOptions.cs (100%) rename src/{MyCSharp.HttpUserAgentParser.MemoryCache => HttpUserAgentParser.MemoryCache}/LICENSE.txt (100%) rename src/{MyCSharp.HttpUserAgentParser.MemoryCache => HttpUserAgentParser.MemoryCache}/readme.md (100%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/DependencyInjection/HttpUserAgentParserDependencyInjectionOptions.cs (100%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/DependencyInjection/HttpUserAgentParserServiceCollectionExtensions.cs (100%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/HttpUserAgentInformation.cs (94%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/HttpUserAgentInformationExtensions.cs (100%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/HttpUserAgentParser.cs (97%) rename src/{MyCSharp.HttpUserAgentParser/MyCSharp.HttpUserAgentParser.csproj => HttpUserAgentParser/HttpUserAgentParser.csproj} (52%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/HttpUserAgentPlatformInformation.cs (100%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/HttpUserAgentPlatformType.cs (100%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/HttpUserAgentStatics.cs (97%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/HttpUserAgentType.cs (100%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/LICENSE.txt (100%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/Providers/HttpUserAgentParserCachedProvider.cs (94%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/Providers/HttpUserAgentParserDefaultProvider.cs (100%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/Providers/IHttpUserAgentParserProvider.cs (100%) rename src/{MyCSharp.HttpUserAgentParser => HttpUserAgentParser}/readme.md (100%) delete mode 100644 src/MyCSharp.HttpUserAgentParser.AspNetCore/MyCSharp.HttpUserAgentParser.AspNetCore.csproj rename tests/{MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests => HttpUserAgentParser.AspNetCore.UnitTests}/DependencyInjection/HttpUserAgentParserServiceCollectionExtensionsTests.cs (100%) rename tests/{MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests => HttpUserAgentParser.AspNetCore.UnitTests}/HttpContextTestHelpers.cs (100%) create mode 100644 tests/HttpUserAgentParser.AspNetCore.UnitTests/HttpUserAgentParser.AspNetCore.UnitTests.csproj rename tests/{MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests => HttpUserAgentParser.AspNetCore.UnitTests}/HttpUserAgentParserAccessorTests.cs (100%) rename tests/{MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests => HttpUserAgentParser.MemoryCache.UnitTests}/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensionssTests.cs (100%) create mode 100644 tests/HttpUserAgentParser.MemoryCache.UnitTests/HttpUserAgentParser.MemoryCache.UnitTests.csproj rename tests/{MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests => HttpUserAgentParser.MemoryCache.UnitTests}/HttpUserAgentParserMemoryCachedProviderOptionsTests.cs (100%) rename tests/{MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests => HttpUserAgentParser.MemoryCache.UnitTests}/HttpUserAgentParserMemoryCachedProviderTests.cs (100%) create mode 100644 tests/HttpUserAgentParser.TestHelpers/HttpUserAgentParser.TestHelpers.csproj rename tests/{MyCSharp.HttpUserAgentParser.UnitTests => HttpUserAgentParser.UnitTests}/DependencyInjection/HttpUserAgentParserDependencyInjectionOptions.cs (100%) rename tests/{MyCSharp.HttpUserAgentParser.UnitTests => HttpUserAgentParser.UnitTests}/DependencyInjection/HttpUserAgentParserServiceCollectionExtensionsTests.cs (97%) rename tests/{MyCSharp.HttpUserAgentParser.UnitTests => HttpUserAgentParser.UnitTests}/HttpUserAgentInformationExtensionsTests.cs (100%) rename tests/{MyCSharp.HttpUserAgentParser.UnitTests => HttpUserAgentParser.UnitTests}/HttpUserAgentInformationTests.cs (83%) create mode 100644 tests/HttpUserAgentParser.UnitTests/HttpUserAgentParser.UnitTests.csproj rename tests/{MyCSharp.HttpUserAgentParser.UnitTests => HttpUserAgentParser.UnitTests}/HttpUserAgentParserTests.cs (100%) rename tests/{MyCSharp.HttpUserAgentParser.UnitTests => HttpUserAgentParser.UnitTests}/HttpUserAgentPlatformInformationTests.cs (90%) rename tests/{MyCSharp.HttpUserAgentParser.UnitTests => HttpUserAgentParser.UnitTests}/HttpUserAgentPlatformTypeTests.cs (100%) rename tests/{MyCSharp.HttpUserAgentParser.UnitTests => HttpUserAgentParser.UnitTests}/HttpUserAgentTypeTests.cs (100%) rename tests/{MyCSharp.HttpUserAgentParser.UnitTests => HttpUserAgentParser.UnitTests}/Providers/HttpUserAgentParserCachedProviderTests.cs (100%) rename tests/{MyCSharp.HttpUserAgentParser.UnitTests => HttpUserAgentParser.UnitTests}/Providers/HttpUserAgentParserDefaultProviderTests.cs (100%) delete mode 100644 tests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests.csproj delete mode 100644 tests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests.csproj delete mode 100644 tests/MyCSharp.HttpUserAgentParser.TestHelpers/MyCSharp.HttpUserAgentParser.TestHelpers.csproj delete mode 100644 tests/MyCSharp.HttpUserAgentParser.UnitTests/MyCSharp.HttpUserAgentParser.UnitTests.csproj diff --git a/.editorconfig b/.editorconfig index 9636fb7..c22c07c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,25 +1,28 @@ +# EditorConfig is awesome:http://EditorConfig.org +# From https://raw.githubusercontent.com/dotnet/roslyn/master/.editorconfig +# https://github.com/BenjaminAbt/templates/blob/main/editorconfig/.editorconfig + ############################### # Core EditorConfig Options # ############################### +# top-most EditorConfig file root = true # stop .editorconfig files search on current file. # All files +# Don't use tabs for indentation. [*] -charset = utf-8 indent_style = space -indent_size = 4 trim_trailing_whitespace = true # Remove trailing whitespace insert_final_newline = true # Ensure file ends with a newline max_line_length = 120 # Maximum line length for readability -end_of_line = lf -tab_width = 4 ############################### # Markdown # ############################### [*.md] +indent_size = 4 trim_trailing_whitespace = false max_line_length = off @@ -83,11 +86,43 @@ max_line_length = off indent_size = 2 max_line_length = off +############################### +# PowerShell # +############################### + +[*.ps1] +indent_size = 2 + +############################### +# Shell # +############################### + +[*.sh] +end_of_line = lf + +[*.{cmd,bat}] +end_of_line = crlf + +############################### +# .NET project files # +############################### + +# Xml project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 2 + +# Xml config files +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +indent_size = 2 + ############################### # C# / VB # ############################### -[*.{cs,vb}] +# Code files +[*.{cs,csx,vb,vbx}] +indent_size = 4 + # Organize usings dotnet_sort_system_directives_first = true @@ -98,8 +133,8 @@ dotnet_style_qualification_for_method = false:silent dotnet_style_qualification_for_event = 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 +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion # Parentheses preferences dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent @@ -124,11 +159,7 @@ dotnet_style_prefer_auto_properties = true:suggestion dotnet_style_prefer_conditional_expression_over_assignment = true:silent dotnet_style_prefer_conditional_expression_over_return = true:silent -############################### -# Naming Conventions # -############################### # Style Definitions - dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i @@ -230,10 +261,8 @@ csharp_preferred_modifier_order = public,private,protected,internal,static,exter csharp_prefer_braces = true:suggestion csharp_style_deconstructed_variable_declaration = true:suggestion csharp_prefer_simple_default_expression = true:suggestion -csharp_style_prefer_local_over_anonymous_function = true:suggestion csharp_style_inlined_variable_declaration = true:suggestion -# ------------------------------------------------------ # New line preferences csharp_new_line_before_open_brace = all csharp_new_line_before_else = true @@ -243,13 +272,11 @@ csharp_new_line_before_members_in_object_initializers = true csharp_new_line_before_members_in_anonymous_types = true csharp_new_line_between_query_expression_clauses = true -# ------------------------------------------------------ # Indentation preferences csharp_indent_case_contents = true csharp_indent_switch_labels = true csharp_indent_labels = one_less_than_current -# ------------------------------------------------------ # Space preferences csharp_space_after_cast = false csharp_space_after_keywords_in_control_flow_statements = true @@ -263,7 +290,6 @@ csharp_space_between_method_declaration_empty_parameter_list_parentheses = false csharp_space_between_method_call_name_and_opening_parenthesis = false csharp_space_between_method_call_empty_parameter_list_parentheses = false -# ------------------------------------------------------ # Wrapping preferences csharp_preserve_single_line_statements = true csharp_preserve_single_line_blocks = true @@ -294,54 +320,6 @@ csharp_style_prefer_pattern_matching = true:silent csharp_style_prefer_not_pattern = true:suggestion csharp_style_prefer_extended_property_pattern = true:suggestion -# ------------------------------------------------------ -# Naming rules - -dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion -dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface -dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i - -dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.types_should_be_pascal_case.symbols = types -dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case - -dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members -dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case - -# ------------------------------------------------------ -# Symbol specifications - -dotnet_naming_symbols.interface.applicable_kinds = interface -dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.interface.required_modifiers = - -dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum -dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.types.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 = - -# ------------------------------------------------------ -# Naming styles - -dotnet_naming_style.begins_with_i.required_prefix = I -dotnet_naming_style.begins_with_i.required_suffix = -dotnet_naming_style.begins_with_i.word_separator = -dotnet_naming_style.begins_with_i.capitalization = pascal_case - -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = -dotnet_naming_style.pascal_case.capitalization = pascal_case - -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = -dotnet_naming_style.pascal_case.capitalization = pascal_case - # ------------------------------------------------------ # CA Style @@ -349,108 +327,129 @@ dotnet_naming_style.pascal_case.capitalization = pascal_case dotnet_diagnostic.CA1050.severity = warning # CA1507: Use nameof in place of string +# Avoiding hard-coded strings in code improves maintainability and reduces the risk of errors during refactoring. dotnet_diagnostic.CA1507.severity = warning -# CA1825: Avoid unnecessary zero-length array allocations. Use Array.Empty() instead. +# CA1825: Avoid unnecessary zero-length array allocations. Use Array.Empty() instead. +# Array.Empty() is more memory-efficient as it reuses a single cached empty array instance rather than creating new ones. dotnet_diagnostic.CA1825.severity = warning # CA1850: It is more efficient to use the static 'HashData' method over creating and managing a HashAlgorithm instance to call 'ComputeHash'. +# This improves performance by avoiding unnecessary instance creation and lifecycle management of HashAlgorithm objects. dotnet_diagnostic.CA1850.severity = warning # CA1860: Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. -# The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method. -dotnet_diagnostic.CA1860.severity = warning - -# CA1860: Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. -# The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method. +# These direct property accesses are more performant and communicate intent more clearly than using LINQ extension methods. dotnet_diagnostic.CA1860.severity = warning # CS1998: This async method lacks 'await' operators and will run synchronously. -# Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. +# Setting this to error prevents misleading code that suggests asynchronous behavior but actually runs synchronously. dotnet_diagnostic.CS1998.severity = error # CA2016: Forward the CancellationToken parameter to methods that take one +# Ensuring proper propagation of cancellation tokens throughout the call chain is critical for responsive and cancellable operations. dotnet_diagnostic.CA2016.severity = error - -# CA2211: Static fields that are neither constants nor read-only are not thread-safe. -# Access to such a field must be carefully controlled and requires advanced programming techniques to synchronize access to the class object. -dotnet_diagnostic.CA2211.severity = silent - # ------------------------------------------------------ # IDE # IDE0060: Avoid unused parameters in your code. -# If the parameter cannot be removed, then change its name so it starts with an underscore and is optionally followed by an -# integer, such as '_', '_1', '_2', etc. These are treated as special discard symbol names. +# Silenced to allow for interface implementations where not all parameters may be needed in every implementation or like URL design in ASP.NET Core. dotnet_diagnostic.IDE0060.severity = silent # IDE0130: Namespace does not match folder structure +# Enforces consistent organization where namespaces reflect folder structure, improving code discoverability. dotnet_diagnostic.IDE0130.severity = warning -# IDE0290: Use primary constructor -dotnet_diagnostic.IDE0290.severity = none -csharp_style_prefer_primary_constructors = false:suggestion +# IDE0039: Use local function instead of lambda +# Local functions improve readability and performance over lambdas for method-local callable code. +dotnet_diagnostic.IDE0039.severity = warning -# IDE1006: Naming rule violation: These words must begin with upper case characters: accessToken +# IDE0270: Null check can be simplified +# Disabled to allow developers to choose their preferred null-checking style based on context and readability. +dotnet_diagnostic.IDE0270.severity = none + +# IDE0305: Use collection expression for fluent +# Silenced because collection expression style is often a matter of preference and readability context. +dotnet_diagnostic.IDE0305.severity = silent + +# IDE1006: Naming rule violation: These words must begin with upper case characters +# Enforces consistent naming conventions across the codebase for better readability and maintainability. dotnet_diagnostic.IDE1006.severity = warning # ------------------------------------------------------ # Roslyn +# RCS0063: Remove unnecessary blank line +# Promotes cleaner, more consistent code formatting by eliminating superfluous whitespace. +dotnet_diagnostic.RCS0063.severity = warning + # RCS1021: Use expression-bodied lambda. +# Silenced to allow both statement and expression-bodied lambda syntax based on complexity and readability. dotnet_diagnostic.RCS1021.severity = silent -# RCS1036: Remove unnecessary blank line -dotnet_diagnostic.RCS1036.severity = warning - # RCS1049: Simplify boolean comparison -# we usually prefer is vs ! +# Silenced to allow explicit boolean comparisons (e.g., x == true) when they improve readability. dotnet_diagnostic.RCS1049.severity = silent # RCS1123: Add parentheses when necessary +# Enforces explicit operator precedence through parentheses, preventing subtle bugs and improving readability. dotnet_diagnostic.RCS1123.severity = warning # RCS1163: Unused parameter -# Often this warning comes also from parameters we want to have for readability +# Silenced because parameters may be kept for API consistency or documentation purposes even when unused or URL design in ASP.NET Core. dotnet_diagnostic.RCS1163.severity = silent # RCS1194: Implement exception constructors +# Silenced to allow custom exception classes with only the constructors needed for the specific use case. dotnet_diagnostic.RCS1194.severity = silent # ------------------------------------------------------ # Meziantou.Analyzer +# MA0007: Add a comma after the last value +# Disabled as trailing commas in C# are not conventional and would make the code less familiar to most developers. +dotnet_diagnostic.MA0007.severity = none + # MA0016: Prefer using collection abstraction instead of implementation +# Disabled to allow direct use of concrete collection types when their specific capabilities are needed. dotnet_diagnostic.MA0016.severity = none # MA0017: Abstract types should not have public or internal constructors +# Disabled to permit protected constructors in abstract classes which are valid for inheritance scenarios. dotnet_diagnostic.MA0017.severity = none -# MA0018: Do not declare static members on generic types (deprecated; use CA1000 instead) +# MA0018: Do not declare static members on generic types +# Disabled in favor of using the standard CA1000 (Do not declare static members on generic types) rule to handle this case. dotnet_diagnostic.MA0018.severity = none # MA0029: Combine LINQ methods -# Often these recommendations have a performance impact, so it is recommended to review them before applying them. +# Disabled because LINQ method chaining can be more readable and potential performance impacts need case-by-case review. dotnet_diagnostic.MA0029.severity = none # MA0040: Forward the CancellationToken parameter to methods that take one +# Enforces proper cancellation token propagation for responsive applications and services. dotnet_diagnostic.MA0040.severity = warning # MA0048: File name must match type name +# Silenced to allow flexibility in file naming, particularly for partial classes or multiple types in one file. dotnet_diagnostic.MA0048.severity = silent -# MA0051: Method is too long (80 lines; maximum allowed: 60) +# MA0051: Method is too long +# Set as suggestion to encourage smaller, more focused methods while allowing flexibility for complex logic. dotnet_diagnostic.MA0051.severity = suggestion # MA0154: Use langword in XML comment +# Disabled to allow flexibility in documentation style and format. dotnet_diagnostic.MA0154.severity = none # ------------------------------------------------------ # Xunit # xUnit1006: Theory methods should have parameters +# Silenced to allow theories that might dynamically generate test cases without explicit parameters. dotnet_diagnostic.xUnit1006.severity = silent -# xUnit1048: Support for 'async void' unit tests is being removed from xUnit.net v3. To simplify upgrading, convert the test to 'async Task' instead. +# xUnit1048: Support for 'async void' unit tests is being removed +# Set as error to ensure future compatibility with xUnit v3 by requiring proper async Task signatures. dotnet_diagnostic.xUnit1048.severity = error diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 15b9090..558da40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,8 +12,13 @@ on: jobs: build: - uses: mycsharp/github-actions/.github/workflows/dotnet-nuget-build.yml@main + uses: mycsharp/github-actions/.github/workflows/dotnet-nuget-build-multi-sdk.yml@main with: configuration: Release + dotnet-sdks: | + 8.0.x + 9.0.x + 10.0.x + secrets: NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} diff --git a/Directory.Build.props b/Directory.Build.props index 4ded6bf..0dd3328 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,55 +1,121 @@ + + MyCSharp.HttpUserAgentParser + MyCSharp.de, Benjamin Abt, Günther Foidl and Contributors + MyCSharp.de + - - MyCSharp.de, Benjamin Abt, Günther Foidl and Contributors - MyCSharp.HttpUserAgentParser - en-US - true - embedded - - - - - $(MSBuildProjectName.Contains('Test')) - $(MsBuildProjectName.Contains('Benchmark')) - - - - https://github.com/mycsharp/HttpUserAgentParser - true - HTTP User Agent Parser for .NET - 2.12 - false - UserAgent, User Agent, Parse, Browser, Client, Detector, Detection, Console, ASP, Desktop, Mobile - true - - - - net8.0;net9.0 - - - - 12.0 - enable - enable - true - - - - true - - - - true - $(MSBuildThisFileDirectory)MyCSharp.HttpUserAgentParser.snk - - 00240000048000009400000006020000002400005253413100040000010001003d5c022c088a46d41d5a5bf7591f3a3dcba30f76b0f43a312b6e45bb419d32283175cbd8bfd83134b123da6db83479e50596fb6bbe0e8c6cef50c01c64a0861c963daaf6905920f44ffe1ce44b3cfcb9c23779f34bc90c7b04e74e36a19bb58af3a69456d49b56993969dba9f8e9e935c2757844a11066d1091477f10cd923b7 - - - - - - + + true + true + true + + $(MSBuildProjectName.EndsWith('Tests')) + $(MSBuildProjectName.EndsWith('UnitTests')) + $(MSBuildProjectName.EndsWith('IntegrationTests')) + $(MsBuildProjectName.EndsWith('Benchmarks')) + + + + net8.0;net9.0;net10.0 + MyCSharp.$(MSBuildProjectName) + MyCSharp.$(MSBuildProjectName) + + + + true + $(MSBuildThisFileDirectory)MyCSharp.HttpUserAgentParser.snk + + + 00240000048000009400000006020000002400005253413100040000010001003d5c022c088a46d41d5a5bf7591f3a3dcba30f76b0f43a312b6e45bb419d32283175cbd8bfd83134b123da6db83479e50596fb6bbe0e8c6cef50c01c64a0861c963daaf6905920f44ffe1ce44b3cfcb9c23779f34bc90c7b04e74e36a19bb58af3a69456d49b56993969dba9f8e9e935c2757844a11066d1091477f10cd923b7 + + + + + preview + embedded + enable + en-US + enable + true + + + + false + true + 2.12 + true + + HTTP User Agent Parser for .NET + https://github.com/mycsharp/HttpUserAgentParser + https://github.com/mycsharp/HttpUserAgentParser + UserAgent, User Agent, Parse, Browser, Client, Detector, Detection, Console, ASP, Desktop, Mobile + + + + true + + + + + true + + + + true + all + low + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + all + runtime; build; native; contentfiles; analyzers + + + all + runtime; build; native; contentfiles; analyzers + + + all + runtime; build; native; contentfiles; analyzers + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + diff --git a/Directory.Packages.props b/Directory.Packages.props index 73f2b79..4d9ff86 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -2,47 +2,64 @@ true - + + + - + - + + + + + + + - - - + + all + runtime; build; native; contentfiles; analyzers + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + all runtime; build; native; contentfiles; analyzers - - - + all runtime; build; native; contentfiles; analyzers - + all runtime; build; native; contentfiles; analyzers - + + + + all runtime; build; native; contentfiles; analyzers diff --git a/MyCSharp.HttpUserAgentParser.sln b/MyCSharp.HttpUserAgentParser.sln index d1dc0c3..a444be3 100644 --- a/MyCSharp.HttpUserAgentParser.sln +++ b/MyCSharp.HttpUserAgentParser.sln @@ -5,19 +5,19 @@ VisualStudioVersion = 17.4.32804.182 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{008A2BAB-78B4-42EB-A5D4-DE434438CEF0}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyCSharp.HttpUserAgentParser.AspNetCore", "src\MyCSharp.HttpUserAgentParser.AspNetCore\MyCSharp.HttpUserAgentParser.AspNetCore.csproj", "{45927CF7-1BF4-479B-BBAA-8AD9CA901AE4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpUserAgentParser.AspNetCore", "src\HttpUserAgentParser.AspNetCore\HttpUserAgentParser.AspNetCore.csproj", "{45927CF7-1BF4-479B-BBAA-8AD9CA901AE4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyCSharp.HttpUserAgentParser", "src\MyCSharp.HttpUserAgentParser\MyCSharp.HttpUserAgentParser.csproj", "{3357BEC0-8216-409E-A539-F9A71DBACB81}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpUserAgentParser", "src\HttpUserAgentParser\HttpUserAgentParser.csproj", "{3357BEC0-8216-409E-A539-F9A71DBACB81}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyCSharp.HttpUserAgentParser.UnitTests", "tests\MyCSharp.HttpUserAgentParser.UnitTests\MyCSharp.HttpUserAgentParser.UnitTests.csproj", "{F16697F7-74B4-441D-A0C0-1A0572AC3AB0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpUserAgentParser.UnitTests", "tests\HttpUserAgentParser.UnitTests\HttpUserAgentParser.UnitTests.csproj", "{F16697F7-74B4-441D-A0C0-1A0572AC3AB0}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests", "tests\MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests\MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests.csproj", "{75960783-8BF9-479C-9ECF-E9653B74C9A2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpUserAgentParser.AspNetCore.UnitTests", "tests\HttpUserAgentParser.AspNetCore.UnitTests\HttpUserAgentParser.AspNetCore.UnitTests.csproj", "{75960783-8BF9-479C-9ECF-E9653B74C9A2}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{F54C9296-4EF7-40F0-9F20-F23A2270ABC9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyCSharp.HttpUserAgentParser.MemoryCache", "src\MyCSharp.HttpUserAgentParser.MemoryCache\MyCSharp.HttpUserAgentParser.MemoryCache.csproj", "{3C8CCD44-F47C-4624-8997-54C42F02E376}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpUserAgentParser.MemoryCache", "src\HttpUserAgentParser.MemoryCache\HttpUserAgentParser.MemoryCache.csproj", "{3C8CCD44-F47C-4624-8997-54C42F02E376}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests", "tests\MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests\MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests.csproj", "{39FC1EC2-2AD3-411F-A545-AB6CCB94FB7E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpUserAgentParser.MemoryCache.UnitTests", "tests\HttpUserAgentParser.MemoryCache.UnitTests\HttpUserAgentParser.MemoryCache.UnitTests.csproj", "{39FC1EC2-2AD3-411F-A545-AB6CCB94FB7E}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_", "_", "{5738CE0D-5E6E-47CB-BFF5-08F45A2C33AD}" ProjectSection(SolutionItems) = preProject @@ -35,9 +35,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_", "_", "{5738CE0D-5E6E-47 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "perf", "perf", "{FAAD18A0-E1B8-448D-B611-AFBDA8A89808}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyCSharp.HttpUserAgentParser.Benchmarks", "perf\MyCSharp.HttpUserAgentParser.Benchmarks\MyCSharp.HttpUserAgentParser.Benchmarks.csproj", "{A0D213E9-6408-46D1-AFAF-5096C2F6E027}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpUserAgentParser.Benchmarks", "perf\HttpUserAgentParser.Benchmarks\HttpUserAgentParser.Benchmarks.csproj", "{A0D213E9-6408-46D1-AFAF-5096C2F6E027}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyCSharp.HttpUserAgentParser.TestHelpers", "tests\MyCSharp.HttpUserAgentParser.TestHelpers\MyCSharp.HttpUserAgentParser.TestHelpers.csproj", "{165EE915-1A4F-4875-90CE-1A2AE1540AE7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpUserAgentParser.TestHelpers", "tests\HttpUserAgentParser.TestHelpers\HttpUserAgentParser.TestHelpers.csproj", "{165EE915-1A4F-4875-90CE-1A2AE1540AE7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/global.json b/global.json index 76474f0..6303b53 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { - "sdk": { - "version": "9.0.100" - } + "sdk": { + "version": "10.0.100-preview.3.25201.16" + } } diff --git a/perf/MyCSharp.HttpUserAgentParser.Benchmarks/MyCSharp.HttpUserAgentParser.Benchmarks.csproj b/perf/HttpUserAgentParser.Benchmarks/HttpUserAgentParser.Benchmarks.csproj similarity index 89% rename from perf/MyCSharp.HttpUserAgentParser.Benchmarks/MyCSharp.HttpUserAgentParser.Benchmarks.csproj rename to perf/HttpUserAgentParser.Benchmarks/HttpUserAgentParser.Benchmarks.csproj index 7623138..e190b11 100644 --- a/perf/MyCSharp.HttpUserAgentParser.Benchmarks/MyCSharp.HttpUserAgentParser.Benchmarks.csproj +++ b/perf/HttpUserAgentParser.Benchmarks/HttpUserAgentParser.Benchmarks.csproj @@ -26,7 +26,7 @@ - + diff --git a/perf/MyCSharp.HttpUserAgentParser.Benchmarks/HttpUserAgentParserBenchmarks.cs b/perf/HttpUserAgentParser.Benchmarks/HttpUserAgentParserBenchmarks.cs similarity index 100% rename from perf/MyCSharp.HttpUserAgentParser.Benchmarks/HttpUserAgentParserBenchmarks.cs rename to perf/HttpUserAgentParser.Benchmarks/HttpUserAgentParserBenchmarks.cs diff --git a/perf/MyCSharp.HttpUserAgentParser.Benchmarks/LibraryComparison/LibraryComparisonBenchmarks.cs b/perf/HttpUserAgentParser.Benchmarks/LibraryComparison/LibraryComparisonBenchmarks.cs similarity index 100% rename from perf/MyCSharp.HttpUserAgentParser.Benchmarks/LibraryComparison/LibraryComparisonBenchmarks.cs rename to perf/HttpUserAgentParser.Benchmarks/LibraryComparison/LibraryComparisonBenchmarks.cs diff --git a/perf/MyCSharp.HttpUserAgentParser.Benchmarks/Program.cs b/perf/HttpUserAgentParser.Benchmarks/Program.cs similarity index 99% rename from perf/MyCSharp.HttpUserAgentParser.Benchmarks/Program.cs rename to perf/HttpUserAgentParser.Benchmarks/Program.cs index b4186c5..5c18157 100644 --- a/perf/MyCSharp.HttpUserAgentParser.Benchmarks/Program.cs +++ b/perf/HttpUserAgentParser.Benchmarks/Program.cs @@ -9,6 +9,5 @@ ManualConfig config = ManualConfig.Create(DefaultConfig.Instance) .WithOptions(ConfigOptions.DisableOptimizationsValidator); - // dotnet run -c Release --framework net80 net90 --runtimes net90 BenchmarkSwitcher.FromAssembly(Assembly.GetExecutingAssembly()).Run(args, config); diff --git a/src/MyCSharp.HttpUserAgentParser.AspNetCore/DependencyInjection/HttpUserAgentParserDependencyInjectionOptionsExtensions.cs b/src/HttpUserAgentParser.AspNetCore/DependencyInjection/HttpUserAgentParserDependencyInjectionOptionsExtensions.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser.AspNetCore/DependencyInjection/HttpUserAgentParserDependencyInjectionOptionsExtensions.cs rename to src/HttpUserAgentParser.AspNetCore/DependencyInjection/HttpUserAgentParserDependencyInjectionOptionsExtensions.cs diff --git a/src/MyCSharp.HttpUserAgentParser.AspNetCore/HttpContextExtensions.cs b/src/HttpUserAgentParser.AspNetCore/HttpContextExtensions.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser.AspNetCore/HttpContextExtensions.cs rename to src/HttpUserAgentParser.AspNetCore/HttpContextExtensions.cs diff --git a/src/HttpUserAgentParser.AspNetCore/HttpUserAgentParser.AspNetCore.csproj b/src/HttpUserAgentParser.AspNetCore/HttpUserAgentParser.AspNetCore.csproj new file mode 100644 index 0000000..fd97e4e --- /dev/null +++ b/src/HttpUserAgentParser.AspNetCore/HttpUserAgentParser.AspNetCore.csproj @@ -0,0 +1,27 @@ + + + + HTTP User Agent Parser Extensions for ASP.NET Core + HTTP User Agent Parser Extensions for ASP.NET Core + + + + true + readme.md + LICENSE.txt + + + + + + + + + + + + + + + + diff --git a/src/MyCSharp.HttpUserAgentParser.AspNetCore/HttpUserAgentParserAccessor.cs b/src/HttpUserAgentParser.AspNetCore/HttpUserAgentParserAccessor.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser.AspNetCore/HttpUserAgentParserAccessor.cs rename to src/HttpUserAgentParser.AspNetCore/HttpUserAgentParserAccessor.cs diff --git a/src/MyCSharp.HttpUserAgentParser.AspNetCore/IHttpUserAgentParserAccessor.cs b/src/HttpUserAgentParser.AspNetCore/IHttpUserAgentParserAccessor.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser.AspNetCore/IHttpUserAgentParserAccessor.cs rename to src/HttpUserAgentParser.AspNetCore/IHttpUserAgentParserAccessor.cs diff --git a/src/MyCSharp.HttpUserAgentParser.AspNetCore/LICENSE.txt b/src/HttpUserAgentParser.AspNetCore/LICENSE.txt similarity index 100% rename from src/MyCSharp.HttpUserAgentParser.AspNetCore/LICENSE.txt rename to src/HttpUserAgentParser.AspNetCore/LICENSE.txt diff --git a/src/MyCSharp.HttpUserAgentParser.AspNetCore/readme.md b/src/HttpUserAgentParser.AspNetCore/readme.md similarity index 100% rename from src/MyCSharp.HttpUserAgentParser.AspNetCore/readme.md rename to src/HttpUserAgentParser.AspNetCore/readme.md diff --git a/src/MyCSharp.HttpUserAgentParser.MemoryCache/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensions.cs b/src/HttpUserAgentParser.MemoryCache/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensions.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser.MemoryCache/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensions.cs rename to src/HttpUserAgentParser.MemoryCache/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensions.cs diff --git a/src/MyCSharp.HttpUserAgentParser.MemoryCache/MyCSharp.HttpUserAgentParser.MemoryCache.csproj b/src/HttpUserAgentParser.MemoryCache/HttpUserAgentParser.MemoryCache.csproj similarity index 50% rename from src/MyCSharp.HttpUserAgentParser.MemoryCache/MyCSharp.HttpUserAgentParser.MemoryCache.csproj rename to src/HttpUserAgentParser.MemoryCache/HttpUserAgentParser.MemoryCache.csproj index ea9e432..31057cb 100644 --- a/src/MyCSharp.HttpUserAgentParser.MemoryCache/MyCSharp.HttpUserAgentParser.MemoryCache.csproj +++ b/src/HttpUserAgentParser.MemoryCache/HttpUserAgentParser.MemoryCache.csproj @@ -21,23 +21,8 @@ - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - - + diff --git a/src/MyCSharp.HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProvider.cs b/src/HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProvider.cs similarity index 83% rename from src/MyCSharp.HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProvider.cs rename to src/HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProvider.cs index b4d4d3b..3673257 100644 --- a/src/MyCSharp.HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProvider.cs +++ b/src/HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProvider.cs @@ -19,7 +19,7 @@ public class HttpUserAgentParserMemoryCachedProvider( /// public HttpUserAgentInformation Parse(string userAgent) { - CacheKey key = this.GetKey(userAgent); + CacheKey key = GetKey(userAgent); return _memoryCache.GetOrCreate(key, static entry => { @@ -50,9 +50,9 @@ private CacheKey GetKey(string userAgent) public HttpUserAgentParserMemoryCachedProviderOptions Options { get; set; } = null!; - public bool Equals(CacheKey? other) => this.UserAgent == other?.UserAgent; - public override bool Equals(object? obj) => this.Equals(obj as CacheKey); + public bool Equals(CacheKey? other) => string.Equals(UserAgent, other?.UserAgent, StringComparison.OrdinalIgnoreCase); + public override bool Equals(object? obj) => Equals(obj as CacheKey); - public override int GetHashCode() => this.UserAgent.GetHashCode(); + public override int GetHashCode() => UserAgent.GetHashCode(StringComparison.Ordinal); } } diff --git a/src/MyCSharp.HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProviderOptions.cs b/src/HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProviderOptions.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProviderOptions.cs rename to src/HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProviderOptions.cs diff --git a/src/MyCSharp.HttpUserAgentParser.MemoryCache/LICENSE.txt b/src/HttpUserAgentParser.MemoryCache/LICENSE.txt similarity index 100% rename from src/MyCSharp.HttpUserAgentParser.MemoryCache/LICENSE.txt rename to src/HttpUserAgentParser.MemoryCache/LICENSE.txt diff --git a/src/MyCSharp.HttpUserAgentParser.MemoryCache/readme.md b/src/HttpUserAgentParser.MemoryCache/readme.md similarity index 100% rename from src/MyCSharp.HttpUserAgentParser.MemoryCache/readme.md rename to src/HttpUserAgentParser.MemoryCache/readme.md diff --git a/src/MyCSharp.HttpUserAgentParser/DependencyInjection/HttpUserAgentParserDependencyInjectionOptions.cs b/src/HttpUserAgentParser/DependencyInjection/HttpUserAgentParserDependencyInjectionOptions.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser/DependencyInjection/HttpUserAgentParserDependencyInjectionOptions.cs rename to src/HttpUserAgentParser/DependencyInjection/HttpUserAgentParserDependencyInjectionOptions.cs diff --git a/src/MyCSharp.HttpUserAgentParser/DependencyInjection/HttpUserAgentParserServiceCollectionExtensions.cs b/src/HttpUserAgentParser/DependencyInjection/HttpUserAgentParserServiceCollectionExtensions.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser/DependencyInjection/HttpUserAgentParserServiceCollectionExtensions.cs rename to src/HttpUserAgentParser/DependencyInjection/HttpUserAgentParserServiceCollectionExtensions.cs diff --git a/src/MyCSharp.HttpUserAgentParser/HttpUserAgentInformation.cs b/src/HttpUserAgentParser/HttpUserAgentInformation.cs similarity index 94% rename from src/MyCSharp.HttpUserAgentParser/HttpUserAgentInformation.cs rename to src/HttpUserAgentParser/HttpUserAgentInformation.cs index 1319154..9c23ae1 100644 --- a/src/MyCSharp.HttpUserAgentParser/HttpUserAgentInformation.cs +++ b/src/HttpUserAgentParser/HttpUserAgentInformation.cs @@ -59,7 +59,7 @@ private HttpUserAgentInformation(string userAgent, HttpUserAgentPlatformInformat /// Creates for a robot /// internal static HttpUserAgentInformation CreateForRobot(string userAgent, string robotName) - => new(userAgent, null, HttpUserAgentType.Robot, robotName, null, null); + => new(userAgent, platform: null, HttpUserAgentType.Robot, robotName, version: null, deviceName: null); /// /// Creates for a browser @@ -71,5 +71,5 @@ internal static HttpUserAgentInformation CreateForBrowser(string userAgent, Http /// Creates for an unknown agent type /// internal static HttpUserAgentInformation CreateForUnknown(string userAgent, HttpUserAgentPlatformInformation? platform, string? deviceName) - => new(userAgent, platform, HttpUserAgentType.Unknown, null, null, deviceName); + => new(userAgent, platform, HttpUserAgentType.Unknown, name: null, version: null, deviceName); } diff --git a/src/MyCSharp.HttpUserAgentParser/HttpUserAgentInformationExtensions.cs b/src/HttpUserAgentParser/HttpUserAgentInformationExtensions.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser/HttpUserAgentInformationExtensions.cs rename to src/HttpUserAgentParser/HttpUserAgentInformationExtensions.cs diff --git a/src/MyCSharp.HttpUserAgentParser/HttpUserAgentParser.cs b/src/HttpUserAgentParser/HttpUserAgentParser.cs similarity index 97% rename from src/MyCSharp.HttpUserAgentParser/HttpUserAgentParser.cs rename to src/HttpUserAgentParser/HttpUserAgentParser.cs index 04eb1ab..3e7dc18 100644 --- a/src/MyCSharp.HttpUserAgentParser/HttpUserAgentParser.cs +++ b/src/HttpUserAgentParser/HttpUserAgentParser.cs @@ -5,10 +5,13 @@ namespace MyCSharp.HttpUserAgentParser; +#pragma warning disable MA0049 // Type name should not match containing namespace + /// /// Parser logic for user agents /// public static class HttpUserAgentParser + { /// /// Parses given user agent diff --git a/src/MyCSharp.HttpUserAgentParser/MyCSharp.HttpUserAgentParser.csproj b/src/HttpUserAgentParser/HttpUserAgentParser.csproj similarity index 52% rename from src/MyCSharp.HttpUserAgentParser/MyCSharp.HttpUserAgentParser.csproj rename to src/HttpUserAgentParser/HttpUserAgentParser.csproj index 0180afe..dc30a64 100644 --- a/src/MyCSharp.HttpUserAgentParser/MyCSharp.HttpUserAgentParser.csproj +++ b/src/HttpUserAgentParser/HttpUserAgentParser.csproj @@ -20,21 +20,6 @@ - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - diff --git a/src/MyCSharp.HttpUserAgentParser/HttpUserAgentPlatformInformation.cs b/src/HttpUserAgentParser/HttpUserAgentPlatformInformation.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser/HttpUserAgentPlatformInformation.cs rename to src/HttpUserAgentParser/HttpUserAgentPlatformInformation.cs diff --git a/src/MyCSharp.HttpUserAgentParser/HttpUserAgentPlatformType.cs b/src/HttpUserAgentParser/HttpUserAgentPlatformType.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser/HttpUserAgentPlatformType.cs rename to src/HttpUserAgentParser/HttpUserAgentPlatformType.cs diff --git a/src/MyCSharp.HttpUserAgentParser/HttpUserAgentStatics.cs b/src/HttpUserAgentParser/HttpUserAgentStatics.cs similarity index 97% rename from src/MyCSharp.HttpUserAgentParser/HttpUserAgentStatics.cs rename to src/HttpUserAgentParser/HttpUserAgentStatics.cs index ae4208d..7f8c203 100644 --- a/src/MyCSharp.HttpUserAgentParser/HttpUserAgentStatics.cs +++ b/src/HttpUserAgentParser/HttpUserAgentStatics.cs @@ -17,7 +17,8 @@ public static class HttpUserAgentStatics /// /// Creates default platform mapping regex /// - private static Regex CreateDefaultPlatformRegex(string key) => new(Regex.Escape($"{key}"), DefaultPlatformsRegexFlags); + private static Regex CreateDefaultPlatformRegex(string key) => new(Regex.Escape($"{key}"), + DefaultPlatformsRegexFlags, matchTimeout: TimeSpan.FromMilliseconds(1000)); /// /// Platforms @@ -77,12 +78,12 @@ public static class HttpUserAgentStatics /// Creates default browser mapping regex /// private static Regex CreateDefaultBrowserRegex(string key) - => new($@"{key}.*?([0-9\.]+)", DefaultBrowserRegexFlags); + => new($@"{key}.*?([0-9\.]+)", DefaultBrowserRegexFlags, matchTimeout: TimeSpan.FromMilliseconds(1000)); /// /// Browsers /// - public static Dictionary Browsers = new() + public static readonly Dictionary Browsers = new() { { CreateDefaultBrowserRegex("OPR"), "Opera" }, { CreateDefaultBrowserRegex("Flock"), "Flock" }, @@ -124,7 +125,7 @@ private static Regex CreateDefaultBrowserRegex(string key) /// /// Mobiles /// - public static readonly Dictionary Mobiles = new() + public static readonly Dictionary Mobiles = new(StringComparer.InvariantCultureIgnoreCase) { // Legacy { "mobileexplorer", "Mobile Explorer" }, @@ -286,7 +287,7 @@ public static readonly (string Key, string Value)[] Robots = /// /// Tools /// - public static readonly Dictionary Tools = new() + public static readonly Dictionary Tools = new(StringComparer.OrdinalIgnoreCase) { { "curl", "curl" } }; diff --git a/src/MyCSharp.HttpUserAgentParser/HttpUserAgentType.cs b/src/HttpUserAgentParser/HttpUserAgentType.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser/HttpUserAgentType.cs rename to src/HttpUserAgentParser/HttpUserAgentType.cs diff --git a/src/MyCSharp.HttpUserAgentParser/LICENSE.txt b/src/HttpUserAgentParser/LICENSE.txt similarity index 100% rename from src/MyCSharp.HttpUserAgentParser/LICENSE.txt rename to src/HttpUserAgentParser/LICENSE.txt diff --git a/src/MyCSharp.HttpUserAgentParser/Providers/HttpUserAgentParserCachedProvider.cs b/src/HttpUserAgentParser/Providers/HttpUserAgentParserCachedProvider.cs similarity index 94% rename from src/MyCSharp.HttpUserAgentParser/Providers/HttpUserAgentParserCachedProvider.cs rename to src/HttpUserAgentParser/Providers/HttpUserAgentParserCachedProvider.cs index 3f776bf..cb6ec3a 100644 --- a/src/MyCSharp.HttpUserAgentParser/Providers/HttpUserAgentParserCachedProvider.cs +++ b/src/HttpUserAgentParser/Providers/HttpUserAgentParserCachedProvider.cs @@ -12,7 +12,7 @@ public class HttpUserAgentParserCachedProvider : IHttpUserAgentParserProvider /// /// internal cache /// - private readonly ConcurrentDictionary _cache = new(); + private readonly ConcurrentDictionary _cache = new(StringComparer.OrdinalIgnoreCase); /// /// Parses the user agent or uses the internal cached information diff --git a/src/MyCSharp.HttpUserAgentParser/Providers/HttpUserAgentParserDefaultProvider.cs b/src/HttpUserAgentParser/Providers/HttpUserAgentParserDefaultProvider.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser/Providers/HttpUserAgentParserDefaultProvider.cs rename to src/HttpUserAgentParser/Providers/HttpUserAgentParserDefaultProvider.cs diff --git a/src/MyCSharp.HttpUserAgentParser/Providers/IHttpUserAgentParserProvider.cs b/src/HttpUserAgentParser/Providers/IHttpUserAgentParserProvider.cs similarity index 100% rename from src/MyCSharp.HttpUserAgentParser/Providers/IHttpUserAgentParserProvider.cs rename to src/HttpUserAgentParser/Providers/IHttpUserAgentParserProvider.cs diff --git a/src/MyCSharp.HttpUserAgentParser/readme.md b/src/HttpUserAgentParser/readme.md similarity index 100% rename from src/MyCSharp.HttpUserAgentParser/readme.md rename to src/HttpUserAgentParser/readme.md diff --git a/src/MyCSharp.HttpUserAgentParser.AspNetCore/MyCSharp.HttpUserAgentParser.AspNetCore.csproj b/src/MyCSharp.HttpUserAgentParser.AspNetCore/MyCSharp.HttpUserAgentParser.AspNetCore.csproj deleted file mode 100644 index c51f1f3..0000000 --- a/src/MyCSharp.HttpUserAgentParser.AspNetCore/MyCSharp.HttpUserAgentParser.AspNetCore.csproj +++ /dev/null @@ -1,42 +0,0 @@ - - - - HTTP User Agent Parser Extensions for ASP.NET Core - HTTP User Agent Parser Extensions for ASP.NET Core - - - - true - readme.md - LICENSE.txt - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - - - - - - diff --git a/tests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests/DependencyInjection/HttpUserAgentParserServiceCollectionExtensionsTests.cs b/tests/HttpUserAgentParser.AspNetCore.UnitTests/DependencyInjection/HttpUserAgentParserServiceCollectionExtensionsTests.cs similarity index 100% rename from tests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests/DependencyInjection/HttpUserAgentParserServiceCollectionExtensionsTests.cs rename to tests/HttpUserAgentParser.AspNetCore.UnitTests/DependencyInjection/HttpUserAgentParserServiceCollectionExtensionsTests.cs diff --git a/tests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests/HttpContextTestHelpers.cs b/tests/HttpUserAgentParser.AspNetCore.UnitTests/HttpContextTestHelpers.cs similarity index 100% rename from tests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests/HttpContextTestHelpers.cs rename to tests/HttpUserAgentParser.AspNetCore.UnitTests/HttpContextTestHelpers.cs diff --git a/tests/HttpUserAgentParser.AspNetCore.UnitTests/HttpUserAgentParser.AspNetCore.UnitTests.csproj b/tests/HttpUserAgentParser.AspNetCore.UnitTests/HttpUserAgentParser.AspNetCore.UnitTests.csproj new file mode 100644 index 0000000..269119a --- /dev/null +++ b/tests/HttpUserAgentParser.AspNetCore.UnitTests/HttpUserAgentParser.AspNetCore.UnitTests.csproj @@ -0,0 +1,16 @@ + + + + Exe + + + + + + + + + + + + diff --git a/tests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests/HttpUserAgentParserAccessorTests.cs b/tests/HttpUserAgentParser.AspNetCore.UnitTests/HttpUserAgentParserAccessorTests.cs similarity index 100% rename from tests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests/HttpUserAgentParserAccessorTests.cs rename to tests/HttpUserAgentParser.AspNetCore.UnitTests/HttpUserAgentParserAccessorTests.cs diff --git a/tests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensionssTests.cs b/tests/HttpUserAgentParser.MemoryCache.UnitTests/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensionssTests.cs similarity index 100% rename from tests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensionssTests.cs rename to tests/HttpUserAgentParser.MemoryCache.UnitTests/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensionssTests.cs diff --git a/tests/HttpUserAgentParser.MemoryCache.UnitTests/HttpUserAgentParser.MemoryCache.UnitTests.csproj b/tests/HttpUserAgentParser.MemoryCache.UnitTests/HttpUserAgentParser.MemoryCache.UnitTests.csproj new file mode 100644 index 0000000..b68d12f --- /dev/null +++ b/tests/HttpUserAgentParser.MemoryCache.UnitTests/HttpUserAgentParser.MemoryCache.UnitTests.csproj @@ -0,0 +1,16 @@ + + + + Exe + + + + + + + + + + + + diff --git a/tests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests/HttpUserAgentParserMemoryCachedProviderOptionsTests.cs b/tests/HttpUserAgentParser.MemoryCache.UnitTests/HttpUserAgentParserMemoryCachedProviderOptionsTests.cs similarity index 100% rename from tests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests/HttpUserAgentParserMemoryCachedProviderOptionsTests.cs rename to tests/HttpUserAgentParser.MemoryCache.UnitTests/HttpUserAgentParserMemoryCachedProviderOptionsTests.cs diff --git a/tests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests/HttpUserAgentParserMemoryCachedProviderTests.cs b/tests/HttpUserAgentParser.MemoryCache.UnitTests/HttpUserAgentParserMemoryCachedProviderTests.cs similarity index 100% rename from tests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests/HttpUserAgentParserMemoryCachedProviderTests.cs rename to tests/HttpUserAgentParser.MemoryCache.UnitTests/HttpUserAgentParserMemoryCachedProviderTests.cs diff --git a/tests/HttpUserAgentParser.TestHelpers/HttpUserAgentParser.TestHelpers.csproj b/tests/HttpUserAgentParser.TestHelpers/HttpUserAgentParser.TestHelpers.csproj new file mode 100644 index 0000000..42cceb3 --- /dev/null +++ b/tests/HttpUserAgentParser.TestHelpers/HttpUserAgentParser.TestHelpers.csproj @@ -0,0 +1,7 @@ + + + + false + + + diff --git a/tests/MyCSharp.HttpUserAgentParser.UnitTests/DependencyInjection/HttpUserAgentParserDependencyInjectionOptions.cs b/tests/HttpUserAgentParser.UnitTests/DependencyInjection/HttpUserAgentParserDependencyInjectionOptions.cs similarity index 100% rename from tests/MyCSharp.HttpUserAgentParser.UnitTests/DependencyInjection/HttpUserAgentParserDependencyInjectionOptions.cs rename to tests/HttpUserAgentParser.UnitTests/DependencyInjection/HttpUserAgentParserDependencyInjectionOptions.cs diff --git a/tests/MyCSharp.HttpUserAgentParser.UnitTests/DependencyInjection/HttpUserAgentParserServiceCollectionExtensionsTests.cs b/tests/HttpUserAgentParser.UnitTests/DependencyInjection/HttpUserAgentParserServiceCollectionExtensionsTests.cs similarity index 97% rename from tests/MyCSharp.HttpUserAgentParser.UnitTests/DependencyInjection/HttpUserAgentParserServiceCollectionExtensionsTests.cs rename to tests/HttpUserAgentParser.UnitTests/DependencyInjection/HttpUserAgentParserServiceCollectionExtensionsTests.cs index c7c97dd..3afec1f 100644 --- a/tests/MyCSharp.HttpUserAgentParser.UnitTests/DependencyInjection/HttpUserAgentParserServiceCollectionExtensionsTests.cs +++ b/tests/HttpUserAgentParser.UnitTests/DependencyInjection/HttpUserAgentParserServiceCollectionExtensionsTests.cs @@ -11,7 +11,7 @@ public class HttpUserAgentParserMemoryCacheServiceCollectionExtensions { public class TestHttpUserAgentParserProvider : IHttpUserAgentParserProvider { - public HttpUserAgentInformation Parse(string userAgent) => throw new System.NotImplementedException(); + public HttpUserAgentInformation Parse(string userAgent) => throw new NotSupportedException(); } [Fact] diff --git a/tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentInformationExtensionsTests.cs b/tests/HttpUserAgentParser.UnitTests/HttpUserAgentInformationExtensionsTests.cs similarity index 100% rename from tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentInformationExtensionsTests.cs rename to tests/HttpUserAgentParser.UnitTests/HttpUserAgentInformationExtensionsTests.cs diff --git a/tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentInformationTests.cs b/tests/HttpUserAgentParser.UnitTests/HttpUserAgentInformationTests.cs similarity index 83% rename from tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentInformationTests.cs rename to tests/HttpUserAgentParser.UnitTests/HttpUserAgentInformationTests.cs index 4022d27..13a446a 100644 --- a/tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentInformationTests.cs +++ b/tests/HttpUserAgentParser.UnitTests/HttpUserAgentInformationTests.cs @@ -5,7 +5,7 @@ namespace MyCSharp.HttpUserAgentParser.UnitTests; -public class HttpUserAgentInformationTests +public partial class HttpUserAgentInformationTests { [Theory] [InlineData("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.62")] @@ -35,8 +35,7 @@ public void CreateForRobot(string userAgent) [InlineData("Mozilla/5.0 (Linux; Android 10; HD1913) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36 EdgA/46.3.4.5155")] public void CreateForBrowser(string userAgent) { - HttpUserAgentPlatformInformation platformInformation = - new(new Regex(""), "Android", HttpUserAgentPlatformType.Android); + HttpUserAgentPlatformInformation platformInformation = new(TextRegex(), "Android", HttpUserAgentPlatformType.Android); HttpUserAgentInformation ua = HttpUserAgentInformation.CreateForBrowser(userAgent, platformInformation, "Edge", "46.3.4.5155", "Android"); @@ -53,11 +52,10 @@ public void CreateForBrowser(string userAgent) [InlineData("Invalid user agent")] public void CreateForUnknown(string userAgent) { - HttpUserAgentPlatformInformation platformInformation = - new(new Regex(""), "Batman", HttpUserAgentPlatformType.Linux); + HttpUserAgentPlatformInformation platformInformation = new(TextRegex(), "Batman", HttpUserAgentPlatformType.Linux); HttpUserAgentInformation ua = - HttpUserAgentInformation.CreateForUnknown(userAgent, platformInformation, null); + HttpUserAgentInformation.CreateForUnknown(userAgent, platformInformation, deviceName: null); Assert.Equal(userAgent, ua.UserAgent); Assert.Equal(HttpUserAgentType.Unknown, ua.Type); @@ -66,4 +64,7 @@ public void CreateForUnknown(string userAgent) Assert.Null(ua.Version); Assert.Null(ua.MobileDeviceType); } + + [GeneratedRegex("", RegexOptions.None, matchTimeoutMilliseconds: 1000)] + private static partial Regex TextRegex(); } diff --git a/tests/HttpUserAgentParser.UnitTests/HttpUserAgentParser.UnitTests.csproj b/tests/HttpUserAgentParser.UnitTests/HttpUserAgentParser.UnitTests.csproj new file mode 100644 index 0000000..cdf4e3d --- /dev/null +++ b/tests/HttpUserAgentParser.UnitTests/HttpUserAgentParser.UnitTests.csproj @@ -0,0 +1,15 @@ + + + + Exe + + + + + + + + + + + diff --git a/tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentParserTests.cs b/tests/HttpUserAgentParser.UnitTests/HttpUserAgentParserTests.cs similarity index 100% rename from tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentParserTests.cs rename to tests/HttpUserAgentParser.UnitTests/HttpUserAgentParserTests.cs diff --git a/tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentPlatformInformationTests.cs b/tests/HttpUserAgentParser.UnitTests/HttpUserAgentPlatformInformationTests.cs similarity index 90% rename from tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentPlatformInformationTests.cs rename to tests/HttpUserAgentParser.UnitTests/HttpUserAgentPlatformInformationTests.cs index 613369d..274e127 100644 --- a/tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentPlatformInformationTests.cs +++ b/tests/HttpUserAgentParser.UnitTests/HttpUserAgentPlatformInformationTests.cs @@ -21,6 +21,6 @@ public void Ctor(string name, HttpUserAgentPlatformType platform) Assert.Equal(platform, info.PlatformType); } - [GeneratedRegex("")] + [GeneratedRegex("", RegexOptions.None, matchTimeoutMilliseconds: 1000)] private static partial Regex EmptyRegex(); } diff --git a/tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentPlatformTypeTests.cs b/tests/HttpUserAgentParser.UnitTests/HttpUserAgentPlatformTypeTests.cs similarity index 100% rename from tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentPlatformTypeTests.cs rename to tests/HttpUserAgentParser.UnitTests/HttpUserAgentPlatformTypeTests.cs diff --git a/tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentTypeTests.cs b/tests/HttpUserAgentParser.UnitTests/HttpUserAgentTypeTests.cs similarity index 100% rename from tests/MyCSharp.HttpUserAgentParser.UnitTests/HttpUserAgentTypeTests.cs rename to tests/HttpUserAgentParser.UnitTests/HttpUserAgentTypeTests.cs diff --git a/tests/MyCSharp.HttpUserAgentParser.UnitTests/Providers/HttpUserAgentParserCachedProviderTests.cs b/tests/HttpUserAgentParser.UnitTests/Providers/HttpUserAgentParserCachedProviderTests.cs similarity index 100% rename from tests/MyCSharp.HttpUserAgentParser.UnitTests/Providers/HttpUserAgentParserCachedProviderTests.cs rename to tests/HttpUserAgentParser.UnitTests/Providers/HttpUserAgentParserCachedProviderTests.cs diff --git a/tests/MyCSharp.HttpUserAgentParser.UnitTests/Providers/HttpUserAgentParserDefaultProviderTests.cs b/tests/HttpUserAgentParser.UnitTests/Providers/HttpUserAgentParserDefaultProviderTests.cs similarity index 100% rename from tests/MyCSharp.HttpUserAgentParser.UnitTests/Providers/HttpUserAgentParserDefaultProviderTests.cs rename to tests/HttpUserAgentParser.UnitTests/Providers/HttpUserAgentParserDefaultProviderTests.cs diff --git a/tests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests.csproj b/tests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests.csproj deleted file mode 100644 index 3d4c3ed..0000000 --- a/tests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests/MyCSharp.HttpUserAgentParser.AspNetCore.UnitTests.csproj +++ /dev/null @@ -1,45 +0,0 @@ - - - - Exe - - - - - - - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - diff --git a/tests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests.csproj b/tests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests.csproj deleted file mode 100644 index 05efe7c..0000000 --- a/tests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests/MyCSharp.HttpUserAgentParser.MemoryCache.UnitTests.csproj +++ /dev/null @@ -1,44 +0,0 @@ - - - - Exe - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - diff --git a/tests/MyCSharp.HttpUserAgentParser.TestHelpers/MyCSharp.HttpUserAgentParser.TestHelpers.csproj b/tests/MyCSharp.HttpUserAgentParser.TestHelpers/MyCSharp.HttpUserAgentParser.TestHelpers.csproj deleted file mode 100644 index dd0a1c7..0000000 --- a/tests/MyCSharp.HttpUserAgentParser.TestHelpers/MyCSharp.HttpUserAgentParser.TestHelpers.csproj +++ /dev/null @@ -1,26 +0,0 @@ - - - - false - - - - - - - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - - diff --git a/tests/MyCSharp.HttpUserAgentParser.UnitTests/MyCSharp.HttpUserAgentParser.UnitTests.csproj b/tests/MyCSharp.HttpUserAgentParser.UnitTests/MyCSharp.HttpUserAgentParser.UnitTests.csproj deleted file mode 100644 index 24f53dd..0000000 --- a/tests/MyCSharp.HttpUserAgentParser.UnitTests/MyCSharp.HttpUserAgentParser.UnitTests.csproj +++ /dev/null @@ -1,44 +0,0 @@ - - - - Exe - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - all - runtime; build; native; contentfiles; analyzers - - - - - - - - diff --git a/version.json b/version.json index 8417f92..de475b0 100644 --- a/version.json +++ b/version.json @@ -1,19 +1,20 @@ { - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "3.0", - "nugetPackageVersion": { - "semVer": 1 // optional. Set to either 1 or 2 to control how the NuGet package version string is generated. Default is 1. - }, - "publicReleaseRefSpec": [ - "^refs/heads/main$" // we release out of main - ], - "cloudBuild": { - "buildNumber": { - "enabled": true - } - }, - "release": { - "versionIncrement": "build", - "firstUnstableTag": "preview" + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "3.0", + "nugetPackageVersion": { + "semVer": 1 // optional. Set to either 1 or 2 to control how the NuGet package version string is generated. Default is 1. + }, + "publicReleaseRefSpec": [ + "^refs/heads/main$", // we release out of main + "^refs/tags/v\\d+\\.\\d+" // we release on tags like v1.0 or v2.0.0 via GitHub Release + ], + "cloudBuild": { + "buildNumber": { + "enabled": true } + }, + "release": { + "versionIncrement": "build", + "firstUnstableTag": "preview" + } } From eb49aa7450bdceb129b1d41ece7f9e3d22409417 Mon Sep 17 00:00:00 2001 From: Benjamin Abt Date: Sat, 12 Apr 2025 12:42:11 +0200 Subject: [PATCH 2/2] Refactor benchmarks and improve code clarity - Updated `LibraryComparisonBenchmarks.cs` to use a record type for `TestData`, enhancing readability and modernizing the code structure. - Added summary comments in `HttpUserAgentParserMemoryCacheServiceCollectionExtensions.cs` and improved method documentation for clarity. - Streamlined constructor initialization in `HttpUserAgentParserMemoryCachedProviderOptions.cs`, removing unnecessary keywords while preserving functionality. --- .../LibraryComparisonBenchmarks.cs | 123 +++++++++--------- ...rMemoryCacheServiceCollectionExtensions.cs | 31 +++-- ...rAgentParserMemoryCachedProviderOptions.cs | 4 +- 3 files changed, 78 insertions(+), 80 deletions(-) diff --git a/perf/HttpUserAgentParser.Benchmarks/LibraryComparison/LibraryComparisonBenchmarks.cs b/perf/HttpUserAgentParser.Benchmarks/LibraryComparison/LibraryComparisonBenchmarks.cs index b6e6c86..460d2ee 100644 --- a/perf/HttpUserAgentParser.Benchmarks/LibraryComparison/LibraryComparisonBenchmarks.cs +++ b/perf/HttpUserAgentParser.Benchmarks/LibraryComparison/LibraryComparisonBenchmarks.cs @@ -7,80 +7,79 @@ using DeviceDetectorNET; using MyCSharp.HttpUserAgentParser.Providers; -namespace MyCSharp.HttpUserAgentParser.Benchmarks.LibraryComparison +namespace MyCSharp.HttpUserAgentParser.Benchmarks.LibraryComparison; + +[ShortRunJob] +[MemoryDiagnoser] +[CategoriesColumn] +[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] +public class LibraryComparisonBenchmarks { - [ShortRunJob] - [MemoryDiagnoser] - [CategoriesColumn] - [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] - public class LibraryComparisonBenchmarks + public record TestData(string Label, string UserAgent) { - public record TestData(string Label, string UserAgent) - { - public override string ToString() => Label; - } + public override string ToString() => Label; + } - [ParamsSource(nameof(GetTestUserAgents))] - public TestData Data { get; set; } + [ParamsSource(nameof(GetTestUserAgents))] + public TestData Data { get; set; } - public IEnumerable GetTestUserAgents() - { - yield return new("Chrome Win10", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"); - yield return new("Google-Bot", "APIs-Google (+https://developers.google.com/webmasters/APIs-Google.html)"); - } + public IEnumerable GetTestUserAgents() + { + yield return new("Chrome Win10", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"); + yield return new("Google-Bot", "APIs-Google (+https://developers.google.com/webmasters/APIs-Google.html)"); + } - [Benchmark(Baseline = true, Description = "MyCSharp")] - [BenchmarkCategory("Basic")] - public HttpUserAgentInformation MyCSharpBasic() - { - HttpUserAgentInformation info = HttpUserAgentParser.Parse(Data.UserAgent); - return info; - } + [Benchmark(Baseline = true, Description = "MyCSharp")] + [BenchmarkCategory("Basic")] + public HttpUserAgentInformation MyCSharpBasic() + { + HttpUserAgentInformation info = HttpUserAgentParser.Parse(Data.UserAgent); + return info; + } - private static readonly HttpUserAgentParserCachedProvider s_myCSharpCachedProvider = new(); + private static readonly HttpUserAgentParserCachedProvider s_myCSharpCachedProvider = new(); - [Benchmark(Baseline = true, Description = "MyCSharp")] - [BenchmarkCategory("Cached")] - public HttpUserAgentInformation MyCSharpCached() - { - return s_myCSharpCachedProvider.Parse(Data.UserAgent); - } + [Benchmark(Baseline = true, Description = "MyCSharp")] + [BenchmarkCategory("Cached")] + public HttpUserAgentInformation MyCSharpCached() + { + return s_myCSharpCachedProvider.Parse(Data.UserAgent); + } - [Benchmark(Description = "UAParser")] - [BenchmarkCategory("Basic")] - public UAParser.ClientInfo UAParserBasic() - { - UAParser.ClientInfo info = UAParser.Parser.GetDefault().Parse(Data.UserAgent); - return info; - } + [Benchmark(Description = "UAParser")] + [BenchmarkCategory("Basic")] + public UAParser.ClientInfo UAParserBasic() + { + UAParser.ClientInfo info = UAParser.Parser.GetDefault().Parse(Data.UserAgent); + return info; + } - private static readonly UAParser.Parser s_uaParser = UAParser.Parser.GetDefault(new UAParser.ParserOptions { UseCompiledRegex = true }); + private static readonly UAParser.Parser s_uaParser = UAParser.Parser.GetDefault(new UAParser.ParserOptions { UseCompiledRegex = true }); - [Benchmark(Description = "UAParser")] - [BenchmarkCategory("Cached")] - public UAParser.ClientInfo UAParserCached() - { - UAParser.ClientInfo info = s_uaParser.Parse(Data.UserAgent); - return info; - } + [Benchmark(Description = "UAParser")] + [BenchmarkCategory("Cached")] + public UAParser.ClientInfo UAParserCached() + { + UAParser.ClientInfo info = s_uaParser.Parse(Data.UserAgent); + return info; + } - [Benchmark(Description = "DeviceDetector.NET")] - [BenchmarkCategory("Basic")] - public object DeviceDetectorNETBasic() - { - DeviceDetector dd = new(Data.UserAgent); - dd.Parse(); + [Benchmark(Description = "DeviceDetector.NET")] + [BenchmarkCategory("Basic")] + public object DeviceDetectorNETBasic() + { + DeviceDetector dd = new(Data.UserAgent); + dd.Parse(); - var info = new - { - Client = dd.GetClient(), - OS = dd.GetOs(), - Device = dd.GetDeviceName(), - Brand = dd.GetBrandName(), - Model = dd.GetModel() - }; + var info = new + { + Client = dd.GetClient(), + OS = dd.GetOs(), + Device = dd.GetDeviceName(), + Brand = dd.GetBrandName(), + Model = dd.GetModel() + }; - return info; - } + return info; } } diff --git a/src/HttpUserAgentParser.MemoryCache/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensions.cs b/src/HttpUserAgentParser.MemoryCache/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensions.cs index ba4e4d6..28f3893 100644 --- a/src/HttpUserAgentParser.MemoryCache/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensions.cs +++ b/src/HttpUserAgentParser.MemoryCache/DependencyInjection/HttpUserAgentParserMemoryCacheServiceCollectionExtensions.cs @@ -4,27 +4,26 @@ using MyCSharp.HttpUserAgentParser.DependencyInjection; using MyCSharp.HttpUserAgentParser.Providers; -namespace MyCSharp.HttpUserAgentParser.MemoryCache.DependencyInjection +namespace MyCSharp.HttpUserAgentParser.MemoryCache.DependencyInjection; + +/// +/// Dependency injection extensions for IMemoryCache +/// +public static class HttpUserAgentParserMemoryCacheServiceCollectionExtensions { /// - /// Dependency injection extensions for IMemoryCache + /// Registers as singleton to /// - public static class HttpUserAgentParserMemoryCacheServiceCollectionExtensions + public static HttpUserAgentParserDependencyInjectionOptions AddHttpUserAgentMemoryCachedParser( + this IServiceCollection services, Action? options = null) { - /// - /// Registers as singleton to - /// - public static HttpUserAgentParserDependencyInjectionOptions AddHttpUserAgentMemoryCachedParser( - this IServiceCollection services, Action? options = null) - { - HttpUserAgentParserMemoryCachedProviderOptions providerOptions = new(); - options?.Invoke(providerOptions); + HttpUserAgentParserMemoryCachedProviderOptions providerOptions = new(); + options?.Invoke(providerOptions); - // register options - services.AddSingleton(providerOptions); + // register options + services.AddSingleton(providerOptions); - // register cache provider - return services.AddHttpUserAgentParser(); - } + // register cache provider + return services.AddHttpUserAgentParser(); } } diff --git a/src/HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProviderOptions.cs b/src/HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProviderOptions.cs index 9baf223..1b2115b 100644 --- a/src/HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProviderOptions.cs +++ b/src/HttpUserAgentParser.MemoryCache/HttpUserAgentParserMemoryCachedProviderOptions.cs @@ -41,13 +41,13 @@ public HttpUserAgentParserMemoryCachedProviderOptions(MemoryCacheEntryOptions ca public HttpUserAgentParserMemoryCachedProviderOptions( MemoryCacheOptions? cacheOptions = null, MemoryCacheEntryOptions? cacheEntryOptions = null) { - this.CacheEntryOptions = cacheEntryOptions ?? new MemoryCacheEntryOptions + CacheEntryOptions = cacheEntryOptions ?? new MemoryCacheEntryOptions { // defaults SlidingExpiration = TimeSpan.FromDays(1) }; - this.CacheOptions = cacheOptions ?? new MemoryCacheOptions + CacheOptions = cacheOptions ?? new MemoryCacheOptions { // defaults SizeLimit = 256