我正在使用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