C Unit Testing with cmocka

Introduction

The cmocka homepage is https://cmocka.org/.

The way cmocka is used is, you will write tests for your code and compile those tests along with a subset of your code into an executable. You can then run that executable which will execute the unit tests and print the test results to the command line.

cmocka gives you assert methods and a way to mock functionality.

Compiling cmocka using the cmake-gui (Ubuntu 19.04)

cmocka is not distributed in binary form so you have to compile it yourself. The compilation instructions say:

To compile the cmocka library and example applications run, create a build dir,
and in the build dir call ‘cmake /path/to/cmocka’ followed by ‘make’. On
Windows you can use the cmake gui. More details can be found in the INSTALL file.

During runtime, the test binary will need access to the cmocka shared libraries. The dynamic linker (not to confuse with the static linker used during application compilation) is responsible to resolve all dynamic shared dependencies. The dynamic linker will look into the compiled binary to retrieve paths to shared libraries.

The cmocka shared libraries are contained in the <BUILD_FOLDER>/src folder after compiling cmocka. You additionally may run the make install command after make. make install will copy the shared libraries to /usr/local/lib.

Wherever you decide to keep the cmocka shared libraries, during the static linking phase of the test binary file, you have to specify the folder using the -L switch that contains the cmocka shared libraries so the static linker can write that path into the binary. This path will be written into the binary by the static linker. During runtime the dynamic linker will look into the application binary, determine all paths to load libraries from and it will load the required libraries. That means you have to specify the correct path to the shared libraries during static linking. If you want to distribute code, a folder such as /usr/local/lib makes more sense than your personal build folder. But this decision is up to you.

The cmake-gui looks like this:

  1. sudo apt-get update
  2. sudo apt-get install make cmake cmake-qt-gui
  3. cmake-gui
  4. The cmake GUI should have started up
  5. Download https://cmocka.org/files/1.1/cmocka-1.1.5.tar.xz
  6. Extract the archive
  7. In cmake GUI, click on the ‘Browse source’ button and select the folder into which you just extracted the archive.
  8. Create a folder which you want to build the cmocka binaries into.
  9. In cmake GUI, click the ‘Browse build’ button and select the build folder you just created
  10. In cmake GUI click on the ‘Configure’ and on the ‘Generate’ buttons in that order
  11. Go into the build folder
  12. Type make to build the cmocka binaries
  13. Optional: Type sudo make install to install the binaries and headers to /usr/local/lib

Using cmocka

The way cmocka is used is, you will write tests for your code and compile those tests into an executable. You can then run that executable which will execute the unit tests and print the test results to the command line.

Example from https://stackoverflow.com/questions/33260973/how-do-i-link-with-cmocka

factorial.h

int factorial(int n);

factorial.c

int factorial(int n) {
    int result = 1;
    for (int i = 1; i <= n; ++i)
        result *= i;
    return result;
}

test_factorial.c

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

#include "factorial.h"

static void test_factorial_zero()
{
    assert_int_equal(factorial(0), 1);
}

int main(int argc, char **argv)
{
    const UnitTest tests[] =
    {
            unit_test(test_factorial_zero),
    };

    return run_tests(tests);
}

To compile the .c files into object files and link the object files with cmocka to retrieve the test-executable:

gcc -c factorial.c
gcc -c test_factorial.c -I/home/<user>/Downloads/cmocka-1.1.5/include
gcc -L/home/<user>/Downloads/cmocka-1.1.5/build/src -o "testmain" ./test_factorial.o ./factorial.o -lcmocka

After make install, the code should compile and run without specifying a library folder as the libraries were installed to the standard library folder so the static as well as the dynamic linker will be able to find them. In that case the compilation can be reduced to:

gcc -o "testmain" ./test_factorial.o ./factorial.o -lcmocka

Once the executable is created, you can start the unit tests by executing it:

./testmain

The output of the test-executable testmain is:

[==========] Running 1 test(s).
[ RUN      ] test_factorial_zero
[       OK ] test_factorial_zero
[==========] 1 test(s) run.
[  PASSED  ] 1 test(s).

 0 FAILED TEST(S)

 

Leave a Reply