ThrowTheSwitch / Ceedling

Ruby-based unit testing and build system for C projects

Home Page:http://throwtheswitch.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

undefined reference to "add"

zlyjob opened this issue · comments

Hi there,
I am new user of Ceedling and I am practicing.

Now I have four files in \src: adder.c, adder.h, my_math.c, my_math.h
They are like:

// adder.c:
#include "adder.h"
#include "my_math.h"
int doAddOnePlusTwo() {
return add(1, 2);
}

// adder.h:
#ifndef BASIC_ADDER_H
#define BASIC_ADDER_H
int doAddOnePlusTwo();
#endif // BASIC_ADDER_H

// my_math.c:
#include "my_math.h"
int add(int a, int b) {
return a + b;
}

// my_math.h:
int add(int a, int b);

The file under test is adder.c, which called add() from my_math.c

The test_adder.c is in folder /test
// test_adder.c:
#include <unity.h>
#include "adder.h"
void setUp() {}
void tearDown() {}
void test_doAddOnePlusTwo() {
int result = doAddOnePlusTwo();
TEST_ASSERT_EQUAL(3, result);
}

Now I ran ceedling and get errors:

Test 'test_adder.c'

Generating dependencies for adder.c...
Compiling test_adder.c...
Compiling adder.c...
Linking test_adder.out...
C:/MinGW-w64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: build/test/out/c/adder.o: in function doAddOnePlusTwo': C:\UnityTest\ceedling\myProject2/src/adder.c:7:(.text+0x13): undefined reference to add'
collect2.exe: error: ld returned 1 exit status
ERROR: Shell command failed.

Shell executed command:
'gcc.exe "build/test/out/c/test_adder_runner.o" "build/test/out/c/test_adder.o" "build/test/out/c/unity.o" "build/test/out/c/adder.o" "build/test/out/c/cmock.o" -o "build/test/out/test_adder.out"'
And exited with status: [1].

NOTICE: If the linker reports missing symbols, the following may be to blame:

  1. Test lacks #include statements corresponding to needed source files.
  2. Project search paths do not contain source files corresponding to #include statements in the test.
  3. Test does not #include needed mocks.

rake aborted!

C:/Ruby30-x64/bin/ceedling:25:in load' C:/Ruby30-x64/bin/ceedling:25:in

'

Caused by:
ShellExecutionException: ShellExecutionException
C:/Ruby30-x64/bin/ceedling:25:in load' C:/Ruby30-x64/bin/ceedling:25:in

'
Tasks: TOP => build/test/results/test_adder.pass => build/test/out/test_adder.out
(See full trace by running task with --trace)
ERROR: Ceedling Failed

Looks like ceedlign cannot find the function add(), but I did include the header file. If I comment it out, then everything become good.

Any comment will be much appreciated!

Welcome to unit testing.

my_math.h is dependency of the adder.c compilation unit, so you should mock it by including mock_my_math.h . In setUp and tearDown you will want function calls to mock_my_math_Init() and mock_my_math_Verify(). What will happen next.is that it will tell you your add function is called more times than expected, since you did not declare that you expect add to be called and for that you will need to put an add_ExpectAndReturn(value_for_a, value_for_b, retval) into the test_adder.c test case.

As a side remark, do not use <> brackets around include file, because that makes compiler to first search compiler system path, before looking for the file in the provided includes. And I am certain your unity.h is not a compiler header file, but you want to take Ceedling's version of it.

Welcome to unit testing.

my_math.h is dependency of the adder.c compilation unit, so you should mock it by including mock_my_math.h . In setUp and tearDown you will want function calls to mock_my_math_Init() and mock_my_math_Verify(). What will happen next.is that it will tell you your add function is called more times than expected, since you did not declare that you expect add to be called and for that you will need to put an add_ExpectAndReturn(value_for_a, value_for_b, retval) into the test_adder.c test case.

As a side remark, do not use <> brackets around include file, because that makes compiler to first search compiler system path, before looking for the file in the provided includes. And I am certain your unity.h is not a compiler header file, but you want to take Ceedling's version of it.

Thank you so much, Letme.
I see, so, even there are complete dependencies files (header and *.c), we still need to mock the function which is called by the function under test.

Dependency files (headers and .c files) are automatically created with the include of mock_headername.h. But yes, you want to replace out of component (.c file) dependencies with mocks, to have control of inputs.