Skip to content

feat: bridge ITimeSystem to the BCL System.TimeProvider#1044

Merged
vbreuss merged 1 commit into
mainfrom
feat/system-timeprovider-bridge
Jul 10, 2026
Merged

feat: bridge ITimeSystem to the BCL System.TimeProvider#1044
vbreuss merged 1 commit into
mainfrom
feat/system-timeprovider-bridge

Conversation

@vbreuss

@vbreuss vbreuss commented Jul 10, 2026

Copy link
Copy Markdown
Member

Add an ITimeSystem.ToTimeProvider() extension that wraps any time system (in particular a MockTimeSystem) as a real System.TimeProvider, so it can be injected into code that consumes the built-in .NET time abstraction (HttpClient, System.Threading.Channels, Microsoft.Extensions.*). Advancing the mock clock is observable through GetUtcNow() and GetTimestamp(), and CreateTimer(...) is routed through the mock timer.

The adapter overrides GetUtcNow, GetTimestamp/TimestampFrequency (which keeps the base GetElapsedTime correct because the mock stopwatch is self-consistent) and CreateTimer, adapting the time system's ITimer to System.Threading.ITimer. It is gated behind a new FEATURE_TIMEPROVIDER flag (net8.0+, where System.TimeProvider is intrinsic, so no additional package dependency is required).

Placed in Testably.Abstractions.Testing because that project references the interface via a package reference and because the primary use case is feeding mock time into code that already takes System.TimeProvider.

Note: System.TimeProvider must be fully qualified throughout, because the unqualified name binds to the existing static Testably.Abstractions.Testing.TimeProvider factory even from nested namespaces.


@vbreuss vbreuss self-assigned this Jul 10, 2026
@vbreuss vbreuss added the enhancement New feature or request label Jul 10, 2026
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

Test Results

    102 files  ±  0      102 suites  ±0   2h 24m 42s ⏱️ - 4m 41s
112 598 tests +  5   99 988 ✅ +  5  12 610 💤 ±0  0 ❌ ±0 
269 306 runs  +216  232 594 ✅ +216  36 712 💤 ±0  0 ❌ ±0 

Results for commit 0b6961d. ± Comparison against base commit 696ffa9.

This pull request removes 109749 and adds 109753 tests. Note that renamed tests count towards both.
  )
)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(0be706b5-98d3-4a22-ad18-f3674a32723b)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(0ef9080e-9a1a-4316-b8a3-6fc6452834b7)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(105354ab-fb15-4339-8d2d-f88066f061e7)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(1708397d-518b-466f-abf4-264b56563dc5)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(2351e0da-4f78-4698-b73a-adf83d72c7fe)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(25787a92-4b56-4f63-a04a-b35dfa13a0de)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(2e219b63-51d0-4f8d-97c9-e5a0250327fd)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(353506a0-c0ac-4917-b666-4519ff84b2f7)
…
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(05d123e7-9ffe-43e4-9998-8eaa7267dae8)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(0954906d-6118-4659-badb-46ea81eac29e)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(10ee308c-85c5-4afa-91d6-f98441fb5c6a)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(1280cb20-b448-4f60-878d-6f0a0f2ed2de)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(1281418d-6b6a-408c-8972-ec3e91008559)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(13c04501-9c0b-4fc3-9cfd-20f08cd58777)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(1af01eea-08d6-4a25-800e-b43f3c513591)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(1c9227bf-d813-469b-a0c1-7a6feb936864)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(2a36a609-b77a-4572-b647-c42da435bc57)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(2c9e7f2e-719a-489e-b4c3-bd31dd5e1bc6)
…
This pull request removes 12552 skipped tests and adds 12552 skipped tests. Note that renamed tests count towards both.
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(0be706b5-98d3-4a22-ad18-f3674a32723b)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(0ef9080e-9a1a-4316-b8a3-6fc6452834b7)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(105354ab-fb15-4339-8d2d-f88066f061e7)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(1708397d-518b-466f-abf4-264b56563dc5)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(2351e0da-4f78-4698-b73a-adf83d72c7fe)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(25787a92-4b56-4f63-a04a-b35dfa13a0de)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(2e219b63-51d0-4f8d-97c9-e5a0250327fd)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(353506a0-c0ac-4917-b666-4519ff84b2f7)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(3bef1e0b-591f-4418-899d-c5465456e0c0)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(3e3935fa-95a6-477a-b145-9ed7705849cc)
…
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(05d123e7-9ffe-43e4-9998-8eaa7267dae8)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(0954906d-6118-4659-badb-46ea81eac29e)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(10ee308c-85c5-4afa-91d6-f98441fb5c6a)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(1280cb20-b448-4f60-878d-6f0a0f2ed2de)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(1281418d-6b6a-408c-8972-ec3e91008559)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(13c04501-9c0b-4fc3-9cfd-20f08cd58777)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(1af01eea-08d6-4a25-800e-b43f3c513591)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(1c9227bf-d813-469b-a0c1-7a6feb936864)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(2a36a609-b77a-4572-b647-c42da435bc57)
Testably.Abstractions.AccessControl.Tests.DirectoryInfoAclExtensionsTests ‑ SetAccessControl_ShouldNotUpdateTimes(2c9e7f2e-719a-489e-b4c3-bd31dd5e1bc6)
…

♻️ This comment has been updated with latest results.

@vbreuss vbreuss force-pushed the feat/system-timeprovider-bridge branch 3 times, most recently from 5d59c88 to 4e7b61c Compare July 10, 2026 15:52
Add an `ITimeSystem.ToTimeProvider()` extension that wraps any time system (in particular a `MockTimeSystem`) as a real `System.TimeProvider`, so it can be injected into code that consumes the built-in .NET time abstraction (`HttpClient`, `System.Threading.Channels`, `Microsoft.Extensions.*`). Advancing the mock clock is observable through `GetUtcNow()` and `GetTimestamp()`, and `CreateTimer(...)` is routed through the mock timer.

The adapter overrides `GetUtcNow`, `GetTimestamp`/`TimestampFrequency` (which keeps the base `GetElapsedTime` correct because the mock stopwatch is self-consistent) and `CreateTimer`, adapting the time system's `ITimer` to `System.Threading.ITimer`. It is gated behind a new `FEATURE_TIMEPROVIDER` flag (net8.0+, where `System.TimeProvider` is intrinsic, so no additional package dependency is required).

Placed in `Testably.Abstractions.Testing` because that project references the interface via a package reference and because the primary use case is feeding mock time into code that already takes `System.TimeProvider`.

Note: `System.TimeProvider` must be fully qualified throughout, because the unqualified name binds to the existing static `Testably.Abstractions.Testing.TimeProvider` factory even from nested namespaces.
@vbreuss vbreuss force-pushed the feat/system-timeprovider-bridge branch from 4e7b61c to 0b6961d Compare July 10, 2026 15:53
@sonarqubecloud

sonarqubecloud Bot commented Jul 10, 2026

Copy link
Copy Markdown

@vbreuss vbreuss merged commit 5e21b5d into main Jul 10, 2026
14 checks passed
@vbreuss vbreuss deleted the feat/system-timeprovider-bridge branch July 10, 2026 19:15
@github-actions

Copy link
Copy Markdown

This is addressed in release v7.0.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request state: released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide a bridge to the BCL System.TimeProvider

1 participant