Pages

GTest on Ubuntu

The Google C++ Testing Framework (better known as Google Test, or even GTest), has been designed to be as platform independent as possible. There are only a few little difference in setting it up on any specific environment, as you could see comparing this post with the one I wrote some time ago on how to set GTest up for Windows, and this one, focused on Linux (in a Debian flavor).

First step is always the same: go to Google code and download the Google Test zipped archive.

Do you already have cmake at hand? The Google Test package provides a few specific building files for some environments, the other ones are generated on the fly by this tool. Have a look at the official CMake site for more information. Here we'll be happy enough getting cmake from the standard repository:
sudo apt-get install cmake
Once you have unzipped the GTest package, you should see in its base directory a file named CMakeLists.txt, we'll pass it to cmake to generate a proper Makefile tailored on the current system characteristics.
cmake CMakeLists.txt
Do you see a newly generated Makefile? Good, make it up. As result you should get (among the other stuff) a couple of static libraries: libgtest.a and libgtest_main.a

I symlink-ed them in /usr/local/lib, then I symlink-ed the include/gtest directory to /usr/local/include. Now I am ready to write a tiny test application.

Here is the Makefile that I am going to use:
MY_NAME := gt
MY_SRCS := $(wildcard *.cpp)
MY_OBJS := ${MY_SRCS:.cpp=.o}

MY_INCLUDE_DIRS := /usr/local/include
MY_LIBRARY_DIRS := /usr/local/lib
MY_LIBRARIES := gtest

CXXFLAGS += $(foreach includedir,$(MY_INCLUDE_DIRS),-I$(includedir))
CXXFLAGS += -Wall -g -pthread
LDFLAGS += $(foreach librarydir,$(MY_LIBRARY_DIRS),-L$(librarydir))
LDLIBS += $(foreach library,$(MY_LIBRARIES),-l$(library))

.PHONY: all clean

all: $(MY_NAME)

$(MY_NAME): $(MY_OBJS)
    $(LINK.cc) -o $(MY_NAME) $(MY_OBJS) $(LDLIBS)

clean:
    @- rm -rf $(MY_OBJS) $(MY_NAME)
Notice that among the C++ flags it has been specified -pthread, since GTest requires the POSIX thread library. If you forget to specify it, you would get a bunch of undefined reference to pthreads symbols.

I reused the source code as defined in my old post about GTest on Windows that, as expected, works smoothly in this new context. The only (really minor) change that I applied is in the main function. Here I want to always run the tests and then give the control to the normal application execution path:
int main(int argc, char* argv[])
{
    Tester(argc, argv).run();

    std::cout << "Normal program behavior" << std::endl;
}
If you run it, you would get the output from GTest, where a test (TestIncrease.NormalBehavior) succeedes and another one (TestIncrease.ErrorTest) fails.

Alternatively, you could remove the C++ main function source from the build, and use instead the standard bootstrap functionality that GTest makes available. To do that, just add gtest_main among the libraries in the MY_LIBRARIES list.

