]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Move test into tests.
authorRoy Marples <roy@marples.name>
Thu, 13 Apr 2017 13:50:58 +0000 (14:50 +0100)
committerRoy Marples <roy@marples.name>
Thu, 13 Apr 2017 13:50:58 +0000 (14:50 +0100)
Add new test, eloop-bench to benchmark eloop.

12 files changed:
Makefile
tests/Makefile [new file with mode: 0644]
tests/crypt/.gitignore [new file with mode: 0644]
tests/crypt/GNUmakefile [moved from test/GNUmakefile with 100% similarity]
tests/crypt/Makefile [moved from test/Makefile with 86% similarity]
tests/crypt/run-test.c [moved from test/test.c with 100% similarity]
tests/crypt/test.h [moved from test/test.h with 100% similarity]
tests/crypt/test_hmac_md5.c [moved from test/test_hmac_md5.c with 99% similarity]
tests/eloop-bench/.gitignore [new file with mode: 0644]
tests/eloop-bench/Makefile [new file with mode: 0644]
tests/eloop-bench/README.md [new file with mode: 0644]
tests/eloop-bench/eloop-bench.c [new file with mode: 0644]

index 658138f89f62bf5ecbd969c5656cfb4e98b6878e..d90beae2fd9ba6c9def9fc99586d919a5737ee74 100644 (file)
--- 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 (file)
index 0000000..1915c32
--- /dev/null
@@ -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 (file)
index 0000000..4390dc8
--- /dev/null
@@ -0,0 +1 @@
+run-test
similarity index 100%
rename from test/GNUmakefile
rename to tests/crypt/GNUmakefile
similarity index 86%
rename from test/Makefile
rename to tests/crypt/Makefile
index fcd0fd725f7d290291db121a800b5994303598b3..27ae54a8ccf8f76598c7903552e999db03ec10d6 100644 (file)
@@ -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}
similarity index 100%
rename from test/test.c
rename to tests/crypt/run-test.c
similarity index 100%
rename from test/test.h
rename to tests/crypt/test.h
similarity index 99%
rename from test/test_hmac_md5.c
rename to tests/crypt/test_hmac_md5.c
index ddb68750fd3342da20599a7d6415864d588d41e7..7f6152257dfe60127817c39b0077b405fba9c270 100644 (file)
@@ -28,7 +28,7 @@
 #include <stdio.h>
 #include <stdint.h>
 
-#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 (file)
index 0000000..346bbde
--- /dev/null
@@ -0,0 +1 @@
+eloop-bench
diff --git a/tests/eloop-bench/Makefile b/tests/eloop-bench/Makefile
new file mode 100644 (file)
index 0000000..3e302a2
--- /dev/null
@@ -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 (file)
index 0000000..e141045
--- /dev/null
@@ -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 (file)
index 0000000..82207bc
--- /dev/null
@@ -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);
+}