mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 14:58:30 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
29
libc/testlib/almostequal.c
Normal file
29
libc/testlib/almostequal.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
/* ┌sign
|
||||
│ ┌exponent
|
||||
│ │ ┌fraction
|
||||
│ │ │
|
||||
│┌┴────────┐┌┴─────────────────────────────────────────────────┐*/
|
||||
#define SGN 0b1000000000000000000000000000000000000000000000000000000000000000lu
|
||||
#define EXP 0b0111111111110000000000000000000000000000000000000000000000000000lu
|
||||
#define FAC 0b0000000000001111111111111111111111111111111111111111111111111111lu
|
29
libc/testlib/almostequalf.c
Normal file
29
libc/testlib/almostequalf.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
/* ┌sign
|
||||
│ ┌exponent
|
||||
│ │ ┌fraction
|
||||
│ │ │
|
||||
│┌┴─────┐┌┴────────────────────┐*/
|
||||
#define BINARY32_SIGN 0b10000000000000000000000000000000u
|
||||
#define BINARY32_EXPO 0b01111111100000000000000000000000u
|
||||
#define BINARY32_FRAC 0b00000000011111111111111111111111u
|
29
libc/testlib/almostequallongdouble.c
Normal file
29
libc/testlib/almostequallongdouble.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
#define EPSILON 0.0000000000001L
|
||||
|
||||
testonly bool testlib_almostequallongdouble(long double x, long double y) {
|
||||
/* TODO(jart): This algorithm has to be binary. */
|
||||
if (isnan(x) || isnan(y)) return false;
|
||||
return fabsl(x - y) <= EPSILON;
|
||||
}
|
43
libc/testlib/bench.S
Normal file
43
libc/testlib/bench.S
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
|
||||
yoink __FILE__
|
||||
yoink testlib_runallbenchmarks
|
||||
|
||||
/ Decentralized section for benchmark registration.
|
||||
/
|
||||
/ @see ape/ape.lds
|
||||
.section .piro.relo.sort.bench.1,"aw",@nobits
|
||||
.type __bench_start,@object
|
||||
.type __bench_end,@object
|
||||
.globl __bench_start,__bench_end
|
||||
.hidden __bench_start,__bench_end
|
||||
.byte 0
|
||||
.align __SIZEOF_POINTER__
|
||||
__bench_start:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .piro.relo.sort.bench.3,"aw",@nobits
|
||||
__bench_end:
|
||||
.quad 0
|
||||
.previous
|
29
libc/testlib/bench.h
Normal file
29
libc/testlib/bench.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_BENCH_H_
|
||||
#define COSMOPOLITAN_LIBC_BENCH_H_
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/nexgen32e/bench.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview Microbenchmarking tools.
|
||||
*/
|
||||
|
||||
#define BENCHLOOP(START, STOP, N, INIT, EXPR) \
|
||||
({ \
|
||||
int Iter, Count; \
|
||||
long double Average, Sample, Time1, Time2; \
|
||||
for (Average = 1.0, Iter = 1, Count = (N); Iter < Count; ++Iter) { \
|
||||
INIT; \
|
||||
Time1 = START(); \
|
||||
EXPR; \
|
||||
Time2 = STOP(); \
|
||||
Sample = Time2 - Time1; \
|
||||
Average += (Sample - Average) / Iter; \
|
||||
} \
|
||||
Average; \
|
||||
})
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_BENCH_H_ */
|
60
libc/testlib/benchrunner.c
Normal file
60
libc/testlib/benchrunner.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/kntprioritycombos.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/mlock.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
double g_avx2_juiceup_doubles_[4] aligned(32);
|
||||
unsigned long long g_avx2_juiceup_quadwords_[4] aligned(32);
|
||||
|
||||
void testlib_benchwarmup(void) {
|
||||
/* get mathematical parts of cpu juiced up */
|
||||
if (X86_HAVE(AVX2) && X86_HAVE(FMA)) {
|
||||
asm("vmovdqa\t%1,%%ymm0\n\t"
|
||||
"vpmaddwd\t(%2),%%ymm0,%%ymm0\n\t"
|
||||
"vmovdqa\t%%ymm0,%0\n\t"
|
||||
"vzeroall"
|
||||
: "=m"(g_avx2_juiceup_quadwords_)
|
||||
: "m"(g_avx2_juiceup_quadwords_), "r"(&_base[0]));
|
||||
asm("vmovapd\t%1,%%ymm1\n\t"
|
||||
"vfmadd132pd\t(%2),%%ymm1,%%ymm1\n\t"
|
||||
"vmovapd\t%%ymm1,%0\n\t"
|
||||
"vzeroall"
|
||||
: "=m"(g_avx2_juiceup_doubles_)
|
||||
: "m"(g_avx2_juiceup_doubles_), "r"(&_base[32]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all benchmark functions in sorted order.
|
||||
*
|
||||
* @see BENCH()
|
||||
*/
|
||||
void testlib_runallbenchmarks(void) {
|
||||
peekall();
|
||||
mlockall(MCL_CURRENT);
|
||||
nice(-1);
|
||||
g_loglevel = kLogWarn;
|
||||
testlib_runtestcases(__bench_start, __bench_end, testlib_benchwarmup);
|
||||
}
|
41
libc/testlib/binequals.c
Normal file
41
libc/testlib/binequals.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
/**
|
||||
* Tests that raw memory is equal to visual representation, e.g.
|
||||
*
|
||||
* testlib_binequals(u" ☺☻♥", "\0\1\2\3", -1ul);
|
||||
*
|
||||
* @see libc/nexgen32e/kCp437.S
|
||||
*/
|
||||
testonly bool testlib_binequals(const char16_t *want, const void *got,
|
||||
size_t n) {
|
||||
size_t i;
|
||||
const unsigned char *p = (const unsigned char *)got;
|
||||
if (!got) return false;
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (!want[i]) break;
|
||||
if (i == n) break;
|
||||
if (want[i] != kCp437[p[i]]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
41
libc/testlib/combo.S
Normal file
41
libc/testlib/combo.S
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Decentralized section for test combo registration.
|
||||
/
|
||||
/ @see ape/ape.lds
|
||||
.section .piro.relo.sort.combo.1,"aw",@nobits
|
||||
.type __combo_start,@object
|
||||
.type __combo_end,@object
|
||||
.globl __combo_start,__combo_end
|
||||
.hidden __combo_start,__combo_end
|
||||
.byte 0
|
||||
.align __SIZEOF_POINTER__
|
||||
__combo_start:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .piro.relo.sort.combo.3,"aw",@nobits
|
||||
__combo_end:
|
||||
.quad 0
|
||||
.previous
|
100
libc/testlib/comborunner.c
Normal file
100
libc/testlib/comborunner.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
struct ComboGroup {
|
||||
unsigned entry;
|
||||
unsigned i;
|
||||
unsigned n;
|
||||
};
|
||||
|
||||
struct ComboProduct {
|
||||
unsigned n;
|
||||
struct ComboGroup groups[];
|
||||
};
|
||||
|
||||
mallocesque testonly struct ComboProduct *testlib_setupcomboproduct(
|
||||
const struct TestFixture *start, const struct TestFixture *end) {
|
||||
unsigned i, j, entrycount;
|
||||
struct ComboProduct *product;
|
||||
entrycount = testlib_countfixtures(start, end);
|
||||
product = calloc(
|
||||
sizeof(struct ComboProduct) + entrycount * sizeof(struct ComboGroup), 1);
|
||||
for (j = i = 0; i < entrycount; ++i) {
|
||||
if (j && strcmp(start[product->groups[j - 1].entry].group,
|
||||
start[i].group) == 0) {
|
||||
product->groups[j - 1].n++;
|
||||
} else {
|
||||
++j;
|
||||
product->groups[j - 1].entry = i;
|
||||
product->groups[j - 1].n = 1;
|
||||
}
|
||||
}
|
||||
product->n = j;
|
||||
return product;
|
||||
}
|
||||
|
||||
static testonly void testlib_describecombo(struct ComboProduct *product,
|
||||
const struct TestFixture *combos) {
|
||||
char *p = &g_fixturename[0];
|
||||
char *pe = p + sizeof(g_fixturename);
|
||||
for (unsigned i = 0; i < product->n && p < pe; ++i) {
|
||||
const char *sep = i ? ", " : "";
|
||||
const struct TestFixture *e =
|
||||
&combos[product->groups[i].entry + product->groups[i].i];
|
||||
p += max(0, snprintf(p, pe - p, "%s%s=%s", sep, e->group, e->name));
|
||||
}
|
||||
}
|
||||
|
||||
static testonly void testlib_callcombos(struct ComboProduct *product,
|
||||
const struct TestFixture *combos,
|
||||
testfn_t *test_start,
|
||||
testfn_t *test_end) {
|
||||
for (;;) {
|
||||
testlib_describecombo(product, combos);
|
||||
for (unsigned i = 0; i < product->n; ++i) {
|
||||
combos[product->groups[i].entry + product->groups[i].i].fn();
|
||||
}
|
||||
for (unsigned i = product->n;; --i) {
|
||||
if (!i) return;
|
||||
if (++product->groups[i - 1].i < product->groups[i - 1].n) break;
|
||||
product->groups[i - 1].i = 0;
|
||||
}
|
||||
testlib_runtestcases(test_start, test_end, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs Cartesian product of COMBO() fixtures registered with linker.
|
||||
* @see ape/ape.lds
|
||||
* @see libc/testlib/testlib.h
|
||||
*/
|
||||
testonly void testlib_runcombos(testfn_t *test_start, testfn_t *test_end,
|
||||
const struct TestFixture *combo_start,
|
||||
const struct TestFixture *combo_end) {
|
||||
struct ComboProduct *product;
|
||||
product = testlib_setupcomboproduct(combo_start, combo_end);
|
||||
testlib_callcombos(product, combo_start, test_start, test_end);
|
||||
free(product);
|
||||
}
|
28
libc/testlib/contains.c
Normal file
28
libc/testlib/contains.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
testonly bool testlib_contains(size_t cw, const void *s, const void *needle) {
|
||||
if (s == needle) return true;
|
||||
if (!s || !needle) return false;
|
||||
return sizeof(cw) == sizeof(char16_t) ? !!strstr16(s, needle)
|
||||
: !!strstr(s, needle);
|
||||
}
|
29
libc/testlib/endswith.c
Normal file
29
libc/testlib/endswith.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
testonly bool testlib_endswith(size_t cw, const void *s, const void *suffix) {
|
||||
if (s == suffix) return true;
|
||||
if (!s || !suffix) return false;
|
||||
return cw == sizeof(wchar_t) ? wcsendswith(s, suffix)
|
||||
: cw == sizeof(char16_t) ? endswith16(s, suffix)
|
||||
: endswith(s, suffix);
|
||||
}
|
29
libc/testlib/ezbench.h
Normal file
29
libc/testlib/ezbench.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_TESTLIB_EZBENCH_H_
|
||||
#define COSMOPOLITAN_LIBC_TESTLIB_EZBENCH_H_
|
||||
#include "libc/macros.h"
|
||||
#include "libc/testlib/bench.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define EZBENCH(INIT, EXPR) EZBENCH2(#EXPR, INIT, EXPR)
|
||||
#define EZBENCH2(NAME, INIT, EXPR) \
|
||||
do { \
|
||||
uint64_t Control, Speculative, MemoryStrict; \
|
||||
Control = __testlib_ezbenchcontrol(); \
|
||||
INIT; \
|
||||
EXPR; \
|
||||
Speculative = BENCHLOOP(__startbench, __endbench, 128, INIT, (EXPR)); \
|
||||
MemoryStrict = BENCHLOOP(__startbench_m, __endbench_m, 8, ({ \
|
||||
INIT; \
|
||||
thrashcodecache(); \
|
||||
}), \
|
||||
(EXPR)); \
|
||||
Control = MIN(Control, MIN(Speculative, MemoryStrict)); \
|
||||
__testlib_ezbenchreport(NAME, Speculative - Control, \
|
||||
MemoryStrict - Control); \
|
||||
} while (0)
|
||||
|
||||
void __testlib_ezbenchreport(const char *, uint64_t, uint64_t);
|
||||
uint64_t __testlib_ezbenchcontrol(void);
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_TESTLIB_EZBENCH_H_ */
|
25
libc/testlib/ezbenchcontrol.c
Normal file
25
libc/testlib/ezbenchcontrol.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/bench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
uint64_t __testlib_ezbenchcontrol(void) {
|
||||
return BENCHLOOP(__startbench, __endbench, 128, donothing, (void)0);
|
||||
}
|
35
libc/testlib/ezbenchreport.c
Normal file
35
libc/testlib/ezbenchreport.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
STATIC_YOINK("ntoa");
|
||||
STATIC_YOINK("stoa");
|
||||
|
||||
void __testlib_ezbenchreport(const char *form, uint64_t c1, uint64_t c2) {
|
||||
uint64_t ns1, ns2;
|
||||
ns1 = lrintl(converttickstonanos(c1));
|
||||
ns2 = lrintl(converttickstonanos(c2));
|
||||
(fprintf)(stderr,
|
||||
VEIL("r", "%-30s l: %,10lu𝑐 %,10lu𝑛𝑠 m: %,10lu𝑐 %,10lu𝑛𝑠\n"),
|
||||
form, c1, ns1, c2, ns2);
|
||||
}
|
41
libc/testlib/fixture.S
Normal file
41
libc/testlib/fixture.S
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Decentralized section for test fixture registration.
|
||||
/
|
||||
/ @see ape/ape.lds
|
||||
.section .piro.relo.sort.fixture.1,"aw",@nobits
|
||||
.type __fixture_start,@object
|
||||
.type __fixture_end,@object
|
||||
.globl __fixture_start,__fixture_end
|
||||
.hidden __fixture_start,__fixture_end
|
||||
.byte 0
|
||||
.align __SIZEOF_POINTER__
|
||||
__fixture_start:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .piro.relo.sort.fixture.3,"aw",@nobits
|
||||
__fixture_end:
|
||||
.quad 0
|
||||
.previous
|
48
libc/testlib/fixturerunner.c
Normal file
48
libc/testlib/fixturerunner.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
testonly int testlib_countfixtures(const struct TestFixture *start,
|
||||
const struct TestFixture *end) {
|
||||
return ((intptr_t)end - (intptr_t)start) / sizeof(struct TestFixture);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs test cases for each FIXTURE() registered with the linker.
|
||||
* @see ape/ape.lds
|
||||
* @see libc/testlib/testlib.h
|
||||
*/
|
||||
testonly void testlib_runfixtures(testfn_t *test_start, testfn_t *test_end,
|
||||
const struct TestFixture *fixture_start,
|
||||
const struct TestFixture *fixture_end) {
|
||||
unsigned i, count;
|
||||
count = testlib_countfixtures(fixture_start, fixture_end);
|
||||
for (i = 0; i < count && !g_testlib_failed; ++i) {
|
||||
snprintf(g_fixturename, sizeof(g_fixturename), "%s_%s",
|
||||
fixture_start[i].group, fixture_start[i].name);
|
||||
__piro(PROT_READ | PROT_WRITE);
|
||||
fixture_start[i].fn();
|
||||
__piro(PROT_READ);
|
||||
testlib_runtestcases(test_start, test_end, NULL);
|
||||
}
|
||||
}
|
30
libc/testlib/formatbinaryasglyphs.c
Normal file
30
libc/testlib/formatbinaryasglyphs.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
testonly void testlib_formatbinaryasglyphs(const char16_t *want,
|
||||
const void *got, size_t n,
|
||||
char **out_v1, char **out_v2) {
|
||||
if (n == -1ul) n = strlen(want);
|
||||
*out_v1 = xasprintf("%`#.*hs", n, want);
|
||||
*out_v2 = xasprintf(" %`'#.*s", n, got);
|
||||
}
|
41
libc/testlib/formatbinaryashex.c
Normal file
41
libc/testlib/formatbinaryashex.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
testonly void testlib_formatbinaryashex(const char *want, const void *got,
|
||||
size_t n, char **out_v1,
|
||||
char **out_v2) {
|
||||
size_t i;
|
||||
uint8_t b;
|
||||
char *gothex;
|
||||
if (n == -1ul) n = strlen(want) / 2;
|
||||
gothex = xmalloc(n * 2 + 1);
|
||||
gothex[n * 2] = '\0';
|
||||
for (i = 0; i < n; ++i) {
|
||||
b = ((uint8_t *)got)[i];
|
||||
gothex[i * 2 + 0] = "0123456789abcdef"[(b >> 4) & 0xf];
|
||||
gothex[i * 2 + 1] = "0123456789abcdef"[(b >> 0) & 0xf];
|
||||
}
|
||||
*out_v1 = strdup(want);
|
||||
*out_v2 = gothex;
|
||||
}
|
27
libc/testlib/formatbool.c
Normal file
27
libc/testlib/formatbool.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
static const char kTrueStr[] = "true";
|
||||
static const char kFalseStr[] = "false";
|
||||
|
||||
char *testlib_formatbool(bool v) {
|
||||
return (/*unconst*/ char *)(v ? kTrueStr : kFalseStr);
|
||||
}
|
30
libc/testlib/formatfloat.c
Normal file
30
libc/testlib/formatfloat.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "third_party/dtoa/dtoa.h"
|
||||
|
||||
testonly char *testlib_formatfloat(long double x) {
|
||||
char dtoabuf[32];
|
||||
char *str = malloc(256);
|
||||
sprintf(str, "%Lf (%s)", x, g_fmt(dtoabuf, x));
|
||||
return str;
|
||||
}
|
39
libc/testlib/formatint.c
Normal file
39
libc/testlib/formatint.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
static size_t sbufi_;
|
||||
static char sbufs_[2][256];
|
||||
|
||||
nodiscard testonly char *testlib_formatint(intmax_t x) {
|
||||
char *str = sbufi_ < ARRAYLEN(sbufs_) ? sbufs_[sbufi_++] : malloc(256);
|
||||
char *p = str;
|
||||
p += sprintf(p, "%jd\t(or %#jx", x, x);
|
||||
if (0 <= x && x < 256) {
|
||||
p += sprintf(p, " or %#`c", (unsigned char)x);
|
||||
}
|
||||
*p++ = ')';
|
||||
*p++ = '\0';
|
||||
return str;
|
||||
}
|
25
libc/testlib/formatrange.c
Normal file
25
libc/testlib/formatrange.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
nodiscard testonly char *testlib_formatrange(intmax_t beg, intmax_t end) {
|
||||
return xasprintf("[%#jx,%#jx]", beg, end);
|
||||
}
|
43
libc/testlib/formatstr.c
Normal file
43
libc/testlib/formatstr.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/progn.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
* Turns string into code.
|
||||
*/
|
||||
nodiscard testonly char *testlib_formatstr(size_t cw, const void *s, int n) {
|
||||
switch (cw) {
|
||||
case 1:
|
||||
if (n == -1) n = s ? strlen(s) : 0;
|
||||
return xasprintf("%`'.*s", n, s);
|
||||
case 2:
|
||||
if (n == -1) n = s ? strlen16(s) : 0;
|
||||
return xasprintf("%`'.*hs", n, s);
|
||||
case 4:
|
||||
if (n == -1) n = s ? wcslen(s) : 0;
|
||||
return xasprintf("%`'.*ls", n, s);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
24
libc/testlib/globals.c
Normal file
24
libc/testlib/globals.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
char g_fixturename[256];
|
||||
unsigned g_testlib_ran;
|
||||
unsigned g_testlib_failed;
|
43
libc/testlib/hexequals.c
Normal file
43
libc/testlib/hexequals.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
/**
|
||||
* Tests that raw memory is equal to numeric representation, e.g.
|
||||
*
|
||||
* testlib_hexequals("00010203", "\0\1\2\3", -1ul);
|
||||
*
|
||||
* @see unhexstr()
|
||||
*/
|
||||
testonly bool testlib_hexequals(const char *want, const void *got, size_t n) {
|
||||
size_t i;
|
||||
const unsigned char *p = (const unsigned char *)got;
|
||||
if (!got) return false;
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (!want[i * 2]) break;
|
||||
if (i == n) break;
|
||||
if (p[i] != (unsigned char)(hextoint(want[i * 2 + 0]) * 16 +
|
||||
hextoint(want[i * 2 + 1]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
34
libc/testlib/hyperion.S
Normal file
34
libc/testlib/hyperion.S
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.rodata
|
||||
.yoink __FILE__
|
||||
|
||||
/ Nontrivial NUL-terminated string test vector.
|
||||
.align 1
|
||||
kHyperion:
|
||||
0: .incbin "libc/testlib/hyperion.txt"
|
||||
1: .byte 0
|
||||
.endobj kHyperion,globl
|
||||
|
||||
.align 8
|
||||
kHyperionSize:
|
||||
.quad 1b-0b
|
||||
.endobj kHyperionSize,globl
|
12
libc/testlib/hyperion.h
Normal file
12
libc/testlib/hyperion.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_TESTLIB_HYPERION_H_
|
||||
#define COSMOPOLITAN_LIBC_TESTLIB_HYPERION_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern size_t kHyperionSize;
|
||||
extern char kHyperion[];
|
||||
extern uint8_t kHyperionZip[];
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_TESTLIB_HYPERION_H_ */
|
547
libc/testlib/hyperion.txt
Normal file
547
libc/testlib/hyperion.txt
Normal file
|
@ -0,0 +1,547 @@
|
|||
The fall of Hyperion - a Dream
|
||||
John Keats
|
||||
|
||||
|
||||
CANTO I
|
||||
|
||||
Fanatics have their dreams, wherewith they weave
|
||||
A paradise for a sect; the savage too
|
||||
From forth the loftiest fashion of his sleep
|
||||
Guesses at Heaven; pity these have not
|
||||
Trac'd upon vellum or wild Indian leaf
|
||||
The shadows of melodious utterance.
|
||||
But bare of laurel they live, dream, and die;
|
||||
For Poesy alone can tell her dreams,
|
||||
With the fine spell of words alone can save
|
||||
Imagination from the sable charm
|
||||
And dumb enchantment. Who alive can say,
|
||||
'Thou art no Poet may'st not tell thy dreams?'
|
||||
Since every man whose soul is not a clod
|
||||
Hath visions, and would speak, if he had loved
|
||||
And been well nurtured in his mother tongue.
|
||||
Whether the dream now purpos'd to rehearse
|
||||
Be poet's or fanatic's will be known
|
||||
When this warm scribe my hand is in the grave.
|
||||
|
||||
Methought I stood where trees of every clime,
|
||||
Palm, myrtle, oak, and sycamore, and beech,
|
||||
With plantain, and spice blossoms, made a screen;
|
||||
In neighbourhood of fountains, by the noise
|
||||
Soft showering in my ears, and, by the touch
|
||||
Of scent, not far from roses. Turning round
|
||||
I saw an arbour with a drooping roof
|
||||
Of trellis vines, and bells, and larger blooms,
|
||||
Like floral censers swinging light in air;
|
||||
Before its wreathed doorway, on a mound
|
||||
Of moss, was spread a feast of summer fruits,
|
||||
Which, nearer seen, seem'd refuse of a meal
|
||||
By angel tasted or our Mother Eve;
|
||||
For empty shells were scattered on the grass,
|
||||
And grape stalks but half bare, and remnants more,
|
||||
Sweet smelling, whose pure kinds I could not know.
|
||||
Still was more plenty than the fabled horn
|
||||
Thrice emptied could pour forth, at banqueting
|
||||
For Proserpine return'd to her own fields,
|
||||
Where the white heifers low. And appetite
|
||||
More yearning than on earth I ever felt
|
||||
Growing within, I ate deliciously;
|
||||
And, after not long, thirsted, for thereby
|
||||
Stood a cool vessel of transparent juice
|
||||
Sipp'd by the wander'd bee, the which I took,
|
||||
And, pledging all the mortals of the world,
|
||||
And all the dead whose names are in our lips,
|
||||
Drank. That full draught is parent of my theme.
|
||||
No Asian poppy nor elixir fine
|
||||
Of the soon fading jealous Caliphat,
|
||||
No poison gender'd in close monkish cell
|
||||
To thin the scarlet conclave of old men,
|
||||
Could so have rapt unwilling life away.
|
||||
Among the fragrant husks and berries crush'd,
|
||||
Upon the grass I struggled hard against
|
||||
The domineering potion; but in vain:
|
||||
The cloudy swoon came on, and down I sunk
|
||||
Like a Silenus on an antique vase.
|
||||
How long I slumber'd 'tis a chance to guess.
|
||||
When sense of life return'd, I started up
|
||||
As if with wings; but the fair trees were gone,
|
||||
The mossy mound and arbour were no more:
|
||||
I look'd around upon the carved sides
|
||||
Of an old sanctuary with roof august,
|
||||
Builded so high, it seem'd that filmed clouds
|
||||
Might spread beneath, as o'er the stars of heaven;
|
||||
So old the place was, I remember'd none
|
||||
The like upon the earth: what I had seen
|
||||
Of grey cathedrals, buttress'd walls, rent towers,
|
||||
The superannuations of sunk realms,
|
||||
Or Nature's rocks toil'd hard in waves and winds,
|
||||
Seem'd but the faulture of decrepit things
|
||||
To that eternal domed monument.
|
||||
Upon the marble at my feet there lay
|
||||
Store of strange vessels and large draperies,
|
||||
Which needs had been of dyed asbestos wove,
|
||||
Or in that place the moth could not corrupt,
|
||||
So white the linen, so, in some, distinct
|
||||
Ran imageries from a sombre loom.
|
||||
All in a mingled heap confus'd there lay
|
||||
Robes, golden tongs, censer and chafing dish,
|
||||
Girdles, and chains, and holy jewelries.
|
||||
|
||||
Turning from these with awe, once more I rais'd
|
||||
My eyes to fathom the space every way;
|
||||
The embossed roof, the silent massy range
|
||||
Of columns north and south, ending in mist
|
||||
Of nothing, then to eastward, where black gates
|
||||
Were shut against the sunrise evermore.
|
||||
Then to the west I look'd, and saw far off
|
||||
An image, huge of feature as a cloud,
|
||||
At level of whose feet an altar slept,
|
||||
To be approach'd on either side by steps,
|
||||
And marble balustrade, and patient travail
|
||||
To count with toil the innumerable degrees.
|
||||
Towards the altar sober paced I went,
|
||||
Repressing haste, as too unholy there;
|
||||
And, coming nearer, saw beside the shrine
|
||||
One minist'ring; and there arose a flame.
|
||||
When in mid May the sickening East wind
|
||||
Shifts sudden to the south, the small warm rain
|
||||
Melts out the frozen incense from all flowers,
|
||||
And fills the air with so much pleasant health
|
||||
That even the dying man forgets his shroud;
|
||||
Even so that lofty sacrificial fire,
|
||||
Sending forth Maian incense, spread around
|
||||
Forgetfulness of everything but bliss,
|
||||
And clouded all the altar with soft smoke,
|
||||
From whose white fragrant curtains thus I heard
|
||||
Language pronounc'd: 'If thou canst not ascend
|
||||
'These steps, die on that marble where thou art.
|
||||
'Thy flesh, near cousin to the common dust,
|
||||
'Will parch for lack of nutriment thy bones
|
||||
'Will wither in few years, and vanish so
|
||||
'That not the quickest eye could find a grain
|
||||
'Of what thou now art on that pavement cold.
|
||||
'The sands of thy short life are spent this hour,
|
||||
'And no hand in the universe can turn
|
||||
'Thy hourglass, if these gummed leaves be burnt
|
||||
'Ere thou canst mount up these immortal steps.'
|
||||
I heard, I look'd: two senses both at once,
|
||||
So fine, so subtle, felt the tyranny
|
||||
Of that fierce threat and the hard task proposed.
|
||||
Prodigious seem'd the toil, the leaves were yet
|
||||
Burning when suddenly a palsied chill
|
||||
Struck from the paved level up my limbs,
|
||||
And was ascending quick to put cold grasp
|
||||
Upon those streams that pulse beside the throat:
|
||||
I shriek'd; and the sharp anguish of my shriek
|
||||
Stung my own ears I strove hard to escape
|
||||
The numbness; strove to gain the lowest step.
|
||||
Slow, heavy, deadly was my pace: the cold
|
||||
Grew stifling, suffocating, at the heart;
|
||||
And when I clasp'd my hands I felt them not.
|
||||
One minute before death, my iced foot touch'd
|
||||
The lowest stair; and as it touch'd, life seem'd
|
||||
To pour in at the toes: I mounted up,
|
||||
As once fair angels on a ladder flew
|
||||
From the green turf to Heaven. 'Holy Power,'
|
||||
Cried I, approaching near the horned shrine,
|
||||
'What am I that should so be saved from death?
|
||||
'What am I that another death come not
|
||||
'To choke my utterance sacrilegious here?'
|
||||
Then said the veiled shadow 'Thou hast felt
|
||||
'What 'tis to die and live again before
|
||||
'Thy fated hour. That thou hadst power to do so
|
||||
'Is thy own safety; thou hast dated on
|
||||
'Thy doom.' 'High Prophetess,' said I, 'purge off,
|
||||
'Benign, if so it please thee, my mind's film.'
|
||||
'None can usurp this height,' return'd that shade,
|
||||
'But those to whom the miseries of the world
|
||||
'Are misery, and will not let them rest.
|
||||
'All else who find a haven in the world,
|
||||
'Where they may thoughtless sleep away their days,
|
||||
'If by a chance into this fane they come,
|
||||
'Rot on the pavement where thou rottedst half.'
|
||||
'Are there not thousands in the world,' said I,
|
||||
Encourag'd by the sooth voice of the shade,
|
||||
'Who love their fellows even to the death;
|
||||
'Who feel the giant agony of the world;
|
||||
'And more, like slaves to poor humanity,
|
||||
'Labour for mortal good? I sure should see
|
||||
'Other men here; but I am here alone.'
|
||||
'Those whom thou spak'st of are no vision'ries,'
|
||||
Rejoin'd that voice; 'they are no dreamers weak;
|
||||
'They seek no wonder but the human face,
|
||||
'No music but a happy noted voice;
|
||||
'They come not here, they have no thought to come;
|
||||
'And thou art here, for thou art less than they:
|
||||
'What benefit canst thou do, or all thy tribe,
|
||||
'To the great world? Thou art a dreaming thing,
|
||||
'A fever of thyself think of the Earth;
|
||||
'What bliss even in hope is there for thee?
|
||||
'What haven? every creature hath its home;
|
||||
'Every sole man hath days of joy and pain,
|
||||
'Whether his labours be sublime or low
|
||||
'The pain alone; the joy alone; distinct:
|
||||
'Only the dreamer venoms all his days,
|
||||
'Bearing more woe than all his sins deserve.
|
||||
'Therefore, that happiness be somewhat shar'd,
|
||||
'Such things as thou art are admitted oft
|
||||
'Into like gardens thou didst pass erewhile,
|
||||
'And suffer'd in these temples: for that cause
|
||||
'Thou standest safe beneath this statue's knees.'
|
||||
'That I am favour'd for unworthiness,
|
||||
'By such propitious parley medicin'd
|
||||
'In sickness not ignoble, I rejoice,
|
||||
'Aye, and could weep for love of such award.'
|
||||
So answer'd I, continuing, 'If it please,
|
||||
'Majestic shadow, tell me: sure not all
|
||||
'Those melodies sung into the world's ear
|
||||
'Are useless: sure a poet is a sage;
|
||||
'A humanist, physician to all men.
|
||||
'That I am none I feel, as vultures feel
|
||||
'They are no birds when eagles are abroad.
|
||||
'What am I then? Thou spakest of my tribe:
|
||||
'What tribe?' The tall shade veil'd in drooping white
|
||||
Then spake, so much more earnest, that the breath
|
||||
Moved the thin linen folds that drooping hung
|
||||
About a golden censer from the hand
|
||||
Pendent. 'Art thou not of the dreamer tribe?
|
||||
'The poet and the dreamer are distinct,
|
||||
'Diverse, sheer opposite, antipodes.
|
||||
'The one pours out a balm upon the world,
|
||||
'The other vexes it.' Then shouted I
|
||||
Spite of myself, and with a Pythia's spleen,
|
||||
'Apollo! faded! O far flown Apollo!
|
||||
'Where is thy misty pestilence to creep
|
||||
'Into the dwellings, through the door crannies
|
||||
'Of all mock lyrists, large self worshipers,
|
||||
'And careless Hectorers in proud bad verse.
|
||||
'Though I breathe death with them it will be life
|
||||
'To see them sprawl before me into graves.
|
||||
'Majestic shadow, tell me where I am,
|
||||
'Whose altar this; for whom this incense curls;
|
||||
'What image this whose face I cannot see,
|
||||
'For the broad marble knees; and who thou art,
|
||||
'Of accent feminine so courteous?'
|
||||
|
||||
Then the tall shade, in drooping linens veil'd,
|
||||
Spoke out, so much more earnest, that her breath
|
||||
Stirr'd the thin folds of gauze that drooping hung
|
||||
About a golden censer from her hand
|
||||
Pendent; and by her voice I knew she shed
|
||||
Long treasured tears. 'This temple, sad and lone,
|
||||
'Is all spar'd from the thunder of a war
|
||||
'Foughten long since by giant hierarchy
|
||||
'Against rebellion: this old image here,
|
||||
'Whose carved features wrinkled as he fell,
|
||||
'Is Saturn's; I Moneta, left supreme
|
||||
'Sole priestess of this desolation.'
|
||||
I had no words to answer, for my tongue,
|
||||
Useless, could find about its roofed home
|
||||
No syllable of a fit majesty
|
||||
To make rejoinder to Moneta's mourn.
|
||||
There was a silence, while the altar's blaze
|
||||
Was fainting for sweet food: I look'd thereon,
|
||||
And on the paved floor, where nigh were piled
|
||||
Faggots of cinnamon, and many heaps
|
||||
Of other crisped spice wood then again
|
||||
I look'd upon the altar, and its horns
|
||||
Whiten'd with ashes, and its lang'rous flame,
|
||||
And then upon the offerings again;
|
||||
And so by turns till sad Moneta cried,
|
||||
'The sacrifice is done, but not the less
|
||||
'Will I be kind to thee for thy good will.
|
||||
'My power, which to me is still a curse,
|
||||
'Shall be to thee a wonder; for the scenes
|
||||
'Still swooning vivid through my globed brain
|
||||
'With an electral changing misery
|
||||
'Thou shalt with those dull mortal eyes behold,
|
||||
'Free from all pain, if wonder pain thee not.'
|
||||
As near as an immortal's sphered words
|
||||
Could to a mother's soften, were these last:
|
||||
And yet I had a terror of her robes,
|
||||
And chiefly of the veils, that from her brow
|
||||
Hung pale, and curtain'd her in mysteries
|
||||
That made my heart too small to hold its blood.
|
||||
This saw that G-ddess, and with sacred hand
|
||||
Parted the veils. Then saw I a wan face,
|
||||
Not pin'd by human sorrows, but bright blanch'd
|
||||
By an immortal sickness which kills not;
|
||||
It works a constant change, which happy death
|
||||
Can put no end to; deathwards progressing
|
||||
To no death was that visage; it had pass'd
|
||||
The lily and the snow; and beyond these
|
||||
I must not think now, though I saw that face
|
||||
But for her eyes I should have fled away.
|
||||
They held me back, with a benignant light
|
||||
Soft mitigated by divinest lids
|
||||
Half closed, and visionless entire they seem'd
|
||||
Of all external things; they saw me not,
|
||||
But in blank splendour beam'd like the mild moon,
|
||||
Who comforts those she sees not, who knows not
|
||||
What eyes are upward cast. As I had found
|
||||
A grain of gold upon a mountain side,
|
||||
And twing'd with avarice strain'd out my eyes
|
||||
To search its sullen entrails rich with ore,
|
||||
So at the view of sad Moneta's brow
|
||||
I ach'd to see what things the hollow brain
|
||||
Behind enwombed: what high tragedy
|
||||
In the dark secret chambers of her skull
|
||||
Was acting, that could give so dread a stress
|
||||
To her cold lips, and fill with such a light
|
||||
Her planetary eyes, and touch her voice
|
||||
With such a sorrow 'Shade of Memory!'
|
||||
Cried I, with act adorant at her feet,
|
||||
'By all the gloom hung round thy fallen house,
|
||||
'By this last temple, by the golden age,
|
||||
'By great Apollo, thy dear Foster Child,
|
||||
'And by thyself, forlorn divinity,
|
||||
'The pale Omega of a withered race,
|
||||
'Let me behold, according as thou saidst,
|
||||
'What in thy brain so ferments to and fro!'
|
||||
No sooner had this conjuration pass'd
|
||||
My devout lips, than side by side we stood
|
||||
(Like a stunt bramble by a solemn pine)
|
||||
Deep in the shady sadness of a vale,
|
||||
Far sunken from the healthy breath of morn,
|
||||
Far from the fiery noon and eve's one star.
|
||||
Onward I look'd beneath the gloomy boughs,
|
||||
And saw, what first I thought an image huge,
|
||||
Like to the image pedestal'd so high
|
||||
In Saturn's temple. Then Moneta's voice
|
||||
Came brief upon mine ear 'So Saturn sat
|
||||
When he had lost his realms ' whereon there grew
|
||||
A power within me of enormous ken
|
||||
To see as a g-d sees, and take the depth
|
||||
Of things as nimbly as the outward eye
|
||||
Can size and shape pervade. The lofty theme
|
||||
At those few words hung vast before my mind,
|
||||
With half unravel'd web. I set myself
|
||||
Upon an eagle's watch, that I might see,
|
||||
And seeing ne'er forget. No stir of life
|
||||
Was in this shrouded vale, not so much air
|
||||
As in the zoning of a summer's day
|
||||
Robs not one light seed from the feather'd grass,
|
||||
But where the dead leaf fell there did it rest.
|
||||
A stream went voiceless by, still deaden'd more
|
||||
By reason of the fallen divinity
|
||||
Spreading more shade; the Naiad 'mid her reeds
|
||||
Press'd her cold finger closer to her lips.
|
||||
Along the margin sand large footmarks went
|
||||
No farther than to where old Saturn's feet
|
||||
Had rested, and there slept, how long a sleep!
|
||||
Degraded, cold, upon the sodden ground
|
||||
His old right hand lay nerveless, listless, dead,
|
||||
Unsceptred; and his realmless eyes were clos'd,
|
||||
While his bow'd head seem'd listening to the Earth,
|
||||
His ancient mother, for some comfort yet.
|
||||
|
||||
It seem'd no force could wake him from his place;
|
||||
But there came one who with a kindred hand
|
||||
Touch'd his wide shoulders after bending low
|
||||
With reverence, though to one who knew it not.
|
||||
Then came the griev'd voice of Mnemosyne,
|
||||
And griev'd I hearken'd. 'That divinity
|
||||
'Whom thou saw'st step from yon forlornest wood,
|
||||
'And with slow pace approach our fallen King,
|
||||
'Is Thea, softest natur'd of our brood.'
|
||||
I mark'd the G-ddess in fair statuary
|
||||
Surpassing wan Moneta by the head,
|
||||
And in her sorrow nearer woman's tears.
|
||||
There was a listening fear in her regard,
|
||||
As if calamity had but begun;
|
||||
As if the vanward clouds of evil days
|
||||
Had spent their malice, and the sullen rear
|
||||
Was with its stored thunder labouring up.
|
||||
One hand she press'd upon that aching spot
|
||||
Where beats the human heart, as if just there,
|
||||
Though an immortal, she felt cruel pain;
|
||||
The other upon Saturn's bended neck
|
||||
She laid, and to the level of his hollow ear
|
||||
Leaning with parted lips, some words she spake
|
||||
In solemn tenor and deep organ tune;
|
||||
Some mourning words, which in our feeble tongue
|
||||
Would come in this like accenting; how frail
|
||||
To that large utterance of the early G-ds!
|
||||
'Saturn! look up and for what, poor lost King?
|
||||
'I have no comfort for thee; no not one;
|
||||
'I cannot cry, Wherefore thus sleepest thou?
|
||||
'For Heaven is parted from thee, and the Earth
|
||||
'Knows thee not, so afflicted, for a G-d;
|
||||
'And Ocean too, with all its solemn noise,
|
||||
'Has from thy sceptre pass'd, and all the air
|
||||
'Is emptied of thine hoary majesty:
|
||||
'Thy thunder, captious at the new command,
|
||||
'Rumbles reluctant o'er our fallen house;
|
||||
'And thy sharp lightning, in unpracticed hands,
|
||||
'Scorches and burns our once serene domain.
|
||||
'With such remorseless speed still come new woes,
|
||||
'That unbelief has not a space to breathe.
|
||||
'Saturn! sleep on: Me thoughtless, why should I
|
||||
'Thus violate thy slumbrous solitude?
|
||||
'Why should I ope thy melancholy eyes?
|
||||
'Saturn, sleep on, while at thy feet I weep.'
|
||||
|
||||
As when upon a tranced summer night
|
||||
Forests, branch charmed by the earnest stars,
|
||||
Dream, and so dream all night without a noise,
|
||||
Save from one gradual solitary gust,
|
||||
Swelling upon the silence; dying off;
|
||||
As if the ebbing air had but one wave;
|
||||
So came these words, and went; the while in tears
|
||||
She press'd her fair large forehead to the earth,
|
||||
Just where her fallen hair might spread in curls
|
||||
A soft and silken mat for Saturn's feet.
|
||||
Long, long those two were postured motionless,
|
||||
Like sculpture builded up upon the grave
|
||||
Of their own power. A long awful time
|
||||
I look'd upon them: still they were the same;
|
||||
The frozen G-d still bending to the earth,
|
||||
And the sad G-ddess weeping at his feet,
|
||||
Moneta silent. Without stay or prop
|
||||
But my own weak mortality, I bore
|
||||
The load of this eternal quietude,
|
||||
The unchanging gloom, and the three fixed shapes
|
||||
Ponderous upon my senses, a whole moon.
|
||||
For by my burning brain I measured sure
|
||||
Her silver seasons shedded on the night,
|
||||
And ever day by day methought I grew
|
||||
More gaunt and ghostly. Oftentimes I pray'd
|
||||
Intense, that Death would take me from the vale
|
||||
And all its burthens gasping with despair
|
||||
Of change, hour after hour I curs'd myself;
|
||||
Until old Saturn rais'd his faded eyes,
|
||||
And look'd around and saw his kingdom gone,
|
||||
And all the gloom and sorrow of the place,
|
||||
And that fair kneeling G-ddess at his feet.
|
||||
As the moist scent of flowers, and grass, and leaves
|
||||
Fills forest dells with a pervading air,
|
||||
Known to the woodland nostril, so the words
|
||||
Of Saturn fill'd the mossy glooms around,
|
||||
Even to the hollows of time eaten oaks
|
||||
And to the windings of the foxes' hole,
|
||||
With sad low tones, while thus he spake, and sent
|
||||
Strange musings to the solitary Pan.
|
||||
'Moan, brethren, moan; for we are swallow'd up
|
||||
'And buried from all G-dlike exercise
|
||||
'Of influence benign on planets pale,
|
||||
'And peaceful sway above man's harvesting,
|
||||
'And all those acts which Deity supreme
|
||||
'Doth ease its heart of love in. Moan and wail,
|
||||
'Moan, brethren, moan; for lo, the rebel spheres
|
||||
'Spin round, the stars their ancient courses keep,
|
||||
'Clouds still with shadowy moisture haunt the earth,
|
||||
'Still suck their fill of light from sun and moon,
|
||||
'Still buds the tree, and still the sea shores murmur;
|
||||
'There is no death in all the Universe,
|
||||
'No smell of death there shall be death Moan, moan,
|
||||
'Moan, Cybele, moan; for thy pernicious babes
|
||||
'Have changed a G-d into a shaking Palsy.
|
||||
'Moan, brethren, moan, for I have no strength left,
|
||||
'Weak as the reed weak feeble as my voice
|
||||
'O, O, the pain, the pain of feebleness.
|
||||
'Moan, moan, for still I thaw or give me help;
|
||||
'Throw down those imps, and give me victory.
|
||||
'Let me hear other groans, and trumpets blown
|
||||
'Of triumph calm, and hymns of festival
|
||||
'From the gold peaks of Heaven's high piled clouds;
|
||||
'Voices of soft proclaim, and silver stir
|
||||
'Of strings in hollow shells; and let there be
|
||||
'Beautiful things made new, for the surprise
|
||||
'Of the sky children.' So he feebly ceas'd,
|
||||
With such a poor and sickly sounding pause,
|
||||
Methought I heard some old man of the earth
|
||||
Bewailing earthly loss; nor could my eyes
|
||||
And ears act with that pleasant unison of sense
|
||||
Which marries sweet sound with the grace of form,
|
||||
And dolorous accent from a tragic harp
|
||||
With large limb'd visions. More I scrutinized:
|
||||
Still fix'd he sat beneath the sable trees,
|
||||
Whose arms spread straggling in wild serpent forms,
|
||||
With leaves all hush'd; his awful presence there
|
||||
(Now all was silent) gave a deadly lie
|
||||
To what I erewhile heard only his lips
|
||||
Trembled amid the white curls of his beard.
|
||||
They told the truth, though, round, the snowy locks
|
||||
Hung nobly, as upon the face of heaven
|
||||
A mid day fleece of clouds. Thea arose,
|
||||
And stretched her white arm through the hollow dark,
|
||||
Pointing some whither: whereat he too rose
|
||||
Like a vast giant, seen by men at sea
|
||||
To grow pale from the waves at dull midnight.
|
||||
They melted from my sight into the woods;
|
||||
Ere I could turn, Moneta cried, 'These twain
|
||||
'Are speeding to the families of grief,
|
||||
'Where roof'd in by black rocks they waste, in pain
|
||||
'And darkness, for no hope.' And she spake on,
|
||||
As ye may read who can unwearied pass
|
||||
Onward from the antechamber of this dream,
|
||||
Where even at the open doors awhile
|
||||
I must delay, and glean my memory
|
||||
Of her high phrase: perhaps no further dare.
|
||||
|
||||
|
||||
CANTO II
|
||||
|
||||
'Mortal, that thou may'st understand aright,
|
||||
'I humanize my sayings to thine ear,
|
||||
'Making comparisons of earthly things;
|
||||
'Or thou might'st better listen to the wind,
|
||||
'Whose language is to thee a barren noise,
|
||||
'Though it blows legend laden through the trees.
|
||||
'In melancholy realms big tears are shed,
|
||||
'More sorrow like to this, and such like woe,
|
||||
'Too huge for mortal tongue, or pen of scribe.
|
||||
'The Titans fierce, self hid or prison bound,
|
||||
'Groan for the old allegiance once more,
|
||||
'Listening in their doom for Saturn's voice.
|
||||
'But one of our whole eagle brood still keeps
|
||||
'His sov'reignty, and rule, and majesty;
|
||||
'Blazing Hyperion on his orbed fire
|
||||
'Still sits, still snuffs the incense teeming up
|
||||
'From man to the sun's G-d: yet unsecure,
|
||||
'For as upon the earth dire prodigies
|
||||
'Fright and perplex, so also shudders he:
|
||||
'Nor at dog's howl or gloom bird's Even screech,
|
||||
'Or the familiar visitings of one
|
||||
'Upon the first toll of his passing bell:
|
||||
'But horrors, portioned to a giant nerve,
|
||||
'Make great Hyperion ache. His palace bright,
|
||||
'Bastion'd with pyramids of glowing gold,
|
||||
'And touch'd with shade of bronzed obelisks,
|
||||
'Glares a blood red through all the thousand courts,
|
||||
'Arches, and domes, and fiery galleries:
|
||||
'And all its curtains of Aurorian clouds
|
||||
'Flush angerly; when he would taste the wreaths
|
||||
'Of incense breath'd aloft from sacred hills,
|
||||
'Instead of sweets his ample palate takes
|
||||
'Savour of poisonous brass and metals sick.
|
||||
'Wherefore when harbour'd in the sleepy West,
|
||||
'After the full completion of fair day,
|
||||
'For rest divine upon exalted couch
|
||||
'And slumber in the arms of melody,
|
||||
'He paces through the pleasant hours of ease
|
||||
'With strides colossal, on from hall to hall;
|
||||
'While far within each aisle and deep recess
|
||||
'His winged minions in close clusters stand
|
||||
'Amaz'd, and full of fear; like anxious men,
|
||||
'Who on a wide plain gather in sad troops,
|
||||
'When earthquakes jar their battlements and towers.
|
||||
'Even now, while Saturn, roused from icy trance,
|
||||
'Goes step for step with Thea from yon woods,
|
||||
'Hyperion, leaving twilight in the rear,
|
||||
'Is sloping to the threshold of the West.
|
||||
'Thither we tend.' Now in clear light I stood,
|
||||
Reliev'd from the dusk vale. Mnemosyne
|
||||
Was sitting on a square edg'd polish'd stone,
|
||||
That in its lucid depth reflected pure
|
||||
Her priestess garments. My quick eyes ran on
|
||||
From stately nave to nave, from vault to vault,
|
||||
Through bow'rs of fragrant and enwreathed light
|
||||
And diamond paved lustrous long arcades.
|
||||
Anon rush'd by the bright Hyperion;
|
||||
His flaming robes stream'd out beyond his heels,
|
||||
And gave a roar, as if of earthly fire,
|
||||
That scared away the meek ethereal hours
|
||||
And made their dove wings tremble. On he flared.
|
||||
|
||||
|
||||
THE END
|
28
libc/testlib/incrementfailed.c
Normal file
28
libc/testlib/incrementfailed.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
void testlib_incrementfailed(void) {
|
||||
if (++g_testlib_failed > 23) {
|
||||
fprintf(stderr, "too many failures, aborting\n");
|
||||
testlib_abort();
|
||||
}
|
||||
}
|
45
libc/testlib/runner.c
Normal file
45
libc/testlib/runner.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/runtime/missioncritical.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
/**
|
||||
* Runs all TEST(), FIXTURE(), etc. recorded by ld.
|
||||
* @see libc/testlib/testlib.h
|
||||
* @see ape/ape.lds
|
||||
*/
|
||||
testonly void testlib_runalltests(void) {
|
||||
if ((intptr_t)__testcase_end > (intptr_t)__testcase_start) {
|
||||
if (testlib_countfixtures(__combo_start, __combo_end)) {
|
||||
testlib_runcombos(__testcase_start, __testcase_end, __combo_start,
|
||||
__combo_end);
|
||||
} else {
|
||||
testlib_runtestcases(__testcase_start, __testcase_end, NULL);
|
||||
testlib_runfixtures(__testcase_start, __testcase_end, __fixture_start,
|
||||
__fixture_end);
|
||||
testlib_finish();
|
||||
}
|
||||
}
|
||||
}
|
22
libc/testlib/shoulddebugbreak.c
Normal file
22
libc/testlib/shoulddebugbreak.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
bool g_testlib_shoulddebugbreak;
|
49
libc/testlib/showerror.c
Normal file
49
libc/testlib/showerror.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
testonly void testlib_showerror(const char *file, int line, const char *func,
|
||||
const char *method, const char *symbol,
|
||||
const char *code, char *v1, char *v2) {
|
||||
/* TODO(jart): Pay off tech debt re duplication */
|
||||
getpid$sysv(); /* make strace easier to read */
|
||||
getpid$sysv();
|
||||
fprintf(stderr,
|
||||
"%s%s%s%s:%s:%d%s: %s() %s %s(%s)\n"
|
||||
"\t%s\n"
|
||||
"\t\t%s %s %s\n"
|
||||
"\t\t%s %s\n"
|
||||
"\t%s%s\n"
|
||||
"\t%s%s\n",
|
||||
RED2, "error", UNBOLD, BLUE1, file, line, RESET, method, "in", func,
|
||||
g_fixturename, code, "want", v1, symbol, " got", v2, SUBTLE,
|
||||
strerror(errno), program_invocation_name, RESET);
|
||||
free_s(&v1);
|
||||
free_s(&v2);
|
||||
}
|
90
libc/testlib/showerror_.c
Normal file
90
libc/testlib/showerror_.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
STATIC_YOINK("isfdkind");
|
||||
|
||||
const char *testlib_showerror_errno;
|
||||
const char *testlib_showerror_file;
|
||||
const char *testlib_showerror_func;
|
||||
const char *testlib_showerror_isfatal;
|
||||
const char *testlib_showerror_macro;
|
||||
const char *testlib_showerror_symbol;
|
||||
|
||||
testonly void testlib_showerror_(int line, const char *wantcode,
|
||||
const char *gotcode, char *FREED_want,
|
||||
char *FREED_got, const char *fmt, ...) {
|
||||
va_list va;
|
||||
|
||||
getpid$sysv(); /* make strace easier to read */
|
||||
getpid$sysv();
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
/* TODO(jart): Pay off tech debt re duplication */
|
||||
|
||||
fprintf(stderr, "%s%s%s%s:%s:%d%s: %s(%s)\n\t%s(%s", RED2, "error", UNBOLD,
|
||||
BLUE1, testlib_showerror_file, line, RESET, testlib_showerror_func,
|
||||
g_fixturename, testlib_showerror_macro, wantcode);
|
||||
|
||||
if (wantcode) {
|
||||
fprintf(stderr,
|
||||
", %s)\n"
|
||||
"\t\t%s %s %s\n"
|
||||
"\t\t%s %s\n",
|
||||
gotcode, "want", FREED_want, testlib_showerror_symbol, " got",
|
||||
FREED_got);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
", %s)\n"
|
||||
"\t\t→ %s%s\n",
|
||||
gotcode, testlib_showerror_symbol, FREED_want);
|
||||
}
|
||||
|
||||
if (!isempty(fmt)) {
|
||||
fputc('\t', stderr);
|
||||
va_start(va, fmt);
|
||||
vfprintf(stderr, fmt, va);
|
||||
va_end(va);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"\t%s%s\n"
|
||||
"\t%s%s\n",
|
||||
SUBTLE, strerror(errno), program_invocation_name, RESET);
|
||||
|
||||
free_s(&FREED_want);
|
||||
free_s(&FREED_got);
|
||||
|
||||
++g_testlib_failed;
|
||||
if (testlib_showerror_isfatal) testlib_abort();
|
||||
}
|
30
libc/testlib/startswith.c
Normal file
30
libc/testlib/startswith.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
testonly bool testlib_startswith(size_t cw, const void *s, const void *prefix) {
|
||||
if (s == prefix) return true;
|
||||
if (!s || !prefix) return false;
|
||||
return cw == sizeof(wchar_t)
|
||||
? wcsstartswith(s, prefix)
|
||||
: cw == sizeof(char16_t) ? startswith16(s, prefix)
|
||||
: startswith(s, prefix);
|
||||
}
|
36
libc/testlib/strcaseequals.c
Normal file
36
libc/testlib/strcaseequals.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
testonly bool testlib_strcaseequals(size_t cw, const void *s1, const void *s2) {
|
||||
return testlib_strncaseequals(cw, s1, s2, SIZE_MAX);
|
||||
}
|
||||
|
||||
testonly bool testlib_strncaseequals(size_t cw, const void *s1, const void *s2,
|
||||
size_t n) {
|
||||
if (s1 == s2) return true;
|
||||
if (!s1 || !s2) return false;
|
||||
return (cw == sizeof(wchar_t)
|
||||
? wcsncasecmp(s1, s2, n)
|
||||
: cw == sizeof(char16_t) ? strncasecmp16(s1, s2, n)
|
||||
: strncasecmp(s1, s2, n)) == 0;
|
||||
}
|
36
libc/testlib/strequals.c
Normal file
36
libc/testlib/strequals.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
testonly bool testlib_strequals(size_t cw, const void *s1, const void *s2) {
|
||||
return testlib_strnequals(cw, s1, s2, SIZE_MAX);
|
||||
}
|
||||
|
||||
testonly bool testlib_strnequals(size_t cw, const void *s1, const void *s2,
|
||||
size_t n) {
|
||||
if (s1 == s2) return true;
|
||||
if (!s1 || !s2) return false;
|
||||
return (cw == sizeof(wchar_t)
|
||||
? wcsncmp(s1, s2, n)
|
||||
: cw == sizeof(char16_t) ? strncmp16(s1, s2, n)
|
||||
: strncmp(s1, s2, n)) == 0;
|
||||
}
|
41
libc/testlib/testcase.S
Normal file
41
libc/testlib/testcase.S
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Decentralized section for test testcase registration.
|
||||
/
|
||||
/ @see ape/ape.lds
|
||||
.section .piro.relo.sort.testcase.1,"aw",@nobits
|
||||
.type __testcase_start,@object
|
||||
.type __testcase_end,@object
|
||||
.globl __testcase_start,__testcase_end
|
||||
.hidden __testcase_start,__testcase_end
|
||||
.byte 0
|
||||
.align __SIZEOF_POINTER__
|
||||
__testcase_start:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .piro.relo.sort.testcase.3,"aw",@nobits
|
||||
__testcase_end:
|
||||
.quad 0
|
||||
.previous
|
631
libc/testlib/testlib.h
Normal file
631
libc/testlib/testlib.h
Normal file
|
@ -0,0 +1,631 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_TESTLIB_H_
|
||||
#define COSMOPOLITAN_LIBC_TESTLIB_H_
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/testlib/ugly.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § testing library ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
/**
|
||||
* Declares test case function.
|
||||
*
|
||||
* Test cases are guaranteed by the linker to be run in order, sorted by
|
||||
* the (SUITE, NAME) tuple passed here.
|
||||
*/
|
||||
#define TEST(SUITE, NAME) __TEST_PROTOTYPE(SUITE, NAME, __TEST_ARRAY)
|
||||
|
||||
/**
|
||||
* Declares function that globally modifies program state.
|
||||
*
|
||||
* All tests will be run an additional time, for each fixture. Fixtures
|
||||
* are useful, for example, when multiple implementations of a function
|
||||
* exist. Memory protections, on sections such as .initbss, are removed
|
||||
* temorarilly by the runtime while calling fixture functions. Fixtures
|
||||
* are also guaranteed by the linker to be run in sorted order.
|
||||
*/
|
||||
#define FIXTURE(SUITE, NAME) __FIXTURE("fixture", SUITE, NAME)
|
||||
|
||||
/**
|
||||
* Registers explosive fixture with linker.
|
||||
*
|
||||
* All tests will run an additional time for each set of entries in the
|
||||
* Cartesian product of groups. That makes this similar to fixture, but
|
||||
* more appropriate for testing pure code (i.e. no syscalls) like math.
|
||||
*/
|
||||
#define COMBO(GROUP, ENTRY) __FIXTURE("combo", GROUP, ENTRY)
|
||||
|
||||
/**
|
||||
* Declares benchmark function.
|
||||
*
|
||||
* These only run if (1) the -b flag is passed to the FOO_test.com; and
|
||||
* (2) the unit tests passed. It's just an ordinary function, that gets
|
||||
* registered with the linker. It should print things to stdout.
|
||||
*
|
||||
* @see EZBENCH()
|
||||
*/
|
||||
#define BENCH(SUITE, NAME) \
|
||||
STATIC_YOINK("__bench_start"); \
|
||||
__TEST_PROTOTYPE(SUITE, NAME, __BENCH_ARRAY)
|
||||
|
||||
#define ASSERT_GE(C, X) _TEST2("ASSERT_GE", C, >=, (X), #C, " ≥ ", #X, 1)
|
||||
#define ASSERT_GT(C, X) _TEST2("ASSERT_GT", C, >, (X), #C, " > ", #X, 1)
|
||||
#define ASSERT_LE(C, X) _TEST2("ASSERT_LE", C, <=, (X), #C, " ≤ ", #X, 1)
|
||||
#define ASSERT_LT(C, X) _TEST2("ASSERT_LT", C, <, (X), #C, " < ", #X, 1)
|
||||
#define EXPECT_GE(C, X) _TEST2("EXPECT_GE", C, >=, (X), #C, " ≥ ", #X, 0)
|
||||
#define EXPECT_GT(C, X) _TEST2("EXPECT_GT", C, >, (X), #C, " > ", #X, 0)
|
||||
#define EXPECT_LE(C, X) _TEST2("EXPECT_LE", C, <=, (X), #C, " ≤ ", #X, 0)
|
||||
#define EXPECT_LT(C, X) _TEST2("EXPECT_LT", C, <, (X), #C, " < ", #X, 0)
|
||||
|
||||
#define _TEST2(NAME, WANT, OP, GOT, WANTCODE, OPSTR, GOTCODE, ISFATAL) \
|
||||
do { \
|
||||
autotype(WANT) Want = (WANT); \
|
||||
autotype(GOT) Got = (GOT); \
|
||||
if (!(Want OP Got)) { \
|
||||
testlib_showerror(FILIFU NAME, OPSTR, WANTCODE OPSTR GOTCODE, \
|
||||
testlib_formatint(Want), testlib_formatint(Got)); \
|
||||
testlib_onfail2(ISFATAL); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § testing library » assert or die ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define EXPECT_TRUE(X) _TEST2("EXPECT_TRUE", true, ==, (X), #X, "", "", 0)
|
||||
#define EXPECT_FALSE(X) _TEST2("EXPECT_FALSE", false, ==, (X), #X, "", "", 0)
|
||||
#define ASSERT_TRUE(X) _TEST2("ASSERT_TRUE", true, ==, (X), #X, "", "", 1)
|
||||
#define ASSERT_FALSE(X) _TEST2("ASSERT_FALSE", false, ==, (X), #X, "", "", 1)
|
||||
|
||||
#define ASSERT_EQ(WANT, GOT, ...) \
|
||||
__TEST_EQ(assert, __FILE__, __LINE__, __FUNCTION__, #WANT, #GOT, WANT, GOT, \
|
||||
__VA_ARGS__)
|
||||
#define EXPECT_EQ(WANT, GOT, ...) \
|
||||
__TEST_EQ(expect, __FILE__, __LINE__, __FUNCTION__, #WANT, #GOT, WANT, GOT, \
|
||||
__VA_ARGS__)
|
||||
#define __TEST_EQ(KIND, FILE, LINE, FUNC, WANTCODE, GOTCODE, WANT, GOT, ...) \
|
||||
({ \
|
||||
autotype(GOT) Got = _I(GOT); \
|
||||
typeof(Got) Want = _I(WANT); \
|
||||
testlib_ontest(); \
|
||||
if (Want != Got) { \
|
||||
TESTLIB_ONFAIL(FILE, FUNC); \
|
||||
TESTLIB_SHOWERROR(testlib_showerror_##KIND##_eq, LINE, WANTCODE, \
|
||||
GOTCODE, testlib_formatint(_I(Want)), \
|
||||
testlib_formatint(_I(Got)), "" __VA_ARGS__); \
|
||||
} \
|
||||
(void)0; \
|
||||
})
|
||||
|
||||
#define ASSERT_NE(WANT, GOT, ...) \
|
||||
__TEST_NE(assert, __FILE__, __LINE__, __FUNCTION__, #WANT, #GOT, WANT, GOT, \
|
||||
__VA_ARGS__)
|
||||
#define EXPECT_NE(WANT, GOT, ...) \
|
||||
__TEST_NE(expect, __FILE__, __LINE__, __FUNCTION__, #WANT, #GOT, WANT, GOT, \
|
||||
__VA_ARGS__)
|
||||
#define __TEST_NE(KIND, FILE, LINE, FUNC, WANTCODE, GOTCODE, WANT, GOT, ...) \
|
||||
({ \
|
||||
autotype(GOT) Got = (GOT); \
|
||||
typeof(Got) Want = (WANT); \
|
||||
testlib_ontest(); \
|
||||
if (Want == Got) { \
|
||||
TESTLIB_ONFAIL(FILE, FUNC); \
|
||||
TESTLIB_SHOWERROR(testlib_showerror_##KIND##_ne, LINE, WANTCODE, \
|
||||
GOTCODE, testlib_formatint(_I(Want)), \
|
||||
testlib_formatint(_I(Got)), "" __VA_ARGS__); \
|
||||
} \
|
||||
(void)0; \
|
||||
})
|
||||
|
||||
#define ASSERT_BETWEEN(BEG, END, GOT) \
|
||||
assertBetween(FILIFU _I(BEG), _I(END), _I(GOT), \
|
||||
#BEG " <= " #GOT " <= " #END, true)
|
||||
#define ASSERT_STREQ(WANT, GOT) \
|
||||
assertStringEquals(FILIFU sizeof(*(WANT)), WANT, GOT, #GOT, true)
|
||||
#define ASSERT_STRNE(NOPE, GOT) \
|
||||
assertStringNotEquals(FILIFU sizeof(*(NOPE)), NOPE, GOT, #GOT, true)
|
||||
#define ASSERT_STREQN(WANT, GOT, N) \
|
||||
assertStrnEquals(FILIFU sizeof(*(WANT)), WANT, GOT, N, #GOT, true)
|
||||
#define ASSERT_STRNEN(NOPE, GOT, N) \
|
||||
assertStrnNotEquals(FILIFU sizeof(*(NOPE)), NOPE, GOT, N, #GOT, true)
|
||||
#define ASSERT_STRCASEEQ(WANT, GOT) \
|
||||
assertStringCaseEquals(FILIFU sizeof(*(WANT)), WANT, GOT, #GOT, true)
|
||||
#define ASSERT_STRCASENE(NOPE, GOT) \
|
||||
assertStringCaseNotEquals(FILIFU sizeof(*(NOPE)), NOPE, GOT, #GOT, true)
|
||||
#define ASSERT_STRNCASEEQ(WANT, GOT, N) \
|
||||
assertStrnCaseEquals(FILIFU sizeof(*(WANT)), WANT, GOT, N, #GOT, true)
|
||||
#define ASSERT_STRNCASENE(NOPE, GOT, N) \
|
||||
assertStrnCaseNotEquals(FILIFU sizeof(*(NOPE)), NOPE, GOT, N, #GOT, true)
|
||||
#define ASSERT_STARTSWITH(PREFIX, GOT) \
|
||||
assertStartsWith(FILIFU sizeof(*(PREFIX)), PREFIX, GOT, #GOT, true)
|
||||
#define ASSERT_ENDSWITH(SUFFIX, GOT) \
|
||||
assertEndsWith(FILIFU sizeof(*(SUFFIX)), SUFFIX, GOT, #GOT, true)
|
||||
#define ASSERT_IN(NEEDLE, GOT) \
|
||||
assertContains(FILIFU sizeof(*(NEEDLE)), NEEDLE, GOT, #GOT, true)
|
||||
|
||||
#define ASSERT_BINEQ(WANT, GOT) \
|
||||
_Generic((WANT)[0], char \
|
||||
: assertBinaryEquals$hex, default \
|
||||
: assertBinaryEquals$cp437)(FILIFU WANT, GOT, -1, #GOT, true)
|
||||
#define ASSERT_BINNE(NOPE, GOT) \
|
||||
_Generic((NOPE)[0], char \
|
||||
: assertBinaryNotEquals$hex, default \
|
||||
: assertBinaryNotEquals$cp437)(FILIFU NOPE, GOT, -1, #GOT, true)
|
||||
#define ASSERT_BINEQN(WANT, GOT, N) \
|
||||
_Generic((WANT)[0], char \
|
||||
: assertBinaryEquals$hex, default \
|
||||
: assertBinaryEquals$cp437)(FILIFU WANT, GOT, N, #GOT, true)
|
||||
#define ASSERT_BINNEN(NOPE, GOT, N) \
|
||||
_Generic((NOPE)[0], char \
|
||||
: assertBinaryNotEquals$hex, default \
|
||||
: assertBinaryNotEquals$cp437)(FILIFU NOPE, GOT, -1, #GOT, true)
|
||||
|
||||
#define ASSERT_FLOAT_EQ(WANT, GOT) \
|
||||
assertLongDoubleEquals(FILIFU WANT, GOT, #GOT, true)
|
||||
#define ASSERT_DOUBLE_EQ(WANT, GOT) \
|
||||
assertLongDoubleEquals(FILIFU WANT, GOT, #GOT, true)
|
||||
#define ASSERT_LDBL_EQ(WANT, GOT) \
|
||||
assertLongDoubleEquals(FILIFU WANT, GOT, #GOT, true)
|
||||
#define ASSERT_LDBL_GT(VAL, GOT) \
|
||||
assertLongDoubleGreaterThan(VAL, GOT, #VAL " > " #GOT, true)
|
||||
#define ASSERT_LDBL_LT(VAL, GOT) \
|
||||
assertLongDoubleLessThan(VAL, GOT, #VAL " < " #GOT, true)
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § testing library » assert or log ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define EXPECT_BETWEEN(BEG, END, GOT) \
|
||||
assertBetween(FILIFU _I(BEG), _I(END), _I(GOT), \
|
||||
#BEG " <= " #GOT " <= " #END, false)
|
||||
#define EXPECT_STREQ(WANT, GOT) \
|
||||
assertStringEquals(FILIFU sizeof(*(WANT)), WANT, GOT, #GOT, false)
|
||||
#define EXPECT_STRNE(NOPE, GOT) \
|
||||
assertStringNotEquals(FILIFU sizeof(*(NOPE)), NOPE, GOT, #GOT, false)
|
||||
#define EXPECT_STREQN(WANT, GOT, N) \
|
||||
assertStrnEquals(FILIFU sizeof(*(WANT)), WANT, GOT, N, #GOT, false)
|
||||
#define EXPECT_STRNEN(NOPE, GOT, N) \
|
||||
assertStrnNotEquals(FILIFU sizeof(*(NOPE)), NOPE, GOT, N, #GOT, false)
|
||||
#define EXPECT_STRCASEEQ(WANT, GOT) \
|
||||
assertStringCaseEquals(FILIFU sizeof(*(WANT)), WANT, GOT, #GOT, false)
|
||||
#define EXPECT_STRCASENE(NOPE, GOT) \
|
||||
assertStringCaseNotEquals(FILIFU sizeof(*(NOPE)), NOPE, GOT, #GOT, false)
|
||||
#define EXPECT_STRNCASEEQ(WANT, GOT, N) \
|
||||
assertStrnCaseEquals(FILIFU sizeof(*(WANT)), WANT, GOT, N, #GOT, false)
|
||||
#define EXPECT_STRNCASENE(NOPE, GOT, N) \
|
||||
assertStrnCaseNotEquals(FILIFU sizeof(*(NOPE)), NOPE, GOT, N, #GOT, false)
|
||||
#define EXPECT_STARTSWITH(PREFIX, GOT) \
|
||||
assertStartsWith(FILIFU sizeof(*(PREFIX)), PREFIX, GOT, #GOT, false)
|
||||
#define EXPECT_ENDSWITH(SUFFIX, GOT) \
|
||||
assertEndsWith(FILIFU sizeof(*(SUFFIX)), SUFFIX, GOT, #GOT, false)
|
||||
#define EXPECT_IN(NEEDLE, GOT) \
|
||||
assertContains(FILIFU sizeof(*(NEEDLE)), NEEDLE, GOT, #GOT, false)
|
||||
|
||||
#define EXPECT_BINEQ(WANT, GOT) \
|
||||
_Generic((WANT)[0], char \
|
||||
: assertBinaryEquals$hex, default \
|
||||
: assertBinaryEquals$cp437)(FILIFU WANT, GOT, -1, #GOT, false)
|
||||
#define EXPECT_BINNE(NOPE, GOT) \
|
||||
_Generic((NOPE)[0], char \
|
||||
: assertBinaryNotEquals$hex, default \
|
||||
: assertBinaryNotEquals$cp437)(FILIFU NOPE, GOT, -1, #GOT, false)
|
||||
#define EXPECT_BINEQN(WANT, GOT, N) \
|
||||
_Generic((WANT)[0], char \
|
||||
: assertBinaryEquals$hex, default \
|
||||
: assertBinaryEquals$cp437)(FILIFU WANT, GOT, N, #GOT, false)
|
||||
#define EXPECT_BINNEN(NOPE, GOT, N) \
|
||||
_Generic((NOPE)[0], char \
|
||||
: assertBinaryNotEquals$hex, default \
|
||||
: assertBinaryNotEquals$cp437)(FILIFU NOPE, GOT, -1, #GOT, false)
|
||||
|
||||
#define EXPECT_FLOAT_EQ(WANT, GOT) \
|
||||
assertLongDoubleEquals(FILIFU WANT, GOT, #GOT, false)
|
||||
#define EXPECT_DOUBLE_EQ(WANT, GOT) \
|
||||
assertLongDoubleEquals(FILIFU WANT, GOT, #GOT, false)
|
||||
#define EXPECT_LDBL_EQ(WANT, GOT) \
|
||||
assertLongDoubleEquals(FILIFU WANT, GOT, #GOT, false)
|
||||
#define EXPECT_LGBL_GT(VAL, GOT) \
|
||||
expectLongDoubleGreaterThan(VAL, GOT, #VAL " > " #GOT, false)
|
||||
#define EXPECT_LGBL_LT(VAL, GOT) \
|
||||
expectLongDoubleLessThan(VAL, GOT, #VAL " < " #GOT, false)
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § testing library » hardware-accelerated memory safety ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
typedef void (*testfn_t)(void);
|
||||
|
||||
struct TestFixture {
|
||||
const char *group;
|
||||
const char *name;
|
||||
testfn_t fn;
|
||||
};
|
||||
|
||||
struct TestAllocation {
|
||||
void *mapaddr;
|
||||
size_t mapsize;
|
||||
void *useraddr;
|
||||
size_t usersize;
|
||||
};
|
||||
|
||||
struct TestMemoryStack {
|
||||
size_t i;
|
||||
size_t n;
|
||||
struct TestAllocation *p;
|
||||
};
|
||||
|
||||
extern struct TestMemoryStack g_testmem;
|
||||
|
||||
void tfree(void *) paramsnonnull();
|
||||
void *tmalloc(size_t) returnsnonnull returnspointerwithnoaliases nodiscard
|
||||
attributeallocsize((1)) returnsaligned((1));
|
||||
void *tmemalign(size_t,
|
||||
size_t) returnsnonnull returnspointerwithnoaliases nodiscard
|
||||
attributeallocsize((2)) libcesque attributeallocalign((1));
|
||||
char *tstrdup(const char *) returnsnonnull returnspointerwithnoaliases nodiscard
|
||||
returnsaligned((1));
|
||||
void *tunbing(const char16_t *)
|
||||
paramsnonnull() returnsnonnull returnspointerwithnoaliases nodiscard
|
||||
returnsaligned((1));
|
||||
void *tunbinga(size_t, const char16_t *)
|
||||
paramsnonnull() returnsnonnull returnspointerwithnoaliases nodiscard
|
||||
attributeallocalign((1));
|
||||
|
||||
#define tgc(TMEM) \
|
||||
({ \
|
||||
void *Res; \
|
||||
/* volatile b/c testmem only lifo atm */ \
|
||||
asm volatile("" ::: "memory"); \
|
||||
Res = defer((tfree), (TMEM)); \
|
||||
asm volatile("" ::: "memory"); \
|
||||
Res; \
|
||||
})
|
||||
|
||||
#define tfree(P) \
|
||||
do { \
|
||||
__tfree_check(P); \
|
||||
(tfree)(P); \
|
||||
} while (0)
|
||||
|
||||
#define __tfree_check(P) \
|
||||
ASSERT_BETWEEN(g_testmem.p[g_testmem.i - 1].useraddr, \
|
||||
((char *)g_testmem.p[g_testmem.i - 1].useraddr + \
|
||||
g_testmem.p[g_testmem.i - 1].usersize), \
|
||||
P)
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § testing library » implementation details ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define FILIFU __FILE__, __LINE__, __FUNCTION__,
|
||||
#define FILIFU_OBJ(...) __FILE__, __LINE__, ##__VA_ARGS__
|
||||
#define FILIFU_ARGS const char *file, int line, const char *func,
|
||||
#define FILIFU_FROM(OBJ) (OBJ)->file, (OBJ)->line, __FUNCTION__,
|
||||
#define FILIFU_FIELDS \
|
||||
const char *file; \
|
||||
int line
|
||||
|
||||
extern char g_fixturename[256];
|
||||
extern bool g_testlib_shoulddebugbreak; /* set by testmain */
|
||||
extern unsigned g_testlib_ran; /* set by wrappers */
|
||||
extern unsigned g_testlib_failed; /* set by wrappers */
|
||||
extern const char *testlib_showerror_errno; /* set by macros */
|
||||
extern const char *testlib_showerror_file; /* set by macros */
|
||||
extern const char *testlib_showerror_func; /* set by macros */
|
||||
extern const testfn_t __bench_start[], __bench_end[];
|
||||
extern const testfn_t __testcase_start[], __testcase_end[];
|
||||
extern const struct TestFixture __fixture_start[], __fixture_end[];
|
||||
extern const struct TestFixture __combo_start[], __combo_end[];
|
||||
|
||||
#define TESTLIB_ONFAIL(FILE, FUNC) \
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak(); \
|
||||
testlib_showerror_file = FILE; \
|
||||
testlib_showerror_func = FUNC
|
||||
|
||||
#define TESTLIB_SHOWERROR(THUNK, ...) \
|
||||
(((typeof(&testlib_showerror_))strongaddr(#THUNK)))(__VA_ARGS__)
|
||||
|
||||
void testlib_showerror_(int line, const char *wantcode, const char *gotcode,
|
||||
char *FREED_want, char *FREED_got, const char *fmt,
|
||||
...) relegated;
|
||||
|
||||
void testlib_showerror(const char *file, int line, const char *func,
|
||||
const char *method, const char *symbol, const char *code,
|
||||
char *v1, char *v2);
|
||||
|
||||
void thrashcodecache(void);
|
||||
|
||||
void testlib_finish(void);
|
||||
void testlib_runalltests(void);
|
||||
void testlib_runallbenchmarks(void);
|
||||
void testlib_runtestcases(testfn_t *, testfn_t *, testfn_t);
|
||||
void testlib_runcombos(testfn_t *, testfn_t *, const struct TestFixture *,
|
||||
const struct TestFixture *);
|
||||
void testlib_runfixtures(testfn_t *, testfn_t *, const struct TestFixture *,
|
||||
const struct TestFixture *);
|
||||
int testlib_countfixtures(const struct TestFixture *,
|
||||
const struct TestFixture *);
|
||||
void testlib_abort(void) noreturn relegated;
|
||||
bool testlib_strequals(size_t, const void *, const void *) nosideeffect;
|
||||
bool testlib_strnequals(size_t, const void *, const void *,
|
||||
size_t) nosideeffect;
|
||||
bool testlib_strcaseequals(size_t, const void *, const void *) nosideeffect;
|
||||
bool testlib_strncaseequals(size_t, const void *, const void *,
|
||||
size_t) nosideeffect;
|
||||
void testlib_free(void *);
|
||||
bool testlib_binequals(const char16_t *, const void *, size_t) nosideeffect;
|
||||
bool testlib_hexequals(const char *, const void *, size_t) nosideeffect;
|
||||
bool testlib_startswith(size_t, const void *, const void *) nosideeffect;
|
||||
bool testlib_endswith(size_t, const void *, const void *) nosideeffect;
|
||||
bool testlib_contains(size_t, const void *, const void *) nosideeffect;
|
||||
char *testlib_formatrange(intmax_t, intmax_t) mallocesque;
|
||||
char *testlib_formatstr(size_t, const void *, int) mallocesque;
|
||||
char *testlib_formatint(intmax_t) mallocesque;
|
||||
char *testlib_formatbool(bool);
|
||||
char *testlib_formatfloat(long double) mallocesque;
|
||||
void testlib_formatbinaryashex(const char *, const void *, size_t, char **,
|
||||
char **);
|
||||
void testlib_formatbinaryasglyphs(const char16_t *, const void *, size_t,
|
||||
char **, char **);
|
||||
bool testlib_almostequallongdouble(long double, long double);
|
||||
void testlib_incrementfailed(void);
|
||||
|
||||
forceinline void testlib_ontest() {
|
||||
YOINK(__testcase_start);
|
||||
YOINK(__fixture_start);
|
||||
YOINK(__combo_start);
|
||||
++g_testlib_ran;
|
||||
}
|
||||
|
||||
forceinline void testlib_onfail2(bool isfatal) {
|
||||
testlib_incrementfailed();
|
||||
if (isfatal) testlib_abort();
|
||||
}
|
||||
|
||||
forceinline void assertNotEquals(FILIFU_ARGS intmax_t donotwant, intmax_t got,
|
||||
const char *gotcode, bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (got != donotwant) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertNotEquals", "=", gotcode,
|
||||
testlib_formatint(got), testlib_formatint(donotwant));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
#define assertLongDoubleGreaterThan(a, b, code, isfatal) \
|
||||
({ \
|
||||
autotype(a) a_ = (a); \
|
||||
autotype(b) b_ = (b); \
|
||||
if (a_ <= b_) { \
|
||||
testlib_showerror(FILIFU "assertLongDoubleGreaterThan", ">", code, \
|
||||
testlib_formatfloat(a_), testlib_formatfloat(b_)); \
|
||||
testlib_onfail2(isfatal); \
|
||||
} \
|
||||
(void)0; \
|
||||
})
|
||||
|
||||
#define assertLongDoubleLessThan(a, b, code, isfatal) \
|
||||
({ \
|
||||
autotype(a) a_ = (a); \
|
||||
autotype(b) b_ = (b); \
|
||||
if (a_ >= b_) { \
|
||||
testlib_showerror(FILIFU "assertLongDoubleLessThan", "<", code, \
|
||||
testlib_formatfloat(a_), testlib_formatfloat(b_)); \
|
||||
testlib_onfail2(isfatal); \
|
||||
} \
|
||||
(void)0; \
|
||||
})
|
||||
|
||||
forceinline void assertBetween(FILIFU_ARGS intmax_t beg, intmax_t end,
|
||||
intmax_t got, const char *gotcode,
|
||||
bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (beg <= got && got <= end) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertBetween", "∉", gotcode,
|
||||
testlib_formatint(got), testlib_formatrange(beg, end));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertStringEquals(FILIFU_ARGS size_t cw, const void *want,
|
||||
const void *got, const char *gotcode,
|
||||
bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (testlib_strequals(cw, want, got)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertStringEquals", "≠", gotcode,
|
||||
testlib_formatstr(cw, want, -1),
|
||||
testlib_formatstr(cw, got, -1));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertStringNotEquals(FILIFU_ARGS size_t cw, const void *want,
|
||||
const void *got, const char *gotcode,
|
||||
bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (!testlib_strequals(cw, want, got)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertStringNotEquals", "=", gotcode,
|
||||
testlib_formatstr(cw, want, -1),
|
||||
testlib_formatstr(cw, got, -1));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertStrnEquals(FILIFU_ARGS size_t cw, const void *want,
|
||||
const void *got, size_t n,
|
||||
const char *gotcode, bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (testlib_strnequals(cw, want, got, n)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertStrnEquals", "≠", gotcode,
|
||||
testlib_formatstr(cw, got, n),
|
||||
testlib_formatstr(cw, want, n));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertStrnNotEquals(FILIFU_ARGS size_t cw, const void *want,
|
||||
const void *got, size_t n,
|
||||
const char *gotcode, bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (!testlib_strnequals(cw, want, got, n)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertStrnNotEquals", "=", gotcode,
|
||||
testlib_formatstr(cw, got, n),
|
||||
testlib_formatstr(cw, want, n));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertStringCaseEquals(FILIFU_ARGS size_t cw, const void *want,
|
||||
const void *got, const char *gotcode,
|
||||
bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (testlib_strcaseequals(cw, want, got)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertStringCaseEquals", "≠", gotcode,
|
||||
testlib_formatstr(cw, got, -1),
|
||||
testlib_formatstr(cw, want, -1));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertStringCaseNotEquals(FILIFU_ARGS size_t cw,
|
||||
const void *want, const void *got,
|
||||
const char *gotcode, bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (!testlib_strcaseequals(cw, want, got)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertStringCaseNotEquals", "=", gotcode,
|
||||
testlib_formatstr(cw, got, -1),
|
||||
testlib_formatstr(cw, want, -1));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertStrnCaseEquals(FILIFU_ARGS size_t cw, const void *want,
|
||||
const void *got, size_t n,
|
||||
const char *gotcode, bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (testlib_strncaseequals(cw, want, got, n)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertStrnCaseEquals", "≠", gotcode,
|
||||
testlib_formatstr(cw, got, n),
|
||||
testlib_formatstr(cw, want, n));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertStrnCaseNotEquals(FILIFU_ARGS size_t cw,
|
||||
const void *want, const void *got,
|
||||
size_t n, const char *gotcode,
|
||||
bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (!testlib_strncaseequals(cw, want, got, n)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertStrnCaseNotEquals", "=", gotcode,
|
||||
testlib_formatstr(cw, got, n),
|
||||
testlib_formatstr(cw, want, n));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertStartsWith(FILIFU_ARGS size_t cw, const char *prefix,
|
||||
const char *s, const char *gotcode,
|
||||
bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (testlib_startswith(cw, s, prefix)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertStartsWith", "≠", gotcode,
|
||||
testlib_formatstr(1, s, -1),
|
||||
testlib_formatstr(1, prefix, -1));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertEndsWith(FILIFU_ARGS size_t cw, const char *suffix,
|
||||
const char *s, const char *gotcode,
|
||||
bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (testlib_endswith(cw, s, suffix)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertEndsWith", "≠", gotcode,
|
||||
testlib_formatstr(1, s, -1),
|
||||
testlib_formatstr(1, suffix, -1));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertContains(FILIFU_ARGS size_t cw, const char *needle,
|
||||
const char *s, const char *gotcode,
|
||||
bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (testlib_contains(cw, s, needle)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertContains", "∉", gotcode,
|
||||
testlib_formatstr(1, s, -1),
|
||||
testlib_formatstr(1, needle, -1));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertBinaryEquals$cp437(FILIFU_ARGS const char16_t *want,
|
||||
const void *got, size_t n,
|
||||
const char *gotcode, bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
char *v1, *v2;
|
||||
if (testlib_binequals(want, got, n)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_formatbinaryasglyphs(want, got, n, &v1, &v2);
|
||||
testlib_showerror(file, line, func, "assertBinaryEquals", "≠", gotcode, v1,
|
||||
v2);
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertBinaryEquals$hex(FILIFU_ARGS const char *want,
|
||||
const void *got, size_t n,
|
||||
const char *gotcode, bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
char *v1, *v2;
|
||||
if (testlib_hexequals(want, got, n)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_formatbinaryashex(want, got, n, &v1, &v2);
|
||||
testlib_showerror(file, line, func, "assertBinaryEquals", "≠", gotcode, v1,
|
||||
v2);
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertBinaryNotEquals$cp437(FILIFU_ARGS const char16_t *want,
|
||||
const void *got, size_t n,
|
||||
const char *gotcode,
|
||||
bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
char *v1, *v2;
|
||||
if (!testlib_binequals(want, got, n)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_formatbinaryasglyphs(want, got, n, &v1, &v2);
|
||||
testlib_showerror(file, line, func, "assertBinaryNotEquals", "=", gotcode, v1,
|
||||
v2);
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertBinaryNotEquals$hex(FILIFU_ARGS const char *want,
|
||||
const void *got, size_t n,
|
||||
const char *gotcode, bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
char *v1, *v2;
|
||||
if (!testlib_hexequals(want, got, n)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_formatbinaryashex(want, got, n, &v1, &v2);
|
||||
testlib_showerror(file, line, func, "assertBinaryNotEquals", "=", gotcode, v1,
|
||||
v2);
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
forceinline void assertLongDoubleEquals(FILIFU_ARGS long double want,
|
||||
long double got, const char *gotcode,
|
||||
bool isfatal) {
|
||||
++g_testlib_ran;
|
||||
if (testlib_almostequallongdouble(want, got)) return;
|
||||
if (g_testlib_shoulddebugbreak) DebugBreak();
|
||||
testlib_showerror(file, line, func, "assertLongDoubleEquals", "≠", gotcode,
|
||||
testlib_formatfloat(want), testlib_formatfloat(got));
|
||||
testlib_onfail2(isfatal);
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_TESTLIB_H_ */
|
197
libc/testlib/testlib.mk
Normal file
197
libc/testlib/testlib.mk
Normal file
|
@ -0,0 +1,197 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
# Description:
|
||||
# Cosmopolitan Testing Library.
|
||||
|
||||
PKGS += LIBC_TESTLIB
|
||||
|
||||
#───────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
LIBC_TESTLIB_ARTIFACTS += LIBC_TESTLIB_A
|
||||
LIBC_TESTLIB = $(LIBC_TESTLIB_A_DEPS) $(LIBC_TESTLIB_A)
|
||||
LIBC_TESTLIB_A = o/$(MODE)/libc/testlib/testlib.a
|
||||
LIBC_TESTLIB_A_CHECKS = $(LIBC_TESTLIB_A).pkg
|
||||
|
||||
LIBC_TESTLIB_A_ASSETS = \
|
||||
libc/testlib/hyperion.txt
|
||||
|
||||
LIBC_TESTLIB_A_HDRS = \
|
||||
libc/testlib/bench.h \
|
||||
libc/testlib/ezbench.h \
|
||||
libc/testlib/hyperion.h \
|
||||
libc/testlib/testlib.h
|
||||
|
||||
LIBC_TESTLIB_A_SRCS_S = \
|
||||
libc/testlib/bench.S \
|
||||
libc/testlib/combo.S \
|
||||
libc/testlib/fixture.S \
|
||||
libc/testlib/hyperion.S \
|
||||
libc/testlib/testcase.S \
|
||||
libc/testlib/thrashcodecache.S \
|
||||
libc/testlib/thunks/assert_eq.S \
|
||||
libc/testlib/thunks/assert_false.S \
|
||||
libc/testlib/thunks/assert_ne.S \
|
||||
libc/testlib/thunks/assert_true.S \
|
||||
libc/testlib/thunks/expect_eq.S \
|
||||
libc/testlib/thunks/expect_false.S \
|
||||
libc/testlib/thunks/expect_ne.S \
|
||||
libc/testlib/thunks/expect_true.S \
|
||||
libc/testlib/thunks/free.S \
|
||||
libc/testlib/thunks/jump.S
|
||||
|
||||
LIBC_TESTLIB_A_SRCS_C = \
|
||||
libc/testlib/almostequallongdouble.c \
|
||||
libc/testlib/hexequals.c \
|
||||
libc/testlib/binequals.c \
|
||||
libc/testlib/formatbool.c \
|
||||
libc/testlib/formatrange.c \
|
||||
libc/testlib/globals.c \
|
||||
libc/testlib/incrementfailed.c \
|
||||
libc/testlib/formatfloat.c \
|
||||
libc/testlib/formatbinaryasglyphs.c \
|
||||
libc/testlib/formatbinaryashex.c \
|
||||
libc/testlib/formatint.c \
|
||||
libc/testlib/formatstr.c \
|
||||
libc/testlib/shoulddebugbreak.c \
|
||||
libc/testlib/showerror.c \
|
||||
libc/testlib/showerror_.c \
|
||||
libc/testlib/testmem.c \
|
||||
libc/testlib/strequals.c \
|
||||
libc/testlib/startswith.c \
|
||||
libc/testlib/endswith.c \
|
||||
libc/testlib/contains.c \
|
||||
libc/testlib/strcaseequals.c \
|
||||
libc/testlib/benchrunner.c \
|
||||
libc/testlib/testrunner.c \
|
||||
libc/testlib/comborunner.c \
|
||||
libc/testlib/fixturerunner.c \
|
||||
libc/testlib/ezbenchreport.c \
|
||||
libc/testlib/ezbenchcontrol.c
|
||||
|
||||
LIBC_TESTLIB_A_SRCS = \
|
||||
$(LIBC_TESTLIB_A_SRCS_S) \
|
||||
$(LIBC_TESTLIB_A_SRCS_C)
|
||||
|
||||
LIBC_TESTLIB_A_OBJS = \
|
||||
$(LIBC_TESTLIB_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(LIBC_TESTLIB_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||
$(LIBC_TESTLIB_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(LIBC_TESTLIB_A_ASSETS:%=o/$(MODE)/%.zip.o)
|
||||
|
||||
LIBC_TESTLIB_A_DIRECTDEPS = \
|
||||
APE_LIB \
|
||||
LIBC_ALG \
|
||||
LIBC_CALLS \
|
||||
LIBC_FMT \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_RAND \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_TIME \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_UNICODE \
|
||||
LIBC_X \
|
||||
LIBC_ZIPOS \
|
||||
THIRD_PARTY_DTOA
|
||||
|
||||
LIBC_TESTLIB_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_TESTLIB_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(LIBC_TESTLIB_A): \
|
||||
libc/testlib/ \
|
||||
$(LIBC_TESTLIB_A).pkg \
|
||||
$(LIBC_TESTLIB_A_OBJS)
|
||||
|
||||
$(LIBC_TESTLIB_A).pkg: \
|
||||
$(LIBC_TESTLIB_A_OBJS) \
|
||||
$(foreach x,$(LIBC_TESTLIB_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
#───────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
LIBC_TESTLIB_ARTIFACTS += LIBC_TESTLIB_RUNNER_A
|
||||
LIBC_TESTLIB_RUNNER = $(LIBC_TESTLIB_RUNNER_A_DEPS) $(LIBC_TESTLIB_RUNNER_A)
|
||||
LIBC_TESTLIB_RUNNER_A = o/$(MODE)/libc/testlib/runner.a
|
||||
LIBC_TESTLIB_RUNNER_A_SRCS = libc/testlib/runner.c
|
||||
LIBC_TESTLIB_RUNNER_A_CHECKS = $(LIBC_TESTLIB_RUNNER_A).pkg
|
||||
|
||||
LIBC_TESTLIB_RUNNER_A_OBJS = \
|
||||
$(LIBC_TESTLIB_RUNNER_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(LIBC_TESTLIB_RUNNER_A_SRCS:%.c=o/$(MODE)/%.o)
|
||||
|
||||
LIBC_TESTLIB_RUNNER_A_DIRECTDEPS = \
|
||||
LIBC_FMT \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_TESTLIB
|
||||
|
||||
LIBC_TESTLIB_RUNNER_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_TESTLIB_RUNNER_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(LIBC_TESTLIB_RUNNER_A): \
|
||||
libc/testlib/ \
|
||||
$(LIBC_TESTLIB_RUNNER_A).pkg \
|
||||
$(LIBC_TESTLIB_RUNNER_A_OBJS)
|
||||
|
||||
$(LIBC_TESTLIB_RUNNER_A).pkg: \
|
||||
$(LIBC_TESTLIB_RUNNER_A_OBJS) \
|
||||
$(foreach x,$(LIBC_TESTLIB_RUNNER_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
#───────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
LIBC_TESTLIB_ARTIFACTS += LIBC_TESTMAIN
|
||||
|
||||
LIBC_TESTMAIN = \
|
||||
$(LIBC_TESTMAIN_DEPS) \
|
||||
$(LIBC_TESTMAIN_OBJS)
|
||||
|
||||
LIBC_TESTMAIN_CHECKS = \
|
||||
o/$(MODE)/libc/testlib/testmain.pkg
|
||||
|
||||
LIBC_TESTMAIN_SRCS = \
|
||||
libc/testlib/testmain.c
|
||||
|
||||
LIBC_TESTMAIN_OBJS = \
|
||||
$(LIBC_TESTMAIN_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
o/$(MODE)/libc/testlib/testmain.o
|
||||
|
||||
LIBC_TESTMAIN_DIRECTDEPS = \
|
||||
LIBC_CALLS \
|
||||
LIBC_LOG \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STDIO \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_TESTLIB \
|
||||
LIBC_TESTLIB_RUNNER \
|
||||
THIRD_PARTY_GETOPT
|
||||
|
||||
LIBC_TESTMAIN_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_TESTMAIN_DIRECTDEPS),$($(x))))
|
||||
|
||||
o/$(MODE)/libc/testlib/testmain.pkg: \
|
||||
$(LIBC_TESTMAIN_OBJS) \
|
||||
$(foreach x,$(LIBC_TESTMAIN_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
#───────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
LIBC_TESTLIB_LIBS = $(foreach x,$(LIBC_TESTLIB_ARTIFACTS),$($(x)_A))
|
||||
LIBC_TESTLIB_ARCHIVES = $(foreach x,$(LIBC_TESTLIB_ARTIFACTS),$($(x)_A))
|
||||
LIBC_TESTLIB_SRCS = $(foreach x,$(LIBC_TESTLIB_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_TESTLIB_HDRS = $(foreach x,$(LIBC_TESTLIB_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_TESTLIB_CHECKS = $(foreach x,$(LIBC_TESTLIB_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_TESTLIB_OBJS = $(foreach x,$(LIBC_TESTLIB_ARTIFACTS),$($(x)_OBJS))
|
||||
$(LIBC_TESTLIB_OBJS): $(BUILD_FILES) libc/libc.mk
|
||||
|
||||
.PHONY: o/$(MODE)/libc/testlib
|
||||
o/$(MODE)/libc/testlib: $(LIBC_TESTLIB_LIBS) $(LIBC_TESTLIB_CHECKS)
|
82
libc/testlib/testmain.c
Normal file
82
libc/testlib/testmain.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/runtime/rbx.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
|
||||
#define USAGE \
|
||||
" [FLAGS]\n\
|
||||
\n\
|
||||
Flags:\n\
|
||||
\n\
|
||||
-b run benchmarks if tests pass\n\
|
||||
-h show this information\n\
|
||||
\n"
|
||||
|
||||
STATIC_YOINK("die");
|
||||
|
||||
static bool runbenchmarks_;
|
||||
|
||||
static testonly void PrintUsage(int rc, FILE *f) {
|
||||
fputs("Usage: ", f);
|
||||
fputs(program_invocation_name, f);
|
||||
fputs(USAGE, f);
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
static testonly void GetOpts(int argc, char *argv[]) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "?hb")) != -1) {
|
||||
switch (opt) {
|
||||
case 'b':
|
||||
runbenchmarks_ = true;
|
||||
break;
|
||||
case '?':
|
||||
case 'h':
|
||||
PrintUsage(EXIT_SUCCESS, stdout);
|
||||
default:
|
||||
PrintUsage(EX_USAGE, stderr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic test program main function.
|
||||
*/
|
||||
testonly int main(int argc, char *argv[]) {
|
||||
g_loglevel = kLogInfo;
|
||||
GetOpts(argc, argv);
|
||||
showcrashreports();
|
||||
g_testlib_shoulddebugbreak = IsDebuggerPresent(false);
|
||||
getpid$sysv(); /* make strace easier to read */
|
||||
testlib_runalltests();
|
||||
if (!g_testlib_failed && runbenchmarks_ && weaken(testlib_runallbenchmarks)) {
|
||||
weaken(testlib_runallbenchmarks)();
|
||||
}
|
||||
return min(255, g_testlib_failed);
|
||||
}
|
185
libc/testlib/testmem.c
Normal file
185
libc/testlib/testmem.c
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/bing.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/sysconf.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
struct TestMemoryStack g_testmem;
|
||||
struct TestMemoryStack g_testmem_trash;
|
||||
static struct TestAllocation g_testmem_scratch[2][8];
|
||||
static const char kMemZero[1];
|
||||
static bool g_atstartofpage;
|
||||
|
||||
static struct TestAllocation testmem_push(struct TestMemoryStack *stack,
|
||||
struct TestAllocation entry) {
|
||||
if (stack->i == stack->n) {
|
||||
if (!grow(&stack->p, &stack->n, sizeof(struct TestAllocation), 0)) abort();
|
||||
}
|
||||
return (stack->p[stack->i++] = entry);
|
||||
}
|
||||
|
||||
static struct TestAllocation testmem_pop(struct TestMemoryStack *stack) {
|
||||
assert(stack->i > 0);
|
||||
struct TestAllocation res = stack->p[--stack->i];
|
||||
return res;
|
||||
}
|
||||
|
||||
static void testmem_destroy(struct TestAllocation alloc) {
|
||||
if (munmap(alloc.mapaddr, alloc.mapsize) == -1) perror("munmap"), die();
|
||||
}
|
||||
|
||||
static struct TestAllocation talloc(size_t n) {
|
||||
struct TestAllocation alloc;
|
||||
if (n) {
|
||||
while (g_testmem_trash.i) {
|
||||
struct TestAllocation trash = testmem_pop(&g_testmem_trash);
|
||||
if (n <= trash.usersize) {
|
||||
return trash;
|
||||
} else {
|
||||
testmem_destroy(trash);
|
||||
}
|
||||
}
|
||||
alloc.mapsize = ROUNDUP(n + PAGESIZE * 2, FRAMESIZE);
|
||||
CHECK_NE(MAP_FAILED, (alloc.mapaddr = mapanon(alloc.mapsize)));
|
||||
CHECK_NE(-1, mprotect(alloc.mapaddr, PAGESIZE, PROT_NONE));
|
||||
CHECK_NE(-1, mprotect((char *)alloc.mapaddr + alloc.mapsize - PAGESIZE,
|
||||
PAGESIZE, PROT_NONE));
|
||||
alloc.useraddr = (char *)alloc.mapaddr + PAGESIZE;
|
||||
alloc.usersize = alloc.mapsize - PAGESIZE * 2;
|
||||
CHECK_GE(alloc.usersize, n);
|
||||
return alloc;
|
||||
} else {
|
||||
alloc.mapaddr = (/*unconst*/ void *)kMemZero;
|
||||
alloc.mapsize = 0;
|
||||
alloc.useraddr = (/*unconst*/ void *)kMemZero;
|
||||
alloc.usersize = 0;
|
||||
return alloc;
|
||||
}
|
||||
}
|
||||
|
||||
static void testmem_fini(void) {
|
||||
CHECK_EQ(0, g_testmem.i);
|
||||
free_s(&g_testmem.p);
|
||||
while (g_testmem_trash.i) {
|
||||
testmem_destroy(testmem_pop(&g_testmem_trash));
|
||||
}
|
||||
}
|
||||
|
||||
static void testmem_init(void) {
|
||||
atexit(testmem_fini);
|
||||
g_testmem.p = g_testmem_scratch[0];
|
||||
g_testmem.n = ARRAYLEN(g_testmem_scratch[0]);
|
||||
g_testmem_trash.p = g_testmem_scratch[1];
|
||||
g_testmem_trash.n = ARRAYLEN(g_testmem_scratch[1]);
|
||||
}
|
||||
|
||||
const void *const testmem_ctor[] initarray = {testmem_init};
|
||||
|
||||
FIXTURE(testmemory, triggerOffByOneArrayErrors) {
|
||||
/* automate testing buffer overflows *and* underflows */
|
||||
g_atstartofpage = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates memory with properties useful for testing.
|
||||
*
|
||||
* This returns a pointer 𝑝 where reading or writing to either 𝑝[-1] or
|
||||
* 𝑝[𝑛+𝟷] will immediately trigger a segmentation fault; and bytes are
|
||||
* initialized to 10100101 (A5).
|
||||
*
|
||||
* Implementation Details: Accomplishing this entails two things. First,
|
||||
* we grant each allocation a page granular memory mapping, with access
|
||||
* to the two adjacent pages disabled. Second, since hardware memory
|
||||
* protection isn't 1-byte granular, we add a fixture so each test runs
|
||||
* a second time; the first call we return a pointer where the data is
|
||||
* placed on the righthand side, and the second call we return the data
|
||||
* on the lefthand side, thereby allowing both underflow/overflow
|
||||
* off-by-one out-of-bounds accesses to be detected.
|
||||
*/
|
||||
void *tmalloc(size_t n) {
|
||||
struct TestAllocation alloc = talloc(n);
|
||||
memset(alloc.useraddr, 0xa5, alloc.usersize);
|
||||
testmem_push(&g_testmem, alloc);
|
||||
return (char *)alloc.useraddr + (g_atstartofpage ? 0 : alloc.usersize - n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as tmalloc() but guarantees a specific alignment.
|
||||
*
|
||||
* Reading or writing to either 𝑝[-1] or 𝑝[roundup(𝑛+𝟷,𝑎)] will
|
||||
* immediately trigger a segmentation fault.
|
||||
*
|
||||
* @param 𝑎 is alignment in bytes, e.g. 16
|
||||
* @param 𝑛 is number of bytes
|
||||
*/
|
||||
void *tmemalign(size_t a, size_t n) {
|
||||
/* TODO(jart): ASAN detect 𝑝[𝑛+𝟷] */
|
||||
return tmalloc(ROUNDUP(n, a));
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as tunbing() w/ alignment guarantee.
|
||||
*/
|
||||
void *tunbinga(size_t a, const char16_t *binglyphs) {
|
||||
size_t size;
|
||||
EXPECT_NE(0, (size = strlen16(binglyphs)));
|
||||
return unbingbuf(tmemalign(a, size), size, binglyphs, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes CP437 glyphs to bounds-checked binary buffer, e.g.
|
||||
*
|
||||
* char *mem = tunbing(u" ☺☻♥♦");
|
||||
* EXPECT_EQ(0, memcmp("\0\1\2\3\4", mem, 5));
|
||||
* tfree(mem);
|
||||
*
|
||||
* @see tunbing(), unbingstr(), unbing()
|
||||
*/
|
||||
void *tunbing(const char16_t *binglyphs) {
|
||||
return tunbinga(1, binglyphs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees memory allocated with tmalloc().
|
||||
* This needs to be called in LIFO order.
|
||||
* @param
|
||||
*/
|
||||
void(tfree)(void *p) {
|
||||
struct TestAllocation alloc;
|
||||
__tfree_check(p);
|
||||
alloc = testmem_pop(&g_testmem);
|
||||
if (alloc.mapsize) testmem_push(&g_testmem_trash, alloc);
|
||||
}
|
||||
|
||||
char *tstrdup(const char *s) {
|
||||
return strcpy(tmalloc(strlen(s) + 1), s);
|
||||
}
|
77
libc/testlib/testrunner.c
Normal file
77
libc/testlib/testrunner.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
void SetUp(void);
|
||||
void TearDown(void);
|
||||
|
||||
void testlib_finish(void) {
|
||||
if (g_testlib_failed) {
|
||||
fprintf(stderr, "%u / %u %s\n", g_testlib_failed, g_testlib_ran,
|
||||
"tests failed");
|
||||
}
|
||||
}
|
||||
|
||||
noreturn void testlib_abort(void) {
|
||||
int rc;
|
||||
testlib_finish();
|
||||
rc = min(255, g_testlib_failed);
|
||||
quick_exit(rc); /* so we don't run __testmemory_fini() */
|
||||
unreachable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all test case functions in sorted order.
|
||||
*/
|
||||
testonly void testlib_runtestcases(testfn_t *start, testfn_t *end,
|
||||
testfn_t warmup) {
|
||||
/**
|
||||
* getpid() calls are inserted to help visually see tests in traces
|
||||
* which can be performed on Linux, FreeBSD, OpenBSD, and XNU:
|
||||
*
|
||||
* strace -f o/default/test.com |& less
|
||||
* truss o/default/test.com |& less
|
||||
* ktrace -f trace o/default/test.com </dev/null; kdump -f trace | less
|
||||
* dtruss o/default/test.com |& less
|
||||
*
|
||||
* Test cases are iterable via a decentralized section. Your TEST()
|
||||
* macro inserts .testcase.SUITENAME sections into the binary which
|
||||
* the linker sorts into an array.
|
||||
*
|
||||
* @see ape/ape.lds
|
||||
*/
|
||||
const testfn_t *fn;
|
||||
for (fn = start; fn != end; ++fn) {
|
||||
if (weaken(SetUp)) weaken(SetUp)();
|
||||
errno = 0;
|
||||
SetLastError(0);
|
||||
getpid$sysv();
|
||||
if (warmup) warmup();
|
||||
(*fn)();
|
||||
getpid$sysv();
|
||||
if (weaken(TearDown)) weaken(TearDown)();
|
||||
}
|
||||
}
|
42
libc/testlib/thrashcodecache.S
Normal file
42
libc/testlib/thrashcodecache.S
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.testonly
|
||||
.yoink __FILE__
|
||||
|
||||
/ Empties L1 instruction cache.
|
||||
thrashcodecache:
|
||||
.leafprologue
|
||||
push %rbx
|
||||
xor %eax,%eax
|
||||
xor %ecx,%ecx
|
||||
cpuid
|
||||
/ pushpop 4,%rcx
|
||||
0: .rept 32768/(8+9)
|
||||
.byte 0x0f,0x1f,0x84,0,0,0,0,0 # fat nop x8
|
||||
.byte 0x66,0x0f,0x1f,0x84,0,0,0,0,0 # fat nop x9
|
||||
.endr
|
||||
/ loop 0b
|
||||
xor %eax,%eax
|
||||
xor %ecx,%ecx
|
||||
cpuid
|
||||
pop %rbx
|
||||
.leafepilogue
|
||||
.endfn thrashcodecache,globl
|
30
libc/testlib/thunks/assert_eq.S
Normal file
30
libc/testlib/thunks/assert_eq.S
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
.text.unlikely
|
||||
testlib_showerror_assert_eq:
|
||||
push $TRUE
|
||||
pushstr "ASSERT_EQ"
|
||||
pushstr "="
|
||||
jmp testlib_showerror_jump
|
||||
.endfn testlib_showerror_assert_eq,globl,hidden
|
||||
.previous
|
30
libc/testlib/thunks/assert_false.S
Normal file
30
libc/testlib/thunks/assert_false.S
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
.text.unlikely
|
||||
testlib_showerror_assert_false:
|
||||
push $TRUE
|
||||
pushstr "ASSERT_FALSE"
|
||||
pushstr "!"
|
||||
jmp testlib_showerror_jump
|
||||
.endfn testlib_showerror_assert_false,globl,hidden
|
||||
.previous
|
30
libc/testlib/thunks/assert_ne.S
Normal file
30
libc/testlib/thunks/assert_ne.S
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
.text.unlikely
|
||||
testlib_showerror_assert_ne:
|
||||
push $TRUE
|
||||
pushstr "ASSERT_NE"
|
||||
pushstr "≠"
|
||||
jmp testlib_showerror_jump
|
||||
.endfn testlib_showerror_assert_ne,globl,hidden
|
||||
.previous
|
30
libc/testlib/thunks/assert_true.S
Normal file
30
libc/testlib/thunks/assert_true.S
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
.text.unlikely
|
||||
testlib_showerror_assert_true:
|
||||
push $TRUE
|
||||
pushstr "ASSERT_TRUE"
|
||||
pushstr ""
|
||||
jmp testlib_showerror_jump
|
||||
.endfn testlib_showerror_assert_true,globl,hidden
|
||||
.previous
|
30
libc/testlib/thunks/expect_eq.S
Normal file
30
libc/testlib/thunks/expect_eq.S
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
.text.unlikely
|
||||
testlib_showerror_expect_eq:
|
||||
push $FALSE
|
||||
pushstr "EXPECT_EQ"
|
||||
pushstr "="
|
||||
jmp testlib_showerror_jump
|
||||
.endfn testlib_showerror_expect_eq,globl,hidden
|
||||
.previous
|
30
libc/testlib/thunks/expect_false.S
Normal file
30
libc/testlib/thunks/expect_false.S
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
.text.unlikely
|
||||
testlib_showerror_expect_false:
|
||||
push $FALSE
|
||||
pushstr "EXPECT_FALSE"
|
||||
pushstr "!"
|
||||
jmp testlib_showerror_jump
|
||||
.endfn testlib_showerror_expect_false,globl,hidden
|
||||
.previous
|
30
libc/testlib/thunks/expect_ne.S
Normal file
30
libc/testlib/thunks/expect_ne.S
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
.text.unlikely
|
||||
testlib_showerror_expect_ne:
|
||||
push $FALSE
|
||||
pushstr "EXPECT_NE"
|
||||
pushstr "≠"
|
||||
jmp testlib_showerror_jump
|
||||
.endfn testlib_showerror_expect_ne,globl,hidden
|
||||
.previous
|
30
libc/testlib/thunks/expect_true.S
Normal file
30
libc/testlib/thunks/expect_true.S
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
.text.unlikely
|
||||
testlib_showerror_expect_true:
|
||||
push $FALSE
|
||||
pushstr "EXPECT_TRUE"
|
||||
pushstr ""
|
||||
jmp testlib_showerror_jump
|
||||
.endfn testlib_showerror_expect_true,globl,hidden
|
||||
.previous
|
28
libc/testlib/thunks/free.S
Normal file
28
libc/testlib/thunks/free.S
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Delegates to free().
|
||||
/
|
||||
/ @note reduces make dependency toil caused by macros
|
||||
testlib_free:
|
||||
jmp free
|
||||
.endfn testlib_free,globl
|
30
libc/testlib/thunks/jump.S
Normal file
30
libc/testlib/thunks/jump.S
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
.text.unlikely
|
||||
testlib_showerror_jump:
|
||||
popstr testlib_showerror_symbol(%rip)
|
||||
popstr testlib_showerror_macro(%rip)
|
||||
pop testlib_showerror_isfatal(%rip)
|
||||
jmp testlib_showerror_
|
||||
.endfn testlib_showerror_jump,globl,hidden
|
||||
.previous
|
40
libc/testlib/ugly.h
Normal file
40
libc/testlib/ugly.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_TESTLIB_UGLY_H_
|
||||
#define COSMOPOLITAN_LIBC_TESTLIB_UGLY_H_
|
||||
#include "libc/macros.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#if defined(__GNUC__) || defined(__llvm__)
|
||||
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" /* j.f.c. */
|
||||
#endif
|
||||
#define _I(x) (TYPE_SIGNED(typeof(x)) ? (intmax_t)(x) : (uintmax_t)(x))
|
||||
|
||||
#define __TEST_ARRAY(S) \
|
||||
_Section(".piro.relo.sort.testcase.2." #S ",\"aw\",@init_array #")
|
||||
|
||||
#define __BENCH_ARRAY(S) \
|
||||
_Section(".piro.relo.sort.bench.2." #S ",\"aw\",@init_array #")
|
||||
|
||||
#define __TEST_PROTOTYPE(S, N, A) \
|
||||
testonly void S##_##N(void); \
|
||||
alignas(8) const void *const S##_##N##_ptr[] A(S) = {S##_##N}; \
|
||||
testonly void S##_##N(void)
|
||||
|
||||
#define __TEST_SECTION(NAME, CONTENT) \
|
||||
".section " NAME "\n" CONTENT "\n\t.previous\n"
|
||||
|
||||
#define __RELOSECTION(NAME, CONTENT) \
|
||||
__TEST_SECTION(".piro.relo.sort" NAME ",\"aw\",@progbits", CONTENT)
|
||||
|
||||
#define __ROSTR(STR) __TEST_SECTION(".rodata.str1.1,\"aSM\",@progbits,1", STR)
|
||||
|
||||
#define __FIXTURE(KIND, GROUP, ENTRY) \
|
||||
asm(__RELOSECTION("." KIND ".2." #GROUP #ENTRY, \
|
||||
"\t.quad\t1f\n" \
|
||||
"\t.quad\t2f\n" \
|
||||
"\t.quad\t" STRINGIFY(GROUP##_##ENTRY)) \
|
||||
__ROSTR("1:\t.asciz\t" STRINGIFY(#GROUP)) \
|
||||
__ROSTR("2:\t.asciz\t" STRINGIFY(#ENTRY))); \
|
||||
testonly void GROUP##_##ENTRY(void)
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_TESTLIB_UGLY_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue