From 3559c6f8e6f97c8c42487041d70165f59a126306 Mon Sep 17 00:00:00 2001
From: Marek Vavrusa <marek@vavrusa.com>
Date: Thu, 14 Oct 2010 17:39:33 +0200
Subject: [PATCH] Initial unit testing framework.

Tests for server unit.
TAP protocol output.
---
 Makefile                 | 23 +++++++++----
 src/tests/main.c         | 21 ++++++++++++
 src/tests/server_tests.c | 74 ++++++++++++++++++++++++++++++++++++++++
 src/tests/tap_unit.h     | 27 +++++++++++++++
 4 files changed, 138 insertions(+), 7 deletions(-)
 create mode 100644 src/tests/main.c
 create mode 100644 src/tests/server_tests.c
 create mode 100644 src/tests/tap_unit.h

diff --git a/Makefile b/Makefile
index ea95b7e26..60e0282b2 100644
--- a/Makefile
+++ b/Makefile
@@ -9,22 +9,24 @@ COL_CYAN = \033[01;36m
 COL_WHITE = \033[01;37m
 COL_END = \033[0m
 
-INC_DIRS = src/ src/tests/ src/hash/ src/dns/ src/other/ src/server/ src/zone/
+INC_DIRS = src/ src/hash/ src/dns/ src/other/ src/server/ src/zone/ src/tests src/tests/libtap
 SRC_DIRS = src/
+TESTS_DIR = src/tests/
 OBJ_DIR = obj/
 BIN_DIR = bin/
 
 VPATH += ${SRC_DIRS} ${INC_DIRS} ${OBJ_DIR}
 
-SRC_FILES = $(shell find $(SRC_DIRS) -name "*.c" )
+SRC_FILES = $(shell find $(SRC_DIRS) ! -path "*/tests/*" -name "*.c" ! -name "main.c")
+TESTS_FILES = $(TESTS_DIR)/main.c $(TESTS_DIR)/libtap/tap.c
 
 OBJS = $(addprefix $(OBJ_DIR), $(addsuffix .o, $(basename $(notdir $(SRC_FILES)))))
 
 CC = gcc
-CFLAGS += -Wall -std=gnu99 -D _XOPEN_SOURCE=600
+CFLAGS += -Wall -std=gnu99 -D _XOPEN_SOURCE=600 -D_GNU_SOURCE
 LDFLAGS += -lpthread -lurcu -lldns
 
-all:cutedns
+all: cutedns unittests
 
 ### Dependencies ###
 DEPEND = $(CC) $(addprefix -I ,$(INC_DIRS)) -MM $(SRC_FILES)   2>/dev/null | sed "s%^\([^\ \t\n]*\.o\)%$(OBJ_DIR)/\1%"
@@ -33,9 +35,16 @@ Makefile.depend:
 	@$(DEPEND) > Makefile.depend
 
 # cutedns
-cutedns: Makefile.depend $(OBJS)
-	@echo "$(COL_WHITE)Linking... $(COL_YELLOW)${BIN_DIR}$@$(COL_END) <-- $(COL_CYAN)$(OBJS)$(COL_END)"
-	@$(CC) $(LDFLAGS) $(OBJS) -o ${BIN_DIR}$@
+cutedns: Makefile.depend $(OBJS) $(SRC_DIRS)main.c
+#	@echo "$(COL_WHITE)Linking... $(COL_YELLOW)${BIN_DIR}$@$(COL_END) <-- $(COL_CYAN)$(OBJS) $(SRC_DIRS)main.c$(COL_END)"
+	@$(CC) $(CFLAGS) $(addprefix -I ,$(INC_DIRS)) $(LDFLAGS) $(OBJS) $(SRC_DIRS)main.c -o ${BIN_DIR}$@
+
+unittests: Makefile.depend cutedns $(OBJS) $(TESTS_FILES)
+#	@echo "$(COL_WHITE)Linking... $(COL_YELLOW)${BIN_DIR}$@$(COL_END) <-- $(COL_CYAN)$(OBJS) $(TESTS_FILES)$(COL_END)"
+	@$(CC) $(CFLAGS) $(addprefix -I ,$(INC_DIRS)) $(LDFLAGS) $(OBJS) $(TESTS_FILES) -o ${BIN_DIR}$@
+
+test: unittests
+	@bin/unittests samples/example.com.zone
 
 .PHONY: Makefile.depend
 .INTERMEDIATE: Makefile.depend
diff --git a/src/tests/main.c b/src/tests/main.c
new file mode 100644
index 000000000..c5069db14
--- /dev/null
+++ b/src/tests/main.c
@@ -0,0 +1,21 @@
+#include "libtap/tap.h"
+#include "common.h"
+
+// Units to test
+#include "server_tests.c"
+
+// Run all loaded units
+int main(int argc, char * argv[])
+{
+   // Plan number of tests
+   int test_count = 0;
+   test_count += server_tests_api.count(argc, argv);
+   plan(test_count);
+
+   // Run tests
+   note("Testing unit: %s ...", server_tests_api.name);
+   server_tests_api.run(argc, argv);
+
+   // Evaluate
+   return exit_status();
+}
diff --git a/src/tests/server_tests.c b/src/tests/server_tests.c
new file mode 100644
index 000000000..9d49354d5
--- /dev/null
+++ b/src/tests/server_tests.c
@@ -0,0 +1,74 @@
+#include "server/server.h"
+#include "tap_unit.h"
+
+int server_tests_count(int argc, char * argv[]);
+int server_tests_run(int argc, char * argv[]);
+
+/*
+ * Unit API.
+ */
+unit_api server_tests_api = {
+   "Server",
+   &server_tests_count,
+   &server_tests_run
+};
+
+/*
+ *  Unit implementation.
+ */
+
+static const int SERVER_TEST_COUNT = 3;
+
+/*! Test: create server. */
+cute_server* test_server_create()
+{
+   return cute_create();
+}
+
+/*! Test: start server. */
+int test_server_start(cute_server* s, char **filenames, uint zones)
+{
+   return cute_start(s, filenames, zones) == 0;
+}
+
+/*! Test: stop server. */
+int test_server_destroy(cute_server* s)
+{
+   cute_destroy(&s);
+   return s == 0;
+}
+
+/*! API: return number of tests. */
+int server_tests_count(int argc, char * argv[])
+{
+   return SERVER_TEST_COUNT * (argc - 1) + 1;
+}
+
+/*! API: run tests. */
+int server_tests_run(int argc, char * argv[])
+{
+   int ret = 0;
+   cute_server* server = 0;
+
+   /* For each zone, try to run and teardown server. */
+   for(int i = 1; i < argc; ++i) {
+
+      //! Test server for correct initialization
+      server = test_server_create();
+      ok(server != 0, "server: initialized");
+
+      //! Test server startup
+      ret = 0;
+      lives_ok({
+         ret = test_server_start(server, argv + i, 1);
+      }, "server: not crashing on runtime");
+
+      //! Test server exit code
+      ok(ret, "server: started ok");
+
+      //! Test server for correct deinitialization
+      ok(test_server_destroy(server), "server: deinit");
+   }
+
+   return 0;
+}
diff --git a/src/tests/tap_unit.h b/src/tests/tap_unit.h
new file mode 100644
index 000000000..c7435d468
--- /dev/null
+++ b/src/tests/tap_unit.h
@@ -0,0 +1,27 @@
+#ifndef TAP_UNIT_H
+#define TAP_UNIT_H
+
+#include "libtap/tap.h"
+
+/*! Pointer to function for unit_api.
+ */
+typedef int(unitapi_f)(int,char*[]);
+
+
+/*! Basic Unit APIs.
+ *
+ *  Each unit should have one global variable with
+ *  initialized instance of unit_api.
+ *
+ *  Unit API should contain:
+ *  - name (const char*)
+ *  - count (function to calculate number of tests)
+ *  - run (function to run unit tests)
+ */
+typedef struct {
+   const char* name;
+   unitapi_f* count;
+   unitapi_f* run;
+} unit_api;
+
+#endif
-- 
GitLab