Building Google Test Framework with CMake

For those who does not know GTest (Google Test Framework), it is a simple way to make unit tests in C and C++ source code.

But what is an unit test?

In GTest Documentation you will find an in-depth description, but in general terms, one unit test consists in a specific test of one function of one source file from an application. It has basically an initialization phase to allows you to call the correspondent function. Then it comprises on make some sanity tests (assertions) to check if your code is behaving as expected.

How GTest works?

GTest provides some assertion macros which simplify the tests as the following numerical comparison assertions (there is also some macros for binary and string comparison):

Fatal assertion Nonfatal assertion Verifies
ASSERT_EQ(expected, actual); EXPECT_EQ(expected, actual); expected == actual
ASSERT_NE(val1, val2); EXPECT_NE(val1, val2); val1 != val2
ASSERT_LT(val1, val2); EXPECT_LT(val1, val2); val1 < val2
ASSERT_LE(val1, val2); EXPECT_LE(val1, val2); val1 <= val2
ASSERT_GT(val1, val2); EXPECT_GT(val1, val2); val1 > val2
ASSERT_GE(val1, val2); EXPECT_GE(val1, val2); val1 >= val2

How to build a simple example?

The first step is download the source code and build the GTest library, which can be performed using g++ compiler (replace $(GTEST_DIR) by the place of GTest directory):

wget http://googletest.googlecode.com/files/gtest-1.6.0.zip
unzip gtest-1.6.0.zip
g++ -I ${GTEST_DIR}/include -I ${GTEST_DIR} -c ${GTEST_DIR}/src/gtest-all.cc
ar -rv libgtest.a gtest-all.o

It will generates the libraries libgtest.a (which contains GTest binaries). Consider a simple unit test example of a C source code named test1.c:

#include <gtest/gtest.h>
TEST(MathTest, TwoPlusTwoEqualsFour) {
EXPECT_EQ(2 + 2, 4);
}
int main(int argc, char **argv) {
::testing::InitGoogleTest( &argc, argv );
return RUN_ALL_TESTS();
}

To build it, it is necessary to defines the GTest headers directory (parameter includes dir -I), compile the source code and link it with the GTest library (libgtest.a) and pthread, as shown below (again, replace $(GTEST_DIR) by the GTest directory):

g++ -I ${GTEST_DIR}/include test1.c libgtest.a -lpthread -o test1

The call and the output is as follows:

./test1
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from MathTest
[ RUN      ] MathTest.TwoPlusTwoEqualsFour
[       OK ] MathTest.TwoPlusTwoEqualsFour (0 ms)
[----------] 1 test from MathTest (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[  PASSED  ] 1 test.

How to build GTest samples?

Jointly with the GTest, it also comes some C++ unit test examples, found in the samples directory. You can build this examples using CMake a simpler and powerful tool to generate Makefiles. It can be installed using apt-get:

sudo apt-get install cmake

The CMake uses a configuration file named CMakeLists.txt. The common way to build a project with CMake is create a build directory, generate a Makefile using CMake and build it with make. One advantage of using CMake is that you separate the deploy from source code and can make the deploy in multiple places with the same CMake file.

cd gtest-1.6.0
mkdir build
cd build
cmake -Dgtest_build_samples=ON ..
make

Now you can execute all examples that comes GTest.

cd gtest-1.6.0/build
./sample1_unittest
./sample2_unittest
...
./sample10_unittest

How to build your own CMake?

A last tip is how to build a CMakeFile.txt for your project. Instead of use the CMake file provided by GTest, let’s make our own CMake to build the GTest’s sample 1 (Factorial test). The CMake file will requires to know where you unzip GTest, which can be performed through an environment variable named GTEST_ROOT (replace “/tmp/gtest-1.6.0” by the GTest directory).

GTEST_ROOT="/tmp/gtest-1.6.0"
export GTEST_ROOT

Then, creates a CMakeLists.txt with the content below:

cmake_minimum_required(VERSION 2.6)
project(sample1)
enable_testing()
find_package (Threads)
message(STATUS GTEST_ROOT=$ENV{GTEST_ROOT})
include_directories($ENV{GTEST_ROOT}/include)
link_directories($ENV{GTEST_ROOT}/mybuild)
add_executable(sample1 sample1.cc sample1_unittest.cc)
target_link_libraries(sample1 gtest gtest_main)
target_link_libraries(sample1 ${CMAKE_THREAD_LIBS_INIT})
add_test(NAME sample1 COMMAND sample1)

To build it you should repeat the same steps above:

mkdir build
cd build
cmake ..
make

The call and output of this example is as follows:

./sample1
[==========] Running 6 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 3 tests from FactorialTest
[ RUN      ] FactorialTest.Negative
[       OK ] FactorialTest.Negative (0 ms)
[ RUN      ] FactorialTest.Zero
[       OK ] FactorialTest.Zero (0 ms)
[ RUN      ] FactorialTest.Positive
[       OK ] FactorialTest.Positive (0 ms)
[----------] 3 tests from FactorialTest (0 ms total)

[----------] 3 tests from IsPrimeTest
[ RUN      ] IsPrimeTest.Negative
[       OK ] IsPrimeTest.Negative (0 ms)
[ RUN      ] IsPrimeTest.Trivial
[       OK ] IsPrimeTest.Trivial (0 ms)
[ RUN      ] IsPrimeTest.Positive
[       OK ] IsPrimeTest.Positive (0 ms)
[----------] 3 tests from IsPrimeTest (0 ms total)

[----------] Global test environment tear-down
[==========] 6 tests from 2 test cases ran. (1 ms total)
[  PASSED  ] 6 tests.

See ya!

Profiling a C/C++ code with Valgrind + KCachegrind

First let’s explain what is profiling. In general terms, profiling is a technique that can be used when you experience performance problems in your application. Basically, it consists in measure the spent time of each code function, to identify where is the bottleneck, i.e., the lines of the code that concentrate more the execution time.

There is a lot of tools for this proposal. In Java we have JPerformance and that are very nice. For C/C++, one that is very used is the GNU gprof, which is very simple to use (just recall to compile your code with -pg flag). Recently I knew KCachegrind, which is a cache profiler based on Valgrind, that surprised me by the simplicity of its QT interface. Valgrind, for those who does not know, is not a profiling tool, it is a memory management tool that helps you to find bugs due to memory leaks, memory conflicts. It is very recommended to use Valgrind since the beginning of coding. Let’s explain a little bit more of KCachegrind.

You can install it by apt-get repostitory:

user@host:~$ sudo apt-get install valgrind kcachegrind

For demonstration, I use a database simulator written in C (by me and others) as a target application. The simulator repeat the database operation thousand of times and compute the average of some measured metrics. The normal execution takes hours, so I run a simple experiment with valgrind (which makes the execution much slower). Before call kcachegrind is necessary to call valgrind to profile the cache data.

user@host:~$ valgrind --tool=callgrind ./simulator --param param.txt --queries 10 --seed 65270
user@host:~$ kcachegrind callgrind.out.12208

I took some screenshots to highlights some KCachegrind features:

A first feature provided by Kcachegrind, showed in the first picture, is a table with the cumulative cost of each function. It consider that main() has 100% of cost and we can follow how this cost is distributed along the functions called by main(). The same feature, explained above, can be viewed in a graphic view, as depicted in the second figure. And another way to analyse the code is through the graph view, which starts in main(), showing the cumulative cost and walk through the code graph. On this graph we can views that the higher cost of the code is concentrated on vprintf function, which is used to log the simulator execution for debug purposes.

See ya!

Recursive makefile

I extended a Makefile, developed by Dr. R. K. Owen for general purposes. It’s usage is very simple. Put this Makefile in one directory above your source code. It considers that all your code are in a directory named ‘src’. It will search recursively on sub-directories of ‘src’ directory, generate the object code .o and link them all. There is also some debug flags and optimization flags that can be used or removed according to the situation.

# ----------------------------------------------------------------------------
# Makefile
# 
# release: 0.1 (28-Ago-2010) create makefile
# 
# purpose: searches recursively in current directory for c/cpp files (using find),
#          compile each source file and link them in a executable.
# ----------------------------------------------------------------------------

APP     = simulator
CC      = gcc
RM      = rm
SRCDIR  = src
SRCEXT  = c
OBJDIR  = obj

SRCS    := $(shell find $(SRCDIR) -name '*.$(SRCEXT)')
SRCDIRS := $(shell find . -name '*.$(SRCEXT)' -exec dirname {} \; | uniq)
OBJS    := $(patsubst %.$(SRCEXT),$(OBJDIR)/%.o,$(SRCS))

DEBUG   = -pg
INCLUDE = -I./inc
CFLAGS  = -Wall -DEBUG -lm -c $(DEBUG) $(INCLUDE)
OFLAGS  = -lm -msse2 -ffast-math -ftree-vectorize

all:    $(APP)

$(APP): buildrepo $(OBJS)
        @echo "$(CC) $(OFLAGS) $(OBJS) -o $@"
        @$(CC) $(OBJS) $(OFLAGS) -o $@

$(OBJDIR)/%.o: %.$(SRCEXT)
        @echo "$(CC) $(CFLAGS) $&lt; -o $@&quot;
        @$(CC) $(CFLAGS) $&lt; -o $@

clean:
        $(RM) -r $(OBJDIR)

buildrepo:
        $(call make-repo)

define make-repo
        for dir in $(SRCDIRS); \
        do \
                mkdir -p $(OBJDIR)/$$dir; \
        done
endef

See ya!

[C/C++] Include headers with crossed references

Hi fellows,

To instantiate a struct (created in a header) in more than one source file the first thing that must be done is use a guard directive #ifndef. It will make gcc export data types and function signatures only once (according to the Makefile order). Meanwhile, if you need that a struct in a header h1 has a pointer to a struct in a header h2, which already has a pointer to a struct from h1 it will result in an error since gcc cannot resolve header cross reference (when gcc is processing header h1, it will find the #include h2 and when it try to create the struct h2 it will no find the type h1 returning the error: “expected specifier-qualifier-list before h1”). The first thing is rethink in the solution design. To overcome this, one alternative is forward struct declaration. Follows an example:

h1.h

#ifndef H1_H
#define H1_H
struct h1;
typedef struct h1 h1;
#include "h2.h"
struct h1 {
	h1 *v1;
	h2 *v2;
};
#endif

h2.h

#ifndef H2_H
#define H2_H
struct h2;
typedef struct h2 h2;
#include "h1.h"
struct h2 {
	h1 *v1;
	h2 *v2;
};
#endif

main.c

#include "h1.h"
#include "h2.h"
int main() {
	h1 v1;
	h2 v2;	
	return 0;
}

See ya!