private static void TestCase_PSPENonMsdtcWithClones(
bool commit,
bool promote,
TransactionStatus spcResponse,
int abortingBeforePSPE = 0,
int abortingAfterPSPE = 0,
int blockingBeforePSPE = 0,
int blockingAfterPSPE = 0,
int abortingAfterPromote = 0,
int blockingAfterPromote = 0)
{
string testCaseDescription = string.Format(
"TestCase_PSPENonMsdtcWithClones commit={0}; promote={1}; spcResponse= {2}; abortingBeforePSPE={3}; abortingAfterPSPE={4}; blockingBeforePSPE={5}; blockingAfterPSPE={6}; abortingAfterPromote={7}; blockingAfterPromote={8}",
commit,
promote,
spcResponse,
abortingBeforePSPE,
abortingAfterPSPE,
blockingBeforePSPE,
blockingAfterPSPE,
abortingAfterPromote,
blockingAfterPromote);
Trace("**** " + testCaseDescription + " ****");
// It doesn't make sense to have "AfterPromote" enlistments if we aren't going to promote the transaction.
if (!promote)
{
if ((abortingAfterPromote > 0) || (blockingAfterPromote > 0))
{
Trace("Not promoting - Resetting abortingAfterPromote and blockingAfterPromote to 0.");
abortingAfterPromote = 0;
blockingAfterPromote = 0;
}
}
AutoResetEvent completedEvent = new AutoResetEvent(false);
IPromotableSinglePhaseNotification enlistment = null;
int numClones = abortingBeforePSPE + abortingAfterPSPE + blockingBeforePSPE + blockingAfterPSPE + abortingAfterPromote + blockingAfterPromote;
DependentTransaction[] clones = new DependentTransaction[numClones];
try
{
using (TransactionScope ts = new TransactionScope())
{
if (abortingBeforePSPE > 0)
{
for (int i = 0; i < abortingBeforePSPE; i++)
{
clones[i] = CreateDependentClone(/*blocking=*/false);
}
}
if (blockingBeforePSPE > 0)
{
for (int i = 0; i < blockingBeforePSPE; i++)
{
clones[abortingBeforePSPE + i] = CreateDependentClone(/*blocking=*/true);
}
}
enlistment = CreatePSPEEnlistment(NonMsdtcPromoterTests.PromoterType1,
NonMsdtcPromoterTests.PromotedToken1,
completedEvent,
/*nonMSDTC = */ true,
/*tx = */ null,
spcResponse,
/*expectRejection=*/ false
);
if (abortingAfterPSPE > 0)
{
for (int i = 0; i < abortingAfterPSPE; i++)
{
clones[abortingBeforePSPE + blockingBeforePSPE + i] = CreateDependentClone(/*blocking=*/false);
}
}
if (blockingAfterPSPE > 0)
{
for (int i = 0; i < blockingAfterPSPE; i++)
{
clones[abortingBeforePSPE + blockingBeforePSPE + abortingAfterPSPE + i] = CreateDependentClone(/*blocking=*/true);
}
}
if (promote)
{
Promote(testCaseDescription, NonMsdtcPromoterTests.PromotedToken1);
if (abortingAfterPromote > 0)
{
for (int i = 0; i < abortingAfterPromote; i++)
{
clones[abortingBeforePSPE + blockingBeforePSPE + abortingAfterPSPE + blockingAfterPSPE + i] = CreateDependentClone(/*blocking=*/false);
}
}
if (blockingAfterPromote > 0)
{
for (int i = 0; i < blockingAfterPromote; i++)
{
clones[abortingBeforePSPE + blockingBeforePSPE + abortingAfterPSPE + blockingAfterPSPE + abortingAfterPromote + i] = CreateDependentClone(/*blocking=*/true);
}
}
}
// Complete all the clones
for (int i = 0; i < numClones; i++)
{
clones[i].Complete();
}
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);
}
Assert.NotEqual(spcResponse, TransactionStatus.Committed);
}
TestPassed();
}