public void TestAmbientManagedFirstEntry() { if (!EnvironmentSupportsTransactions) { Assert.Inconclusive("Cannot test transactions in this environment"); return; } Repository.Settings.StorageTransactionSettings = StorageTransactionSettings.RequireTransactions; TransactionSubscriber subscriber = new TransactionSubscriber(); IFileSystemTransaction transaction; using (TransactionScope masterScope = new TransactionScope()) { using (var scope = StorageTransactionScope.Create(Repository)) { Assert.AreEqual(1, StorageTransactionScope.ScopeNestLevel); Assert.IsTrue(scope.HasChangedContext, "Scope must have changed context"); Assert.IsFalse(scope.IsTransactionOwner, "Transaction must be slave under managed"); Assert.IsFalse(scope.ToBeDisposed, "Scope having created slave transaction must not be disposing"); Assert.IsNotNull(AmbientTransaction, "Context not set"); Assert.AreSame(AmbientTransaction, scope.UnderlyingTransaction, "Underlying transaction is not in sync with context"); Assert.IsTrue(scope.UnderlyingTransaction.IsActive, "Transaction must be active in this scope"); Assert.IsFalse(scope.UnderlyingTransaction.Unsubscribe(subscriber), "Unsubscribing not yet subscribed returned true"); scope.UnderlyingTransaction.Subscribe(subscriber); transaction = scope.UnderlyingTransaction; Assert.Throws( Is.InstanceOf <InvalidOperationException>() , () => transaction.Commit(), "Committing slave transaction must throw InvalidOperationException"); Assert.IsFalse(scope.ToBeDisposed, "Scope turned disposing after transaction detached"); Assert.IsFalse(scope.IsTransactionOwner); } Assert.AreEqual(0, StorageTransactionScope.ScopeNestLevel); Assert.IsTrue(transaction.IsActive, "Detached transaction must remain active after disposing scope"); Assert.AreEqual(0, subscriber.TimesNotified, "Disposing detached scope must not result in notification"); Assert.IsNull(KtmTransaction.Current, "The scope was disposed and must have restored context"); using (var scope = StorageTransactionScope.Create(Repository, transaction)) { Assert.AreEqual(1, StorageTransactionScope.ScopeNestLevel); Assert.AreSame(transaction, scope.UnderlyingTransaction, "Underlying transaction is not what was explicitly assigned"); Assert.IsTrue(scope.HasChangedContext, "Scope must have changed context"); Assert.IsFalse(scope.IsTransactionOwner, "Transaction must be slave under managed"); Assert.IsFalse(scope.ToBeDisposed, "Scope must not be disposing as explicitly specified when creating"); Assert.IsNotNull(AmbientTransaction, "Context not set"); Assert.AreSame(AmbientTransaction, scope.UnderlyingTransaction, "Underlying transaction is not in sync with context"); Assert.IsTrue(scope.UnderlyingTransaction.IsActive, "Transaction must be active in this scope"); scope.UnderlyingTransaction.Subscribe(subscriber); } int level = StorageTransactionScope.ScopeNestLevel; Assert.AreEqual(0, StorageTransactionScope.ScopeNestLevel); Assert.IsTrue(transaction.IsActive, "Detached transaction must remain active after disposing scope"); Assert.AreEqual(0, subscriber.TimesNotified, "Scope was not to dispose or commit transaction"); Assert.IsNull(AmbientTransaction, "The scope was disposed and must have restored context"); masterScope.Complete(); Assume.That(transaction.IsActive && subscriber.TimesNotified == 0); } System.Threading.Thread.Sleep(50); Assert.IsFalse(transaction.IsActive, "Master transaction was committed, KTM must be committed too"); Assert.AreEqual(1, subscriber.TimesNotified, "Master transaction was committed, must have recieved 1 notification"); Assert.IsTrue(subscriber.Committed, "Transaction must have beed reported committed."); Assert.Throws( Is.InstanceOf <InvalidOperationException>() , () => transaction.Subscribe(subscriber), "Subscribing to inactive transaction must throw exception"); }
public void TestRepeatedReuseSlave() { if (!EnvironmentSupportsTransactions) { Assert.Inconclusive("Cannot test transactions in this environment"); } else { Assume.That(!FileSystemProvider.IsStorageAmbientTransactionActive); Repository.Settings.StorageTransactionSettings = StorageTransactionSettings.RequireTransactions; TransactionSubscriber subscriber = new TransactionSubscriber(); IFileSystemTransaction transaction; LongSlaveTransactionManager tman = new LongSlaveTransactionManager(Repository, subscriber); using (TransactionScope masterScope = new TransactionScope()) { using (var scope = tman.GetTransactionScope()) { Assert.IsTrue(scope.HasChangedContext); Assert.IsFalse(scope.IsNullScope); Assert.IsFalse(scope.IsTransactionOwner); Assert.IsFalse(scope.NoTransaction); Assert.AreSame(AmbientTransaction, tman.PendingTransaction); Assert.AreSame(scope.UnderlyingTransaction, tman.PendingTransaction); Assert.IsTrue(tman.CanIOTransactionSpanMultipleRepositoryCalls); Assert.IsTrue(tman.IsTransactionPending()); Assert.AreEqual(1, StorageTransactionScope.ScopeNestLevel); transaction = AmbientTransaction; } Assert.AreEqual(0, StorageTransactionScope.ScopeNestLevel); Assert.IsNull(AmbientTransaction); Assert.IsNotNull(tman.PendingTransaction); Assert.IsFalse(tman.CanIOTransactionSpanMultipleRepositoryCalls, "No ambientr transaction here"); for (int n = 0; n < 10; ++n) { using (var scope = tman.GetTransactionScope()) { Assert.IsTrue(scope.HasChangedContext); Assert.IsFalse(scope.IsNullScope); Assert.IsFalse(scope.IsTransactionOwner); Assert.IsFalse(scope.NoTransaction); Assert.AreSame(transaction, tman.PendingTransaction); Assert.AreSame(AmbientTransaction, tman.PendingTransaction); Assert.AreSame(scope.UnderlyingTransaction, tman.PendingTransaction); Assert.IsTrue(tman.CanIOTransactionSpanMultipleRepositoryCalls); Assert.IsTrue(tman.IsTransactionPending()); Assert.AreEqual(1, StorageTransactionScope.ScopeNestLevel); transaction = AmbientTransaction; } Assert.AreEqual(0, StorageTransactionScope.ScopeNestLevel); Assert.IsNull(AmbientTransaction); Assert.IsNotNull(tman.PendingTransaction); Assert.IsFalse(tman.CanIOTransactionSpanMultipleRepositoryCalls, "No ambientr transaction here"); } //masterScope.Complete(); } // using (TransactionScope masterScope = new TransactionScope()) System.Threading.Thread.Sleep(50); Console.WriteLine("About to test times notified"); Assert.AreEqual(1, subscriber.TimesNotified, "Only 1 storage transaction must have been instantiated and therefore 1 notification received"); Assert.IsFalse(subscriber.Committed, "Master scope has not been completed"); //Assert.IsFalse(transaction.IsActive); Assert.IsNull(tman.PendingTransaction, "Must have received notification and reset pending transaction"); Assert.IsFalse(tman.CanIOTransactionSpanMultipleRepositoryCalls, "There should be no ambient transaction here at all"); tman.Dispose(); Assert.Throws <ObjectDisposedException>(() => tman.GetTransactionScope()); } }