summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2017-04-13 14:50:58 +0100
committerRoy Marples <roy@marples.name>2017-04-13 14:50:58 +0100
commitea06be506a7cb14d6efca20b67160197d13948a8 (patch)
treeaf92a000cf18481ec95a37c7e8d02fc6b251419c /tests
parent6231a35b1a1aea14be67795682146c82ccec8ac2 (diff)
downloaddhcpcd-ea06be506a7cb14d6efca20b67160197d13948a8.tar.xz
Move test into tests.
Add new test, eloop-bench to benchmark eloop.
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile16
-rw-r--r--tests/crypt/.gitignore1
-rw-r--r--tests/crypt/GNUmakefile7
-rw-r--r--tests/crypt/Makefile38
-rw-r--r--tests/crypt/run-test.c38
-rw-r--r--tests/crypt/test.h32
-rw-r--r--tests/crypt/test_hmac_md5.c173
-rw-r--r--tests/eloop-bench/.gitignore1
-rw-r--r--tests/eloop-bench/Makefile40
-rw-r--r--tests/eloop-bench/README.md57
-rw-r--r--tests/eloop-bench/eloop-bench.c165
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);
+}