When a test is run via CuTestRun, setjmp(buf) is compared to 0, if it's zero it's the first time executing the current test.
void CuTestRun(CuTest* tc)
{
jmp_buf buf;
tc->jumpBuf = &buf;
if (setjmp(buf) == 0)
{
tc->ran = 1;
(tc->function)(tc);
}
tc->jumpBuf = 0;
}
The expectation is that if CuFailInternal is run (due to a failed assertion), longjmp will jump back to the location in the CuTestRun code where
setjmp(buf) was set so longjmp will jump back to
if (setjmp(buf) == 0)
in CuTestRun. If you look at CuFailInternal you can see that the return value of longjmp is 0.
static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string)
{
char buf[HUGE_STRING_LEN];
sprintf(buf, "%s:%d: ", file, line);
CuStringInsert(string, buf, 0);
tc->failed = 1;
tc->message = string->buffer;
if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0);
}
So when longjmp is executed it return value is 0 and when
if (setjmp(buf) == 0)
is executed it thinks this is the first time that the function is called and re-executes the test. For the failure case to work properly longjmp must have its return value set to a non-zero value so
static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string)
{
char buf[HUGE_STRING_LEN];
sprintf(buf, "%s:%d: ", file, line);
CuStringInsert(string, buf, 0);
tc->failed = 1;
tc->message = string->buffer;
// if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0);
if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 1);
}
appears to work fine.
The test case is simple. Create a test where the assertion fails and you'll see the problem.