Add Owned<T> behaviour comparison suite vs Autofac (tests for #147) - #148
Merged
NikolayPianikov merged 2 commits intoJul 19, 2026
Merged
Conversation
added 2 commits
July 17, 2026 16:17
Adds a suite under tests/Pure.DI.UsageTests/Owned that pins Pure.DI's Owned<T> disposal and lifetime behaviour against Autofac's Owned<T> as the reference implementation. Every test asserts both containers against the same expected literal; the Autofac side compiles only when AUTOFAC_REFERENCE is defined (via a local, git-ignored .csproj.user), so the committed suite has no Autofac dependency and builds clean without it. 23 tests document confirmed parity: transient/singleton/scoped disposal, root isolation, owned-of-singleton lifetime, mixed-lifetime nested graphs, diamond (shared) dependencies, LIFO disposal order, factory-created disposables, all async-disposal paths (incl. sync-over-async and mixed sync/async), double-dispose idempotency, and explicit release by a singleton owner. 5 tests fail on purpose, documenting divergences from Autofac: - Func<Owned<T>> reuses a single per-resolution accumulator, so in the canonical message-pump loop only the first unit of work is disposed and every later one leaks (instance never disposed and pinned by the shared accumulator). - Nested Owned<T> share that same accumulator, so disposing either the outer or the inner Owned<T> disposes both graphs. - Owned<T>.Dispose() swallows exceptions thrown by a component's Dispose() (routed to the empty OnDisposeException partial); Autofac surfaces them. - A never-released Owned<T> is not disposed on composition disposal; Autofac disposes it as a container-level safety net.
Explains the suite's purpose, how to enable the Autofac reference oracle locally (the git-ignored .csproj.user with the AUTOFAC_REFERENCE symbol and the Autofac package), how to run it, and a table of the parity results and the five intentional failures with their shared root cause.
This was referenced Jul 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follows up on #147.
Adds an
Owned<T>behaviour-comparison suite undertests/Pure.DI.UsageTests/Owned/(14 files, 28 tests). It uses differential testing: each test asserts Pure.DI and Autofac'sOwned<T>against the same expected value, with Autofac as a proven reference implementation. That gives two things at once:They document the defects from #147 and are expected to stay red until
Owned<T>is fixed:MessagePumpTests— a capturedFunc<Owned<T>>reuses one accumulator per resolution, so in the canonical message-pump loop only the first unit of work is disposed; the rest leak.NestedOwnedTests(×2) — outer and innerOwned<T>share that same accumulator, so disposing either disposes both graphs.DisposalExceptionTests—Owned<T>.Dispose()swallows exceptions thrown by a component'sDispose(); Autofac surfaces them.SingletonOwnerTests— a never-releasedOwned<T>is not disposed on composition disposal; Autofac disposes it as a container-level safety net.The first three share one root cause (a single
Ownedaccumulator reused per composition-root resolution instead of one perOwned<T>).23 tests confirm parity
Transient/singleton/scoped disposal, root isolation, owned-of-singleton lifetime, mixed-lifetime nested graphs, diamond (shared) dependencies, LIFO disposal order, factory-created disposables, all async-disposal paths (including sync-over-async and mixed sync/async), double-dispose idempotency, and explicit release by a singleton owner.
No Autofac dependency by default
All Autofac code is compiled only under the
AUTOFAC_REFERENCEsymbol; the package reference is not committed (it lives in a git-ignored.csproj.user). Without the symbol — the default, and what CI sees — the suite builds and runs as pure Pure.DI tests, no Autofac package or reference. The same 5 tests fail either way; the Autofac side just adds an independent witness that the expected values are correct. Seetests/Pure.DI.UsageTests/Owned/README.mdfor the enable recipe.Verified locally on
net10.0: builds with 0 warnings and runs 23 passed / 5 failed both with and withoutAUTOFAC_REFERENCE.Run just this suite