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))
{
Assert.Equal(spcResponse, TransactionStatus.Aborted);
}
TransactionInDoubtException indoubtEx = ex as TransactionInDoubtException;
if ((indoubtEx != null) && (spcResponse != TransactionStatus.InDoubt))
{
Assert.Equal(spcResponse, TransactionStatus.InDoubt);
}
if (spcResponse == TransactionStatus.Committed)
{
Trace(string.Format("Caught unexpected exception {0}:{1}", ex.GetType().ToString(), ex.ToString()));
return;
}
}
NonMSDTCPromoterEnlistment nonDtcEnlistment = enlistment as NonMSDTCPromoterEnlistment;
Assert.NotNull(nonDtcEnlistment);
if (numVolatiles > 0)
{
for (int i = 0; i < numVolatiles; i++)
{
Assert.True(enlistmentDoneEvts[i].WaitOne(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++;
}
}
}
Assert.Equal(numVolatiles, passCount);
}
Assert.True(completedEvent.WaitOne(TimeSpan.FromSeconds(5)));
Assert.False(!promote && nonDtcEnlistment.Promoted);
Assert.False(promote && !nonDtcEnlistment.Promoted);
if (commit)
{
Assert.False((spcResponse == TransactionStatus.Committed) && (nonDtcEnlistment.Aborted));
Assert.Equal(spcResponse, savedTransaction.TransactionInformation.Status);
}
else
{
Assert.True(nonDtcEnlistment.Aborted);
Assert.Equal(TransactionStatus.Aborted, savedTransaction.TransactionInformation.Status);
}
TestPassed();
}