diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/Makefile | 20 | ||||
| -rw-r--r-- | tests/crypt/.gitignore | 1 | ||||
| -rw-r--r-- | tests/crypt/GNUmakefile | 7 | ||||
| -rw-r--r-- | tests/crypt/Makefile | 36 | ||||
| -rw-r--r-- | tests/crypt/README.md | 8 | ||||
| -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 | 209 | ||||
| -rw-r--r-- | tests/eloop-bench/.gitignore | 1 | ||||
| -rw-r--r-- | tests/eloop-bench/Makefile | 45 | ||||
| -rw-r--r-- | tests/eloop-bench/README.md | 53 | ||||
| -rw-r--r-- | tests/eloop-bench/eloop-bench.c | 184 |
12 files changed, 634 insertions, 0 deletions
diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 000000000000..16a229ff47af --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,20 @@ +SUBDIRS= crypt eloop-bench + +all: + for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@ || exit $$?; cd ..; done + +install: + +proginstall: + +clean: + for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@ || exit $$?; cd ..; done + +distclean: clean + rm -f *.diff *.patch *.orig *.rej + for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@ || exit $$?; cd ..; done + +test: + for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@ || exit $$?; cd ..; done + +tests: test diff --git a/tests/crypt/.gitignore b/tests/crypt/.gitignore new file mode 100644 index 000000000000..4390dc850728 --- /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 000000000000..2e838d5e7283 --- /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 000000000000..dd676f4b2aa9 --- /dev/null +++ b/tests/crypt/Makefile @@ -0,0 +1,36 @@ +TOP= ../.. +include ${TOP}/iconfig.mk + +PROG= run-test +SRCS= run-test.c +SRCS+= test_hmac_md5.c + +CFLAGS?= -O2 +CSTD?= c99 +CFLAGS+= -std=${CSTD} + +CPPFLAGS+= -I${TOP} -I${TOP}/src + +PCRYPT_SRCS= ${CRYPT_SRCS:compat/%=${TOP}/compat/%} +OBJS+= ${SRCS:.c=.o} ${PCRYPT_SRCS:.c=.o} + +.c.o: + ${CC} ${CFLAGS} ${CPPFLAGS} -c $< -o $@ + +all: ${PROG} + +clean: + rm -f ${OBJS} ${PROG} ${PROG}.core ${CLEANFILES} + +distclean: clean + rm -f .depend + rm -f *.diff *.patch *.orig *.rej + +.depend: ${SRCS} ${PCRYPT_SRCS} + ${CC} ${CPPFLAGS} -MM ${SRCS} ${PCRYPT_SRCS} + +${PROG}: ${DEPEND} ${OBJS} + ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LDADD} + +test: ${PROG} + ./${PROG} diff --git a/tests/crypt/README.md b/tests/crypt/README.md new file mode 100644 index 000000000000..8269e51fee56 --- /dev/null +++ b/tests/crypt/README.md @@ -0,0 +1,8 @@ +# dhcpcd Test Suite + +Currently this just tests the RFC2202 MD5 implementation in dhcpcd. +This is important, because dhcpcd will either use the system MD5 +implementation if found, otherwise some compat code. + +This test suit ensures that it works in accordance with known standards +on your platform. diff --git a/tests/crypt/run-test.c b/tests/crypt/run-test.c new file mode 100644 index 000000000000..42f52d1fce2d --- /dev/null +++ b/tests/crypt/run-test.c @@ -0,0 +1,38 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2018 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 000000000000..4f716f1220f4 --- /dev/null +++ b/tests/crypt/test.h @@ -0,0 +1,32 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2018 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 000000000000..aed6345d5707 --- /dev/null +++ b/tests/crypt/test_hmac_md5.c @@ -0,0 +1,209 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2018 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 <stdlib.h> +#include <string.h> + +#include "config.h" +#include "test.h" + +#ifdef HAVE_HMAC_H +#include <hmac.h> +#endif + +static void +print_hmac(FILE *stream, const uint8_t *hmac) +{ + int i; + + fprintf(stream, "digest = 0x"); + for (i = 0; i < 16; i++) + fprintf(stream, "%02x", *hmac++); + fprintf(stream, "\n"); +} + +static void +test_hmac(const uint8_t *hmac, const uint8_t *tst) +{ + print_hmac(stdout, hmac); + if (memcmp(hmac, tst, 16) == 0) + return; + fprintf(stderr, "FAILED!\nExpected\t\t\t"); + print_hmac(stderr, tst); + exit(EXIT_FAILURE); +} + +static void +hmac_md5_test1(void) +{ + const uint8_t text[] = "Hi There"; + uint8_t key[16]; + const uint8_t expect[16] = { + 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, + 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d, + }; + uint8_t digest[16]; + int i; + + printf ("HMAC MD5 Test 1:\t\t"); + for (i = 0; i < 16; i++) + key[i] = 0x0b; + hmac("md5", key, 16, text, 8, digest, sizeof(digest)); + test_hmac(digest, expect); +} + +static void +hmac_md5_test2(void) +{ + const uint8_t text[] = "what do ya want for nothing?"; + const uint8_t key[] = "Jefe"; + const uint8_t expect[16] = { + 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, + 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38, + }; + uint8_t digest[16]; + + printf("HMAC MD5 Test 2:\t\t"); + hmac("md5", key, 4, text, 28, digest, sizeof(digest)); + test_hmac(digest, expect); +} + +static void +hmac_md5_test3(void) +{ + const uint8_t expect[16] = { + 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, + 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6, + }; + uint8_t digest[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", key, 16, text, 50, digest, sizeof(digest)); + test_hmac(digest, expect); +} + +static void +hmac_md5_test4(void) +{ + const uint8_t expect[16] = { + 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, + 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79, + }; + uint8_t digest[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", key, 25, text, 50, digest, sizeof(digest)); + test_hmac(digest, expect); +} + +static void +hmac_md5_test5(void) +{ + const uint8_t text[] = "Test With Truncation"; + const uint8_t expect[] = { + 0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, + 0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c, + }; + uint8_t digest[16]; + uint8_t key[16]; + int i; + + printf ("HMAC MD5 Test 5:\t\t"); + for (i = 0; i < 16; i++) + key[i] = 0x0c; + hmac("md5", key, 16, text, 20, digest, sizeof(digest)); + test_hmac(digest, expect); +} + +static void +hmac_md5_test6(void) +{ + const uint8_t text[] = "Test Using Larger Than Block-Size Key - Hash Key First"; + const uint8_t expect[] = { + 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, + 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd, + }; + uint8_t digest[16]; + uint8_t key[80]; + int i; + + printf ("HMAC MD5 Test 6:\t\t"); + for (i = 0; i < 80; i++) + key[i] = 0xaa; + hmac("md5", key, 80, text, 54, digest, sizeof(digest)); + test_hmac(digest, expect); +} + +static void +hmac_md5_test7(void) +{ + const uint8_t text[] = "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"; + const uint8_t expect[] = { + 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, + 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e, + }; + uint8_t digest[16]; + uint8_t key[80]; + int i; + + printf ("HMAC MD5 Test 7:\t\t"); + for (i = 0; i < 80; i++) + key[i] = 0xaa; + hmac("md5", key, 80, text, 73, digest, sizeof(digest)); + test_hmac(digest, expect); +} + +int test_hmac_md5(void) +{ + + printf ("Starting RFC2202 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("\nAll tests pass.\n"); + return 0; +} diff --git a/tests/eloop-bench/.gitignore b/tests/eloop-bench/.gitignore new file mode 100644 index 000000000000..346bbde39b13 --- /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 000000000000..2827c6070422 --- /dev/null +++ b/tests/eloop-bench/Makefile @@ -0,0 +1,45 @@ +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+= -DNO_CONFIG_H +#CPPFLAGS+= -DQUEUE_H=../compat/queue.h +CPPFLAGS+= -I${TOP} -I${TOP}/src + +# Default is to let eloop decide +#CPPFLAGS+= -DHAVE_KQUEUE +#CPPFLAGS+= -DHAVE_POLLTS +#CPPFLAGS+= -DHAVE_PSELECT +#CPPFLAGS+= -DHAVE_EPOLL +#CPPFLAGS+= -DHAVE_PPOLL +CPPFLAGS+= -DWARN_SELECT + +PCOMPAT_SRCS= ${COMPAT_SRCS:compat/%=${TOP}/compat/%} +OBJS+= ${SRCS:.c=.o} ${PCOMPAT_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 + rm -f *.diff *.patch *.orig *.rej + +depend: + +${PROG}: ${DEPEND} ${OBJS} + ${CC} ${LDFLAGS} -o $@ ${OBJS} + +test: ${PROG} + ./${PROG} diff --git a/tests/eloop-bench/README.md b/tests/eloop-bench/README.md new file mode 100644 index 000000000000..6f4a20c7ea81 --- /dev/null +++ b/tests/eloop-bench/README.md @@ -0,0 +1,53 @@ +# 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 mechanisms. It's inspired by libevent/bench. + +eloop needs to be compiled for a specific polling mechanism. +eloop will try and work out which one to use, but you can influence which one +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(7) 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, defalt 100. + * `-r runs` + The number of timed runs to make, default 25. + * `-w writes` + The number of writes to make by the read callback, default 100. diff --git a/tests/eloop-bench/eloop-bench.c b/tests/eloop-bench/eloop-bench.c new file mode 100644 index 000000000000..0f90e824c3ad --- /dev/null +++ b/tests/eloop-bench/eloop-bench.c @@ -0,0 +1,184 @@ +/* + * eloop benchmark + * Copyright (c) 2006-2018 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 <fcntl.h> +#include <stdio.h> +#include <stdlib.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 buf[1]; + + if (read(p->fd[0], buf, 1) != 1) { + warn("%s: read", __func__); + bad++; + } else + good++; + + if (writes != 0) { + writes--; + if (write(p->fd[1], "e", 1) != 1) { + warn("%s: write", __func__); + bad++; + } else + fired++; + } + + if (writes == 0 && fired == good) { + //printf("fired %zu, good %zu, bad %zu\n", fired, good, bad); + eloop_exit(e, good == fired && bad == 0 ? + EXIT_SUCCESS : EXIT_FAILURE); + } +} + +static int +runone(struct timespec *t) +{ + size_t i; + struct pipe *p; + struct timespec ts, te; + int result; + + 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"); + writes--; + fired++; + } + + if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) + err(EXIT_FAILURE, "clock_gettime"); + result = eloop_start(e, NULL); + if (clock_gettime(CLOCK_MONOTONIC, &te) == -1) + err(EXIT_FAILURE, "clock_gettime"); + + timespecsub(&te, &ts, t); + return result; +} + +int +main(int argc, char **argv) +{ + int c, result, exit_code; + size_t i, nruns = 25; + struct pipe *p; + struct timespec ts, te, t; + + while ((c = getopt(argc, argv, "a:n:r: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 (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) + err(EXIT_FAILURE, "clock_gettime"); + + if ((e = eloop_new()) == NULL) + err(EXIT_FAILURE, "eloop_init"); + + if (nactive > npipes) + nactive = npipes; + + pipes = calloc(npipes, sizeof(*p)); + if (pipes == NULL) + err(EXIT_FAILURE, "malloc"); + + for (i = 0, p = pipes; i < npipes; i++, p++) { + if (pipe2(p->fd, O_CLOEXEC | O_NONBLOCK) == -1) + err(EXIT_FAILURE, "pipe"); + if (eloop_event_add(e, p->fd[0], read_cb, p) == -1) + err(EXIT_FAILURE, "eloop_event_add"); + } + + printf("active = %zu, pipes = %zu, runs = %zu, writes = %zu\n", + nactive, npipes, nruns, nwrites); + + exit_code = EXIT_SUCCESS; + for (i = 0; i < nruns; i++) { + result = runone(&t); + if (result != EXIT_SUCCESS) + exit_code = result; + printf("run %zu took %lld.%.9ld seconds, result %d\n", + i + 1, (long long)t.tv_sec, t.tv_nsec, result); + } + + eloop_free(e); + free(pipes); + + if (clock_gettime(CLOCK_MONOTONIC, &te) == -1) + err(EXIT_FAILURE, "clock_gettime"); + timespecsub(&te, &ts, &t); + printf("total %lld.%.9ld seconds, result %d\n", + (long long)t.tv_sec, t.tv_nsec, exit_code); + exit(exit_code); +} |
