mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-24 14:22:28 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
72
test/libc/runtime/arch_prctl_test.c
Normal file
72
test/libc/runtime/arch_prctl_test.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*-*- 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/dce.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(arch_prctl, fs) {
|
||||
if (IsLinux() || IsOpenbsd()) {
|
||||
uint64_t n, x;
|
||||
x = 0xdeadbeef;
|
||||
arch_prctl(ARCH_SET_FS, &x);
|
||||
ASSERT_NE(-1, arch_prctl(ARCH_GET_FS, (intptr_t)&n));
|
||||
ASSERT_EQ((intptr_t)&x, n);
|
||||
ASSERT_EQ(0xdeadbeef, fs((int64_t *)0));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(arch_prctl, pointerRebasingFs) {
|
||||
if (IsLinux() || IsOpenbsd()) {
|
||||
unsigned long s[] = {0x0706050403020100, 0x0f0e0d0c0b0a0908};
|
||||
ASSERT_EQ(0x0706050403020100, s[0]);
|
||||
ASSERT_EQ(0, arch_prctl(ARCH_SET_FS, 1));
|
||||
ASSERT_EQ(0x0807060504030201, fs(&s[0]));
|
||||
ASSERT_EQ(0, arch_prctl(ARCH_SET_FS, 2));
|
||||
ASSERT_EQ(0x0908070605040302, fs(&s[0]));
|
||||
intptr_t fs;
|
||||
ASSERT_EQ(0, arch_prctl(ARCH_GET_FS, &fs));
|
||||
ASSERT_EQ(2, fs);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(arch_prctl, gs) {
|
||||
if (IsLinux()) {
|
||||
uint64_t n, x;
|
||||
x = 0xdeadbeef;
|
||||
arch_prctl(ARCH_SET_GS, &x);
|
||||
ASSERT_NE(-1, arch_prctl(ARCH_GET_GS, (intptr_t)&n));
|
||||
ASSERT_EQ((intptr_t)&x, n);
|
||||
ASSERT_EQ(0xdeadbeef, gs((int64_t *)0));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(arch_prctl, pointerRebasing) {
|
||||
if (IsLinux()) {
|
||||
unsigned long s[] = {0x0706050403020100, 0x0f0e0d0c0b0a0908};
|
||||
ASSERT_EQ(0x0706050403020100, s[0]);
|
||||
ASSERT_EQ(0, arch_prctl(ARCH_SET_GS, 1));
|
||||
ASSERT_EQ(0x0807060504030201, gs(&s[0]));
|
||||
ASSERT_EQ(0, arch_prctl(ARCH_SET_GS, 2));
|
||||
ASSERT_EQ(0x0908070605040302, gs(&s[0]));
|
||||
intptr_t gs;
|
||||
ASSERT_EQ(0, arch_prctl(ARCH_GET_GS, &gs));
|
||||
ASSERT_EQ(2, gs);
|
||||
}
|
||||
}
|
105
test/libc/runtime/balloc_test.c
Normal file
105
test/libc/runtime/balloc_test.c
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*-*- 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/calls.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/runtime/buffer.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/xed/x86.h"
|
||||
|
||||
char *p;
|
||||
bool segfaulted_;
|
||||
struct GuardedBuffer b_;
|
||||
struct sigaction oldsegv_;
|
||||
struct XedDecodedInst xedd_;
|
||||
|
||||
void RestrictPage(void *addr, unsigned flags) {
|
||||
addr = (void *)rounddown((intptr_t)addr, PAGESIZE);
|
||||
EXPECT_NE(-1, mprotect(addr, PAGESIZE, flags));
|
||||
}
|
||||
|
||||
void OnSegLol(int sig, struct siginfo *si, struct ucontext *uc) {
|
||||
size_t i;
|
||||
uint8_t *rip;
|
||||
segfaulted_ = true;
|
||||
rip = (uint8_t *)uc->uc_mcontext.rip;
|
||||
RestrictPage(rip, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
ASSERT_EQ(XED_ERROR_NONE,
|
||||
xed_instruction_length_decode(xed_decoded_inst_zero_set_mode(
|
||||
&xedd_, XED_MACHINE_MODE_LONG_64),
|
||||
rip, XED_MAX_INSTRUCTION_BYTES));
|
||||
for (i = 0; i < xedd_.decoded_length; ++i) rip[i] = 0x90; /* NOP */
|
||||
RestrictPage(rip, PROT_READ | PROT_EXEC);
|
||||
}
|
||||
|
||||
void SetUp(void) {
|
||||
segfaulted_ = false;
|
||||
memset(&b_, 0, sizeof(b_));
|
||||
ASSERT_NE(-1, xsigaction(SIGSEGV, OnSegLol, SA_RESETHAND | SA_RESTART, 0,
|
||||
&oldsegv_));
|
||||
}
|
||||
|
||||
void TearDown(void) {
|
||||
EXPECT_NE(-1, sigaction(SIGSEGV, &oldsegv_, NULL));
|
||||
bfree(&b_);
|
||||
EXPECT_EQ(NULL, b_.p);
|
||||
}
|
||||
|
||||
TEST(balloc, createsGuardPage) {
|
||||
ASSERT_NE(NULL, (p = balloc(&b_, 1, 1)));
|
||||
EXPECT_EQ(p, b_.p);
|
||||
p[0] = '.';
|
||||
ASSERT_FALSE(segfaulted_);
|
||||
/* TODO(jart): fix me!!! */
|
||||
/* p[1 + __BIGGEST_ALIGNMENT__] = '!'; */
|
||||
/* EXPECT_TRUE(segfaulted_); */
|
||||
}
|
||||
|
||||
TEST(balloc, aligned_roundsUp) {
|
||||
ASSERT_NE(NULL, (p = balloc(&b_, 128, 1)));
|
||||
EXPECT_EQ(0, (intptr_t)b_.p & 127);
|
||||
p[127] = '.';
|
||||
ASSERT_FALSE(segfaulted_);
|
||||
/* TODO(jart): fix me!!! */
|
||||
/* p[128 + __BIGGEST_ALIGNMENT__] = '!'; */
|
||||
/* EXPECT_TRUE(segfaulted_); */
|
||||
}
|
||||
|
||||
TEST(balloc, multipleCalls_avoidsNeedlessSyscalls) {
|
||||
size_t c;
|
||||
c = g_syscount;
|
||||
ASSERT_NE(NULL, (p = balloc(&b_, 1, 31337)));
|
||||
EXPECT_GT(g_syscount, c);
|
||||
c = g_syscount;
|
||||
ASSERT_NE(NULL, (p = balloc(&b_, 1, 31337 / 2)));
|
||||
EXPECT_EQ(g_syscount, c);
|
||||
c = g_syscount;
|
||||
ASSERT_NE(NULL, (p = balloc(&b_, 1, 31337 * 2)));
|
||||
EXPECT_GT(g_syscount, c);
|
||||
}
|
81
test/libc/runtime/gc_test.c
Normal file
81
test/libc/runtime/gc_test.c
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*-*- 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/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/* TODO(jart): calling malloc_usable_size was a terrible idea */
|
||||
|
||||
TEST(todo_jart, broken_in_opt_native_mode) {
|
||||
(void)0;
|
||||
(void)0;
|
||||
}
|
||||
|
||||
int64_t fd;
|
||||
|
||||
TEST(gc, usageExample_c11) {
|
||||
fd = open("/dev/null", O_WRONLY);
|
||||
defer(close_s, &fd);
|
||||
char *msg = gc(xasprintf("%d + %d = %d", 2, 2, 2 + 2));
|
||||
write(fd, msg, strlen(msg));
|
||||
}
|
||||
|
||||
TEST(gc, checkMallocUsableSizeWorksTheWayWeHopeItDoes) {
|
||||
char *p = malloc(32);
|
||||
EXPECT_GE(malloc_usable_size(p), 32);
|
||||
free(p);
|
||||
EXPECT_GE(malloc_usable_size(p), 0);
|
||||
}
|
||||
|
||||
noinline void function1of1(char *p) {
|
||||
EXPECT_GE(malloc_usable_size(gc(p)), 32);
|
||||
}
|
||||
TEST(gc, testOne) {
|
||||
char *p = malloc(32);
|
||||
function1of1(p);
|
||||
EXPECT_EQ(malloc_usable_size(p), 0);
|
||||
}
|
||||
|
||||
noinline void function2of2(char *p1, char *p2) {
|
||||
EXPECT_GE(malloc_usable_size(p1), 32);
|
||||
EXPECT_GE(malloc_usable_size(p2), 64);
|
||||
gc(p2);
|
||||
EXPECT_GE(malloc_usable_size(p1), 32);
|
||||
EXPECT_GE(malloc_usable_size(p2), 64);
|
||||
}
|
||||
noinline void function1of2(char *p1, char *p2) {
|
||||
EXPECT_GE(malloc_usable_size(p1), 32);
|
||||
EXPECT_GE(malloc_usable_size(p2), 64);
|
||||
function2of2(gc(p1), p2);
|
||||
EXPECT_GE(malloc_usable_size(p1), 32);
|
||||
EXPECT_GE(malloc_usable_size(p2), 0);
|
||||
}
|
||||
TEST(gc, testTwo) {
|
||||
char *p1 = malloc(32);
|
||||
char *p2 = malloc(64);
|
||||
function1of2(p1, p2);
|
||||
EXPECT_GE(malloc_usable_size(p1), 0);
|
||||
EXPECT_GE(malloc_usable_size(p2), 0);
|
||||
}
|
171
test/libc/runtime/getdosargv_test.c
Normal file
171
test/libc/runtime/getdosargv_test.c
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*-*- 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/runtime/internal.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(getdosargv, empty) {
|
||||
size_t max = 4;
|
||||
size_t size = ARG_MAX;
|
||||
char *buf = tmalloc(size * sizeof(char));
|
||||
char **argv = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(0, getdosargv(u"", buf, size, argv, max));
|
||||
EXPECT_EQ(NULL, argv[0]);
|
||||
tfree(argv);
|
||||
tfree(buf);
|
||||
}
|
||||
|
||||
TEST(getdosargv, emptyish) {
|
||||
size_t max = 4;
|
||||
size_t size = ARG_MAX;
|
||||
char *buf = tmalloc(size * sizeof(char));
|
||||
char **argv = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(0, getdosargv(u" ", buf, size, argv, max));
|
||||
EXPECT_EQ(NULL, argv[0]);
|
||||
tfree(argv);
|
||||
tfree(buf);
|
||||
}
|
||||
|
||||
TEST(getdosargv, basicUsage) {
|
||||
size_t max = 4;
|
||||
size_t size = ARG_MAX;
|
||||
char *buf = tmalloc(size * sizeof(char));
|
||||
char **argv = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(3, getdosargv(u"a\t \"b c\" d ", buf, size, argv, max));
|
||||
EXPECT_STREQ("a", argv[0]);
|
||||
EXPECT_STREQ("b c", argv[1]);
|
||||
EXPECT_STREQ("d", argv[2]);
|
||||
EXPECT_EQ(NULL, argv[3]);
|
||||
tfree(argv);
|
||||
tfree(buf);
|
||||
}
|
||||
|
||||
TEST(getdosargv, advancedUsage) {
|
||||
size_t max = 4;
|
||||
size_t size = ARG_MAX;
|
||||
char *buf = tmalloc(size * sizeof(char));
|
||||
char **argv = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(2, getdosargv(u"(╯°□°)╯︵ ┻━┻", buf, size, argv, max));
|
||||
EXPECT_STREQ("(╯°□°)╯︵", argv[0]);
|
||||
EXPECT_STREQ("┻━┻", argv[1]);
|
||||
EXPECT_EQ(NULL, argv[2]);
|
||||
tfree(argv);
|
||||
tfree(buf);
|
||||
}
|
||||
|
||||
TEST(getdosargv, testAegeanGothicSupplementaryPlanes) {
|
||||
size_t max = 4; /* these symbols are almost as old as dos */
|
||||
size_t size = ARG_MAX;
|
||||
char *buf = tmalloc(size * sizeof(char));
|
||||
char **argv = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(2, getdosargv(u"𐄷𐄸𐄹𐄺𐄻𐄼 𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷", buf, size, argv, max));
|
||||
EXPECT_STREQ("𐄷𐄸𐄹𐄺𐄻𐄼", argv[0]);
|
||||
EXPECT_STREQ("𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷", argv[1]);
|
||||
EXPECT_EQ(NULL, argv[2]);
|
||||
tfree(argv);
|
||||
tfree(buf);
|
||||
}
|
||||
|
||||
TEST(getdosargv, realWorldUsage) {
|
||||
size_t max = 512;
|
||||
size_t size = ARG_MAX;
|
||||
char *buf = tmalloc(size * sizeof(char));
|
||||
char **argv = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(5, getdosargv(u"C:\\Users\\jtunn\\printargs.com oh yes yes yes",
|
||||
buf, size, argv, max));
|
||||
EXPECT_STREQ("C:\\Users\\jtunn\\printargs.com", argv[0]);
|
||||
EXPECT_STREQ("oh", argv[1]);
|
||||
EXPECT_STREQ("yes", argv[2]);
|
||||
EXPECT_STREQ("yes", argv[3]);
|
||||
EXPECT_STREQ("yes", argv[4]);
|
||||
EXPECT_EQ(NULL, argv[5]);
|
||||
tfree(argv);
|
||||
tfree(buf);
|
||||
}
|
||||
|
||||
TEST(getdosargv, bufferOverrun_countIsStillAccurate_truncatesMemoryWithGrace) {
|
||||
size_t max = 3;
|
||||
size_t size = 7;
|
||||
char *buf = tmalloc(size * sizeof(char));
|
||||
char **argv = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(3, getdosargv(u"a\t \"b c\" d ", buf, size, argv, max));
|
||||
EXPECT_STREQ("a", argv[0]);
|
||||
EXPECT_STREQ("b c", argv[1]);
|
||||
EXPECT_EQ(NULL, argv[2]);
|
||||
tfree(argv);
|
||||
tfree(buf);
|
||||
}
|
||||
|
||||
TEST(getdosargv, pureScanningMode) {
|
||||
size_t max = 0;
|
||||
size_t size = 0;
|
||||
char *buf = NULL;
|
||||
char **argv = NULL;
|
||||
EXPECT_EQ(3, getdosargv(u"a b c", buf, size, argv, max));
|
||||
}
|
||||
|
||||
TEST(getdosargv, justSlashQuote) {
|
||||
size_t max = 4, size = 16;
|
||||
char *buf = tmalloc(size * sizeof(char));
|
||||
char **argv = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(1, getdosargv(u"\"\\\\\\\"\"", buf, size, argv, max));
|
||||
EXPECT_STREQ("\\\"", argv[0]);
|
||||
tfree(argv);
|
||||
tfree(buf);
|
||||
}
|
||||
|
||||
TEST(getdosargv, quoteInMiddleOfArg_wontSplitArg) {
|
||||
size_t max = 4, size = 16;
|
||||
char *buf = tmalloc(size * sizeof(char));
|
||||
char **argv = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(1, getdosargv(u"hi\"\"there", buf, size, argv, max));
|
||||
EXPECT_STREQ("hithere", argv[0]);
|
||||
max = 4, size = 16;
|
||||
EXPECT_EQ(1, getdosargv(u"hi\" \"there", buf, size, argv, max));
|
||||
EXPECT_STREQ("hi there", argv[0]);
|
||||
tfree(argv);
|
||||
tfree(buf);
|
||||
}
|
||||
|
||||
TEST(getdosargv, waqQuoting1) {
|
||||
size_t max = 4;
|
||||
size_t size = ARG_MAX;
|
||||
char *buf = tmalloc(size * sizeof(char));
|
||||
char **argv = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(2,
|
||||
getdosargv(u"a\\\\\"\"\"\"\"\"\"\"b c\" d", buf, size, argv, max));
|
||||
EXPECT_STREQ("a\\\"\"b", argv[0]);
|
||||
EXPECT_STREQ("c d", argv[1]);
|
||||
EXPECT_EQ(NULL, argv[2]);
|
||||
tfree(argv);
|
||||
tfree(buf);
|
||||
}
|
||||
|
||||
TEST(getdosargv, waqQuoting2) {
|
||||
size_t max = 4;
|
||||
size_t size = ARG_MAX;
|
||||
char *buf = tmalloc(size * sizeof(char));
|
||||
char **argv = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(2, getdosargv(u"\"a\\\"b c\" d", buf, size, argv, max));
|
||||
EXPECT_STREQ("a\"b c", argv[0]);
|
||||
EXPECT_STREQ("d", argv[1]);
|
||||
EXPECT_EQ(NULL, argv[2]);
|
||||
tfree(argv);
|
||||
tfree(buf);
|
||||
}
|
103
test/libc/runtime/getdosenviron_test.c
Normal file
103
test/libc/runtime/getdosenviron_test.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*-*- 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/runtime/getdosenviron.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(getdosenviron, testOneVariable) {
|
||||
#define kEnv u"A=Und wird die Welt auch in Flammen stehen\0"
|
||||
size_t max = 2;
|
||||
size_t size = sizeof(kEnv) >> 1;
|
||||
char *block = tmalloc(size);
|
||||
char16_t *env = memcpy(tmalloc(sizeof(kEnv)), kEnv, sizeof(kEnv));
|
||||
char **envp = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(1, getdosenviron(env, block, size, envp, max));
|
||||
EXPECT_STREQ("A=Und wird die Welt auch in Flammen stehen", envp[0]);
|
||||
EXPECT_EQ(NULL, envp[1]);
|
||||
ASSERT_BINEQ(u"A=Und wird die Welt auch in Flammen stehen ", block);
|
||||
tfree(envp);
|
||||
tfree(env);
|
||||
tfree(block);
|
||||
#undef kEnv
|
||||
}
|
||||
|
||||
TEST(getdosenviron, testTwoVariables) {
|
||||
#define kEnv \
|
||||
(u"𐌰𐌱𐌲𐌳=Und wird die Welt auch in Flammen stehen\0" \
|
||||
u"𐌴𐌵𐌶𐌷=Wir werden wieder auferstehen\0")
|
||||
size_t max = 3;
|
||||
size_t size = 1024;
|
||||
char *block = tmalloc(size);
|
||||
char16_t *env = memcpy(tmalloc(sizeof(kEnv)), kEnv, sizeof(kEnv));
|
||||
char **envp = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(2, getdosenviron(env, block, size, envp, max));
|
||||
EXPECT_STREQ("𐌰𐌱𐌲𐌳=Und wird die Welt auch in Flammen stehen", envp[0]);
|
||||
EXPECT_STREQ("𐌴𐌵𐌶𐌷=Wir werden wieder auferstehen", envp[1]);
|
||||
EXPECT_EQ(NULL, envp[2]);
|
||||
tfree(envp);
|
||||
tfree(env);
|
||||
tfree(block);
|
||||
#undef kEnv
|
||||
}
|
||||
|
||||
TEST(getdosenviron, testOverrun_truncatesWithGrace) {
|
||||
#define kEnv u"A=Und wird die Welt auch in Flammen stehen\0"
|
||||
size_t max = 2;
|
||||
size_t size = sizeof(kEnv) >> 2;
|
||||
char *block = tmalloc(size);
|
||||
char16_t *env = memcpy(tmalloc(sizeof(kEnv)), kEnv, sizeof(kEnv));
|
||||
char **envp = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(1, getdosenviron(env, block, size, envp, max));
|
||||
EXPECT_STREQ("A=Und wird die Welt ", envp[0]);
|
||||
EXPECT_EQ(NULL, envp[1]);
|
||||
ASSERT_BINEQ(u"A=Und wird die Welt ", block);
|
||||
tfree(envp);
|
||||
tfree(env);
|
||||
tfree(block);
|
||||
#undef kEnv
|
||||
}
|
||||
|
||||
TEST(getdosenviron, testEmpty_doesntTouchMemory) {
|
||||
EXPECT_EQ(0, getdosenviron(u"", NULL, 0, NULL, 0));
|
||||
}
|
||||
|
||||
TEST(getdosenviron, testEmpty_zeroTerminatesWheneverPossible_1) {
|
||||
size_t max = 1;
|
||||
char **envp = tmalloc(max * sizeof(char *));
|
||||
EXPECT_EQ(0, getdosenviron(u"", NULL, 0, envp, max));
|
||||
EXPECT_EQ(NULL, envp[0]);
|
||||
tfree(envp);
|
||||
}
|
||||
|
||||
TEST(getdosenviron, testEmpty_zeroTerminatesWheneverPossible_2) {
|
||||
size_t size = 1;
|
||||
char *block = tmalloc(size);
|
||||
EXPECT_EQ(0, getdosenviron(u"", block, size, NULL, 0));
|
||||
EXPECT_BINEQ(u" ", block);
|
||||
tfree(block);
|
||||
}
|
||||
|
||||
TEST(getdosenviron, testEmpty_zeroTerminatesWheneverPossible_3) {
|
||||
size_t size = 2;
|
||||
char *block = tmalloc(size);
|
||||
EXPECT_EQ(0, getdosenviron(u"", block, size, NULL, 0));
|
||||
EXPECT_BINEQ(u" ", block);
|
||||
tfree(block);
|
||||
}
|
98
test/libc/runtime/grow_test.c
Normal file
98
test/libc/runtime/grow_test.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*-*- 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/pushpop.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(grow, testNull_hasAllocatingBehavior) {
|
||||
void *p = NULL;
|
||||
size_t capacity = 0;
|
||||
EXPECT_TRUE(grow(&p, &capacity, 1, 0));
|
||||
EXPECT_NE(NULL, p);
|
||||
EXPECT_EQ(32, capacity);
|
||||
free_s(&p);
|
||||
}
|
||||
|
||||
TEST(grow, testCapacity_isInUnits_withTerminatorGuarantee) {
|
||||
void *p = NULL;
|
||||
size_t capacity = 0;
|
||||
EXPECT_TRUE(grow(&p, &capacity, 8, 0));
|
||||
EXPECT_NE(NULL, p);
|
||||
EXPECT_EQ(32 / 8 + 1, capacity);
|
||||
free_s(&p);
|
||||
}
|
||||
|
||||
TEST(grow, testStackMemory_convertsToDynamic) {
|
||||
int A[] = {1, 2, 3};
|
||||
int *p = A;
|
||||
size_t capacity = ARRAYLEN(A);
|
||||
EXPECT_FALSE(isheap(p));
|
||||
EXPECT_TRUE(grow(&p, &capacity, sizeof(int), 0));
|
||||
EXPECT_TRUE(isheap(p));
|
||||
EXPECT_GT(capacity, ARRAYLEN(A));
|
||||
EXPECT_EQ(1, p[0]);
|
||||
EXPECT_EQ(2, p[1]);
|
||||
EXPECT_EQ(3, p[2]);
|
||||
p[0] = 7;
|
||||
EXPECT_EQ(1, A[0]);
|
||||
free(p);
|
||||
}
|
||||
|
||||
TEST(grow, testGrowth_clearsNewMemory) {
|
||||
size_t i, capacity = 123;
|
||||
char *p = malloc(capacity);
|
||||
memset(p, 'a', capacity);
|
||||
EXPECT_TRUE(grow(&p, &capacity, 1, 0));
|
||||
EXPECT_GT(capacity, 123);
|
||||
for (i = 0; i < 123; ++i) ASSERT_EQ('a', p[i]);
|
||||
for (i = 123; i < capacity; ++i) ASSERT_EQ(0, p[i]);
|
||||
free_s(&p);
|
||||
}
|
||||
|
||||
TEST(grow, testBonusParam_willGoAboveAndBeyond) {
|
||||
size_t capacity = 32;
|
||||
char *p = malloc(capacity);
|
||||
EXPECT_TRUE(grow(&p, &capacity, 1, 0));
|
||||
EXPECT_LT(capacity, 1024);
|
||||
free_s(&p);
|
||||
p = malloc((capacity = 32));
|
||||
EXPECT_TRUE(grow(&p, &capacity, 1, 1024));
|
||||
EXPECT_GT(capacity, 1024);
|
||||
free_s(&p);
|
||||
}
|
||||
|
||||
TEST(grow, testOverflow_returnsFalseAndDoesNotFree) {
|
||||
int A[] = {1, 2, 3};
|
||||
int *p = A;
|
||||
size_t capacity = ARRAYLEN(A);
|
||||
EXPECT_FALSE(isheap(p));
|
||||
EXPECT_FALSE(grow(&p, &capacity, pushpop(SIZE_MAX), 0));
|
||||
EXPECT_FALSE(isheap(p));
|
||||
EXPECT_EQ(capacity, ARRAYLEN(A));
|
||||
EXPECT_EQ(1, p[0]);
|
||||
EXPECT_EQ(2, p[1]);
|
||||
EXPECT_EQ(3, p[2]);
|
||||
free_s(&p);
|
||||
}
|
35
test/libc/runtime/heapsortcar_test.c
Normal file
35
test/libc/runtime/heapsortcar_test.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/alg/alg.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(heapsortcar, test) {
|
||||
int32_t A[][2] = {{4, 'a'}, {65, 'b'}, {2, 'c'}, {-31, 'd'}, {0, 'e'},
|
||||
{99, 'f'}, {2, 'g'}, {83, 'h'}, {782, 'i'}, {1, 'j'}};
|
||||
const int32_t B[][2] = {{-31, 'd'}, {0, 'e'}, {1, 'j'}, {2, 'c'},
|
||||
{2, 'g'}, {4, 'a'}, {65, 'b'}, {83, 'h'},
|
||||
{99, 'f'}, {782, 'i'}};
|
||||
unsigned n = ARRAYLEN(A);
|
||||
heapsortcar(A, n);
|
||||
ASSERT_EQ(0, memcmp(&A[0], &B[0], sizeof(A)));
|
||||
}
|
248
test/libc/runtime/itsatrap_test.c
Normal file
248
test/libc/runtime/itsatrap_test.c
Normal file
|
@ -0,0 +1,248 @@
|
|||
/*-*- 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/runtime/runtime.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Tests for arithmetic overflow traps.
|
||||
*
|
||||
* This module assumes -ftrapv, but not -fsanitize=undefined; since
|
||||
* Ubsan provides a superset trapping functionality, and therefore
|
||||
* overrides the prior. The nice thing about -ftrapv is that it doesn't
|
||||
* leak huge amounts of information into the binary. So it's appropriate
|
||||
* to enable in a release build.
|
||||
*
|
||||
* @note LLVM's implementation of the runtime for this crashes due to
|
||||
* relying on undefined behavior lool, the very thing the flag was
|
||||
* meant to help prevent, so we don't get punked by the compiler
|
||||
* @see __addvsi3, __mulvsi3, etc.
|
||||
*/
|
||||
|
||||
bool overflowed_;
|
||||
|
||||
void __on_arithmetic_overflow(void) {
|
||||
overflowed_ = true;
|
||||
}
|
||||
|
||||
void SetUp(void) {
|
||||
overflowed_ = false;
|
||||
}
|
||||
|
||||
/* 32-BIT SIGNED NEGATION */
|
||||
|
||||
TEST(__negvsi2, testMax) {
|
||||
EXPECT_EQ(-INT_MAX, -VEIL("r", INT_MAX));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__negvsi2, testMin0) {
|
||||
EXPROPRIATE(-VEIL("r", INT_MIN));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
/* 64-BIT SIGNED NEGATION */
|
||||
|
||||
TEST(__negvdi2, testMax) {
|
||||
EXPECT_EQ(-LONG_MAX, -VEIL("r", LONG_MAX));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__negvdi2, testMin0) {
|
||||
EXPROPRIATE(-VEIL("r", LONG_MIN));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
/* 32-BIT SIGNED MULTIPLICATION */
|
||||
|
||||
TEST(__mulvsi3, testMin0) {
|
||||
EXPECT_EQ(0, 0 * VEIL("r", INT_MIN));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, testMin1) {
|
||||
EXPECT_EQ(INT_MIN, 1 * VEIL("r", INT_MIN));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, testMin2) {
|
||||
EXPROPRIATE(2 * VEIL("r", INT_MIN));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, testMax0) {
|
||||
EXPECT_EQ(0, 0 * VEIL("r", INT_MAX));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, testMax1) {
|
||||
EXPECT_EQ(INT_MAX, 1 * VEIL("r", INT_MAX));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, testMax2) {
|
||||
EXPROPRIATE(2 * VEIL("r", INT_MAX));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, test7) {
|
||||
EXPECT_EQ(0x70000000, 7 * VEIL("r", 0x10000000));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, test8) {
|
||||
EXPROPRIATE(8 * VEIL("r", 0x10000000));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, test31337) {
|
||||
EXPROPRIATE(0x31337 * VEIL("r", 0x31337));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, standAndDeliver_aNegativeTimesANegativeEqualsAPositive) {
|
||||
EXPECT_EQ(25, -5 * VEIL("r", -5));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
/* 64-BIT SIGNED MULTIPLICATION */
|
||||
|
||||
TEST(__mulvdi3, testMin0) {
|
||||
EXPECT_EQ(0, 0 * VEIL("r", LONG_MIN));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, testMin1) {
|
||||
EXPECT_EQ(LONG_MIN, 1 * VEIL("r", LONG_MIN));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, testMin2) {
|
||||
EXPROPRIATE(2 * VEIL("r", LONG_MIN));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, testMax0) {
|
||||
EXPECT_EQ(0, 0 * VEIL("r", LONG_MAX));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, testMax1) {
|
||||
EXPECT_EQ(LONG_MAX, 1 * VEIL("r", LONG_MAX));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, testMax2) {
|
||||
EXPROPRIATE(2 * VEIL("r", LONG_MAX));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, test7) {
|
||||
EXPECT_EQ(0x7000000000000000l, 7 * VEIL("r", 0x1000000000000000l));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, test8) {
|
||||
EXPROPRIATE(8 * VEIL("r", 0x1000000000000000l));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, test31337) {
|
||||
EXPROPRIATE(0x3133700000000l * VEIL("r", 0x3133700000000l));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, standAndDeliver_aNegativeTimesANegativeEqualsAPositive) {
|
||||
EXPECT_EQ(25l, -5l * VEIL("r", -5l));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
/* 32-BIT SIGNED ADDITION */
|
||||
|
||||
TEST(__addvsi3, testMin1) {
|
||||
EXPECT_EQ(INT_MIN + 1, 1 + VEIL("r", INT_MIN));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__addvsi3, testMax1) {
|
||||
EXPROPRIATE(1 + VEIL("r", INT_MAX));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__addvsi3, testNegPos) {
|
||||
EXPECT_EQ(2, -2 + VEIL("r", 4));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__addvsi3, testPosNeg) {
|
||||
EXPECT_EQ(-2, 2 + VEIL("r", -4));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
/* 64-BIT SIGNED ADDITION */
|
||||
|
||||
TEST(__addvdi3, testMin1) {
|
||||
EXPECT_EQ(LONG_MIN + 1, 1 + VEIL("r", LONG_MIN));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__addvdi3, testMax1) {
|
||||
EXPROPRIATE(1 + VEIL("r", LONG_MAX));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__addvdi3, testNegPos) {
|
||||
EXPECT_EQ(2l, -2l + VEIL("r", 4l));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__addvdi3, testPosNeg) {
|
||||
EXPECT_EQ(-2l, 2l + VEIL("r", -4l));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
/* 32-BIT SIGNED SUBTRACTION */
|
||||
|
||||
TEST(__subvsi3, testMin1) {
|
||||
EXPROPRIATE(VEIL("r", INT_MIN) - 1);
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__subvsi3, testMax1) {
|
||||
EXPECT_EQ(INT_MAX - 1, VEIL("r", INT_MAX) - 1);
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__subvsi3, testPosNeg) {
|
||||
EXPECT_EQ(-2, 2 - VEIL("r", 4));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
/* 64-BIT SIGNED SUBTRACTION */
|
||||
|
||||
TEST(__subvdi3, testMin1) {
|
||||
EXPROPRIATE(VEIL("r", LONG_MIN) - 1);
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__subvdi3, testMax1) {
|
||||
EXPECT_EQ(LONG_MAX - 1, VEIL("r", LONG_MAX) - 1);
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
58
test/libc/runtime/mappings_test.c
Normal file
58
test/libc/runtime/mappings_test.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*-*- 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/limits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
#define ADDR
|
||||
|
||||
struct MemoryCoord stack = ADDRSIZE_TO_COORD(0x7fffffff0000L, 0x00010000);
|
||||
struct MemoryCoord heap3 = ADDRSIZE_TO_COORD(0x200000020000L, 0x00010000);
|
||||
struct MemoryCoord heap2 = ADDRSIZE_TO_COORD(0x200000010000L, 0x00010000);
|
||||
struct MemoryCoord heap1 = ADDRSIZE_TO_COORD(0x200000000000L, 0x00010000);
|
||||
struct MemoryCoord heapa = ADDRSIZE_TO_COORD(0x200000000000L, 0x00030000);
|
||||
struct MemoryCoord progg = ADDRSIZE_TO_COORD(0x000000400000L, 0x00010000);
|
||||
struct MemoryCoord bane = ADDRSIZE_TO_COORD(0xffff800000080000L, 0x00010000);
|
||||
|
||||
TEST(isoverlapping, test) {
|
||||
EXPECT_FALSE(ISOVERLAPPING(stack, heap3));
|
||||
EXPECT_FALSE(ISOVERLAPPING(heap1, heap2));
|
||||
EXPECT_FALSE(ISOVERLAPPING(heap2, heap3));
|
||||
EXPECT_FALSE(ISOVERLAPPING(heap1, heap3));
|
||||
EXPECT_TRUE(ISOVERLAPPING(heapa, heap1));
|
||||
EXPECT_TRUE(ISOVERLAPPING(heapa, heap3));
|
||||
}
|
||||
|
||||
TEST(findmapping, limits) {
|
||||
ASSERT_EQ(INT_MAX, ADDR_TO_COORD(0x7fffffff0000L));
|
||||
ASSERT_EQ(INT_MIN, ADDR_TO_COORD(-0x800000000000L));
|
||||
}
|
||||
|
||||
TEST(findmapping, test) {
|
||||
struct MemoryCoord c[] = {bane, progg, heap1, heap2, heap3, stack};
|
||||
EXPECT_EQ(6, ARRAYLEN(c));
|
||||
EXPECT_EQ(0, findmapping_(ADDR_TO_COORD(-0x800000000000UL), c, 6));
|
||||
EXPECT_EQ(1, findmapping_(ADDR_TO_COORD(-42), c, 6));
|
||||
EXPECT_EQ(1, findmapping_(ADDR_TO_COORD(0x000000300000L), c, 6));
|
||||
EXPECT_EQ(2, findmapping_(ADDR_TO_COORD(0x000000400000L), c, 6));
|
||||
EXPECT_EQ(6, findmapping_(ADDR_TO_COORD(0x7fffffffffffL), c, 6));
|
||||
}
|
146
test/libc/runtime/mmap_test.c
Normal file
146
test/libc/runtime/mmap_test.c
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*-*- 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/xchg.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/msync.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
unsigned m1;
|
||||
|
||||
TEST(mmap, testMapUnmapAnonAnyAddr) {
|
||||
void *p;
|
||||
m1 = _mm.i;
|
||||
EXPECT_NE(MAP_FAILED, (p = mmap(NULL, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)));
|
||||
EXPECT_EQ(m1 + 1, _mm.i);
|
||||
EXPECT_NE(-1, munmap(p, FRAMESIZE));
|
||||
EXPECT_EQ(m1 + 0, _mm.i);
|
||||
}
|
||||
|
||||
TEST(mmap, testMunmapUnmapsMultiple) {
|
||||
void *p1, *p2;
|
||||
m1 = _mm.i;
|
||||
EXPECT_NE(MAP_FAILED, (p1 = mmap(NULL, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)));
|
||||
EXPECT_NE(MAP_FAILED, (p2 = mmap(NULL, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)));
|
||||
if ((intptr_t)p1 > (intptr_t)p2) xchg(&p1, &p2);
|
||||
EXPECT_EQ(m1 + 2, _mm.i);
|
||||
EXPECT_NE(-1, munmap(p1, (intptr_t)p2 + (intptr_t)FRAMESIZE - (intptr_t)p1));
|
||||
EXPECT_EQ(m1 + 0, _mm.i);
|
||||
}
|
||||
|
||||
TEST(mmap, testPartialUnmapRight) {
|
||||
if (1) return; /* naaah */
|
||||
char *p;
|
||||
m1 = _mm.i;
|
||||
EXPECT_NE(MAP_FAILED, (p = mmap(NULL, FRAMESIZE * 2, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)));
|
||||
EXPECT_EQ(m1 + 1, _mm.i);
|
||||
EXPECT_NE(-1, munmap(p + FRAMESIZE, FRAMESIZE));
|
||||
EXPECT_EQ(m1 + 1, _mm.i);
|
||||
EXPECT_NE(-1, munmap(p, FRAMESIZE));
|
||||
EXPECT_EQ(m1 + 0, _mm.i);
|
||||
}
|
||||
|
||||
TEST(mmap, testPartialUnmapLeft) {
|
||||
if (1) return; /* naaah */
|
||||
char *p;
|
||||
m1 = _mm.i;
|
||||
EXPECT_NE(MAP_FAILED, (p = mmap(NULL, FRAMESIZE * 2, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)));
|
||||
EXPECT_EQ(m1 + 1, _mm.i);
|
||||
EXPECT_NE(-1, munmap(p, FRAMESIZE));
|
||||
EXPECT_EQ(m1 + 1, _mm.i);
|
||||
EXPECT_NE(-1, munmap(p + FRAMESIZE, FRAMESIZE));
|
||||
EXPECT_EQ(m1 + 0, _mm.i);
|
||||
}
|
||||
|
||||
TEST(mmap, testMapFile) {
|
||||
int fd;
|
||||
char *p;
|
||||
char path[PATH_MAX];
|
||||
sprintf(path, "%s%s.%d", kTmpPath, program_invocation_short_name, getpid());
|
||||
m1 = _mm.i;
|
||||
ASSERT_NE(-1, (fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644)));
|
||||
EXPECT_EQ(5, write(fd, "hello", 5));
|
||||
EXPECT_NE(-1, fdatasync(fd));
|
||||
EXPECT_NE(MAP_FAILED, (p = mmap(NULL, 5, PROT_READ, MAP_PRIVATE, fd, 0)));
|
||||
EXPECT_EQ(m1 + 1, _mm.i);
|
||||
EXPECT_STREQ("hello", p);
|
||||
EXPECT_NE(-1, munmap(p, 5));
|
||||
EXPECT_EQ(m1 + 0, _mm.i);
|
||||
EXPECT_NE(-1, close(fd));
|
||||
EXPECT_NE(-1, unlink(path));
|
||||
}
|
||||
|
||||
TEST(mmap, testMapFile_fdGetsClosed_makesNoDifference) {
|
||||
int fd;
|
||||
char *p, buf[16], path[PATH_MAX];
|
||||
sprintf(path, "%s%s.%d", kTmpPath, program_invocation_short_name, getpid());
|
||||
m1 = _mm.i;
|
||||
ASSERT_NE(-1, (fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644)));
|
||||
EXPECT_EQ(5, write(fd, "hello", 5));
|
||||
EXPECT_NE(-1, fdatasync(fd));
|
||||
EXPECT_NE(MAP_FAILED,
|
||||
(p = mmap(NULL, 5, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)));
|
||||
EXPECT_NE(-1, close(fd));
|
||||
EXPECT_EQ(m1 + 1, _mm.i);
|
||||
EXPECT_STREQ("hello", p);
|
||||
p[1] = 'a';
|
||||
EXPECT_NE(-1, msync(p, PAGESIZE, MS_SYNC));
|
||||
ASSERT_NE(-1, (fd = open(path, O_RDONLY)));
|
||||
EXPECT_EQ(5, read(fd, buf, 5));
|
||||
EXPECT_STREQN("hallo", buf, 5);
|
||||
EXPECT_NE(-1, close(fd));
|
||||
EXPECT_NE(-1, munmap(p, 5));
|
||||
EXPECT_EQ(m1 + 0, _mm.i);
|
||||
EXPECT_NE(-1, unlink(path));
|
||||
}
|
||||
|
||||
TEST(mmap, testMapFixed_destroysEverythingInItsPath) {
|
||||
m1 = _mm.i;
|
||||
EXPECT_NE(MAP_FAILED, mmap((void *)(kFixedMappingsStart + FRAMESIZE * 0),
|
||||
FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
|
||||
EXPECT_NE(MAP_FAILED, mmap((void *)(kFixedMappingsStart + FRAMESIZE * 1),
|
||||
FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
|
||||
EXPECT_NE(MAP_FAILED, mmap((void *)(kFixedMappingsStart + FRAMESIZE * 2),
|
||||
FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
|
||||
ASSERT_EQ(m1 + 3, _mm.i);
|
||||
EXPECT_NE(MAP_FAILED, mmap((void *)(kFixedMappingsStart + FRAMESIZE * 0),
|
||||
FRAMESIZE * 3, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
|
||||
ASSERT_EQ(m1 + 1, _mm.i);
|
||||
EXPECT_NE(-1, munmap((void *)kFixedMappingsStart, FRAMESIZE * 3));
|
||||
}
|
48
test/libc/runtime/ringalloc_test.c
Normal file
48
test/libc/runtime/ringalloc_test.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/runtime/ring.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(ringalloc, testMagic) {
|
||||
char *p;
|
||||
size_t n;
|
||||
struct RingBuffer ring = {};
|
||||
n = FRAMESIZE * 2;
|
||||
EXPECT_NE(NULL, ringalloc(&ring, n));
|
||||
if ((p = ring.p)) {
|
||||
EXPECT_EQ(0, p[0]);
|
||||
EXPECT_EQ(0, p[7]);
|
||||
EXPECT_EQ(0, p[n + 0]);
|
||||
EXPECT_EQ(0, p[n + 7]);
|
||||
p[0] = 23;
|
||||
p[7] = 123;
|
||||
EXPECT_EQ(23, p[0]);
|
||||
EXPECT_EQ(123, p[7]);
|
||||
EXPECT_EQ(23, p[n + 0]);
|
||||
EXPECT_EQ(123, p[n + 7]);
|
||||
}
|
||||
EXPECT_NE(-1, ringfree(&ring));
|
||||
}
|
||||
|
||||
TEST(ringalloc, testFrameSized) {
|
||||
struct RingBuffer ring = {};
|
||||
EXPECT_NE(NULL, ringalloc(&ring, FRAMESIZE));
|
||||
EXPECT_NE(-1, ringfree(&ring));
|
||||
}
|
71
test/libc/runtime/test.mk
Normal file
71
test/libc/runtime/test.mk
Normal file
|
@ -0,0 +1,71 @@
|
|||
#-*-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───────────────────────┘
|
||||
|
||||
PKGS += TEST_LIBC_RUNTIME
|
||||
|
||||
TEST_LIBC_RUNTIME_SRCS := $(wildcard test/libc/runtime/*.c)
|
||||
TEST_LIBC_RUNTIME_SRCS_TEST = $(filter %_test.c,$(TEST_LIBC_RUNTIME_SRCS))
|
||||
TEST_LIBC_RUNTIME_COMS = $(TEST_LIBC_RUNTIME_OBJS:%.o=%.com)
|
||||
|
||||
TEST_LIBC_RUNTIME_OBJS = \
|
||||
$(TEST_LIBC_RUNTIME_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(TEST_LIBC_RUNTIME_SRCS:%.c=o/$(MODE)/%.o)
|
||||
|
||||
TEST_LIBC_RUNTIME_BINS = \
|
||||
$(TEST_LIBC_RUNTIME_COMS) \
|
||||
$(TEST_LIBC_RUNTIME_COMS:%=%.dbg)
|
||||
|
||||
TEST_LIBC_RUNTIME_TESTS = \
|
||||
$(TEST_LIBC_RUNTIME_SRCS_TEST:%.c=o/$(MODE)/%.com.ok)
|
||||
|
||||
TEST_LIBC_RUNTIME_CHECKS = \
|
||||
$(TEST_LIBC_RUNTIME_SRCS_TEST:%.c=o/$(MODE)/%.com.runs)
|
||||
|
||||
TEST_LIBC_RUNTIME_DIRECTDEPS = \
|
||||
LIBC_CALLS \
|
||||
LIBC_CALLS_HEFTY \
|
||||
LIBC_FMT \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_TESTLIB \
|
||||
LIBC_X \
|
||||
THIRD_PARTY_XED
|
||||
|
||||
TEST_LIBC_RUNTIME_DEPS := \
|
||||
$(call uniq,$(foreach x,$(TEST_LIBC_RUNTIME_DIRECTDEPS),$($(x))))
|
||||
|
||||
o/$(MODE)/test/libc/runtime/runtime.pkg: \
|
||||
$(TEST_LIBC_RUNTIME_OBJS) \
|
||||
$(foreach x,$(TEST_LIBC_RUNTIME_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/test/libc/runtime/%.com.dbg: \
|
||||
$(TEST_LIBC_RUNTIME_DEPS) \
|
||||
o/$(MODE)/test/libc/runtime/%.o \
|
||||
o/$(MODE)/test/libc/runtime/runtime.pkg \
|
||||
$(LIBC_TESTMAIN) \
|
||||
$(CRT) \
|
||||
$(APE)
|
||||
@$(APELINK)
|
||||
|
||||
$(TEST_LIBC_RUNTIME_OBJS): \
|
||||
DEFAULT_CCFLAGS += \
|
||||
-fno-builtin
|
||||
|
||||
o/$(MODE)/test/libc/runtime/getenv_test.com.runs: \
|
||||
o/$(MODE)/test/libc/runtime/getenv_test.com
|
||||
@HELLO=THERE build/runit $@ $<
|
||||
|
||||
o/$(MODE)/test/libc/runtime/itsatrap_test.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fno-sanitize=all \
|
||||
-ftrapv
|
||||
|
||||
.PHONY: o/$(MODE)/test/libc/runtime
|
||||
o/$(MODE)/test/libc/runtime: \
|
||||
$(TEST_LIBC_RUNTIME_BINS) \
|
||||
$(TEST_LIBC_RUNTIME_CHECKS)
|
Loading…
Add table
Add a link
Reference in a new issue