###Pushy I’ve been developing a cheerfully indolent little HTTP server for some time now, as one of those ’learn-more-c’, ’learn-TDD’ projects that I imagine nearly everyone has lying around, half neglected.

You can see the code for pushy on github.

I’ve also been familiarizing myself with the HTTP RFCs as I go, so I was planning to add a 414 response^[1] to pushy’s repertoire, which I reckoned would take me about 30 minutes, but I have the TDD policy on this project, so naturally I can’t write a line of code until there’s a failing test. I’m on a new machine, so I need to install Check.

Let the games commence.

###Install MacPorts

MacPorts is available from the MacPorts project website. Once you have this, installing Check should be as simple as port install check.

###Get the tutorial project

You’ll be pleased to know that Check comes with a wildly overcomplicated tutorial.

On my system the Check install includes a set of tutorial files in /opt/local/share/doc/check/example. If you don’t find anything here it should be possible to query your package manager, for instance port contents check, or rpm -ql <package-name>, dpkg -L <package-name>, depending on your poison.

Create a working directory and copy the tutorial files there:

mkdir check-tutorial
cp -r /opt/local/share/doc/check/example check-tutorial/

###Build the project

That’s easy, isn’t it? I checked the README, and saw I needed to grab the following dependencies:

  • Autoconf
  • Automake
  • Libtool

And then it should be a case of:

autoreconf --install
./configure
make
make check

So, I gave that a spin:

tom@binky:check-tutorial:$ autoreconf --install
glibtoolize: Consider adding `AC_CONFIG_MACRO_DIR([m4])' to configure.ac and
glibtoolize: rerunning glibtoolize, to keep the correct libtool macros in-tree.
glibtoolize: Consider adding `-I m4' to ACLOCAL_AMFLAGS in Makefile.am.
automake: warnings are treated as errors
/opt/local/share/automake-1.12/am/ltlibrary.am: warning: 'libmoney.la': linking libtool libraries using a non-POSIX
/opt/local/share/automake-1.12/am/ltlibrary.am: archiver requires 'AM_PROG_AR' in 'configure.ac'
src/Makefile.am:3:   while processing Libtool library 'libmoney.la'
tests/Makefile.am:5: warning: compiling 'check_money.c' with per-target flags requires 'AM_PROG_CC_C_O' in 'configure.ac'
autoreconf: automake failed with exit status: 1

And fell very much at the first hurdle. Still, those are some sensible errors so it should be easy to fix. First I added the missing macros, as directed by the output, which led to the following changes to Makefile.am:

{% highlight diff %} — /opt/local/share/doc/check/example/Makefile.am 2012-08-10 22:56:02.000000000 +0100 +++ Makefile.am 2012-08-12 15:21:39.000000000 +0100 @@ -1,5 +1,3 @@

Process this file with automake to produce Makefile.in

+SUBDIRS = src . tests + +ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = src . tests {% endhighlight %}

I also added AC_CONFIG_MACRO_DIR([m4]) to configure.ac and created the corresponding directory in the project:

tom@binky:check-tutorial:$ mkdir m4

Now I get:

tom@binky:check-tutorial:$ autoreconf --install
...
/opt/local/share/automake-1.12/am/ltlibrary.am: archiver requires 'AM_PROG_AR' in 'configure.ac'

So I add the final macro to configure.ac which results in the following changes:

{% highlight diff %} — /opt/local/share/doc/check/example/configure.ac 2012-08-10 22:56:02.000000000 +0100 +++ configure.ac 2012-08-12 15:24:38.000000000 +0100 @@ -10,16 +10,13 @@

place to put some extra build scripts installed

AC_CONFIG_AUX_DIR([build-aux])

+AC_CONFIG_MACRO_DIR([m4]) +

fairly severe build strictness

change foreign to gnu or gnits to comply with gnu standards

AM_INIT_AUTOMAKE([-Wall -Werror foreign 1.9.6])

Checks for programs.

+AM_PROG_CC_C_O -AC_PROG_CC AC_PROG_LIBTOOL +AM_PROG_AR

Checks for libraries.

{% endhighlight %}

And finally it passes this step.

The next instruction is ./configure, which in my experience is always a one-stop-shop for merriment. It wasn’t too bad in this instance.

checking for check - version >= 0.8.2... no
*** Could not run check test program, checking why...
*** The test program failed to compile or link. See the file config.log for
*** the exact error that occured.
configure: error: check not found

This is to be expected, because my environment doesn’t know about the includes MacPorts installs under /opt. To fix, I first check the variable C_INCLUDE_PATH is unset:

echo $C_INCLUDE_PATH

And then set it:

export C_INCLUDE_PATH=/opt/local/include

If it already has some value, you should prepend the new path to the old, i.e.

export C_INCLUDE_PATH=/opt/local/include:$C_INCLUDE_PATH

And then, run ./configure a final time. Next, make. If I were a betting man I’d put money on the linker having a great big episode.

tom@binky:check-tutorial:$ make; make check
...
/bin/sh ../libtool --tag=CC   --mode=link gcc  -g -O2   -o check_money check_money-check_money.o ../src/libmoney.la -lcheck 
libtool: link: gcc -g -O2 -o .libs/check_money check_money-check_money.o  ../src/.libs/libmoney.dylib -lcheck
ld: library not found for -lcheck
collect2: ld returned 1 exit status
make[2]: *** [check_money] Error 1
make[1]: *** [check-am] Error 2
make: *** [check-recursive] Error 1

I love it when I’m right. No, really. Love it.

So the most useful line in there is ld: library not found for -lcheck, which tells me the linker (ld) can’t find libcheck. Because I’m using a Mac I know that I’m looking for the .dylib files that were installed with Check. On linux I expect they would be .so files. In my case these happen to be in /opt/local/lib, so I need to make the environment aware of this location by setting LIBRARY_PATH (linux: LD_LIBRARY_PATH):

export LIBRARY_PATH=/opt/local/lib

And finally:

tom@binky:check-tutorial:$ make check
Making check in src
...
Running suite(s): Money
100%: Checks: 3, Failures: 0, Errors: 0
PASS: check_money
=============
1 test passed
=============

Job done.

Why’s it so painful?

The tutorial fails at the first step and it can be hard to understand why. I’ve never had the pleasure of using autotools, but I’m beginning to see why there’s some anti-gnu sentiment in the Unix-sphere. It’s a tremendously complicated build for a very, very simple project.

It doesn’t help that many of the links to documentation on the Check project page are broken.

I happen to think that a test framework should be independent of the build system (you may say I’m a dreamer), so I’m going to pursue this to some sort of logical, probably painful, conclusion.

###What have we achieved? Well, nothing that I set out to achieve, which was having a working test suite so I can add a simple feature to my server. Expect a Part Deux in the near-ish future.

[1] and yes, this is related to a buffer over-run bug, thank you for asking.