From: Pat Thoyts Date: Tue, 15 Jun 2010 23:31:01 +0000 (+0100) Subject: Added some unit tests for some of the utility functions. X-Git-Tag: v0.4~20^2 X-Git-Url: http://privyetmir.co.uk/gitweb?a=commitdiff_plain;h=04f0b40741931deeb05f52973f8cb9849e767200;p=anagramarama Added some unit tests for some of the utility functions. Signed-off-by: Pat Thoyts --- diff --git a/makefile b/makefile index 82cf077..66f4e65 100755 --- a/makefile +++ b/makefile @@ -1,27 +1,33 @@ -LFLAGS=-Wall -funroll-loops -fomit-frame-pointer -pipe -O9 -CFLAGS=-Wall `sdl-config --cflags --libs` -funroll-loops -fomit-frame-pointer -pipe -O9 -lSDL_mixer CC=gcc +LD=gcc +CFLAGS=-g -Wall `sdl-config --cflags` +CFLAG_OPTS=-funroll-loops -fomit-frame-pointer +LDFLAGS=`sdl-config --libs` -lSDL_mixer C_FILES=src/dlb.c src/linked.c src/sprite.c src/ag.c OBJ_FILES=src/dlb.o src/linked.o src/sprite.o src/ag.o +TEST_OBJS=$(OBJ_FILES:src/ag.o=src/ag_test.o) OUT_FILE=ag all:ag ag: $(OBJ_FILES) - $(CC) $(CFLAGS) -o $(OUT_FILE) $(OBJ_FILES) + $(LD) $(LDFLAGS) -o $@ $^ + +ag_test: $(TEST_OBJS) + $(LD) $(LDFLAGS) -o $@ $^ src/dlb.o: src/dlb.c - $(CC) $(LFLAGS) -c -o $@ $^ + $(CC) $(CFLAGS) -c -o $@ $^ src/linked.o: src/linked.c - $(CC) $(LFLAGS) -c -o $@ $^ - + $(CC) $(CFLAGS) -c -o $@ $^ + src/sprite.o: src/sprite.c - $(CC) $(LFLAGS) -c -o $@ $^ + $(CC) $(CFLAGS) -c -o $@ $^ src/ag.o: src/ag.c - $(CC) $(LFLAGS) -c -o $@ $^ + $(CC) $(CFLAGS) -c -o $@ $^ clean: rm -f src/*.o diff --git a/src/ag_test.c b/src/ag_test.c new file mode 100644 index 0000000..6bea8a4 --- /dev/null +++ b/src/ag_test.c @@ -0,0 +1,80 @@ +#define UNIT_TEST +#include "unittest.h" +#define main ag_main +#include "ag.c" +#undef main + +static int test_nextBlank() +{ + char a[7] = {'a','b',SPACE_CHAR,'c',SPACE_CHAR,'d', 0}; + test_equals_int("nextBlank", 3, nextBlank(a)); + test_equals_int("nextBlank substr", 2, nextBlank(a+3)); + test_equals_int("nextBlank no-blanks", 0, nextBlank("abcdef")); + test_equals_int("nextBlank zero-length", 0, nextBlank("")); + return 0; +} + +static int test_shiftLeftKill() +{ + char a[7] = { 'a','b','c','d','e','f', 0 }; + test_equals_str("shiftLeftKill", "bcdef", shiftLeftKill(a)); + test_equals_str("shiftLeftKill const str", "bcdef", shiftLeftKill("abcdef")); + return 0; +} + +static int test_shiftLeft() +{ + char a[7] = { 'a','b','c','d','e','f', 0 }; + char b[2] = { 'a', 0 }; + test_equals_str("shiftLeft string", "bcdefa", shiftLeft(a)); + test_equals_str("shiftLeft short string", "a", shiftLeft(b)); + return 0; +} + +static int test_swapChars() +{ + char a[7] = { 'a','b','c','d','e','f', 0 }; + const char *p = a, *q = NULL; + test_equals_str("swapChars end", "fbcdea", swapChars(0, 5, a)); + q = swapChars(2, 3, a); + test_equals_str("swapChars inner", "fbdcea", q); + test_equals_ptr("swapChars ptr equiv", p, q); + return 0; +} + +static int test_revFirstNonSpace() +{ + char a[7] = { 'a','b','c','d','e','f', 0 }; + char b[7] = { 'a','b',SPACE_CHAR,'d','e',SPACE_CHAR, 0 }; + test_equals_int("rev no space", 6, revFirstNonSpace(a)); + test_equals_int("rev find space", 5, revFirstNonSpace(b)); + return 0; +} + +static int test_whereinstr() +{ + test_equals_int("where is b", 1, whereinstr("abcdef",'b')); + test_equals_int("where is f", 5, whereinstr("abcdef",'f')); + test_equals_int("where is x", 0, whereinstr("abcdef",'x')); + return 0; +} + +struct unit_test_t unit_tests[] = { + {NULL, test_shiftLeftKill, NULL}, + {NULL, test_shiftLeft, NULL}, + {NULL, test_nextBlank, NULL}, + {NULL, test_swapChars, NULL}, + {NULL, test_revFirstNonSpace, NULL}, + {NULL, test_whereinstr, NULL}, +}; + +int +main(void) +{ + size_t n; + for (n = 0; n < sizeof(unit_tests)/sizeof(unit_tests[0]); ++n) { + run_tests(&unit_tests[n]); + } + test_print_results(); + return 0; +} diff --git a/src/unittest.h b/src/unittest.h new file mode 100644 index 0000000..9b4e7fc --- /dev/null +++ b/src/unittest.h @@ -0,0 +1,136 @@ +/* + * Simple C unit testing framework. + * + * Declare a table containing your tests and call the run_test function + * passing in this table. You can declare a setup and teardown function + * for each test and provide per-test custom data if needed. + * + * A number of test helpers are provided to check values. They all print + * to stdout and increment the pass/fail counters. + * + * For instance: + * + * #ifdef UNIT_TEST + * #include "unittest.h" + * + * static int testHashInit(void *clientData) + * { + * struct hash_table_t ht; + * + * hash_init(&ht, hash_algorithm_jim); + * test_equals_int("new table has size 0", ht.size, 0); + * test_equals_int("new table has usage 0", ht.used, 0); + * test_equals_ptr("new table using jim hash", ht.hashfunc, hash_algorithm_jim); + * + * hash_init(&ht, hash_algorithm_jenkins); + * test_equals_ptr("new table using jenkins hash", ht.hashfunc, hash_algorithm_jenkins); + * + * return 0; + * } + * + * struct unit_test_t unit_tests[] = { + * {NULL, testHashInit, NULL}, + * }; + * + * int + * main(void) + * { + * size_t n = 0; + * for (n = 0; n < sizeof(unit_tests)/sizeof(unit_tests[0]); ++n) { + * run_tests(&unit_tests[n]); + * } + * test_print_results(); + * } + */ + +#include +#include +#include + +#ifdef _MSC_VER +#ifndef FAKE_STDINT +#define FAKE_STDINT +typedef signed __int8 int8_t; +typedef signed __int16 int16_t; +typedef signed __int32 int32_t; +typedef signed __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#endif /* FAKE_STDINT*/ +#endif /* _MSC_VER */ +#ifndef FAKE_STDINT +#include +#endif + +typedef void * (unit_test_setup_t)(); +typedef int (unit_test_run_t)(void *); +typedef void (unit_test_teardown_t)(void *); + +struct unit_test_t { + unit_test_setup_t *setUp; + unit_test_run_t *runTest; + unit_test_teardown_t *tearDown; +}; + +static int test_count = 0; +static int fail_count = 0; + +#define RUN(what) printf("\t%s\n", what); test_count++; + +static test_fail(const char *what) +{ + printf("\tFAIL: %s\n", what); + fflush(stdout); + fail_count++; +} +static void test_equals_int(const char *what, const int a, const int b) +{ + RUN(what); + if (a != b) test_fail(what); +} +static void test_equals_wide(const char *what, const uint64_t a, const uint64_t b) +{ + RUN(what); + if (a != b) test_fail(what); +} +static void test_equals_ptr(const char *what, const void *a, const void *b) +{ + RUN(what); + if (a != b) test_fail(what); +} +static void test_equals_str(const char *what, const uint8_t *a, const uint8_t *b) +{ + RUN(what); + if (strcmp((const char *)a,(const char *)b)) test_fail(what); +} +static void test_equals_strn(const char *what, const uint8_t *a, const uint8_t *b, size_t n) +{ + RUN(what); + if (strncmp((const char *)a,(const char *)b,n)) test_fail(what); +} +static void test_non_null_ptr(const char *what, const void *a) +{ + RUN(what); + if (NULL == a) test_fail(what); +} + +static void +test_print_results() +{ + printf("\t%d / %d pass\n", (test_count-fail_count),test_count); +} + +static int +run_tests(const struct unit_test_t *testPtr) +{ + int r = 0; + void *clientData = NULL; + if (testPtr->setUp) + clientData = testPtr->setUp(); + r = testPtr->runTest(clientData); + if (testPtr->tearDown) + testPtr->tearDown(clientData); + return r; +}