private static void TestCase_VolatileEnlistments( int count, TransactionStatus expectedOutcome, EnlistmentOptions options = EnlistmentOptions.None, bool commitTx = true, bool votePrepared = true, Type expectedExceptionType = null) { string testCaseDescription = string.Format("TestCase_VolatileEnlistments; count = {0}; expectedOutcome = {1}; options = {2}; votePrepared = {3}, expectedExceptionType = {4}", count, expectedOutcome.ToString(), options.ToString(), votePrepared, expectedExceptionType); Trace("**** " + testCaseDescription + " ****"); AutoResetEvent[] enlistmentDoneEvts = new AutoResetEvent[count]; MyEnlistment[] vols = new MyEnlistment[count]; for (int i = 0; i < count; i++) { enlistmentDoneEvts[i] = new AutoResetEvent(false); } try { using (TransactionScope ts = new TransactionScope()) { for (int i = 0; i < count; i++) { vols[i] = CreateVolatileEnlistment(enlistmentDoneEvts[i], null, options, votePrepared); } if (commitTx) { ts.Complete(); } } } catch (Exception ex) { if (ex.GetType() != expectedExceptionType) { TestFailed(testCaseDescription, string.Format("Unexpected exception {0}: {1}", ex.GetType().ToString(), ex.ToString())); return; } } for (int i = 0; i < count; i++) { if (!enlistmentDoneEvts[i].WaitOne(TimeSpan.FromSeconds(5))) { TestFailed(testCaseDescription, "Timeout waiting for enlistment outcomes"); return; } } int passCount = 0; for (int i = 0; i < count; i++) { if (((expectedOutcome == TransactionStatus.Committed) && vols[i].CommittedOutcome) || ((expectedOutcome == TransactionStatus.Aborted) && vols[i].AbortedOutcome) || ((expectedOutcome == TransactionStatus.InDoubt) && vols[i].InDoubtOutcome) ) { passCount++; } } if (passCount == count) { TestPassed(); } else { TestFailed(testCaseDescription, string.Format("{0} enlistments received an outcome of {1}", passCount, expectedOutcome.ToString())); } }
private static void TestCase_PSPENonMsdtc(bool commit, bool promote, TransactionStatus spcResponse, int p0BeforePSPE = 0, int p0AfterPSPE = 0, int p1BeforePSPE = 0, int p1AfterPSPE = 0, int p0AfterPromote = 0, int p1AfterPromote = 0 ) { string testCaseDescription = string.Format( "TestCase_PSPENonMsdtc commit={0}; promote={1}; spcResponse= {2}; p0BeforePSPE={3}; p0AfterPSPE={4}; p1BeforePSPE={5}; p1AfterPSPE={6}; p0AfterPromote={7}; p1AfterPromote={8}", commit, promote, spcResponse, p0BeforePSPE, p0AfterPSPE, p1BeforePSPE, p1AfterPSPE, p0AfterPromote, p1AfterPromote); Trace("**** " + testCaseDescription + " ****"); // It doesn't make sense to have "AfterPromote" enlistments if we aren't going to promote the transaction. if (!promote) { if ((p0AfterPromote > 0) || (p1AfterPromote > 0)) { Trace("Not promoting - Resetting p0AfterPromote and p1AfterPromote to 0."); p0AfterPromote = 0; p1AfterPromote = 0; } } AutoResetEvent completedEvent = new AutoResetEvent(false); IPromotableSinglePhaseNotification enlistment = null; Transaction savedTransaction = null; int numVolatiles = p0BeforePSPE + p0AfterPSPE + p1BeforePSPE + p1AfterPSPE + p0AfterPromote + p1AfterPromote; AutoResetEvent[] enlistmentDoneEvts = new AutoResetEvent[numVolatiles]; MyEnlistment[] vols = new MyEnlistment[numVolatiles]; for (int i = 0; i < numVolatiles; i++) { enlistmentDoneEvts[i] = new AutoResetEvent(false); } try { using (TransactionScope ts = new TransactionScope()) { // For checking status later, outside the scope. savedTransaction = Transaction.Current.Clone(); if (p0BeforePSPE > 0) { for (int i = 0; i < p0BeforePSPE; i++) { vols[i] = CreateVolatileEnlistment(enlistmentDoneEvts[i], null, EnlistmentOptions.EnlistDuringPrepareRequired, /*votePrepared=*/ true); } } if (p1BeforePSPE > 0) { for (int i = 0; i < p1BeforePSPE; i++) { vols[p0BeforePSPE + i] = CreateVolatileEnlistment(enlistmentDoneEvts[p0BeforePSPE + i], null, EnlistmentOptions.None, /*votePrepared=*/ true); } } enlistment = CreatePSPEEnlistment(NonMsdtcPromoterTests.PromoterType1, NonMsdtcPromoterTests.PromotedToken1, completedEvent, /*nonMSDTC = */ true, /*tx = */ null, spcResponse, /*expectRejection=*/ false ); if (p0AfterPSPE > 0) { for (int i = 0; i < p0AfterPSPE; i++) { vols[p0BeforePSPE + p1BeforePSPE + i] = CreateVolatileEnlistment( enlistmentDoneEvts[p0BeforePSPE + p1BeforePSPE + i], null, EnlistmentOptions.EnlistDuringPrepareRequired, /*votePrepared=*/ true); } } if (p1AfterPSPE > 0) { for (int i = 0; i < p1AfterPSPE; i++) { vols[p0BeforePSPE + p1BeforePSPE + p0AfterPSPE + i] = CreateVolatileEnlistment( enlistmentDoneEvts[p0BeforePSPE + p1BeforePSPE + p0AfterPSPE + i], null, EnlistmentOptions.None, /*votePrepared=*/ true); } } if (promote) { Promote(testCaseDescription, NonMsdtcPromoterTests.PromotedToken1); if (p0AfterPromote > 0) { for (int i = 0; i < p0AfterPromote; i++) { vols[p0BeforePSPE + p1BeforePSPE + p0AfterPSPE + p1AfterPSPE + i] = CreateVolatileEnlistment( enlistmentDoneEvts[p0BeforePSPE + p1BeforePSPE + p0AfterPSPE + p1AfterPSPE + i], null, EnlistmentOptions.EnlistDuringPrepareRequired, /*votePrepared=*/ true); } } if (p1AfterPromote > 0) { for (int i = 0; i < p1AfterPromote; i++) { vols[p0BeforePSPE + p1BeforePSPE + p0AfterPSPE + p1AfterPSPE + p0AfterPromote + i] = CreateVolatileEnlistment( enlistmentDoneEvts[p0BeforePSPE + p1BeforePSPE + p0AfterPSPE + p1AfterPSPE + p0AfterPromote + i], null, EnlistmentOptions.None, /*votePrepared=*/ true); } } } if (commit) { ts.Complete(); } } } catch (Exception ex) { TransactionAbortedException abortedEx = ex as TransactionAbortedException; if ((abortedEx != null) && (spcResponse != TransactionStatus.Aborted)) { TestFailed(testCaseDescription, "The transaction aborted unexpectedly"); return; } TransactionInDoubtException indoubtEx = ex as TransactionInDoubtException; if ((indoubtEx != null) && (spcResponse != TransactionStatus.InDoubt)) { TestFailed(testCaseDescription, "The transaction was indoubt unexpectedly"); return; } if (spcResponse == TransactionStatus.Committed) { Trace(string.Format("Caught unexpected exception {0}:{1}", ex.GetType().ToString(), ex.ToString())); return; } } NonMSDTCPromoterEnlistment nonDtcEnlistment = enlistment as NonMSDTCPromoterEnlistment; if (nonDtcEnlistment == null) { TestFailed(testCaseDescription, "The enlistment was not a NonMSDTCPromoterEnlistment"); return; } if (numVolatiles > 0) { for (int i = 0; i < numVolatiles; i++) { if (!enlistmentDoneEvts[i].WaitOne(TimeSpan.FromSeconds(5))) { TestFailed(testCaseDescription, "Timeout waiting for enlistment outcomes"); return; } } //if (WaitHandle.WaitAll(enlistmentDoneEvts, TimeSpan.FromSeconds(5))) //{ int passCount = 0; for (int i = 0; i < numVolatiles; i++) { if (commit) { if (((spcResponse == TransactionStatus.Committed) && vols[i].CommittedOutcome) || ((spcResponse == TransactionStatus.Aborted) && vols[i].AbortedOutcome) || ((spcResponse == TransactionStatus.InDoubt) && vols[i].InDoubtOutcome) ) { passCount++; } } else { if (vols[i].AbortedOutcome) { passCount++; } } } if (passCount != numVolatiles) { TestFailed(testCaseDescription, string.Format("{0} enlistments received an outcome of {1}", passCount, spcResponse.ToString())); } //} //else //{ // TestFailed(testCaseDescription, "Timeout waiting for enlistment outcomes"); //} } if (completedEvent.WaitOne(TimeSpan.FromSeconds(5))) { if (!promote && nonDtcEnlistment.Promoted) { TestFailed(testCaseDescription, "The enlistment promoted"); return; } if (promote && !nonDtcEnlistment.Promoted) { TestFailed(testCaseDescription, "The enlistment was not promoted"); return; } if (commit) { if ((spcResponse == TransactionStatus.Committed) && (nonDtcEnlistment.Aborted)) { TestFailed(testCaseDescription, "The enlistment aborted"); return; } } else { if (!nonDtcEnlistment.Aborted) { TestFailed(testCaseDescription, "The enlistment committed"); return; } } if (commit) { if (savedTransaction.TransactionInformation.Status != spcResponse) { TestFailed(testCaseDescription, string.Format("Unexpected final transaction status of {0}", savedTransaction.TransactionInformation.Status)); return; } } else if (!commit & savedTransaction.TransactionInformation.Status != TransactionStatus.Aborted) { TestFailed(testCaseDescription, string.Format("Unexpected final transaction status of {0}", savedTransaction.TransactionInformation.Status)); return; } TestPassed(); } else { TestFailed(testCaseDescription, "Timeout waiting for enlistment outcome"); } }
public void Prepare(PreparingEnlistment preparingEnlistment) { if (_enlistDuringPrepare) { Trace(string.Format("MyEnlistment.Prepare - attempting another enlistment with options {0}", _enlistOptions.ToString())); try { MyEnlistment enlist2 = new MyEnlistment( _secondEnlistmentCompleted, /*votePrepared=*/ true, /*enlistDuringPrepare=*/ false, _enlistOptions); this.TransactionToEnlist.EnlistVolatile(enlist2, _enlistOptions); if (!_expectSuccessfulEnlist) { // Force rollback of the transaction because the second enlistment was unsuccessful. Trace("MyEnlistment.Prepare - Force Rollback because second enlistment succeeded unexpectedly"); _aborted = true; _outcomeReceived.Set(); preparingEnlistment.ForceRollback(new Exception("MyEnlistment voted ForceRollback")); return; } } catch (Exception ex) { if (_expectSuccessfulEnlist) { Trace(string.Format("MyEnlistment.Prepare - Force Rollback because second enlistment failed unexpectedly - {0}; {1}", ex.GetType().ToString(), ex.ToString())); // Force rollback of the transaction because the second enlistment was unsuccessful. _aborted = true; _outcomeReceived.Set(); preparingEnlistment.ForceRollback(new Exception("MyEnlistment voted ForceRollback")); return; } } } if (_votePrepared) { Trace("MyEnlistment.Prepare voting Prepared"); preparingEnlistment.Prepared(); } else { Trace("MyEnlistment.Prepare - Force Rollback"); _aborted = true; _outcomeReceived.Set(); preparingEnlistment.ForceRollback(new Exception("MyEnlistment voted ForceRollback")); } }
public void SimpleTransactionSuperior() { MySimpleTransactionSuperior superior = new MySimpleTransactionSuperior(); SubordinateTransaction subTx = new SubordinateTransaction(IsolationLevel.Serializable, superior); AutoResetEvent durableCompleted = new AutoResetEvent(false); MyEnlistment durable = null; durable = new MyEnlistment( durableCompleted, true, false, EnlistmentOptions.None, /*expectSuccessfulEnlist=*/ false, /*secondEnlistmentCompleted=*/ null); durable.TransactionToEnlist = Transaction.Current; Assert.Throws<PlatformNotSupportedException>(() => // SubordinateTransaction promotes to MSDTC { subTx.EnlistDurable(Guid.NewGuid(), durable, EnlistmentOptions.None); }); Assert.Equal(0, s_testFailures); }
public static void TestCase_EnlistDuringPrepare(bool promote, bool beforePromote, EnlistmentOptions firstOptions = EnlistmentOptions.None, EnlistmentOptions secondOptions = EnlistmentOptions.None, bool expectSecondEnlistSuccess = true ) { string testCaseDescription = string.Format( "TestCase_EnlistDuringPrepare promote={0}; beforePromote={1}, firstOptions={2}, secondOptions={3}, expectSecondEnlistSuccess={4}", promote, beforePromote, firstOptions.ToString(), secondOptions.ToString(), expectSecondEnlistSuccess ); Trace("**** " + testCaseDescription + " ****"); AutoResetEvent volCompleted = new AutoResetEvent(false); AutoResetEvent vol2Completed = new AutoResetEvent(false); AutoResetEvent pspeCompleted = new AutoResetEvent(false); MyEnlistment vol = null; NonMSDTCPromoterEnlistment pspe = null; try { using (TransactionScope ts = new TransactionScope()) { if (beforePromote) { vol = new MyEnlistment( volCompleted, true, true, secondOptions, /*expectSuccessfulEnlist=*/ expectSecondEnlistSuccess, vol2Completed); vol.TransactionToEnlist = Transaction.Current; Transaction.Current.EnlistVolatile(vol, firstOptions); } pspe = (NonMSDTCPromoterEnlistment)CreatePSPEEnlistment(NonMsdtcPromoterTests.PromoterType1, NonMsdtcPromoterTests.PromotedToken1, pspeCompleted, /*nonMSDTC = */ true, /*tx = */ null, /*spcResponse=*/ TransactionStatus.Committed, /*expectRejection=*/ false ); if (promote) { Promote(testCaseDescription, NonMsdtcPromoterTests.PromotedToken1); if (!beforePromote) { vol = new MyEnlistment( volCompleted, true, true, secondOptions, /*expectSuccessfulEnlist=*/ expectSecondEnlistSuccess, vol2Completed); vol.TransactionToEnlist = Transaction.Current; Transaction.Current.EnlistVolatile(vol, firstOptions); } } ts.Complete(); } } catch (Exception ex) { TestFailed(testCaseDescription, string.Format("Unexpected exception {0}: {1}", ex.GetType().ToString(), ex.ToString())); return; } if (!expectSecondEnlistSuccess) { vol2Completed.Set(); } if (!volCompleted.WaitOne(TimeSpan.FromSeconds(5)) || !vol2Completed.WaitOne(TimeSpan.FromSeconds(5)) || !pspeCompleted.WaitOne(TimeSpan.FromSeconds(5))) { TestFailed(testCaseDescription, "Timeout waiting for enlistment outcomes"); return; } //if (WaitHandle.WaitAll(new WaitHandle[3] { volCompleted, vol2Completed, pspeCompleted }, TimeSpan.FromSeconds(5))) //{ if (vol.AbortedOutcome) { TestFailed(testCaseDescription, "The volatile enlistment aborted unexpectedly"); } if (!promote && pspe.Promoted) { TestFailed(testCaseDescription, "The enlistment promoted"); return; } if (promote && !pspe.Promoted) { TestFailed(testCaseDescription, "The enlistment was not promoted"); return; } if (pspe.Aborted) { TestFailed(testCaseDescription, "The pspe aborted unexpectedly"); return; } TestPassed(); //} //else //{ // TestFailed(testCaseDescription, "Timeout waiting for enlistment outcomes"); //} }
private static MyEnlistment CreateVolatileEnlistment( AutoResetEvent outcomeReceived, Transaction tx = null, EnlistmentOptions options = EnlistmentOptions.None, bool votePrepared = true) { MyEnlistment enlistment = new MyEnlistment(outcomeReceived, votePrepared); Transaction txToEnlist = Transaction.Current; if (tx != null) { txToEnlist = tx; } txToEnlist.EnlistVolatile(enlistment, options); return enlistment; }
public static void TestCase_EnlistDuringPrepare(bool promote, bool beforePromote, EnlistmentOptions firstOptions = EnlistmentOptions.None, EnlistmentOptions secondOptions = EnlistmentOptions.None, bool expectSecondEnlistSuccess = true ) { string testCaseDescription = string.Format( "TestCase_EnlistDuringPrepare promote={0}; beforePromote={1}, firstOptions={2}, secondOptions={3}, expectSecondEnlistSuccess={4}", promote, beforePromote, firstOptions.ToString(), secondOptions.ToString(), expectSecondEnlistSuccess ); Trace("**** " + testCaseDescription + " ****"); AutoResetEvent volCompleted = new AutoResetEvent(false); AutoResetEvent vol2Completed = new AutoResetEvent(false); AutoResetEvent pspeCompleted = new AutoResetEvent(false); MyEnlistment vol = null; NonMSDTCPromoterEnlistment pspe = null; try { using (TransactionScope ts = new TransactionScope()) { if (beforePromote) { vol = new MyEnlistment( volCompleted, true, true, secondOptions, /*expectSuccessfulEnlist=*/ expectSecondEnlistSuccess, vol2Completed); vol.TransactionToEnlist = Transaction.Current; Transaction.Current.EnlistVolatile(vol, firstOptions); } pspe = (NonMSDTCPromoterEnlistment)CreatePSPEEnlistment(NonMsdtcPromoterTests.PromoterType1, NonMsdtcPromoterTests.PromotedToken1, pspeCompleted, /*nonMSDTC = */ true, /*tx = */ null, /*spcResponse=*/ TransactionStatus.Committed, /*expectRejection=*/ false ); if (promote) { Promote(testCaseDescription, NonMsdtcPromoterTests.PromotedToken1); if (!beforePromote) { vol = new MyEnlistment( volCompleted, true, true, secondOptions, /*expectSuccessfulEnlist=*/ expectSecondEnlistSuccess, vol2Completed); vol.TransactionToEnlist = Transaction.Current; Transaction.Current.EnlistVolatile(vol, firstOptions); } } ts.Complete(); } } catch (Exception ex) { Assert.Null(ex); } if (!expectSecondEnlistSuccess) { vol2Completed.Set(); } Assert.True(volCompleted.WaitOne(TimeSpan.FromSeconds(5)) && vol2Completed.WaitOne(TimeSpan.FromSeconds(5)) && pspeCompleted.WaitOne(TimeSpan.FromSeconds(5))); Assert.False(vol.AbortedOutcome); if (promote) { Assert.True(pspe.Promoted); } else { Assert.False(pspe.Promoted); } Assert.False(pspe.Aborted); TestPassed(); }