From 88805fe91e4079fe57d4865fdd9e8ce594dbe18d Mon Sep 17 00:00:00 2001 From: "codebelt-aicia[bot]" Date: Fri, 16 Oct 2026 14:13:42 +0000 Subject: [PATCH 1/8] V1.3.5/service update --- .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ CHANGELOG.md | 4 ++++ Directory.Packages.props | 6 +++--- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/.nuget/Codebelt.Extensions.BenchmarkDotNet.Console/PackageReleaseNotes.txt b/.nuget/Codebelt.Extensions.BenchmarkDotNet.Console/PackageReleaseNotes.txt index c53ac07..3622691 100644 --- a/.nuget/Codebelt.Extensions.BenchmarkDotNet.Console/PackageReleaseNotes.txt +++ b/.nuget/Codebelt.Extensions.BenchmarkDotNet.Console/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 1.3.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 1.3.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Codebelt.Extensions.BenchmarkDotNet/PackageReleaseNotes.txt b/.nuget/Codebelt.Extensions.BenchmarkDotNet/PackageReleaseNotes.txt index 6579b94..42d7785 100644 --- a/.nuget/Codebelt.Extensions.BenchmarkDotNet/PackageReleaseNotes.txt +++ b/.nuget/Codebelt.Extensions.BenchmarkDotNet/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 1.3.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 1.3.4 Availability: .NET 10 and .NET 9 diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f23fb7..001bf94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), For more details, please refer to `PackageReleaseNotes.txt` on a per assembly basis in the `.nuget` folder. +## [1.3.5] - 2026-10-16 + +This is a service update that focuses on package dependencies. + ## [1.3.4] - 2026-09-12 This is a patch release focused on dependency upgrades, code coverage infrastructure modernization, and developer experience improvements through enhanced tooling and documentation. diff --git a/Directory.Packages.props b/Directory.Packages.props index c68e421..cd8a694 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,9 +5,9 @@ - - - + + + From a8330e542498f3f3ebe913d60a21adc9519e1f5f Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sat, 17 Oct 2026 19:48:24 +0200 Subject: [PATCH 2/8] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20upgrade=20test=20frame?= =?UTF-8?q?work=20and=20xunit=20package=20versions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keeps central package versions current so tests run on the latest supported test platform and xUnit releases. πŸ€– Generated with Codebuff Co-Authored-By: Codebuff --- Directory.Packages.props | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index cd8a694..c76636b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -8,11 +8,11 @@ - - + + - - - + + + - \ No newline at end of file + From 637c1362abeb8d5a8e3eccf654fae40976ccbc3a Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sat, 17 Oct 2026 19:48:24 +0200 Subject: [PATCH 3/8] =?UTF-8?q?=F0=9F=90=B3=20serve=20docs=20with=20dhi=20?= =?UTF-8?q?nginx=20and=20pinned=20docfx=20builder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moves the DocFX site into a reproducible container build so published API docs are served the same way everywhere. πŸ€– Generated with Codebuff Co-Authored-By: Codebuff --- .docfx/Dockerfile.docfx | 9 ++++----- .docfx/docfx.json | 10 ++++++++-- .docfx/nginx.conf | 31 +++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 .docfx/nginx.conf diff --git a/.docfx/Dockerfile.docfx b/.docfx/Dockerfile.docfx index f4064e2..39006f1 100644 --- a/.docfx/Dockerfile.docfx +++ b/.docfx/Dockerfile.docfx @@ -1,17 +1,16 @@ ο»ΏARG NGINX_VERSION=1.31-alpine -FROM --platform=$BUILDPLATFORM nginx:${NGINX_VERSION} AS base +FROM --platform=$BUILDPLATFORM dhi.io/nginx:${NGINX_VERSION} AS base RUN rm -rf /usr/share/nginx/html/* -FROM --platform=$BUILDPLATFORM codebeltnet/docfx:2.78.5 AS build +FROM --platform=$BUILDPLATFORM codebeltnet/docfx:2 AS build ADD [".", "docfx"] RUN cd docfx; \ docfx build -FROM nginx:${NGINX_VERSION} AS final +FROM dhi.io/nginx:${NGINX_VERSION} AS final WORKDIR /usr/share/nginx/html COPY --from=build /build/docfx/wwwroot /usr/share/nginx/html - -ENTRYPOINT ["nginx", "-g", "daemon off;"] +COPY nginx.conf /etc/nginx/conf.d/default.conf diff --git a/.docfx/docfx.json b/.docfx/docfx.json index f09678b..2bf81aa 100644 --- a/.docfx/docfx.json +++ b/.docfx/docfx.json @@ -11,6 +11,7 @@ } ], "dest": "api", + "memberLayout": "separatePages", "filter": "filterConfig.yml", "properties": { "TargetFramework": "net10.0" @@ -65,7 +66,8 @@ "fileMetadataFiles": [], "template": [ "default", - "modern" + "modern", + "templates/ms-style" ], "overwrite": [ { @@ -84,6 +86,10 @@ "noLangKeyword": false, "keepFileLink": false, "cleanupCacheHistory": false, - "disableGitFeatures": false + "disableGitFeatures": false, + "sitemap": { + "baseUrl": "https://benchmarkdotnet.codebelt.net/", + "changefreq": "monthly" + } } } diff --git a/.docfx/nginx.conf b/.docfx/nginx.conf new file mode 100644 index 0000000..c95d1b1 --- /dev/null +++ b/.docfx/nginx.conf @@ -0,0 +1,31 @@ +server { + listen 8080; + server_name _; + # The ingress terminates TLS; keep redirects from exposing this container port. + absolute_redirect off; + + root /usr/share/nginx/html; + index index.html; + + # DocFX fingerprints these generated dependencies in their filenames. They can be + # cached permanently because changed content is published under a different URL. + location ~ "^/public/.+-[A-Z0-9]{8}(?:-[A-Z0-9]{8})?(?:\.min)?\.(?:(?:css|js)(?:\.map)?|woff2?)$" { + try_files $uri =404; + add_header Cache-Control "public, max-age=31536000, immutable" always; + add_header Vary "Accept-Encoding" always; + } + + # Pages, navigation data, images, and DocFX entry assets keep stable URLs. Do not + # retain them across deployments, and ignore validators cached under an old policy. + location / { + # Nginx derives ETags from modification time and file size. Those values can be + # reused by files copied from different image layers, producing a false 304. + etag off; + if_modified_since off; + try_files $uri $uri/ =404; + add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0" always; + add_header Expires "0" always; + add_header Pragma "no-cache" always; + add_header Vary "Accept-Encoding" always; + } +} From 845da32260d38da9f9052ceb3dc625a8ddd5f382 Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sat, 17 Oct 2026 19:48:25 +0200 Subject: [PATCH 4/8] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20consolidate=20agent=20?= =?UTF-8?q?guidance=20into=20agents=20md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A single AGENTS.md avoids drift between duplicated Copilot and agent instruction files. πŸ€– Generated with Codebuff Co-Authored-By: Codebuff --- .github/copilot-instructions.md | 632 -------------------------------- AGENTS.md | 628 ++++++++++++++++++++++++++++++- 2 files changed, 626 insertions(+), 634 deletions(-) delete mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index 7ce5415..0000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,632 +0,0 @@ ---- -description: 'Writing Unit Tests in Codebelt.Extensions.BenchmarkDotNet' -applyTo: "**/*.{cs,csproj}" ---- - -# Writing Unit Tests in Codebelt.Extensions.BenchmarkDotNet -This document provides instructions for writing unit tests in the Codebelt.Extensions.BenchmarkDotNet codebase. Please follow these guidelines to ensure consistency and maintainability. - -## 1. Base Class - -**Always inherit from the `Test` base class** for all unit test classes. -This ensures consistent setup, teardown, and output handling across all tests. - -> Important: Do NOT add `using Xunit.Abstractions`. xUnit v3 no longer exposes that namespace; including it is incorrect and will cause compilation errors. Use the `Codebelt.Extensions.Xunit` Test base class and `using Xunit;` as shown in the examples below. If you need access to test output, rely on the Test base class (which accepts the appropriate output helper) rather than importing `Xunit.Abstractions`. - -```csharp -using Codebelt.Extensions.Xunit; -using Xunit; - -namespace Your.Namespace -{ - public class YourTestClass : Test - { - public YourTestClass(ITestOutputHelper output) : base(output) - { - } - - // Your tests here - } -} -``` - -## 2. Test Method Attributes - -- Use `[Fact]` for standard unit tests. -- Use `[Theory]` with `[InlineData]` or other data sources for parameterized tests. - -## 3. Naming Conventions - -- **Test classes**: End with `Test` (e.g., `DateSpanTest`). -- **Test methods**: Use descriptive names that state the expected behavior (e.g., `ShouldReturnTrue_WhenConditionIsMet`). - -## 4. Assertions - -- Use `Assert` methods from xUnit for all assertions. -- Prefer explicit and expressive assertions (e.g., `Assert.Equal`, `Assert.NotNull`, `Assert.Contains`). - -## 5. File and Namespace Organization - -- Place test files in the appropriate test project and folder structure. -- Use namespaces that mirror the source code structure. The namespace of a test file MUST match the namespace of the System Under Test (SUT). Do NOT append ".Tests", ".Benchmarks" or similar suffixes to the namespace. Only the assembly/project name should indicate that the file is a test/benchmark (for example: Codebelt.Extensions.BenchmarkDotNet.Foo.Tests assembly, but namespace Codebelt.Extensions.BenchmarkDotNet.Foo). - - Example: If the SUT class is declared as: - ```csharp - namespace Codebelt.Extensions.BenchmarkDotNet.Foo.Bar - { - public class Zoo { /* ... */ } - } - ``` - then the corresponding unit test class must use the exact same namespace: - ```csharp - namespace Codebelt.Extensions.BenchmarkDotNet.Foo.Bar - { - public class ZooTest : Test { /* ... */ } - } - ``` - - Do NOT use: - ```csharp - namespace Codebelt.Extensions.BenchmarkDotNet.Foo.Bar.Tests { /* ... */ } // ❌ - namespace Codebelt.Extensions.BenchmarkDotNet.Foo.Bar.Benchmarks { /* ... */ } // ❌ - ``` -- The unit tests for the Codebelt.Extensions.BenchmarkDotNet.Foo assembly live in the Codebelt.Extensions.BenchmarkDotNet.Foo.Tests assembly. -- The functional tests for the Codebelt.Extensions.BenchmarkDotNet.Foo assembly live in the Codebelt.Extensions.BenchmarkDotNet.Foo.FunctionalTests assembly. -- Test class names end with Test and live in the same namespace as the class being tested, e.g., the unit tests for the Boo class that resides in the Codebelt.Extensions.BenchmarkDotNet.Foo assembly would be named BooTest and placed in the Codebelt.Extensions.BenchmarkDotNet.Foo namespace in the Codebelt.Extensions.BenchmarkDotNet.Foo.Tests assembly. -- Modify the associated .csproj file to override the root namespace so the compiled namespace matches the SUT. Example: - ```xml - - Codebelt.Extensions.BenchmarkDotNet.Foo - - ``` -- When generating test scaffolding automatically, resolve the SUT's namespace from the source file (or project/assembly metadata) and use that exact namespace in the test file header. - -- Notes: - - This rule ensures type discovery and XML doc links behave consistently and reduces confusion when reading tests. - - Keep folder structure aligned with the production code layout to make locating SUT <-> test pairs straightforward. - -## 6. Example Test - -```csharp -using System; -using System.Globalization; -using Codebelt.Extensions.Xunit; -using Xunit; - -namespace Codebelt.Extensions.BenchmarkDotNet -{ - /// - /// Tests for the class. - /// - public class DateSpanTest : Test - { - public DateSpanTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void Parse_ShouldGetOneMonthOfDifference_UsingIso8601String() - { - var start = new DateTime(2021, 3, 5).ToString("O"); - var end = new DateTime(2021, 4, 5).ToString("O"); - - var span = DateSpan.Parse(start, end); - - Assert.Equal("0:01:31:00:00:00.0", span.ToString()); - Assert.Equal(0, span.Years); - Assert.Equal(1, span.Months); - Assert.Equal(31, span.Days); - Assert.Equal(0, span.Hours); - Assert.Equal(0, span.Minutes); - Assert.Equal(0, span.Seconds); - Assert.Equal(0, span.Milliseconds); - - Assert.Equal(0.08493150684931507, span.TotalYears); - Assert.Equal(1, span.TotalMonths); - Assert.Equal(31, span.TotalDays); - Assert.Equal(744, span.TotalHours); - Assert.Equal(44640, span.TotalMinutes); - Assert.Equal(2678400, span.TotalSeconds); - Assert.Equal(2678400000, span.TotalMilliseconds); - - Assert.Equal(6, span.GetWeeks()); - Assert.Equal(-1566296493, span.GetHashCode()); - - TestOutput.WriteLine(span.ToString()); - } - } -} -``` - -## 7. Additional Guidelines - -- Keep tests focused and isolated. -- Do not rely on external systems except for xUnit itself and Codebelt.Extensions.Xunit (and derived from this). -- Ensure tests are deterministic and repeatable. - -## 8. Test Doubles - -- Preferred test doubles include dummies, fakes, stubs and spies if and when the design allows it. -- Under special circumstances, mock can be used (using Moq library). -- Before overriding methods, verify that the method is virtual or abstract; this rule also applies to mocks. -- Never mock IMarshaller; always use a new instance of JsonMarshaller. - -## 9. Avoid `InternalsVisibleTo` in Tests - -- **Do not** use `InternalsVisibleTo` to access internal types or members from test projects. -- Prefer **indirect testing via public APIs** that depend on the internal implementation (public facades, public extension methods, or other public entry points). - -### Preferred Pattern - -**Pattern name:** Public Facade Testing (also referred to as *Public API Proxy Testing*) - -**Description:** -Internal classes and methods must be validated by exercising the public API that consumes them. Tests should assert observable behavior exposed by the public surface rather than targeting internal implementation details directly. - -### Example Mapping - -- **Internal helper:** `DelimitedString` (internal static class) -- **Public API:** `TestOutputHelperExtensions.WriteLines()` (public extension method) -- **Test strategy:** Write tests for `WriteLines()` and verify its public behavior. The internal call to `DelimitedString.Create()` is exercised implicitly. - -### Benefits - -- Avoids exposing internal types to test assemblies. -- Ensures tests reflect real-world usage patterns. -- Maintains strong encapsulation and a clean public API. -- Tests remain resilient to internal refactoring as long as public behavior is preserved. - -### When to Apply - -- Internal logic is fully exercised through existing public APIs. -- Public entry points provide sufficient coverage of internal code paths. -- The internal implementation exists solely as a helper or utility for public-facing functionality. - -## 10. ExcludeFromCodeCoverage Prohibition - -**Do not use `ExcludeFromCodeCoverage` attribute on any code.** This includes: - -- Test classes or test methods -- Production code -- Configuration code -- Any other code path - -### Rationale - -- Excluding code from coverage hides gaps and creates false confidence in test completeness. -- If a code path cannot or should not be tested, refactor the code to eliminate that path rather than hiding it from metrics. -- Every executable line should be covered by tests or be genuinely unreachable (dead code to be removed). - -### Alternative Approaches - -- **Untestable code paths**: Refactor to separate concerns and eliminate the untestable path. -- **External dependencies**: Use test doubles (fakes, stubs, spies) instead of excluding from coverage. -- **Configuration-only code**: Move to configuration files or extract into testable methods. -- **Generated or third-party code**: These should not be in the primary codebase; use NuGet packages or dedicated vendor folders if necessary. - ---- -description: 'Writing Performance Tests in Codebelt.Extensions.BenchmarkDotNet' -applyTo: "tuning/**, **/*Benchmark*.cs" ---- - -# Writing Performance Tests in Codebelt.Extensions.BenchmarkDotNet -This document provides guidance for writing performance tests (benchmarks) in the Codebelt.Extensions.BenchmarkDotNet codebase using BenchmarkDotNet. Follow these guidelines to keep benchmarks consistent, readable, and comparable. - -## 1. Naming and Placement - -- Place micro- and component-benchmarks under the `tuning/` folder or in projects named `*.Benchmarks`. -- Place benchmark files in the appropriate benchmark project and folder structure. -- Use namespaces that mirror the source code structure, e.g. do not suffix with `Benchmarks`. -- Namespace rule: DO NOT append `.Benchmarks` to the namespace. Benchmarks must live in the same namespace as the production assembly. Example: if the production assembly uses `namespace Codebelt.Extensions.BenchmarkDotNet.Security.Cryptography`, the benchmark file should also use: - ``` - namespace Codebelt.Extensions.BenchmarkDotNet.Security.Cryptography - { - public class Sha512256Benchmark { /* ... */ } - } - ``` -The class name must end with `Benchmark`, but the namespace must match the assembly (no `.Benchmarks` suffix). -- The benchmarks for the Codebelt.Extensions.BenchmarkDotNet.Bar assembly live in the Codebelt.Extensions.BenchmarkDotNet.Bar.Benchmarks assembly. -- Benchmark class names end with Benchmark and live in the same namespace as the class being measured, e.g., the benchmarks for the Zoo class that resides in the Codebelt.Extensions.BenchmarkDotNet.Bar assembly would be named ZooBenchmark and placed in the Codebelt.Extensions.BenchmarkDotNet.Bar namespace in the Codebelt.Extensions.BenchmarkDotNet.Bar.Benchmarks assembly. -- Modify the associated .csproj file to override the root namespace, e.g., Codebelt.Extensions.BenchmarkDotNet.Bar. - -## 2. Attributes and Configuration - -- Use `BenchmarkDotNet` attributes to express intent and collect relevant metrics: - - `[MemoryDiagnoser]` to capture memory allocations. - - `[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]` to group related benchmarks. - - `[Params]` for input sizes or variations to exercise multiple scenarios. - - `[GlobalSetup]` for one-time initialization that's not part of measured work. - - `[Benchmark]` on methods representing measured operations; consider `Baseline = true` and `Description` to improve report clarity. -- Keep benchmark configuration minimal and explicit; prefer in-class attributes over large shared configs unless re-used widely. - -## 3. Structure and Best Practices - -- Keep benchmarks focused: each `Benchmark` method should measure a single logical operation. -- Avoid doing expensive setup work inside a measured method; use `[GlobalSetup]`, `[IterationSetup]`, or cached fields instead. -- Use `Params` to cover micro, mid and macro input sizes (for example: small, medium, large) and verify performance trends across them. -- Use small, deterministic data sets and avoid external systems (network, disk, DB). If external systems are necessary, mark them clearly and do not include them in CI benchmark runs by default. -- Capture results that are meaningful: time, allocations, and if needed custom counters. Prefer `MemoryDiagnoser` and descriptive `Description` values. - -## 4. Naming Conventions for Methods - -- Method names should be descriptive and indicate the scenario, e.g., `Parse_Short`, `ComputeHash_Large`. -- When comparing implementations, mark one method with `Baseline = true` and use similar names so reports are easy to read. - -## 5. Example Benchmark - -```csharp -using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Configs; - -namespace Codebelt.Extensions.BenchmarkDotNet -{ - [MemoryDiagnoser] - [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] - public class SampleOperationBenchmark - { - [Params(8, 256, 4096)] - public int Count { get; set; } - - private byte[] _payload; - - [GlobalSetup] - public void Setup() - { - _payload = new byte[Count]; - // deterministic initialization - } - - [Benchmark(Baseline = true, Description = "Operation - baseline")] - public int Operation_Baseline() => SampleOperation.Process(_payload); - - [Benchmark(Description = "Operation - optimized")] - public int Operation_Optimized() => SampleOperation.ProcessOptimized(_payload); - } -} -``` - -## 6. Reporting and CI - -- Benchmarks are primarily for local and tuning runs; be cautious about running heavy BenchmarkDotNet workloads in CI. Prefer targeted runs or harnesses for CI where appropriate. -- Keep benchmark projects isolated (e.g., `tuning/*.csproj`) so they don't affect package builds or production artifacts. - -## 7. Additional Guidelines - -- Keep benchmarks readable and well-documented; add comments explaining non-obvious choices. -- If a benchmark exposes regressions or optimizations, add a short note in the benchmark file referencing the relevant issue or PR. -- For any shared helpers for benchmarking, prefer small utility classes inside the `tuning` projects rather than cross-cutting changes to production code. - -For further examples, refer to the benchmark files under the `tuning/` folder. - ---- -description: 'Writing XML documentation in Codebelt.Extensions.BenchmarkDotNet' -applyTo: "**/*.cs" ---- - -# Writing XML documentation in Codebelt.Extensions.BenchmarkDotNet -This document provides instructions for writing XML documentation. - -## 1. Documentation Style - -- Use the same documentation style as found throughout the codebase. -- Add XML doc comments to public and protected classes and methods where appropriate. -- Example: - -```csharp -using System; -using System.Collections.Generic; -using System.IO; -using Cuemon.Collections.Generic; -using Cuemon.Configuration; -using Cuemon.IO; -using Cuemon.Text; - -namespace Cuemon.Security -{ - /// - /// Represents the base class from which all implementations of hash algorithms and checksums should derive. - /// - /// The type of the configured options. - /// - /// - /// - public abstract class Hash : Hash, IConfigurable where TOptions : ConvertibleOptions, new() - { - /// - /// Initializes a new instance of the class. - /// - /// The which may be configured. - protected Hash(Action setup) - { - Options = Patterns.Configure(setup); - } - - /// - /// Gets the configured options of this instance. - /// - /// The configured options of this instance. - public TOptions Options { get; } - - - /// - /// The endian-initializer of this instance. - /// - /// An instance of the configured options. - protected sealed override void EndianInitializer(EndianOptions options) - { - options.ByteOrder = Options.ByteOrder; - } - } - - /// - /// Represents the base class that defines the public facing structure to expose. - /// - /// - public abstract class Hash : IHash - { - /// - /// Initializes a new instance of the class. - /// - protected Hash() - { - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(bool input) - { - return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(byte input) - { - return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(char input) - { - return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(DateTime input) - { - return ComputeHash(Convertible.GetBytes(input)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(DBNull input) - { - return ComputeHash(Convertible.GetBytes(input)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(decimal input) - { - return ComputeHash(Convertible.GetBytes(input)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(double input) - { - return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(short input) - { - return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(int input) - { - return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(long input) - { - return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(sbyte input) - { - return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(float input) - { - return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(ushort input) - { - return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(uint input) - { - return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(ulong input) - { - return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// The which may be configured. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(string input, Action setup = null) - { - return ComputeHash(Convertible.GetBytes(input, setup)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(Enum input) - { - return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(params IConvertible[] input) - { - return ComputeHash(Arguments.ToEnumerableOf(input)); - } - - /// - /// Computes the hash value for the specified sequence of . - /// - /// The sequence of to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(IEnumerable input) - { - return ComputeHash(Convertible.GetBytes(input)); - } - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public abstract HashResult ComputeHash(byte[] input); - - /// - /// Computes the hash value for the specified . - /// - /// The to compute the hash code for. - /// A containing the computed hash code of the specified . - public virtual HashResult ComputeHash(Stream input) - { - return ComputeHash(Patterns.SafeInvoke(() => new MemoryStream(), destination => - { - Decorator.Enclose(input).CopyStream(destination); - return destination; - }).ToArray()); - } - - /// - /// Defines the initializer that must implement. - /// - /// An instance of the configured options. - protected abstract void EndianInitializer(EndianOptions options); - } -} - -namespace Cuemon.Security -{ - /// - /// Configuration options for . - /// - public class FowlerNollVoOptions : ConvertibleOptions - { - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public FowlerNollVoOptions() - { - Algorithm = FowlerNollVoAlgorithm.Fnv1a; - ByteOrder = Endianness.BigEndian; - } - - /// - /// Gets or sets the algorithm of the Fowler-Noll-Vo hash function. - /// - /// The algorithm of the Fowler-Noll-Vo hash function. - public FowlerNollVoAlgorithm Algorithm { get; set; } - } -} -``` diff --git a/AGENTS.md b/AGENTS.md index aec2f1e..0641fc1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -26,7 +26,7 @@ Codebelt.Extensions.BenchmarkDotNet is a .NET library that provides a uniform, o - `reports/` β€” Benchmark reports and tuning output produced by tooling - `.nuget/` β€” Per-package NuGet metadata (icon, README, release notes) - `.docfx/` β€” DocFX documentation configuration -- `.github/` β€” CI/CD workflows, contributing guidelines, Copilot instructions +- `.github/` β€” CI/CD workflows and contributing guidelines; agent instructions are in root `AGENTS.md` ## Test Conventions @@ -48,7 +48,7 @@ Codebelt.Extensions.BenchmarkDotNet is a .NET library that provides a uniform, o If a `.bot/` folder exists at the root, it contains **confidential, local-only** working material for AI agents β€” product requirement documents (PRDs), design proposals, agentic loop state, and brainstorming outputs. This folder is gitignored and never committed. -When starting creative or design work (new features, architecture decisions, PRD drafts), use the [brainstorming skill](https://skills.sh/obra/superpowers/brainstorming) and save outputs to `.bot/`. Only move finalized, non-confidential instructions into `AGENTS.md` or `.github/copilot-instructions.md`. +When starting creative or design work (new features, architecture decisions, PRD drafts), use the [brainstorming skill](https://skills.sh/obra/superpowers/brainstorming) and save outputs to `.bot/`. Only move finalized, non-confidential instructions into `AGENTS.md`. ## Git Operations Safeguards @@ -118,3 +118,627 @@ The final DocFX verification must run outside the working tree when possible. Th If a command cannot be run, report the exact limitation or failure instead of claiming the documentation was verified. + +Applicability: **Writing Unit Tests in Codebelt.Extensions.BenchmarkDotNet** applies to `**/*.{cs,csproj}` paths in this repository. + +# Writing Unit Tests in Codebelt.Extensions.BenchmarkDotNet +This document provides instructions for writing unit tests in the Codebelt.Extensions.BenchmarkDotNet codebase. Please follow these guidelines to ensure consistency and maintainability. + +## 1. Base Class + +**Always inherit from the `Test` base class** for all unit test classes. +This ensures consistent setup, teardown, and output handling across all tests. + +> Important: Do NOT add `using Xunit.Abstractions`. xUnit v3 no longer exposes that namespace; including it is incorrect and will cause compilation errors. Use the `Codebelt.Extensions.Xunit` Test base class and `using Xunit;` as shown in the examples below. If you need access to test output, rely on the Test base class (which accepts the appropriate output helper) rather than importing `Xunit.Abstractions`. + +```csharp +using Codebelt.Extensions.Xunit; +using Xunit; + +namespace Your.Namespace +{ + public class YourTestClass : Test + { + public YourTestClass(ITestOutputHelper output) : base(output) + { + } + + // Your tests here + } +} +``` + +## 2. Test Method Attributes + +- Use `[Fact]` for standard unit tests. +- Use `[Theory]` with `[InlineData]` or other data sources for parameterized tests. + +## 3. Naming Conventions + +- **Test classes**: End with `Test` (e.g., `DateSpanTest`). +- **Test methods**: Use descriptive names that state the expected behavior (e.g., `ShouldReturnTrue_WhenConditionIsMet`). + +## 4. Assertions + +- Use `Assert` methods from xUnit for all assertions. +- Prefer explicit and expressive assertions (e.g., `Assert.Equal`, `Assert.NotNull`, `Assert.Contains`). + +## 5. File and Namespace Organization + +- Place test files in the appropriate test project and folder structure. +- Use namespaces that mirror the source code structure. The namespace of a test file MUST match the namespace of the System Under Test (SUT). Do NOT append ".Tests", ".Benchmarks" or similar suffixes to the namespace. Only the assembly/project name should indicate that the file is a test/benchmark (for example: Codebelt.Extensions.BenchmarkDotNet.Foo.Tests assembly, but namespace Codebelt.Extensions.BenchmarkDotNet.Foo). + - Example: If the SUT class is declared as: + ```csharp + namespace Codebelt.Extensions.BenchmarkDotNet.Foo.Bar + { + public class Zoo { /* ... */ } + } + ``` + then the corresponding unit test class must use the exact same namespace: + ```csharp + namespace Codebelt.Extensions.BenchmarkDotNet.Foo.Bar + { + public class ZooTest : Test { /* ... */ } + } + ``` + - Do NOT use: + ```csharp + namespace Codebelt.Extensions.BenchmarkDotNet.Foo.Bar.Tests { /* ... */ } // ❌ + namespace Codebelt.Extensions.BenchmarkDotNet.Foo.Bar.Benchmarks { /* ... */ } // ❌ + ``` +- The unit tests for the Codebelt.Extensions.BenchmarkDotNet.Foo assembly live in the Codebelt.Extensions.BenchmarkDotNet.Foo.Tests assembly. +- The functional tests for the Codebelt.Extensions.BenchmarkDotNet.Foo assembly live in the Codebelt.Extensions.BenchmarkDotNet.Foo.FunctionalTests assembly. +- Test class names end with Test and live in the same namespace as the class being tested, e.g., the unit tests for the Boo class that resides in the Codebelt.Extensions.BenchmarkDotNet.Foo assembly would be named BooTest and placed in the Codebelt.Extensions.BenchmarkDotNet.Foo namespace in the Codebelt.Extensions.BenchmarkDotNet.Foo.Tests assembly. +- Modify the associated .csproj file to override the root namespace so the compiled namespace matches the SUT. Example: + ```xml + + Codebelt.Extensions.BenchmarkDotNet.Foo + + ``` +- When generating test scaffolding automatically, resolve the SUT's namespace from the source file (or project/assembly metadata) and use that exact namespace in the test file header. + +- Notes: + - This rule ensures type discovery and XML doc links behave consistently and reduces confusion when reading tests. + - Keep folder structure aligned with the production code layout to make locating SUT <-> test pairs straightforward. + +## 6. Example Test + +```csharp +using System; +using System.Globalization; +using Codebelt.Extensions.Xunit; +using Xunit; + +namespace Codebelt.Extensions.BenchmarkDotNet +{ + /// + /// Tests for the class. + /// + public class DateSpanTest : Test + { + public DateSpanTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void Parse_ShouldGetOneMonthOfDifference_UsingIso8601String() + { + var start = new DateTime(2021, 3, 5).ToString("O"); + var end = new DateTime(2021, 4, 5).ToString("O"); + + var span = DateSpan.Parse(start, end); + + Assert.Equal("0:01:31:00:00:00.0", span.ToString()); + Assert.Equal(0, span.Years); + Assert.Equal(1, span.Months); + Assert.Equal(31, span.Days); + Assert.Equal(0, span.Hours); + Assert.Equal(0, span.Minutes); + Assert.Equal(0, span.Seconds); + Assert.Equal(0, span.Milliseconds); + + Assert.Equal(0.08493150684931507, span.TotalYears); + Assert.Equal(1, span.TotalMonths); + Assert.Equal(31, span.TotalDays); + Assert.Equal(744, span.TotalHours); + Assert.Equal(44640, span.TotalMinutes); + Assert.Equal(2678400, span.TotalSeconds); + Assert.Equal(2678400000, span.TotalMilliseconds); + + Assert.Equal(6, span.GetWeeks()); + Assert.Equal(-1566296493, span.GetHashCode()); + + TestOutput.WriteLine(span.ToString()); + } + } +} +``` + +## 7. Additional Guidelines + +- Keep tests focused and isolated. +- Do not rely on external systems except for xUnit itself and Codebelt.Extensions.Xunit (and derived from this). +- Ensure tests are deterministic and repeatable. + +## 8. Test Doubles + +- Preferred test doubles include dummies, fakes, stubs and spies if and when the design allows it. +- Under special circumstances, mock can be used (using Moq library). +- Before overriding methods, verify that the method is virtual or abstract; this rule also applies to mocks. +- Never mock IMarshaller; always use a new instance of JsonMarshaller. + +## 9. Avoid `InternalsVisibleTo` in Tests + +- **Do not** use `InternalsVisibleTo` to access internal types or members from test projects. +- Prefer **indirect testing via public APIs** that depend on the internal implementation (public facades, public extension methods, or other public entry points). + +### Preferred Pattern + +**Pattern name:** Public Facade Testing (also referred to as *Public API Proxy Testing*) + +**Description:** +Internal classes and methods must be validated by exercising the public API that consumes them. Tests should assert observable behavior exposed by the public surface rather than targeting internal implementation details directly. + +### Example Mapping + +- **Internal helper:** `DelimitedString` (internal static class) +- **Public API:** `TestOutputHelperExtensions.WriteLines()` (public extension method) +- **Test strategy:** Write tests for `WriteLines()` and verify its public behavior. The internal call to `DelimitedString.Create()` is exercised implicitly. + +### Benefits + +- Avoids exposing internal types to test assemblies. +- Ensures tests reflect real-world usage patterns. +- Maintains strong encapsulation and a clean public API. +- Tests remain resilient to internal refactoring as long as public behavior is preserved. + +### When to Apply + +- Internal logic is fully exercised through existing public APIs. +- Public entry points provide sufficient coverage of internal code paths. +- The internal implementation exists solely as a helper or utility for public-facing functionality. + +## 10. ExcludeFromCodeCoverage Prohibition + +**Do not use `ExcludeFromCodeCoverage` attribute on any code.** This includes: + +- Test classes or test methods +- Production code +- Configuration code +- Any other code path + +### Rationale + +- Excluding code from coverage hides gaps and creates false confidence in test completeness. +- If a code path cannot or should not be tested, refactor the code to eliminate that path rather than hiding it from metrics. +- Every executable line should be covered by tests or be genuinely unreachable (dead code to be removed). + +### Alternative Approaches + +- **Untestable code paths**: Refactor to separate concerns and eliminate the untestable path. +- **External dependencies**: Use test doubles (fakes, stubs, spies) instead of excluding from coverage. +- **Configuration-only code**: Move to configuration files or extract into testable methods. +- **Generated or third-party code**: These should not be in the primary codebase; use NuGet packages or dedicated vendor folders if necessary. + +Applicability: **Writing Performance Tests in Codebelt.Extensions.BenchmarkDotNet** applies to `tuning/**, **/*Benchmark*.cs` paths in this repository. + +# Writing Performance Tests in Codebelt.Extensions.BenchmarkDotNet +This document provides guidance for writing performance tests (benchmarks) in the Codebelt.Extensions.BenchmarkDotNet codebase using BenchmarkDotNet. Follow these guidelines to keep benchmarks consistent, readable, and comparable. + +## 1. Naming and Placement + +- Place micro- and component-benchmarks under the `tuning/` folder or in projects named `*.Benchmarks`. +- Place benchmark files in the appropriate benchmark project and folder structure. +- Use namespaces that mirror the source code structure, e.g. do not suffix with `Benchmarks`. +- Namespace rule: DO NOT append `.Benchmarks` to the namespace. Benchmarks must live in the same namespace as the production assembly. Example: if the production assembly uses `namespace Codebelt.Extensions.BenchmarkDotNet.Security.Cryptography`, the benchmark file should also use: + ``` + namespace Codebelt.Extensions.BenchmarkDotNet.Security.Cryptography + { + public class Sha512256Benchmark { /* ... */ } + } + ``` +The class name must end with `Benchmark`, but the namespace must match the assembly (no `.Benchmarks` suffix). +- The benchmarks for the Codebelt.Extensions.BenchmarkDotNet.Bar assembly live in the Codebelt.Extensions.BenchmarkDotNet.Bar.Benchmarks assembly. +- Benchmark class names end with Benchmark and live in the same namespace as the class being measured, e.g., the benchmarks for the Zoo class that resides in the Codebelt.Extensions.BenchmarkDotNet.Bar assembly would be named ZooBenchmark and placed in the Codebelt.Extensions.BenchmarkDotNet.Bar namespace in the Codebelt.Extensions.BenchmarkDotNet.Bar.Benchmarks assembly. +- Modify the associated .csproj file to override the root namespace, e.g., Codebelt.Extensions.BenchmarkDotNet.Bar. + +## 2. Attributes and Configuration + +- Use `BenchmarkDotNet` attributes to express intent and collect relevant metrics: + - `[MemoryDiagnoser]` to capture memory allocations. + - `[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]` to group related benchmarks. + - `[Params]` for input sizes or variations to exercise multiple scenarios. + - `[GlobalSetup]` for one-time initialization that's not part of measured work. + - `[Benchmark]` on methods representing measured operations; consider `Baseline = true` and `Description` to improve report clarity. +- Keep benchmark configuration minimal and explicit; prefer in-class attributes over large shared configs unless re-used widely. + +## 3. Structure and Best Practices + +- Keep benchmarks focused: each `Benchmark` method should measure a single logical operation. +- Avoid doing expensive setup work inside a measured method; use `[GlobalSetup]`, `[IterationSetup]`, or cached fields instead. +- Use `Params` to cover micro, mid and macro input sizes (for example: small, medium, large) and verify performance trends across them. +- Use small, deterministic data sets and avoid external systems (network, disk, DB). If external systems are necessary, mark them clearly and do not include them in CI benchmark runs by default. +- Capture results that are meaningful: time, allocations, and if needed custom counters. Prefer `MemoryDiagnoser` and descriptive `Description` values. + +## 4. Naming Conventions for Methods + +- Method names should be descriptive and indicate the scenario, e.g., `Parse_Short`, `ComputeHash_Large`. +- When comparing implementations, mark one method with `Baseline = true` and use similar names so reports are easy to read. + +## 5. Example Benchmark + +```csharp +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +namespace Codebelt.Extensions.BenchmarkDotNet +{ + [MemoryDiagnoser] + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class SampleOperationBenchmark + { + [Params(8, 256, 4096)] + public int Count { get; set; } + + private byte[] _payload; + + [GlobalSetup] + public void Setup() + { + _payload = new byte[Count]; + // deterministic initialization + } + + [Benchmark(Baseline = true, Description = "Operation - baseline")] + public int Operation_Baseline() => SampleOperation.Process(_payload); + + [Benchmark(Description = "Operation - optimized")] + public int Operation_Optimized() => SampleOperation.ProcessOptimized(_payload); + } +} +``` + +## 6. Reporting and CI + +- Benchmarks are primarily for local and tuning runs; be cautious about running heavy BenchmarkDotNet workloads in CI. Prefer targeted runs or harnesses for CI where appropriate. +- Keep benchmark projects isolated (e.g., `tuning/*.csproj`) so they don't affect package builds or production artifacts. + +## 7. Additional Guidelines + +- Keep benchmarks readable and well-documented; add comments explaining non-obvious choices. +- If a benchmark exposes regressions or optimizations, add a short note in the benchmark file referencing the relevant issue or PR. +- For any shared helpers for benchmarking, prefer small utility classes inside the `tuning` projects rather than cross-cutting changes to production code. + +For further examples, refer to the benchmark files under the `tuning/` folder. + +Applicability: **Writing XML documentation in Codebelt.Extensions.BenchmarkDotNet** applies to `**/*.cs` paths in this repository. + +# Writing XML documentation in Codebelt.Extensions.BenchmarkDotNet +This document provides instructions for writing XML documentation. + +## 1. Documentation Style + +- Use the same documentation style as found throughout the codebase. +- Add XML doc comments to public and protected classes and methods where appropriate. +- Example: + +```csharp +using System; +using System.Collections.Generic; +using System.IO; +using Cuemon.Collections.Generic; +using Cuemon.Configuration; +using Cuemon.IO; +using Cuemon.Text; + +namespace Cuemon.Security +{ + /// + /// Represents the base class from which all implementations of hash algorithms and checksums should derive. + /// + /// The type of the configured options. + /// + /// + /// + public abstract class Hash : Hash, IConfigurable where TOptions : ConvertibleOptions, new() + { + /// + /// Initializes a new instance of the class. + /// + /// The which may be configured. + protected Hash(Action setup) + { + Options = Patterns.Configure(setup); + } + + /// + /// Gets the configured options of this instance. + /// + /// The configured options of this instance. + public TOptions Options { get; } + + + /// + /// The endian-initializer of this instance. + /// + /// An instance of the configured options. + protected sealed override void EndianInitializer(EndianOptions options) + { + options.ByteOrder = Options.ByteOrder; + } + } + + /// + /// Represents the base class that defines the public facing structure to expose. + /// + /// + public abstract class Hash : IHash + { + /// + /// Initializes a new instance of the class. + /// + protected Hash() + { + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(bool input) + { + return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(byte input) + { + return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(char input) + { + return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(DateTime input) + { + return ComputeHash(Convertible.GetBytes(input)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(DBNull input) + { + return ComputeHash(Convertible.GetBytes(input)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(decimal input) + { + return ComputeHash(Convertible.GetBytes(input)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(double input) + { + return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(short input) + { + return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(int input) + { + return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(long input) + { + return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(sbyte input) + { + return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(float input) + { + return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(ushort input) + { + return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(uint input) + { + return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(ulong input) + { + return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// The which may be configured. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(string input, Action setup = null) + { + return ComputeHash(Convertible.GetBytes(input, setup)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(Enum input) + { + return ComputeHash(Convertible.GetBytes(input, EndianInitializer)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(params IConvertible[] input) + { + return ComputeHash(Arguments.ToEnumerableOf(input)); + } + + /// + /// Computes the hash value for the specified sequence of . + /// + /// The sequence of to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(IEnumerable input) + { + return ComputeHash(Convertible.GetBytes(input)); + } + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public abstract HashResult ComputeHash(byte[] input); + + /// + /// Computes the hash value for the specified . + /// + /// The to compute the hash code for. + /// A containing the computed hash code of the specified . + public virtual HashResult ComputeHash(Stream input) + { + return ComputeHash(Patterns.SafeInvoke(() => new MemoryStream(), destination => + { + Decorator.Enclose(input).CopyStream(destination); + return destination; + }).ToArray()); + } + + /// + /// Defines the initializer that must implement. + /// + /// An instance of the configured options. + protected abstract void EndianInitializer(EndianOptions options); + } +} + +namespace Cuemon.Security +{ + /// + /// Configuration options for . + /// + public class FowlerNollVoOptions : ConvertibleOptions + { + /// + /// Initializes a new instance of the class. + /// + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public FowlerNollVoOptions() + { + Algorithm = FowlerNollVoAlgorithm.Fnv1a; + ByteOrder = Endianness.BigEndian; + } + + /// + /// Gets or sets the algorithm of the Fowler-Noll-Vo hash function. + /// + /// The algorithm of the Fowler-Noll-Vo hash function. + public FowlerNollVoAlgorithm Algorithm { get; set; } + } +} +``` From 0e326ece1c420157616a3d12426150efe4fd814c Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sat, 17 Oct 2026 19:48:25 +0200 Subject: [PATCH 5/8] =?UTF-8?q?=F0=9F=92=AC=20update=20changelog=20for=201?= =?UTF-8?q?.3.5=20service=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Records the service update changes so consumers can see what shipped in this release. πŸ€– Generated with Codebuff Co-Authored-By: Codebuff --- CHANGELOG.md | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 001bf94..62dc6e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), For more details, please refer to `PackageReleaseNotes.txt` on a per assembly basis in the `.nuget` folder. -## [1.3.5] - 2026-10-16 +## [1.3.5] - 2026-10-17 -This is a service update that focuses on package dependencies. +This is a patch release that updates dependencies, consolidates agent guidance and revises documentation hosting. + +### Added + +- Added `nginx.conf` for port 8080, immutable caching of fingerprinted public assets and disabled caching and validators for stable documentation URLs. + +### Changed + +- Updated `Cuemon.Core` from 10.7.1 to 10.8.1, +- Updated `Codebelt.Extensions.Xunit.App` from 12.0.1 to 12.0.2, +- Updated `Microsoft.NET.Test.Sdk` from 18.10.0 to 18.11.0, +- Updated `Microsoft.Testing.Extensions.CodeCoverage` from 18.11.2 to 18.12.0, +- Updated `xunit.runner.visualstudio` from 4.0.0 to 4.0.1, +- Updated `xunit.v3`, `xunit.v3.runner.console` from 4.0.0 to 4.0.2, +- Updated `Codebelt.Bootstrapper.Console` from 5.2.1 to 5.2.2, +- Consolidated the complete test, benchmark and XML documentation guidance in `AGENTS.md`, preserving examples and path scopes and updating guidance links, +- Configured DocFX for separate member pages, the `templates/ms-style` template and a monthly sitemap; switched documentation containers to `dhi.io/nginx` and the `codebeltnet/docfx:2` builder. ## [1.3.4] - 2026-09-12 @@ -179,8 +195,8 @@ This is the initial stable release of the `Codebelt.Extensions.BenchmarkDotNet` - ADDED `BenchmarkProgram` class in the Codebelt.Extensions.BenchmarkDotNet.Console namespace that provides the main entry point for hosting and running benchmarks using BenchmarkDotNet, - ADDED `BenchmarkWorker` class in the Codebelt.Extensions.BenchmarkDotNet.Console namespace that is responsible for executing benchmarks within the console host. -[Unreleased]: https://github.com/codebeltnet/benchmarkdotnet/compare/v1.3.3...HEAD -[1.3.4]: https://github.com/codebeltnet/benchmarkdotnet/compare/v1.3.3...HEAD +[1.3.5]: https://github.com/codebeltnet/benchmarkdotnet/compare/v1.3.4...v1.3.5 +[1.3.4]: https://github.com/codebeltnet/benchmarkdotnet/compare/v1.3.3...v1.3.4 [1.3.3]: https://github.com/codebeltnet/benchmarkdotnet/compare/v1.3.2...v1.3.3 [1.3.2]: https://github.com/codebeltnet/benchmarkdotnet/compare/v1.3.1...v1.3.2 [1.3.1]: https://github.com/codebeltnet/benchmarkdotnet/compare/v1.3.0...v1.3.1 From 46ffdaaf8ce6ceac7b5c2d5b02d1b25f91b3f9cd Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sat, 17 Oct 2026 20:03:50 +0200 Subject: [PATCH 6/8] =?UTF-8?q?=F0=9F=A7=AA=20switch=20test=20coverage=20t?= =?UTF-8?q?o=20Codebelt.Coverlet.MTP=20and=20add=20hang=20dumps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the Microsoft code coverage extension with Codebelt.Coverlet.MTP and adds the HangDump extension so hung test runs produce diagnostics. πŸ€– Generated with Codebuff Co-Authored-By: Codebuff --- Directory.Build.props | 3 ++- Directory.Packages.props | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 75831cb..0283897 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -81,8 +81,9 @@ + - + diff --git a/Directory.Packages.props b/Directory.Packages.props index c76636b..9d589af 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,13 +3,14 @@ true + - + From f499d187777653c8b68e2d4d9fa8598a28cbac78 Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sat, 17 Oct 2026 20:07:24 +0200 Subject: [PATCH 7/8] =?UTF-8?q?=F0=9F=93=9D=20update=20bot=20working=20not?= =?UTF-8?q?es=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Points the local agent-notes guidance at AGENTS.md now that copilot instructions are consolidated there. πŸ€– Generated with Codebuff Co-Authored-By: Codebuff --- .bot/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bot/README.md b/.bot/README.md index de97dce..f3aa97d 100644 --- a/.bot/README.md +++ b/.bot/README.md @@ -7,4 +7,4 @@ This folder is reserved for local-only AI working material such as: - design alternatives - temporary agent state -Keep this folder out of source control. Move only finalized, non-confidential guidance into `AGENTS.md` or `.github/copilot-instructions.md`. +Keep this folder out of source control. Move only finalized, non-confidential guidance into `AGENTS.md`. From 1909fa78280b6b0694dbce60d126d9e5f9bcd6b1 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 17 Oct 2026 20:27:17 +0200 Subject: [PATCH 8/8] =?UTF-8?q?=F0=9F=92=AC=20correct=20coverage=20tooling?= =?UTF-8?q?=20entry=20in=20changelog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corrects the 1.3.5 entry that described a routine CodeCoverage version bump when the change actually replaces it with Codebelt.Coverlet.MTP and adds HangDump, so maintainers are not misled. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62dc6e6..183e6c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ This is a patch release that updates dependencies, consolidates agent guidance a - Updated `Cuemon.Core` from 10.7.1 to 10.8.1, - Updated `Codebelt.Extensions.Xunit.App` from 12.0.1 to 12.0.2, - Updated `Microsoft.NET.Test.Sdk` from 18.10.0 to 18.11.0, -- Updated `Microsoft.Testing.Extensions.CodeCoverage` from 18.11.2 to 18.12.0, +- Replaced `Microsoft.Testing.Extensions.CodeCoverage` with `Codebelt.Coverlet.MTP` 10.1.0 and added `Microsoft.Testing.Extensions.HangDump` 2.5.1, - Updated `xunit.runner.visualstudio` from 4.0.0 to 4.0.1, - Updated `xunit.v3`, `xunit.v3.runner.console` from 4.0.0 to 4.0.2, - Updated `Codebelt.Bootstrapper.Console` from 5.2.1 to 5.2.2,