单元测试的带wrap指令的c链接可以用来重新定义子程序吗



我正在使用Cmocka为用C编写的共享对象编写单元测试套件,但我遇到了一些问题。由于我不能共享源代码,所以我写了一个最小的"不工作";举例说明问题所在:

我的程序由5个文件组成:foo.c,foo.h bar.c bar.h main.c

  • bar.*文件定义了一个bar((函数,它只返回参数乘以2
  • foo.*文件声明了一个使用bar.h定义的bar((函数的foo((函数
  • main.c包含一个简单的cmocka测试和一个__wrap_bar((

函数,返回参数乘以3。

我通过生成一个libfootest.so对象(foo+bar(来编译程序,然后将这个对象与main.o链接,并将-Wl,--wrap=bar标志传递给编译器。在这个配置中,libfootest是被测试的模块,main是测试程序。我希望调用__wrap__bar(测试失败(,但调用了标准bar(((测试通过(。我该如何解决这个问题?下面是我使用的所有代码。

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

问题在于库的构建。您不会像通常那样创建带有独立模块的链接库。相反,您可以链接所有给定的模块,并将生成的单个模块放置在目标库中。

这就是为什么链接器已经解析了对bar()的调用,并且在链接测试程序时不再解析它。

选项--wrap仅适用于模块之间未解析的引用

解决方案是从分离的模块构建库。使用工具ar进行以下操作:

ar r libfootest.a foo.o bar.o

最新更新