mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-28 08:12:28 +00:00
Make fixes and improvements
- Invent iso8601us() for faster timestamps - Improve --strace descriptions of sigset_t - Rebuild the Landlock Make bootstrap binary - Introduce MODE=sysv for non-Windows builds - Permit OFD fcntl() locks under pledge(flock) - redbean can now protect your kernel from ddos - Have vfork() fallback to sys_fork() not fork() - Change kmalloc() to not die when out of memory - Improve documentation for some termios functions - Rewrite putenv() and friends to conform to POSIX - Fix linenoise + strace verbosity issue on Windows - Fix regressions in our ability to show backtraces - Change redbean SetHeader() to no-op if value is nil - Improve fcntl() so SQLite locks work in non-WAL mode - Remove some unnecessary work during fork() on Windows - Create redbean-based SSL reverse proxy for IPv4 TurfWar - Fix ape/apeinstall.sh warning when using non-bash shells - Add ProgramTrustedIp(), and IsTrustedIp() APIs to redbean - Support $PWD, $UID, $GID, and $EUID in command interpreter - Introduce experimental JTqFpD APE prefix for non-Windows builds - Invent blackhole daemon for firewalling IP addresses via UNIX named socket - Add ProgramTokenBucket(), AcquireToken(), and CountTokens() APIs to redbean
This commit is contained in:
parent
648bf6555c
commit
f7ff77d865
209 changed files with 3818 additions and 998 deletions
|
@ -36,7 +36,7 @@ void SetUpOnce(void) {
|
|||
|
||||
TEST(access, efault) {
|
||||
ASSERT_SYS(EFAULT, -1, access(0, F_OK));
|
||||
if (IsWindows() && !IsAsan()) return; // not possible
|
||||
if (IsWindows() || !IsAsan()) return; // not possible
|
||||
ASSERT_SYS(EFAULT, -1, access((void *)77, F_OK));
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ void SetUpOnce(void) {
|
|||
|
||||
TEST(chdir, efault) {
|
||||
ASSERT_SYS(EFAULT, -1, chdir(0));
|
||||
if (IsWindows() && !IsAsan()) return; // not possible
|
||||
if (IsWindows() || !IsAsan()) return; // not possible
|
||||
ASSERT_SYS(EFAULT, -1, chdir((void *)77));
|
||||
}
|
||||
|
||||
|
|
168
test/libc/calls/lock2_test.c
Normal file
168
test/libc/calls/lock2_test.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*-*- 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 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/subprocess.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
TEST(lock, wholeFile) {
|
||||
char buf[512];
|
||||
ASSERT_SYS(0, 3, open("db", O_RDWR | O_CREAT | O_EXCL, 0644));
|
||||
ASSERT_SYS(0, 0, fcntl(3, F_SETLK, &(struct flock){.l_type = F_RDLCK}));
|
||||
ASSERT_SYS(0, 0, fcntl(3, F_SETLK, &(struct flock){.l_type = F_UNLCK}));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(lock, testUpgradeFromReadToWriteLock) {
|
||||
char buf[512];
|
||||
ASSERT_SYS(0, 3, open("db", O_RDWR | O_CREAT | O_EXCL, 0644));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(3, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_RDLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(3, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(lock, testUpgradeWriteToWriteLock) {
|
||||
char buf[512];
|
||||
ASSERT_SYS(0, 3, open("db", O_RDWR | O_CREAT | O_EXCL, 0644));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(3, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(3, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(lock, unlockEverything_unlocksSmallerRanges) {
|
||||
int fd, pi[2];
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, creat("db", 0644));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 0, pipe(pi));
|
||||
SPAWN(fork);
|
||||
ASSERT_SYS(0, 5, open("db", O_RDWR));
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
ASSERT_SYS(0, 8, read(3, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(5, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(5, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000005,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0, close(5));
|
||||
PARENT();
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_NE(-1, (fd = open("db", O_RDWR)));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(fd, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(fd, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000005,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(fd, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_UNLCK,
|
||||
}));
|
||||
ASSERT_SYS(0, 8, write(4, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
WAIT(exit, 0);
|
||||
ASSERT_SYS(0, 0, close(fd));
|
||||
}
|
||||
|
||||
TEST(lock, close_releasesLocks) {
|
||||
int fd, pi[2];
|
||||
char buf[8] = {0};
|
||||
ASSERT_SYS(0, 3, creat("db", 0644));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 0, pipe(pi));
|
||||
SPAWN(fork);
|
||||
ASSERT_SYS(0, 5, open("db", O_RDWR));
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
ASSERT_SYS(0, 8, read(3, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(5, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0, close(5));
|
||||
PARENT();
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_NE(-1, (fd = open("db", O_RDWR)));
|
||||
ASSERT_SYS(0, 0,
|
||||
fcntl(fd, F_SETLK,
|
||||
&(struct flock){
|
||||
.l_type = F_WRLCK,
|
||||
.l_start = 0x40000000,
|
||||
.l_len = 1,
|
||||
}));
|
||||
ASSERT_SYS(0, 0, close(fd));
|
||||
ASSERT_SYS(0, 8, write(4, buf, 8));
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
WAIT(exit, 0);
|
||||
}
|
207
test/libc/calls/lock_ofd_test.c
Normal file
207
test/libc/calls/lock_ofd_test.c
Normal file
|
@ -0,0 +1,207 @@
|
|||
/*-*- 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 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Better Advisory Locks Test
|
||||
*/
|
||||
|
||||
#define PROCESSES 8
|
||||
#define THREADS 8 // <-- THIS
|
||||
#define RATIO 3
|
||||
#define ITERATIONS 10
|
||||
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
_Thread_local const char *kind;
|
||||
|
||||
bool SupportsOfdLocks(void) {
|
||||
int e;
|
||||
bool r;
|
||||
if (!IsLinux()) return false;
|
||||
// F_OFD_* was introduced in linux 3.15
|
||||
// getrandom() was introduced in linux 3.17
|
||||
// testing for getrandom() should be a sure thing w/o creating an fd
|
||||
e = errno;
|
||||
r = !sys_getrandom(0, 0, 0);
|
||||
errno = e;
|
||||
return r;
|
||||
}
|
||||
|
||||
void SetUp(void) {
|
||||
if (!SupportsOfdLocks()) {
|
||||
kprintf("ofd locks not supported on this system\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Log(const char *fmt, ...) {
|
||||
#if 0
|
||||
va_list va;
|
||||
char b[512];
|
||||
int i, n = sizeof(b);
|
||||
va_start(va, fmt);
|
||||
i = ksnprintf(b, n, "%s pid=%d tid=%d ", kind, getpid(), gettid());
|
||||
i += kvsnprintf(b + i, MAX(0, n - i), fmt, va);
|
||||
i += ksnprintf(b + i, MAX(0, n - i), "\n");
|
||||
write(2, b, MIN(i, n));
|
||||
va_end(va);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Lock(int fd, int type, long start, long len) {
|
||||
int e;
|
||||
struct flock lock = {
|
||||
.l_type = type,
|
||||
.l_whence = SEEK_SET,
|
||||
.l_start = start,
|
||||
.l_len = len,
|
||||
};
|
||||
e = errno;
|
||||
while (fcntl(fd, F_OFD_SETLK, &lock)) {
|
||||
ASSERT_TRUE(errno == EAGAIN || errno == EACCES);
|
||||
errno = e;
|
||||
Log("flock spinning on %d", fd);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteLock(int fd, long start, long len) {
|
||||
Lock(fd, F_WRLCK, start, len);
|
||||
Log("acquired write lock on %d", fd);
|
||||
}
|
||||
|
||||
void ReadLock(int fd, long start, long len) {
|
||||
Lock(fd, F_RDLCK, start, len);
|
||||
Log("acquired read lock on %d", fd);
|
||||
}
|
||||
|
||||
void Unlock(int fd, long start, long len) {
|
||||
Lock(fd, F_UNLCK, start, len);
|
||||
Log("released lock on %d", fd);
|
||||
}
|
||||
|
||||
void *Reader(void *arg) {
|
||||
int i, j, fd;
|
||||
char buf[10];
|
||||
kind = arg;
|
||||
ASSERT_NE(-1, (fd = open("db", O_RDONLY)));
|
||||
for (j = 0; j < ITERATIONS; ++j) {
|
||||
ReadLock(fd, 10, 10);
|
||||
for (i = 0; i < 10; ++i) {
|
||||
ASSERT_SYS(0, 1, pread(fd, buf + i, 1, 10 + i));
|
||||
ASSERT_EQ(buf[0], buf[i]);
|
||||
}
|
||||
Unlock(fd, 10, 10);
|
||||
sched_yield();
|
||||
}
|
||||
ASSERT_SYS(0, 0, close(fd));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *Writer(void *arg) {
|
||||
int i, j, fd;
|
||||
char buf[10];
|
||||
kind = arg;
|
||||
ASSERT_NE(-1, (fd = open("db", O_RDWR)));
|
||||
for (j = 0; j < ITERATIONS; ++j) {
|
||||
WriteLock(fd, 10, 10);
|
||||
for (i = 0; i < 10; ++i) {
|
||||
ASSERT_SYS(0, 1, pread(fd, buf + i, 1, 10 + i));
|
||||
ASSERT_EQ(buf[0], buf[i]);
|
||||
}
|
||||
for (i = 0; i < 10; ++i) {
|
||||
buf[i]++;
|
||||
}
|
||||
for (i = 0; i < 10; ++i) {
|
||||
ASSERT_SYS(0, 1, pwrite(fd, buf + i, 1, 10 + i));
|
||||
}
|
||||
Unlock(fd, 10, 10);
|
||||
sched_yield();
|
||||
}
|
||||
ASSERT_SYS(0, 0, close(fd));
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(posixAdvisoryLocks, threadsAndProcessesFightingForLock) {
|
||||
int i, rc, pid, fd, ws;
|
||||
pthread_t th[THREADS + 1];
|
||||
|
||||
ASSERT_SYS(0, 3, creat("db", 0644));
|
||||
ASSERT_SYS(0, 0, ftruncate(3, 30));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
|
||||
for (i = 0; i < THREADS; ++i) {
|
||||
if (i % RATIO == 0) {
|
||||
ASSERT_EQ(0, pthread_create(th + i, 0, Reader, "reader thread"));
|
||||
} else {
|
||||
ASSERT_EQ(0, pthread_create(th + i, 0, Writer, "writer thread"));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < PROCESSES; ++i) {
|
||||
ASSERT_NE(-1, (rc = fork()));
|
||||
if (!rc) {
|
||||
if (i % RATIO == 0) {
|
||||
Writer("writer process");
|
||||
} else {
|
||||
Reader("reader process");
|
||||
}
|
||||
_Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_NE(-1, (fd = open("db", O_RDWR)));
|
||||
Lock(fd, F_WRLCK, 0, 10);
|
||||
Lock(fd, F_WRLCK, 20, 10);
|
||||
|
||||
for (i = 0; i < THREADS; ++i) {
|
||||
ASSERT_EQ(0, pthread_join(th[i], 0));
|
||||
}
|
||||
|
||||
kind = "main process";
|
||||
for (;;) {
|
||||
int e = errno;
|
||||
if ((pid = waitpid(0, &ws, 0)) != -1) {
|
||||
if (WIFSIGNALED(ws)) {
|
||||
Log("process %d terminated with %G", pid, WTERMSIG(ws));
|
||||
testlib_incrementfailed();
|
||||
} else if (WEXITSTATUS(ws)) {
|
||||
Log("process %d exited with %d", pid, WEXITSTATUS(ws));
|
||||
testlib_incrementfailed();
|
||||
}
|
||||
} else {
|
||||
ASSERT_EQ(ECHILD, errno);
|
||||
errno = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_SYS(0, 0, close(fd));
|
||||
}
|
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
|
||||
#define PROCESSES 8
|
||||
#define THREADS (IsWindows() ? 8 : 0)
|
||||
#define THREADS 0 // <-- consider F_OFD_* locks
|
||||
#define RATIO 3
|
||||
#define ITERATIONS 10
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ void SetUpOnce(void) {
|
|||
|
||||
TEST(open, efault) {
|
||||
ASSERT_SYS(EFAULT, -1, open(0, O_RDONLY));
|
||||
if (IsWindows() && !IsAsan()) return; // not possible
|
||||
if (IsWindows() || !IsAsan()) return; // not possible
|
||||
ASSERT_SYS(EFAULT, -1, open((void *)77, O_RDONLY));
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
|
@ -175,3 +176,27 @@ TEST(sigaction, ignoringSignalDiscardsSignal) {
|
|||
ASSERT_EQ(0, sigprocmask(SIG_UNBLOCK, &blocked, NULL));
|
||||
EXPECT_EQ(0, OnSignalCnt);
|
||||
}
|
||||
|
||||
TEST(sigaction, autoZombieSlayer) {
|
||||
if (IsWindows()) return;
|
||||
int pid;
|
||||
struct sigaction sa;
|
||||
// make sure we're starting in expected state
|
||||
ASSERT_SYS(0, 0, sigaction(SIGCHLD, 0, &sa));
|
||||
ASSERT_EQ(SIG_DFL, sa.sa_handler);
|
||||
// verify child becomes zombie
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) _Exit(0);
|
||||
ASSERT_SYS(0, pid, wait(0));
|
||||
// enable automatic zombie slayer
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sa.sa_flags = SA_NOCLDWAIT; // seems to be optional
|
||||
sigemptyset(&sa.sa_mask);
|
||||
ASSERT_SYS(0, 0, sigaction(SIGCHLD, &sa, &sa));
|
||||
// verify it works
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) _Exit(0);
|
||||
ASSERT_SYS(ECHILD, -1, wait(0));
|
||||
// clean up
|
||||
ASSERT_SYS(0, 0, sigaction(SIGCHLD, &sa, 0));
|
||||
}
|
||||
|
|
|
@ -117,6 +117,12 @@ o/$(MODE)/test/libc/calls/fcntl_test.com.runs: \
|
|||
o/$(MODE)/test/libc/calls/lock_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc flock
|
||||
|
||||
o/$(MODE)/test/libc/calls/lock2_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc flock
|
||||
|
||||
o/$(MODE)/test/libc/calls/lock_ofd_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc flock
|
||||
|
||||
o/$(MODE)/test/libc/calls/openbsd_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc unveil
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ void SetUpOnce(void) {
|
|||
|
||||
TEST(unlink, efault) {
|
||||
ASSERT_SYS(EFAULT, -1, unlink(0));
|
||||
if (IsWindows() && !IsAsan()) return; // not possible
|
||||
if (IsWindows() || !IsAsan()) return; // not possible
|
||||
ASSERT_SYS(EFAULT, -1, unlink((void *)77));
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
@ -25,7 +26,7 @@
|
|||
TEST(DescribeSigset, full) {
|
||||
sigset_t ss;
|
||||
sigfillset(&ss);
|
||||
EXPECT_STREQ("~{}", DescribeSigset(0, &ss));
|
||||
EXPECT_STREQ("~{ABRT,KILL,STOP}", DescribeSigset(0, &ss));
|
||||
}
|
||||
|
||||
TEST(DescribeSigset, present) {
|
||||
|
@ -41,5 +42,9 @@ TEST(DescribeSigset, absent) {
|
|||
sigfillset(&ss);
|
||||
sigdelset(&ss, SIGINT);
|
||||
sigdelset(&ss, SIGUSR1);
|
||||
EXPECT_STREQ("~{INT,USR1}", DescribeSigset(0, &ss));
|
||||
if (IsBsd()) {
|
||||
EXPECT_STREQ("~{INT,ABRT,KILL,STOP,USR1}", DescribeSigset(0, &ss));
|
||||
} else {
|
||||
EXPECT_STREQ("~{INT,ABRT,KILL,USR1,STOP}", DescribeSigset(0, &ss));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/intrin.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "libc/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/intrin/intrin.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/intrin.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(putenv, test) {
|
||||
|
@ -31,3 +32,38 @@ TEST(putenv, test) {
|
|||
EXPECT_EQ(0, setenv("hi", "therethree", 0));
|
||||
EXPECT_STREQ("therethree", getenv("hi"));
|
||||
}
|
||||
|
||||
TEST(putenv, usesProvidedMemory) {
|
||||
char kv[32] = "hi=hello";
|
||||
EXPECT_EQ(0, putenv(kv));
|
||||
EXPECT_STREQ("hello", getenv("hi"));
|
||||
strcpy(kv, "hi=there");
|
||||
EXPECT_STREQ("there", getenv("hi"));
|
||||
EXPECT_EQ(0, unsetenv("hi"));
|
||||
EXPECT_EQ(0, unsetenv("hi"));
|
||||
EXPECT_EQ(0, getenv("hi"));
|
||||
EXPECT_EQ(0, clearenv());
|
||||
}
|
||||
|
||||
TEST(putenv, keyonly) {
|
||||
EXPECT_EQ(0, clearenv());
|
||||
EXPECT_EQ(0, putenv("hi"));
|
||||
EXPECT_STREQ("", getenv("hi"));
|
||||
EXPECT_STREQ("hi", environ[0]);
|
||||
EXPECT_EQ(0, environ[1]);
|
||||
EXPECT_EQ(0, unsetenv("hi"));
|
||||
EXPECT_EQ(0, getenv("hi"));
|
||||
EXPECT_EQ(0, environ[0]);
|
||||
EXPECT_EQ(0, environ[1]);
|
||||
}
|
||||
|
||||
TEST(putenv, environ) {
|
||||
char *s = strdup("hi=there");
|
||||
EXPECT_EQ(0, clearenv());
|
||||
EXPECT_EQ(0, putenv(s));
|
||||
EXPECT_EQ(0, putenv(s));
|
||||
EXPECT_EQ(s, environ[0]);
|
||||
EXPECT_EQ(0, environ[1]);
|
||||
EXPECT_EQ(0, clearenv());
|
||||
free(s);
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
|
|
126
test/libc/mem/sortedints_test.c
Normal file
126
test/libc/mem/sortedints_test.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*-*- 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 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/mem/sortedints.internal.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
struct SortedInts T;
|
||||
|
||||
void TearDown(void) {
|
||||
free(T.p);
|
||||
bzero(&T, sizeof(T));
|
||||
}
|
||||
|
||||
TEST(sortedints, test) {
|
||||
EXPECT_TRUE(InsertInt(&T, 3, false));
|
||||
EXPECT_TRUE(InsertInt(&T, 1, false));
|
||||
EXPECT_TRUE(InsertInt(&T, -1, false));
|
||||
EXPECT_TRUE(InsertInt(&T, 2, false));
|
||||
EXPECT_EQ(4, T.n);
|
||||
EXPECT_EQ(-1, T.p[0]);
|
||||
EXPECT_EQ(+1, T.p[1]);
|
||||
EXPECT_EQ(+2, T.p[2]);
|
||||
EXPECT_EQ(+3, T.p[3]);
|
||||
EXPECT_FALSE(ContainsInt(&T, -2));
|
||||
EXPECT_TRUE(ContainsInt(&T, -1));
|
||||
EXPECT_FALSE(ContainsInt(&T, 0));
|
||||
EXPECT_TRUE(ContainsInt(&T, 1));
|
||||
EXPECT_TRUE(ContainsInt(&T, 2));
|
||||
EXPECT_TRUE(ContainsInt(&T, 3));
|
||||
EXPECT_FALSE(ContainsInt(&T, 4));
|
||||
}
|
||||
|
||||
TEST(sortedints, unique) {
|
||||
EXPECT_TRUE(InsertInt(&T, INT_MAX, true));
|
||||
EXPECT_TRUE(InsertInt(&T, 1, true));
|
||||
EXPECT_FALSE(InsertInt(&T, INT_MAX, true));
|
||||
EXPECT_TRUE(InsertInt(&T, INT_MIN, true));
|
||||
EXPECT_FALSE(InsertInt(&T, 1, true));
|
||||
EXPECT_TRUE(InsertInt(&T, 2, true));
|
||||
EXPECT_EQ(4, T.n);
|
||||
EXPECT_EQ(INT_MIN, T.p[0]);
|
||||
EXPECT_EQ(+1, T.p[1]);
|
||||
EXPECT_EQ(+2, T.p[2]);
|
||||
EXPECT_EQ(INT_MAX, T.p[3]);
|
||||
EXPECT_FALSE(ContainsInt(&T, -2));
|
||||
EXPECT_TRUE(ContainsInt(&T, INT_MIN));
|
||||
EXPECT_FALSE(ContainsInt(&T, 0));
|
||||
EXPECT_TRUE(ContainsInt(&T, 1));
|
||||
EXPECT_TRUE(ContainsInt(&T, 2));
|
||||
EXPECT_TRUE(ContainsInt(&T, INT_MAX));
|
||||
EXPECT_FALSE(ContainsInt(&T, 4));
|
||||
EXPECT_EQ(1, CountInt(&T, 1));
|
||||
EXPECT_EQ(0, CountInt(&T, -5));
|
||||
}
|
||||
|
||||
TEST(sortedints, bag) {
|
||||
EXPECT_TRUE(InsertInt(&T, INT_MAX, false));
|
||||
EXPECT_TRUE(InsertInt(&T, 1, false));
|
||||
EXPECT_TRUE(InsertInt(&T, INT_MAX, false));
|
||||
EXPECT_TRUE(InsertInt(&T, INT_MIN, false));
|
||||
EXPECT_TRUE(InsertInt(&T, 1, false));
|
||||
EXPECT_TRUE(InsertInt(&T, 2, false));
|
||||
EXPECT_EQ(6, T.n);
|
||||
EXPECT_EQ(INT_MIN, T.p[0]);
|
||||
EXPECT_EQ(1, T.p[1]);
|
||||
EXPECT_EQ(1, T.p[2]);
|
||||
EXPECT_EQ(2, T.p[3]);
|
||||
EXPECT_EQ(INT_MAX, T.p[4]);
|
||||
EXPECT_EQ(INT_MAX, T.p[5]);
|
||||
EXPECT_FALSE(ContainsInt(&T, -2));
|
||||
EXPECT_TRUE(ContainsInt(&T, INT_MIN));
|
||||
EXPECT_FALSE(ContainsInt(&T, 0));
|
||||
EXPECT_TRUE(ContainsInt(&T, 1));
|
||||
EXPECT_TRUE(ContainsInt(&T, 2));
|
||||
EXPECT_TRUE(ContainsInt(&T, INT_MAX));
|
||||
EXPECT_FALSE(ContainsInt(&T, 4));
|
||||
EXPECT_EQ(1, CountInt(&T, INT_MIN));
|
||||
EXPECT_EQ(2, CountInt(&T, 1));
|
||||
EXPECT_EQ(0, CountInt(&T, -5));
|
||||
}
|
||||
|
||||
TEST(sortedints, fuzz) {
|
||||
for (int i = 0; i < 10000; ++i) {
|
||||
volatile bool b;
|
||||
volatile int y, x = lemur64();
|
||||
InsertInt(&T, x, x & 1);
|
||||
b = ContainsInt(&T, x);
|
||||
b = ContainsInt(&T, -x);
|
||||
y = CountInt(&T, x);
|
||||
}
|
||||
for (int i = 1; i < T.n; ++i) {
|
||||
ASSERT_GE(T.p[i], T.p[i - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
BENCH(sortedints, bench) {
|
||||
volatile int x;
|
||||
EZBENCH2("overhead", donothing, x = lemur64());
|
||||
EZBENCH2("insert small", donothing, InsertInt(&T, lemur64(), true));
|
||||
EZBENCH2("contains small", donothing, ContainsInt(&T, lemur64()));
|
||||
for (int i = 0; i < 20000; ++i) {
|
||||
InsertInt(&T, lemur64(), true);
|
||||
}
|
||||
EZBENCH2("insert big", donothing, InsertInt(&T, lemur64(), true));
|
||||
EZBENCH2("contains big", donothing, ContainsInt(&T, lemur64()));
|
||||
}
|
|
@ -61,6 +61,8 @@ TEST(opendir, enotdir) {
|
|||
TEST(opendir, zipTest_fake) {
|
||||
ASSERT_NE(NULL, (dir = opendir("/zip")));
|
||||
EXPECT_NE(NULL, (ent = readdir(dir)));
|
||||
EXPECT_STREQ(".cosmo", ent->d_name);
|
||||
EXPECT_NE(NULL, (ent = readdir(dir)));
|
||||
EXPECT_STREQ("echo", ent->d_name);
|
||||
EXPECT_NE(NULL, (ent = readdir(dir)));
|
||||
EXPECT_STREQ("usr", ent->d_name);
|
||||
|
@ -68,6 +70,8 @@ TEST(opendir, zipTest_fake) {
|
|||
EXPECT_EQ(0, closedir(dir));
|
||||
ASSERT_NE(NULL, (dir = opendir("/zip/")));
|
||||
EXPECT_NE(NULL, (ent = readdir(dir)));
|
||||
EXPECT_STREQ(".cosmo", ent->d_name);
|
||||
EXPECT_NE(NULL, (ent = readdir(dir)));
|
||||
EXPECT_STREQ("echo", ent->d_name);
|
||||
EXPECT_NE(NULL, (ent = readdir(dir)));
|
||||
EXPECT_STREQ("usr", ent->d_name);
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "libc/thread/thread.h"
|
||||
#include "libc/thread/thread2.h"
|
||||
|
||||
// TODO(jart): Can we make this test go faster on NetBSD?
|
||||
|
||||
int pos;
|
||||
int count;
|
||||
int limit;
|
||||
|
@ -77,7 +79,7 @@ long Get(struct timespec *abs_deadline) {
|
|||
return v;
|
||||
}
|
||||
|
||||
#define N 10000
|
||||
#define N 1000
|
||||
|
||||
void *Producer(void *arg) {
|
||||
for (int i = 0; i < N; i++) {
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/thread/spawn.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
|
51
test/libc/time/iso8601_test.c
Normal file
51
test/libc/time/iso8601_test.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*-*- 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 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/time/struct/tm.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
TEST(iso8601, test) {
|
||||
char p[20];
|
||||
struct tm tm;
|
||||
int64_t t = 0x62820bcd;
|
||||
gmtime_r(&t, &tm);
|
||||
EXPECT_EQ(p + 19, iso8601(p, &tm));
|
||||
EXPECT_STREQ("2022-05-16T08:31:09", p);
|
||||
}
|
||||
|
||||
TEST(iso8601us, test) {
|
||||
char p[27];
|
||||
struct tm tm;
|
||||
int64_t t = 0x62820bcd;
|
||||
gmtime_r(&t, &tm);
|
||||
EXPECT_EQ(p + 26, iso8601us(p, &tm, 1234000));
|
||||
EXPECT_STREQ("2022-05-16T08:31:09.001234", p);
|
||||
}
|
||||
|
||||
BENCH(iso8601, bench) {
|
||||
char p[27];
|
||||
struct tm tm;
|
||||
int64_t t = 0x62820bcd;
|
||||
gmtime_r(&t, &tm);
|
||||
EZBENCH2("iso8601", donothing, iso8601(p, &tm));
|
||||
EZBENCH2("iso8601us", donothing, iso8601us(p, &tm, 123456));
|
||||
EZBENCH2("strftime", donothing,
|
||||
strftime(p, sizeof(p), "%Y-%m-%dT%H:%M:%S", &tm));
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- 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 2021 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
|
@ -17,11 +17,12 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "tool/build/lib/isnocompressext.h"
|
||||
#include "net/http/http.h"
|
||||
|
||||
TEST(IsNoCompressExt, test) {
|
||||
EXPECT_TRUE(IsNoCompressExt("MP4", -1));
|
||||
EXPECT_TRUE(IsNoCompressExt("mp4", -1));
|
||||
EXPECT_FALSE(IsNoCompressExt("dog", -1));
|
||||
EXPECT_TRUE(IsNoCompressExt("dog.mp4", -1));
|
||||
EXPECT_FALSE(IsNoCompressExt("dog.mp4mp4mp4", -1));
|
||||
}
|
|
@ -41,7 +41,7 @@
|
|||
#include "third_party/regex/regex.h"
|
||||
|
||||
STATIC_YOINK("zip_uri_support");
|
||||
STATIC_YOINK("o/" MODE "/tool/net/redbean.com");
|
||||
STATIC_YOINK("o/" MODE "/test/tool/net/redbean-tester.com");
|
||||
|
||||
char testlib_enable_tmp_setup_teardown_once;
|
||||
int port;
|
||||
|
@ -52,9 +52,9 @@ void SetUpOnce(void) {
|
|||
char buf[1024];
|
||||
int fdin, fdout;
|
||||
ASSERT_NE(-1, mkdir("bin", 0755));
|
||||
ASSERT_NE(-1,
|
||||
(fdin = open("/zip/o/" MODE "/tool/net/redbean.com", O_RDONLY)));
|
||||
ASSERT_NE(-1, (fdout = creat("bin/redbean.com", 0755)));
|
||||
ASSERT_NE(-1, (fdin = open("/zip/o/" MODE "/test/tool/net/redbean-tester.com",
|
||||
O_RDONLY)));
|
||||
ASSERT_NE(-1, (fdout = creat("bin/redbean-tester.com", 0755)));
|
||||
for (;;) {
|
||||
ASSERT_NE(-1, (n = read(fdin, buf, sizeof(buf))));
|
||||
if (!n) break;
|
||||
|
@ -93,6 +93,7 @@ char *SendHttpRequest(const char *s) {
|
|||
bool Matches(const char *regex, const char *str) {
|
||||
bool r;
|
||||
regex_t re;
|
||||
printf("%s\n", str);
|
||||
EXPECT_EQ(REG_OK, regcomp(&re, regex, 0));
|
||||
r = regexec(&re, str, 0, 0, 0) == REG_OK;
|
||||
regfree(&re);
|
||||
|
@ -113,14 +114,12 @@ TEST(redbean, testOptions) {
|
|||
close(0);
|
||||
open("/dev/null", O_RDWR);
|
||||
close(1);
|
||||
dup(0);
|
||||
close(2);
|
||||
open("log", O_CREAT | O_TRUNC | O_WRONLY | O_APPEND, 0644);
|
||||
close(pipefds[0]);
|
||||
dup2(pipefds[1], 1);
|
||||
sigprocmask(SIG_SETMASK, &savemask, NULL);
|
||||
execv("bin/redbean.com",
|
||||
(char *const[]){"bin/redbean.com", "-vvszp0", "-l127.0.0.1", 0});
|
||||
execv("bin/redbean-tester.com",
|
||||
(char *const[]){"bin/redbean-tester.com", "-vvszXp0", "-l127.0.0.1",
|
||||
__strace > 0 ? "--strace" : 0, 0});
|
||||
_exit(127);
|
||||
}
|
||||
EXPECT_NE(-1, close(pipefds[1]));
|
||||
|
@ -139,7 +138,6 @@ TEST(redbean, testOptions) {
|
|||
EXPECT_NE(-1, kill(pid, SIGTERM));
|
||||
EXPECT_NE(-1, wait(0));
|
||||
EXPECT_NE(-1, sigprocmask(SIG_SETMASK, &savemask, 0));
|
||||
if (g_testlib_failed) fputs(gc(xslurp("log", 0)), stderr);
|
||||
}
|
||||
|
||||
TEST(redbean, testPipeline) {
|
||||
|
@ -155,13 +153,12 @@ TEST(redbean, testPipeline) {
|
|||
setpgrp();
|
||||
close(0);
|
||||
open("/dev/null", O_RDWR);
|
||||
close(2);
|
||||
open("log", O_CREAT | O_TRUNC | O_WRONLY | O_APPEND, 0644);
|
||||
close(pipefds[0]);
|
||||
dup2(pipefds[1], 1);
|
||||
sigprocmask(SIG_SETMASK, &savemask, NULL);
|
||||
execv("bin/redbean.com",
|
||||
(char *const[]){"bin/redbean.com", "-vvszp0", "-l127.0.0.1", 0});
|
||||
execv("bin/redbean-tester.com",
|
||||
(char *const[]){"bin/redbean-tester.com", "-vvszXp0", "-l127.0.0.1",
|
||||
__strace > 0 ? "--strace" : 0, 0});
|
||||
_exit(127);
|
||||
}
|
||||
EXPECT_NE(-1, close(pipefds[1]));
|
||||
|
@ -189,5 +186,85 @@ TEST(redbean, testPipeline) {
|
|||
EXPECT_NE(-1, kill(pid, SIGTERM));
|
||||
EXPECT_NE(-1, wait(0));
|
||||
EXPECT_NE(-1, sigprocmask(SIG_SETMASK, &savemask, 0));
|
||||
if (g_testlib_failed) fputs(gc(xslurp("log", 0)), stderr);
|
||||
}
|
||||
|
||||
TEST(redbean, testContentRange) {
|
||||
if (IsWindows()) return;
|
||||
char portbuf[16];
|
||||
int pid, pipefds[2];
|
||||
sigset_t chldmask, savemask;
|
||||
sigaddset(&chldmask, SIGCHLD);
|
||||
EXPECT_NE(-1, sigprocmask(SIG_BLOCK, &chldmask, &savemask));
|
||||
ASSERT_NE(-1, pipe(pipefds));
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
setpgrp();
|
||||
close(0);
|
||||
open("/dev/null", O_RDWR);
|
||||
close(pipefds[0]);
|
||||
dup2(pipefds[1], 1);
|
||||
sigprocmask(SIG_SETMASK, &savemask, NULL);
|
||||
execv("bin/redbean-tester.com",
|
||||
(char *const[]){"bin/redbean-tester.com", "-vvszXp0", "-l127.0.0.1",
|
||||
__strace > 0 ? "--strace" : 0, 0});
|
||||
_exit(127);
|
||||
}
|
||||
EXPECT_NE(-1, close(pipefds[1]));
|
||||
EXPECT_NE(-1, read(pipefds[0], portbuf, sizeof(portbuf)));
|
||||
port = atoi(portbuf);
|
||||
|
||||
EXPECT_TRUE(Matches("\
|
||||
HTTP/1.1 206 Partial Content\r\n\
|
||||
Content-Range: bytes 18-21/52\r\n\
|
||||
Content-Type: text/plain; charset=utf-8\r\n\
|
||||
Vary: Accept-Encoding\r\n\
|
||||
Last-Modified: .*\r\n\
|
||||
Accept-Ranges: bytes\r\n\
|
||||
X-Content-Type-Options: nosniff\r\n\
|
||||
Date: .*\r\n\
|
||||
Server: redbean/.*\r\n\
|
||||
Content-Length: 4\r\n\
|
||||
\r\n\
|
||||
J\n\
|
||||
K\n",
|
||||
gc(SendHttpRequest("GET /seekable.txt HTTP/1.1\r\n"
|
||||
"Range: bytes=18-21\r\n"
|
||||
"\r\n"))));
|
||||
|
||||
EXPECT_TRUE(Matches("\
|
||||
HTTP/1.1 416 Range Not Satisfiable\r\n\
|
||||
Content-Range: bytes \\*/52\r\n\
|
||||
Content-Type: text/plain; charset=utf-8\r\n\
|
||||
Vary: Accept-Encoding\r\n\
|
||||
Last-Modified: .*\r\n\
|
||||
Accept-Ranges: bytes\r\n\
|
||||
X-Content-Type-Options: nosniff\r\n\
|
||||
Date: .*\r\n\
|
||||
Server: redbean/.*\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n",
|
||||
gc(SendHttpRequest("GET /seekable.txt HTTP/1.1\r\n"
|
||||
"Range: bytes=-18-21\r\n"
|
||||
"\r\n"))));
|
||||
|
||||
EXPECT_TRUE(Matches("\
|
||||
HTTP/1.1 416 Range Not Satisfiable\r\n\
|
||||
Content-Range: bytes \\*/52\r\n\
|
||||
Content-Type: text/plain; charset=utf-8\r\n\
|
||||
Vary: Accept-Encoding\r\n\
|
||||
Last-Modified: .*\r\n\
|
||||
Accept-Ranges: bytes\r\n\
|
||||
X-Content-Type-Options: nosniff\r\n\
|
||||
Date: .*\r\n\
|
||||
Server: redbean/.*\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n",
|
||||
gc(SendHttpRequest("GET /seekable.txt HTTP/1.1\r\n"
|
||||
"Range: bytes=18-60\r\n"
|
||||
"\r\n"))));
|
||||
|
||||
EXPECT_EQ(0, close(pipefds[0]));
|
||||
EXPECT_NE(-1, kill(pid, SIGTERM));
|
||||
EXPECT_NE(-1, wait(0));
|
||||
EXPECT_NE(-1, sigprocmask(SIG_SETMASK, &savemask, 0));
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
void SetUpOnce(void) {
|
||||
if (IsWindows()) exit(0);
|
||||
sqlite3_initialize();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ TEST_TOOL_NET_COMS = $(TEST_TOOL_NET_SRCS:%.c=o/$(MODE)/%.com)
|
|||
|
||||
TEST_TOOL_NET_OBJS = \
|
||||
$(TEST_TOOL_NET_SRCS:%.c=o/$(MODE)/%.o) \
|
||||
o/$(MODE)/tool/net/redbean.com.zip.o
|
||||
o/$(MODE)/test/tool/net/redbean-tester.com.zip.o
|
||||
|
||||
TEST_TOOL_NET_BINS = \
|
||||
$(TEST_TOOL_NET_COMS) \
|
||||
|
@ -71,6 +71,26 @@ o/$(MODE)/test/tool/net/%.com.dbg: \
|
|||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/test/tool/net/redbean-tester.com.dbg: \
|
||||
$(TOOL_NET_DEPS) \
|
||||
o/$(MODE)/tool/net/redbean.o \
|
||||
$(TOOL_NET_REDBEAN_LUA_MODULES) \
|
||||
o/$(MODE)/tool/net/demo/seekable.txt.zip.o \
|
||||
o/$(MODE)/tool/net/net.pkg \
|
||||
$(CRT) \
|
||||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/test/tool/net/redbean-tester.com: \
|
||||
o/$(MODE)/test/tool/net/redbean-tester.com.dbg \
|
||||
o/$(MODE)/third_party/zip/zip.com \
|
||||
o/$(MODE)/tool/build/symtab.com \
|
||||
$(TOOL_NET_REDBEAN_STANDARD_ASSETS)
|
||||
@$(MAKE_OBJCOPY)
|
||||
@$(MAKE_SYMTAB_CREATE)
|
||||
@$(MAKE_SYMTAB_ZIP)
|
||||
@$(TOOL_NET_REDBEAN_STANDARD_ASSETS_ZIP)
|
||||
|
||||
o/$(MODE)/test/tool/net/redbean_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue