diff --git a/Makefile.am b/Makefile.am index b24415c..1129b92 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,6 +16,7 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libite.pc doc_DATA = README.md LICENSE EXTRA_DIST = README.md LICENSE ChangeLog.md +SUBDIRS = tests ## Generate MD5 checksum file MD5 = md5sum diff --git a/configure.ac b/configure.ac index dccd9b0..53d51fc 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ AM_SILENT_RULES([yes]) AC_CONFIG_SRCDIR(lite.h) AM_CONFIG_HEADER(config.h) -AC_CONFIG_FILES([Makefile libite.pc]) +AC_CONFIG_FILES([Makefile tests/Makefile libite.pc]) AC_CONFIG_MACRO_DIR([m4]) AC_PROG_CC diff --git a/pidfilefn.c b/pidfilefn.c index 6300295..bb32b3b 100644 --- a/pidfilefn.c +++ b/pidfilefn.c @@ -21,7 +21,6 @@ #include #include -extern char *__pidfile_name; extern char *chomp(char *str); /** @@ -118,131 +117,6 @@ int pidfile_signal(const char *pidfile, int signal) return 0; } - -/********************************* UNIT TESTS ************************************/ -#ifdef UNITTEST -#include -#include -#include -#include "lite.h" - -extern char *__progname; -static char PIDFILE[42]; -static int verbose = 0; -static struct stat before, after; - -static int test(int result, const char *fmt, ...) -{ - char buf[80]; - size_t len; - va_list ap; - const char success[] = " \e[1m[ OK ]\e[0m\n"; - const char failure[] = " \e[7m[FAIL]\e[0m\n"; - const char dots[] = " ....................................................................."; - - va_start(ap, fmt); - len = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - - write(STDERR_FILENO, buf, len); - write(STDERR_FILENO, dots, 60 - len); /* pad with dots. */ - - if (!result) - write(STDERR_FILENO, success, strlen(success)); - else - write(STDERR_FILENO, failure, strlen(failure)); - - return result; -} - -static inline int timespec_newer(const struct timespec *a, const struct timespec *b) -{ - if (a->tv_sec != b->tv_sec) - return a->tv_sec > b->tv_sec; - - return a->tv_nsec > b->tv_nsec; -} - -char *timespec2str(struct timespec *ts, char *buf, size_t len) -{ - size_t ret, pos; - struct tm t; - - memset(buf, 0, len); - - tzset(); - if (localtime_r(&(ts->tv_sec), &t) == NULL) - return buf; - - ret = strftime(buf, len, "%F %T", &t); - if (ret == 0) - return buf; - len -= ret - 1; - - pos = strlen(buf); - len -= pos; - snprintf(&buf[pos], len, ".%09ld", ts->tv_nsec); - - return buf; -} - -static void sigterm_handler(int UNUSED(signo)) -{ - if (verbose) - printf("Exiting ...\n"); -} - -static void sigalrm_handler(int UNUSED(signo)) -{ - pidfile(NULL); - if (!fexist(PIDFILE)) - err(1, "failed creating %s", PIDFILE); - stat(PIDFILE, &before); -} - -static int mtime() -{ - int ret; - char buf[80]; - - /* Must sleep a while here otherwise we execute too fast => no mtime change :-( */ - usleep(10000); - - if (verbose) - printf("Calling pidfile() again to update mtime ...\n"); - pidfile(NULL); - stat(PIDFILE, &after); - - ret = timespec_newer(&after.st_mtim, &before.st_mtim); - if (verbose) { - printf("Before: %s\n", timespec2str(&before.st_mtim, buf, sizeof(buf))); - printf("After : %s\n", timespec2str(&after.st_mtim, buf, sizeof(buf))); - } - - return !ret; -} - -int main(int argc, char *argv[]) -{ - if (argc > 1 && !strcmp(argv[1], "-v")) - verbose = 1; - - snprintf(PIDFILE, sizeof(PIDFILE), "%s%s.pid", _PATH_VARRUN, __progname); - - signal(SIGTERM, sigterm_handler); - signal(SIGALRM, sigalrm_handler); - alarm(1); - - return test(pidfile_poll(PIDFILE) != getpid(), "Testing pidfile_poll()") - || test(strcmp(__pidfile_name, PIDFILE), "Testing __pidfile_name vs guessed PID filename") - || test(mtime(), "Testing mtime update of followup pidfile() call") - || test(pidfile_signal(PIDFILE, SIGTERM), "Testing signalling ourselves") - ; - - return 0; -} -#endif /* UNITTEST */ - /** * Local Variables: * compile-command: "make V=1 -f pidfilefn.mk" diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..5636549 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,11 @@ +EXTRA_DIST = check.h +CLEANFILES = *~ + +TESTS = +TESTS += pidfile_func + +check_PROGRAMS = $(TESTS) + +# Ignore warnings about unused result, in e.g. write() +CFLAGS = -Wno-unused-result +LDADD = -L../ ../libite.la diff --git a/tests/check.h b/tests/check.h new file mode 100644 index 0000000..b61b625 --- /dev/null +++ b/tests/check.h @@ -0,0 +1,73 @@ +#ifndef LITE_TESTS_CHECK_H_ +#define LITE_TESTS_CHECK_H_ + +#include "../lite.h" + +#define fail_unless(test) \ + do { \ + if (!(test)) { \ + fprintf(stderr, \ + "----------------------------------------------\n" \ + "%s:%d: test FAILED:\nFailed test: %s\n" \ + "----------------------------------------------\n", \ + __FILE__, __LINE__, #test); \ + exit(1); \ + } \ + } while (0) + +static inline int test(int result, const char *fmt, ...) +{ + char buf[80]; + size_t len; + va_list ap; + const char success[] = " \e[1m[ OK ]\e[0m\n"; + const char failure[] = " \e[7m[FAIL]\e[0m\n"; + const char dots[] = " ....................................................................."; + + va_start(ap, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + write(STDERR_FILENO, buf, len); + write(STDERR_FILENO, dots, 60 - len); /* pad with dots. */ + + if (!result) + write(STDERR_FILENO, success, strlen(success)); + else + write(STDERR_FILENO, failure, strlen(failure)); + + return result; +} + +static inline int timespec_newer(const struct timespec *a, const struct timespec *b) +{ + if (a->tv_sec != b->tv_sec) + return a->tv_sec > b->tv_sec; + + return a->tv_nsec > b->tv_nsec; +} + +static inline char *timespec2str(struct timespec *ts, char *buf, size_t len) +{ + size_t ret, pos; + struct tm t; + + memset(buf, 0, len); + + tzset(); + if (localtime_r(&(ts->tv_sec), &t) == NULL) + return buf; + + ret = strftime(buf, len, "%F %T", &t); + if (ret == 0) + return buf; + len -= ret - 1; + + pos = strlen(buf); + len -= pos; + snprintf(&buf[pos], len, ".%09ld", ts->tv_nsec); + + return buf; +} + +#endif /* LITE_TESTS_CHECK_H_ */ diff --git a/tests/pidfile_func.c b/tests/pidfile_func.c new file mode 100644 index 0000000..e13eb1b --- /dev/null +++ b/tests/pidfile_func.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include "check.h" + +extern char *__progname; +extern char *__pidfile_name; +extern char *__pidfile_path; + +static char PIDFILE[42]; +static int verbose = 0; +static struct stat before, after; + +static void sigterm_handler(int UNUSED(signo)) +{ + if (verbose) + printf("Exiting ...\n"); +} + +static void sigalrm_handler(int UNUSED(signo)) +{ + pidfile(NULL); + if (!fexist(PIDFILE)) + err(1, "failed creating %s", PIDFILE); + stat(PIDFILE, &before); +} + +static int mtime() +{ + int ret; + char buf[80]; + + /* Must sleep a while here otherwise we execute too fast => no mtime change :-( */ + usleep(10000); + + if (verbose) + printf("Calling pidfile() again to update mtime ...\n"); + pidfile(NULL); + stat(PIDFILE, &after); + + ret = timespec_newer(&after.st_mtim, &before.st_mtim); + if (verbose) { + printf("Before: %s\n", timespec2str(&before.st_mtim, buf, sizeof(buf))); + printf("After : %s\n", timespec2str(&after.st_mtim, buf, sizeof(buf))); + } + + return !ret; +} + +int main(int argc, char *argv[]) +{ + if (argc > 1 && !strcmp(argv[1], "-v")) + verbose = 1; + + /* Override default _PATH_VARRUN in pidfile() */ + __pidfile_path = _PATH_TMP; + snprintf(PIDFILE, sizeof(PIDFILE), "%s%s.pid", __pidfile_path, __progname); + + signal(SIGTERM, sigterm_handler); + signal(SIGALRM, sigalrm_handler); + alarm(1); + + return test(pidfile_poll(PIDFILE) != getpid(), "Testing pidfile_poll()") + || test(strcmp(__pidfile_name, PIDFILE), "Testing __pidfile_name vs guessed PID filename") + || test(mtime(), "Testing mtime update of followup pidfile() call") + || test(pidfile_signal(PIDFILE, SIGTERM), "Testing signalling ourselves") + ; + + return 0; +} +