From 55ea945e524bb0ef83da1c235316639e145a35c6 Mon Sep 17 00:00:00 2001 From: David Kallesen Date: Thu, 10 Oct 2024 23:48:17 +0200 Subject: [PATCH 1/7] feat: update coding-rules --- .editorconfig | 40 ++++++++++++++++++- Directory.Build.props | 2 +- sample/.editorconfig | 5 +++ .../.editorconfig | 25 ++++++++++++ sample/Demo.Atc.Dotnet.Cli/.editorconfig | 25 ++++++++++++ src/Directory.Build.props | 2 +- test/.editorconfig | 2 +- .../BlazorServerApp1/.editorconfig | 14 ++++++- .../.editorconfig | 14 ++++++- .../BlazorWebAssemblyApp1/.editorconfig | 14 ++++++- .../.editorconfig | 14 ++++++- .../CliApp1/.editorconfig | 25 ++++++++++++ .../WebApi1/.editorconfig | 33 ++++++++++++++- .../WpfApp1/.editorconfig | 6 ++- test/Directory.Build.props | 2 +- 15 files changed, 205 insertions(+), 18 deletions(-) create mode 100644 sample/Demo.Atc.Console.Spectre.Cli/.editorconfig create mode 100644 sample/Demo.Atc.Dotnet.Cli/.editorconfig create mode 100644 test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/CliApp1/.editorconfig diff --git a/.editorconfig b/.editorconfig index 9ac83152..46c2f8de 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,6 +1,6 @@ # ATC coding rules - https://github.com/atc-net/atc-coding-rules -# Version: 1.0.0 -# Updated: 25-09-2023 +# Version: 1.0.1 +# Updated: 03-06-2024 # Location: Root # Distribution: DotNet8 # Inspired by: https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/code-style-rule-options @@ -464,10 +464,46 @@ dotnet_diagnostic.MA0048.severity = error # https://github.com/atc-net dotnet_diagnostic.CA1014.severity = none # https://github.com/atc-net/atc-coding-rules/blob/main/documentation/CodeAnalyzersRules/MicrosoftCodeAnalysis/CA1014.md dotnet_diagnostic.CA1068.severity = error # https://github.com/atc-net/atc-coding-rules/blob/main/documentation/CodeAnalyzersRules/MicrosoftCodeAnalysis/CA1068.md dotnet_diagnostic.CA1305.severity = error +dotnet_diagnostic.CA1308.severity = suggestion # Normalize strings to uppercase +dotnet_diagnostic.CA1510.severity = suggestion # Use ArgumentNullException throw helper +dotnet_diagnostic.CA1511.severity = suggestion # Use ArgumentException throw helper +dotnet_diagnostic.CA1512.severity = suggestion # Use ArgumentOutOfRangeException throw helper +dotnet_diagnostic.CA1513.severity = suggestion # Use ObjectDisposedException throw helper +dotnet_diagnostic.CA1514.severity = error # Avoid redundant length argument dotnet_diagnostic.CA1707.severity = error # https://github.com/atc-net/atc-coding-rules/blob/main/documentation/CodeAnalyzersRules/MicrosoftCodeAnalysis/CA1707.md dotnet_diagnostic.CA1812.severity = none dotnet_diagnostic.CA1822.severity = suggestion +dotnet_diagnostic.CA1849.severity = error # Call async methods when in an async method +dotnet_diagnostic.CA1854.severity = suggestion # Prefer the 'IDictionary.TryGetValue(TKey, out TValue)' method +dotnet_diagnostic.CA1855.severity = suggestion # Prefer 'Clear' over 'Fill' +dotnet_diagnostic.CA1856.severity = error # Incorrect usage of ConstantExpected attribute +dotnet_diagnostic.CA1857.severity = suggestion # A constant is expected for the parameter +dotnet_diagnostic.CA1858.severity = suggestion # Use 'StartsWith' instead of 'IndexOf' +dotnet_diagnostic.CA1859.severity = suggestion # Use concrete types when possible for improved performance +dotnet_diagnostic.CA1860.severity = suggestion # Avoid using 'Enumerable.Any()' extension method +dotnet_diagnostic.CA1861.severity = suggestion # Avoid constant arrays as arguments +dotnet_diagnostic.CA1862.severity = error # Use the 'StringComparison' method overloads to perform case-insensitive string comparisons +dotnet_diagnostic.CA1863.severity = suggestion # Use 'CompositeFormat' +dotnet_diagnostic.CA1864.severity = suggestion # Prefer the 'IDictionary.TryAdd(TKey, TValue)' method +dotnet_diagnostic.CA1865.severity = suggestion # Use char overload +dotnet_diagnostic.CA1866.severity = suggestion # Use char overload +dotnet_diagnostic.CA1867.severity = suggestion # Use char overload +dotnet_diagnostic.CA1868.severity = suggestion # Unnecessary call to 'Contains(item)' +dotnet_diagnostic.CA1869.severity = suggestion # Cache and reuse 'JsonSerializerOptions' instances +dotnet_diagnostic.CA1870.severity = suggestion # Use a cached 'SearchValues' instance dotnet_diagnostic.CA2007.severity = suggestion # https://github.com/atc-net/atc-coding-rules/blob/main/documentation/CodeAnalyzersRules/MicrosoftCodeAnalysis/CA2007.md +dotnet_diagnostic.CA2017.severity = error # Parameter count mismatch +dotnet_diagnostic.CA2018.severity = error # The count argument to Buffer.BlockCopy should specify the number of bytes to copy +dotnet_diagnostic.CA2019.severity = error # ThreadStatic fields should not use inline initialization +dotnet_diagnostic.CA2021.severity = error # Don't call Enumerable.Cast or Enumerable.OfType with incompatible types +dotnet_diagnostic.CA2250.severity = suggestion # Use ThrowIfCancellationRequested +dotnet_diagnostic.CA2252.severity = suggestion # Opt-in to preview features should be used with caution +dotnet_diagnostic.CA2253.severity = error # Named placeholders should not be numeric values +dotnet_diagnostic.CA2254.severity = suggestion # Template should be a static expression +dotnet_diagnostic.CA2255.severity = suggestion # The ModuleInitializer attribute should not be used in libraries +dotnet_diagnostic.CA2259.severity = error # Ensure ThreadStatic is only used with static fields +dotnet_diagnostic.CA2260.severity = error # Implement generic math interfaces correctly +dotnet_diagnostic.CA2261.severity = error # Do not use ConfigureAwaitOptions.SuppressThrowing with Task dotnet_diagnostic.IDE0005.severity = warning # https://github.com/atc-net/atc-coding-rules/blob/main/documentation/CodeAnalyzersRules/MicrosoftCodeAnalysis/IDE0005.md dotnet_diagnostic.IDE0058.severity = none # https://github.com/atc-net/atc-coding-rules/blob/main/documentation/CodeAnalyzersRules/MicrosoftCodeAnalysis/IDE0058.md diff --git a/Directory.Build.props b/Directory.Build.props index 5818e300..38691e1c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -43,7 +43,7 @@ - + diff --git a/sample/.editorconfig b/sample/.editorconfig index 016082b3..2598ce6a 100644 --- a/sample/.editorconfig +++ b/sample/.editorconfig @@ -41,6 +41,11 @@ # StyleCop # https://github.com/DotNetAnalyzers/StyleCopAnalyzers +# SonarAnalyzer.CSharp +# https://rules.sonarsource.com/csharp + +dotnet_diagnostic.S1075.severity = none # Refactor your code not to use hardcoded absolute paths or URIs + ########################################## # Custom - Code Analyzers Rules diff --git a/sample/Demo.Atc.Console.Spectre.Cli/.editorconfig b/sample/Demo.Atc.Console.Spectre.Cli/.editorconfig new file mode 100644 index 00000000..a9ab1446 --- /dev/null +++ b/sample/Demo.Atc.Console.Spectre.Cli/.editorconfig @@ -0,0 +1,25 @@ +# ATC coding rules - https://github.com/atc-net/atc-coding-rules +# Version: 1.0.0 +# Updated: 11-04-2024 +# Location: cli +# Distribution: Frameworks + +########################################## +# Code Analyzers Rules +########################################## +[*.{cs}] + +dotnet_diagnostic.CA1031.severity = none # Do not catch general exception types +dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters +dotnet_diagnostic.CA1819.severity = none # Properties should not return arrays +dotnet_diagnostic.CA1848.severity = none # Use the LoggerMessage delegates +dotnet_diagnostic.CA2000.severity = none # Dispose objects before losing scope +dotnet_diagnostic.CA2254.severity = none # Template should be a static expression + +dotnet_diagnostic.MA0076.severity = none # Do not use implicit culture-sensitive ToString in interpolated strings + +dotnet_diagnostic.S2629.severity = none # Don't use string interpolation in logging message templates. + +########################################## +# Custom - Code Analyzers Rules +########################################## \ No newline at end of file diff --git a/sample/Demo.Atc.Dotnet.Cli/.editorconfig b/sample/Demo.Atc.Dotnet.Cli/.editorconfig new file mode 100644 index 00000000..a9ab1446 --- /dev/null +++ b/sample/Demo.Atc.Dotnet.Cli/.editorconfig @@ -0,0 +1,25 @@ +# ATC coding rules - https://github.com/atc-net/atc-coding-rules +# Version: 1.0.0 +# Updated: 11-04-2024 +# Location: cli +# Distribution: Frameworks + +########################################## +# Code Analyzers Rules +########################################## +[*.{cs}] + +dotnet_diagnostic.CA1031.severity = none # Do not catch general exception types +dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters +dotnet_diagnostic.CA1819.severity = none # Properties should not return arrays +dotnet_diagnostic.CA1848.severity = none # Use the LoggerMessage delegates +dotnet_diagnostic.CA2000.severity = none # Dispose objects before losing scope +dotnet_diagnostic.CA2254.severity = none # Template should be a static expression + +dotnet_diagnostic.MA0076.severity = none # Do not use implicit culture-sensitive ToString in interpolated strings + +dotnet_diagnostic.S2629.severity = none # Don't use string interpolation in logging message templates. + +########################################## +# Custom - Code Analyzers Rules +########################################## \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 96a2d6a7..a5c611b0 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -54,7 +54,7 @@ - + \ No newline at end of file diff --git a/test/.editorconfig b/test/.editorconfig index 39474412..ecca8022 100644 --- a/test/.editorconfig +++ b/test/.editorconfig @@ -22,7 +22,7 @@ # https://www.meziantou.net/enforcing-asynchronous-code-good-practices-using-a-roslyn-analyzer.htm dotnet_diagnostic.MA0004.severity = none # https://github.com/atc-net/atc-coding-rules/blob/main/documentation/CodeAnalyzersRules/Meziantou/MA0004.md dotnet_diagnostic.MA0016.severity = none # https://github.com/atc-net/atc-coding-rules/blob/main/documentation/CodeAnalyzersRules/Meziantou/MA0016.md - +dotnet_diagnostic.MA0051.severity = none # Method Length # Microsoft - Code Analysis # https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ diff --git a/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorServerApp1/.editorconfig b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorServerApp1/.editorconfig index c96bba9d..f731f937 100644 --- a/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorServerApp1/.editorconfig +++ b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorServerApp1/.editorconfig @@ -1,6 +1,6 @@ # ATC coding rules - https://github.com/atc-net/atc-coding-rules -# Version: 1.0.0 -# Updated: 27-03-2024 +# Version: 1.0.1 +# Updated: 03-06-2024 # Location: blazor # Distribution: Frameworks @@ -9,8 +9,18 @@ ########################################## [*.{cs}] +dotnet_diagnostic.ASP0006.severity = suggestion # Do not use non-literal sequence numbers - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0006?view=aspnetcore-8.0 + +dotnet_diagnostic.BL0001.severity = error # Component parameter should have public setters - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0001?view=aspnetcore-8.0 +dotnet_diagnostic.BL0002.severity = error # Component has multiple CaptureUnmatchedValues parameters - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0002?view=aspnetcore-8.0 +dotnet_diagnostic.BL0003.severity = error # Component parameter with CaptureUnmatchedValues has the wrong type - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0003?view=aspnetcore-8.0 +dotnet_diagnostic.BL0004.severity = error # Component parameter should be public - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0004?view=aspnetcore-8.0 +dotnet_diagnostic.BL0005.severity = error # Component parameter should not be set outside of its component - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0005?view=aspnetcore-8.0 +dotnet_diagnostic.BL0006.severity = warning # Do not use RenderTree types - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0006?view=aspnetcore-8.0 + dotnet_diagnostic.MA0048.severity = none # To support code-behind [component].razor.cs files / Inherit from ComponentBase - File will not match type name. + ########################################## # Custom - Code Analyzers Rules ########################################## \ No newline at end of file diff --git a/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorWebAssemblyApp1/BlazorWebAssemblyApp1.Client/.editorconfig b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorWebAssemblyApp1/BlazorWebAssemblyApp1.Client/.editorconfig index c96bba9d..f731f937 100644 --- a/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorWebAssemblyApp1/BlazorWebAssemblyApp1.Client/.editorconfig +++ b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorWebAssemblyApp1/BlazorWebAssemblyApp1.Client/.editorconfig @@ -1,6 +1,6 @@ # ATC coding rules - https://github.com/atc-net/atc-coding-rules -# Version: 1.0.0 -# Updated: 27-03-2024 +# Version: 1.0.1 +# Updated: 03-06-2024 # Location: blazor # Distribution: Frameworks @@ -9,8 +9,18 @@ ########################################## [*.{cs}] +dotnet_diagnostic.ASP0006.severity = suggestion # Do not use non-literal sequence numbers - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0006?view=aspnetcore-8.0 + +dotnet_diagnostic.BL0001.severity = error # Component parameter should have public setters - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0001?view=aspnetcore-8.0 +dotnet_diagnostic.BL0002.severity = error # Component has multiple CaptureUnmatchedValues parameters - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0002?view=aspnetcore-8.0 +dotnet_diagnostic.BL0003.severity = error # Component parameter with CaptureUnmatchedValues has the wrong type - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0003?view=aspnetcore-8.0 +dotnet_diagnostic.BL0004.severity = error # Component parameter should be public - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0004?view=aspnetcore-8.0 +dotnet_diagnostic.BL0005.severity = error # Component parameter should not be set outside of its component - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0005?view=aspnetcore-8.0 +dotnet_diagnostic.BL0006.severity = warning # Do not use RenderTree types - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0006?view=aspnetcore-8.0 + dotnet_diagnostic.MA0048.severity = none # To support code-behind [component].razor.cs files / Inherit from ComponentBase - File will not match type name. + ########################################## # Custom - Code Analyzers Rules ########################################## \ No newline at end of file diff --git a/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorWebAssemblyApp1/BlazorWebAssemblyApp1/.editorconfig b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorWebAssemblyApp1/BlazorWebAssemblyApp1/.editorconfig index c96bba9d..f731f937 100644 --- a/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorWebAssemblyApp1/BlazorWebAssemblyApp1/.editorconfig +++ b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorWebAssemblyApp1/BlazorWebAssemblyApp1/.editorconfig @@ -1,6 +1,6 @@ # ATC coding rules - https://github.com/atc-net/atc-coding-rules -# Version: 1.0.0 -# Updated: 27-03-2024 +# Version: 1.0.1 +# Updated: 03-06-2024 # Location: blazor # Distribution: Frameworks @@ -9,8 +9,18 @@ ########################################## [*.{cs}] +dotnet_diagnostic.ASP0006.severity = suggestion # Do not use non-literal sequence numbers - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0006?view=aspnetcore-8.0 + +dotnet_diagnostic.BL0001.severity = error # Component parameter should have public setters - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0001?view=aspnetcore-8.0 +dotnet_diagnostic.BL0002.severity = error # Component has multiple CaptureUnmatchedValues parameters - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0002?view=aspnetcore-8.0 +dotnet_diagnostic.BL0003.severity = error # Component parameter with CaptureUnmatchedValues has the wrong type - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0003?view=aspnetcore-8.0 +dotnet_diagnostic.BL0004.severity = error # Component parameter should be public - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0004?view=aspnetcore-8.0 +dotnet_diagnostic.BL0005.severity = error # Component parameter should not be set outside of its component - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0005?view=aspnetcore-8.0 +dotnet_diagnostic.BL0006.severity = warning # Do not use RenderTree types - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0006?view=aspnetcore-8.0 + dotnet_diagnostic.MA0048.severity = none # To support code-behind [component].razor.cs files / Inherit from ComponentBase - File will not match type name. + ########################################## # Custom - Code Analyzers Rules ########################################## \ No newline at end of file diff --git a/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorWebAssemblyStandaloneApp1/.editorconfig b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorWebAssemblyStandaloneApp1/.editorconfig index c96bba9d..f731f937 100644 --- a/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorWebAssemblyStandaloneApp1/.editorconfig +++ b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/BlazorWebAssemblyStandaloneApp1/.editorconfig @@ -1,6 +1,6 @@ # ATC coding rules - https://github.com/atc-net/atc-coding-rules -# Version: 1.0.0 -# Updated: 27-03-2024 +# Version: 1.0.1 +# Updated: 03-06-2024 # Location: blazor # Distribution: Frameworks @@ -9,8 +9,18 @@ ########################################## [*.{cs}] +dotnet_diagnostic.ASP0006.severity = suggestion # Do not use non-literal sequence numbers - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0006?view=aspnetcore-8.0 + +dotnet_diagnostic.BL0001.severity = error # Component parameter should have public setters - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0001?view=aspnetcore-8.0 +dotnet_diagnostic.BL0002.severity = error # Component has multiple CaptureUnmatchedValues parameters - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0002?view=aspnetcore-8.0 +dotnet_diagnostic.BL0003.severity = error # Component parameter with CaptureUnmatchedValues has the wrong type - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0003?view=aspnetcore-8.0 +dotnet_diagnostic.BL0004.severity = error # Component parameter should be public - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0004?view=aspnetcore-8.0 +dotnet_diagnostic.BL0005.severity = error # Component parameter should not be set outside of its component - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0005?view=aspnetcore-8.0 +dotnet_diagnostic.BL0006.severity = warning # Do not use RenderTree types - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/bl0006?view=aspnetcore-8.0 + dotnet_diagnostic.MA0048.severity = none # To support code-behind [component].razor.cs files / Inherit from ComponentBase - File will not match type name. + ########################################## # Custom - Code Analyzers Rules ########################################## \ No newline at end of file diff --git a/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/CliApp1/.editorconfig b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/CliApp1/.editorconfig new file mode 100644 index 00000000..a9ab1446 --- /dev/null +++ b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/CliApp1/.editorconfig @@ -0,0 +1,25 @@ +# ATC coding rules - https://github.com/atc-net/atc-coding-rules +# Version: 1.0.0 +# Updated: 11-04-2024 +# Location: cli +# Distribution: Frameworks + +########################################## +# Code Analyzers Rules +########################################## +[*.{cs}] + +dotnet_diagnostic.CA1031.severity = none # Do not catch general exception types +dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters +dotnet_diagnostic.CA1819.severity = none # Properties should not return arrays +dotnet_diagnostic.CA1848.severity = none # Use the LoggerMessage delegates +dotnet_diagnostic.CA2000.severity = none # Dispose objects before losing scope +dotnet_diagnostic.CA2254.severity = none # Template should be a static expression + +dotnet_diagnostic.MA0076.severity = none # Do not use implicit culture-sensitive ToString in interpolated strings + +dotnet_diagnostic.S2629.severity = none # Don't use string interpolation in logging message templates. + +########################################## +# Custom - Code Analyzers Rules +########################################## \ No newline at end of file diff --git a/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/WebApi1/.editorconfig b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/WebApi1/.editorconfig index 733de3c7..8cc4afce 100644 --- a/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/WebApi1/.editorconfig +++ b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/WebApi1/.editorconfig @@ -1,6 +1,6 @@ # ATC coding rules - https://github.com/atc-net/atc-coding-rules -# Version: 1.0.0 -# Updated: 27-03-2024 +# Version: 1.0.2 +# Updated: 03-06-2024 # Location: webapi # Distribution: Frameworks @@ -9,8 +9,37 @@ ########################################## [*.{cs}] +dotnet_diagnostic.ASP0000.severity = error # Do not call 'IServiceCollection.BuildServiceProvider' in 'ConfigureServices' - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0000?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0001.severity = error # Authorization middleware is incorrectly configured - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/ASP0001?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0003.severity = error # Do not use model binding attributes with route handlers - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0003?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0004.severity = error # Do not use action results with route handlers - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0004?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0005.severity = error # Do not place attribute on method called by route handler lambda - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0005?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0007.severity = error # Route parameter and argument optionality is mismatched - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0007?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0008.severity = error # Do not use ConfigureWebHost with WebApplicationBuilder.Host - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0008?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0009.severity = error # Do not use Configure with WebApplicationBuilder.WebHost - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0009?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0010.severity = error # Do not use UseStartup with WebApplicationBuilder.WebHost - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0010?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0011.severity = suggestion # Suggest using builder.Logging over Host.ConfigureLogging or WebHost.ConfigureLogging - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0011?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0012.severity = suggestion # Suggest using builder.Services over Host.ConfigureServices or WebHost.ConfigureServices - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0012?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0013.severity = suggestion # Suggest switching from using Configure methods to WebApplicationBuilder.Configuration - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0013?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0014.severity = suggestion # Suggest using top level route registrations - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0014?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0015.severity = suggestion # Suggest using IHeaderDictionary properties - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0015?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0016.severity = error # Do not return a value from RequestDelegate - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0016?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0017.severity = error # Invalid route pattern - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0017?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0018.severity = suggestion # Unused route parameter - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0018?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0019.severity = suggestion # Suggest using IHeaderDictionary.Append or the indexer - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0019?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0020.severity = none # Complex types referenced by route parameters must be parsable - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0020?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0021.severity = none # The return type of the BindAsync method must be ValueTask - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0021?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0022.severity = error # Route conflict detected between route handlers (Minimal API) - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0022?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0023.severity = error # Route conflict detected between route handlers (MVC) - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0023?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0024.severity = error # Route handler has multiple parameters with the [FromBody] attribute - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0024?view=aspnetcore-8.0 +dotnet_diagnostic.ASP0025.severity = suggestion # Use AddAuthorizationBuilder to register authorization services and construct policies - https://learn.microsoft.com/en-us/aspnet/core/diagnostics/asp0025?view=aspnetcore-8.0 + dotnet_diagnostic.CA1062.severity = none # No need for null-checking in public method. +dotnet_diagnostic.MA0004.severity = none # Use Task.ConfigureAwait(false) https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0004.md + +dotnet_diagnostic.S6964.severity = none # The rule S6964 should not be active for model properties that use the required keyword. Those properties can never be under-posted because the JSON deserialization for them fails. + ########################################## # Custom - Code Analyzers Rules diff --git a/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/WpfApp1/.editorconfig b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/WpfApp1/.editorconfig index 566e43f3..4e7e24ae 100644 --- a/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/WpfApp1/.editorconfig +++ b/test/Atc.DotNet.Tests/XUnitTestDataProjectSampleTypes/WpfApp1/.editorconfig @@ -1,6 +1,6 @@ # ATC coding rules - https://github.com/atc-net/atc-coding-rules -# Version: 1.0.0 -# Updated: 27-03-2024 +# Version: 1.0.1 +# Updated: 06-06-2024 # Location: wpf # Distribution: Frameworks @@ -9,6 +9,8 @@ ########################################## [*.{cs}] +dotnet_diagnostic.CA2227.severity = none # Change property to be read-only by removing the property setter - https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2227 + dotnet_diagnostic.MA0004.severity = error # Use Task.ConfigureAwait(false) https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0004.md dotnet_diagnostic.MA0048.severity = none # To support partial classes - File will not match type name. diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 020fd5c2..31909604 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -11,7 +11,7 @@ - + From 890698e1e1ef8ece965d8c861787f093bd2dfff8 Mon Sep 17 00:00:00 2001 From: David Kallesen Date: Thu, 10 Oct 2024 23:49:04 +0200 Subject: [PATCH 2/7] feat: add ReflectionHelper.GetPrivateField --- docs/CodeDoc/Atc/Atc.Helpers.md | 19 +++++-- docs/CodeDoc/Atc/IndexExtended.md | 1 + src/Atc/Helpers/ReflectionHelper.cs | 80 +++++++++++++++++++++++------ 3 files changed, 79 insertions(+), 21 deletions(-) diff --git a/docs/CodeDoc/Atc/Atc.Helpers.md b/docs/CodeDoc/Atc/Atc.Helpers.md index 75fc2325..0ead9b3b 100644 --- a/docs/CodeDoc/Atc/Atc.Helpers.md +++ b/docs/CodeDoc/Atc/Atc.Helpers.md @@ -1945,16 +1945,27 @@ ReflectionHelper. ### Static Methods +#### GetPrivateField +>```csharp +>T GetPrivateField(object target, string fieldName) +>``` +>Summary: Gets the value of a private field from the specified target object. +> +>Parameters:
+>     `target`  -  The target object containing the private field.
+>     `fieldName`  -  The name of the private field to retrieve.
+> +>Returns: The value of the private field, cast to the specified type. #### SetPrivateField >```csharp >void SetPrivateField(object target, string fieldName, object value) >``` ->Summary: Sets the private field. +>Summary: Sets the value of a private field on the specified target object. > >Parameters:
->     `target`  -  The target.
->     `fieldName`  -  Name of the field.
->     `value`  -  The value.
+>     `target`  -  The target object containing the private field.
+>     `fieldName`  -  The name of the private field to set.
+>     `value`  -  The value to set on the private field.

diff --git a/docs/CodeDoc/Atc/IndexExtended.md b/docs/CodeDoc/Atc/IndexExtended.md index 676305ec..7938599f 100644 --- a/docs/CodeDoc/Atc/IndexExtended.md +++ b/docs/CodeDoc/Atc/IndexExtended.md @@ -4669,6 +4669,7 @@ - KillEntryCaller(int timeoutInSec = 30) - [ReflectionHelper](Atc.Helpers.md#reflectionhelper) - Static Methods + - GetPrivateField(object target, string fieldName) - SetPrivateField(object target, string fieldName, object value) - [RegionInfoHelper](Atc.Helpers.md#regioninfohelper) - Static Methods diff --git a/src/Atc/Helpers/ReflectionHelper.cs b/src/Atc/Helpers/ReflectionHelper.cs index 4bad3321..2e9cc1d2 100644 --- a/src/Atc/Helpers/ReflectionHelper.cs +++ b/src/Atc/Helpers/ReflectionHelper.cs @@ -6,12 +6,14 @@ namespace Atc.Helpers; public static class ReflectionHelper { /// - /// Sets the private field. + /// Sets the value of a private field on the specified target object. /// - /// The target. - /// Name of the field. - /// The value. - [SuppressMessage("Major Code Smell", "S3011:Reflection should not be used to increase accessibility of classes, methods, or fields", Justification = "OK.")] + /// The target object containing the private field. + /// The name of the private field to set. + /// The value to set on the private field. + /// Thrown if the target or field name is null. + /// Thrown if the private field is not found in the object hierarchy. + [SuppressMessage("Major Code Smell", "S3011:Reflection should not be used to increase accessibility of classes, methods, or fields", Justification = "Reflection required for testing private fields.")] [ExcludeFromCodeCoverage] public static void SetPrivateField(object target, string fieldName, object value) { @@ -22,27 +24,71 @@ public static void SetPrivateField(object target, string fieldName, object value if (string.IsNullOrEmpty(fieldName)) { - throw new ArgumentNullOrDefaultException(nameof(fieldName)); + throw new ArgumentException("Field name cannot be null or empty", nameof(fieldName)); } + var fieldInfo = GetFieldInfo(target, fieldName); + if (fieldInfo is null) + { + throw new ArgumentPropertyException($"Field '{fieldName}' not found in type '{target.GetType()}' or its base types."); + } + + fieldInfo.SetValue(target, value); + } + + /// + /// Gets the value of a private field from the specified target object. + /// + /// The type of the field value. + /// The target object containing the private field. + /// The name of the private field to retrieve. + /// The value of the private field, cast to the specified type. + /// Thrown if the target or field name is null. + /// Thrown if the private field is not found in the object hierarchy. + [SuppressMessage("Major Code Smell", "S3011:Reflection should not be used to increase accessibility of classes, methods, or fields", Justification = "Reflection required for testing private fields.")] + [ExcludeFromCodeCoverage] + public static T? GetPrivateField(object target, string fieldName) + { + if (target is null) + { + throw new ArgumentNullException(nameof(target)); + } + + if (string.IsNullOrEmpty(fieldName)) + { + throw new ArgumentException("Field name cannot be null or empty", nameof(fieldName)); + } + + var fieldInfo = GetFieldInfo(target, fieldName); + if (fieldInfo is null) + { + throw new ArgumentPropertyException($"Field '{fieldName}' not found in type '{target.GetType()}' or its base types."); + } + + return (T?)fieldInfo.GetValue(target); + } + + /// + /// Retrieves FieldInfo for a private field by name, traversing the inheritance hierarchy. + /// + /// The target object containing the private field. + /// The name of the private field. + /// FieldInfo object representing the field, or null if not found. + [SuppressMessage("Major Code Smell", "S3011:Make sure that this accessibility bypass is safe here", Justification = "OK.")] + private static FieldInfo? GetFieldInfo(object target, string fieldName) + { var type = target.GetType(); - FieldInfo? fi = null; while (type is not null) { - fi = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); - if (fi is not null) + var fieldInfo = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); + if (fieldInfo != null) { - break; + return fieldInfo; } - type = type.BaseType!; - } - - if (fi is null) - { - throw new ArgumentPropertyException($"Field '{fieldName}' not found in type hierarchy."); + type = type.BaseType; } - fi.SetValue(target, value); + return null; } } \ No newline at end of file From b3c9e512a2833997f23befeaef5a5bbe76a61d79 Mon Sep 17 00:00:00 2001 From: David Kallesen Date: Thu, 10 Oct 2024 23:57:20 +0200 Subject: [PATCH 3/7] feat: nuget updates --- .../Demo.Atc.Console.Spectre.Cli.csproj | 2 +- sample/Demo.Atc.Dotnet.Cli/Demo.Atc.Dotnet.Cli.csproj | 2 +- .../Atc.CodeAnalysis.CSharp.csproj | 2 +- src/Atc.Console.Spectre/Atc.Console.Spectre.csproj | 2 +- src/Atc.OpenApi/Atc.OpenApi.csproj | 2 +- src/Atc.Rest.Extended/Atc.Rest.Extended.csproj | 4 ++-- .../Atc.Rest.FluentAssertions.csproj | 2 +- src/Atc.Rest.HealthChecks/Atc.Rest.HealthChecks.csproj | 2 +- src/Atc.XUnit/Atc.XUnit.csproj | 4 ++-- src/Atc/Atc.csproj | 6 +++--- src/Atc/Helpers/ReflectionHelper.cs | 8 ++------ .../Atc.CodeAnalysis.CSharp.Tests.csproj | 4 ++-- .../Atc.CodeDocumentation.Tests.csproj | 4 ++-- .../Atc.Console.Spectre.Tests.csproj | 4 ++-- test/Atc.DotNet.Tests/Atc.DotNet.Tests.csproj | 4 ++-- test/Atc.OpenApi.Tests/Atc.OpenApi.Tests.csproj | 4 ++-- .../Atc.Rest.Extended.Tests.csproj | 4 ++-- .../Atc.Rest.FluentAssertions.Tests.csproj | 4 ++-- .../Atc.Rest.HealthChecks.Tests.csproj | 4 ++-- test/Atc.Rest.Tests/Atc.Rest.Tests.csproj | 4 ++-- test/Atc.Tests/Atc.Tests.csproj | 4 ++-- test/Atc.XUnit.Tests/Atc.XUnit.Tests.csproj | 4 ++-- 22 files changed, 38 insertions(+), 42 deletions(-) diff --git a/sample/Demo.Atc.Console.Spectre.Cli/Demo.Atc.Console.Spectre.Cli.csproj b/sample/Demo.Atc.Console.Spectre.Cli/Demo.Atc.Console.Spectre.Cli.csproj index 9e0796d3..c141096b 100644 --- a/sample/Demo.Atc.Console.Spectre.Cli/Demo.Atc.Console.Spectre.Cli.csproj +++ b/sample/Demo.Atc.Console.Spectre.Cli/Demo.Atc.Console.Spectre.Cli.csproj @@ -10,7 +10,7 @@ - + diff --git a/sample/Demo.Atc.Dotnet.Cli/Demo.Atc.Dotnet.Cli.csproj b/sample/Demo.Atc.Dotnet.Cli/Demo.Atc.Dotnet.Cli.csproj index ca472f2b..803cc720 100644 --- a/sample/Demo.Atc.Dotnet.Cli/Demo.Atc.Dotnet.Cli.csproj +++ b/sample/Demo.Atc.Dotnet.Cli/Demo.Atc.Dotnet.Cli.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Atc.CodeAnalysis.CSharp/Atc.CodeAnalysis.CSharp.csproj b/src/Atc.CodeAnalysis.CSharp/Atc.CodeAnalysis.CSharp.csproj index f123c887..486729e3 100644 --- a/src/Atc.CodeAnalysis.CSharp/Atc.CodeAnalysis.CSharp.csproj +++ b/src/Atc.CodeAnalysis.CSharp/Atc.CodeAnalysis.CSharp.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/Atc.Console.Spectre/Atc.Console.Spectre.csproj b/src/Atc.Console.Spectre/Atc.Console.Spectre.csproj index 47d2d590..9634f09b 100644 --- a/src/Atc.Console.Spectre/Atc.Console.Spectre.csproj +++ b/src/Atc.Console.Spectre/Atc.Console.Spectre.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/Atc.OpenApi/Atc.OpenApi.csproj b/src/Atc.OpenApi/Atc.OpenApi.csproj index 2b2b5074..caaa5671 100644 --- a/src/Atc.OpenApi/Atc.OpenApi.csproj +++ b/src/Atc.OpenApi/Atc.OpenApi.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/Atc.Rest.Extended/Atc.Rest.Extended.csproj b/src/Atc.Rest.Extended/Atc.Rest.Extended.csproj index 4ff2943e..86b1bd1a 100644 --- a/src/Atc.Rest.Extended/Atc.Rest.Extended.csproj +++ b/src/Atc.Rest.Extended/Atc.Rest.Extended.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/src/Atc.Rest.FluentAssertions/Atc.Rest.FluentAssertions.csproj b/src/Atc.Rest.FluentAssertions/Atc.Rest.FluentAssertions.csproj index 9227048a..4929653d 100644 --- a/src/Atc.Rest.FluentAssertions/Atc.Rest.FluentAssertions.csproj +++ b/src/Atc.Rest.FluentAssertions/Atc.Rest.FluentAssertions.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/Atc.Rest.HealthChecks/Atc.Rest.HealthChecks.csproj b/src/Atc.Rest.HealthChecks/Atc.Rest.HealthChecks.csproj index 34c2e828..d2bb6ea0 100644 --- a/src/Atc.Rest.HealthChecks/Atc.Rest.HealthChecks.csproj +++ b/src/Atc.Rest.HealthChecks/Atc.Rest.HealthChecks.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/Atc.XUnit/Atc.XUnit.csproj b/src/Atc.XUnit/Atc.XUnit.csproj index a4d1f3dd..ca1783d9 100644 --- a/src/Atc.XUnit/Atc.XUnit.csproj +++ b/src/Atc.XUnit/Atc.XUnit.csproj @@ -12,12 +12,12 @@ - + NU1701 - + diff --git a/src/Atc/Atc.csproj b/src/Atc/Atc.csproj index 79a36086..c1d586f5 100644 --- a/src/Atc/Atc.csproj +++ b/src/Atc/Atc.csproj @@ -8,13 +8,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + diff --git a/src/Atc/Helpers/ReflectionHelper.cs b/src/Atc/Helpers/ReflectionHelper.cs index 2e9cc1d2..0e2dd96e 100644 --- a/src/Atc/Helpers/ReflectionHelper.cs +++ b/src/Atc/Helpers/ReflectionHelper.cs @@ -11,9 +11,7 @@ public static class ReflectionHelper /// The target object containing the private field. /// The name of the private field to set. /// The value to set on the private field. - /// Thrown if the target or field name is null. - /// Thrown if the private field is not found in the object hierarchy. - [SuppressMessage("Major Code Smell", "S3011:Reflection should not be used to increase accessibility of classes, methods, or fields", Justification = "Reflection required for testing private fields.")] + [SuppressMessage("Major Code Smell", "S3011:Reflection should not be used to increase accessibility of classes, methods, or fields", Justification = "OK.")] [ExcludeFromCodeCoverage] public static void SetPrivateField(object target, string fieldName, object value) { @@ -43,9 +41,7 @@ public static void SetPrivateField(object target, string fieldName, object value /// The target object containing the private field. /// The name of the private field to retrieve. /// The value of the private field, cast to the specified type. - /// Thrown if the target or field name is null. - /// Thrown if the private field is not found in the object hierarchy. - [SuppressMessage("Major Code Smell", "S3011:Reflection should not be used to increase accessibility of classes, methods, or fields", Justification = "Reflection required for testing private fields.")] + [SuppressMessage("Major Code Smell", "S3011:Reflection should not be used to increase accessibility of classes, methods, or fields", Justification = "OK.")] [ExcludeFromCodeCoverage] public static T? GetPrivateField(object target, string fieldName) { diff --git a/test/Atc.CodeAnalysis.CSharp.Tests/Atc.CodeAnalysis.CSharp.Tests.csproj b/test/Atc.CodeAnalysis.CSharp.Tests/Atc.CodeAnalysis.CSharp.Tests.csproj index 48ce9515..8c26f22a 100644 --- a/test/Atc.CodeAnalysis.CSharp.Tests/Atc.CodeAnalysis.CSharp.Tests.csproj +++ b/test/Atc.CodeAnalysis.CSharp.Tests/Atc.CodeAnalysis.CSharp.Tests.csproj @@ -6,8 +6,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Atc.CodeDocumentation.Tests/Atc.CodeDocumentation.Tests.csproj b/test/Atc.CodeDocumentation.Tests/Atc.CodeDocumentation.Tests.csproj index ec6f142a..f9f5ed99 100644 --- a/test/Atc.CodeDocumentation.Tests/Atc.CodeDocumentation.Tests.csproj +++ b/test/Atc.CodeDocumentation.Tests/Atc.CodeDocumentation.Tests.csproj @@ -6,8 +6,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Atc.Console.Spectre.Tests/Atc.Console.Spectre.Tests.csproj b/test/Atc.Console.Spectre.Tests/Atc.Console.Spectre.Tests.csproj index 29d0090b..c9befb21 100644 --- a/test/Atc.Console.Spectre.Tests/Atc.Console.Spectre.Tests.csproj +++ b/test/Atc.Console.Spectre.Tests/Atc.Console.Spectre.Tests.csproj @@ -6,8 +6,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Atc.DotNet.Tests/Atc.DotNet.Tests.csproj b/test/Atc.DotNet.Tests/Atc.DotNet.Tests.csproj index a4b4cc72..c4d4335a 100644 --- a/test/Atc.DotNet.Tests/Atc.DotNet.Tests.csproj +++ b/test/Atc.DotNet.Tests/Atc.DotNet.Tests.csproj @@ -12,8 +12,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Atc.OpenApi.Tests/Atc.OpenApi.Tests.csproj b/test/Atc.OpenApi.Tests/Atc.OpenApi.Tests.csproj index cd026929..8cb403c1 100644 --- a/test/Atc.OpenApi.Tests/Atc.OpenApi.Tests.csproj +++ b/test/Atc.OpenApi.Tests/Atc.OpenApi.Tests.csproj @@ -6,8 +6,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Atc.Rest.Extended.Tests/Atc.Rest.Extended.Tests.csproj b/test/Atc.Rest.Extended.Tests/Atc.Rest.Extended.Tests.csproj index 40762005..3fb8dc7c 100644 --- a/test/Atc.Rest.Extended.Tests/Atc.Rest.Extended.Tests.csproj +++ b/test/Atc.Rest.Extended.Tests/Atc.Rest.Extended.Tests.csproj @@ -7,8 +7,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Atc.Rest.FluentAssertions.Tests/Atc.Rest.FluentAssertions.Tests.csproj b/test/Atc.Rest.FluentAssertions.Tests/Atc.Rest.FluentAssertions.Tests.csproj index c8ea0221..0ca2843a 100644 --- a/test/Atc.Rest.FluentAssertions.Tests/Atc.Rest.FluentAssertions.Tests.csproj +++ b/test/Atc.Rest.FluentAssertions.Tests/Atc.Rest.FluentAssertions.Tests.csproj @@ -6,8 +6,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Atc.Rest.HealthChecks.Tests/Atc.Rest.HealthChecks.Tests.csproj b/test/Atc.Rest.HealthChecks.Tests/Atc.Rest.HealthChecks.Tests.csproj index 8b744034..28f05630 100644 --- a/test/Atc.Rest.HealthChecks.Tests/Atc.Rest.HealthChecks.Tests.csproj +++ b/test/Atc.Rest.HealthChecks.Tests/Atc.Rest.HealthChecks.Tests.csproj @@ -6,8 +6,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Atc.Rest.Tests/Atc.Rest.Tests.csproj b/test/Atc.Rest.Tests/Atc.Rest.Tests.csproj index 361ab6d3..1a0b888c 100644 --- a/test/Atc.Rest.Tests/Atc.Rest.Tests.csproj +++ b/test/Atc.Rest.Tests/Atc.Rest.Tests.csproj @@ -7,9 +7,9 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Atc.Tests/Atc.Tests.csproj b/test/Atc.Tests/Atc.Tests.csproj index 011e6999..32bfd9db 100644 --- a/test/Atc.Tests/Atc.Tests.csproj +++ b/test/Atc.Tests/Atc.Tests.csproj @@ -7,8 +7,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Atc.XUnit.Tests/Atc.XUnit.Tests.csproj b/test/Atc.XUnit.Tests/Atc.XUnit.Tests.csproj index ec6f142a..f9f5ed99 100644 --- a/test/Atc.XUnit.Tests/Atc.XUnit.Tests.csproj +++ b/test/Atc.XUnit.Tests/Atc.XUnit.Tests.csproj @@ -6,8 +6,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive From a1a422ec456a10d9612f658f00a47b7201880762 Mon Sep 17 00:00:00 2001 From: David Kallesen Date: Fri, 11 Oct 2024 00:07:56 +0200 Subject: [PATCH 4/7] feat: improve ReflectionHelper.GetPrivateField with InvalidCastException using pattern matching --- src/Atc/Helpers/ReflectionHelper.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Atc/Helpers/ReflectionHelper.cs b/src/Atc/Helpers/ReflectionHelper.cs index 0e2dd96e..3e771cc7 100644 --- a/src/Atc/Helpers/ReflectionHelper.cs +++ b/src/Atc/Helpers/ReflectionHelper.cs @@ -1,3 +1,4 @@ +// ReSharper disable ReturnTypeCanBeNotNullable namespace Atc.Helpers; /// @@ -61,7 +62,12 @@ public static void SetPrivateField(object target, string fieldName, object value throw new ArgumentPropertyException($"Field '{fieldName}' not found in type '{target.GetType()}' or its base types."); } - return (T?)fieldInfo.GetValue(target); + if (fieldInfo.GetValue(target) is not T fieldValue) + { + throw new InvalidCastException($"Field '{fieldName}' found in type '{target.GetType()}', but cannot be cast to type '{typeof(T)}'."); + } + + return fieldValue; } /// @@ -77,7 +83,7 @@ public static void SetPrivateField(object target, string fieldName, object value while (type is not null) { var fieldInfo = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); - if (fieldInfo != null) + if (fieldInfo is not null) { return fieldInfo; } From 101a85d368cfdf31811e3614340e5e79772d979c Mon Sep 17 00:00:00 2001 From: David Kallesen Date: Fri, 11 Oct 2024 00:28:18 +0200 Subject: [PATCH 5/7] fix: test is not working in pipeline - datetime format --- test/Atc.Tests/Extensions/BaseTypes/DateTimeExtensionsTests.cs | 3 +++ .../Extensions/BaseTypes/DateTimeOffsetExtensionsTests.cs | 3 +++ test/Atc.Tests/GlobalUsings.cs | 3 ++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/test/Atc.Tests/Extensions/BaseTypes/DateTimeExtensionsTests.cs b/test/Atc.Tests/Extensions/BaseTypes/DateTimeExtensionsTests.cs index ae092634..5b00dbe2 100644 --- a/test/Atc.Tests/Extensions/BaseTypes/DateTimeExtensionsTests.cs +++ b/test/Atc.Tests/Extensions/BaseTypes/DateTimeExtensionsTests.cs @@ -1,6 +1,9 @@ // ReSharper disable StringLiteralTypo namespace Atc.Tests.Extensions.BaseTypes; +[Collection(nameof(TestCollection))] +[Trait(Traits.Category, Traits.Categories.Integration)] +[Trait(Traits.Category, Traits.Categories.SkipWhenLiveUnitTesting)] public class DateTimeExtensionsTests { [Theory] diff --git a/test/Atc.Tests/Extensions/BaseTypes/DateTimeOffsetExtensionsTests.cs b/test/Atc.Tests/Extensions/BaseTypes/DateTimeOffsetExtensionsTests.cs index 98b75524..e7f0d419 100644 --- a/test/Atc.Tests/Extensions/BaseTypes/DateTimeOffsetExtensionsTests.cs +++ b/test/Atc.Tests/Extensions/BaseTypes/DateTimeOffsetExtensionsTests.cs @@ -1,5 +1,8 @@ namespace Atc.Tests.Extensions.BaseTypes; +[Collection(nameof(TestCollection))] +[Trait(Traits.Category, Traits.Categories.Integration)] +[Trait(Traits.Category, Traits.Categories.SkipWhenLiveUnitTesting)] public class DateTimeOffsetExtensionsTests { [Theory] diff --git a/test/Atc.Tests/GlobalUsings.cs b/test/Atc.Tests/GlobalUsings.cs index 0fcf5445..c1ca8055 100644 --- a/test/Atc.Tests/GlobalUsings.cs +++ b/test/Atc.Tests/GlobalUsings.cs @@ -36,4 +36,5 @@ global using Atc.Units.InternationalSystemOfUnits; global using Atc.XUnit; -global using Xunit.Abstractions; \ No newline at end of file +global using Xunit.Abstractions; +global using Xunit.Sdk; \ No newline at end of file From bd4994b42f7430d199983e45da7a19781877ca0d Mon Sep 17 00:00:00 2001 From: David Kallesen Date: Fri, 11 Oct 2024 00:43:04 +0200 Subject: [PATCH 6/7] fix: Add system namespace to NullException (conflict with xunit.sdk) --- test/Atc.Tests/Exceptions/ExceptionsTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Atc.Tests/Exceptions/ExceptionsTests.cs b/test/Atc.Tests/Exceptions/ExceptionsTests.cs index 84db9fb1..53dec359 100644 --- a/test/Atc.Tests/Exceptions/ExceptionsTests.cs +++ b/test/Atc.Tests/Exceptions/ExceptionsTests.cs @@ -300,8 +300,8 @@ public void NullException(string? expectedMessage, string? inputMessage) { // Arrange & Act var sut = inputMessage is not null - ? new NullException(inputMessage) - : new NullException(); + ? new System.NullException(inputMessage) + : new System.NullException(); // Assert if (expectedMessage is null) From bc1bf9e76caef0b656ca8d5875c0a5c37fc95367 Mon Sep 17 00:00:00 2001 From: David Kallesen Date: Fri, 11 Oct 2024 01:00:33 +0200 Subject: [PATCH 7/7] chore: clenaup in DateTimeOffsetExtensionsTests --- .../DateTimeOffsetExtensionsTests.cs | 265 +++++++++++++++- .../Helpers/DateTimeOffsetExtensionsTests.cs | 296 ------------------ 2 files changed, 262 insertions(+), 299 deletions(-) delete mode 100644 test/Atc.Tests/Helpers/DateTimeOffsetExtensionsTests.cs diff --git a/test/Atc.Tests/Extensions/BaseTypes/DateTimeOffsetExtensionsTests.cs b/test/Atc.Tests/Extensions/BaseTypes/DateTimeOffsetExtensionsTests.cs index e7f0d419..e439632a 100644 --- a/test/Atc.Tests/Extensions/BaseTypes/DateTimeOffsetExtensionsTests.cs +++ b/test/Atc.Tests/Extensions/BaseTypes/DateTimeOffsetExtensionsTests.cs @@ -1,3 +1,4 @@ +// ReSharper disable StringLiteralTypo namespace Atc.Tests.Extensions.BaseTypes; [Collection(nameof(TestCollection))] @@ -5,6 +6,95 @@ namespace Atc.Tests.Extensions.BaseTypes; [Trait(Traits.Category, Traits.Categories.SkipWhenLiveUnitTesting)] public class DateTimeOffsetExtensionsTests { + [Theory] + [InlineData(10000, 10, DateTimeDiffCompareType.Milliseconds)] + [InlineData(42000, 42, DateTimeDiffCompareType.Milliseconds)] + public void DateTimeDiff(double expected, int seconds, DateTimeDiffCompareType dateTimeDiffCompareType) + { + // Arrange + var inputA = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); + var inputB = new DateTimeOffset(1970, 1, 1, 0, 0, seconds, TimeSpan.Zero); + + // Act + var actual = inputA.DateTimeDiff(inputB, dateTimeDiffCompareType); + + // Assert + Assert.Equal(expected, actual); + } + + [Theory] + [MemberData(nameof(TestMemberDataForDateTimeOffsetExtensions.GetPrettyTimeDiff), MemberType = typeof(TestMemberDataForDateTimeOffsetExtensions))] + public void GetPrettyTimeDiff(string expected, DateTimeOffset start, int arrangeUiLcid) + { + // Arrange + Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); + + // Act + var actual = start.GetPrettyTimeDiff(); + + // Assert - A kind of dummy test, because of timing issues + Assert.NotNull(expected); + Assert.NotNull(actual); + } + + [Theory] + [MemberData(nameof(TestMemberDataForDateTimeOffsetExtensions.GetPrettyTimeDiffWithDecimalPrecision), MemberType = typeof(TestMemberDataForDateTimeOffsetExtensions))] + public void GetPrettyTimeDiff_DecimalPrecision(string expected, DateTimeOffset start, int decimalPrecision, int arrangeUiLcid) + { + // Arrange + Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); + + // Act + var actual = start.GetPrettyTimeDiff(decimalPrecision); + + // Assert - A kind of dummy test, because of timing issues + Assert.NotNull(expected); + Assert.NotNull(actual); + } + + [Theory] + [MemberData(nameof(TestMemberDataForDateTimeOffsetExtensions.GetPrettyTimeDiffWithEnd), MemberType = typeof(TestMemberDataForDateTimeOffsetExtensions))] + public void GetPrettyTimeDiff_EndNow(string expected, DateTimeOffset start, DateTimeOffset end, int arrangeUiLcid) + { + // Arrange + Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); + + // Act + var actual = start.GetPrettyTimeDiff(end); + + // Assert + Assert.Equal(expected, actual); + } + + [Theory] + [MemberData(nameof(TestMemberDataForDateTimeOffsetExtensions.GetPrettyTimeDiffWithEndNowAndDecimalPrecision), MemberType = typeof(TestMemberDataForDateTimeOffsetExtensions))] + public void GetPrettyTimeDiff_EndNow_DecimalPrecision(string expected, DateTimeOffset start, DateTimeOffset end, int decimalPrecision, int arrangeUiLcid) + { + // Arrange + Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); + + // Act + var actual = start.GetPrettyTimeDiff(end, decimalPrecision); + + // Assert + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData(1, 1970, 1)] + [InlineData(48, 2019, 12)] + public void GetWeekNumber(int expected, int year, int month) + { + // Arrange + var input = new DateTimeOffset(year, month, 1, 0, 0, 0, TimeSpan.Zero); + + // Act + var actual = input.GetWeekNumber(); + + // Assert + Assert.Equal(expected, actual); + } + [Theory] [InlineData(true, 2019, 10, 5, 15)] [InlineData(true, 2019, 10, 10, 15)] @@ -79,11 +169,12 @@ public void ToUnixTime(int expected, int seconds) } [Theory] - [InlineData("1970-01-01T00:00:42", 42)] - public void ToIso8601Date(string expected, int seconds) + [InlineData("1970-01-01T00:00:42", 1970, 42)] + [InlineData("2019-01-01T00:00:42", 2019, 42)] + public void ToIso8601Date(string expected, int year, int seconds) { // Arrange - var input = new DateTimeOffset(1970, 1, 1, 0, 0, seconds, TimeSpan.Zero); + var input = new DateTimeOffset(year, 1, 1, 0, 0, seconds, TimeSpan.Zero); // Act var actual = input.ToIso8601Date(); @@ -91,4 +182,172 @@ public void ToIso8601Date(string expected, int seconds) // Assert Assert.Equal(expected, actual); } + + [Theory] + [InlineData(1970, 0, 42)] + [InlineData(1970, 2, 42)] + [InlineData(2019, 0, 42)] + public void ToIso8601Utc(int year, int hour, int seconds) + { + // Arrange + var input = new DateTimeOffset(year, 1, 1, hour, 0, seconds, TimeSpan.Zero); + + // Act + var actual = input.ToIso8601UtcDate(); + + // Assert + Assert.NotNull(actual); + } + + [Theory] + [InlineData("Sunday, October 15, 2023", GlobalizationLcidConstants.UnitedStates)] + [InlineData("Sunday, 15 October 2023", GlobalizationLcidConstants.GreatBritain)] + [InlineData("søndag den 15. oktober 2023", GlobalizationLcidConstants.Denmark)] + [InlineData("Sonntag, 15. Oktober 2023", GlobalizationLcidConstants.Germany)] + public void ToLongDateStringUsingCurrentUiCulture( + string expected, int arrangeUiLcid) + { + // Arrange + var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); + Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); + + // Act + var actual = dateTimeOffset.ToLongDateStringUsingCurrentUiCulture(); + + // Assert + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData("Sunday, October 15, 2023", GlobalizationLcidConstants.UnitedStates)] + [InlineData("Sunday, 15 October 2023", GlobalizationLcidConstants.GreatBritain)] + [InlineData("søndag den 15. oktober 2023", GlobalizationLcidConstants.Denmark)] + [InlineData("Sonntag, 15. Oktober 2023", GlobalizationLcidConstants.Germany)] + public void ToLongDateString( + string expected, int arrangeUiLcid) + { + // Arrange + var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); + Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); + + // Act + var actual = dateTimeOffset.ToLongDateString(Thread.CurrentThread.CurrentUICulture.DateTimeFormat); + + // Assert + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData("3:30:45 PM", GlobalizationLcidConstants.UnitedStates)] + [InlineData("15:30:45", GlobalizationLcidConstants.GreatBritain)] + [InlineData("15.30.45", GlobalizationLcidConstants.Denmark)] + [InlineData("15:30:45", GlobalizationLcidConstants.Germany)] + public void ToLongTimeStringUsingCurrentUiCulture( + string expected, int arrangeUiLcid) + { + // Arrange + var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); + Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); + + // Act + var actual = dateTimeOffset.ToLongTimeStringUsingCurrentUiCulture(); + + // Assert + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData("3:30:45 PM", GlobalizationLcidConstants.UnitedStates)] + [InlineData("15:30:45", GlobalizationLcidConstants.GreatBritain)] + [InlineData("15.30.45", GlobalizationLcidConstants.Denmark)] + [InlineData("15:30:45", GlobalizationLcidConstants.Germany)] + public void ToLongTimeString( + string expected, int arrangeUiLcid) + { + // Arrange + var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); + Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); + + // Act + var actual = dateTimeOffset.ToLongTimeString(Thread.CurrentThread.CurrentUICulture.DateTimeFormat); + + // Assert + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData("10/15/2023", GlobalizationLcidConstants.UnitedStates)] + [InlineData("15/10/2023", GlobalizationLcidConstants.GreatBritain)] + [InlineData("15.10.2023", GlobalizationLcidConstants.Denmark)] + [InlineData("15.10.2023", GlobalizationLcidConstants.Germany)] + public void ToShortDateStringUsingCurrentUiCulture( + string expected, int arrangeUiLcid) + { + // Arrange + var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); + Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); + + // Act + var actual = dateTimeOffset.ToShortDateStringUsingCurrentUiCulture(); + + // Assert + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData("10/15/2023", GlobalizationLcidConstants.UnitedStates)] + [InlineData("15/10/2023", GlobalizationLcidConstants.GreatBritain)] + [InlineData("15.10.2023", GlobalizationLcidConstants.Denmark)] + [InlineData("15.10.2023", GlobalizationLcidConstants.Germany)] + public void ToShortDateString( + string expected, int arrangeUiLcid) + { + // Arrange + var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); + Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); + + // Act + var actual = dateTimeOffset.ToShortDateString(Thread.CurrentThread.CurrentUICulture.DateTimeFormat); + + // Assert + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData("3:30 PM", GlobalizationLcidConstants.UnitedStates)] + [InlineData("15:30", GlobalizationLcidConstants.GreatBritain)] + [InlineData("15.30", GlobalizationLcidConstants.Denmark)] + [InlineData("15:30", GlobalizationLcidConstants.Germany)] + public void ToShortTimeStringUsingCurrentUiCulture( + string expected, int arrangeUiLcid) + { + // Arrange + var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); + Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); + + // Act + var actual = dateTimeOffset.ToShortTimeStringUsingCurrentUiCulture(); + + // Assert + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData("3:30 PM", GlobalizationLcidConstants.UnitedStates)] + [InlineData("15:30", GlobalizationLcidConstants.GreatBritain)] + [InlineData("15.30", GlobalizationLcidConstants.Denmark)] + [InlineData("15:30", GlobalizationLcidConstants.Germany)] + public void ToShortTimeString( + string expected, int arrangeUiLcid) + { + // Arrange + var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); + Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); + + // Act + var actual = dateTimeOffset.ToShortTimeString(Thread.CurrentThread.CurrentUICulture.DateTimeFormat); + + // Assert + Assert.Equal(expected, actual); + } } \ No newline at end of file diff --git a/test/Atc.Tests/Helpers/DateTimeOffsetExtensionsTests.cs b/test/Atc.Tests/Helpers/DateTimeOffsetExtensionsTests.cs deleted file mode 100644 index c32e02b6..00000000 --- a/test/Atc.Tests/Helpers/DateTimeOffsetExtensionsTests.cs +++ /dev/null @@ -1,296 +0,0 @@ -// ReSharper disable StringLiteralTypo -namespace Atc.Tests.Helpers; - -public class DateTimeOffsetExtensionsTests -{ - [Theory] - [InlineData(true, 2019, 10, 5, 15)] - [InlineData(true, 2019, 10, 10, 15)] - [InlineData(true, 2019, 10, 5, 10)] - [InlineData(false, 2019, 10, 15, 25)] - public void IsBetween(bool expected, int year, int inputSeconds, int secondsA, int secondsB) - { - // Arrange - var input = new DateTimeOffset(year, 1, 1, 0, 0, inputSeconds, TimeSpan.Zero); - var inputA = new DateTimeOffset(year, 1, 1, 0, 0, secondsA, TimeSpan.Zero); - var inputB = new DateTimeOffset(year, 1, 1, 0, 0, secondsB, TimeSpan.Zero); - - // Act - var actual = input.IsBetween(inputA, inputB); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [MemberData(nameof(TestMemberDataForDateTimeOffsetExtensions.GetPrettyTimeDiff), MemberType = typeof(TestMemberDataForDateTimeOffsetExtensions))] - public void GetPrettyTimeDiff(string expected, DateTimeOffset start, int arrangeUiLcid) - { - // Arrange - Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); - - // Act - var actual = start.GetPrettyTimeDiff(); - - // Assert - A kind of a dummy test, because of timing issues - Assert.NotNull(expected); - Assert.NotNull(actual); - } - - [Theory] - [MemberData(nameof(TestMemberDataForDateTimeOffsetExtensions.GetPrettyTimeDiffWithDecimalPrecision), MemberType = typeof(TestMemberDataForDateTimeOffsetExtensions))] - public void GetPrettyTimeDiff_DecimalPrecision(string expected, DateTimeOffset start, int decimalPrecision, int arrangeUiLcid) - { - // Arrange - Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); - - // Act - var actual = start.GetPrettyTimeDiff(decimalPrecision); - - // Assert - A kind of a dummy test, because of timing issues - Assert.NotNull(expected); - Assert.NotNull(actual); - } - - [Theory] - [MemberData(nameof(TestMemberDataForDateTimeOffsetExtensions.GetPrettyTimeDiffWithEnd), MemberType = typeof(TestMemberDataForDateTimeOffsetExtensions))] - public void GetPrettyTimeDiff_EndNow(string expected, DateTimeOffset start, DateTimeOffset end, int arrangeUiLcid) - { - // Arrange - Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); - - // Act - var actual = start.GetPrettyTimeDiff(end); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [MemberData(nameof(TestMemberDataForDateTimeOffsetExtensions.GetPrettyTimeDiffWithEndNowAndDecimalPrecision), MemberType = typeof(TestMemberDataForDateTimeOffsetExtensions))] - public void GetPrettyTimeDiff_EndNow_DecimalPrecision(string expected, DateTimeOffset start, DateTimeOffset end, int decimalPrecision, int arrangeUiLcid) - { - // Arrange - Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); - - // Act - var actual = start.GetPrettyTimeDiff(end, decimalPrecision); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData(1, 1970, 1)] - [InlineData(48, 2019, 12)] - public void GetWeekNumber(int expected, int year, int month) - { - // Arrange - var input = new DateTimeOffset(year, month, 1, 0, 0, 0, TimeSpan.Zero); - - // Act - var actual = input.GetWeekNumber(); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData(10000, 10, DateTimeDiffCompareType.Milliseconds)] - [InlineData(42000, 42, DateTimeDiffCompareType.Milliseconds)] - public void DateTimeDiff(double expected, int seconds, DateTimeDiffCompareType dateTimeDiffCompareType) - { - // Arrange - var inputA = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); - var inputB = new DateTimeOffset(1970, 1, 1, 0, 0, seconds, TimeSpan.Zero); - - // Act - var actual = inputA.DateTimeDiff(inputB, dateTimeDiffCompareType); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData("1970-01-01T00:00:42", 1970, 42)] - [InlineData("2019-01-01T00:00:42", 2019, 42)] - public void ToIso8601Date(string expected, int year, int seconds) - { - // Arrange - var input = new DateTimeOffset(year, 1, 1, 0, 0, seconds, TimeSpan.Zero); - - // Act - var actual = input.ToIso8601Date(); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData(1970, 0, 42)] - [InlineData(1970, 2, 42)] - [InlineData(2019, 0, 42)] - public void ToIso8601Utc(int year, int hour, int seconds) - { - // Arrange - var input = new DateTimeOffset(year, 1, 1, hour, 0, seconds, TimeSpan.Zero); - - // Act - var actual = input.ToIso8601UtcDate(); - - // Assert - Assert.NotNull(actual); - } - - [Theory] - [InlineData("Sunday, October 15, 2023", GlobalizationLcidConstants.UnitedStates)] - [InlineData("Sunday, 15 October 2023", GlobalizationLcidConstants.GreatBritain)] - [InlineData("søndag den 15. oktober 2023", GlobalizationLcidConstants.Denmark)] - [InlineData("Sonntag, 15. Oktober 2023", GlobalizationLcidConstants.Germany)] - public void ToLongDateStringUsingCurrentUiCulture( - string expected, int arrangeUiLcid) - { - // Arrange - var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); - Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); - - // Act - var actual = dateTimeOffset.ToLongDateStringUsingCurrentUiCulture(); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData("Sunday, October 15, 2023", GlobalizationLcidConstants.UnitedStates)] - [InlineData("Sunday, 15 October 2023", GlobalizationLcidConstants.GreatBritain)] - [InlineData("søndag den 15. oktober 2023", GlobalizationLcidConstants.Denmark)] - [InlineData("Sonntag, 15. Oktober 2023", GlobalizationLcidConstants.Germany)] - public void ToLongDateString( - string expected, int arrangeUiLcid) - { - // Arrange - var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); - Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); - - // Act - var actual = dateTimeOffset.ToLongDateString(Thread.CurrentThread.CurrentUICulture.DateTimeFormat); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData("3:30:45 PM", GlobalizationLcidConstants.UnitedStates)] - [InlineData("15:30:45", GlobalizationLcidConstants.GreatBritain)] - [InlineData("15.30.45", GlobalizationLcidConstants.Denmark)] - [InlineData("15:30:45", GlobalizationLcidConstants.Germany)] - public void ToLongTimeStringUsingCurrentUiCulture( - string expected, int arrangeUiLcid) - { - // Arrange - var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); - Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); - - // Act - var actual = dateTimeOffset.ToLongTimeStringUsingCurrentUiCulture(); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData("3:30:45 PM", GlobalizationLcidConstants.UnitedStates)] - [InlineData("15:30:45", GlobalizationLcidConstants.GreatBritain)] - [InlineData("15.30.45", GlobalizationLcidConstants.Denmark)] - [InlineData("15:30:45", GlobalizationLcidConstants.Germany)] - public void ToLongTimeString( - string expected, int arrangeUiLcid) - { - // Arrange - var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); - Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); - - // Act - var actual = dateTimeOffset.ToLongTimeString(Thread.CurrentThread.CurrentUICulture.DateTimeFormat); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData("10/15/2023", GlobalizationLcidConstants.UnitedStates)] - [InlineData("15/10/2023", GlobalizationLcidConstants.GreatBritain)] - [InlineData("15.10.2023", GlobalizationLcidConstants.Denmark)] - [InlineData("15.10.2023", GlobalizationLcidConstants.Germany)] - public void ToShortDateStringUsingCurrentUiCulture( - string expected, int arrangeUiLcid) - { - // Arrange - var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); - Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); - - // Act - var actual = dateTimeOffset.ToShortDateStringUsingCurrentUiCulture(); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData("10/15/2023", GlobalizationLcidConstants.UnitedStates)] - [InlineData("15/10/2023", GlobalizationLcidConstants.GreatBritain)] - [InlineData("15.10.2023", GlobalizationLcidConstants.Denmark)] - [InlineData("15.10.2023", GlobalizationLcidConstants.Germany)] - public void ToShortDateString( - string expected, int arrangeUiLcid) - { - // Arrange - var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); - Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); - - // Act - var actual = dateTimeOffset.ToShortDateString(Thread.CurrentThread.CurrentUICulture.DateTimeFormat); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData("3:30 PM", GlobalizationLcidConstants.UnitedStates)] - [InlineData("15:30", GlobalizationLcidConstants.GreatBritain)] - [InlineData("15.30", GlobalizationLcidConstants.Denmark)] - [InlineData("15:30", GlobalizationLcidConstants.Germany)] - public void ToShortTimeStringUsingCurrentUiCulture( - string expected, int arrangeUiLcid) - { - // Arrange - var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); - Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); - - // Act - var actual = dateTimeOffset.ToShortTimeStringUsingCurrentUiCulture(); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData("3:30 PM", GlobalizationLcidConstants.UnitedStates)] - [InlineData("15:30", GlobalizationLcidConstants.GreatBritain)] - [InlineData("15.30", GlobalizationLcidConstants.Denmark)] - [InlineData("15:30", GlobalizationLcidConstants.Germany)] - public void ToShortTimeString( - string expected, int arrangeUiLcid) - { - // Arrange - var dateTimeOffset = new DateTimeOffset(2023, 10, 15, 15, 30, 45, TimeSpan.Zero); - Thread.CurrentThread.CurrentUICulture = new CultureInfo(arrangeUiLcid); - - // Act - var actual = dateTimeOffset.ToShortTimeString(Thread.CurrentThread.CurrentUICulture.DateTimeFormat); - - // Assert - Assert.Equal(expected, actual); - } -} \ No newline at end of file