cgreen: Trying to mock multiple functions with the is_not_null constraint does not work

I’m using Ubuntu 20.04 with GCC 9.3.0-10ubuntu2 and clang 10.0.0-4ubuntu1 (the issue can be reproduced with both compilers), with cgreen compiled from source from commit 34cd1b6 - Extract common "discover_tests" function from the master branch.

The problem is that setting two different is_not_null constraints for different functions makes cgreen think that both functions should define that particular parameter. For lack of a better description I have a minimal sample with which I can reproduce this:

#include <cgreen/cgreen.h>
#include <cgreen/mocks.h>

Describe(test);
BeforeEach(test) {}
AfterEach(test) {}

void first_mock(int a, int *a_out)
{
    mock(a, a_out);
}

void second_mock(int b, int *b_out)
{
    mock(b, b_out);
}

int tested_func(int a, int b)
{
    int a_out, b_out;
    first_mock(a, &a_out); 
    second_mock(b, &b_out);
    return a_out + b_out;
}

Ensure(test, does_the_thing)
{
    int a_out_val = 10;
    int b_out_val = 20;

    expect(first_mock, 
        when(a_out, is_not_null),
        will_set_contents_of_parameter(a_out, &a_out_val, sizeof(a_out_val)));
    expect(second_mock, 
        when(b_out, is_not_null),
        will_set_contents_of_parameter(b_out, &b_out_val, sizeof(b_out_val)));

    assert_that(tested_func(1, 2), is_equal_to(30));
}

int main(void)
{
    TestSuite *suite = create_test_suite();
    add_test_with_context(suite, test, does_the_thing);
    return run_test_suite(suite, create_text_reporter());
}

Compiled with:

gcc test.c /usr/local/lib/libcgreen.so -o test

When run this gives the following output:

$ ./test
Running "main" (1 test)...
test.c:31: Failure: does_the_thing
        Mocked function [first_mock] did not define a parameter named [b_out]. Did you misspell it in the expectation or forget it in the mock's argument list?

test.c:38: Failure: does_the_thing
        Expected [tested_func(1, 2)] to [equal] [30]
                actual value:                   [262849778]
                expected value:                 [30]

  "main": 1 pass, 2 failures in 1ms.
Completed "main": 1 pass, 2 failures in 1ms.

If I remove when(a_out, is_not_null) or when(b_out, is_not_null),, or if I rename the parameter to have the same name in both cases it seems to work as intended:

$ ./test
Running "main" (1 test)...
  "main": 2 passes in 0ms.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 15 (8 by maintainers)

Most upvoted comments

Thanks for reporting the problem and to @thoni56 for fixing it. Not sure what we (I) were thinking here, sorry for the inconvenience! It’s so cool to see the project continue to get new users 10 years after I originally contributed and deployed it at several companies.

I am looking for a testing and mocking framework for C, to introduce some unit tests for a code base that lacks them, and so far cgreen is my favorite (I think that the docs are great, the mocking is really powerful, and a bug I found was fixed really fast). So thank you for what looks like a really cool and easy to use testing framework.

This is caused by the “optimized” implementation of is_not_null to use a singleton static constraint data structure. (And it has been that way for years 😉

I’m guessing that this also affects is_null, is_true, and is_false, all of which I can replace with is_equal_to/is_not_equal_to.

Thank you again for your quick response.