summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2024-05-17 13:13:06 -0400
committerTavian Barnes <tavianator@tavianator.com>2024-05-17 13:57:01 -0400
commitc70e7375b1808b23fe4db2018d5e8c9bcb70464d (patch)
treeb84fca909d89c7d5a7f461c7cafeae0058bdca79
parentc3d6f07b8e4d22df533ce7a90660ae1da2df5476 (diff)
downloadbfs-c70e7375b1808b23fe4db2018d5e8c9bcb70464d.tar.xz
diag: New helpers to include xstrerror(errno) automatically
-rw-r--r--src/diag.c4
-rw-r--r--src/diag.h43
-rw-r--r--src/sighook.c4
-rw-r--r--src/xspawn.c2
-rw-r--r--src/xtime.c4
-rw-r--r--tests/bfstd.c4
-rw-r--r--tests/ioq.c6
-rw-r--r--tests/main.c5
-rw-r--r--tests/sighook.c12
-rw-r--r--tests/tests.h15
-rw-r--r--tests/xspawn.c42
-rw-r--r--tests/xtime.c8
12 files changed, 93 insertions, 56 deletions
diff --git a/src/diag.c b/src/diag.c
index deb6f26..bb744f6 100644
--- a/src/diag.c
+++ b/src/diag.c
@@ -38,6 +38,10 @@ noreturn void bfs_abortf(const struct bfs_loc *loc, const char *format, ...) {
abort();
}
+const char *bfs_errstr(void) {
+ return xstrerror(errno);
+}
+
const char *debug_flag_name(enum debug_flags flag) {
switch (flag) {
case DEBUG_COST:
diff --git a/src/diag.h b/src/diag.h
index 2b13609..f2498b5 100644
--- a/src/diag.h
+++ b/src/diag.h
@@ -55,6 +55,20 @@ void bfs_diagf(const struct bfs_loc *loc, const char *format, ...);
#define bfs_diag(...) bfs_diagf(bfs_location(), __VA_ARGS__)
/**
+ * Get the last error message.
+ */
+const char *bfs_errstr(void);
+
+/**
+ * Print a diagnostic message including the last error.
+ */
+#define bfs_ediag(...) \
+ bfs_ediag_("" __VA_ARGS__, bfs_errstr())
+
+#define bfs_ediag_(format, ...) \
+ bfs_diag(sizeof(format) > 1 ? format ": %s" : "%s", __VA_ARGS__)
+
+/**
* Print a message to standard error and abort.
*/
attr(cold, printf(2, 3))
@@ -63,15 +77,27 @@ noreturn void bfs_abortf(const struct bfs_loc *loc, const char *format, ...);
/**
* Unconditional abort with a message.
*/
-#define bfs_abort(...) bfs_abortf(bfs_location(), __VA_ARGS__)
+#define bfs_abort(...) \
+ bfs_abortf(bfs_location(), __VA_ARGS__)
+
+/**
+ * Abort with a message including the last error.
+ */
+#define bfs_eabort(...) \
+ bfs_eabort_("" __VA_ARGS__, bfs_errstr())
+
+#define bfs_eabort_(format, ...) \
+ bfs_abort(sizeof(format) > 1 ? format ": %s" : "%s", __VA_ARGS__)
/**
* Abort in debug builds; no-op in release builds.
*/
#ifdef NDEBUG
# define bfs_bug(...) ((void)0)
+# define bfs_ebug(...) ((void)0)
#else
# define bfs_bug bfs_abort
+# define bfs_ebug bfs_eabort
#endif
/**
@@ -88,12 +114,27 @@ noreturn void bfs_abortf(const struct bfs_loc *loc, const char *format, ...);
str, __VA_ARGS__))
/**
+ * Unconditional assert, including the last error.
+ */
+#define bfs_everify(...) \
+ bfs_everify_(#__VA_ARGS__, __VA_ARGS__, "", bfs_errstr())
+
+#define bfs_everify_(str, cond, format, ...) \
+ ((cond) ? (void)0 : bfs_abort( \
+ sizeof(format) > 1 \
+ ? "%.0s" format "%s: %s" \
+ : "Assertion failed: `%s`: %s", \
+ str, __VA_ARGS__))
+
+/**
* Assert in debug builds; no-op in release builds.
*/
#ifdef NDEBUG
# define bfs_assert(...) ((void)0)
+# define bfs_eassert(...) ((void)0)
#else
# define bfs_assert bfs_verify
+# define bfs_eassert bfs_everify
#endif
struct bfs_ctx;
diff --git a/src/sighook.c b/src/sighook.c
index 745ccb9..ff5b96f 100644
--- a/src/sighook.c
+++ b/src/sighook.c
@@ -104,7 +104,7 @@ static int arc_sem_wait(struct arc *arc) {
#if _POSIX_SEMAPHORES > 0
if (arc->sem_status == 0) {
while (sem_wait(&arc->sem) != 0) {
- bfs_verify(errno == EINTR, "sem_wait(): %s", xstrerror(errno));
+ bfs_everify(errno == EINTR, "sem_wait()");
}
return 0;
}
@@ -146,7 +146,7 @@ static void arc_destroy(struct arc *arc) {
#if _POSIX_SEMAPHORES > 0
if (arc->sem_status == 0) {
- bfs_verify(sem_destroy(&arc->sem) == 0, "sem_destroy(): %s", xstrerror(errno));
+ bfs_everify(sem_destroy(&arc->sem) == 0, "sem_destroy()");
}
#endif
}
diff --git a/src/xspawn.c b/src/xspawn.c
index 5a8277d..33e5a4a 100644
--- a/src/xspawn.c
+++ b/src/xspawn.c
@@ -611,7 +611,7 @@ static pid_t bfs_fork_spawn(struct bfs_resolver *res, const struct bfs_spawn *ct
// Restore the original signal mask
int ret = pthread_sigmask(SIG_SETMASK, &old_mask, NULL);
- bfs_verify(ret == 0, "pthread_sigmask(): %s", xstrerror(ret));
+ bfs_everify(ret == 0, "pthread_sigmask()");
if (pid < 0) {
// fork() failed
diff --git a/src/xtime.c b/src/xtime.c
index eb11afa..2808455 100644
--- a/src/xtime.c
+++ b/src/xtime.c
@@ -20,7 +20,7 @@ int xmktime(struct tm *tm, time_t *timep) {
struct tm tmp;
if (!localtime_r(&time, &tmp)) {
- bfs_bug("localtime_r(-1): %s", xstrerror(errno));
+ bfs_ebug("localtime_r(-1)");
return -1;
}
@@ -46,7 +46,7 @@ int xtimegm(struct tm *tm, time_t *timep) {
struct tm tmp;
if (!gmtime_r(&time, &tmp)) {
- bfs_bug("gmtime_r(-1): %s", xstrerror(errno));
+ bfs_ebug("gmtime_r(-1)");
return -1;
}
diff --git a/tests/bfstd.c b/tests/bfstd.c
index 07b68b0..f0f61ce 100644
--- a/tests/bfstd.c
+++ b/tests/bfstd.c
@@ -15,12 +15,12 @@ static bool check_base_dir(const char *path, const char *dir, const char *base)
bool ret = true;
char *xdir = xdirname(path);
- bfs_verify(xdir, "xdirname(): %s", xstrerror(errno));
+ bfs_everify(xdir, "xdirname()");
ret &= bfs_check(strcmp(xdir, dir) == 0, "xdirname('%s') == '%s' (!= '%s')", path, xdir, dir);
free(xdir);
char *xbase = xbasename(path);
- bfs_verify(xbase, "xbasename(): %s", xstrerror(errno));
+ bfs_everify(xbase, "xbasename()");
ret &= bfs_check(strcmp(xbase, base) == 0, "xbasename('%s') == '%s' (!= '%s')", path, xbase, base);
free(xbase);
diff --git a/tests/ioq.c b/tests/ioq.c
index ef5ee3b..99c98a2 100644
--- a/tests/ioq.c
+++ b/tests/ioq.c
@@ -40,15 +40,15 @@ static void check_ioq_push_block(void) {
const size_t depth = 2;
struct ioq *ioq = ioq_create(depth, 1);
- bfs_verify(ioq, "ioq_create(): %s", xstrerror(errno));
+ bfs_everify(ioq, "ioq_create()");
// Push enough operations to fill the queue
for (size_t i = 0; i < depth; ++i) {
struct bfs_dir *dir = bfs_allocdir();
- bfs_verify(dir, "bfs_allocdir(): %s", xstrerror(errno));
+ bfs_everify(dir, "bfs_allocdir()");
int ret = ioq_opendir(ioq, dir, AT_FDCWD, ".", 0, NULL);
- bfs_verify(ret == 0, "ioq_opendir(): %s", xstrerror(errno));
+ bfs_everify(ret == 0, "ioq_opendir()");
}
bfs_verify(ioq_capacity(ioq) == 0);
diff --git a/tests/main.c b/tests/main.c
index 58def32..aef0583 100644
--- a/tests/main.c
+++ b/tests/main.c
@@ -9,7 +9,6 @@
#include "tests.h"
#include "bfstd.h"
#include "color.h"
-#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
@@ -90,10 +89,6 @@ static void run_test(struct test_ctx *ctx, const char *test, test_fn *fn) {
}
}
-const char *bfs_errstr(void) {
- return xstrerror(errno);
-}
-
int main(int argc, char *argv[]) {
// Try to set a UTF-8 locale
if (!setlocale(LC_ALL, "C.UTF-8")) {
diff --git a/tests/sighook.c b/tests/sighook.c
index e5dd47f..c94526e 100644
--- a/tests/sighook.c
+++ b/tests/sighook.c
@@ -20,7 +20,7 @@ static void alrm_hook(int sig, siginfo_t *info, void *arg) {
/** Swap out an old hook for a new hook. */
static int swap_hooks(struct sighook **hook) {
struct sighook *next = sighook(SIGALRM, alrm_hook, NULL, SH_CONTINUE);
- if (!bfs_pcheck(next, "sighook(SIGALRM)")) {
+ if (!bfs_echeck(next, "sighook(SIGALRM)")) {
return -1;
}
@@ -32,7 +32,7 @@ static int swap_hooks(struct sighook **hook) {
/** Background thread that rapidly (un)registers signal hooks. */
static void *hook_thread(void *ptr) {
struct sighook *hook = sighook(SIGALRM, alrm_hook, NULL, SH_CONTINUE);
- if (!bfs_pcheck(hook, "sighook(SIGALRM)")) {
+ if (!bfs_echeck(hook, "sighook(SIGALRM)")) {
return NULL;
}
@@ -51,7 +51,7 @@ bool check_sighook(void) {
bool ret = true;
struct sighook *hook = sighook(SIGALRM, alrm_hook, NULL, SH_CONTINUE);
- ret &= bfs_pcheck(hook, "sighook(SIGALRM)");
+ ret &= bfs_echeck(hook, "sighook(SIGALRM)");
if (!ret) {
goto done;
}
@@ -64,13 +64,13 @@ bool check_sighook(void) {
.tv_usec = 100,
},
};
- ret &= bfs_pcheck(setitimer(ITIMER_REAL, &ival, NULL) == 0);
+ ret &= bfs_echeck(setitimer(ITIMER_REAL, &ival, NULL) == 0);
if (!ret) {
goto unhook;
}
pthread_t thread;
- ret &= bfs_pcheck(thread_create(&thread, NULL, hook_thread, NULL) == 0);
+ ret &= bfs_echeck(thread_create(&thread, NULL, hook_thread, NULL) == 0);
if (!ret) {
goto untime;
}
@@ -85,7 +85,7 @@ bool check_sighook(void) {
untime:
ival.it_value.tv_usec = 0;
- ret &= bfs_pcheck(setitimer(ITIMER_REAL, &ival, NULL) == 0);
+ ret &= bfs_echeck(setitimer(ITIMER_REAL, &ival, NULL) == 0);
if (!ret) {
goto unhook;
}
diff --git a/tests/tests.h b/tests/tests.h
index d26a5a0..19b7f5e 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -57,20 +57,17 @@ static inline bool bfs_check(bool ret) {
: "Check failed: `%s`%s", \
str, __VA_ARGS__), false))
-/** Get a string description of the last error. */
-const char *bfs_errstr(void);
-
/**
* Check a condition, logging the current error string on failure.
*/
-#define bfs_pcheck(...) \
- bfs_pcheck_(#__VA_ARGS__, __VA_ARGS__, "", "")
+#define bfs_echeck(...) \
+ bfs_echeck_(#__VA_ARGS__, __VA_ARGS__, "", bfs_errstr())
-#define bfs_pcheck_(str, cond, format, ...) \
+#define bfs_echeck_(str, cond, format, ...) \
((cond) ? true : (bfs_diag( \
sizeof(format) > 1 \
- ? "%.0s" format "%s%s: %s" \
- : "Check failed: `%s`%s: %s", \
- str, __VA_ARGS__, bfs_errstr()), false))
+ ? "%.0s" format "%s: %s" \
+ : "Check failed: `%s`: %s", \
+ str, __VA_ARGS__), false))
#endif // BFS_TESTS_H
diff --git a/tests/xspawn.c b/tests/xspawn.c
index 785ea48..b1d6dc1 100644
--- a/tests/xspawn.c
+++ b/tests/xspawn.c
@@ -54,7 +54,7 @@ static bool check_use_path(bool use_posix) {
bool ret = true;
struct bfs_spawn spawn;
- ret &= bfs_pcheck(bfs_spawn_init(&spawn) == 0);
+ ret &= bfs_echeck(bfs_spawn_init(&spawn) == 0);
if (!ret) {
goto out;
}
@@ -64,18 +64,18 @@ static bool check_use_path(bool use_posix) {
spawn.flags &= ~BFS_SPAWN_USE_POSIX;
}
- ret &= bfs_pcheck(bfs_spawn_addopen(&spawn, 10, "bin", O_RDONLY | O_DIRECTORY, 0) == 0);
- ret &= bfs_pcheck(bfs_spawn_adddup2(&spawn, 10, 11) == 0);
- ret &= bfs_pcheck(bfs_spawn_addclose(&spawn, 10) == 0);
- ret &= bfs_pcheck(bfs_spawn_addfchdir(&spawn, 11) == 0);
- ret &= bfs_pcheck(bfs_spawn_addclose(&spawn, 11) == 0);
+ ret &= bfs_echeck(bfs_spawn_addopen(&spawn, 10, "bin", O_RDONLY | O_DIRECTORY, 0) == 0);
+ ret &= bfs_echeck(bfs_spawn_adddup2(&spawn, 10, 11) == 0);
+ ret &= bfs_echeck(bfs_spawn_addclose(&spawn, 10) == 0);
+ ret &= bfs_echeck(bfs_spawn_addfchdir(&spawn, 11) == 0);
+ ret &= bfs_echeck(bfs_spawn_addclose(&spawn, 11) == 0);
if (!ret) {
goto destroy;
}
// Check that $PATH is resolved in the parent's environment
char **envp;
- ret &= bfs_pcheck(envp = envdup());
+ ret &= bfs_echeck(envp = envdup());
if (!ret) {
goto destroy;
}
@@ -84,7 +84,7 @@ static bool check_use_path(bool use_posix) {
char *old_path = getenv("PATH");
dchar *new_path = NULL;
if (old_path) {
- ret &= bfs_pcheck(old_path = strdup(old_path));
+ ret &= bfs_echeck(old_path = strdup(old_path));
if (!ret) {
goto env;
}
@@ -97,20 +97,20 @@ static bool check_use_path(bool use_posix) {
goto path;
}
- ret &= bfs_pcheck(setenv("PATH", new_path, true) == 0);
+ ret &= bfs_echeck(setenv("PATH", new_path, true) == 0);
if (!ret) {
goto path;
}
char *argv[] = {"xspawnee", old_path, NULL};
pid_t pid = bfs_spawn("xspawnee", &spawn, argv, envp);
- ret &= bfs_pcheck(pid >= 0, "bfs_spawn()");
+ ret &= bfs_echeck(pid >= 0, "bfs_spawn()");
if (!ret) {
goto unset;
}
int wstatus;
- ret &= bfs_pcheck(xwaitpid(pid, &wstatus, 0) == pid)
+ ret &= bfs_echeck(xwaitpid(pid, &wstatus, 0) == pid)
&& bfs_check(WIFEXITED(wstatus));
if (ret) {
int wexit = WEXITSTATUS(wstatus);
@@ -119,9 +119,9 @@ static bool check_use_path(bool use_posix) {
unset:
if (old_path) {
- ret &= bfs_pcheck(setenv("PATH", old_path, true) == 0);
+ ret &= bfs_echeck(setenv("PATH", old_path, true) == 0);
} else {
- ret &= bfs_pcheck(unsetenv("PATH") == 0);
+ ret &= bfs_echeck(unsetenv("PATH") == 0);
}
path:
dstrfree(new_path);
@@ -132,7 +132,7 @@ env:
}
free(envp);
destroy:
- ret &= bfs_pcheck(bfs_spawn_destroy(&spawn) == 0);
+ ret &= bfs_echeck(bfs_spawn_destroy(&spawn) == 0);
out:
return ret;
}
@@ -142,7 +142,7 @@ static bool check_enoent(bool use_posix) {
bool ret = true;
struct bfs_spawn spawn;
- ret &= bfs_pcheck(bfs_spawn_init(&spawn) == 0);
+ ret &= bfs_echeck(bfs_spawn_init(&spawn) == 0);
if (!ret) {
goto out;
}
@@ -154,9 +154,9 @@ static bool check_enoent(bool use_posix) {
char *argv[] = {"eW6f5RM9Qi", NULL};
pid_t pid = bfs_spawn("eW6f5RM9Qi", &spawn, argv, NULL);
- ret &= bfs_pcheck(pid < 0 && errno == ENOENT, "bfs_spawn()");
+ ret &= bfs_echeck(pid < 0 && errno == ENOENT, "bfs_spawn()");
- ret &= bfs_pcheck(bfs_spawn_destroy(&spawn) == 0);
+ ret &= bfs_echeck(bfs_spawn_destroy(&spawn) == 0);
out:
return ret;
}
@@ -166,18 +166,18 @@ static bool check_resolve(void) {
char *exe;
exe = bfs_spawn_resolve("sh");
- ret &= bfs_pcheck(exe, "bfs_spawn_resolve('sh')");
+ ret &= bfs_echeck(exe, "bfs_spawn_resolve('sh')");
free(exe);
exe = bfs_spawn_resolve("/bin/sh");
- ret &= bfs_pcheck(exe && strcmp(exe, "/bin/sh") == 0);
+ ret &= bfs_echeck(exe && strcmp(exe, "/bin/sh") == 0);
free(exe);
exe = bfs_spawn_resolve("bin/tests/xspawnee");
- ret &= bfs_pcheck(exe && strcmp(exe, "bin/tests/xspawnee") == 0);
+ ret &= bfs_echeck(exe && strcmp(exe, "bin/tests/xspawnee") == 0);
free(exe);
- ret &= bfs_pcheck(!bfs_spawn_resolve("eW6f5RM9Qi") && errno == ENOENT);
+ ret &= bfs_echeck(!bfs_spawn_resolve("eW6f5RM9Qi") && errno == ENOENT);
return ret;
}
diff --git a/tests/xtime.c b/tests/xtime.c
index d9d6c5c..1907e26 100644
--- a/tests/xtime.c
+++ b/tests/xtime.c
@@ -29,9 +29,9 @@ static bool check_one_xgetdate(const char *str, int error, time_t expected) {
int ret = xgetdate(str, &ts);
if (error) {
- return bfs_pcheck(ret == -1 && errno == error, "xgetdate('%s')", str);
+ return bfs_echeck(ret == -1 && errno == error, "xgetdate('%s')", str);
} else {
- return bfs_pcheck(ret == 0, "xgetdate('%s')", str)
+ return bfs_echeck(ret == 0, "xgetdate('%s')", str)
&& bfs_check(ts.tv_sec == expected && ts.tv_nsec == 0,
"xgetdate('%s'): %jd.%09jd != %jd",
str, (intmax_t)ts.tv_sec, (intmax_t)ts.tv_nsec, (intmax_t)expected);
@@ -82,12 +82,12 @@ static bool check_xgetdate(void) {
static bool check_one_xmktime(time_t expected) {
struct tm tm;
if (!localtime_r(&expected, &tm)) {
- bfs_diag("localtime_r(%jd): %s", (intmax_t)expected, xstrerror(errno));
+ bfs_ediag("localtime_r(%jd)", (intmax_t)expected);
return false;
}
time_t actual;
- return bfs_pcheck(xmktime(&tm, &actual) == 0, "xmktime(" TM_FORMAT ")", TM_PRINTF(tm))
+ return bfs_echeck(xmktime(&tm, &actual) == 0, "xmktime(" TM_FORMAT ")", TM_PRINTF(tm))
&& bfs_check(actual == expected, "xmktime(" TM_FORMAT "): %jd != %jd", TM_PRINTF(tm), (intmax_t)actual, (intmax_t)expected);
}