summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2024-02-29 13:23:02 -0500
committerTavian Barnes <tavianator@tavianator.com>2024-02-29 13:41:46 -0500
commit4e2f094d29ff8140f2b46a059128c780560db0f1 (patch)
treec492f871db65857f106b755d21c413ff74357f03
parenta228788769d7e3c71154606609a13eafb03a5fc2 (diff)
downloadbfs-4e2f094d29ff8140f2b46a059128c780560db0f1.tar.xz
tests: New bfs_check() macro
We now report failures and continue, rather than aborting after the first failure.
-rw-r--r--tests/alloc.c22
-rw-r--r--tests/bfstd.c65
-rw-r--r--tests/bit.c108
-rw-r--r--tests/tests.h20
-rw-r--r--tests/trie.c46
-rw-r--r--tests/xtime.c220
6 files changed, 247 insertions, 234 deletions
diff --git a/tests/alloc.c b/tests/alloc.c
index e14f131..4ce23d4 100644
--- a/tests/alloc.c
+++ b/tests/alloc.c
@@ -9,30 +9,32 @@
#include <stdint.h>
bool check_alloc(void) {
+ bool ret = true;
+
// Check sizeof_flex()
struct flexible {
alignas(64) int foo[8];
int bar[];
};
- bfs_verify(sizeof_flex(struct flexible, bar, 0) >= sizeof(struct flexible));
- bfs_verify(sizeof_flex(struct flexible, bar, 16) % alignof(struct flexible) == 0);
+ ret &= bfs_check(sizeof_flex(struct flexible, bar, 0) >= sizeof(struct flexible));
+ ret &= bfs_check(sizeof_flex(struct flexible, bar, 16) % alignof(struct flexible) == 0);
size_t too_many = SIZE_MAX / sizeof(int) + 1;
- bfs_verify(sizeof_flex(struct flexible, bar, too_many) == align_floor(alignof(struct flexible), SIZE_MAX));
+ ret &= bfs_check(sizeof_flex(struct flexible, bar, too_many) == align_floor(alignof(struct flexible), SIZE_MAX));
// Corner case: sizeof(type) > align_ceil(alignof(type), offsetof(type, member))
// Doesn't happen in typical ABIs
- bfs_verify(flex_size(8, 16, 4, 4, 1) == 16);
+ ret &= bfs_check(flex_size(8, 16, 4, 4, 1) == 16);
// Make sure we detect allocation size overflows
#if __GNUC__ && !__clang__
# pragma GCC diagnostic ignored "-Walloc-size-larger-than="
#endif
- bfs_verify(ALLOC_ARRAY(int, too_many) == NULL && errno == EOVERFLOW);
- bfs_verify(ZALLOC_ARRAY(int, too_many) == NULL && errno == EOVERFLOW);
- bfs_verify(ALLOC_FLEX(struct flexible, bar, too_many) == NULL && errno == EOVERFLOW);
- bfs_verify(ZALLOC_FLEX(struct flexible, bar, too_many) == NULL && errno == EOVERFLOW);
+ ret &= bfs_check(ALLOC_ARRAY(int, too_many) == NULL && errno == EOVERFLOW);
+ ret &= bfs_check(ZALLOC_ARRAY(int, too_many) == NULL && errno == EOVERFLOW);
+ ret &= bfs_check(ALLOC_FLEX(struct flexible, bar, too_many) == NULL && errno == EOVERFLOW);
+ ret &= bfs_check(ZALLOC_FLEX(struct flexible, bar, too_many) == NULL && errno == EOVERFLOW);
// varena tests
struct varena varena;
@@ -41,9 +43,9 @@ bool check_alloc(void) {
for (size_t i = 0; i < 256; ++i) {
bfs_verify(varena_alloc(&varena, i));
struct arena *arena = &varena.arenas[varena.narenas - 1];
- bfs_verify(arena->size >= sizeof_flex(struct flexible, bar, i));
+ ret &= bfs_check(arena->size >= sizeof_flex(struct flexible, bar, i));
}
varena_destroy(&varena);
- return true;
+ return ret;
}
diff --git a/tests/bfstd.c b/tests/bfstd.c
index d385c6b..4d0ec23 100644
--- a/tests/bfstd.c
+++ b/tests/bfstd.c
@@ -14,61 +14,68 @@
#include <string.h>
/** Check the result of xdirname()/xbasename(). */
-static void check_base_dir(const char *path, const char *dir, const char *base) {
+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_verify(strcmp(xdir, dir) == 0, "xdirname('%s') == '%s' (!= '%s')", path, xdir, dir);
+ 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_verify(strcmp(xbase, base) == 0, "xbasename('%s') == '%s' (!= '%s')", path, xbase, base);
+ ret &= bfs_check(strcmp(xbase, base) == 0, "xbasename('%s') == '%s' (!= '%s')", path, xbase, base);
free(xbase);
+
+ return ret;
}
/** Check the result of wordesc(). */
-static void check_wordesc(const char *str, const char *exp, enum wesc_flags flags) {
+static bool check_wordesc(const char *str, const char *exp, enum wesc_flags flags) {
char buf[256];
char *end = buf + sizeof(buf);
- char *ret = wordesc(buf, end, str, flags);
- bfs_verify(ret != end);
- bfs_verify(strcmp(buf, exp) == 0, "wordesc(%s) == %s (!= %s)", str, buf, exp);
+ char *esc = wordesc(buf, end, str, flags);
+
+ return bfs_check(esc != end)
+ && bfs_check(strcmp(buf, exp) == 0, "wordesc('%s') == '%s' (!= '%s')", str, buf, exp);
}
bool check_bfstd(void) {
+ bool ret = true;
+
// Try to set a UTF-8 locale
if (!setlocale(LC_ALL, "C.UTF-8")) {
setlocale(LC_ALL, "");
}
// From man 3p basename
- check_base_dir("usr", ".", "usr");
- check_base_dir("usr/", ".", "usr");
- check_base_dir("", ".", ".");
- check_base_dir("/", "/", "/");
+ ret &= check_base_dir("usr", ".", "usr");
+ ret &= check_base_dir("usr/", ".", "usr");
+ ret &= check_base_dir("", ".", ".");
+ ret &= check_base_dir("/", "/", "/");
// check_base_dir("//", "/" or "//", "/" or "//");
- check_base_dir("///", "/", "/");
- check_base_dir("/usr/", "/", "usr");
- check_base_dir("/usr/lib", "/usr", "lib");
- check_base_dir("//usr//lib//", "//usr", "lib");
- check_base_dir("/home//dwc//test", "/home//dwc", "test");
+ ret &= check_base_dir("///", "/", "/");
+ ret &= check_base_dir("/usr/", "/", "usr");
+ ret &= check_base_dir("/usr/lib", "/usr", "lib");
+ ret &= check_base_dir("//usr//lib//", "//usr", "lib");
+ ret &= check_base_dir("/home//dwc//test", "/home//dwc", "test");
- check_wordesc("", "\"\"", WESC_SHELL);
- check_wordesc("word", "word", WESC_SHELL);
- check_wordesc("two words", "\"two words\"", WESC_SHELL);
- check_wordesc("word's", "\"word's\"", WESC_SHELL);
- check_wordesc("\"word\"", "'\"word\"'", WESC_SHELL);
- check_wordesc("\"word's\"", "'\"word'\\''s\"'", WESC_SHELL);
- check_wordesc("\033[1mbold's\033[0m", "$'\\e[1mbold\\'s\\e[0m'", WESC_SHELL | WESC_TTY);
- check_wordesc("\x7F", "$'\\x7F'", WESC_SHELL | WESC_TTY);
+ ret &= check_wordesc("", "\"\"", WESC_SHELL);
+ ret &= check_wordesc("word", "word", WESC_SHELL);
+ ret &= check_wordesc("two words", "\"two words\"", WESC_SHELL);
+ ret &= check_wordesc("word's", "\"word's\"", WESC_SHELL);
+ ret &= check_wordesc("\"word\"", "'\"word\"'", WESC_SHELL);
+ ret &= check_wordesc("\"word's\"", "'\"word'\\''s\"'", WESC_SHELL);
+ ret &= check_wordesc("\033[1mbold's\033[0m", "$'\\e[1mbold\\'s\\e[0m'", WESC_SHELL | WESC_TTY);
+ ret &= check_wordesc("\x7F", "$'\\x7F'", WESC_SHELL | WESC_TTY);
const char *charmap = nl_langinfo(CODESET);
if (strcmp(charmap, "UTF-8") == 0) {
- check_wordesc("\xF0", "$'\\xF0'", WESC_SHELL | WESC_TTY);
- check_wordesc("\xF0\x9F", "$'\\xF0\\x9F'", WESC_SHELL | WESC_TTY);
- check_wordesc("\xF0\x9F\x98", "$'\\xF0\\x9F\\x98'", WESC_SHELL | WESC_TTY);
- check_wordesc("\xF0\x9F\x98\x80", "\xF0\x9F\x98\x80", WESC_SHELL | WESC_TTY);
+ ret &= check_wordesc("\xF0", "$'\\xF0'", WESC_SHELL | WESC_TTY);
+ ret &= check_wordesc("\xF0\x9F", "$'\\xF0\\x9F'", WESC_SHELL | WESC_TTY);
+ ret &= check_wordesc("\xF0\x9F\x98", "$'\\xF0\\x9F\\x98'", WESC_SHELL | WESC_TTY);
+ ret &= check_wordesc("\xF0\x9F\x98\x80", "\xF0\x9F\x98\x80", WESC_SHELL | WESC_TTY);
}
- return true;
+ return ret;
}
diff --git a/tests/bit.c b/tests/bit.c
index 1c6a4de..b944748 100644
--- a/tests/bit.c
+++ b/tests/bit.c
@@ -52,75 +52,77 @@ bfs_static_assert(UINTMAX_MAX == UWIDTH_MAX(UINTMAX_WIDTH));
bfs_static_assert(INTMAX_MIN == IWIDTH_MIN(INTMAX_WIDTH));
bfs_static_assert(INTMAX_MAX == IWIDTH_MAX(INTMAX_WIDTH));
-#define verify_eq(a, b) \
- bfs_verify((a) == (b), "(0x%jX) %s != %s (0x%jX)", (uintmax_t)(a), #a, #b, (uintmax_t)(b))
+#define check_eq(a, b) \
+ bfs_check((a) == (b), "(0x%jX) %s != %s (0x%jX)", (uintmax_t)(a), #a, #b, (uintmax_t)(b))
bool check_bit(void) {
- verify_eq(bswap((uint8_t)0x12), 0x12);
- verify_eq(bswap((uint16_t)0x1234), 0x3412);
- verify_eq(bswap((uint32_t)0x12345678), 0x78563412);
- verify_eq(bswap((uint64_t)0x1234567812345678), 0x7856341278563412);
-
- verify_eq(count_ones(0x0), 0);
- verify_eq(count_ones(0x1), 1);
- verify_eq(count_ones(0x2), 1);
- verify_eq(count_ones(0x3), 2);
- verify_eq(count_ones(0x137F), 10);
-
- verify_eq(count_zeros(0), INT_WIDTH);
- verify_eq(count_zeros(0L), LONG_WIDTH);
- verify_eq(count_zeros(0LL), LLONG_WIDTH);
- verify_eq(count_zeros((uint8_t)0), 8);
- verify_eq(count_zeros((uint16_t)0), 16);
- verify_eq(count_zeros((uint32_t)0), 32);
- verify_eq(count_zeros((uint64_t)0), 64);
-
- verify_eq(rotate_left((uint8_t)0xA1, 4), 0x1A);
- verify_eq(rotate_left((uint16_t)0x1234, 12), 0x4123);
- verify_eq(rotate_left((uint32_t)0x12345678, 20), 0x67812345);
- verify_eq(rotate_left((uint32_t)0x12345678, 0), 0x12345678);
-
- verify_eq(rotate_right((uint8_t)0xA1, 4), 0x1A);
- verify_eq(rotate_right((uint16_t)0x1234, 12), 0x2341);
- verify_eq(rotate_right((uint32_t)0x12345678, 20), 0x45678123);
- verify_eq(rotate_right((uint32_t)0x12345678, 0), 0x12345678);
+ bool ret = true;
+
+ ret &= check_eq(bswap((uint8_t)0x12), 0x12);
+ ret &= check_eq(bswap((uint16_t)0x1234), 0x3412);
+ ret &= check_eq(bswap((uint32_t)0x12345678), 0x78563412);
+ ret &= check_eq(bswap((uint64_t)0x1234567812345678), 0x7856341278563412);
+
+ ret &= check_eq(count_ones(0x0), 0);
+ ret &= check_eq(count_ones(0x1), 1);
+ ret &= check_eq(count_ones(0x2), 1);
+ ret &= check_eq(count_ones(0x3), 2);
+ ret &= check_eq(count_ones(0x137F), 10);
+
+ ret &= check_eq(count_zeros(0), INT_WIDTH);
+ ret &= check_eq(count_zeros(0L), LONG_WIDTH);
+ ret &= check_eq(count_zeros(0LL), LLONG_WIDTH);
+ ret &= check_eq(count_zeros((uint8_t)0), 8);
+ ret &= check_eq(count_zeros((uint16_t)0), 16);
+ ret &= check_eq(count_zeros((uint32_t)0), 32);
+ ret &= check_eq(count_zeros((uint64_t)0), 64);
+
+ ret &= check_eq(rotate_left((uint8_t)0xA1, 4), 0x1A);
+ ret &= check_eq(rotate_left((uint16_t)0x1234, 12), 0x4123);
+ ret &= check_eq(rotate_left((uint32_t)0x12345678, 20), 0x67812345);
+ ret &= check_eq(rotate_left((uint32_t)0x12345678, 0), 0x12345678);
+
+ ret &= check_eq(rotate_right((uint8_t)0xA1, 4), 0x1A);
+ ret &= check_eq(rotate_right((uint16_t)0x1234, 12), 0x2341);
+ ret &= check_eq(rotate_right((uint32_t)0x12345678, 20), 0x45678123);
+ ret &= check_eq(rotate_right((uint32_t)0x12345678, 0), 0x12345678);
for (int i = 0; i < 16; ++i) {
uint16_t n = (uint16_t)1 << i;
for (int j = i; j < 16; ++j) {
uint16_t m = (uint16_t)1 << j;
uint16_t nm = n | m;
- verify_eq(count_ones(nm), 1 + (n != m));
- verify_eq(count_zeros(nm), 15 - (n != m));
- verify_eq(leading_zeros(nm), 15 - j);
- verify_eq(trailing_zeros(nm), i);
- verify_eq(first_leading_one(nm), j + 1);
- verify_eq(first_trailing_one(nm), i + 1);
- verify_eq(bit_width(nm), j + 1);
- verify_eq(bit_floor(nm), m);
+ ret &= check_eq(count_ones(nm), 1 + (n != m));
+ ret &= check_eq(count_zeros(nm), 15 - (n != m));
+ ret &= check_eq(leading_zeros(nm), 15 - j);
+ ret &= check_eq(trailing_zeros(nm), i);
+ ret &= check_eq(first_leading_one(nm), j + 1);
+ ret &= check_eq(first_trailing_one(nm), i + 1);
+ ret &= check_eq(bit_width(nm), j + 1);
+ ret &= check_eq(bit_floor(nm), m);
if (n == m) {
- verify_eq(bit_ceil(nm), m);
- bfs_verify(has_single_bit(nm));
+ ret &= check_eq(bit_ceil(nm), m);
+ ret &= bfs_check(has_single_bit(nm));
} else {
if (j < 15) {
- verify_eq(bit_ceil(nm), (m << 1));
+ ret &= check_eq(bit_ceil(nm), (m << 1));
}
- bfs_verify(!has_single_bit(nm));
+ ret &= bfs_check(!has_single_bit(nm));
}
}
}
- verify_eq(leading_zeros((uint16_t)0), 16);
- verify_eq(trailing_zeros((uint16_t)0), 16);
- verify_eq(first_leading_one(0), 0);
- verify_eq(first_trailing_one(0), 0);
- verify_eq(bit_width(0), 0);
- verify_eq(bit_floor(0), 0);
- verify_eq(bit_ceil(0), 1);
+ ret &= check_eq(leading_zeros((uint16_t)0), 16);
+ ret &= check_eq(trailing_zeros((uint16_t)0), 16);
+ ret &= check_eq(first_leading_one(0), 0);
+ ret &= check_eq(first_trailing_one(0), 0);
+ ret &= check_eq(bit_width(0), 0);
+ ret &= check_eq(bit_floor(0), 0);
+ ret &= check_eq(bit_ceil(0), 1);
- bfs_verify(!has_single_bit(0));
- bfs_verify(!has_single_bit(UINT32_MAX));
- bfs_verify(has_single_bit((uint32_t)1 << (UINT_WIDTH - 1)));
+ ret &= bfs_check(!has_single_bit(0));
+ ret &= bfs_check(!has_single_bit(UINT32_MAX));
+ ret &= bfs_check(has_single_bit((uint32_t)1 << (UINT_WIDTH - 1)));
- return true;
+ return ret;
}
diff --git a/tests/tests.h b/tests/tests.h
index d8adbb9..6629dcf 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -9,6 +9,7 @@
#define BFS_TESTS_H
#include "../src/config.h"
+#include "../src/diag.h"
/** Unit test function type. */
typedef bool test_fn(void);
@@ -31,4 +32,23 @@ bool check_trie(void);
/** Time tests. */
bool check_xtime(void);
+/** Don't ignore the bfs_check() return value. */
+attr(nodiscard)
+static inline bool bfs_check(bool ret) {
+ return ret;
+}
+
+/**
+ * Check a condition, logging a message on failure but continuing.
+ */
+#define bfs_check(...) \
+ bfs_check(bfs_check_(#__VA_ARGS__, __VA_ARGS__, "", ""))
+
+#define bfs_check_(str, cond, format, ...) \
+ ((cond) ? true : (bfs_diag( \
+ sizeof(format) > 1 \
+ ? "%.0s" format "%s%s" \
+ : "Check failed: `%s`%s", \
+ str, __VA_ARGS__), false))
+
#endif // BFS_TESTS_H
diff --git a/tests/trie.c b/tests/trie.c
index f94d7c8..fec0de2 100644
--- a/tests/trie.c
+++ b/tests/trie.c
@@ -40,11 +40,13 @@ const char *keys[] = {
const size_t nkeys = countof(keys);
bool check_trie(void) {
+ bool ret = true;
+
struct trie trie;
trie_init(&trie);
for (size_t i = 0; i < nkeys; ++i) {
- bfs_verify(!trie_find_str(&trie, keys[i]));
+ ret &= bfs_check(!trie_find_str(&trie, keys[i]));
const char *prefix = NULL;
for (size_t j = 0; j < i; ++j) {
@@ -58,37 +60,37 @@ bool check_trie(void) {
struct trie_leaf *leaf = trie_find_prefix(&trie, keys[i]);
if (prefix) {
bfs_verify(leaf);
- bfs_verify(strcmp(prefix, leaf->key) == 0);
+ ret &= bfs_check(strcmp(prefix, leaf->key) == 0);
} else {
- bfs_verify(!leaf);
+ ret &= bfs_check(!leaf);
}
leaf = trie_insert_str(&trie, keys[i]);
bfs_verify(leaf);
- bfs_verify(strcmp(keys[i], leaf->key) == 0);
- bfs_verify(leaf->length == strlen(keys[i]) + 1);
+ ret &= bfs_check(strcmp(keys[i], leaf->key) == 0);
+ ret &= bfs_check(leaf->length == strlen(keys[i]) + 1);
}
{
size_t i = 0;
for_trie (leaf, &trie) {
- bfs_verify(leaf == trie_find_str(&trie, keys[i]));
- bfs_verify(!leaf->prev || leaf->prev->next == leaf);
- bfs_verify(!leaf->next || leaf->next->prev == leaf);
+ ret &= bfs_check(leaf == trie_find_str(&trie, keys[i]));
+ ret &= bfs_check(!leaf->prev || leaf->prev->next == leaf);
+ ret &= bfs_check(!leaf->next || leaf->next->prev == leaf);
++i;
}
- bfs_verify(i == nkeys);
+ ret &= bfs_check(i == nkeys);
}
for (size_t i = 0; i < nkeys; ++i) {
struct trie_leaf *leaf = trie_find_str(&trie, keys[i]);
bfs_verify(leaf);
- bfs_verify(strcmp(keys[i], leaf->key) == 0);
- bfs_verify(leaf->length == strlen(keys[i]) + 1);
+ ret &= bfs_check(strcmp(keys[i], leaf->key) == 0);
+ ret &= bfs_check(leaf->length == strlen(keys[i]) + 1);
trie_remove(&trie, leaf);
leaf = trie_find_str(&trie, keys[i]);
- bfs_verify(!leaf);
+ ret &= bfs_check(!leaf);
const char *postfix = NULL;
for (size_t j = i + 1; j < nkeys; ++j) {
@@ -102,14 +104,14 @@ bool check_trie(void) {
leaf = trie_find_postfix(&trie, keys[i]);
if (postfix) {
bfs_verify(leaf);
- bfs_verify(strcmp(postfix, leaf->key) == 0);
+ ret &= bfs_check(strcmp(postfix, leaf->key) == 0);
} else {
- bfs_verify(!leaf);
+ ret &= bfs_check(!leaf);
}
}
for_trie (leaf, &trie) {
- bfs_verify(false);
+ ret &= bfs_check(false, "trie should be empty");
}
// This tests the "jump" node handling on 32-bit platforms
@@ -118,18 +120,18 @@ bool check_trie(void) {
bfs_verify(longstr);
memset(longstr, 0xAC, longsize);
- bfs_verify(!trie_find_mem(&trie, longstr, longsize));
- bfs_verify(trie_insert_mem(&trie, longstr, longsize));
+ ret &= bfs_check(!trie_find_mem(&trie, longstr, longsize));
+ ret &= bfs_check(trie_insert_mem(&trie, longstr, longsize));
memset(longstr + longsize / 2, 0xAB, longsize / 2);
- bfs_verify(!trie_find_mem(&trie, longstr, longsize));
- bfs_verify(trie_insert_mem(&trie, longstr, longsize));
+ ret &= bfs_check(!trie_find_mem(&trie, longstr, longsize));
+ ret &= bfs_check(trie_insert_mem(&trie, longstr, longsize));
memset(longstr, 0xAA, longsize / 2);
- bfs_verify(!trie_find_mem(&trie, longstr, longsize));
- bfs_verify(trie_insert_mem(&trie, longstr, longsize));
+ ret &= bfs_check(!trie_find_mem(&trie, longstr, longsize));
+ ret &= bfs_check(trie_insert_mem(&trie, longstr, longsize));
free(longstr);
trie_destroy(&trie);
- return true;
+ return ret;
}
diff --git a/tests/xtime.c b/tests/xtime.c
index 4a7d55c..f853428 100644
--- a/tests/xtime.c
+++ b/tests/xtime.c
@@ -12,121 +12,122 @@
#include <time.h>
static bool tm_equal(const struct tm *tma, const struct tm *tmb) {
- if (tma->tm_year != tmb->tm_year) {
- return false;
- }
- if (tma->tm_mon != tmb->tm_mon) {
- return false;
- }
- if (tma->tm_mday != tmb->tm_mday) {
- return false;
- }
- if (tma->tm_hour != tmb->tm_hour) {
- return false;
- }
- if (tma->tm_min != tmb->tm_min) {
- return false;
- }
- if (tma->tm_sec != tmb->tm_sec) {
- return false;
- }
- if (tma->tm_wday != tmb->tm_wday) {
- return false;
- }
- if (tma->tm_yday != tmb->tm_yday) {
- return false;
- }
- if (tma->tm_isdst != tmb->tm_isdst) {
- return false;
- }
-
- return true;
-}
-
-static void tm_print(FILE *file, const struct tm *tm) {
- fprintf(file, "Y%d M%d D%d h%d m%d s%d wd%d yd%d%s\n",
- tm->tm_year, tm->tm_mon, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec,
- tm->tm_wday, tm->tm_yday,
- tm->tm_isdst ? (tm->tm_isdst < 0 ? " (DST?)" : " (DST)") : "");
+ return tma->tm_year == tmb->tm_year
+ && tma->tm_mon == tmb->tm_mon
+ && tma->tm_mday == tmb->tm_mday
+ && tma->tm_hour == tmb->tm_hour
+ && tma->tm_min == tmb->tm_min
+ && tma->tm_sec == tmb->tm_sec
+ && tma->tm_wday == tmb->tm_wday
+ && tma->tm_yday == tmb->tm_yday
+ && tma->tm_isdst == tmb->tm_isdst;
}
/** Check one xgetdate() result. */
-static bool compare_xgetdate(const char *str, int error, time_t expected) {
+static bool check_one_xgetdate(const char *str, int error, time_t expected) {
struct timespec ts;
int ret = xgetdate(str, &ts);
if (error) {
- if (ret != -1 || errno != error) {
- fprintf(stderr, "xgetdate('%s'): %s\n", str, xstrerror(errno));
- return false;
- }
- } else if (ret != 0) {
- fprintf(stderr, "xgetdate('%s'): %s\n", str, xstrerror(errno));
- return false;
- } else if (ts.tv_sec != expected || ts.tv_nsec != 0) {
- fprintf(stderr, "xgetdate('%s'): %jd.%09jd != %jd\n", str, (intmax_t)ts.tv_sec, (intmax_t)ts.tv_nsec, (intmax_t)expected);
- return false;
+ return bfs_check(ret == -1 && errno == error, "xgetdate('%s'): %s", str, xstrerror(errno));
+ } else {
+ return bfs_check(ret == 0, "xgetdate('%s'): %s", str, xstrerror(errno))
+ && 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);
}
-
- return true;
}
/** xgetdate() tests. */
static bool check_xgetdate(void) {
- return compare_xgetdate("", EINVAL, 0)
- & compare_xgetdate("????", EINVAL, 0)
- & compare_xgetdate("1991", EINVAL, 0)
- & compare_xgetdate("1991-??", EINVAL, 0)
- & compare_xgetdate("1991-12", EINVAL, 0)
- & compare_xgetdate("1991-12-", EINVAL, 0)
- & compare_xgetdate("1991-12-??", EINVAL, 0)
- & compare_xgetdate("1991-12-14", 0, 692668800)
- & compare_xgetdate("1991-12-14-", EINVAL, 0)
- & compare_xgetdate("1991-12-14T", EINVAL, 0)
- & compare_xgetdate("1991-12-14T??", EINVAL, 0)
- & compare_xgetdate("1991-12-14T10", 0, 692704800)
- & compare_xgetdate("1991-12-14T10:??", EINVAL, 0)
- & compare_xgetdate("1991-12-14T10:11", 0, 692705460)
- & compare_xgetdate("1991-12-14T10:11:??", EINVAL, 0)
- & compare_xgetdate("1991-12-14T10:11:12", 0, 692705472)
- & compare_xgetdate("1991-12-14T10Z", 0, 692704800)
- & compare_xgetdate("1991-12-14T10:11Z", 0, 692705460)
- & compare_xgetdate("1991-12-14T10:11:12Z", 0, 692705472)
- & compare_xgetdate("1991-12-14T10:11:12?", EINVAL, 0)
- & compare_xgetdate("1991-12-14T03-07", 0, 692704800)
- & compare_xgetdate("1991-12-14T06:41-03:30", 0, 692705460)
- & compare_xgetdate("1991-12-14T03:11:12-07:00", 0, 692705472)
- & compare_xgetdate("19911214 031112-0700", 0, 692705472);
+ bool ret = true;
+
+ ret &= check_one_xgetdate("", EINVAL, 0);
+ ret &= check_one_xgetdate("????", EINVAL, 0);
+ ret &= check_one_xgetdate("1991", EINVAL, 0);
+ ret &= check_one_xgetdate("1991-??", EINVAL, 0);
+ ret &= check_one_xgetdate("1991-12", EINVAL, 0);
+ ret &= check_one_xgetdate("1991-12-", EINVAL, 0);
+ ret &= check_one_xgetdate("1991-12-??", EINVAL, 0);
+ ret &= check_one_xgetdate("1991-12-14", 0, 692668800);
+ ret &= check_one_xgetdate("1991-12-14-", EINVAL, 0);
+ ret &= check_one_xgetdate("1991-12-14T", EINVAL, 0);
+ ret &= check_one_xgetdate("1991-12-14T??", EINVAL, 0);
+ ret &= check_one_xgetdate("1991-12-14T10", 0, 692704800);
+ ret &= check_one_xgetdate("1991-12-14T10:??", EINVAL, 0);
+ ret &= check_one_xgetdate("1991-12-14T10:11", 0, 692705460);
+ ret &= check_one_xgetdate("1991-12-14T10:11:??", EINVAL, 0);
+ ret &= check_one_xgetdate("1991-12-14T10:11:12", 0, 692705472);
+ ret &= check_one_xgetdate("1991-12-14T10Z", 0, 692704800);
+ ret &= check_one_xgetdate("1991-12-14T10:11Z", 0, 692705460);
+ ret &= check_one_xgetdate("1991-12-14T10:11:12Z", 0, 692705472);
+ ret &= check_one_xgetdate("1991-12-14T10:11:12?", EINVAL, 0);
+ ret &= check_one_xgetdate("1991-12-14T03-07", 0, 692704800);
+ ret &= check_one_xgetdate("1991-12-14T06:41-03:30", 0, 692705460);
+ ret &= check_one_xgetdate("1991-12-14T03:11:12-07:00", 0, 692705472);
+ ret &= check_one_xgetdate("19911214 031112-0700", 0, 692705472);;
+
+ return ret;
+}
+
+#define TM_FORMAT "%04d-%02d-%02d %02d:%02d:%02d (%d/7, %d/365%s)"
+
+#define TM_PRINTF(tm) \
+ (1900 + (tm).tm_year), (tm).tm_mon, (tm).tm_mday, \
+ (tm).tm_hour, (tm).tm_min, (tm).tm_sec, \
+ ((tm).tm_wday + 1), ((tm).tm_yday + 1), \
+ ((tm).tm_isdst ? ((tm).tm_isdst < 0 ? ", DST?" : ", DST") : "")
+
+/** Check one xmktime() result. */
+static bool check_one_xmktime(time_t expected) {
+ struct tm tm;
+ if (xlocaltime(&expected, &tm) != 0) {
+ bfs_diag("xlocaltime(%jd): %s", (intmax_t)expected, xstrerror(errno));
+ return false;
+ }
+
+ time_t actual;
+ return bfs_check(xmktime(&tm, &actual) == 0, "xmktime(" TM_FORMAT "): %s", TM_PRINTF(tm), xstrerror(errno))
+ && bfs_check(actual == expected, "xmktime(" TM_FORMAT "): %jd != %jd", TM_PRINTF(tm), (intmax_t)actual, (intmax_t)expected);
}
/** xmktime() tests. */
static bool check_xmktime(void) {
+ bool ret = true;
+
for (time_t time = -10; time <= 10; ++time) {
- struct tm tm;
- if (xlocaltime(&time, &tm) != 0) {
- perror("xlocaltime()");
- return false;
- }
-
- time_t made;
- if (xmktime(&tm, &made) != 0) {
- perror("xmktime()");
- return false;
- }
-
- if (time != made) {
- fprintf(stderr, "Mismatch: %jd != %jd\n", (intmax_t)time, (intmax_t)made);
- tm_print(stderr, &tm);
- return false;
- }
+ ret &= check_one_xmktime(time);
+ }
+
+ return ret;
+}
+
+/** Check one xtimegm() result. */
+static bool check_one_xtimegm(const struct tm *tm) {
+ struct tm tma = *tm, tmb = *tm;
+ time_t ta, tb;
+ ta = mktime(&tma);
+ if (xtimegm(&tmb, &tb) != 0) {
+ tb = -1;
}
- return true;
+ bool ret = true;
+ ret &= bfs_check(ta == tb, "%jd != %jd", (intmax_t)ta, (intmax_t)tb);
+ ret &= bfs_check(ta == -1 || tm_equal(&tma, &tmb));
+
+ if (!ret) {
+ bfs_diag("mktime(): " TM_FORMAT, TM_PRINTF(tma));
+ bfs_diag("xtimegm(): " TM_FORMAT, TM_PRINTF(tmb));
+ bfs_diag("(input): " TM_FORMAT, TM_PRINTF(*tm));
+ }
+
+ return ret;
}
/** xtimegm() tests. */
static bool check_xtimegm(void) {
+ bool ret = true;
+
struct tm tm = {
.tm_isdst = -1,
};
@@ -137,33 +138,10 @@ static bool check_xtimegm(void) {
for (tm.tm_hour = -1; tm.tm_hour <= 24; tm.tm_hour += 5)
for (tm.tm_min = -1; tm.tm_min <= 60; tm.tm_min += 31)
for (tm.tm_sec = -60; tm.tm_sec <= 120; tm.tm_sec += 5) {
- struct tm tma = tm, tmb = tm;
- time_t ta, tb;
- ta = mktime(&tma);
- if (xtimegm(&tmb, &tb) != 0) {
- tb = -1;
- }
-
- bool fail = false;
- if (ta != tb) {
- printf("Mismatch: %jd != %jd\n", (intmax_t)ta, (intmax_t)tb);
- fail = true;
- }
- if (ta != -1 && !tm_equal(&tma, &tmb)) {
- printf("mktime(): ");
- tm_print(stdout, &tma);
- printf("xtimegm(): ");
- tm_print(stdout, &tmb);
- fail = true;
- }
- if (fail) {
- printf("Input: ");
- tm_print(stdout, &tm);
- return false;
- }
+ ret &= check_one_xtimegm(&tm);
}
- return true;
+ return ret;
}
bool check_xtime(void) {
@@ -173,7 +151,9 @@ bool check_xtime(void) {
}
tzset();
- return check_xgetdate()
- & check_xmktime()
- & check_xtimegm();
+ bool ret = true;
+ ret &= check_xgetdate();
+ ret &= check_xmktime();
+ ret &= check_xtimegm();
+ return ret;
}