Gary (thank you!) suggests me to stress a couple of points, very useful if you are new in this area:
  • Indentation in Makefile is done with tabs!
  • In the UNIX family of Operating Systems, the file separator is the slash ('/'), be careful not to use the backslash ('\')!

Go to the full post

Redis hello world

Once your environment is set up for Redis, it is easy to use the hiredis C interface to work with it. Here I write and use a minimal, shamelessly almost-C, bunch of functions to connect, set, get, and finally disconnect from a Redis server.

I am writing in C++, but here you won't see much of a difference from a plain C implementation. This is to keep the example focused on the hiredis features. I plan to refactor this code to have some C++ fun in a next post.

What I want to do, is connecting to a Redis server (assuming it runs locally on the default port), store on it a key/value pair, and immediately fetch it back. Something like this:
redisContext* ctx = TTR::connect("localhost", 6379); // 1
if(ctx)
{
    std::string key("key"); // 2
    std::string value("value");

    TTR::set(ctx, key, value); // 3
    std::string cache = TTR::get(ctx, key); // 4
    if(value == cache)
    {
        std::cout << "Value stored and fetched correctly" << std::endl;
    }
    else
    {
        std::cout << "Something weird happened" << std::endl;
    }

    TTR::disconnect(ctx); // 5
}
1. redisContext is the hiredis structure that keeps the context for a connection to Redis. Namespace is one of the few C++ features I'm using here, all my wrapper functions are in a namespace named TTR, so to avoid any name clash. The TTR::connect() function is one of them and, as you should expect, it establish a connection to the specified Redis server, or returns NULL in case of failure.
2. The key/value pair that I want to store on Redis.
3. Push a key/value to the server.
4. Fetch the value from the Radis server for the same key I have already used for the set(). I wouldn't ever expect the fetched value being different from the original one.
5. Do not forget to disconnect!

Writing code like that in the real world is asking for trouble. Converting my bunch of free functions in a class is easy, straightforward and immediately pays off, saving the nuisance of passing around the Redis context and be forced of taking care of its disposal. But I'll do it another time.

Let's now see how I have implemented my functions - remember that all of them are in the TTR namespace.

The most interesting one is connect():
redisContext* connect(const std::string& server, int port)
{
    std::string sport = server + ":" + boost::lexical_cast<std::string>(port); // 1

    if(!port || server.empty()) // 2
    {
        std::cout << "Can't connect to Redis [" + sport + "]" << std::endl;
        return NULL;
    }

    redisContext* context = redisConnect(server.c_str(), port); // 3
    if(!context) // paranoid
    {
        std::cout << "No memory for Redis on " + sport << std::endl;
        return NULL;
    }

    if(context->err) // 4
    {
        std::cout << "Can't connect to Redis on " + sport + " - " + context->errstr << std::endl;

        redisFree(context); // 5
        return NULL;
    }

    std::cout << "Connected to Redis [" + sport + "]" << std::endl;
    return context;
}
1. I concatenate the server name to the port number for debugging purpose, notice the usage of the handy boost lexical cast to convert an integer to a C++ string.
2. Test for valid user input. It could, and probably should, be more strict. But you get the idea.
3. Call the hiredis connection function. It would fail, returning NULL, for an out of memory problem. This is quite improbable. Still, better safe than sorry.
4. When there is a trouble connecting to the Redis server, we have it reported in the fields err and errstr on the Redis context object returned. If this is the case, I log a message, release the context, and return a fat NULL to the caller.
5. Remember, any context returned by redisConnect() has to be cleaned up calling redisFree().

The disconnect() is so boring that one would happily hide it in a class destructor:
void disconnect(redisContext* context)
{
    if(context) // 1
    {
        std::cout << "Disconnecting from Redis" << std::endl;
        redisFree(context);
    }
}
1. Passing a NULL to redisFree could result in a disaster (AKA a segmentation fault), so, I'd better check for it.

The real stuff, setting and getting a value on Redis, is done by these functions:
void set(redisContext* context, const std::string& key, const std::string& value) // 1
{
    if(!context) // 2
        return;

    void* reply = // 3
        redisCommand(context, "SET %b %b", key.c_str(), key.length(), value.c_str(), value.length());
    if(reply)
    {
        freeReplyObject(reply);
        return;
    }

    // unexpected
    std::cout << "No reply from Redis" << std::endl;
}

std::string get(redisContext* context, const std::string& key)
{
    if(!context)
        return "";

    redisReply* reply = static_cast<redisReply*>(redisCommand(context, "GET %b", key.c_str(), key.length()));
    if(!reply)
        return "";

    std::string result = reply->str ? reply->str : ""; // 4
    freeReplyObject(reply);
    return result;
}
1. We don't care about the Redis reply, any failure in setting a value for a specified key for the passed Redis context is (almost) silently ignored.
2. As we have already seen, Redis doesn't check if the context we pass to it is good or not. To avoid an unpleasent segmentation fault, it's better to check it ourself.
3. Here I don't care of what is the actual reply of the Redis server, I only check if it actually emits an answer and, if so, I clean it up.
As you can see, redisCommand() is designed to be similar to the standard C fprintf() function. First argument is the Redis context on which the call is performed, Than we have a string, containing the name of the actual operation (here is SET) and any required parameter, identified by a percent flag. If you know that you are about to send plain strings with no special character in it, you can use the "%s" placeholder. By I want to play safe, so I use the "%b", that allows binary strings to be sent. In this case I have to double the number of subsequent arguments, passing both the relative C-string and its size.
4. When I GET from Redis, I am much more interested in the reply object, so I cast the redisCommand() return value (a void pointer) to a pointer to its actual type, redisReply. I need its str field, that contains the value that Redis stores for the key passed as GET parameter, so firstly I check if the reply is not NULL, then I copy its str content in a C++ string, so that I can safely clean the reply object up before returning.

Go to the full post

Preparing to write a Redis client

I have to add some caching capabilities to a C++ module in my current project. There are a few viable alternatives, but we already have a Redis server available, and we don't have any compelling reason to look to anything else. So, it is almost done, I have just to download Redis source code, and preparing the environment to write a tiny test client.

There are a few ways to install Redis, I downloaded it from the official site, redis.io, following the instructions you could find there. In a matter of minutes I had a plain Redis server up and running and I checked it through redis-cli (Redis command line interface utility).

There are plenty of available Redis clients for different programming languages and you typically want to get an existing one matching your elected language. But in C++ case, I see only one alternative in the list proposed by Redis, and there are a few reasons not to peek it up. The code in the repository is quite old (2/3 years), and in the list it is not marked as recommended. So I fell back to hiredis, the official C client, included in the distribution (you could find it under deps/hiredis).

All I need is at hand, I just have to write a Makefile (you can download it from github), and then I am ready to write some code:
#
# Makefile for hiredis client
#

MY_NAME := hrc
MY_SRCS := $(wildcard *.cpp)
MY_OBJS := ${MY_SRCS:.cpp=.o}

MY_INCLUDE_DIRS := /usr/local/include/hiredis
MY_LIBRARY_DIRS := /usr/local/lib
MY_LIBRARIES := hiredis

CXXFLAGS += $(foreach includedir,$(MY_INCLUDE_DIRS),-I$(includedir))
CXXFLAGS += -Wall -g -std=c++11
LDFLAGS += $(foreach librarydir,$(MY_LIBRARY_DIRS),-L$(librarydir))
LDLIBS += $(foreach library,$(MY_LIBRARIES),-l$(library))

.PHONY: all clean

all: $(MY_NAME)

$(MY_NAME): $(MY_OBJS)
    $(LINK.cc) -o $(MY_NAME) $(MY_OBJS) $(LDLIBS)

clean:
    @- rm -rf $(MY_OBJS) $(MY_NAME)
My client is going to be named hrc (as MY_NAME shows), it is written in C++, and the code is contained in .cpp files (MY_SRCS). Any cpp file would have a matching object file identified by the "o" extension (MY_OBJS).

The only custom directory I want to include now is the one for the hiredis client (MY_INCLUDE_DIRS), and I want the make tool to check just in one custom directory for non standard library (MY_LIBRARY_DIRS), and the only custom library I currently want (MY_LIBRARIES) is hiredis. You would probably ask makefile to look in other directories. Remember that the actual library names are decorated versions for the bare name you should put in the makefile. In this case, Redis compilation has generated an archive named libhiredis.a, for static linkage, and a shareable object named libhiredis.so.

Besides, the linker would search for the actual versioned file, as maintained by ldd. In the worst case scenario, it could happens that the linker would complain for missing a versioned so. You could fix this by ldconfig, or even by hand, creating a reference to the missing file through symlink.

I add to the CXXFLAGS firstly the dependencies for include directories and then a bunch of option - I want all the warnings up (-Wall), the executable filled with debug information (-g), and the code generated to support the latest C++ standard (-std=c++11).

In the LDFLAGS I add the dependencies for library directories, and in LDLIBS the actual requested library names.

An then I defines a few targets. A couple of phony ones, "all" and "clean", as tradition wants, and the one that actually creates my target.

Notice that I don't specify explicitly the name of the C++ compiler, but I rely on the make tool to be smart enough to deduce it from the environment. For this reason I use LINK.cc, that in my case contains the expected g++.

In the next post, I am going to write some C++ code meant to be compiled with this Makefile.

Go to the full post