Monday, April 2, 2007

About deterministic testing...

Consider the following common piece of code:

static Bool
mmGenCon23FollowReferences(MmLockNodeP lockNode)
{
Bool scannedObject = FALSE;
ObjectP obj;
MmDumpEnvS dumpEnv;
MmBalanceWorkSetP ws;

mmRegisterScanDumpHandler(&dumpEnv);
ws = mmGetCurrentBalanceWorkSet();
obj = mmBalanceGetReference(ws);
while (obj != NULL)
{
scannedObject = TRUE;
mmGenCon23ScanObject(&dumpEnv, ws, obj);
obj = mmBalanceGetReference(ws);

if (lockNode != NULL && --mmObjectCounter == 0) {
mmGenConMarkCheckForContentionPhase23(lockNode);
mmObjectCounter = OBJECTS_BEFORE_CONTENTIONCHECK;
}
}
mmBalanceReturnWorkSet();
mmDeregisterScanDumpHandler(&dumpEnv);

return scannedObject;
}

This is inherently impossible to run in any kind of functional testing. Why?
It has some interaction point that actually not is known when calling this method:

  • dumpEnv
  • ws
  • mmObjectCounter (Global var.)

dumpEnv
Is populated from the method

mmRegisterScanDumpHandler(MmDumpEnvP dumpEnv)

ws
The workset is something related to the current thread

&(vmtGetGcEnv(tsGetCurrentThread())->balanceWorkSet);

This method does not considering that the other methods may get their values 'randomly' from other methods or global variables but the method can be testable if the method would look something like:

static Bool
mmGenCon23FollowReferences(MmLockNodeP lockNode, MmDumpEnvP dumpEnv, MmDumpEnvP dumpEnv, MmBalanceWorkSetP ws, int* counter)
{
.
.
.
}

No comments: