[Nelug] ld and unit testing in C

Oliver Burnett-Hall olly at burnett-hall.co.uk
Mon Sep 24 11:55:28 UTC 2007


I posted this plea for help on the TyneLUG list a week or two ago, and got
absolutely no responses.  So I'm trying here now, hoping the someone knows
about this stuff...

I'm trying to play around with unit testing in C to try help in making
safe changes to a large code bases (it's gnumeric that I'm interesting
in hacking, about 350k lines).  From a small amount of googling, check
(http://check.sf.net) seems to be well suited for my needs.

Unfortunately, due to my very limited knowledge of building C programs,
I'm having trouble getting anything to build in the testing harness.
And I'm hoping that someone who knows about this stuff can tell me where
I'm going wrong.

The basic directory structure I've got is this:

gnumeric/
   |
   +--src/        <-- program code base, including subdirs
   |
   +--test/       <-- existing functional tests
        |
        +--unit/  <-- new unit tests

I started off by trying to put a very simple function under test.  This
is the basic contents of the file check_ranges.c that I've created:

----------------------------------------
#include <stdlib.h>
#include <check.h>
#include "ranges.h"

START_TEST (test_range_is_sane) {
         GnmRange range;
         range_init (&range, 1, 1, 2, 2);
         fail_unless (range_is_sane (&range));
} END_TEST

int
main (void)
{
        /* code for running the test */
}
----------------------------------------

I want to have everything built using autofoo, but as I can't get
anything to build at the moment I've been trying to get this to work in
baby steps.

I can compile an object file from this using this command (broken onto
multiple lines to make it easier to read):

# gcc -c -I../../src \
      -I/usr/local/include/libgoffice-0.5 \
      -I/usr/include/glib-2.0 \
      -I/usr/lib/glib-2.0/include \
      check_ranges.c

Looking for undefined references in the object file, I get these:

# nm check_ranges.o | grep U
          U _fail_unless
          U _tcase_add_test
          U range_init
          U range_is_sane
          U srunner_create
          U srunner_free
          U srunner_ntests_failed
          U srunner_run_all
          U suite_add_tcase
          U suite_create
          U tcase_create
          U tcase_fn_start

The tcase_*, srunner_* and _* functions are all from check.  That leaves
just the two functions from gnumeric that I included in my test; these are
both simple functions and don't themselves depend on anything else.  Both
of these are declared/defined in src/ranges.[ch], and have already been
compiled into src/.lib/ranges.o.

Now, I was expecting to be able to produce an executable by doing this:
# gcc check_ranges.o ../../src/.libs/ranges.o -lcheck -o check_ranges

But this tries to find every undefined reference in ranges.o as well,
giving me a ton of errors as I haven't included all of the
libraries/object files that it requires.

So, what I really want to do is somehow treat ranges.o as a static
library and just pull out the definitions that I need.  Is this at all
possible?

The gnumeric build does produce a libspreadsheet.la library, and I can
use this to build the test (i.e. gcc check_ranges.o -lspreadsheet
-lcheck -o check_ranges) and can run it succesfully.  But doing that
would mean that libspreadsheet would have to be rebuilt after every
change in the gnumeric source code, which is something I don't want to
do.  It would also defeat the point of unit tests, which are supposed to
include as few dependencies as possible.

So, is there any way I can partially link to ranges.o?  Or am I doing
this all completely wrong?

- olly






More information about the Nelug mailing list