@@ -410,40 +410,48 @@ public async ValueTask GrowIndexVersionSwitchTxnTest(
410410 /// orphaning the first semaphore in the waitingList. ProcessWaitingListAsync
411411 /// then waits on it forever.
412412 /// </summary>
413+ [ AllureNUnit ]
413414 [ TestFixture ]
414- public class TrackLastVersionTwoStoreDeadlock
415+ public class TrackLastVersionTwoStoreDeadlock : AllureTestBase
415416 {
416417 [ Test ]
417418 public async Task TrackLastVersionCalledTwiceDoesNotDeadlock ( )
418419 {
419420 var epoch = new LightEpoch ( ) ;
420- var driver = new StateMachineDriver ( epoch ) ;
421+ try
422+ {
423+ var driver = new StateMachineDriver ( epoch ) ;
421424
422- // Simulate an active transaction (e.g. Lua script touching both stores)
423- var txnVersion = driver . AcquireTransactionVersion ( ) ;
425+ // Simulate an active transaction (e.g. Lua script touching both stores)
426+ var txnVersion = driver . AcquireTransactionVersion ( ) ;
424427
425- // GlobalAfterEnteringState calls TrackLastVersion once per store
426- driver . TrackLastVersion ( txnVersion ) ; // MainStore
427- driver . TrackLastVersion ( txnVersion ) ; // ObjectStore
428+ // GlobalAfterEnteringState calls TrackLastVersion once per store
429+ driver . TrackLastVersion ( txnVersion ) ; // MainStore
430+ driver . TrackLastVersion ( txnVersion ) ; // ObjectStore
428431
429- // Transaction completes
430- driver . EndTransaction ( txnVersion ) ;
432+ // Transaction completes
433+ driver . EndTransaction ( txnVersion ) ;
431434
432- // Verify all waitingList semaphores are released (not orphaned)
433- var waitingList = ( System . Collections . Generic . List < System . Threading . SemaphoreSlim > )
434- typeof ( StateMachineDriver )
435- . GetField ( "waitingList" , System . Reflection . BindingFlags . NonPublic | System . Reflection . BindingFlags . Instance )
436- . GetValue ( driver ) ;
435+ // Verify all waitingList semaphores are released (not orphaned)
436+ var waitingList = ( System . Collections . Generic . List < System . Threading . SemaphoreSlim > )
437+ typeof ( StateMachineDriver )
438+ . GetField ( "waitingList" , System . Reflection . BindingFlags . NonPublic | System . Reflection . BindingFlags . Instance )
439+ . GetValue ( driver ) ;
437440
438- ClassicAssert . AreEqual ( 1 , waitingList . Count ,
439- "Expected 1 semaphore in waitingList, not 2. " +
440- "Two means the second TrackLastVersion call created a new semaphore " +
441- "that overwrote the first, orphaning it." ) ;
441+ ClassicAssert . AreEqual ( 1 , waitingList . Count ,
442+ "Expected 1 semaphore in waitingList, not 2. " +
443+ "Two means the second TrackLastVersion call created a new semaphore " +
444+ "that overwrote the first, orphaning it." ) ;
442445
443- var acquired = await waitingList [ 0 ] . WaitAsync ( System . TimeSpan . FromSeconds ( 5 ) ) ;
444- ClassicAssert . IsTrue ( acquired ,
445- "Semaphore was not released after EndTransaction. " +
446- "This causes ProcessWaitingListAsync to deadlock permanently." ) ;
446+ var acquired = await waitingList [ 0 ] . WaitAsync ( System . TimeSpan . FromSeconds ( 5 ) ) ;
447+ ClassicAssert . IsTrue ( acquired ,
448+ "Semaphore was not released after EndTransaction. " +
449+ "This causes ProcessWaitingListAsync to deadlock permanently." ) ;
450+ }
451+ finally
452+ {
453+ epoch . Dispose ( ) ;
454+ }
447455 }
448456 }
449457}
0 commit comments