diff options
| author | Roy Marples <roy@marples.name> | 2017-04-13 14:50:58 +0100 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2017-04-13 14:50:58 +0100 |
| commit | ea06be506a7cb14d6efca20b67160197d13948a8 (patch) | |
| tree | af92a000cf18481ec95a37c7e8d02fc6b251419c /tests | |
| parent | 6231a35b1a1aea14be67795682146c82ccec8ac2 (diff) | |
| download | dhcpcd-ea06be506a7cb14d6efca20b67160197d13948a8.tar.xz | |
Move test into tests.
Add new test, eloop-bench to benchmark eloop.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/Makefile | 16 | ||||
| -rw-r--r-- | tests/crypt/.gitignore | 1 | ||||
| -rw-r--r-- | tests/crypt/GNUmakefile | 7 | ||||
| -rw-r--r-- | tests/crypt/Makefile | 38 | ||||
| -rw-r--r-- | tests/crypt/run-test.c | 38 | ||||
| -rw-r--r-- | tests/crypt/test.h | 32 | ||||
| -rw-r--r-- | tests/crypt/test_hmac_md5.c | 173 | ||||
| -rw-r--r-- | tests/eloop-bench/.gitignore | 1 | ||||
| -rw-r--r-- | tests/eloop-bench/Makefile | 40 | ||||
| -rw-r--r-- | tests/eloop-bench/README.md | 57 | ||||
| -rw-r--r-- | tests/eloop-bench/eloop-bench.c | 165 |
11 files changed, 568 insertions, 0 deletions
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/tests/crypt/GNUmakefile b/tests/crypt/GNUmakefile new file mode 100644 index 00000000..2e838d5e --- /dev/null +++ b/tests/crypt/GNUmakefile @@ -0,0 +1,7 @@ +# GNU Make does not automagically include .depend +# Luckily it does read GNUmakefile over Makefile so we can work around it + +include Makefile +ifneq ($(wildcard .depend), ) +include .depend +endif diff --git a/tests/crypt/Makefile b/tests/crypt/Makefile new file mode 100644 index 00000000..27ae54a8 --- /dev/null +++ b/tests/crypt/Makefile @@ -0,0 +1,38 @@ +TOP?= ../.. +include ${TOP}/iconfig.mk + +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} -I${TOP}/src + +T_COMPAT_SRCS= ${COMPAT_SRCS:compat/%=${TOP}/src/compat/%} +T_MD5_SRC= ${MD5_SRC:crypt/%=${TOP}/src/crypt/%} +OBJS+= ${SRCS:.c=.o} ${T_COMPAT_SRCS:.c=.o} ${T_MD5_SRC:.c=.o} + +.c.o: + ${CC} ${CFLAGS} ${CPPFLAGS} -c $< -o $@ + +all: ${PROG} + +clean: + rm -f ${OBJS} ${PROG} ${PROG}.core ${CLEANFILES} + +distclean: clean + rm -f .depend + +.depend: ${SRCS} ${T_COMPAT_SRCS} ${T_CRYPT_SRCS} + ${CC} ${CPPFLAGS} -MM ${SRCS} ${T_COMPAT_SRCS} ${T_CRYPT_SRCS} > .depend + +depend: .depend + +${PROG}: ${DEPEND} ${OBJS} + ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LDADD} + +test: ${PROG} + ./${PROG} diff --git a/tests/crypt/run-test.c b/tests/crypt/run-test.c new file mode 100644 index 00000000..fd8d5b4f --- /dev/null +++ b/tests/crypt/run-test.c @@ -0,0 +1,38 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2014 Roy Marples <roy@marples.name> + * 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 "test.h" + +int main(void) +{ + int r = 0; + + if (test_hmac_md5()) + r = -1; + + return r; +} diff --git a/tests/crypt/test.h b/tests/crypt/test.h new file mode 100644 index 00000000..0ca61823 --- /dev/null +++ b/tests/crypt/test.h @@ -0,0 +1,32 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2014 Roy Marples <roy@marples.name> + * 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. + */ + +#ifndef TEST_H + +int test_hmac_md5(void); + +#endif diff --git a/tests/crypt/test_hmac_md5.c b/tests/crypt/test_hmac_md5.c new file mode 100644 index 00000000..7f615225 --- /dev/null +++ b/tests/crypt/test_hmac_md5.c @@ -0,0 +1,173 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2014 Roy Marples <roy@marples.name> + * 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 <stdio.h> +#include <stdint.h> + +#include "crypt/crypt.h" +#include "test.h" + +/* RFC2202 MD5 implementation */ + +static void +print_hmac(uint8_t *hmac) +{ + int i; + + printf("digest = 0x"); + for (i = 0; i < 16; i++) + printf("%02x", *hmac++); + printf("\n"); +} + +static void +hmac_md5_test1(void) +{ + uint8_t hmac[16]; + const uint8_t text[] = "Hi There"; + uint8_t key[16]; + int i; + + printf ("HMAC MD5 Test 1:\t\t"); + for (i = 0; i < 16; i++) + key[i] = 0x0b; + hmac_md5(text, 8, key, 16, hmac); + print_hmac(hmac); + printf("\t\texpected result:\t 0x9294727a3638bb1c13f48ef8158bfc9d\n"); +} + +static void +hmac_md5_test2(void) +{ + uint8_t hmac[16]; + const uint8_t text[] = "what do ya want for nothing?"; + const uint8_t key[] = "Jefe"; + + printf("HMAC MD5 Test 2:\t\t"); + hmac_md5(text, 28, key, 4, hmac); + print_hmac(hmac); + printf("\t\texpected result:\t 0x750c783e6ab0b503eaa863e10a5db738\n"); +} + +static void +hmac_md5_test3(void) +{ + uint8_t hmac[16]; + uint8_t text[50]; + uint8_t key[16]; + int i; + + printf ("HMAC MD5 Test 3:\t\t"); + for (i = 0; i < 50; i++) + text[i] = 0xdd; + for (i = 0; i < 16; i++) + key[i] = 0xaa; + hmac_md5(text, 50, key, 16, hmac); + print_hmac(hmac); + printf("\t\texpected result:\t 0x56be34521d144c88dbb8c733f0e8b3f6\n"); +} + +static void +hmac_md5_test4(void) +{ + uint8_t hmac[16]; + uint8_t text[50]; + uint8_t key[25]; + uint8_t i; + + printf ("HMAC MD5 Test 4:\t\t"); + for (i = 0; i < 50; i++) + text[i] = 0xcd; + for (i = 0; i < 25; i++) + key[i] = (uint8_t)(i + 1); + hmac_md5(text, 50, key, 25, hmac); + print_hmac(hmac); + printf("\t\texpected result:\t 0x697eaf0aca3a3aea3a75164746ffaa79\n"); +} + +static void +hmac_md5_test5(void) +{ + uint8_t hmac[16]; + const uint8_t text[] = "Test With Truncation"; + uint8_t key[16]; + int i; + + printf ("HMAC MD5 Test 5:\t\t"); + for (i = 0; i < 16; i++) + key[i] = 0x0c; + hmac_md5(text, 20, key, 16, hmac); + print_hmac(hmac); + printf("\t\texpected result:\t 0x56461ef2342edc00f9bab995690efd4c\n"); +} + +static void +hmac_md5_test6(void) +{ + uint8_t hmac[16]; + const uint8_t text[] = "Test Using Larger Than Block-Size Key - Hash Key First"; + uint8_t key[80]; + int i; + + printf ("HMAC MD5 Test 6:\t\t"); + for (i = 0; i < 80; i++) + key[i] = 0xaa; + hmac_md5(text, 54, key, 80, hmac); + print_hmac(hmac); + printf("\t\texpected result:\t 0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd\n"); +} + +static void +hmac_md5_test7(void) +{ + uint8_t hmac[16]; + const uint8_t text[] = "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"; + uint8_t key[80]; + int i; + + printf ("HMAC MD5 Test 7:\t\t"); + for (i = 0; i < 80; i++) + key[i] = 0xaa; + hmac_md5(text, 73, key, 80, hmac); + print_hmac(hmac); + printf("\t\texpected result:\t 0x6f630fad67cda0ee1fb1f562db3aa53e\n"); +} + +int test_hmac_md5(void) +{ + + printf ("Starting HMAC MD5 tests...\n\n"); + hmac_md5_test1(); + hmac_md5_test2(); + hmac_md5_test3(); + hmac_md5_test4(); + hmac_md5_test5(); + hmac_md5_test6(); + hmac_md5_test7(); + printf("\nConfirm above results visually against RFC 2202.\n"); + return 0; +} 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 <roy@marples.name> + * 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 <sys/resource.h> + +#include <err.h> +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <unistd.h> + +#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); +} |
