0

我正在使用 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() (通过测试)。我怎么解决这个问题?您可以在下面找到我正在使用的所有代码。

酒吧.c:

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

酒吧.h:

int bar(int val);

富.h:

#include <stdio.h>

int foo(int val);

富.c:

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

主.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);
}

生成文件:

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
4

1 回答 1

1

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

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

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

解决方案是从分离的模块构建库。为此使用该工具ar

ar r libfootest.a foo.o bar.o
于 2021-07-06T06:50:48.250 回答