Skip to content

perf(engine): collapse async state machines on hook cache-hit / empty-hook path (#5713)#5726

Merged
thomhurst merged 1 commit intomainfrom
perf/5713-hook-cache-hit
Apr 24, 2026
Merged

perf(engine): collapse async state machines on hook cache-hit / empty-hook path (#5713)#5726
thomhurst merged 1 commit intomainfrom
perf/5713-hook-cache-hit

Conversation

@thomhurst
Copy link
Copy Markdown
Owner

Closes #5713

Summary

  • Per-test hot path previously materialized ~4 async state machines even when the per-class hook cache was populated and the hook lists were empty. HookDelegateBuilder.Collect*(Test|Class|Assembly)HooksAsync were marked async and still boxed a state machine on cache hit; HookExecutor.Execute(Before|After)TestHooksAsync awaited every hook accessor even when both lists were empty.
  • Split each Collect*HooksAsync into a sync ValueTask-returning wrapper (cache hit returns synchronously) plus a private async builder helper used only on cache miss.
  • Added sync TryGetCached(Before|After)TestHooks + GetCached(Before|After)EveryTestHooks accessors to IHookDelegateBuilder. HookExecutor.Execute(Before|After)TestHooksAsync is now a non-async wrapper that returns a completed ValueTask when both lists are known-empty, and delegates to a private core helper only when hooks exist.
  • Hook ordering semantics preserved: beforeEvery -> before for Before, after -> afterEvery for After.

Expected impact

  • ~1% CPU per test on the steady-state path.
  • 4 fewer async state machines allocated per test.

Test plan

  • dotnet build TUnit.slnx -c Release (0 errors, 237 warnings — all pre-existing)
  • TUnit.Core.SourceGenerator.Tests snapshot suite (net10.0): 116 passed, 1 pre-existing skip
  • TUnit.TestProject -- --treenode-filter "/*/*/HookExecutorTests/*" (net10.0): 5/5 pass
  • TUnit.TestProject -- --treenode-filter "/*/*/HookExecutorHookTests_*/*" (net10.0): 4/4 pass
  • TUnit.Engine.Tests -- --treenode-filter "/*/*/HookExecutionOrderTests/*" (net10.0): 1/1 pass (ordering invariant holds)
  • TUnit.UnitTests (net10.0): 180/180 pass (exercises StubHookDelegateBuilder with the new interface members)

…-hook path (#5713)

Each test previously materialized ~4 async state machines when iterating
hooks even though the steady-state path is fully synchronous:

- HookDelegateBuilder.Collect(Before|After)(Test|Class|Assembly)HooksAsync
  was marked `async` with a cache-hit short-circuit, forcing a state
  machine on every call once the cache was populated.
- HookExecutor.Execute(Before|After)TestHooksAsync awaited both the
  BeforeEvery/AfterEvery and Before/After lists unconditionally, even
  when both were empty.

Changes:
- Split the Collect* methods into a sync ValueTask-returning wrapper
  (cache hit) and a private async helper (cache miss).
- Add sync TryGetCached(Before|After)TestHooks + GetCached(Before|After)
  EveryTestHooks accessors on IHookDelegateBuilder.
- Make ExecuteBeforeTestHooksAsync / ExecuteAfterTestHooksAsync
  non-async wrappers that early-return a completed ValueTask when
  both hook lists are known-empty, delegating to a private core
  helper only when work is required.

Hook ordering (beforeEvery -> before, after -> afterEvery) is preserved.
Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Overall: Solid, well-scoped performance optimization. No blocking issues.

This PR correctly applies the standard C# "sync fast-path / async slow-path" pattern to eliminate ~4 async state machine allocations per test on the steady-state (no-hooks) path. The approach is idiomatic and follows TUnit's existing ValueTask conventions.


What works well

  • Correctness on all three paths: The cache-miss path (first test of a given class type), the cache-hit path, and the empty-hooks short-circuit all behave identically to the original semantics. The TryGetCachedBeforeTestHooks / hasCachedBeforeTestHooks guard correctly prevents the empty-list short-circuit from firing on a cold cache, so the full async build path is still taken when needed.
  • Consistent pattern across all hook scopes: The same refactor is applied to Class, Assembly, and Session hook builders — not just Test. This is the right call; it eliminates the unnecessary state machine on every cache hit regardless of scope.
  • Incidental .ConfigureAwait(false) additions: The new private BuildAndCache* helpers now have .ConfigureAwait(false) that the original async methods were missing. Small but correct improvement.
  • Interface changes are appropriately scoped: IHookDelegateBuilder is internal, all implementors are in-repo, and the unit-test stub (StubHookDelegateBuilder) is correctly updated to implement the four new members.

One observation worth noting (not a blocker)

_beforeEveryTestHooks / _afterEveryTestHooks visibility on the read path

GetCachedBeforeEveryTestHooks() reads _beforeEveryTestHooks without a memory barrier and returns _beforeEveryTestHooks ?? []. This is safe today because InitializeAsync() is fully awaited before any test executes — so the write always happens-before the reads. But if that startup ordering were ever relaxed, a test thread could observe null and silently run with an empty hook list instead of the real one.

This is an existing pattern in the codebase and is fine here, but consider adding a brief comment or an ObjectDisposedException/assertion guard if this ever moves to a lazier initialization model.


Impact

For a test suite with thousands of tests and no hooks (the most common case), this removes 4 heap allocations per test. On 10 000 tests that's 40 000 fewer short-lived objects on the heap per run — a meaningful reduction in GC pressure with no behavior change. The "~1% CPU" estimate is plausible and likely conservative on allocation-heavy workloads.

Approved. Clean implementation of an established C# perf pattern, correct across all edge cases.

@codacy-production
Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 22 complexity

Metric Results
Complexity 22

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@thomhurst
Copy link
Copy Markdown
Owner Author

macOS CI failure diagnosis

The macOS failure is unrelated to this PR's changes.

Failing test: GenerateMock_Attribute_With_Concrete_Class in TUnit.Mocks.SourceGenerator.Tests — a snapshot-comparison test for the mock source generator output. The PR touches only HookExecutor, HookDelegateBuilder, IHookDelegateBuilder, and a unit test in TUnit.UnitTests — none of which are reachable from that source-generator snapshot test.

Evidence this is pre-existing: The prior macOS run on main (run 24864304955, commit 35e2ef3) had multiple TUnit.Mocks.SourceGenerator.Tests snapshot mismatches on both macOS and Ubuntu, before this PR was opened. Looks like a platform-specific snapshot flake (likely line-ending / analyzer version / arm64-vs-x64 generator output differences) that is already affecting main.

Action: Once the current workflow run finishes (Windows + Ubuntu jobs are still in progress in the same run, so it can't be re-run partial yet) I'll re-run the failed macOS job. Alternatively any new push will trigger a fresh run.

@thomhurst thomhurst merged commit a01ad00 into main Apr 24, 2026
14 of 15 checks passed
@thomhurst thomhurst deleted the perf/5713-hook-cache-hit branch April 24, 2026 13:54
This was referenced Apr 26, 2026
intellitect-bot pushed a commit to IntelliTect/EssentialCSharp.Web that referenced this pull request Apr 27, 2026
Updated [TUnit](https://github.com/thomhurst/TUnit) from 1.39.0 to
1.40.5.

<details>
<summary>Release notes</summary>

_Sourced from [TUnit's
releases](https://github.com/thomhurst/TUnit/releases)._

## 1.40.5

<!-- Release notes generated using configuration in .github/release.yml
at v1.40.5 -->

## What's Changed
### Other Changes
* Fix reflection property injection reuse by @​thomhurst in
thomhurst/TUnit#5763
* fix(assertions): gate IsEqualTo<TValue, TOther> overload to net9+
(#​5765) by @​thomhurst in thomhurst/TUnit#5767
### Dependencies
* chore(deps): update tunit to 1.40.0 by @​thomhurst in
thomhurst/TUnit#5762


**Full Changelog**:
thomhurst/TUnit@v1.40.0...v1.40.5

## 1.40.0

<!-- Release notes generated using configuration in .github/release.yml
at v1.40.0 -->

## What's Changed
### Other Changes
* perf(engine): collapse async forwarding wrappers in test execution
(#​5714) by @​thomhurst in thomhurst/TUnit#5725
* perf(engine): skip Console.Out/Err FlushAsync when no output captured
(#​5712) by @​thomhurst in thomhurst/TUnit#5724
* perf(engine): collapse async state machines on hook cache-hit /
empty-hook path (#​5713) by @​thomhurst in
thomhurst/TUnit#5726
* perf: eliminate per-test closure + GetOrAdd factory alloc (#​5710) by
@​thomhurst in thomhurst/TUnit#5727
* perf(engine): replace global lock in EventReceiverRegistry with
lock-free CAS by @​thomhurst in
thomhurst/TUnit#5731
* perf(engine): batch per-test overhead cleanups (#​5719) by @​thomhurst
in thomhurst/TUnit#5730
* #​5733 handling all arguments for Fact and Theory by @​inyutin-maxim
in thomhurst/TUnit#5734
* fix(assertions): prefer string overload of Member() over
IEnumerable<char> (#​5702) by @​thomhurst in
thomhurst/TUnit#5721
* fix(migration): preserve comments/XML docs when removing sole
attributes (#​5698) by @​thomhurst in
thomhurst/TUnit#5739
* perf(build): trim test TFMs and skip viewer dump by default by
@​thomhurst in thomhurst/TUnit#5741
* fix(pipeline): skip TestBaseModule frameworks with missing binaries by
@​thomhurst in thomhurst/TUnit#5752
* feat(assertions): focused diff messages for IsEqualTo/IsEquivalentTo
(#​5732) by @​thomhurst in thomhurst/TUnit#5747
* fix(analyzers): remove incorrect AOT rules TUnit0300/0301/0302
(#​5722) by @​thomhurst in thomhurst/TUnit#5746
* perf(engine): lazy hook metadata registration (#​5448) by @​thomhurst
in thomhurst/TUnit#5750
* chore(templates): unify TUnit version pinning to 1.* (#​5709) by
@​thomhurst in thomhurst/TUnit#5743
* fix(templates): floating TUnit.Aspire version (#​5708) by @​thomhurst
in thomhurst/TUnit#5742
* fix(assertions): preserve specialised source in .Count(itemAssertion)
(#​5707) by @​thomhurst in thomhurst/TUnit#5749
* feat(assertions): IsEqualTo with implicitly-convertible wrappers
(#​5720) by @​thomhurst in thomhurst/TUnit#5751
* feat(aspire): add ability to manually remove resources by @​Odonno in
thomhurst/TUnit#5586
* fix(fscheck): register default CancellationToken arbitrary that
surfaces TestContext token by @​JohnVerheij in
thomhurst/TUnit#5758
* fix(engine): allow keyed NotInParallel tests to run alongside
unconstrained tests (#​5700) by @​thomhurst in
thomhurst/TUnit#5740
* perf: skip TimeoutHelper wrap when no explicit [Timeout] is set
(#​5711) by @​thomhurst in thomhurst/TUnit#5728
### Dependencies
* chore(deps): update tunit to 1.39.0 by @​thomhurst in
thomhurst/TUnit#5701
* chore(deps): update aspire to 13.2.4 by @​thomhurst in
thomhurst/TUnit#5735
* chore(deps): bump postcss from 8.5.6 to 8.5.10 in /docs by
@​dependabot[bot] in thomhurst/TUnit#5736
* chore(deps): update dependency fscheck to 3.3.3 by @​thomhurst in
thomhurst/TUnit#5760

## New Contributors
* @​inyutin-maxim made their first contribution in
thomhurst/TUnit#5734
* @​Odonno made their first contribution in
thomhurst/TUnit#5586

**Full Changelog**:
thomhurst/TUnit@v1.39.0...v1.40.0

Commits viewable in [compare
view](thomhurst/TUnit@v1.39.0...v1.40.5).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit&package-manager=nuget&previous-version=1.39.0&new-version=1.40.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
github-actions Bot pushed a commit to IntelliTect/CodingGuidelines that referenced this pull request Apr 27, 2026
Updated [TUnit.Core](https://github.com/thomhurst/TUnit) from 1.37.0 to
1.40.10.

<details>
<summary>Release notes</summary>

_Sourced from [TUnit.Core's
releases](https://github.com/thomhurst/TUnit/releases)._

## 1.40.10

<!-- Release notes generated using configuration in .github/release.yml
at v1.40.10 -->

## What's Changed
### Other Changes
* refactor(opentelemetry): depend on TUnit.Core instead of umbrella
TUnit by @​thomhurst in thomhurst/TUnit#5774
### Dependencies
* chore(deps): update tunit to 1.40.5 by @​thomhurst in
thomhurst/TUnit#5769


**Full Changelog**:
thomhurst/TUnit@v1.40.5...v1.40.10

## 1.40.5

<!-- Release notes generated using configuration in .github/release.yml
at v1.40.5 -->

## What's Changed
### Other Changes
* Fix reflection property injection reuse by @​thomhurst in
thomhurst/TUnit#5763
* fix(assertions): gate IsEqualTo<TValue, TOther> overload to net9+
(#​5765) by @​thomhurst in thomhurst/TUnit#5767
### Dependencies
* chore(deps): update tunit to 1.40.0 by @​thomhurst in
thomhurst/TUnit#5762


**Full Changelog**:
thomhurst/TUnit@v1.40.0...v1.40.5

## 1.40.0

<!-- Release notes generated using configuration in .github/release.yml
at v1.40.0 -->

## What's Changed
### Other Changes
* perf(engine): collapse async forwarding wrappers in test execution
(#​5714) by @​thomhurst in thomhurst/TUnit#5725
* perf(engine): skip Console.Out/Err FlushAsync when no output captured
(#​5712) by @​thomhurst in thomhurst/TUnit#5724
* perf(engine): collapse async state machines on hook cache-hit /
empty-hook path (#​5713) by @​thomhurst in
thomhurst/TUnit#5726
* perf: eliminate per-test closure + GetOrAdd factory alloc (#​5710) by
@​thomhurst in thomhurst/TUnit#5727
* perf(engine): replace global lock in EventReceiverRegistry with
lock-free CAS by @​thomhurst in
thomhurst/TUnit#5731
* perf(engine): batch per-test overhead cleanups (#​5719) by @​thomhurst
in thomhurst/TUnit#5730
* #​5733 handling all arguments for Fact and Theory by @​inyutin-maxim
in thomhurst/TUnit#5734
* fix(assertions): prefer string overload of Member() over
IEnumerable<char> (#​5702) by @​thomhurst in
thomhurst/TUnit#5721
* fix(migration): preserve comments/XML docs when removing sole
attributes (#​5698) by @​thomhurst in
thomhurst/TUnit#5739
* perf(build): trim test TFMs and skip viewer dump by default by
@​thomhurst in thomhurst/TUnit#5741
* fix(pipeline): skip TestBaseModule frameworks with missing binaries by
@​thomhurst in thomhurst/TUnit#5752
* feat(assertions): focused diff messages for IsEqualTo/IsEquivalentTo
(#​5732) by @​thomhurst in thomhurst/TUnit#5747
* fix(analyzers): remove incorrect AOT rules TUnit0300/0301/0302
(#​5722) by @​thomhurst in thomhurst/TUnit#5746
* perf(engine): lazy hook metadata registration (#​5448) by @​thomhurst
in thomhurst/TUnit#5750
* chore(templates): unify TUnit version pinning to 1.* (#​5709) by
@​thomhurst in thomhurst/TUnit#5743
* fix(templates): floating TUnit.Aspire version (#​5708) by @​thomhurst
in thomhurst/TUnit#5742
* fix(assertions): preserve specialised source in .Count(itemAssertion)
(#​5707) by @​thomhurst in thomhurst/TUnit#5749
* feat(assertions): IsEqualTo with implicitly-convertible wrappers
(#​5720) by @​thomhurst in thomhurst/TUnit#5751
* feat(aspire): add ability to manually remove resources by @​Odonno in
thomhurst/TUnit#5586
* fix(fscheck): register default CancellationToken arbitrary that
surfaces TestContext token by @​JohnVerheij in
thomhurst/TUnit#5758
* fix(engine): allow keyed NotInParallel tests to run alongside
unconstrained tests (#​5700) by @​thomhurst in
thomhurst/TUnit#5740
* perf: skip TimeoutHelper wrap when no explicit [Timeout] is set
(#​5711) by @​thomhurst in thomhurst/TUnit#5728
### Dependencies
* chore(deps): update tunit to 1.39.0 by @​thomhurst in
thomhurst/TUnit#5701
* chore(deps): update aspire to 13.2.4 by @​thomhurst in
thomhurst/TUnit#5735
* chore(deps): bump postcss from 8.5.6 to 8.5.10 in /docs by
@​dependabot[bot] in thomhurst/TUnit#5736
* chore(deps): update dependency fscheck to 3.3.3 by @​thomhurst in
thomhurst/TUnit#5760

## New Contributors
* @​inyutin-maxim made their first contribution in
thomhurst/TUnit#5734
* @​Odonno made their first contribution in
thomhurst/TUnit#5586

**Full Changelog**:
thomhurst/TUnit@v1.39.0...v1.40.0

## 1.39.0

<!-- Release notes generated using configuration in .github/release.yml
at v1.39.0 -->

## What's Changed
### Other Changes
* perf(mocks): shrink MethodSetup + cache stateless matchers by
@​thomhurst in thomhurst/TUnit#5669
* fix(mocks): handle base classes with explicit interface impls (#​5673)
by @​thomhurst in thomhurst/TUnit#5674
* fix(mocks): implement indexer in generated mock (#​5676) by
@​thomhurst in thomhurst/TUnit#5683
* fix(mocks): disambiguate IEquatable<T>.Equals from object.Equals
(#​5675) by @​thomhurst in thomhurst/TUnit#5680
* fix(mocks): escape C# keyword identifiers at all emit sites (#​5679)
by @​thomhurst in thomhurst/TUnit#5684
* fix(mocks): emit [SetsRequiredMembers] on generated mock ctor (#​5678)
by @​thomhurst in thomhurst/TUnit#5682
* fix(mocks): skip MockBridge for class targets with static-abstract
interfaces (#​5677) by @​thomhurst in
thomhurst/TUnit#5681
* chore(mocks): regenerate source generator snapshots by @​thomhurst in
thomhurst/TUnit#5691
* perf(engine): collapse async state-machine layers on hot test path
(#​5687) by @​thomhurst in thomhurst/TUnit#5690
* perf(engine): reduce lock contention in scheduling and hook caches
(#​5686) by @​thomhurst in thomhurst/TUnit#5693
* fix(assertions): prevent implicit-to-string op from NREing on null
(#​5692) by @​thomhurst in thomhurst/TUnit#5696
* perf(engine/core): reduce per-test allocations (#​5688) by @​thomhurst
in thomhurst/TUnit#5694
* perf(engine): reduce message-bus contention on test start (#​5685) by
@​thomhurst in thomhurst/TUnit#5695
### Dependencies
* chore(deps): update tunit to 1.37.36 by @​thomhurst in
thomhurst/TUnit#5667
* chore(deps): update verify to 31.16.2 by @​thomhurst in
thomhurst/TUnit#5699


**Full Changelog**:
thomhurst/TUnit@v1.37.36...v1.39.0

## 1.37.36

<!-- Release notes generated using configuration in .github/release.yml
at v1.37.36 -->

## What's Changed
### Other Changes
* fix(telemetry): remove duplicate HTTP client spans by @​thomhurst in
thomhurst/TUnit#5668


**Full Changelog**:
thomhurst/TUnit@v1.37.35...v1.37.36

## 1.37.35

<!-- Release notes generated using configuration in .github/release.yml
at v1.37.35 -->

## What's Changed
### Other Changes
* Add TUnit.TestProject.Library to the TUnit.Dev.slnx solution file by
@​Zodt in thomhurst/TUnit#5655
* fix(aspire): preserve user-supplied OTLP endpoint (#​4818) by
@​thomhurst in thomhurst/TUnit#5665
* feat(aspire): emit client spans for HTTP by @​thomhurst in
thomhurst/TUnit#5666
### Dependencies
* chore(deps): update dependency dotnet-sdk to v10.0.203 by @​thomhurst
in thomhurst/TUnit#5656
* chore(deps): update microsoft.aspnetcore to 10.0.7 by @​thomhurst in
thomhurst/TUnit#5657
* chore(deps): update tunit to 1.37.24 by @​thomhurst in
thomhurst/TUnit#5659
* chore(deps): update microsoft.extensions to 10.0.7 by @​thomhurst in
thomhurst/TUnit#5658
* chore(deps): update aspire to 13.2.3 by @​thomhurst in
thomhurst/TUnit#5661
* chore(deps): update dependency microsoft.net.test.sdk to 18.5.0 by
@​thomhurst in thomhurst/TUnit#5664

## New Contributors
* @​Zodt made their first contribution in
thomhurst/TUnit#5655

**Full Changelog**:
thomhurst/TUnit@v1.37.24...v1.37.35

## 1.37.24

<!-- Release notes generated using configuration in .github/release.yml
at v1.37.24 -->

## What's Changed
### Other Changes
* docs: add Tluma Ask AI widget to Docusaurus site by @​thomhurst in
thomhurst/TUnit#5638
* Revert "chore(deps): update dependency docusaurus-plugin-llms to
^0.4.0 (#​5637)" by @​thomhurst in
thomhurst/TUnit#5640
* fix(asp-net): forward disposal in FlowSuppressingHostedService
(#​5651) by @​JohnVerheij in
thomhurst/TUnit#5652
### Dependencies
* chore(deps): update dependency docusaurus-plugin-llms to ^0.4.0 by
@​thomhurst in thomhurst/TUnit#5637
* chore(deps): update tunit to 1.37.10 by @​thomhurst in
thomhurst/TUnit#5639
* chore(deps): update opentelemetry to 1.15.3 by @​thomhurst in
thomhurst/TUnit#5645
* chore(deps): update opentelemetry by @​thomhurst in
thomhurst/TUnit#5647
* chore(deps): update dependency dompurify to v3.4.1 by @​thomhurst in
thomhurst/TUnit#5648
* chore(deps): update dependency system.commandline to 2.0.7 by
@​thomhurst in thomhurst/TUnit#5650
* chore(deps): update dependency microsoft.entityframeworkcore to 10.0.7
by @​thomhurst in thomhurst/TUnit#5649
* chore(deps): update dependency microsoft.templateengine.authoring.cli
to v10.0.203 by @​thomhurst in
thomhurst/TUnit#5653
* chore(deps): update dependency
microsoft.templateengine.authoring.templateverifier to 10.0.203 by
@​thomhurst in thomhurst/TUnit#5654


**Full Changelog**:
thomhurst/TUnit@v1.37.10...v1.37.24

## 1.37.10

<!-- Release notes generated using configuration in .github/release.yml
at v1.37.10 -->

## What's Changed
### Other Changes
* docs(test-filters): add migration callout for --filter →
--treenode-filter by @​johnkattenhorn in
thomhurst/TUnit#5628
* fix: re-enable RPC tests and modernize harness (#​5540) by @​thomhurst
in thomhurst/TUnit#5632
* fix(mocks): propagate [Obsolete] and null-forgiving raise dispatch
(#​5626) by @​JohnVerheij in
thomhurst/TUnit#5631
* ci: use setup-dotnet built-in NuGet cache by @​thomhurst in
thomhurst/TUnit#5635
* feat(playwright): propagate W3C trace context into browser contexts by
@​thomhurst in thomhurst/TUnit#5636
### Dependencies
* chore(deps): update tunit to 1.37.0 by @​thomhurst in
thomhurst/TUnit#5625

## New Contributors
* @​johnkattenhorn made their first contribution in
thomhurst/TUnit#5628
* @​JohnVerheij made their first contribution in
thomhurst/TUnit#5631

**Full Changelog**:
thomhurst/TUnit@v1.37.0...v1.37.10

Commits viewable in [compare
view](thomhurst/TUnit@v1.37.0...v1.40.10).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit.Core&package-manager=nuget&previous-version=1.37.0&new-version=1.40.10)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf: collapse async state machines on hook cache-hit / empty-hook path

1 participant