meekrosoft / fff

A testing micro framework for creating function test doubles
Other
761 stars 167 forks source link

Multiple definition error #36

Closed anat0lius closed 6 years ago

anat0lius commented 6 years ago

This is what I have:

#include "lib/fff.h"
DEFINE_FFF_GLOBALS;
FAKE_VALUE_FUNC(bool_t, probe_is_ok, adc_probe_t);
/* List of fakes used by this unit tester */
#define FFF_FAKES_LIST(FAKE)            \
  FAKE(probe_is_ok)                    \

And this is what I get when I build

../app/middleware/libmiddleware.a(probe.c.o): In function `probe_is_ok':
~/AppProject/app/middleware/probe.c:19: multiple definition of `probe_is_ok'
CMakeFiles/unit_tests.dir/AppTest.cpp.o:~/AppProject/test/AppTestTest.cpp:16: first defined here
dturner commented 6 years ago

Also running into this. My exact linker error message is:

ld: 1 duplicate symbol for architecture i386

dturner commented 6 years ago

Think I figured it out. In my case at least, I was linking against the object which I was mocking, as well as the fake.

It looks like you're doing the same thing. Make sure probe.c.ois excluded from your unit test binary.

meekrosoft commented 6 years ago

Hi folks, Yes, the fake will clash with an existing function definition if it is linked in...be sure not to include it in the test binary. I will close this issue...

anat0lius commented 6 years ago

If I dont link it, how is supposed I make it work?

program to test --> depends on some external programs (linked) test --> depends on program to test (linked)

I'm using cmake and google test

target_link_libraries(unit_tests gtest gtest_main)
target_link_libraries(unit_tests app)
meekrosoft commented 6 years ago

The trick is to put functions that are faked in tests in separate translation units (object files) that are only linked in production. An uglier alternative, is to use the preprocessor to #ifdef PROD away the function during test builds

louiske0911 commented 6 years ago

Hi, @meekrosoft . I would like to confirm some problem, please help to solve my confusion. So, that means the fake function and original function can't be called in the same object file? In other words, if I can't call or use the original A function after I fake the A function? thanks.

note: this problem same as the issue #55

meekrosoft commented 6 years ago

Yes, you are correct. The whole point of fff is to create a replacement function for testing a translation unit without changing the production code.

If the code you want to test calls something you want to assert on, e.g.

void do_something(void){
  counter++;
  another_function(counter);
}

You want to test this code works by asserting that another_function is called, and with the correct parameters....without changing the production code. The only way to do so is with the preprocessor or the linker.

louiske0911 commented 6 years ago

Okay, but if I fake the A function then I would like to use original_A function in other test case in the same c file, or I don't want to fake the A function in the some unit test case / scenario in same test c file any more. How could I do?

The simple example code such as below:

// A.c
int original_A_function(){
         return 5;
}

// unit_test_A.c
DEFINE_FFF_GLOBALS;
FAKE_VALUE_FUNC(int, original_A_function);

TEST(examples,  test_the_fake_A_function)
{   
        original_A_function_fake.return_val = 999;
    ASSERT_INT_EQ(original_A_function(), 999);
}

TEST(examples, test_the_origin_A_function)
{   
    original_A_function();
        ASSERT_INT_EQ(original_A_function(), 5);
}
wulfgarpro commented 5 years ago

Response #55.