Disposable data-source roots leak when object-graph tracking throws in a nested getter

Aperta
#7,213 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
1-2 giorni
Idoneità per principianti
48/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
csharp
Ambito
testing

Direzione di ricerca

Start with ObjectTracker.TrackObjects and ObjectGraphDiscoverer.DiscoverAndTrackObjects in src/TUnit.Core/Tracking/ObjectTracker.cs, then trace the normal and skipped registration paths named in the issue. Reproduce the throwing nested getter in the supplied example and check disposal and reference counts for both paths, including shared objects. Done means roots discovered before the exception are disposed at test completion while shared reference counts remain correct.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug P2

What happens

When object-graph tracking for a test throws, the test's data-source objects are never disposed, including disposable root arguments that were created successfully.

ObjectTracker.TrackObjects (src/TUnit.Core/Tracking/ObjectTracker.cs) asks ObjectGraphDiscoverer.DiscoverAndTrackObjects for the test's object graph and only counts references after discovery finishes. If a nested property getter throws during discovery (for example an IAsyncInitializer-typed or injectable property on a class-data object), no reference is counted. Since PR #7191, the objects that discovery had already added to TestContext.TrackedObjects are also removed, so completing the test does not release references it never took.

As a result the root argument objects are neither counted nor tracked. Neither UntrackObjects at test completion nor the session-end sweep (DisposeAndClearStaticTrackingAsync) disposes them.

This affects both registration paths:

  • Normal registration: TestFilterService.RegisterTest → RegisterTestArgumentsAsync → ObjectLifecycleService.RegisterTestAsync → TrackObjects. The exception marks the test failed, and its roots leak. The same leak exists on main before #7191.
  • Skipped tests (#7156 / PR #7191): TrackSkippedTestArguments. The exception is caught and logged, the test stays skipped, and its roots leak. That is no worse than before #7156, when skipped tests' objects were never tracked.

Repro

public sealed class Root : IDisposable
{
    public static bool Disposed;
    public Nested Child => throw new InvalidOperationException("getter");
    public void Dispose() => Disposed = true;
}
public sealed class Nested : IAsyncInitializer { public Task InitializeAsync() => Task.CompletedTask; }

[ClassDataSource<Root>(Shared = SharedType.None)]
public class T(Root root) { [Test] public void A() { } }

From reading the code (not yet run): A fails during registration, and Root.Disposed stays false at session end, in both modes. Adding [Skip] to A should give the same result.

Expected

Roots that discovery has already produced are counted before nested traversal starts, or are kept when discovery fails, so they are disposed when the test completes. Rollback should remove only what nested discovery added. Shared objects must keep correct reference counts.

Found while reviewing CodeRabbit feedback on PR #7191 (src/TUnit.Engine/Services/TestFilterService.cs around line 126).

Lingua principale
C#
Stelle
4k
Fork
139
Merge medio
10h 27m
PR unite (30g)
236

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di thomhurst/TUnit

Tutte le issue di thomhurst/TUnit

Issue simili

Altre issue su C#

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.