From: Roy Marples Date: Thu, 13 Apr 2017 13:50:58 +0000 (+0100) Subject: Move test into tests. X-Git-Tag: v7.0.0-beta3~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=45d3597364e08f0080cc70192fe5081780288584;p=thirdparty%2Fdhcpcd.git Move test into tests. Add new test, eloop-bench to benchmark eloop. --- diff --git a/Makefile b/Makefile index 658138f8..d90beae2 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ DISTINFOSIGN= ${DISTINFO}.asc CLEANFILES+= *.tar.xz -.PHONY: hooks import import-bsd test +.PHONY: hooks import import-bsd tests .SUFFIXES: .in @@ -26,8 +26,10 @@ all: config.h depend: config.h for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@; cd ..; done -test: - cd $@; ${MAKE} $@; ./$@ +tests: + cd $@; ${MAKE} $@ + +test: tests hooks: cd $@; ${MAKE} @@ -43,7 +45,7 @@ proginstall: clean: rm -rf cov-int - for x in ${SUBDIRS} test; do cd $$x; ${MAKE} $@; cd ..; done + for x in ${SUBDIRS} tests; do cd $$x; ${MAKE} $@; cd ..; done distclean: clean rm -f config.h config.mk config.log \ diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 00000000..1915c32c --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,16 @@ +SUBDIRS= crypt eloop-bench + +all: + for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@; cd ..; done + +install: + +proginstall: + +clean: + for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@; cd ..; done + +test: + for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@; cd ..; done + +tests: test diff --git a/tests/crypt/.gitignore b/tests/crypt/.gitignore new file mode 100644 index 00000000..4390dc85 --- /dev/null +++ b/tests/crypt/.gitignore @@ -0,0 +1 @@ +run-test diff --git a/test/GNUmakefile b/tests/crypt/GNUmakefile similarity index 100% rename from test/GNUmakefile rename to tests/crypt/GNUmakefile diff --git a/test/Makefile b/tests/crypt/Makefile similarity index 86% rename from test/Makefile rename to tests/crypt/Makefile index fcd0fd72..27ae54a8 100644 --- a/test/Makefile +++ b/tests/crypt/Makefile @@ -1,15 +1,15 @@ -TOP?= .. +TOP?= ../.. include ${TOP}/iconfig.mk -PROG= test -SRCS= test.c +PROG= run-test +SRCS= run-test.c SRCS+= test_hmac_md5.c ${TOP}/src/crypt/hmac_md5.c CFLAGS?= -O2 CSTD?= c99 CFLAGS+= -std=${CSTD} -CPPFLAGS+= -I${TOP}/src/crypt +CPPFLAGS+= -I${TOP} -I${TOP}/src T_COMPAT_SRCS= ${COMPAT_SRCS:compat/%=${TOP}/src/compat/%} T_MD5_SRC= ${MD5_SRC:crypt/%=${TOP}/src/crypt/%} @@ -33,3 +33,6 @@ depend: .depend ${PROG}: ${DEPEND} ${OBJS} ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LDADD} + +test: ${PROG} + ./${PROG} diff --git a/test/test.c b/tests/crypt/run-test.c similarity index 100% rename from test/test.c rename to tests/crypt/run-test.c diff --git a/test/test.h b/tests/crypt/test.h similarity index 100% rename from test/test.h rename to tests/crypt/test.h diff --git a/test/test_hmac_md5.c b/tests/crypt/test_hmac_md5.c similarity index 99% rename from test/test_hmac_md5.c rename to tests/crypt/test_hmac_md5.c index ddb68750..7f615225 100644 --- a/test/test_hmac_md5.c +++ b/tests/crypt/test_hmac_md5.c @@ -28,7 +28,7 @@ #include #include -#include "../crypt/crypt.h" +#include "crypt/crypt.h" #include "test.h" /* RFC2202 MD5 implementation */ diff --git a/tests/eloop-bench/.gitignore b/tests/eloop-bench/.gitignore new file mode 100644 index 00000000..346bbde3 --- /dev/null +++ b/tests/eloop-bench/.gitignore @@ -0,0 +1 @@ +eloop-bench diff --git a/tests/eloop-bench/Makefile b/tests/eloop-bench/Makefile new file mode 100644 index 00000000..3e302a20 --- /dev/null +++ b/tests/eloop-bench/Makefile @@ -0,0 +1,40 @@ +TOP?= ../.. +include ${TOP}/iconfig.mk + +PROG= eloop-bench +SRCS= eloop-bench.c +SRCS+= ${TOP}/src/eloop.c + +CFLAGS?= -O2 +CSTD?= c99 +CFLAGS+= -std=${CSTD} + +CPPFLAGS= -I${TOP} -I${TOP}/src -I${TOP}/compat + +# Default is to let eloop decide +#CPPFLAGS+= -DHAVE_KQUEUE +#CPPFLAGS+= -DHAVE_POLLTS +#CPPFLAGS+= -DHAVE_PSELECT +#CPPFLAGS+= -DHAVE_EPOLL +#CPPFLAGS+= -DHAVE_PPOLL + +OBJS+= ${SRCS:.c=.o} + +.c.o: Makefile + ${CC} ${CFLAGS} ${CPPFLAGS} -c $< -o $@ + +all: ${PROG} + +clean: + rm -f ${OBJS} ${PROG} ${PROG}.core ${CLEANFILES} + +distclean: clean + rm -f .depend + +depend: + +${PROG}: ${DEPEND} ${OBJS} + ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LDADD} + +test: ${PROG} + ./${PROG} diff --git a/tests/eloop-bench/README.md b/tests/eloop-bench/README.md new file mode 100644 index 00000000..e141045c --- /dev/null +++ b/tests/eloop-bench/README.md @@ -0,0 +1,57 @@ +# eloop-bench + +eloop is a portable event loop designed to be dropped into the code of a +program. It is not in any library to date. +The basic requirement of eloop is a descriptor polling mechanism which +allows the safe delivery of signals. +As such, select(2) and poll(2) are not suitable. + +This is an eloop benchmark to test the performance of the various +polling functions. It's inspired by libevent/bench. + +eloop needs to be compiled for a specific function, and these can be chosen +by giving one of these CPPFLAGS to the Makefile: + * HAVE_KQUEUE + * HAVE_EPOLL + * HAVE_PSELECT + * HAVE_POLLTS + * HAVE_PPOLL + +kqueue(2) is found on modern BSD kernels. +epoll(2) is found on modern Linux and Solaris kernels. +These two *should* be the best performers. + +pselect(2) *should* be found on any POSIX libc. +This *should* be the worst performer. + +pollts(2) and ppoll(2) are NetBSD and Linux specific variants on poll(2), +but allow safe signal delivery like pselect(2). +Aside from the function name, the arguments and functionality are identical. +They are of little use as both platforms have kqueue(2) and epoll(2), +but there is an edge case where system doesn't have epoll(2) compiled hence +it's inclusion here. + +## using eloop-bench + +The benchmark runs by setting up npipes to read/write to and attaching +an eloop callback for each pipe reader. +Once setup, it will perform a run by writing to nactive pipes. +For each successful pipe read, if nwrites >0 then the reader will reduce +nwrites by one on successful write back to itself. +Once nwrites is 0, the timed run will end once the last write has been read. +At the end of run, the time taken in seconds and nanoseconds is printed. + +The following arguments can influence the benchmark: + + * `-a active` + The number of active pipes. + (default 1) + * `-n pipes` + The number of pipes to create and attach an eloop callback to. + (default (100) + * `-r runs` + The number of timed runs to make. + (default 25) + * `-w writes` + The number of writes to make by the read callbacks. + (default 100) diff --git a/tests/eloop-bench/eloop-bench.c b/tests/eloop-bench/eloop-bench.c new file mode 100644 index 00000000..82207bc5 --- /dev/null +++ b/tests/eloop-bench/eloop-bench.c @@ -0,0 +1,165 @@ +/* + * eloop benchmark + * Copyright (c) 2006-2017 Roy Marples + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include + +#include "eloop.h" + +#ifndef timespecsub +#define timespecsub(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ + if ((vsp)->tv_nsec < 0) { \ + (vsp)->tv_sec--; \ + (vsp)->tv_nsec += 1000000000L; \ + } \ + } while (/* CONSTCOND */ 0) +#endif + +struct pipe { + int fd[2]; +}; + +static size_t good, bad, writes, fired; +static size_t npipes = 100, nwrites = 100, nactive = 1; +static struct pipe *pipes; +static struct eloop *e; + +static void +read_cb(void *arg) +{ + struct pipe *p = arg; + unsigned char c; + ssize_t l; + + l = read(p->fd[0], &c, sizeof(c)); + if (l == -1) + bad++; + else + good += (size_t)l; + if (writes) { + p = (struct pipe *)arg; + l = write(p->fd[1], "e", 1); + if (l != 1) + bad++; + else { + writes -= (size_t)l; + fired += (size_t)l; + } + } + + if (writes == 0) { + if (good == fired) + eloop_exit(e, EXIT_SUCCESS); + } +} + +static struct timespec * +runone(void) +{ + size_t i; + struct pipe *p; + static struct timespec _ts; + struct timespec ts, te; + + writes = nwrites; + fired = good = 0; + + for (i = 0, p = pipes; i < nactive; i++, p++) { + if (write(p->fd[1], "e", 1) != 1) + err(EXIT_FAILURE, "send"); + } + + if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) + err(EXIT_FAILURE, "clock_gettime"); + (void) eloop_start(e, NULL); + if (clock_gettime(CLOCK_MONOTONIC, &te) == -1) + err(EXIT_FAILURE, "clock_gettime"); + + timespecsub(&te, &ts, &_ts); + return &_ts; +} + +int +main(int argc, char **argv) +{ + int c; + size_t i, nruns = 25; + struct pipe *p; + struct timespec *ts; + + if ((e = eloop_new()) == NULL) + err(EXIT_FAILURE, "eloop_init"); + + while ((c = getopt(argc, argv, "a:n:w:")) != -1) { + switch (c) { + case 'a': + nactive = (size_t)atoi(optarg); + break; + case 'n': + npipes = (size_t)atoi(optarg); + break; + case 'r': + nruns = (size_t)atoi(optarg); + break; + case 'w': + nwrites = (size_t)atoi(optarg); + break; + default: + errx(EXIT_FAILURE, "illegal argument `%c'", c); + } + } + + if (nactive > npipes) + nactive = npipes; + + pipes = malloc(sizeof(*p) * npipes); + if (pipes == NULL) + err(EXIT_FAILURE, "malloc"); + + for (i = 0, p = pipes; i < npipes; i++, p++) { + if (pipe(p->fd) == -1) + err(EXIT_FAILURE, "pipe"); + if (eloop_event_add(e, p->fd[0], read_cb, p) == -1) + err(EXIT_FAILURE, "eloop_event_add"); + } + + for (i = 0; i < nruns; i++) { + if ((ts = runone()) == NULL) + err(EXIT_FAILURE, "runone"); + printf("%lld.%.9ld\n", (long long)ts->tv_sec, ts->tv_nsec); + } + + exit(0); +}