Jon
Jon

Reputation: 1801

How do I properly build cmocka unit tests with CMake

I have a simple test code suite set up in the C language to provide a template for the use of CMake to simultaneously build unit tests with cmocka and also build the integrated code in the main.c file. The code has the following directory structure, where the main.c file integrates code, the functions are contained in the include directory, the build directory contains the build files (i.e. makefile) and the exectable, as well as the test executable in a test directory. In this simple example I am trying to build the test code for the add.h and add.c files with cmocka

apples
|__ CMakeLists.txt
|__ main.c
|__ include
|   |__ CMakeLists.txt
|   |__ add.c
|   |__ add.h
|__ build
|   |__ apples (executable)
|   |__ test
|       |__ unit_tests (executable)
|__ test
    |__ CMakeLists.txt
    |__ test_add.h
    |__ test_add.c
    |__ unit_test.c

I am trying to get this build configuration to work with CMake, and I can make create the apples executable in the build directory. However, I am not sure how to link cmocka to the CMake build and cannot get that part to work. In order to ensure that cmocka is working properly I cd'd to the test directory and manually built it with the gcc unit_tests.t test_add.c ../include/add.c -lcmocka command, and it compiled correctly. I am listing the contents of each file below.

CMakeLists.txt file in the apples directory

# CMake version
cmake_minimum_required(VERSION 3.22.2)
project(apples)

# Set the compiler, for some reason this does not work with clang++ or g++
set(CMAKE_C_COMPILER "/usr/bin/gcc")

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

enable_testing()
set(CMAKE_C_FLAGS "-Wall -Werror -Wpedantic -std=c11 -lcmocka")
# --------------------------------------------------------------------------------
# Set executable terms

# Specify directory where the executable is stored
# set(CMAKE_CURRENT_BINARY_DIR "bin")

# Add subdirectories
add_subdirectory(include)

# Create name for executable
add_executable(${PROJECT_NAME} main.c)

# Add target libraries if necessary
target_link_libraries(${PROJECT_NAME} PUBLIC include)
# --------------------------------------------------------------------------------
# Set test terms

add_subdirectory(test)

CMakeLists.txt file in the include directory

add_library(include
    add.c
    add.h
)

target_include_directories(include PUBLIC .)

CMakeLists.txt file in the test directory

cmake_minimum_required(VERSION 3.22.2)

enable_testing()

add_executable(
  unit_test.c
  test_add.c
  test_add.h
)
target_link_libraries(
  include
)

add.c #include "add.h" float float_add(float a, float b) { return a + b; }

int int_add(int a, int b) {
    return a + b;
}

add.h

#ifndef add_H
#define add_H

#include <stdio.h>

float float_add(float a, float b);
int int_add(int a, int b);

#endif /* add_H */

test_add.c

#include "test_add.h"
void test_i_add(void **state)
{
    (void) state;
    int a = 5;
    int b = 2;
    int c = int_add(a, b);
    assert_int_equal(c, 7);
}

void test_f_add(void **state)
{
    float a = 3.2;
    float b = 2.1;
    float c = float_add(a, b);
    assert_float_equal(c, 5.3f, 1.0e-3);
}

test_add.h

#ifndef addtest_H
#define addtest_H

#include <stdio.h>
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <stdint.h>
#include <cmocka.h>

#include "../include/add.h"

void test_i_add(void **state);
void test_f_add(void **state);

#endif /* addtest_H */

unit_test.c

#include <stdio.h>
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <stdint.h>
#include <cmocka.h>

#include "test_add.h"

// Begin code
int main(int argc, const char * argv[]) {
    const struct CMUnitTest add_tests[] = {
        cmocka_unit_test(test_i_add),
        cmocka_unit_test(test_f_add)
    };
    return cmocka_run_group_tests(add_tests, NULL, NULL);
}

I am excluding the main.c file in the apples directory, since it is irrelevent to the cmocka build. Unfortunately the CMake setup in the CMakeLists.txt files is not correct, and will not build the unit tests with cmocka. However, I am not sure in what way I am supposed to modify the CMakeLists.txt files. I am assuming that the upper most CMakeLists.txt file should reference cmocka, but I am not sure how, or if this should occur in the CMakeLists.txt file in the test directory. Any suggestions or guidance would be greatly appreciated.

Upvotes: 0

Views: 37

Answers (0)

Related Questions