From 34217eabacbeb472144919777063c7cf0e52b72f Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Tue, 27 Mar 2012 12:56:15 +0200 Subject: [PATCH] more tests...and some little structural changes to make then happen correctly with coverage reports. KEEP IN MIND: coverage reports lie to you. (But they are a good hint to see whats not testes enough --- .gitignore | 2 + Makefile.am.coverage | 10 ++- include/class/class.h | 5 +- src/class/Makefile.am | 2 +- src/class/interface/{class.c => i_class.c} | 0 src/http/Makefile.am | 13 ++- .../{http_intro.c => i_http_intro.c} | 0 src/http/parser/{body.c => p_body.c} | 0 src/http/parser/{header.c => p_header.c} | 0 .../parser/{post_vars.c => p_post_vars.c} | 0 .../{request_vars.c => p_request_vars.c} | 0 src/http/worker/{write.c => answer.c} | 0 src/logger/Makefile.am | 3 +- src/logger/interface/{logger.c => i_logger.c} | 0 tests/Makefile.am | 26 ++++-- tests/classTest.c | 32 ++++++- tests/loggerTest | Bin 0 -> 62970 bytes tests/loggerTest.c | 83 +++++++++++------- tests/mock/mock_class.c | 35 +++----- tests/mock/mock_logger.c | 29 ++++++ tests/mock/mock_logger.h | 20 +++++ tests/runtest.c | 10 +-- tests/runtest.h | 6 +- 23 files changed, 188 insertions(+), 88 deletions(-) rename src/class/interface/{class.c => i_class.c} (100%) rename src/http/interface/{http_intro.c => i_http_intro.c} (100%) rename src/http/parser/{body.c => p_body.c} (100%) rename src/http/parser/{header.c => p_header.c} (100%) rename src/http/parser/{post_vars.c => p_post_vars.c} (100%) rename src/http/parser/{request_vars.c => p_request_vars.c} (100%) rename src/http/worker/{write.c => answer.c} (100%) rename src/logger/interface/{logger.c => i_logger.c} (100%) create mode 100755 tests/loggerTest create mode 100644 tests/mock/mock_logger.c create mode 100644 tests/mock/mock_logger.h diff --git a/.gitignore b/.gitignore index edf81c9..f9e7c69 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ Makefile.in m4/ /docs/ /INSTALL +coverage.base +coverage.run coverage.info coveragereport/ *.m4 diff --git a/Makefile.am.coverage b/Makefile.am.coverage index 72e718b..470d456 100644 --- a/Makefile.am.coverage +++ b/Makefile.am.coverage @@ -10,13 +10,19 @@ .PHONY: coverage-html generate-coverage-html clean-coverage-html coverage-html: clean-gcda + -$(MAKE) -C tests $(AM_MAKEFLAGS) -k check-build + $(MAKE) $(AM_MAKEFLAGS) init-coverage-html -$(MAKE) $(AM_MAKEFLAGS) -k check $(MAKE) $(AM_MAKEFLAGS) generate-coverage-html + + init-coverage-html: + $(LCOV) -d $(top_builddir) -c -i -o coverage.base --no-checksum --compat-libtool generate-coverage-html: @echo Collecting coverage data - $(LCOV) --directory $(top_builddir) --capture --output-file coverage.info --no-checksum --compat-libtool - LANG=C $(GENHTML) --prefix $(top_builddir) --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info + $(LCOV) -d $(top_builddir) -c -o coverage.run --no-checksum --compat-libtool + $(LCOV) -d $(top_builddir) -a ./coverage.base -a ./coverage.run -o coverage.info --no-checksum --compat-libtool + LANG=C $(GENHTML) --prefix $(top_builddir) --output-directory coveragereport --title "Code Coverage" --legend --branch-coverage --show-details coverage.info clean-coverage-html: clean-gcda -$(LCOV) --directory $(top_builddir) -z diff --git a/include/class/class.h b/include/class/class.h index 4a8146c..b8b38cc 100644 --- a/include/class/class.h +++ b/include/class/class.h @@ -66,10 +66,13 @@ }; struct class * const _##name = &c_##name #define INIT_CLASS(class) ((class)->init? (class)->init() : (class)) -#define GET_CLASS(object) (INIT_CLASS(*(class_ptr *)((object) - sizeof(void*)))) +#define GET_CLASS(object) (INIT_CLASS(*(class_ptr *)((void*)(object) - sizeof(void*)))) #define IFACE_GET(class,iface) (interfaceGet(&((class)->impl),(iface))) #define HAS_PARENT(class) (NULL != ((class)->parent) && INIT_CLASS((class)->parent)) +#define IS_OBJECT(obj) ((GET_CLASS((obj)))->magic == CLASS_MAGIC) +#define INSTANCE_OF(class,obj) ((GET_CLASS((obj))) == _##class) + /** * \todo actually i use gcc feature ## for variadoc... think about * a way to make this standard. diff --git a/src/class/Makefile.am b/src/class/Makefile.am index 0f13153..2b5b0ad 100644 --- a/src/class/Makefile.am +++ b/src/class/Makefile.am @@ -2,5 +2,5 @@ ACLOCAL_AMFLAGS = -I m4 noinst_LIBRARIES = libclass.a -libclass_a_SOURCES = interface.c interface/class.c +libclass_a_SOURCES = interface.c interface/i_class.c libclass_a_CFLAGS = -Wall -I ../../include/ diff --git a/src/class/interface/class.c b/src/class/interface/i_class.c similarity index 100% rename from src/class/interface/class.c rename to src/class/interface/i_class.c diff --git a/src/http/Makefile.am b/src/http/Makefile.am index d6c64b1..e6b2ace 100644 --- a/src/http/Makefile.am +++ b/src/http/Makefile.am @@ -1,5 +1,4 @@ ACLOCAL_AMFLAGS = -I m4 -AUTOMAKE_OPTIONS = subdir-objects MSG = message.c \ message/has_keep_alive.c \ @@ -21,15 +20,15 @@ RESP = response.c \ PARSER = parser.c \ parser/parse.c \ parser/new_message.c \ - parser/header.c \ - parser/body.c \ - parser/request_vars.c \ - parser/post_vars.c + parser/p_header.c \ + parser/p_body.c \ + parser/p_request_vars.c \ + parser/p_post_vars.c WRITER = writer.c \ writer/write.c WORKER = worker.c \ worker/process.c \ - worker/write.c \ + worker/answer.c \ worker/get_asset.c \ worker/add_common_header.c HEADER = header.c \ @@ -38,5 +37,5 @@ HEADER = header.c \ noinst_LIBRARIES = libhttp.a libhttp_a_SOURCES = $(MSG) $(MSGQ) $(REQ) $(RESP) $(PARSER) $(WRITER) \ - $(WORKER) $(HEADER) interface/http_intro.c + $(WORKER) $(HEADER) interface/i_http_intro.c libhttp_a_CFLAGS = -Wall -I ../../include/ diff --git a/src/http/interface/http_intro.c b/src/http/interface/i_http_intro.c similarity index 100% rename from src/http/interface/http_intro.c rename to src/http/interface/i_http_intro.c diff --git a/src/http/parser/body.c b/src/http/parser/p_body.c similarity index 100% rename from src/http/parser/body.c rename to src/http/parser/p_body.c diff --git a/src/http/parser/header.c b/src/http/parser/p_header.c similarity index 100% rename from src/http/parser/header.c rename to src/http/parser/p_header.c diff --git a/src/http/parser/post_vars.c b/src/http/parser/p_post_vars.c similarity index 100% rename from src/http/parser/post_vars.c rename to src/http/parser/p_post_vars.c diff --git a/src/http/parser/request_vars.c b/src/http/parser/p_request_vars.c similarity index 100% rename from src/http/parser/request_vars.c rename to src/http/parser/p_request_vars.c diff --git a/src/http/worker/write.c b/src/http/worker/answer.c similarity index 100% rename from src/http/worker/write.c rename to src/http/worker/answer.c diff --git a/src/logger/Makefile.am b/src/logger/Makefile.am index dc433f1..261a0b9 100644 --- a/src/logger/Makefile.am +++ b/src/logger/Makefile.am @@ -1,7 +1,6 @@ ACLOCAL_AMFLAGS = -I m4 -AUTOMAKE_OPTIONS = subdir-objects noinst_LIBRARIES = liblogger.a -liblogger_a_SOURCES = interface/logger.c logger.c stderr.c syslog.c +liblogger_a_SOURCES = interface/i_logger.c logger.c stderr.c syslog.c liblogger_a_CFLAGS = -Wall -I ../../include/ diff --git a/src/logger/interface/logger.c b/src/logger/interface/i_logger.c similarity index 100% rename from src/logger/interface/logger.c rename to src/logger/interface/i_logger.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 1bdee2a..bb2385f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,17 +1,24 @@ ACLOCAL_AMFLAGS = -I m4 TESTS_ENVIRONMENT = valgrind --error-exitcode=123 --leak-check=full --quiet -TESTS = classTest# loggerTest socketTest serverTest -check_PROGRAMS = classTest# loggerTest socketTest serverTest +TESTS = classTest loggerTest# socketTest serverTest +check_PROGRAMS = classTest loggerTest# socketTest serverTest COMMON = runtest.c CLASS = $(COMMON) \ ../src/class/interface.c \ - ../src/class/interface/class.c \ + ../src/class/interface/i_class.c \ mock/mock_class.c -#LOGGER = $(COMMON) ../src/logger.c ../src/interface/logger.c \ -# ../src/logger/stderr.c ../src/logger/syslog.c +LOGGER = $(COMMON) \ + ../src/class/interface.c \ + ../src/class/interface/i_class.c \ + ../src/logger/logger.c \ + ../src/logger/stderr.c \ + ../src/logger/syslog.c \ + ../src/logger/interface/i_logger.c \ + mock/mock_logger.c + #SOCKET = $(LOGGER) ../src/socket.c ../src/socket/listen.c \ # ../src/socket/accept.c ../src/socket/connect.c #SERVER = $(SOCKET) ../src/server.c ../src/server/run.c \ @@ -21,9 +28,10 @@ classTest_SOURCES = $(CLASS) classTest.c classTest_CFLAGS = -Wall -ggdb -O0 -fprofile-arcs -ftest-coverage -I ../include -I .. -I . classTest_LDFLAGS = -lgcov -#loggerTest_SOURCES = $(LOGGER) loggerTest.c -#loggerTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I . -# +loggerTest_SOURCES = $(LOGGER) loggerTest.c +loggerTest_CFLAGS = -Wall -ggdb -O0 -fprofile-arcs -ftest-coverage -I ../include -I .. -I . +loggerTest_LDFLAGS = -lgcov + #socketTest_SOURCES = $(SOCKET) socketTest.c #socketTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I . # @@ -31,3 +39,5 @@ classTest_LDFLAGS = -lgcov #serverTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I . EXTRA_DIST = runtest.h mock/mock_class.h + +check-build: $(check_PROGRAMS) diff --git a/tests/classTest.c b/tests/classTest.c index a16b757..a9847e8 100644 --- a/tests/classTest.c +++ b/tests/classTest.c @@ -60,7 +60,18 @@ testNew(void) ASSERT_OBJECT_NOT_NULL(mock); ASSERT_EQUAL(1, _called); - ASSERT_EQUAL(123, mockClassGetValue(mock)); + ASSERT_EQUAL(123, mock->value); + + return TEST_OK; +} + +static +int +testNewFail(void) +{ + mock = new(MockClass, 321); + + ASSERT_NULL(mock); return TEST_OK; } @@ -82,9 +93,28 @@ testDelete(void) return TEST_OK; } +static +int +testClone(void) +{ + MockClass clone; + + mock = new(MockClass, 123); + clone = clone(mock); + + ASSERT_INSTANCE_OF(MockClass, clone); + ASSERT_EQUAL(mock->value, clone->value); + + delete(clone); + + return TEST_OK; +} + const testfunc tests[] = { testNew, + testNewFail, testDelete, + testClone }; const size_t count = FUNCS_COUNT(tests); diff --git a/tests/loggerTest b/tests/loggerTest new file mode 100755 index 0000000000000000000000000000000000000000..08e44f29cfdba8aa6a7874be0d45ffac0358fca3 GIT binary patch literal 62970 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 literal 0 HcmV?d00001 diff --git a/tests/loggerTest.c b/tests/loggerTest.c index 2727a47..acf6bff 100644 --- a/tests/loggerTest.c +++ b/tests/loggerTest.c @@ -21,73 +21,94 @@ #include #include "runtest.h" -#include "cclass.h" +#include "class.h" #include "logger.h" +#include "mock/mock_logger.h" -int level = -1; -char * msg = NULL; +const char testname[] = "loggerTest"; +Logger logger = NULL; + -static void -logfnct_mock(int _level, const char * _msg) +static +int +__setUp() { - level = _level; - msg = malloc(strlen(_msg) + 1); - strcpy(msg, _msg); + return TEST_OK; } +int (* const setUp)() = __setUp; -const char testname[] = "loggerTest"; -LOGGER logger = NULL; +static +int +__tearDown() +{ + if (NULL != logger) { + ASSERT_OBJECT(logger); + delete(logger); + } + return TEST_OK; +} +int (* const tearDown)() = __tearDown; static int -__setUp() +testLoggerLevel() { - logger = new(LOGGER, NULL); + logger = new(MockLogger, LOGGER_ERR); - ASSERT_INSTANCE_OF(LOGGER, logger); + ASSERT_INSTANCE_OF(MockLogger, logger); + ASSERT_EQUAL(LOGGER_ERR, logger->min_level); - logger_add(logger, logfnct_mock); + loggerLog(logger, LOGGER_WARNING, "foo %d %s", 123, "bar"); + + ASSERT_STRING_EQUAL("", ((MockLogger)logger)->message); + + loggerLog(logger, LOGGER_ERR, "foo %d %s", 123, "bar"); + ASSERT_STRING_EQUAL("[ERR] foo 123 bar", ((MockLogger)logger)->message); + + mockLoggerCleanMsg((MockLogger)logger); + loggerLog(logger, LOGGER_CRIT, "foo %d %s", 123, "bar"); + ASSERT_STRING_EQUAL("[CRIT] foo 123 bar", ((MockLogger)logger)->message); return TEST_OK; } -int (* const setUp)() = __setUp; static int -__tearDown() +testLoggerStderr() { - level = -1; + logger = new(LoggerStderr, LOGGER_ERR); - if (NULL != msg) { - free(msg); - msg = NULL; - } + freopen("/dev/null", "w", stderr); + loggerLog(logger, LOGGER_ERR, "foo %d %s", 123, "bar"); - if (NULL != logger) { - ASSERT_OBJECT(logger); - delete(&logger); - } + /** + * \todo think about a way to assert something here + */ return TEST_OK; } -int (* const tearDown)() = __tearDown; static int -testLogger() +testLoggerSyslog() { - logger_log(logger, LOGGER_ERR, "foo %d %s", 123, "bar"); + logger = new(LoggerSyslog, LOGGER_ERR); + + loggerLog(logger, LOGGER_ERR, "foo %d %s", 123, "bar"); - ASSERT_EQUAL(LOGGER_ERR, level); - ASSERT_STRING_EQUAL("foo 123 bar", msg); + /** + * \todo think about a way to assert something here + */ return TEST_OK; } const testfunc tests[] = { - testLogger + testLoggerLevel, + testLoggerStderr, + testLoggerSyslog }; const size_t count = FUNCS_COUNT(tests); diff --git a/tests/mock/mock_class.c b/tests/mock/mock_class.c index f603d94..6088e16 100644 --- a/tests/mock/mock_class.c +++ b/tests/mock/mock_class.c @@ -41,6 +41,9 @@ mockCtor(void * _this, va_list * params) _called = 1; this->value = va_arg(* params, int); + if (321 == this->value) + return -1; + return 0; } @@ -52,32 +55,18 @@ mockDtor(void * _this) _called = 1; } -INIT_IFACE(Class, mockCtor, mockDtor, NULL); -CREATE_CLASS(MockClass, NULL, IFACE(Class)); - -/** - * ~~~ method implementations ~~~~~~~~ - */ - -int -mockClassGetValue(MockClass this) -{ - return this->value; -} - +static +inline void -mockClassSetValue(MockClass this, int value) +mockClone(void * _this, void * _base) { - this->value = value; -} + MockClass this = _this; + MockClass base = _base; -/** - * ~~~ helper for mock assertions ~~~~~~~~ - */ -void * -getConstruct() -{ - return mockCtor; + this->value = base->value; } +INIT_IFACE(Class, mockCtor, mockDtor, mockClone); +CREATE_CLASS(MockClass, NULL, IFACE(Class)); + // vim: set et ts=4 sw=4: diff --git a/tests/mock/mock_logger.c b/tests/mock/mock_logger.c new file mode 100644 index 0000000..6423f8c --- /dev/null +++ b/tests/mock/mock_logger.c @@ -0,0 +1,29 @@ +#include + +#include "class.h" +#include "logger.h" +#include "mock/mock_logger.h" + +static +void +logMock(void * _this, logger_level level, const char * const msg) +{ + MockLogger this = _this; + + snprintf(this->message, + MOCK_MESSAGE_MAX - 1, + "[%s] %s", + logger_level_str[level], + msg); +} + +void +mockLoggerCleanMsg(MockLogger this) +{ + this->message[0] = 0; +} + +INIT_IFACE(Logger, logMock); +CREATE_CLASS(MockLogger, Logger, IFACE(Logger)); + +// vim: set ts=4 sw=4: diff --git a/tests/mock/mock_logger.h b/tests/mock/mock_logger.h new file mode 100644 index 0000000..47dbcee --- /dev/null +++ b/tests/mock/mock_logger.h @@ -0,0 +1,20 @@ +#ifndef __MOCK_MOCK_LOGGER_H__ +#define __MOCK_MOCK_LOGGER_H__ + +#define MOCK_MESSAGE_MAX 1024 + +#include "class.h" +#include "logger.h" + +CLASS(MockLogger) +{ + EXTENDS(Logger); + + char message[MOCK_MESSAGE_MAX]; +}; + +void mockLoggerCleanMsg(MockLogger); + +#endif // __MOCK_MOCK_LOGGER_H__ + +// vim: set ts=4 sw=4: diff --git a/tests/runtest.c b/tests/runtest.c index ed85345..450ae19 100644 --- a/tests/runtest.c +++ b/tests/runtest.c @@ -36,20 +36,12 @@ const char results[3] = { TEST_ERROR_CHAR }; -int -isObject(void * object) -{ - class_ptr class = GET_CLASS(object); - - return (class->magic == CLASS_MAGIC); -} - int isObjectNull(void * object) { class_ptr class = GET_CLASS(object); - if (! isObject(object)) { + if (! IS_OBJECT(object)) { return 0; } diff --git a/tests/runtest.h b/tests/runtest.h index 8245172..1b60fd7 100644 --- a/tests/runtest.h +++ b/tests/runtest.h @@ -26,6 +26,7 @@ #include #include +#include "class.h" enum RESULT_TYPES { TEST_OK=0, @@ -94,7 +95,7 @@ enum RESULT_TYPES { return TEST_FAILED; } #define ASSERT_OBJECT(val) \ - if (! isObject((val))) { \ + if (! IS_OBJECT((val))) { \ printf("%s[%d]: Assertion failed that %s IS an object\n", \ __FILE__, __LINE__, #val); \ return TEST_FAILED; } @@ -112,7 +113,7 @@ enum RESULT_TYPES { return TEST_FAILED; } #define ASSERT_INSTANCE_OF(class, val) \ - if (! instanceOf(class, val)) { \ + if (! INSTANCE_OF(class, val)) { \ printf("%s[%d]: Assertion failed that %s is instance of %s\n", \ __FILE__, __LINE__, #val, #class); \ return TEST_FAILED; } @@ -130,7 +131,6 @@ extern int (* const tearDown)(); int isMemNull(void * _mem, size_t size); int isObjectNull(void * _object); -int isObject(void * _object); #endif//__RUNTEST_h__ // vim: set et ts=4 sw=4: