0

In my CMakeLists.txt file, I have:

include_directories("${algorithm}/include")
add_executable(
        test_runner
        test_runner.cpp
        test_file1.cpp
        test_file2.cpp
        test_file2.cpp
)
target_link_libraries(
        test_runner
        gtest_main)
gtest_discover_tests(test_runner)

Unfortunately, this doesn't work, as these files both import algorithm.c from "${algorithm}/include".

I don't know what to do here. How can I have multiple test_files which all depend on algorithm.c, which test_runner can discover?

Am I forced to put all of the test_files into one file, or to make a separate executable for each? That would be extremely unfortunate.

Is there an alternative? Something involving headers, I expect? Or does algorithms.c need to be a library which I import?

Daniel Paczuski Bak
  • 3,720
  • 8
  • 32
  • 78
  • What do you mean by `multiple test_files which all depend on algorithm.c` ? – selbie Apr 30 '19 at 01:01
  • I have multiple files like `test_file1.cpp`, `test_file2.cpp`. `algorithm.c` is a file. Each test_file does `#include ` – Daniel Paczuski Bak Apr 30 '19 at 01:04
  • 2
    You should not be including a `*.c` file ... separate the definitions from the declarations and add the later to an header file (`algorithm.h`) and include that. (`int foo() { return 42; }` --> `int foo();` in header and `int foo() { return 42; }` in source file) – Daniel Jour Apr 30 '19 at 01:09
  • I need to include the `.c` file because I need to access a `static` function in order to test it. Is it impossible to do what I need to do here? I cannot make the function non-static. – Daniel Paczuski Bak Apr 30 '19 at 01:09
  • Have you looked at [class guards](http://faculty.cs.niu.edu/~mcmahon/CS241/c241man/node90.html) before? Essentially you add `#ifndef ALGORITHM_H` and `#define ALGORITHM_H` to the start of your code and `#endif` at the end, which will only have the header be loaded once. – Aplet123 Apr 30 '19 at 01:14
  • Don't add `#include ` to your test files. Instead, add `#include ` (using the `#ifndef` thing Aplet123 suggests). Then add `algorithm.c` to be build or linked into your test_runner compile. – selbie Apr 30 '19 at 01:20
  • @selbie I attempted this and it's failing - all the calls to the methods are now "undefined references". They were working just fine when I was importing the `.c`, but now I am using the `.h` and they're failing. – Daniel Paczuski Bak Apr 30 '19 at 01:37
  • 1
    Did you add `algorithm.c` to your `add_executable` section? – selbie Apr 30 '19 at 01:38
  • Approach with including source files is not good in *general*, but in case of **unit testing of static functions** it is sometimes *inevitable*. So, there is a little reason to remind that source files shouldn't be included. See e.g. this question: https://stackoverflow.com/questions/593414/how-to-test-a-static-function. @DanielPaczuskiBak: Didn't you consider to put the words about "testing static functions" into the question post and into the title? I see this would be more descriptive than simple "multiple definition" problem. – Tsyvarev Apr 30 '19 at 08:20

1 Answers1

0

You may wrap inclusion of source file into additional header file, which has proper inclusion guards. Something like:

// File: algorithm_test.h
#ifndef ALGORITHM_TEST_H
#define ALGORITHM_TEST_H

#include <algorithm.c>
#endif /* ALGORITHM_TEST_H */

After that, your tests (test_file1.cpp, test_file2.cpp, etc.) may include this header instead of including the source file directly:

// File: test_file1.cpp
#include <algorithm_test.h>

... define test methods ...
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153