Criterion icon indicating copy to clipboard operation
Criterion copied to clipboard

Using a pointer to a function in parameterized tests

Open BSFishy opened this issue 5 years ago • 2 comments

I am working on a project which uses an API that defines a struct with pointers to functions to provide flexible functionality. I've been writing tests to confirm a little bit of the functionality so far, but I've just run into an issue trying to use one of those pointers. I know how memory must use the criterion functions (i.e. cr_malloc), so I'm not exactly sure how I should go about this.

I've written a minimal example here:

#include <criterion/parameterized.h>

#include <stdlib.h>

void customFunc() {
    cr_log_info("In function\n");
}

typedef struct Param {
    void (*func)();
} Param;

void cleanupHandlerParam(struct criterion_test_params *ctp) {
    cr_free(ctp->params);
}

ParameterizedTestParameters(example, test) {
    const size_t size = 2;
    Param *params = cr_malloc(sizeof(Param) * size);

    params[0] = (Param) {.func = NULL};
    params[1] = (Param) {.func = &customFunc};

    return cr_make_param_array(Param, params, size, cleanupHandlerParam);
}

ParameterizedTest(Param * param, example, test) {
    int pos = 0;

    cr_log_info("Pos %d\n", pos++);
    if (param->func) {
        cr_log_info("Pos %d\n", pos++);
        param->func();
        cr_log_info("Pos %d\n", pos++);
    }
}

And this is the output:

[----] Criterion v2.3.3
[====] Running 1 test from example:
[RUN ] example::test
[----] Pos 0
[PASS] example::test: (0.00s)
[RUN ] example::test
[----] Pos 0
[----] Pos 1
[----] ../test/net/test.c:32: Unexpected signal caught below this line!
[FAIL] example::test: CRASH!
[====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 1

BSFishy avatar Jan 27 '20 18:01 BSFishy

After testing a little bit, I figured you could add the following to the top of the actual test:

if (param->func) {
    param->func = &customFunc;
}

I presume this is because the test cannot access a function in a separate address space. While this does fix the issue, it adds extra code which takes away from readability.

BSFishy avatar Jan 27 '20 19:01 BSFishy

This happens because of ASLR. I'm not even sure how to tackle that seamlessly to be honest, because we can't just translate these addresses between the parent and the child unless we're 100% sure that this is in fact an address and not some other random value in memory.

A workaround for this would be to disable ASLR when running the test (setarch --addr-no-randomize) or have the subtest not being run in another process somehow.

For consideration for #204, where this would be simply fixed with a non-isolated cr_run.

Snaipe avatar Jan 03 '22 17:01 Snaipe