Gionata Benelli
Gionata Benelli

Reputation: 407

linking with wrap directive for unit testing can be used to redefine a subroutine?

I'm using Cmocka to write a unit testing suite for a shared object written in C, but I'm having some issue. Since I cannot share the source code, I have written a minimum "not-working" example to show what is the issue:

my program is composed 5 files: foo.c, foo.h bar.c bar.h main.c.

function, returning the argument multiplied by 3.

I compile the program by producing a libfootest.so object (foo+bar) and then I link this object with main.o passing the -Wl,--wrap=bar flag to the compiler. In this configuration libfootest is the module under test and main is the tester program. I expect the __wrap__bar to be called (failing the test), but the standard bar() is called(test is passed). How can I solve this problem? Below you find all the code I'm using.

bar.c:

#include "bar.h"
int bar(int val) {
    return val*2;
}

bar.h:

int bar(int val);

foo.h:

#include <stdio.h>

int foo(int val);

foo.c:

#include "foo.h"
#include "bar.h"
int foo(int val) {
    int ret;
    ret = bar(val);
    printf("RET: %d", ret);
    return ret;
}

main.c:

#include <stdio.h>
//required include for CMOCKA
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <setjmp.h>
#include <cmocka.h>


//library under test
#include "foo.h"
int __wrap_bar(int val) {
        return 3*val;
}


static void test_foo(void **state) {
    int ret = foo(5);
    assert_int_equal(ret, 10);
    

}

int main (int argc, char** argv) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(test_foo),
    };

    return cmocka_run_group_tests(tests, NULL, NULL);
}

Makefile:

CMOCKA_LIB_DIR=../../cmocka-1.1.5/build/src
CXXFLAGS+=-g -Og  -fPIC
CFLAGS+=-g  -Og  -std=c99 -fPIC
CC=gcc
CXX=g++

all: main.o ./libfootest.so
    gcc -o linux-test -g -L. -L$(CMOCKA_LIB_DIR) $(filter %.o, $^) -lcmocka -lfootest -Wl,-rpath=. -Wall -Wl,--wrap=bar -Wl,-rpath=$(CMOCKA_LIB_DIR)

./libfootest.so: foo.o bar.o
    $(CC) -shared -o $@ -g $^  -pedantic -Wall

clean: 
    rm -f *.o
    rm -f *.so

Upvotes: 0

Views: 264

Answers (1)

the busybee
the busybee

Reputation: 12653

The problem is your build of the library. You don't create a link library as commonly done, with separated modules. Instead you link all given modules and place the resulting single module in the target library.

That's why the linker resolved the call to bar() already, and it is no longer unresolved when linking the test program.

The option --wrap works only for unresolved references between modules.

The solution is to build the library from separated modules. Use the tool ar for this:

ar r libfootest.a foo.o bar.o

Upvotes: 1

Related Questions