--- /dev/null
+Rich Felker
+Szabolcs Nagy
+Kirill Ternovsky
--- /dev/null
+libc-test is licensed under the following standard MIT license:
+
+Copyright © 2005-2013 libc-test AUTHORS
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Portions of this software is derived from software authored by
+third parties:
+
+math tests use numbers under BSD and GPL licenses see src/math/ucb/*
+and src/math/crlibm/* for details
-DIRS = $(sort $(wildcard src/*))
+SRCS:=$(sort $(wildcard src/*/*.c))
+OBJS:=$(SRCS:%.c=%.o)
+DIRS:=$(sort $(wildcard src/*))
+NAMES:=$(OBJS:.o=)
+SPEC_PATTERNS:=src/common/% src/api/% src/math/%
+CFLAGS:=-Isrc/common
+LDLIBS:=src/common/libtest.a
+
+-include config.mak
all:
- for i in $(DIRS); do printf "%-20s\n" $$i; make -s -C $$i; done
-run:
- for i in $(DIRS); do printf "%-20s" $$i; make -s -C $$i run; done
+%.mk:
+
+define template
+$(1).BINS := $(1) $(1)-static
+D:=$$(dir $(1))
+N:=$(1)
+-include $(1).mk
+$(1) $(1)-static: $$($(1).OBJS)
+$(1).so: $$($(1).LOBJS)
+endef
+
+$(foreach n,$(filter-out $(SPEC_PATTERNS),$(NAMES)),$(eval $(call template,$(n))))
+
+MBINS:=$(filter src/math/%,$(NAMES))
+BINS:=$(foreach n,$(NAMES),$($(n).BINS)) src/api/main $(MBINS)
+LIBS:=$(foreach n,$(NAMES),$($(n).LIBS)) src/common/libtest.a
+ERRS:=$(BINS:%=%.err)
+
+define target_template
+$(1)/all: $(1)/REPORT
+$(1)/clean:
+ rm -f $$(filter $(1)/%,$$(OBJS) $$(BINS) $$(LIBS)) $(1)/*.err
+$(1)/REPORT: $$(filter $(1)/%,$$(ERRS))
+ cat $(1)/*.err >$$@
+REPORT: $(1)/REPORT
+.PHONY: $(1)/all $(1)/clean
+endef
+
+$(foreach d,$(DIRS),$(eval $(call target_template,$(d))))
+
+all:REPORT
clean:
- for i in $(DIRS); do make -s -C $$i clean; done
+ rm -f $(OBJS) $(BINS) $(LIBS) src/*/*.err
+cleanall: clean
+ rm -f REPORT src/*/REPORT
+REPORT:
+ cat $^ |tee $@
+
+src/common/libtest.a: $(filter src/common/%,$(OBJS))
+ rm -f $@
+ $(AR) rc $@ $^
+ $(RANLIB) $@
+
+$(BINS): src/common/libtest.a
+$(OBJS): src/common/test.h
+
+src/common/mtest.o: src/common/mtest.h
+$(MBINS:%=%.o): src/common/mtest.h
+
+IOBJS:=$(filter src/api/%,$(OBJS))
+src/api/main: $(IOBJS)
+src/api/main.OBJS:=$(IOBJS)
+$(IOBJS):CFLAGS+=-pedantic-errors -Werror -Wno-unused -D_XOPEN_SOURCE=700
+$(IOBJS):CFLAGS+=-DX_PS -DX_TPS -DX_SS
+
+%.o: %.c
+ $(CC) $(CFLAGS) $($*.CFLAGS) -c -o $@ $< 2>$@.err || echo BUILDERROR $@
+%.s: %.c
+ $(CC) $(CFLAGS) $($*.CFLAGS) -S -o $@ $< || echo BUILDERROR $@
+%.lo: %.c
+ $(CC) $(CFLAGS) $($*.CFLAGS) -fPIC -DSHARED -c -o $@ $< 2>$@.err || echo BUILDERROR $@
+%.so: %.lo
+ $(CC) -shared $(LDFLAGS) $($@.LDFLAGS) -o $@ $< $($*.LOBJS) $(LDLIBS) $($@.LDLIBS) 2>$@.err || echo BUILDERROR $@
+%-static: %.o
+ $(CC) -static $(LDFLAGS) $($@.LDFLAGS) -o $@ $< $($*.OBJS) $(LDLIBS) $($@.LDLIBS) 2>$@.err || echo BUILDERROR $@
+%: %.o
+ $(CC) $(LDFLAGS) $($@.LDFLAGS) -o $@ $< $($@.OBJS) $(LDLIBS) $($@.LDLIBS) 2>$@.err || echo BUILDERROR $@
+
+%.o.err: %.o
+ touch $@
+%.lo.err: %.lo
+ touch $@
+%.so.err: %.so
+ touch $@
+%.err: %
+# TODO: proper wrapping that records exit status
+ ./$< 2>/dev/null >$@ || true
+
+.PHONY: all clean cleanall
+
-libc tests based on libc-testsuit by Rich Felker
-see http://git.musl-libc.org/cgit
+libc-test is developed as part of the musl project
+http://www.musl-libc.org/
-configure tests:
- cp dist/config.mak .
- # edit config.mak
-build tests:
+configuring:
+ edit config.mak
+build and run tests:
make
-run tests:
- make run
+clean up:
+ make clean
+
+make builds all test binaries and runs them to create
+a REPORT file that contains all build and runtime errors
+(this means that make does not stop at build failures)
+
+contributing tests:
design goals:
-- tests should be easy to run even a single test in isolation
+- tests should be easy to run and build even a single test in isolation
(so test should be self contained if possible)
- failure of one test should not interfere with others
(build failure, crash or unexpected results are all failures)
-- test output should point to the cause of failure
+- test output should point to the cause of the failure
- test results should be robust
- the test system should have minimal dependency
(libc, posix sh, gnu make)
- the test system should run on all archs and libcs
- tests should leave the system in a clean state
-framework:
+conventions:
+
+each test is in a separate file at a path like src/directory/file.c with
+its own main
+
+the test should return 0 on success and non-0 on failure, on failure it
+should print error messages to standard out if possible, on success no
+message should be printed
+
+to help with the above test protocol use t_error function for printing
+errors and return t_status from main, see src/common/test.h
+(t_error allows standard printf formatting, outputs at most 512bytes
+in a single write call to fd 1, so there is no buffering, long outputs
+are truncated, it sets the global t_status to 1)
+
+it is common to do many similar checks in a test, in such cases macros
+may be used to simplify the code like
+#define T1(a,b) (check(a,b) || (t_error("check(%s,%s) failed\n", a, b),0))
+#define T2(f,w) (result=(f), result==(w) || (t_error("%s failed: got %s, want %s\n", #f, result, w),0))
+
+directories:
+
+src/api: interface tests, build time include header tests
+src/common: common utilities compiled into libtest.a
+src/functional: functional tests aiming for large coverage of libc
+src/math: tests for each math function with input-output test vectors
+src/regression: regression tests aiming for testing particular bugs
-the convention is that each test is in a separate file
-at a path like src/directory/file.c with its own main
+initial set of functional tests are derived from the libc-testsuit of
+Rich Felker, regression tests should contain reference of the bug
+(musl commit hash, glibc bug tracker url, etc)
-the test should return 0 on success and non-0 on failure
-error messages relevant to the test system should be
-printed to standard out (fd 1)
+build system:
-src/functional/test.h usage:
+the targets src/directory/all and src/directory/clean build and clean
+only the specified directory, each directory has its own Makefile that
+invokes the top level make with src/directory/foo for the foo target,
+so it is possible to work only under a specific test directory
-use error in tests when possible instead of printf
-(error truncates the formatted string to 512 bytes and uses a
-single write call to output it to fd 1, terminating the error
-string with a \n is the responsibility of the caller)
-and return test_status from main (set by error, 0 by default)
+the build and runtime errors of each target are accumulated into a
+target.err file and in the end they are concatenated into a REPORT
-when many similar checks are done, helper macros can be used like
-#define T1(a,b) (check(a,b) || (error("check(%s,%s) failed\n", a, b),0))
-#define T2(f,w) (result=(f), result==(w) || (error("%s failed: got %s, want %s\n", #f, result, w),0))
+each .c file in src/functional and src/regression are built into a
+dynamic linked and a static linked executable test binary by default,
+this behaviour can be changed by a similarly named .mk file changing
+make variables and specifying additional rules:
-a simple example:
+$(N) is the name of the binary target (the file name without the .c)
+$(N)-static is the name of the static binary target
+$(D) is the directory
+$(N).CFLAGS are added to the CFLAGS at compilation
+$(N).LDFLAGS are added to the LDFLAGS at linking
+$(N).LDLIBS are added to the LDLIBS at linking
+$(N).BINS are the targets (if empty no binaries are built)
+$(N).LIBS are the non-executable targets (shared objects may use it)
-#include "test.h"
-#define T(c,...) ((c) || (error(#c " failed: " __VA_ARGS__),0))
-int main(void)
-{
- T('a'+1=='b', "'a'==%d 'b'==%d\n", 'a', 'b');
- T(-5%3==-2, "bad mod semantics\n");
- return test_status;
-}
+if a binary is linked together from several .o files then they
+have to be specified as prerequisits for the binary targets and
+added to the $(N).LDLIBS as well
+if a binary depends on a file at runtime (eg. a .so opened by dlopen)
+then the $(N).err target should depend on that file
--- /dev/null
+CFLAGS += -pipe -std=c99 -D_POSIX_C_SOURCE=200809L -Wall -Wno-unused-function -Wno-missing-braces
+CFLAGS += -Wno-unknown-pragmas -fno-builtin -frounding-math
+CFLAGS += -g
+LDFLAGS += -g
+LDLIBS += -lpthread -lm -lrt
+
+# glibc specific settings
+CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+LDLIBS += -lcrypt -ldl -lresolv -lutil
+
+AR = $(CROSS_COMPILE)ar
+RANLIB = $(CROSS_COMPILE)ranlib
+
+++ /dev/null
-# copy to ../config.mak
-
-# to test the native libc with native cc no config is required
-
-# to test non-native musl with gcc use
-#CC = musl-gcc
-
-# to test non-native musl with installed pcc use
-#prefix = /path/to/musl
-#includedir = $(prefix)/include
-#libdir = $(prefix)/lib
-#CC = pcc
-#LIBCC = $(shell pcc -v /dev/null 2>&1 |sed -n 's,/crtbegin.o.*,,;s,.* /,/,p')
-#CFLAGS += -nostdinc -ffreestanding -fno-stack-protector -isystem $(includedir)
-#LDFLAGS += -nostdlib -Wl,-e,_start,-Bstatic $(libdir)/crti.o $(libdir)/crt1.o $(libdir)/crtn.o -L$(libdir) -lc -L$(LIBCC) -l$(CC)
-CFLAGS+=-std=c99 -pedantic-errors -Wall -Werror -Wno-unused -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700
-CFLAGS+=-DX_PS -DX_TPS -DX_SS
-#CFLAGS+=-DX_RPP_TPP -DX_TYM -DX_FMTMSG -DX_NDBM
-LDFLAGS+=-lcrypt -ldl -lm -lpthread -lrt
+all:
+%:
+ $(MAKE) -C ../.. src/api/$@
-SRC=$(sort $(wildcard *.c))
-ERR=$(SRC:.c=.err)
-
--include ../../config.mak
-
-all: all.err
-
-run: all.err
- cat $<
-
-all.err: $(ERR)
- LC_ALL=C $(CC) $(LDFLAGS) -o main *.o 2>main.err || true
- cat $(ERR) |\
- grep -v 'In function .f.' |\
- grep -v 'Each undeclared identifier is reported only once' |\
- grep -v 'for each function it appears in' >$@ || true
-
-%.err: %.c
- LC_ALL=C $(CC) $(CFLAGS) -c $< 2>$@ || true
-
-clean:
- rm -f main *.o *.err
--- /dev/null
+all:
+%:
+ $(MAKE) -C ../.. src/common/$@
+
--- /dev/null
+#include <unistd.h>
+#include "test.h"
+
+void t_fdfill(void)
+{
+ int fd[2];
+ while (pipe(fd) == 0);
+ dup(0);
+}
--- /dev/null
+#include <stdio.h>
+#include <stdint.h>
+#include "mtest.h"
+
+int eulpf(float x)
+{
+ union { float f; uint32_t i; } u = { x };
+ int e = u.i>>23 & 0xff;
+
+ if (!e)
+ e++;
+ return e - 0x7f - 23;
+}
+
+int eulp(double x)
+{
+ union { double f; uint64_t i; } u = { x };
+ int e = u.i>>52 & 0x7ff;
+
+ if (!e)
+ e++;
+ return e - 0x3ff - 52;
+}
+
+int eulpl(long double x)
+{
+#if LDBL_MANT_DIG == 53
+ return eulp(x);
+#elif LDBL_MANT_DIG == 64
+ union { long double f; struct {uint64_t m; uint16_t e; uint16_t pad;} i; } u = { x };
+ int e = u.i.e & 0x7fff;
+
+ if (!e)
+ e++;
+ return e - 0x3fff - 63;
+#else
+ // TODO
+ return 0;
+#endif
+}
+
+float ulperrf(float got, float want, float dwant)
+{
+ if (isnan(got) && isnan(want))
+ return 0;
+ if (got == want) {
+ if (signbit(got) == signbit(want))
+ return dwant;
+ return inf;
+ }
+ if (isinf(got)) {
+ got = copysignf(0x1p127, got);
+ want *= 0.5;
+ }
+ return scalbn(got - want, -eulpf(want)) + dwant;
+}
+
+float ulperr(double got, double want, float dwant)
+{
+ if (isnan(got) && isnan(want))
+ return 0;
+ if (got == want) {
+ if (signbit(got) == signbit(want))
+ return dwant;
+ return inf; // treat 0 sign errors badly
+ }
+ if (isinf(got)) {
+ got = copysign(0x1p1023, got);
+ want *= 0.5;
+ }
+ return scalbn(got - want, -eulp(want)) + dwant;
+}
+
+float ulperrl(long double got, long double want, float dwant)
+{
+#if LDBL_MANT_DIG == 53
+ return ulperr(got, want, dwant);
+#elif LDBL_MANT_DIG == 64
+ if (isnan(got) && isnan(want))
+ return 0;
+ if (got == want) {
+ if (signbit(got) == signbit(want))
+ return dwant;
+ return inf;
+ }
+ if (isinf(got)) {
+ got = copysignl(0x1p16383L, got);
+ want *= 0.5;
+ }
+ return scalbnl(got - want, -eulpl(want)) + dwant;
+#else
+ // TODO
+ return inf;
+#endif
+}
+
+#define length(a) (sizeof(a)/sizeof*(a))
+#define flag(x) {x, #x}
+static struct {
+ int flag;
+ char *s;
+} eflags[] = {
+ flag(INEXACT),
+ flag(INVALID),
+ flag(DIVBYZERO),
+ flag(UNDERFLOW),
+ flag(OVERFLOW)
+};
+
+char *estr(int f)
+{
+ static char buf[256];
+ char *p = buf;
+ int i, all = 0;
+
+ for (i = 0; i < length(eflags); i++)
+ if (f & eflags[i].flag) {
+ p += sprintf(p, "%s%s", all ? "|" : "", eflags[i].s);
+ all |= eflags[i].flag;
+ }
+ if (all != f) {
+ p += sprintf(p, "%s%d", all ? "|" : "", f & ~all);
+ all = f;
+ }
+ p += sprintf(p, "%s", all ? "" : "0");
+ return buf;
+}
+
+char *rstr(int r)
+{
+ switch (r) {
+ case RN: return "RN";
+#ifdef FE_TOWARDZERO
+ case RZ: return "RZ";
+#endif
+#ifdef FE_UPWARD
+ case RU: return "RU";
+#endif
+#ifdef FE_DOWNWARD
+ case RD: return "RD";
+#endif
+ }
+ return "R?";
+}
--- /dev/null
+#include <fenv.h>
+#include <float.h>
+#include <math.h>
+
+#undef RN
+#undef RZ
+#undef RD
+#undef RU
+#ifdef FE_TONEAREST
+#define RN FE_TONEAREST
+#else
+#define RN 0
+#endif
+#ifdef FE_TOWARDZERO
+#define RZ FE_TOWARDZERO
+#else
+#define RZ -1
+#endif
+#ifdef FE_DOWNWARD
+#define RD FE_DOWNWARD
+#else
+#define RD -1
+#endif
+#ifdef FE_UPWARD
+#define RU FE_UPWARD
+#else
+#define RU -1
+#endif
+
+#undef INEXACT
+#undef INVALID
+#undef DIVBYZERO
+#undef UNDERFLOW
+#undef OVERFLOW
+#ifdef FE_INEXACT
+#define INEXACT FE_INEXACT
+#else
+#define INEXACT 0
+#endif
+#ifdef FE_INVALID
+#define INVALID FE_INVALID
+#else
+#define INVALID 0
+#endif
+#ifdef FE_DIVBYZERO
+#define DIVBYZERO FE_DIVBYZERO
+#else
+#define DIVBYZERO 0
+#endif
+#ifdef FE_UNDERFLOW
+#define UNDERFLOW FE_UNDERFLOW
+#else
+#define UNDERFLOW 0
+#endif
+#ifdef FE_OVERFLOW
+#define OVERFLOW FE_OVERFLOW
+#else
+#define OVERFLOW 0
+#endif
+
+#undef inf
+#undef nan
+#define inf INFINITY
+#define nan NAN
+
+#define T(...) {__FILE__, __LINE__, __VA_ARGS__},
+
+#define POS char *file; int line;
+struct d_d {POS int r; double x; double y; float dy; int e; };
+struct f_f {POS int r; float x; float y; float dy; int e; };
+struct l_l {POS int r; long double x; long double y; float dy; int e; };
+struct ff_f {POS int r; float x; float x2; float y; float dy; int e; };
+struct dd_d {POS int r; double x; double x2; double y; float dy; int e; };
+struct ll_l {POS int r; long double x; long double x2; long double y; float dy; int e; };
+struct d_di {POS int r; double x; double y; float dy; long long i; int e; };
+struct f_fi {POS int r; float x; float y; float dy; long long i; int e; };
+struct l_li {POS int r; long double x; long double y; float dy; long long i; int e; };
+struct di_d {POS int r; double x; long long i; double y; float dy; int e; };
+struct fi_f {POS int r; float x; long long i; float y; float dy; int e; };
+struct li_l {POS int r; long double x; long long i; long double y; float dy; int e; };
+struct d_i {POS int r; double x; long long i; int e; };
+struct f_i {POS int r; float x; long long i; int e; };
+struct l_i {POS int r; long double x; long long i; int e; };
+struct d_dd {POS int r; double x; double y; float dy; double y2; float dy2; int e; };
+struct f_ff {POS int r; float x; float y; float dy; float y2; float dy2; int e; };
+struct l_ll {POS int r; long double x; long double y; float dy; long double y2; float dy2; int e; };
+struct ff_fi {POS int r; float x; float x2; float y; float dy; long long i; int e; };
+struct dd_di {POS int r; double x; double x2; double y; float dy; long long i; int e; };
+struct ll_li {POS int r; long double x; long double x2; long double y; float dy; long long i; int e; };
+struct fff_f {POS int r; float x; float x2; float x3; float y; float dy; int e; };
+struct ddd_d {POS int r; double x; double x2; double x3; double y; float dy; int e; };
+struct lll_l {POS int r; long double x; long double x2; long double x3; long double y; float dy; int e; };
+#undef POS
+
+char *estr(int);
+char *rstr(int);
+
+float ulperr(double got, double want, float dwant);
+float ulperrf(float got, float want, float dwant);
+float ulperrl(long double got, long double want, float dwant);
+
+static int checkexcept(int got, int want, int r)
+{
+ if (r == RN)
+ return got == want || got == (want|INEXACT);
+ return (got|INEXACT|UNDERFLOW) == (want|INEXACT|UNDERFLOW);
+}
+
+static int checkulp(float d, int r)
+{
+ // TODO: we only care about >=1.5 ulp errors for now, should be 1.0
+ if (r == RN)
+ return fabsf(d) < 1.5;
+ return 1;
+}
+
+static int checkcr(long double y, long double ywant, int r)
+{
+ if (isnan(ywant))
+ return isnan(y);
+ return y == ywant && signbit(y) == signbit(ywant);
+}
+
--- /dev/null
+#include <string.h>
+#include "test.h"
+
+/* relative path to p */
+char *t_pathrel(char *buf, size_t n, char *argv0, char *p)
+{
+ char *s = strrchr(argv0, '/');
+ int k;
+
+ if (s)
+ k = snprintf(buf, n, "%.*s/%s", (int)(s-argv0), argv0, p);
+ else
+ k = snprintf(buf, n, "./%s", p);
+ if ((size_t)k >= n)
+ return 0;
+ return buf;
+}
--- /dev/null
+#include <float.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+// TODO: use large period prng
+static uint64_t seed = -1;
+static uint32_t rand32(void)
+{
+ seed = 6364136223846793005ULL*seed + 1;
+ return seed >> 32;
+}
+static uint64_t rand64(void)
+{
+ uint64_t u = rand32();
+ return u<<32 | rand32();
+}
+static double frand()
+{
+ return rand64() * 0x1p-64;
+}
+static float frandf()
+{
+ return rand32() * 0x1p-32f;
+}
+static long double frandl()
+{
+ return rand64() * 0x1p-64L
+#if LDBL_MANT_DIG > 64
++ rand64() * 0x1p-128L
+#endif
+;
+}
+
+void t_randseed(uint64_t s)
+{
+ seed = s;
+}
+
+/* uniform random in [0,n), n > 0 must hold */
+uint64_t t_randn(uint64_t n)
+{
+ uint64_t r, m;
+
+ /* m is the largest multiple of n */
+ m = -1;
+ m -= m%n;
+ while ((r = rand64()) >= m);
+ return r%n;
+}
+
+/* uniform on [a,b], a <= b must hold */
+uint64_t t_randint(uint64_t a, uint64_t b)
+{
+ uint64_t n = b - a + 1;
+ if (n)
+ return a + t_randn(n);
+ return rand64();
+}
+
+/* shuffle the elements of p and q until the elements in p are well shuffled */
+static void shuffle2(uint64_t *p, uint64_t *q, size_t np, size_t nq)
+{
+ size_t r;
+ uint64_t t;
+
+ while (np) {
+ r = t_randn(nq+np--);
+ t = p[np];
+ if (r < nq) {
+ p[np] = q[r];
+ q[r] = t;
+ } else {
+ p[np] = p[r-nq];
+ p[r-nq] = t;
+ }
+ }
+}
+
+/* shuffle the elements of p */
+void t_shuffle(uint64_t *p, size_t n)
+{
+ shuffle2(p,0,n,0);
+}
+
+void t_randrange(uint64_t *p, size_t n)
+{
+ size_t i;
+ for (i = 0; i < n; i++)
+ p[i] = i;
+ t_shuffle(p, n);
+}
+
+/* hash table insert, 0 means empty, v > 0 must hold, len is power-of-2 */
+static int insert(uint64_t *tab, size_t len, uint64_t v)
+{
+ size_t i = v & (len-1);
+ size_t j = 1;
+
+ while (tab[i]) {
+ if (tab[i] == v)
+ return -1;
+ i += j++;
+ i &= len-1;
+ }
+ tab[i] = v;
+ return 0;
+}
+
+/* choose k unique numbers from [0,n), k <= n */
+int t_choose(uint64_t n, size_t k, uint64_t *p)
+{
+ uint64_t *tab;
+ size_t i, j, len;
+
+ if (n < k)
+ return -1;
+
+ if (n < 16) {
+ /* no alloc */
+ while (k)
+ if (t_randn(n--) < k)
+ p[--k] = n;
+ return 0;
+ }
+
+ if (k < 8) {
+ /* no alloc, n > 15 > 2*k */
+ for (i = 0; i < k;) {
+ p[i] = t_randn(n);
+ for (j = 0; p[j] != p[i]; j++);
+ if (j == i)
+ i++;
+ }
+ return 0;
+ }
+
+ // TODO: if k < n/k use k*log(k) solution without alloc
+
+ if (n < 5*k && (n-k)*sizeof *tab < (size_t)-1) {
+ /* allocation is n-k < 4*k */
+ tab = malloc((n-k) * sizeof *tab);
+ if (!tab)
+ return -1;
+ for (i = 0; i < k; i++)
+ p[i] = i;
+ for (; i < n; i++)
+ tab[i-k] = i;
+ if (k < n-k)
+ shuffle2(p, tab, k, n-k);
+ else
+ shuffle2(tab, p, n-k, k);
+ free(tab);
+ return 0;
+ }
+
+ /* allocation is 2*k <= len < 4*k */
+ for (len = 16; len < 2*k; len *= 2);
+ tab = calloc(len, sizeof *tab);
+ if (!tab)
+ return -1;
+ for (i = 0; i < k; i++)
+ while (insert(tab, len, t_randn(n)+1));
+ for (i = 0; i < len; i++)
+ if (tab[i])
+ *p++ = tab[i]-1;
+ free(tab);
+ return 0;
+}
+
--- /dev/null
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+/* TODO: not thread-safe nor fork-safe */
+static volatile int t_status;
+
+#define T_LOC2(l) __FILE__ ":" #l
+#define T_LOC1(l) T_LOC2(l)
+#define t_error(...) t_printf("ERROR " T_LOC1(__LINE__) ": " __VA_ARGS__)
+
+static int t_printf(const char *s, ...)
+{
+ va_list ap;
+ char buf[512];
+ int n;
+
+ t_status = 1;
+ va_start(ap, s);
+ n = vsnprintf(buf, sizeof buf, s, ap);
+ va_end(ap);
+ if (n < 0)
+ n = 0;
+ else if (n >= sizeof buf) {
+ n = sizeof buf;
+ buf[n - 1] = '\n';
+ buf[n - 2] = '.';
+ buf[n - 3] = '.';
+ buf[n - 4] = '.';
+ }
+ return write(1, buf, n);
+}
+
+int t_vmfill(void **, size_t *, int);
+
+void t_fdfill(void);
+
+void t_randseed(uint64_t s);
+uint64_t t_randn(uint64_t n);
+uint64_t t_randint(uint64_t a, uint64_t b);
+void t_shuffle(uint64_t *p, size_t n);
+void t_randrange(uint64_t *p, size_t n);
+int t_choose(uint64_t n, size_t k, uint64_t *p);
+
+char *t_pathrel(char *buf, size_t n, char *argv0, char *p);
+
--- /dev/null
+#include <stdint.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "test.h"
+#ifndef PAGE_SIZE
+ #define PAGE_SIZE sysconf(_SC_PAGE_SIZE)
+#endif
+
+/* max mmap size, *start is the largest power-of-2 size considered */
+static size_t mmax(int fd, size_t *start)
+{
+ size_t i, n;
+ void *p;
+
+ for (i=n=*start; i>=PAGE_SIZE; i/=2) {
+ if ((p=mmap(0, n, PROT_NONE, MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
+ n -= i/2;
+ } else {
+ munmap(p, n);
+ if (n == i)
+ *start = n;
+ n += i/2;
+ }
+ }
+ return n & -PAGE_SIZE;
+}
+
+/*
+fills the virtual memory with anonymous PROT_NONE mmaps,
+returns the mappings in *p and *n in decreasing size order,
+the return value is the number of mappings or -1 on failure.
+*/
+int t_vmfill(void **p, size_t *n, int len)
+{
+ int fd = open("/dev/zero", O_RDWR);
+ size_t start = SIZE_MAX/2 + 1;
+ size_t m;
+ void *q;
+ int i;
+
+ for (i=0;;i++) {
+ m = mmax(fd, &start);
+ if (!m)
+ break;
+ q = mmap(0, m, PROT_NONE, MAP_PRIVATE, fd, 0);
+ if (q == MAP_FAILED)
+ return -1;
+ if (i < len) {
+ p[i] = q;
+ n[i] = m;
+ }
+ }
+ return i;
+}
-CFLAGS+=-pipe -std=c99 -D_POSIX_C_SOURCE=200809L -Wall -Wno-unused-function -Wno-missing-braces
-LDFLAGS+=
-LDLIBS+=
-BUILD?=.
-
-SRC=$(sort $(wildcard *.c))
-OBJ=$(SRC:%.c=$(BUILD)/%.o)
-DSOOBJ=$(filter %_dso.o,$(OBJ))
-BINOBJ=$(filter-out %_dso.o,$(OBJ))
-NO_DL_OBJ=$(filter-out %dlopen.o,$(BINOBJ))
-DSO=$(DSOOBJ:.o=.so)
-BIN=$(BINOBJ:.o=)
-BIN_STATIC=$(NO_DL_OBJ:.o=-static)
-ALL=$(BIN) $(BIN_STATIC) $(DSO)
-
--include ../../config.mak
-
-all: $(ALL)
-run: all
- @N=0; A=0; for i in $(BIN) $(BIN_STATIC);do \
- A=$$((A+1)); ./$$i || { N=$$((N+1)); echo FAIL $$i; } \
- done; \
- [ "$$N" = 0 ] && echo PASS || echo FAILS: $$N/$$A
-clean:
- rm -f $(OBJ) $(ALL)
-
-$(BUILD):
- mkdir -p $@
-$(OBJ): test.h | $(BUILD)
-$(DSOOBJ): CFLAGS+=-fPIC
-$(BUILD)/%.o: %.c
- $(CC) $(CFLAGS) -c -o $@ $< || echo BUILDERROR $@
-%.so: %.o
- $(CC) -shared $(LDFLAGS) -o $@ $< $(LDLIBS) || echo BUILDERROR $@
-%-static: %.o
- $(CC) -static $(LDFLAGS) -o $@ $< $(LDLIBS) || echo BUILDERROR $@
-%: %.o
- $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS) || echo BUILDERROR $@
-
-$(BUILD)/dlopen: LDLIBS+=-ldl -rdynamic
-$(BUILD)/pthread%: LDLIBS+=-lpthread
-$(BUILD)/sem $(BUILD)/sem-static: LDLIBS+=-lpthread -lrt
-$(BUILD)/strtod_simple $(BUILD)/strtod_simple-static: LDLIBS+=-lm
-$(BUILD)/tgmath tgmath-static: LDLIBS+=-lm
-# adding ./lib.so through LDLIBS instead of $^ in the implicit rule because make removes the leading ./ from dependencies
-$(BUILD)/tls_align: LDLIBS+=$(BUILD)/tls_align_dso.so
-$(BUILD)/tls_align: $(BUILD)/tls_align_dso.so
-# make bug: tls_align target specific flags are also set for tls_align_dso.so when both target is built
-$(BUILD)/tls_align_dso.so: LDLIBS=
-$(BUILD)/tls_align-static: LDLIBS+=$(BUILD)/tls_align_dso.o
-$(BUILD)/tls_align-static: $(BUILD)/tls_align_dso.o
-$(BUILD)/tls_align_dlopen: LDLIBS+=-ldl
-$(BUILD)/tls_init tls_init-static: LDLIBS+=-lpthread
+all:
+%:
+ $(MAKE) -C ../.. src/functional/$@
char tmp[100]; \
char *got = basename(strcpy(tmp, path)); \
if (strcmp(want, got) != 0) \
- error("basename(\"%s\") got \"%s\" want \"%s\"\n", path, got, want); \
+ t_error("basename(\"%s\") got \"%s\" want \"%s\"\n", path, got, want); \
}
int main()
{
if (strcmp(basename(0), ".") != 0)
- error("basename(0) returned \"%s\"; expected \".\"\n", basename(0));
+ t_error("basename(0) returned \"%s\"; expected \".\"\n", basename(0));
T("", ".");
T("/usr/lib", "lib");
T("/usr/", "usr");
T("//usr//lib//", "lib");
T(".", ".");
T("..", "..");
- return test_status;
+ return t_status;
}
char tmp[100]; \
char *got = dirname(strcpy(tmp, path)); \
if (strcmp(want, got) != 0) \
- error("dirname(\"%s\") got \"%s\" want \"%s\"\n", path, got, want); \
+ t_error("dirname(\"%s\") got \"%s\" want \"%s\"\n", path, got, want); \
}
int main()
{
if (strcmp(dirname(0), ".") != 0)
- error("dirname(0) returned \"%s\"; expected \".\"\n", dirname(0));
+ t_error("dirname(0) returned \"%s\"; expected \".\"\n", dirname(0));
T("", ".");
T("/usr/lib", "/usr");
T("/usr/", "/");
T("///", "/");
T(".", ".");
T("..", ".");
- return test_status;
+ return t_status;
}
#include <dlfcn.h>
#include "test.h"
-int main()
+int main(int argc, char *argv[])
{
void *h, *g;
int *i, *i2;
char *s;
void (*f)(void);
+ char buf[512];
- h = dlopen("./dlopen_dso.so", RTLD_LAZY|RTLD_LOCAL);
+ if (!t_pathrel(buf, sizeof buf, argv[0], "dlopen_dso.so")) {
+ t_error("failed to obtain relative path to dlopen_dso.so\n");
+ return 1;
+ }
+ h = dlopen(buf, RTLD_LAZY|RTLD_LOCAL);
if (!h)
- error("dlopen ./dlopen_dso.so failed: %s\n", dlerror());
+ t_error("dlopen %s failed: %s\n", buf, dlerror());
i = dlsym(h, "i");
if (!i)
- error("dlsym i failed: %s\n", dlerror());
+ t_error("dlsym i failed: %s\n", dlerror());
if (*i != 1)
- error("initialization failed: want i=1 got i=%d\n", *i);
+ t_error("initialization failed: want i=1 got i=%d\n", *i);
f = (void (*)(void))dlsym(h, "f");
if (!f)
- error("dlsym f failed: %s\n", dlerror());
+ t_error("dlsym f failed: %s\n", dlerror());
f();
if (*i != 2)
- error("f call failed: want i=2 got i=%d\n", *i);
- if (dlclose(h))
- error("dlclose failed: %s\n", dlerror());
+ t_error("f call failed: want i=2 got i=%d\n", *i);
g = dlopen(0, RTLD_LAZY|RTLD_LOCAL);
if (!g)
- error("dlopen 0 failed: %s\n", dlerror());
+ t_error("dlopen 0 failed: %s\n", dlerror());
i2 = dlsym(g, "i");
s = dlerror();
if (i2 || s == 0)
- error("dlsym i should have failed\n");
- if (dlsym(g, "main") == 0)
- error("dlsym main failed: %s\n", dlerror());
+ t_error("dlsym i should have failed\n");
+ if (dlsym(g, "main") != (void*)main)
+ t_error("dlsym main failed: %s\n", dlerror());
- h = dlopen("./dlopen_dso.so", RTLD_LAZY|RTLD_GLOBAL);
+ /* close+open reinitializes the dso with glibc but not with musl */
+ h = dlopen(buf, RTLD_LAZY|RTLD_GLOBAL);
i2 = dlsym(g, "i");
if (!i2)
- error("dlsym i failed: %s\n", dlerror());
+ t_error("dlsym i failed: %s\n", dlerror());
+ if (i2 != i)
+ t_error("reopened dso should have the same symbols, want %p, got %p\n", i, i2);
if (*i2 != 2)
- error("want i2=2, got i2=%d\n", *i2);
+ t_error("reopened dso should have the same symbols, want i2==2, got i2==%d\n", *i2);
if (dlclose(g))
- error("dlclose failed: %s\n", dlerror());
- return test_status;
+ t_error("dlclose failed: %s\n", dlerror());
+ if (dlclose(h))
+ t_error("dlclose failed: %s\n", dlerror());
+ return t_status;
}
--- /dev/null
+$(N).BINS:=$(N)
+$(N).LDFLAGS:=-rdynamic
+$(N).err: $(D)/dlopen_dso.so
--- /dev/null
+$(N).BINS:=
+$(N).LIBS:=$(N).so
int r;
if (clearenv() || (environ && *environ))
- error("clrearenv: %s\n", strerror(errno));
+ t_error("clrearenv: %s\n", strerror(errno));
if (putenv("TEST=1"))
- error("putenv: %s\n", strerror(errno));
+ t_error("putenv: %s\n", strerror(errno));
if ((s=environ[1]))
- error("environ[1]: %p, wanted 0\n", s);
+ t_error("environ[1]: %p, wanted 0\n", s);
if (!(s=getenv("TEST")))
- error("getenv(\"TEST\"): 0, wanted \"1\"\n");
+ t_error("getenv(\"TEST\"): 0, wanted \"1\"\n");
if (strcmp(s,"1") != 0)
- error("getenv(\"TEST\"): \"%s\", wanted \"1\"\n", s);
+ t_error("getenv(\"TEST\"): \"%s\", wanted \"1\"\n", s);
if (unsetenv("TEST"))
- error("unsetenv: %s\n", strerror(errno));
+ t_error("unsetenv: %s\n", strerror(errno));
if ((s=*environ))
- error("*environ: %p != 0\n", s);
+ t_error("*environ: %p != 0\n", s);
if ((s=getenv("TEST")))
- error("getenv(\"TEST\"): %p, wanted 0\n", s);
+ t_error("getenv(\"TEST\"): %p, wanted 0\n", s);
if (setenv("TEST", "2", 0))
- error("setenv: %s\n", strerror(errno));
+ t_error("setenv: %s\n", strerror(errno));
if (strcmp(s=getenv("TEST"),"2") != 0)
- error("getenv(\"TEST\"): \"%s\", wanted \"2\"\n", s);
+ t_error("getenv(\"TEST\"): \"%s\", wanted \"2\"\n", s);
if (setenv("TEST", "3", 0))
- error("setenv: %s\n", strerror(errno));
+ t_error("setenv: %s\n", strerror(errno));
if (strcmp(s=getenv("TEST"),"2") != 0)
- error("getenv(\"TEST\"): \"%s\", wanted \"2\"\n", s);
+ t_error("getenv(\"TEST\"): \"%s\", wanted \"2\"\n", s);
if (setenv("TEST", "3", 1))
- error("setenv: %s\n", strerror(errno));
+ t_error("setenv: %s\n", strerror(errno));
if (strcmp(s=getenv("TEST"),"3") != 0)
- error("getenv(\"TEST\"): \"%s\", wanted \"3\"\n", s);
+ t_error("getenv(\"TEST\"): \"%s\", wanted \"3\"\n", s);
/* test failures */
if ((r=setenv("","",0)) != -1 || errno != EINVAL)
- error("setenv(\"\",\"\",0): %d, errno: %d (%s), wanted -1, %d (EINVAL)\n", r, errno, strerror(errno), EINVAL);
+ t_error("setenv(\"\",\"\",0): %d, errno: %d (%s), wanted -1, %d (EINVAL)\n", r, errno, strerror(errno), EINVAL);
if ((r=setenv(0,"",0)) != -1 || errno != EINVAL)
- error("setenv(0,\"\",0): %d, errno: %d (%s), wanted -1, %d (EINVAL)\n", r, errno, strerror(errno), EINVAL);
- return test_status;
+ t_error("setenv(0,\"\",0): %d, errno: %d (%s), wanted -1, %d (EINVAL)\n", r, errno, strerror(errno), EINVAL);
+ return t_status;
}
#include <sys/wait.h>
#include "test.h"
-#define TEST(c, ...) ((c) ? 1 : (error(#c" failed: " __VA_ARGS__),0))
+#define TEST(c, ...) ((c) ? 1 : (t_error(#c" failed: " __VA_ARGS__),0))
#define TESTE(c) (errno=0, TEST(c, "errno = %s\n", strerror(errno)))
int main(void)
pid_t pid;
int status;
- if (!TESTE(f=tmpfile())) return test_status;
+ if (!TESTE(f=tmpfile())) return t_status;
fd = fileno(f);
fl.l_type = F_WRLCK;
fclose(f);
- return test_status;
+ return t_status;
}
#define TEST(c) do { \
errno = 0; \
if (!(c)) \
- error("%s failed (errno = %d)\n", #c, errno); \
+ t_error("%s failed (errno = %d)\n", #c, errno); \
} while(0)
int main(void)
TEST(fseeko(f, 0, SEEK_SET)==0);
TEST(fgets(foo, sizeof foo, f));
if (strcmp(foo,"hello") != 0)
- error("fgets read back: \"%s\"; wanted: \"hello\"\n", foo);
+ t_error("fgets read back: \"%s\"; wanted: \"hello\"\n", foo);
fclose(f);
}
if (fd > 2)
TEST(unlink(tmp) != -1);
- return test_status;
+ return t_status;
}
r = fnmatch(tests[i].pattern, tests[i].string, tests[i].flags);
x = tests[i].expected;
if (r != x && (r != FNM_NOMATCH || x != -FNM_NOMATCH)) {
- error("fnmatch(\"%s\", \"%s\", %s) failed, got %d want %d\n",
+ t_error("fnmatch(\"%s\", \"%s\", %s) failed, got %d want %d\n",
tests[i].pattern, tests[i].string,
flagstr(fnmatch_flags, tests[i].flags),
r, x);
}
}
- return test_status;
+ return t_status;
}
#define TEST(r, f, x, m) ( \
errno=0, ((r) = (f)) == (x) || \
- (error("%s failed (" m ")\n", #f, r, x, strerror(errno)), 0) )
+ (t_error("%s failed (" m ")\n", #f, r, x, strerror(errno)), 0) )
#define TEST_S(s, x, m) ( \
!strcmp((s),(x)) || \
- (error("[%s] != [%s] (%s)\n", s, x, m), 0) )
+ (t_error("[%s] != [%s] (%s)\n", s, x, m), 0) )
static FILE *writetemp(const char *data)
{
fclose(f);
}
- return test_status;
+ return t_status;
}
#define TEST(r, f, x, m) ( \
errno=0, ((r) = (f)) == (x) || \
- (error("%s failed (" m ")\n", #f, r, x, strerror(errno)), 0) )
+ (t_error("%s failed (" m ")\n", #f, r, x, strerror(errno)), 0) )
#define TEST_S(s, x, m) ( \
!strcmp((s),(x)) || \
- (error("[%s] != [%s] (%s)\n", s, x, m), 0) )
+ (t_error("[%s] != [%s] (%s)\n", s, x, m), 0) )
static FILE *writetemp(const char *data)
{
fclose(f);
}
- return test_status;
+ return t_status;
}
#define T(f) do{ \
if ((f)+1 == 0) \
- error("%s failed: %s\n", #f, strerror(errno)); \
+ t_error("%s failed: %s\n", #f, strerror(errno)); \
}while(0)
#define EQ(a,b,fmt) do{ \
if ((a) != (b)) \
- error("%s == %s failed: " fmt "\n", #a, #b, a, b); \
+ t_error("%s == %s failed: " fmt "\n", #a, #b, a, b); \
}while(0)
static void snd()
T(msgctl(qid, IPC_RMID, 0));
T(qid = msgget(k, IPC_CREAT|IPC_EXCL|0666));
- if (test_status)
- exit(test_status);
+ if (t_status)
+ exit(t_status);
/* check IPC_EXCL */
errno = 0;
if (msgget(k, IPC_CREAT|IPC_EXCL|0666) != -1 || errno != EEXIST)
- error("msgget(IPC_CREAT|IPC_EXCL) should have failed with EEXIST, got %s\n", strerror(errno));
+ t_error("msgget(IPC_CREAT|IPC_EXCL) should have failed with EEXIST, got %s\n", strerror(errno));
/* check if msgget initilaized the msqid_ds structure correctly */
T(msgctl(qid, IPC_STAT, &qid_ds));
EQ((long)qid_ds.msg_stime, 0, "got %ld, want %d");
EQ((long)qid_ds.msg_rtime, 0, "got %ld, want %d");
if (qid_ds.msg_ctime < t)
- error("qid_ds.msg_ctime >= t failed: got %ld, want %ld\n", (long)qid_ds.msg_ctime, (long)t);
+ t_error("qid_ds.msg_ctime >= t failed: got %ld, want %ld\n", (long)qid_ds.msg_ctime, (long)t);
if (qid_ds.msg_qbytes <= 0)
- error("qid_ds.msg_qbytes > 0 failed: got %d, want 0\n", qid_ds.msg_qbytes, t);
+ t_error("qid_ds.msg_qbytes > 0 failed: got %d, want 0\n", qid_ds.msg_qbytes, t);
/* test send */
T(msgsnd(qid, &msg, sizeof msg.data, IPC_NOWAIT));
EQ(qid_ds.msg_qnum, 1, "got %d, want %d");
EQ(qid_ds.msg_lspid, getpid(), "got %d, want %d");
if (qid_ds.msg_stime < t)
- error("msg_stime is %ld want >= %ld\n", (long)qid_ds.msg_stime, (long)t);
+ t_error("msg_stime is %ld want >= %ld\n", (long)qid_ds.msg_stime, (long)t);
}
static void rcv()
errno = 0;
if (msgrcv(qid, &msg, 0, msgtyp, 0) != -1 || errno != E2BIG)
- error("msgrcv should have failed when msgsize==0 with E2BIG, got %s\n", strerror(errno));
+ t_error("msgrcv should have failed when msgsize==0 with E2BIG, got %s\n", strerror(errno));
/* test receive */
T(msgrcv(qid, &msg, sizeof msg.data, msgtyp, IPC_NOWAIT));
if (strcmp(msg.data,"test message") != 0)
- error("received \"%s\" instead of \"%s\"\n", msg.data, "test message");
+ t_error("received \"%s\" instead of \"%s\"\n", msg.data, "test message");
errno = 0;
if (msgrcv(qid, &msg, sizeof msg.data, msgtyp, MSG_NOERROR|IPC_NOWAIT) != -1 || errno != ENOMSG)
- error("msgrcv should have failed when ther is no msg with ENOMSG, got %s\n", strerror(errno));
+ t_error("msgrcv should have failed when ther is no msg with ENOMSG, got %s\n", strerror(errno));
/* cleanup */
T(msgctl(qid, IPC_RMID, 0));
snd();
p = fork();
if (p == -1)
- error("fork failed: %s\n", strerror(errno));
+ t_error("fork failed: %s\n", strerror(errno));
else if (p == 0)
rcv();
else {
T(waitpid(p, &status, 0));
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
- error("child exit status: %d\n", status);
+ t_error("child exit status: %d\n", status);
}
- return test_status;
+ return t_status;
}
#define T(f) do{ \
if ((f)+1 == 0) \
- error("%s failed: %s\n", #f, strerror(errno)); \
+ t_error("%s failed: %s\n", #f, strerror(errno)); \
}while(0)
#define EQ(a,b,fmt) do{ \
if ((a) != (b)) \
- error("%s == %s failed: " fmt "\n", #a, #b, a, b); \
+ t_error("%s == %s failed: " fmt "\n", #a, #b, a, b); \
}while(0)
static void inc()
T(semctl(semid, 0, IPC_RMID));
T(semid = semget(k, 1, IPC_CREAT|IPC_EXCL|0666));
- if (test_status)
- exit(test_status);
+ if (t_status)
+ exit(t_status);
/* check IPC_EXCL */
errno = 0;
if (semget(k, 1, IPC_CREAT|IPC_EXCL|0666) != -1 || errno != EEXIST)
- error("semget(IPC_CREAT|IPC_EXCL) should have failed with EEXIST, got %s\n", strerror(errno));
+ t_error("semget(IPC_CREAT|IPC_EXCL) should have failed with EEXIST, got %s\n", strerror(errno));
/* check if msgget initilaized the msqid_ds structure correctly */
arg.buf = &semid_ds;
EQ(semid_ds.sem_nsems, 1, "got %d, want %d");
EQ((long)semid_ds.sem_otime, 0, "got %ld, want %d");
if (semid_ds.sem_ctime < t)
- error("semid_ds.sem_ctime >= t failed: got %ld, want %ld\n", (long)semid_ds.sem_ctime, (long)t);
+ t_error("semid_ds.sem_ctime >= t failed: got %ld, want %ld\n", (long)semid_ds.sem_ctime, (long)t);
/* test sem_op > 0 */
sops.sem_num = 0;
inc();
p = fork();
if (p == -1)
- error("fork failed: %s\n", strerror(errno));
+ t_error("fork failed: %s\n", strerror(errno));
else if (p == 0)
dec();
else {
T(waitpid(p, &status, 0));
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
- error("child exit status: %d\n", status);
+ t_error("child exit status: %d\n", status);
}
- return test_status;
+ return t_status;
}
#define T(f) do{ \
if ((f)+1 == 0) \
- error("%s failed: %s\n", #f, strerror(errno)); \
+ t_error("%s failed: %s\n", #f, strerror(errno)); \
}while(0)
#define EQ(a,b,fmt) do{ \
if ((a) != (b)) \
- error("%s == %s failed: " fmt "\n", #a, #b, a, b); \
+ t_error("%s == %s failed: " fmt "\n", #a, #b, a, b); \
}while(0)
static void set()
T(shmctl(shmid, IPC_RMID, 0));
T(shmid = shmget(k, 100, IPC_CREAT|IPC_EXCL|0666));
- if (test_status)
- exit(test_status);
+ if (t_status)
+ exit(t_status);
/* check IPC_EXCL */
errno = 0;
if (shmget(k, 100, IPC_CREAT|IPC_EXCL|0666) != -1 || errno != EEXIST)
- error("shmget(IPC_CREAT|IPC_EXCL) should have failed with EEXIST, got %s\n", strerror(errno));
+ t_error("shmget(IPC_CREAT|IPC_EXCL) should have failed with EEXIST, got %s\n", strerror(errno));
/* check if shmget initilaized the msshmid_ds structure correctly */
T(shmctl(shmid, IPC_STAT, &shmid_ds));
EQ((long)shmid_ds.shm_atime, 0, "got %ld, want %d");
EQ((long)shmid_ds.shm_dtime, 0, "got %ld, want %d");
if (shmid_ds.shm_ctime < t)
- error("shmid_ds.shm_ctime >= t failed: got %ld, want %ld\n", (long)shmid_ds.shm_ctime, (long)t);
+ t_error("shmid_ds.shm_ctime >= t failed: got %ld, want %ld\n", (long)shmid_ds.shm_ctime, (long)t);
/* test attach */
if ((p=shmat(shmid, 0, 0)) == 0)
- error("shmat failed: %s\n", strerror(errno));
+ t_error("shmat failed: %s\n", strerror(errno));
T(shmctl(shmid, IPC_STAT, &shmid_ds));
EQ((int)shmid_ds.shm_nattch, 1, "got %d, want %d");
EQ(shmid_ds.shm_lpid, getpid(), "got %d, want %d");
if (shmid_ds.shm_atime < t)
- error("shm_atime is %ld want >= %ld\n", (long)shmid_ds.shm_atime, (long)t);
+ t_error("shm_atime is %ld want >= %ld\n", (long)shmid_ds.shm_atime, (long)t);
strcpy(p, "test data");
T(shmdt(p));
}
errno = 0;
if ((p=shmat(shmid, 0, SHM_RDONLY)) == 0)
- error("shmat failed: %s\n", strerror(errno));
+ t_error("shmat failed: %s\n", strerror(errno));
if (strcmp(p, "test data") != 0)
- error("reading shared mem failed: got \"%.100s\" want \"test data\"\n", p);
+ t_error("reading shared mem failed: got \"%.100s\" want \"test data\"\n", p);
/* cleanup */
T(shmdt(p));
set();
p = fork();
if (p == -1)
- error("fork failed: %s\n", strerror(errno));
+ t_error("fork failed: %s\n", strerror(errno));
else if (p == 0)
get();
else {
T(waitpid(p, &status, 0));
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
- error("child exit status: %d\n", status);
+ t_error("child exit status: %d\n", status);
}
- return test_status;
+ return t_status;
}
#define T(f, x, m) (void)( \
memset(&st, 0, sizeof st), \
(i = (f)) == (x) || \
- error("%s failed (%s) got %d want %d\n", #f, m, i, x) )
+ t_error("%s failed (%s) got %d want %d\n", #f, m, i, x) )
#define TCHAR(f, x, m) (void)( \
memset(&st, 0, sizeof st), \
(i = (f)) == (x) || \
- error("%s failed (%s) got 0x%04x want 0x%04x\n", #f, m, i, x) )
+ t_error("%s failed (%s) got 0x%04x want 0x%04x\n", #f, m, i, x) )
int main(void)
{
T(mbsrtowcs(NULL, (cs="abcdef",&cs), 2, &st), 6, "wrong semantics for NULL wcs");
if (strcmp(nl_langinfo(CODESET), "UTF-8"))
- return error("cannot set UTF-8 locale for test (codeset=%s)\n", nl_langinfo(CODESET));
+ return t_error("cannot set UTF-8 locale for test (codeset=%s)\n", nl_langinfo(CODESET));
T(mbrtowc(&wc, "\x80", 1, &st), -1, "failed to catch error");
T(mbrtowc(&wc, "\xc0", 1, &st), -1, "failed to catch illegal initial");
TCHAR(wcs[0], 0xa0, "wrong char");
TCHAR(wcs[1], 'a', "wrong char");
T(!cs, 1, "wrong final position");
- return test_status;
+ return t_status;
}
#define TEST(r, f, x, m) ( \
((r) = (f)) == (x) || \
-(error("%s failed (" m ")\n", #f, r, x), 0) )
+(t_error("%s failed (" m ")\n", #f, r, x), 0) )
#define TEST_E(f) ( (errno = 0), (f) || \
-(error("%s failed (errno = %d)\n", #f, errno), 0) )
+(t_error("%s failed (errno = %d)\n", #f, errno), 0) )
#define TEST_S(s, x, m) ( \
!strcmp((s),(x)) || \
-(error("[%s] != [%s] (%s)\n", s, x, m), 0) )
+(t_error("[%s] != [%s] (%s)\n", s, x, m), 0) )
#define TEST_M(s, x, n, m) ( \
!memcmp((s),(x),(n)) || \
-(error("[%s] != [%s] (%s)\n", s, x, m), 0) )
+(t_error("[%s] != [%s] (%s)\n", s, x, m), 0) )
int main(void)
{
TEST(i, ftell(f), 8, "%d != %d");
TEST_S(buf, "hello104", "");
fclose(f);
- return test_status;
+ return t_status;
}
#include "test.h"
#define TEST(r, f, x, m) ( \
- ((r) = (f)) == (x) || (error("%s failed (" m ")\n", #f, r, x), 0) )
+ ((r) = (f)) == (x) || (t_error("%s failed (" m ")\n", #f, r, x), 0) )
#define TEST_E(f) ( \
(errno = 0), \
- (f) || (error("%s failed (errno = %d)\n", #f, errno), 0) )
+ (f) || (t_error("%s failed (errno = %d)\n", #f, errno), 0) )
#define TEST_S(s, x, m) ( \
!strcmp((s),(x)) || \
- (error("[%s] != [%s] (%s)\n", s, x, m), 0) )
+ (t_error("[%s] != [%s] (%s)\n", s, x, m), 0) )
static sig_atomic_t got_sig;
TEST(i, got_sig, 1, "child process did not send signal");
}
signal(SIGUSR1, SIG_DFL);
- return test_status;
+ return t_status;
}
#include <string.h>
#include "test.h"
-#define TESTC(c, m) ( (c) || (error("%s failed (" m ")\n", #c), 0) )
+#define TESTC(c, m) ( (c) || (t_error("%s failed (" m ")\n", #c), 0) )
#define TESTR(r, f, m) ( \
- ((r) = (f)) == 0 || (error("%s failed: %s (" m ")\n", #f, strerror(r)), 0) )
+ ((r) = (f)) == 0 || (t_error("%s failed: %s (" m ")\n", #f, strerror(r)), 0) )
static void *start_async(void *arg)
{
TESTC(foo[2] == 3, "cleanup handler failed to run");
TESTC(foo[3] == 4, "cleanup handler failed to run");
- return test_status;
+ return t_status;
}
#include "test.h"
#define TEST(r, f, m) ( \
- ((r) = (f)) == 0 || (error("%s failed: %s (" m ")\n", #f, strerror(r)), 0) )
+ ((r) = (f)) == 0 || (t_error("%s failed: %s (" m ")\n", #f, strerror(r)), 0) )
static void *start_signal(void *arg)
TEST(r, pthread_mutex_destroy(&mtx), "");
TEST(r, pthread_cond_destroy(&cond), "");
- return test_status;
+ return t_status;
}
#include "test.h"
#define TEST(r, f, m) ( \
- ((r) = (f)) == 0 || (error("%s failed: %s (" m ")\n", #f, strerror(r)), 0) )
+ ((r) = (f)) == 0 || (t_error("%s failed: %s (" m ")\n", #f, strerror(r)), 0) )
#define TESTX(r, f, x, m) ( \
- ((r) = (f)) == (x) || (error("%s failed: got %d \"%s\" want %d \"%s\" (" m ")\n", #f, r, strerror(r), x, strerror(x)), 0) )
+ ((r) = (f)) == (x) || (t_error("%s failed: got %d \"%s\" want %d \"%s\" (" m ")\n", #f, r, strerror(r), x, strerror(x)), 0) )
static void *start_lock(void *arg)
{
TEST(r, pthread_create(&td, 0, start_wait, (void *[]){ &barrier2, &mtx }), "");
r = pthread_barrier_wait(&barrier2);
if (r && r != PTHREAD_BARRIER_SERIAL_THREAD)
- error("pthread_barrier_wait failed: got %d \"%s\", wanted either 0 or %d\n",
+ t_error("pthread_barrier_wait failed: got %d \"%s\", wanted either 0 or %d\n",
r, strerror(r), PTHREAD_BARRIER_SERIAL_THREAD);
TESTX(r, pthread_mutex_lock(&mtx), EOWNERDEAD, "");
TEST(r, pthread_join(td, &res), "");
TEST(r, pthread_mutex_unlock(&mtx), "");
TEST(r, pthread_mutex_destroy(&mtx), "");
- return test_status;
+ return t_status;
}
#include <string.h>
#include "test.h"
-#define TESTC(c, m) ( (c) || (error("%s failed (" m ")\n", #c), 0) )
+#define TESTC(c, m) ( (c) || (t_error("%s failed (" m ")\n", #c), 0) )
#define TESTR(r, f, m) ( \
- ((r) = (f)) == 0 || (error("%s failed: %s (" m ")\n", #f, strerror(r)), 0) )
+ ((r) = (f)) == 0 || (t_error("%s failed: %s (" m ")\n", #f, strerror(r)), 0) )
static pthread_key_t k1, k2;
TESTR(r, pthread_setspecific(k2, 0), "failed to clear tsd");
TESTR(r, pthread_key_delete(k1), "failed to destroy key");
TESTR(r, pthread_key_delete(k2), "failed to destroy key");
- return test_status;
+ return t_status;
}
+#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
return *(char*)a - *(char*)b;
}
+static int cmp64(const void *a, const void *b)
+{
+ const uint64_t *ua = a, *ub = b;
+ return *ua < *ub ? -1 : *ua != *ub;
+}
+
/* 26 items -- even */
static const char *s[] = {
"Bob", "Alice", "John", "Ceres",
93994, 232323, 848405, 879045, 2230404, 3434344, 99405644
};
-static void string_sort(const char **a, const char **a_sorted, int len)
+static void str_test(const char **a, const char **a_sorted, int len)
{
int i;
qsort(a, len, sizeof *a, scmp);
for (i=0; i<len; i++) {
if (strcmp(a[i], a_sorted[i]) != 0) {
- error("string sort failed at index %d\n", i);
- test_printf("\ti\tgot\twant\n");
+ t_error("string sort failed at index %d\n", i);
+ t_printf("\ti\tgot\twant\n");
for (i=0; i<len; i++)
- test_printf("\t%d\t%s\t%s\n", i, a[i], a_sorted[i]);
+ t_printf("\t%d\t%s\t%s\n", i, a[i], a_sorted[i]);
break;
}
}
}
-static void integer_sort(int *a, int *a_sorted, int len)
+static void int_test(int *a, int *a_sorted, int len)
{
int i;
qsort(a, len, sizeof *a, icmp);
for (i=0; i<len; i++) {
if (a[i] != a_sorted[i]) {
- error("integer sort failed at index %d\n", i);
- test_printf("\ti\tgot\twant\n");
+ t_error("integer sort failed at index %d\n", i);
+ t_printf("\ti\tgot\twant\n");
for (i=0; i<len; i++)
- test_printf("\t%d\t%d\t%d\n", i, a[i], a_sorted[i]);
+ t_printf("\t%d\t%d\t%d\n", i, a[i], a_sorted[i]);
+ break;
+ }
+ }
+}
+
+static void uint64_gen(uint64_t *p, uint64_t *p_sorted, int n)
+{
+ int i;
+ uint64_t r = 0;
+ t_randseed(n);
+ for (i = 0; i < n; i++) {
+ r += t_randn(20);
+ p[i] = r;
+ }
+ memcpy(p_sorted, p, n * sizeof *p);
+ t_shuffle(p, n);
+}
+
+static void uint64_test(uint64_t *a, uint64_t *a_sorted, int len)
+{
+ int i;
+ qsort(a, len, sizeof *a, cmp64);
+ for (i=0; i<len; i++) {
+ if (a[i] != a_sorted[i]) {
+ t_error("uint64 sort failed at index %d\n", i);
+ t_printf("\ti\tgot\twant\n");
+ for (i=0; i<len; i++)
+ t_printf("\t%d\t%" PRIu64 "\t%" PRIu64 "\n", i, a[i], a_sorted[i]);
break;
}
}
char p[] = a; \
qsort(p, sizeof p - 1, 1, ccmp); \
if (memcmp(p, a_sorted, sizeof p) != 0) { \
- error("character sort failed\n"); \
- test_printf("\tgot: \"%s\"\n", p); \
- test_printf("\twant: \"%s\"\n", a_sorted); \
+ t_error("character sort failed\n"); \
+ t_printf("\tgot: \"%s\"\n", p); \
+ t_printf("\twant: \"%s\"\n", a_sorted); \
} \
} while(0)
-static void character_sort(void)
+static void char_test(void)
{
T("", "");
T("1", "1");
int main(void)
{
- string_sort(s, s_sorted, sizeof s/sizeof*s);
- integer_sort(n, n_sorted, sizeof n/sizeof*n);
- character_sort();
- return test_status;
+ int i;
+
+ str_test(s, s_sorted, sizeof s/sizeof*s);
+ int_test(n, n_sorted, sizeof n/sizeof*n);
+ char_test();
+ for (i = 1023; i<=1026; i++) {
+ uint64_t p[1026], p_sorted[1026];
+ uint64_gen(p, p_sorted, i);
+ uint64_test(p, p_sorted, i);
+ }
+ return t_status;
}
#include "test.h"
#define TEST(c, ...) \
- ( (c) || (error(#c " failed: " __VA_ARGS__),0) )
+ ( (c) || (t_error(#c " failed: " __VA_ARGS__),0) )
int main(void)
{
TEST(sem_close(sem) == 0, "%s\n", strerror(errno));
TEST(sem_close(sem) == 0, "%s\n", strerror(errno));
TEST(sem_unlink(buf) == 0, "%s\n", strerror(errno));
- return test_status;
+ return t_status;
}
#include <setjmp.h>
#include "test.h"
-#define TEST(c, ...) ((c) ? 1 : (error(#c" failed: " __VA_ARGS__),0))
+#define TEST(c, ...) ((c) ? 1 : (t_error(#c" failed: " __VA_ARGS__),0))
int main(void)
{
sigprocmask(SIG_SETMASK, &set, &set);
TEST(sigismember(&set, SIGUSR1)==0, "siglongjmp failed to restore mask\n");
- return test_status;
+ return t_status;
}
#define TEST(r, f, x, m) ( \
((r) = (f)) == (x) || \
- (error("%s failed (" m ")\n", #f, r, x), 0) )
+ (t_error("%s failed (" m ")\n", #f, r, x), 0) )
#define TEST_S(s, x, m) ( \
!strcmp((s),(x)) || \
- (error("[%s] != [%s] (%s)\n", s, x, m), 0) )
+ (t_error("[%s] != [%s] (%s)\n", s, x, m), 0) )
static const struct {
const char *fmt;
for (j=0; int_tests[j].fmt; j++) {
i = snprintf(b, sizeof b, int_tests[j].fmt, int_tests[j].i);
if (i != strlen(int_tests[j].expect)) {
- error("snprintf(b, sizeof b, \"%s\", %d) returned %d wanted %d\n",
+ t_error("snprintf(b, sizeof b, \"%s\", %d) returned %d wanted %d\n",
int_tests[j].fmt, int_tests[j].i, i, strlen(int_tests[j].expect));
}
if (strcmp(b, int_tests[j].expect) != 0)
- error("bad integer conversion: got \"%s\", want \"%s\"\n", b, int_tests[j].expect);
+ t_error("bad integer conversion: got \"%s\", want \"%s\"\n", b, int_tests[j].expect);
}
for (j=0; fp_tests[j].fmt; j++) {
i = snprintf(b, sizeof b, fp_tests[j].fmt, fp_tests[j].f);
if (i != strlen(fp_tests[j].expect)) {
- error("snprintf(b, sizeof b, \"%s\", %f) returned %d wanted %d\n",
+ t_error("snprintf(b, sizeof b, \"%s\", %f) returned %d wanted %d\n",
fp_tests[j].fmt, fp_tests[j].f, i, strlen(fp_tests[j].expect));
}
if (strcmp(b, fp_tests[j].expect) != 0)
- error("bad floating-point conversion: got \"%s\", want \"%s\"\n", b, fp_tests[j].expect);
+ t_error("bad floating-point conversion: got \"%s\", want \"%s\"\n", b, fp_tests[j].expect);
}
TEST(i, snprintf(0, 0, "%.4a", 1.0), 11, "%d != %d");
- return test_status;
+ return t_status;
}
#include <fcntl.h>
#include "test.h"
-#define TEST(c, ...) ((c) ? 1 : (error(#c" failed: " __VA_ARGS__),0))
+#define TEST(c, ...) ((c) ? 1 : (t_error(#c" failed: " __VA_ARGS__),0))
#define TESTE(c) (errno=0, TEST(c, "errno = %s\n", strerror(errno)))
int main(void)
close(c);
close(s);
- return test_status;
+ return t_status;
}
#define TEST(f, x) (void)( \
(r = (f)) == (x) || \
- error("%s failed, got %d want %d\n", #f, r, x) )
+ t_error("%s failed, got %d want %d\n", #f, r, x) )
#define TEST_E(f) (void)( \
(errno = 0), (f) || \
- error("%s failed (errno = %d \"%s\")\n", #f, errno, strerror(errno)) )
+ t_error("%s failed (errno = %d \"%s\")\n", #f, errno, strerror(errno)) )
int main(void)
{
TEST(read(p[0], foo, sizeof foo), 6);
close(p[0]);
TEST(posix_spawn_file_actions_destroy(&fa), 0);
- return test_status;
+ return t_status;
}
#define TEST(r, f, x, m) ( \
((r) = (f)) == (x) || \
- (error("%s failed (" m ")\n", #f, r, x), 0) )
+ (t_error("%s failed (" m ")\n", #f, r, x), 0) )
#define TEST_S(s, x, m) ( \
!strcmp((s),(x)) || \
- (error("[%s] != [%s] (%s)\n", s, x, m), 0) )
+ (t_error("[%s] != [%s] (%s)\n", s, x, m), 0) )
#define TEST_F(x) ( \
TEST(i, sscanf(# x, "%lf", &d), 1, "got %d fields, expected %d"), \
TEST(i, sscanf("10e", "%lf", &d), 0, "got %d fields, expected no match (%d)");
TEST(i, sscanf("", "%lf\n", &d), -1, "got %d fields, expected input failure (%d)");
- return test_status;
+ return t_status;
}
struct rlimit rl;
if (getrlimit(r, &rl))
- error("getrlimit %d: %s\n", r, strerror(errno));
+ t_error("getrlimit %d: %s\n", r, strerror(errno));
rl.rlim_cur = lim;
if (setrlimit(r, &rl))
- error("setrlimit %d: %s\n", r, strerror(errno));
+ t_error("setrlimit %d: %s\n", r, strerror(errno));
}
int main(void)
char c;
if (!s)
- return error("out of memory");
+ return t_error("out of memory");
setrl(RLIMIT_STACK, 128*1024);
for (i = 0; i < n; i++) s[i] = '1';
i = sscanf(s, "%f %c", &f, &c);
if (i != 2)
- error("sscanf returned %d, want 2\n", i);
+ t_error("sscanf returned %d, want 2\n", i);
if (f != INFINITY)
- error("sscanf(longnum, \"%%f\") read %f, want inf\n", f);
+ t_error("sscanf(longnum, \"%%f\") read %f, want inf\n", f);
if (c != '1')
- error("sscanf(\"1\", %%c) read '%c', want '1'\n", c);
+ t_error("sscanf(\"1\", %%c) read '%c', want '1'\n", c);
free(s);
- return test_status;
+ return t_status;
}
#include <unistd.h>
#include "test.h"
-#define TEST(c, ...) ((c) ? 1 : (error(#c" failed: " __VA_ARGS__),0))
+#define TEST(c, ...) ((c) ? 1 : (t_error(#c" failed: " __VA_ARGS__),0))
int main(void)
{
fclose(f);
}
- return test_status;
+ return t_status;
}
#define TEST(r, f, x, m) ( \
((r) = (f)) == (x) || \
- (error("%s failed (" m ")\n", #f, r, x), 0) )
+ (t_error("%s failed (" m ")\n", #f, r, x), 0) )
#define TEST_S(s, x, m) ( \
!strcmp((s),(x)) || \
- (error("[%s] != [%s] (%s)\n", s, x, m), 0) )
+ (t_error("[%s] != [%s] (%s)\n", s, x, m), 0) )
int main(void)
{
TEST(i, strlcat(b, "123", 3), 6, "length %d != %d");
TEST_S(b, "abc", "strlcat result");
#endif
- return test_status;
+ return t_status;
}
char *p = s; \
char *q = memmem(p, strlen(p), sub, strlen(sub)); \
if (q) \
- error("memmem(%s,%s) returned str+%d, wanted 0\n", #s, #sub, q-p); \
+ t_error("memmem(%s,%s) returned str+%d, wanted 0\n", #s, #sub, q-p); \
}
#define T(s, sub, n) { \
char *p = s; \
char *q = memmem(p, strlen(p), sub, strlen(sub)); \
if (q == 0) \
- error("memmem(%s,%s) returned 0, wanted str+%d\n", #s, #sub, n); \
+ t_error("memmem(%s,%s) returned 0, wanted str+%d\n", #s, #sub, n); \
else if (q - p != n) \
- error("memmem(%s,%s) returned str+%d, wanted str+%d\n", #s, #sub, q-p, n); \
+ t_error("memmem(%s,%s) returned str+%d, wanted str+%d\n", #s, #sub, q-p, n); \
}
int main(void)
T("nanabanabanana", "banana", 8)
T("_ _\xff_ _", "_\xff_", 2)
- return test_status;
+ return t_status;
}
char *p = s; \
char *q = strchr(p, c); \
if (q) \
- error("strchr(%s,%s) returned str+%d, wanted 0\n", #s, #c, q-p); \
+ t_error("strchr(%s,%s) returned str+%d, wanted 0\n", #s, #c, q-p); \
}
#define T(s, c, n) { \
char *p = s; \
char *q = strchr(p, c); \
if (q == 0) \
- error("strchr(%s,%s) returned 0, wanted str+%d\n", #s, #c, n); \
+ t_error("strchr(%s,%s) returned 0, wanted str+%d\n", #s, #c, n); \
else if (q - p != n) \
- error("strchr(%s,%s) returned str+%d, wanted str+%d\n", #s, #c, q-p, n); \
+ t_error("strchr(%s,%s) returned str+%d, wanted str+%d\n", #s, #c, q-p, n); \
}
int main(void)
T(s, 255, 254)
T(s, 0, 255)
- return test_status;
+ return t_status;
}
char *q = c; \
size_t r = strcspn(p, q); \
if (r != n) \
- error("strcspn(%s,%s) returned %lu, wanted %lu\n", #s, #c, (unsigned long)r, (unsigned long)(n)); \
+ t_error("strcspn(%s,%s) returned %lu, wanted %lu\n", #s, #c, (unsigned long)r, (unsigned long)(n)); \
}
int main(void)
T("\xff\x80 abc", a, 2)
T(s, "\xff", 254)
- return test_status;
+ return t_status;
}
char *p = s; \
char *q = strstr(p, sub); \
if (q) \
- error("strstr(%s,%s) returned str+%d, wanted 0\n", #s, #sub, q-p); \
+ t_error("strstr(%s,%s) returned str+%d, wanted 0\n", #s, #sub, q-p); \
}
#define T(s, sub, n) { \
char *p = s; \
char *q = strstr(p, sub); \
if (q == 0) \
- error("strstr(%s,%s) returned 0, wanted str+%d\n", #s, #sub, n); \
+ t_error("strstr(%s,%s) returned 0, wanted str+%d\n", #s, #sub, n); \
else if (q - p != n) \
- error("strstr(%s,%s) returned str+%d, wanted str+%d\n", #s, #sub, q-p, n); \
+ t_error("strstr(%s,%s) returned str+%d, wanted str+%d\n", #s, #sub, q-p, n); \
}
int main(void)
T("nanabanabanana", "banana", 8)
T("_ _\xff_ _", "_\xff_", 2)
- return test_status;
+ return t_status;
}
for (i = 0; i < length(t); i++) {
x = strtod(t[i].s, &p);
if (x != t[i].f)
- error("strtod(\"%s\") want %a got %a\n", t[i].s, t[i].f, x);
+ t_error("strtod(\"%s\") want %a got %a\n", t[i].s, t[i].f, x);
}
- return test_status;
+ return t_status;
}
buf[sizeof buf - 1] = 0;
if ((x=strtod(buf, 0)) != want)
- error("strtod(.11[...]1) got %a want %a\n", x, want);
- return test_status;
+ t_error("strtod(.11[...]1) got %a want %a\n", x, want);
+ return t_status;
}
* f = function call to test (or any expression)
* x = expected result
* m = message to print on failure (with formats for r & x)
-**/
+ */
#define TEST(r, f, x, m) ( \
((r) = (f)) == (x) || \
- (error("%s failed (" m ")\n", #f, r, x, r-x), 0) )
+ (t_error("%s failed (" m ")\n", #f, r, x, r-x), 0) )
int main(void)
{
TEST(d, strtod("0x1p4", 0), 16.0, "hex float %a != %a");
TEST(d, strtod("0x1.1p4", 0), 17.0, "hex float %a != %a");
- return test_status;
+ return t_status;
}
for (i = 0; i < length(t); i++) {
x = strtof(t[i].s, &p);
if (x != t[i].f)
- error("strtof(\"%s\") want %a got %a\n", t[i].s, t[i].f, x);
+ t_error("strtof(\"%s\") want %a got %a\n", t[i].s, t[i].f, x);
}
- return test_status;
+ return t_status;
}
#define TEST(r, f, x, m) ( \
errno = 0, msg = #f, ((r) = (f)) == (x) || \
- (error("%s failed (" m ")\n", #f, r, x), 0) )
+ (t_error("%s failed (" m ")\n", #f, r, x), 0) )
#define TEST2(r, f, x, m) ( \
((r) = (f)) == (x) || \
- (error("%s failed (" m ")\n", msg, r, x), 0) )
+ (t_error("%s failed (" m ")\n", msg, r, x), 0) )
int main(void)
{
TEST(l, strtol(s=" 1", &c, 0), 1, "%ld != %ld");
TEST2(i, c-s, 3, "wrong final position %d != %d");
- return test_status;
+ return t_status;
}
for (i = 0; i < length(t); i++) {
x = strtold(t[i].s, &p);
if (x != t[i].f)
- error("strtold(\"%s\") want %La got %La\n", t[i].s, t[i].f, x);
+ t_error("strtold(\"%s\") want %La got %La\n", t[i].s, t[i].f, x);
}
- return test_status;
+ return t_status;
}
#define TEST(r, f, x, m) ( \
((r) = (f)) == (x) || \
- (error("%s failed (" m ")\n", #f, r, x), 0) )
+ (t_error("%s failed (" m ")\n", #f, r, x), 0) )
#define TEST_S(s, x, m) ( \
!wcscmp((s),(x)) || \
- (error("[%ls] != [%ls] (%s)\n", s, x, m), 0) )
+ (t_error("[%ls] != [%ls] (%s)\n", s, x, m), 0) )
static const struct {
const wchar_t *fmt;
for (j=0; int_tests[j].fmt; j++) {
i = swprintf(b, sizeof b, int_tests[j].fmt, int_tests[j].i);
if (i != wcslen(int_tests[j].expect)) {
- error("swprintf(b, sizeof b, \"%ls\", %d) returned %d wanted %d\n",
+ t_error("swprintf(b, sizeof b, \"%ls\", %d) returned %d wanted %d\n",
int_tests[j].fmt, int_tests[j].i, i, wcslen(int_tests[j].expect));
}
if (wcscmp(b, int_tests[j].expect) != 0)
- error("bad integer conversion: got \"%ls\", want \"%ls\"\n", b, int_tests[j].expect);
+ t_error("bad integer conversion: got \"%ls\", want \"%ls\"\n", b, int_tests[j].expect);
}
for (j=0; fp_tests[j].fmt; j++) {
i = swprintf(b, sizeof b, fp_tests[j].fmt, fp_tests[j].f);
if (i != wcslen(fp_tests[j].expect)) {
- error("swprintf(b, sizeof b, \"%ls\", %f) returned %d wanted %d\n",
+ t_error("swprintf(b, sizeof b, \"%ls\", %f) returned %d wanted %d\n",
fp_tests[j].fmt, fp_tests[j].f, i, wcslen(fp_tests[j].expect));
}
if (wcscmp(b, fp_tests[j].expect) != 0)
- error("bad floating-point conversion: got \"%ls\", want \"%ls\"\n", b, fp_tests[j].expect);
+ t_error("bad floating-point conversion: got \"%ls\", want \"%ls\"\n", b, fp_tests[j].expect);
}
- return test_status;
+ return t_status;
}
i = lrint(123456789.1f) & 0x7fffffff;
if (i != 123456792)
- error("lrint(123456789.1f)&0x7fffffff want 123456792 got %ld\n", i);
+ t_error("lrint(123456789.1f)&0x7fffffff want 123456792 got %ld\n", i);
i = lrint(123456789.1) & 0x7fffffff;
if (i != 123456789)
- error("lrint(123456789.1)&0x7fffffff want 123456789 got %ld\n", i);
+ t_error("lrint(123456789.1)&0x7fffffff want 123456789 got %ld\n", i);
if (sqrt(2.0f) != 1.41421353816986083984375)
- error("sqrt(2.0f) want 0x1.6a09e6p+0 got %a\n", sqrt(2.0f));
+ t_error("sqrt(2.0f) want 0x1.6a09e6p+0 got %a\n", sqrt(2.0f));
if (sqrt(2.0) != 1.414213562373095145474621858738828450441360)
- error("sqrt(2.0) want 0x1.6a09e667f3bcdp+0 got %a\n", sqrt(2.0));
+ t_error("sqrt(2.0) want 0x1.6a09e667f3bcdp+0 got %a\n", sqrt(2.0));
if (sqrt(2) != 1.414213562373095145474621858738828450441360)
- error("sqrt(2) want 0x1.6a09e667f3bcdp+0 got %a\n", sqrt(2.0));
+ t_error("sqrt(2) want 0x1.6a09e667f3bcdp+0 got %a\n", sqrt(2.0));
if (sizeof pow(sqrt(8),0.5f) != sizeof(double))
- error("sizeof pow(sqrt(8),0.5f) want %d got %d\n", (int)sizeof(double), (int)sizeof pow(sqrt(8),0.5f));
+ t_error("sizeof pow(sqrt(8),0.5f) want %d got %d\n", (int)sizeof(double), (int)sizeof pow(sqrt(8),0.5f));
if (sizeof pow(2.0,0.5) != sizeof(double))
- error("sizeof pow(2.0,0.5) want %d got %d\n", (int)sizeof(double), (int)sizeof pow(2.0,0.5));
+ t_error("sizeof pow(2.0,0.5) want %d got %d\n", (int)sizeof(double), (int)sizeof pow(2.0,0.5));
if (sizeof pow(2.0f,0.5f) != sizeof(float))
- error("sizeof pow(2.0f,0.5f) want %d got %d\n", (int)sizeof(float), (int)sizeof pow(2.0f,0.5f));
+ t_error("sizeof pow(2.0f,0.5f) want %d got %d\n", (int)sizeof(float), (int)sizeof pow(2.0f,0.5f));
if (sizeof pow(2.0,0.5+0*I) != sizeof(double complex))
- error("sizeof pow(2.0,0.5+0*I) want %d got %d\n", (int)sizeof(double complex), (int)sizeof pow(2.0,0.5+0*I));
+ t_error("sizeof pow(2.0,0.5+0*I) want %d got %d\n", (int)sizeof(double complex), (int)sizeof pow(2.0,0.5+0*I));
if (pow(2.0,0.5) != 1.414213562373095145474621858738828450441360)
- error("pow(2.0,0.5) want 0x1.6a09e667f3bcdp+0 got %a\n", pow(2.0,0.5));
+ t_error("pow(2.0,0.5) want 0x1.6a09e667f3bcdp+0 got %a\n", pow(2.0,0.5));
if (pow(2,0.5) != 1.414213562373095145474621858738828450441360)
- error("pow(2,0.5) want 0x1.6a09e667f3bcdp+0 got %a\n", pow(2,0.5));
+ t_error("pow(2,0.5) want 0x1.6a09e667f3bcdp+0 got %a\n", pow(2,0.5));
if (pow(2,0.5f) != 1.414213562373095145474621858738828450441360)
- error("pow(2,0.5f) want 0x1.6a09e667f3bcdp+0 got %a\n", pow(2,0.5f));
+ t_error("pow(2,0.5f) want 0x1.6a09e667f3bcdp+0 got %a\n", pow(2,0.5f));
- return test_status;
+ return t_status;
}
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
#include "test.h"
/* We use this instead of memcmp because some broken C libraries
#define TM_Y2038_1S TM(7,14,3,19,0,138,2,18,0)
#define TM_Y2038 TM(8,14,3,19,0,138,2,18,0)
-#define TEST_TM(r,x,m) (!tm_cmp((r),(x)) || \
- (error("%s failed:\n\tresult: %s\n\texpect: %s\n", \
- m, tm_str(r), tm_str(x)), 0) )
+static void sec2tm(time_t t, char *m)
+{
+ struct tm *tm;
+ time_t r;
+
+ errno = 0;
+ tm = gmtime(&t);
+ if (errno != 0)
+ t_error("%s: gmtime((time_t)%lld) should not set errno, got %s\n",
+ m, (long long)t, strerror(errno));
+ errno = 0;
+ r = mktime(tm);
+ if (errno != 0)
+ t_error("%s: mktime(%s) should not set errno, got %s\n",
+ m, tm_str(*tm), strerror(errno));
+ if (t != r)
+ t_error("%s: mktime(gmtime(%lld)) roundtrip failed: got %lld (gmtime is %s)\n",
+ m, (long long)t, (long long)r, tm_str(*tm));
+}
-#define TEST(r, f, x, m) ( \
- ((r) = (f)) == (x) || \
- (error("%s failed (" m ")\n", #f, r, x), 0) )
+static void tm2sec(struct tm *tm, int big, char *m)
+{
+ struct tm *r;
+ time_t t;
+ int overflow = big && (time_t)LLONG_MAX!=LLONG_MAX;
+
+ errno = 0;
+ t = mktime(tm);
+ if (overflow && t != -1)
+ t_error("%s: mktime(%s) expected -1, got (time_t)%ld\n",
+ m, tm_str(*tm), (long)t);
+ if (overflow && errno != EOVERFLOW)
+ t_error("%s: mktime(%s) expected EOVERFLOW (%s), got (%s)\n",
+ m, tm_str(*tm), strerror(EOVERFLOW), strerror(errno));
+ if (!overflow && t == -1)
+ t_error("%s: mktime(%s) expected success, got (time_t)-1\n",
+ m, tm_str(*tm));
+ if (!overflow && errno)
+ t_error("%s: mktime(%s) expected no error, got (%s)\n",
+ m, tm_str(*tm), strerror(errno));
+ r = gmtime(&t);
+ if (!overflow && tm_cmp(*r, *tm))
+ t_error("%s: gmtime(mktime(%s)) roundtrip failed: got %s\n",
+ m, tm_str(*tm), tm_str(*r));
+}
int main(void)
{
- struct tm tm, *tm_p;
time_t t;
putenv("TZ=GMT");
tzset();
+ tm2sec(&TM_EPOCH, 0, "gmtime(0)");
+ tm2sec(&TM_Y2038_1S, 0, "2038-1s");
+ tm2sec(&TM_Y2038, 1, "2038");
- t=0; tm_p = gmtime(&t);
- TEST_TM(*tm_p, TM_EPOCH, "gmtime(0)");
-
- tm = TM_Y2038_1S;
- t = mktime(&tm);
- tm = *(gmtime(&t));
- TEST_TM(*tm_p, TM_Y2038_1S, "mktime/gmtime(Y2038-1)");
-
- tm = TM_Y2038;
- t = mktime(&tm);
- tm = *(gmtime(&t));
- TEST_TM(*tm_p, TM_Y2038, "mktime/gmtime(Y2038)");
+ sec2tm(0, "EPOCH");
+ for (t = 1; t < 1000; t++)
+ sec2tm(t*100003, "EPOCH+eps");
/* FIXME: set a TZ var and check DST boundary conditions */
- return test_status;
+ return t_status;
}
for (i = 0; i < sizeof t/sizeof *t; i++) {
if (!t[i].name)
- error("name is not set for t[%d]\n", i);
+ t_error("name is not set for t[%d]\n", i);
if (t[i].addr & (t[i].align-1))
- error("bad alignment: %s, size: %u, align: %u, addr: 0x%lx\n",
+ t_error("bad alignment: %s, size: %u, align: %u, addr: 0x%lx\n",
t[i].name, t[i].size, t[i].align, t[i].addr);
}
- return test_status;
+ return t_status;
}
--- /dev/null
+$(N).LDLIBS := $(D)/tls_align_dso.so
+$(N)-static.LDLIBS := $(D)/tls_align_dso.o
+
+$(N): $(D)/tls_align_dso.so
+$(N)-static: $(D)/tls_align_dso.o
+
h = dlopen("./tls_align_dso.so", RTLD_LAZY);
if (!h)
- error("dlopen failed\n");
+ t_error("dlopen failed\n");
t = dlsym(h, "t");
if (!t)
- error("dlsym failed\n");
+ t_error("dlsym failed\n");
for (i = 0; i < 4; i++) {
if (!t[i].name)
- error("name is not set for t[%d]\n", i);
+ t_error("name is not set for t[%d]\n", i);
if (t[i].addr & (t[i].align-1))
- error("bad alignment: %s, size: %u, align: %u, addr: 0x%lx\n",
+ t_error("bad alignment: %s, size: %u, align: %u, addr: 0x%lx\n",
t[i].name, t[i].size, t[i].align, t[i].addr);
}
- return test_status;
+ return t_status;
}
--- /dev/null
+$(N).BINS=$(N)
+$(N).err: $(D)/tls_align_dso.so
--- /dev/null
+$(N).BINS:=
+$(N).LIBS:=$(N).so
static void *f(void *arg)
{
if (tls_fix != 23)
- error("fixed init failed: want 23 got %d\n", tls_fix);
+ t_error("fixed init failed: want 23 got %d\n", tls_fix);
if (tls_zero != 0)
- error("zero init failed: want 0 got %d\n", tls_zero);
+ t_error("zero init failed: want 0 got %d\n", tls_zero);
tls_fix++;
tls_zero++;
return 0;
}
-#define CHECK(f) do{ if(f) error("%s failed.\n", #f); }while(0)
+#define CHECK(f) do{ if(f) t_error("%s failed.\n", #f); }while(0)
#define length(a) (sizeof(a)/sizeof*(a))
int main()
int i, j;
if (tls_fix != 23)
- error("fixed init failed: want 23 got %d\n", tls_fix);
+ t_error("fixed init failed: want 23 got %d\n", tls_fix);
if (tls_zero != 0)
- error("zero init failed: want 0 got %d\n", tls_zero);
+ t_error("zero init failed: want 0 got %d\n", tls_zero);
for (j = 0; j < 2; j++) {
for (i = 0; i < length(t); i++) {
CHECK(pthread_join(t[i], 0));
}
- return test_status;
+ return t_status;
}
div = x / y;
mod = x % y;
if (div != t[i].div)
- error("udiv %llu/%llu want %llu got %llu\n", x, y, t[i].div, div);
+ t_error("udiv %llu/%llu want %llu got %llu\n", x, y, t[i].div, div);
if (mod != t[i].mod)
- error("umod %llu%%%llu want %llu got %llu\n", x, y, t[i].mod, mod);
+ t_error("umod %llu%%%llu want %llu got %llu\n", x, y, t[i].mod, mod);
}
- return test_status;
+ return t_status;
}
#define TEST(r, f, x, m) ( \
errno = 0, ((r) = (f)) == (x) || \
- (error("%s failed (" m ")\n", #f, r, x, strerror(errno)), 0) )
+ (t_error("%s failed (" m ")\n", #f, r, x, strerror(errno)), 0) )
#define TEST_S(s, x, m) ( \
!strcmp((s),(x)) || \
- (error("[%s] != [%s] (%s)\n", s, x, m), 0) )
+ (t_error("[%s] != [%s] (%s)\n", s, x, m), 0) )
int main(void)
{
TEST(i, !(f = tmpfile()), 0, "failed to create temp file %d!=%d (%s)");
- if (!f) return test_status;
+ if (!f) return t_status;
TEST(i, fprintf(f, "hello, world\n"), 13, "%d != %d (%m)");
TEST(i, fseek(f, 0, SEEK_SET), 0, "%d != %d (%m)");
TEST(i, fgetc(f), 'h', "'%c' != '%c'");
fclose(f);
- return test_status;
+ return t_status;
}
#define TEST(r, f, x, m) ( \
errno = 0, msg = #f, ((r) = (f)) == (x) || \
- (error("%s failed (" m ")\n", #f, r, x), 0) )
+ (t_error("%s failed (" m ")\n", #f, r, x), 0) )
#define TEST2(r, f, x, m) ( \
((r) = (f)) == (x) || \
- (error("%s failed (" m ")\n", msg, r, x), 0) )
+ (t_error("%s failed (" m ")\n", msg, r, x), 0) )
int main(void)
{
TEST(l, wcstol(s=L"123", &c, 37), 0, "%ld != %ld");
TEST2(i, c-s, 0, "wrong final position %d != %d");
TEST2(i, errno, EINVAL, "%d != %d");
- return test_status;
+ return t_status;
}
-CFLAGS+=-g -pipe -std=c99 -D_POSIX_C_SOURCE=200809L -Wall -Wno-unused-function -Wno-missing-braces
-CFLAGS+=-Wno-unknown-pragmas -fno-builtin -frounding-math
-CFLAGS+=-D_GNU_SOURCE -O0
-LDFLAGS+=-g -lm
-BUILD?=.
+all:
+%:
+ $(MAKE) -C ../.. src/math/$@
-SRC=$(sort $(wildcard *.c))
-OBJ=$(SRC:%.c=$(BUILD)/%.o)
-BINOBJ=$(filter-out $(BUILD)/util.o,$(OBJ))
-BIN=$(BINOBJ:.o=)
-
--include ../../config.mak
-
-all: $(BIN)
-run: all
- @N=0; for i in $(BIN);do ./$$i || N=$$((N+1)); done; [ "$$N" = 0 ] && echo PASS || echo FAILS: $$N
-clean:
- rm -f $(OBJ) $(BIN)
-
-$(BUILD):
- mkdir -p $@
-$(BIN): $(BUILD)/util.o
-$(OBJ): util.h | $(BUILD)
-$(BUILD)/%.o: %.c
- $(CC) $(CFLAGS) -c -o $@ $<
-%: %.c
-
-%: %.o
- $(CC) $(LDFLAGS) -o $@ $^
-
-.PRECIOUS: $(OBJ)
echo 3.14 |./gen sin
-using crlibm, ucb and a few random sanity test inputs
+using crlibm, ucb and a various other test inputs
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/acos.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/acosf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/acosh.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/acoshf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/asin.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/asinf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/asinh.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/asinhf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/atan.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct dd_d t[] = {
#include "ucb/atan2.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ff_f t[] = {
#include "ucb/atan2f.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ll_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/atanf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/atanh.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/atanhf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/cbrt.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/cbrtf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "ucb/ceil.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/ceilf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct dd_d t[] = {
#include "sanity/copysign.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ff_f t[] = {
#include "sanity/copysignf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ll_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/cos.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/cosf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/cosh.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/coshf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/erf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/erfc.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/erfcf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/erff.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/exp.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/exp10.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/exp10f.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/exp2.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/exp2f.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/expf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/expm1.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/expm1f.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "ucb/fabs.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/fabsf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct dd_d t[] = {
#include "sanity/fdim.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ff_f t[] = {
#include "sanity/fdimf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ll_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
-#include "util.h"
+#include "mtest.h"
static int test_status;
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "ucb/floor.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/floorf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ddd_d t[] = {
#include "sanity/fma.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct fff_f t[] = {
#include "sanity/fmaf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct lll_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct dd_d t[] = {
#include "sanity/fmax.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ff_f t[] = {
#include "sanity/fmaxf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ll_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct dd_d t[] = {
#include "sanity/fmin.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ff_f t[] = {
#include "sanity/fminf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ll_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct dd_d t[] = {
#include "ucb/fmod.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ff_f t[] = {
#include "ucb/fmodf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ll_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_di t[] = {
#include "sanity/frexp.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_fi t[] = {
#include "sanity/frexpf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_li t[] = {
#if LDBL_MANT_DIG == 53
tools for generating testcases and checking ulp error of math functions
+(needs cleanup)
gen: math functions implemented with mpfr
mgen: math functions from libm
check: compare input to libm and report errors
-# check asinh in the [0.125,0.5] domain over 100k points and report >1.5ulp errors
+check asinh in the [0.125,0.5] domain over 100k points and report >1.5ulp errors:
+
./rnd -a 0x1p-3 -b 0x1p-1 -n 100000 |./gen asinh |./check asinh 1.5
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct dd_d t[] = {
#include "ucb/hypot.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ff_f t[] = {
#include "ucb/hypotf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ll_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_i t[] = {
#include "sanity/ilogb.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_i t[] = {
#include "sanity/ilogbf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_i t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/j0.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/j0f.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/j1.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/j1f.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct di_d t[] = {
#include "sanity/jn.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct fi_f t[] = {
#include "sanity/jnf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct di_d t[] = {
#include "sanity/ldexp.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct fi_f t[] = {
#include "sanity/ldexpf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct li_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_di t[] = {
#include "sanity/lgamma.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_di t[] = {
#include "sanity/lgamma_r.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_fi t[] = {
#include "sanity/lgammaf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_fi t[] = {
#include "sanity/lgammaf_r.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_li t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_li t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_i t[] = {
#include "sanity/llrint.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_i t[] = {
#include "sanity/llrintf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_i t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_i t[] = {
#include "sanity/llround.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_i t[] = {
#include "sanity/llroundf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_i t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/log.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/log10.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/log10f.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/log1p.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/log1pf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/log2.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/log2f.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/logb.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/logbf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/logf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_i t[] = {
#include "sanity/lrint.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_i t[] = {
#include "sanity/lrintf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_i t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_i t[] = {
#include "sanity/lround.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_i t[] = {
#include "sanity/lroundf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_i t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_dd t[] = {
#include "sanity/modf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_ff t[] = {
#include "sanity/modff.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_ll t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/nearbyint.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/nearbyintf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct dd_d t[] = {
#include "sanity/nextafter.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ff_f t[] = {
#include "sanity/nextafterf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ll_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
// TODO: fix ldbl
static struct ll_l t[] = {
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
// TODO: separate ldbl dir
static struct ll_l t[] = {
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ll_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct dd_d t[] = {
#include "crlibm/pow.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/pow10.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/pow10f.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ff_f t[] = {
#include "ucb/powf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ll_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct dd_d t[] = {
#include "sanity/remainder.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ff_f t[] = {
#include "sanity/remainderf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ll_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct dd_di t[] = {
#include "sanity/remquo.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ff_fi t[] = {
#include "sanity/remquof.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ll_li t[] = {
#include "sanity/remquol.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/rint.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/rintf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/round.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/roundf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct dd_d t[] = {
#include "sanity/scalb.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct ff_f t[] = {
#include "sanity/scalbf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct di_d t[] = {
#include "sanity/scalbln.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct fi_f t[] = {
#include "sanity/scalblnf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct li_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct di_d t[] = {
#include "sanity/scalbn.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct fi_f t[] = {
#include "sanity/scalbnf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct li_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/sin.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_dd t[] = {
#include "sanity/sincos.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_ff t[] = {
#include "sanity/sincosf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_ll t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/sinf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/sinh.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/sinhf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "ucb/sqrt.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/sqrtf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "crlibm/tan.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/tanf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "ucb/tanh.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "ucb/tanhf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/tgamma.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/tgammaf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/trunc.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/truncf.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct l_l t[] = {
#if LDBL_MANT_DIG == 53
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/y0.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/y0f.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct d_d t[] = {
#include "sanity/y1.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct f_f t[] = {
#include "sanity/y1f.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct di_d t[] = {
#include "sanity/yn.h"
#include <stdint.h>
#include <stdio.h>
-#include "util.h"
+#include "mtest.h"
static struct fi_f t[] = {
#include "sanity/ynf.h"
--- /dev/null
+all:
+%:
+ $(MAKE) -C ../.. src/regression/$@
+
--- /dev/null
+// commit: 19e35c500bd2b5e6146e42705ab9b69c155a2006 2011-02-17
+// commit: 187fe29d5b89644b68cade75a34257a1c32a75f6 2011-02-17
+// non-standard musl specific behaviour
+// daemon should not fork in case of failure of chdir or open, but
+// since setsid and fork may still fail after fork this behaviour
+// is not very useful
+#define _BSD_SOURCE 1
+#include <string.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "test.h"
+
+int daemon(int, int);
+
+int main(void)
+{
+ int r, pid, fd[2], fdout, s;
+ char c;
+
+ r = pipe(fd);
+ if (r == -1) {
+ t_error("pipe failed: %s\n", strerror(errno));
+ return 1;
+ }
+ fdout = dup(1);
+ if (fdout == -1) {
+ t_error("dup(1) failed: %s\n", strerror(errno));
+ return 1;
+ }
+ r = fork();
+ if (r == -1) {
+ t_error("fork failed: %s\n", strerror(errno));
+ return 1;
+ }
+
+ if (r == 0) {
+ /* exhausting all fds makes open("/dev/null") fail in daemon */
+ t_fdfill();
+ pid = getpid();
+ errno = 0;
+ r = daemon(0, 0);
+ if (dup2(fdout,1) == -1) {
+ write(fdout, "ERROR:\n", 7);
+ t_error("failed to dup pipe fd for communicating results: %s\n", strerror(errno));
+ }
+ if (r != -1)
+ t_error("daemon should have failed\n");
+ if (errno != EMFILE)
+ t_error("daemon should have failed with %d [EMFILE] got %d [%s]\n", EMFILE, errno, strerror(errno));
+ if (getpid() != pid || getppid() == 1)
+ t_error("daemon forked despite failure: ppid is %d, pid is %d, old pid is %d\n",
+ getppid(), getpid(), pid);
+ if (write(fd[1], "1" + !t_status, 1) != 1)
+ t_error("write failed: %s\n", strerror(errno));
+ return t_status;
+ }
+ close(fd[1]);
+ if (waitpid(r, &s, 0) != r)
+ t_error("waitpid failed: %s\n", strerror(errno));
+ else if (!WIFEXITED(s))
+ t_error("child exited abnormally (signal %d)\n", WIFSIGNALED(s) ? WTERMSIG(s) : 0);
+ else if (WEXITSTATUS(s))
+ t_error("child exited with %d\n", WEXITSTATUS(s));
+ r = read(fd[0], &c, 1);
+ if (r == -1)
+ t_error("read failed: %s\n", strerror(errno));
+ else if (r == 0)
+ t_error("read failed: child did not send its exit status\n");
+ else if (c != 0)
+ t_error("child failed\n");
+
+ return t_status;
+}
--- /dev/null
+// commit: 26031da0f83a2a3ed52190077931ee6c18dfd689 2011-02-20
+// malloc(0) should return unique pointers
+#include <stdlib.h>
+#include "test.h"
+
+int main(void)
+{
+ void *p = malloc(0);
+ void *q = malloc(0);
+ void *r = malloc(0);
+ if (!p || !q || !r)
+ t_error("malloc(0) returned NULL\n");
+ if (p == q || p == r || q == r)
+ t_error("malloc(0) returned non-unique pointers: %p, %p, %p\n", p, q, r);
+ free(q);
+ free(p);
+ free(r);
+ return t_status;
+}
--- /dev/null
+// commit: 69ecbd0f3188be97f91cc0d6415836d23e88f7fc 2011-02-19
+// commit: 382584724308442f03f3d29f7fc6de9e9d140982 2011-06-12
+// mkdtemp should return -1 on bad template
+#define _BSD_SOURCE 1
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "test.h"
+
+char *mkdtemp(char *);
+
+#define S "/dev/null/fooXXXX"
+
+int main(void)
+{
+ char p[] = S;
+ char *r;
+
+ r = mkdtemp(p);
+ if (r)
+ t_error("mkdtemp(" S ") did not fail\n");
+ if (memcmp(p, S, sizeof p) != 0)
+ t_error("mkdtemp(" S ") modified the template: %s\n", p);
+ if (r == 0 && errno != EINVAL)
+ t_error("mkdtemp(" S ") failed with %d [%s] instead of %d [%s]\n",
+ errno, strerror(errno), EINVAL, strerror(EINVAL));
+ return t_status;
+}
--- /dev/null
+// commit: 2e6239dd064d201c6e1b0f589bae9ff27949d2eb 2011-02-19
+// commit: 382584724308442f03f3d29f7fc6de9e9d140982 2011-06-12
+// mkstemp should return -1 on bad template
+#define _BSD_SOURCE 1
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "test.h"
+
+int mkstemp(char *);
+
+#define S "/dev/null/fooXXXX"
+
+int main(void)
+{
+ char p[] = S;
+ int r;
+
+ r = mkstemp(p);
+ if (r != -1)
+ t_error("mkstemp(" S ") did not fail\n");
+ if (memcmp(p, S, sizeof p) != 0)
+ t_error("mkstemp(" S ") modified the template: %s\n", p);
+ if (r == -1 && errno != EINVAL)
+ t_error("mkstemp(" S ") failed with %d [%s] instead of %d [%s]\n",
+ errno, strerror(errno), EINVAL, strerror(EINVAL));
+ return t_status;
+}
--- /dev/null
+// commit: 5cbd76c6b05b381f269e0e204e10690d69f1d6ea 2011-02-16
+// commit: bdc9ed15651b70e89f83c5a9f7d1ba349e624503 2011-02-20
+// printf %n fmt
+#include <stdint.h>
+#include <stdio.h>
+#include "test.h"
+
+#define T(n,nfmt,fmt) do { \
+ if ((ret = sprintf(buf, "%256d%d" nfmt "%d", 1, 2, &n, 3)) != 258) \
+ t_error("expexted sprintf to write 258 chars, got %d\n", ret); \
+ if (n != 257) \
+ t_error("%%n format failed: wanted 257, got " fmt "\n", n); \
+} while(0)
+
+int main(void)
+{
+ char buf[1024];
+ int ret;
+ int i;
+ long l;
+ long long ll;
+ short h;
+ size_t z;
+ uintmax_t j;
+
+ T(i, "%n", "%d");
+ T(l, "%ln", "%ld");
+ T(ll, "%lln", "%lld");
+ T(h, "%hn", "%d");
+ T(z, "%zn", "%zd");
+ T(j, "%jn", "%jd");
+
+ return t_status;
+}
--- /dev/null
+// commit: 59666802fba592a59f2f4ea4dcb053287fd55826 2011-02-15
+// pthread_create should return EAGAIN on failure
+#include <pthread.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include "test.h"
+
+static void *start(void *arg)
+{
+ return 0;
+}
+
+int main(void)
+{
+ pthread_t td;
+ int r, arg;
+
+ r = t_vmfill(0, 0, 0);
+ if (r <= 0) {
+ t_error("fatal: vmfill has failed\n");
+ return 1;
+ }
+ r = pthread_create(&td, 0, start, &arg);
+ if (r == 0)
+ t_error("pthread_create succeeded\n");
+ else if (r != EAGAIN)
+ t_error("pthread_create should fail with EAGAIN but failed with %d (%s)\n", r, strerror(r));
+
+ return t_status;
+}
--- /dev/null
+// commit: 1a9a2ff7b0daf99100db53440a0b18b2801566ca 2011-02-13
+// pthread_exit should call cancelation handlers
+#include <pthread.h>
+#include <string.h>
+#include "test.h"
+
+#define TEST(r, f) if (((r)=(f))) t_error(#f " failed: %s\n", strerror(r))
+
+static void cleanup(void *arg)
+{
+ *(int *)arg = 1;
+}
+
+static void *start(void *arg)
+{
+ pthread_cleanup_push(cleanup, arg);
+ pthread_exit(0);
+ pthread_cleanup_pop(0);
+ return arg;
+}
+
+int main(void)
+{
+ pthread_t td;
+ void *status;
+ int arg = 0;
+ int r;
+
+ TEST(r, pthread_create(&td, 0, start, &arg));
+ TEST(r, pthread_join(td, &status));
+ if (status)
+ t_error("expected 0 thread exit status, got 0x%lx\n", (long)status);
+ if (arg != 1)
+ t_error("cleanup handler failed to run\n");
+ return t_status;
+}
--- /dev/null
+// commit: fb11b6b85e1e01daf17228be32d7f98b47517363 2011-02-19
+// pthread_exit should call dtors (even in the last thread)
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <pthread.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include "test.h"
+
+#define TEST(r, f) if (((r)=(f))) t_error(#f " failed: %s\n", strerror(r))
+#define TESTC(c, m) ( (c) || (t_error("%s failed (" m ")\n", #c), 0) )
+
+static pthread_key_t k;
+static int data;
+
+static void dtor(void *p)
+{
+ *(int *)p = 1;
+}
+
+static void *start(void *arg)
+{
+ if (pthread_setspecific(k, arg))
+ return arg;
+ return 0;
+}
+
+static void cleanup(void)
+{
+ TESTC(data == 1, "dtor was not run for the last thread");
+ _exit(t_status);
+}
+
+static void die(void)
+{
+ _exit(1);
+}
+
+int main(void)
+{
+ pthread_t td;
+ int r, arg=0, pid;
+ void *res;
+
+ // test if atexit handlers are run after pthread_exit
+ // (early musl failed this test)
+ pid = fork();
+ switch (pid) {
+ case -1:
+ t_error("fork failed: %s\n", strerror(errno));
+ return 1;
+ case 0:
+ atexit(die);
+ pthread_exit(0);
+ default:
+ if (waitpid(pid, &r, 0) != pid) {
+ t_error("waitpid failed: %s\n", strerror(errno));
+ return 1;
+ }
+ if (!WIFEXITED(r) || WEXITSTATUS(r) != 1) {
+ t_error("atexit handler was not run after last thread exited"
+ " (exited=%d, signal=%d, status=%d, want exit status=1)\n",
+ WIFEXITED(r), !WIFEXITED(r)&&WIFSIGNALED(r)?WTERMSIG(r):0, WIFEXITED(r)?WEXITSTATUS(r):0);
+ return 1;
+ }
+ }
+
+ // dtor should set tsd (arg and data) from 0 to 1
+ if (atexit(cleanup)) {
+ t_error("atexit failed\n");
+ return 1;
+ }
+ TEST(r, pthread_key_create(&k, dtor));
+ TEST(r, pthread_setspecific(k, &data));
+ TEST(r, pthread_create(&td, 0, start, &arg));
+ TEST(r, pthread_join(td, &res));
+ TESTC(res == 0, "pthread_setspecific failed in thread");
+ TESTC(arg == 1, "dtor failed to run");
+ TESTC(data == 0, "tsd in main thread is corrupted");
+ TESTC(pthread_getspecific(k) == &data, "tsd in main thread is corrupted");
+ pthread_exit(0);
+}
--- /dev/null
+// commit: 5efc6af4ebb9d50eb978d0338835544fdfea0396 2011-04-25
+// scanf misreports bytes consumed when EOF is hit (or null for sscanf)
+#include <stdio.h>
+#include "test.h"
+
+int main(void)
+{
+ char buf[] = { 'a', 'a', 0 };
+ char dest[3];
+ int read_count;
+ int n;
+
+ n = sscanf(buf, "%s%n", dest, &read_count);
+ if(n != 1)
+ t_error("sscanf matched 1 input items but returned %d\n", n);
+ if(read_count != 2)
+ t_error("sscanf consumed 2 bytes but reported %d\n", read_count);
+ return t_status;
+}
--- /dev/null
+// commit: 5efc6af4ebb9d50eb978d0338835544fdfea0396 2011-04-25
+// scanf misreports literal match as input failure when reading EOF (null for sscanf)
+#include <stdio.h>
+#include "test.h"
+
+int main(void)
+{
+ char buf[] = { 0 };
+ int match_count;
+
+ match_count = sscanf(buf, "a");
+ if(match_count != EOF)
+ t_error("scanf reported match failure instead of input failure on literal EOF match\n");
+
+ return t_status;
+}
--- /dev/null
+// commit: ef5507867b59d19f21437970e87b5d0415c07b2e 2013-06-22
+// scanf should not append null byte after scanning %c
+#include <stdio.h>
+#include "test.h"
+
+int main(void)
+{
+ char dst[] = { 'a', 'a' };
+ char src[] = { 'b', 'b' };
+
+ if (sscanf(src, "%c", dst) != 1)
+ t_error("sscanf %%c failed\n");
+ if (dst[1] != 'a')
+ t_error("scanf clobbered the char buffer for %%c conversion\n");
+ return t_status;
+}
--- /dev/null
+// commit: a49c119276742d7d212fb88f83a8f559ca549e72 2011-02-19
+// commit: 96f2197494791f5884c01b5caa908074cc7e90a6 2011-02-20
+// commit: 23815f88df6c45247f3755dc7857f4013264c04f 2013-07-18
+// implementation signals should not be masked
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include "test.h"
+
+int main(void)
+{
+ sigset_t s;
+ int i;
+
+ sigemptyset(&s);
+ for (i = 32; i < SIGRTMIN; i++) {
+ sigaddset(&s, i);
+ if (sigismember(&s, i) == 1)
+ t_error("sigaddset(&s, %d) set implementation internal rt signal\n", i);
+ }
+ if (sigprocmask(SIG_BLOCK, &s, 0))
+ t_error("blocking signals failed: %s\n", strerror(errno));
+ if (sigprocmask(SIG_BLOCK, 0, &s))
+ t_error("querying sigmask failed: %s\n", strerror(errno));
+ for (i = 32; i < SIGRTMIN; i++)
+ if (sigismember(&s, i) == 1)
+ t_error("implementation internal rt signal %d can be blocked\n", i);
+ return t_status;
+}
--- /dev/null
+// commit: dc3776d445957cd3ea4a682db518701b93d34292 2011-02-13
+// sigreturn crash
+#include <signal.h>
+
+static volatile sig_atomic_t x;
+
+void handler(int s)
+{
+ x = 1;
+}
+
+int main(void)
+{
+ signal(SIGINT, handler);
+ if (raise(SIGINT))
+ return 2;
+ if (x != 1)
+ return 1;
+ return 0;
+}
--- /dev/null
+// commit: e98136207ad1a6df1cdc1578e4ad56f8f0db4047 2011-05-22
+#include <wchar.h>
+#include "test.h"
+
+int main(void)
+{
+ wchar_t dst[] = { 'a', 'a' };
+ wchar_t src[] = { 0, 'b' };
+
+ wcsncpy(dst, src, 1);
+ if(dst[1] != 'a')
+ t_error("wcsncpy copied more than N\n");
+ return t_status;
+}