diff options
Diffstat (limited to 'src/test/test-macro.c')
-rw-r--r-- | src/test/test-macro.c | 374 |
1 files changed, 260 insertions, 114 deletions
diff --git a/src/test/test-macro.c b/src/test/test-macro.c index b91a1f9..9e2875d 100644 --- a/src/test/test-macro.c +++ b/src/test/test-macro.c @@ -1,7 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include <stddef.h> +#include <sys/stat.h> +#include "errno-util.h" #include "log.h" #include "macro.h" #include "tests.h" @@ -159,6 +161,153 @@ TEST(container_of) { #pragma GCC diagnostic pop +#define TEST_OVERFLOW_MATH_BY_TYPE(type, min, max, lit) \ + ({ \ + type x; \ + \ + assert_se(ADD_SAFE(&x, lit(5), lit(10))); \ + assert_se(x == lit(15)); \ + if (IS_SIGNED_INTEGER_TYPE(type)) { \ + assert_se(ADD_SAFE(&x, lit(5), lit(-10))); \ + assert_se(x == lit(-5)); \ + } \ + assert_se(ADD_SAFE(&x, min, lit(0))); \ + assert_se(x == min); \ + assert_se(ADD_SAFE(&x, max, lit(0))); \ + assert_se(x == max); \ + if (IS_SIGNED_INTEGER_TYPE(type)) \ + assert_se(!ADD_SAFE(&x, min, lit(-1))); \ + assert_se(!ADD_SAFE(&x, max, lit(1))); \ + \ + x = lit(5); \ + assert_se(INC_SAFE(&x, lit(10))); \ + assert_se(x == lit(15)); \ + if (IS_SIGNED_INTEGER_TYPE(type)) { \ + assert_se(INC_SAFE(&x, lit(-20))); \ + assert_se(x == lit(-5)); \ + } \ + x = min; \ + assert_se(INC_SAFE(&x, lit(0))); \ + assert_se(x == min); \ + if (IS_SIGNED_INTEGER_TYPE(type)) \ + assert_se(!INC_SAFE(&x, lit(-1))); \ + x = max; \ + assert_se(INC_SAFE(&x, lit(0))); \ + assert_se(x == max); \ + assert_se(!INC_SAFE(&x, lit(1))); \ + \ + assert_se(SUB_SAFE(&x, lit(10), lit(5))); \ + assert_se(x == lit(5)); \ + if (IS_SIGNED_INTEGER_TYPE(type)) { \ + assert_se(SUB_SAFE(&x, lit(5), lit(10))); \ + assert_se(x == lit(-5)); \ + \ + assert_se(SUB_SAFE(&x, lit(5), lit(-10))); \ + assert_se(x == lit(15)); \ + } else \ + assert_se(!SUB_SAFE(&x, lit(5), lit(10))); \ + assert_se(SUB_SAFE(&x, min, lit(0))); \ + assert_se(x == min); \ + assert_se(SUB_SAFE(&x, max, lit(0))); \ + assert_se(x == max); \ + assert_se(!SUB_SAFE(&x, min, lit(1))); \ + if (IS_SIGNED_INTEGER_TYPE(type)) \ + assert_se(!SUB_SAFE(&x, max, lit(-1))); \ + \ + x = lit(10); \ + assert_se(DEC_SAFE(&x, lit(5))); \ + assert_se(x == lit(5)); \ + if (IS_SIGNED_INTEGER_TYPE(type)) { \ + assert_se(DEC_SAFE(&x, lit(10))); \ + assert_se(x == lit(-5)); \ + \ + x = lit(5); \ + assert_se(DEC_SAFE(&x, lit(-10))); \ + assert_se(x == lit(15)); \ + } else \ + assert_se(!DEC_SAFE(&x, lit(10))); \ + x = min; \ + assert_se(DEC_SAFE(&x, lit(0))); \ + assert_se(x == min); \ + assert_se(!DEC_SAFE(&x, lit(1))); \ + x = max; \ + assert_se(DEC_SAFE(&x, lit(0))); \ + if (IS_SIGNED_INTEGER_TYPE(type)) \ + assert_se(!DEC_SAFE(&x, lit(-1))); \ + \ + assert_se(MUL_SAFE(&x, lit(2), lit(4))); \ + assert_se(x == lit(8)); \ + if (IS_SIGNED_INTEGER_TYPE(type)) { \ + assert_se(MUL_SAFE(&x, lit(2), lit(-4))); \ + assert_se(x == lit(-8)); \ + } \ + assert_se(MUL_SAFE(&x, lit(5), lit(0))); \ + assert_se(x == lit(0)); \ + assert_se(MUL_SAFE(&x, min, lit(1))); \ + assert_se(x == min); \ + if (IS_SIGNED_INTEGER_TYPE(type)) \ + assert_se(!MUL_SAFE(&x, min, lit(2))); \ + assert_se(MUL_SAFE(&x, max, lit(1))); \ + assert_se(x == max); \ + assert_se(!MUL_SAFE(&x, max, lit(2))); \ + \ + x = lit(2); \ + assert_se(MUL_ASSIGN_SAFE(&x, lit(4))); \ + assert_se(x == lit(8)); \ + if (IS_SIGNED_INTEGER_TYPE(type)) { \ + assert_se(MUL_ASSIGN_SAFE(&x, lit(-1))); \ + assert_se(x == lit(-8)); \ + } \ + assert_se(MUL_ASSIGN_SAFE(&x, lit(0))); \ + assert_se(x == lit(0)); \ + x = min; \ + assert_se(MUL_ASSIGN_SAFE(&x, lit(1))); \ + assert_se(x == min); \ + if IS_SIGNED_INTEGER_TYPE(type) \ + assert_se(!MUL_ASSIGN_SAFE(&x, lit(2))); \ + x = max; \ + assert_se(MUL_ASSIGN_SAFE(&x, lit(1))); \ + assert_se(x == max); \ + assert_se(!MUL_ASSIGN_SAFE(&x, lit(2))); \ + }) + +TEST(overflow_safe_math) { + int64_t i; + uint64_t u, *p; + + /* basic tests */ + TEST_OVERFLOW_MATH_BY_TYPE(int8_t, INT8_MIN, INT8_MAX, INT8_C); + TEST_OVERFLOW_MATH_BY_TYPE(int16_t, INT16_MIN, INT16_MAX, INT16_C); + TEST_OVERFLOW_MATH_BY_TYPE(int32_t, INT32_MIN, INT32_MAX, INT32_C); + TEST_OVERFLOW_MATH_BY_TYPE(int64_t, INT64_MIN, INT64_MAX, INT64_C); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" /* Otherwise the compiler complains about comparisons to negative numbers always being false */ + TEST_OVERFLOW_MATH_BY_TYPE(uint8_t, UINT8_C(0), UINT8_MAX, UINT8_C); + TEST_OVERFLOW_MATH_BY_TYPE(uint16_t, UINT16_C(0), UINT16_MAX, UINT16_C); + TEST_OVERFLOW_MATH_BY_TYPE(uint32_t, UINT32_C(0), UINT32_MAX, UINT32_C); + TEST_OVERFLOW_MATH_BY_TYPE(uint64_t, UINT64_C(0), UINT64_MAX, UINT64_C); +#pragma GCC diagnostic pop + + /* make sure we handle pointers correctly */ + p = &u; + assert_se(ADD_SAFE(p, 35, 15) && (u == 50)); + assert_se(SUB_SAFE(p, 35, 15) && (u == 20)); + assert_se(MUL_SAFE(p, 5, 10) && (u == 50)); + assert_se(INC_SAFE(p, 10) && (u == 60)); + assert_se(DEC_SAFE(p, 10) && (u == 50)); + assert_se(MUL_ASSIGN_SAFE(p, 3) && (u == 150)); + assert_se(!ADD_SAFE(p, UINT64_MAX, 1)); + assert_se(!SUB_SAFE(p, 0, 1)); + + /* cross-type sanity checks */ + assert_se(ADD_SAFE(&i, INT32_MAX, 1)); + assert_se(SUB_SAFE(&i, INT32_MIN, 1)); + assert_se(!ADD_SAFE(&i, UINT64_MAX, 0)); + assert_se(ADD_SAFE(&u, INT32_MAX, 1)); + assert_se(MUL_SAFE(&u, INT32_MAX, 2)); +} + TEST(DIV_ROUND_UP) { int div; @@ -221,92 +370,13 @@ TEST(IN_SET) { assert_se(!IN_SET(t.x, 2, 3, 4)); } -TEST(FOREACH_POINTER) { - int a, b, c, *i; - size_t k = 0; - - FOREACH_POINTER(i, &a, &b, &c) { - switch (k) { - - case 0: - assert_se(i == &a); - break; - - case 1: - assert_se(i == &b); - break; - - case 2: - assert_se(i == &c); - break; - - default: - assert_not_reached(); - break; - } - - k++; - } - - assert_se(k == 3); - - FOREACH_POINTER(i, &b) { - assert_se(k == 3); - assert_se(i == &b); - k = 4; - } - - assert_se(k == 4); - - FOREACH_POINTER(i, NULL, &c, NULL, &b, NULL, &a, NULL) { - switch (k) { - - case 4: - assert_se(i == NULL); - break; - - case 5: - assert_se(i == &c); - break; - - case 6: - assert_se(i == NULL); - break; - - case 7: - assert_se(i == &b); - break; - - case 8: - assert_se(i == NULL); - break; - - case 9: - assert_se(i == &a); - break; - - case 10: - assert_se(i == NULL); - break; - - default: - assert_not_reached(); - break; - } - - k++; - } - - assert_se(k == 11); -} - -TEST(FOREACH_VA_ARGS) { +TEST(FOREACH_ARGUMENT) { size_t i; i = 0; uint8_t u8, u8_1 = 1, u8_2 = 2, u8_3 = 3; - VA_ARGS_FOREACH(u8, u8_2, 8, 0xff, u8_1, u8_3, 0, 1) { - switch(i++) { + FOREACH_ARGUMENT(u8, u8_2, 8, 0xff, u8_1, u8_3, 0, 1) { + switch (i++) { case 0: assert_se(u8 == u8_2); break; case 1: assert_se(u8 == 8); break; case 2: assert_se(u8 == 0xff); break; @@ -319,24 +389,24 @@ TEST(FOREACH_VA_ARGS) { } assert_se(i == 7); i = 0; - VA_ARGS_FOREACH(u8, 0) { + FOREACH_ARGUMENT(u8, 0) { assert_se(u8 == 0); assert_se(i++ == 0); } assert_se(i == 1); i = 0; - VA_ARGS_FOREACH(u8, 0xff) { + FOREACH_ARGUMENT(u8, 0xff) { assert_se(u8 == 0xff); assert_se(i++ == 0); } assert_se(i == 1); - VA_ARGS_FOREACH(u8) + FOREACH_ARGUMENT(u8) assert_se(false); i = 0; uint32_t u32, u32_1 = 0xffff0000, u32_2 = 10, u32_3 = 0xffff; - VA_ARGS_FOREACH(u32, 1, 100, u32_2, 1000, u32_3, u32_1, 1, 0) { - switch(i++) { + FOREACH_ARGUMENT(u32, 1, 100, u32_2, 1000, u32_3, u32_1, 1, 0) { + switch (i++) { case 0: assert_se(u32 == 1); break; case 1: assert_se(u32 == 100); break; case 2: assert_se(u32 == u32_2); break; @@ -350,24 +420,24 @@ TEST(FOREACH_VA_ARGS) { } assert_se(i == 8); i = 0; - VA_ARGS_FOREACH(u32, 0) { + FOREACH_ARGUMENT(u32, 0) { assert_se(u32 == 0); assert_se(i++ == 0); } assert_se(i == 1); i = 0; - VA_ARGS_FOREACH(u32, 1000) { + FOREACH_ARGUMENT(u32, 1000) { assert_se(u32 == 1000); assert_se(i++ == 0); } assert_se(i == 1); - VA_ARGS_FOREACH(u32) + FOREACH_ARGUMENT(u32) assert_se(false); i = 0; uint64_t u64, u64_1 = 0xffffffffffffffff, u64_2 = 50, u64_3 = 0xffff; - VA_ARGS_FOREACH(u64, 44, 0, u64_3, 100, u64_2, u64_1, 50000) { - switch(i++) { + FOREACH_ARGUMENT(u64, 44, 0, u64_3, 100, u64_2, u64_1, 50000) { + switch (i++) { case 0: assert_se(u64 == 44); break; case 1: assert_se(u64 == 0); break; case 2: assert_se(u64 == u64_3); break; @@ -380,18 +450,18 @@ TEST(FOREACH_VA_ARGS) { } assert_se(i == 7); i = 0; - VA_ARGS_FOREACH(u64, 0) { + FOREACH_ARGUMENT(u64, 0) { assert_se(u64 == 0); assert_se(i++ == 0); } assert_se(i == 1); i = 0; - VA_ARGS_FOREACH(u64, 0xff00ff00000000) { + FOREACH_ARGUMENT(u64, 0xff00ff00000000) { assert_se(u64 == 0xff00ff00000000); assert_se(i++ == 0); } assert_se(i == 1); - VA_ARGS_FOREACH(u64) + FOREACH_ARGUMENT(u64) assert_se(false); struct test { @@ -405,8 +475,8 @@ TEST(FOREACH_VA_ARGS) { s_2 = { .a = 100000, .b = 'z', }, s_3 = { .a = 0xff, .b = 'q', }, s_4 = { .a = 1, .b = 'x', }; - VA_ARGS_FOREACH(s, s_1, (struct test){ .a = 10, .b = 'd', }, s_2, (struct test){}, s_3, s_4) { - switch(i++) { + FOREACH_ARGUMENT(s, s_1, (struct test){ .a = 10, .b = 'd', }, s_2, (struct test){}, s_3, s_4) { + switch (i++) { case 0: assert_se(s.a == 0 ); assert_se(s.b == 'c'); break; case 1: assert_se(s.a == 10 ); assert_se(s.b == 'd'); break; case 2: assert_se(s.a == 100000); assert_se(s.b == 'z'); break; @@ -418,69 +488,69 @@ TEST(FOREACH_VA_ARGS) { } assert_se(i == 6); i = 0; - VA_ARGS_FOREACH(s, (struct test){ .a = 1, .b = 'A', }) { + FOREACH_ARGUMENT(s, (struct test){ .a = 1, .b = 'A', }) { assert_se(s.a == 1); assert_se(s.b == 'A'); assert_se(i++ == 0); } assert_se(i == 1); - VA_ARGS_FOREACH(s) + FOREACH_ARGUMENT(s) assert_se(false); i = 0; struct test *p, *p_1 = &s_1, *p_2 = &s_2, *p_3 = &s_3, *p_4 = &s_4; - VA_ARGS_FOREACH(p, p_1, NULL, p_2, p_3, NULL, p_4, NULL) { - switch(i++) { + FOREACH_ARGUMENT(p, p_1, NULL, p_2, p_3, NULL, p_4, NULL) { + switch (i++) { case 0: assert_se(p == p_1); break; - case 1: assert_se(p == NULL); break; + case 1: ASSERT_NULL(p); break; case 2: assert_se(p == p_2); break; case 3: assert_se(p == p_3); break; - case 4: assert_se(p == NULL); break; + case 4: ASSERT_NULL(p); break; case 5: assert_se(p == p_4); break; - case 6: assert_se(p == NULL); break; + case 6: ASSERT_NULL(p); break; default: assert_se(false); } } assert_se(i == 7); i = 0; - VA_ARGS_FOREACH(p, p_3) { + FOREACH_ARGUMENT(p, p_3) { assert_se(p == p_3); assert_se(i++ == 0); } assert_se(i == 1); - VA_ARGS_FOREACH(p) + FOREACH_ARGUMENT(p) assert_se(false); i = 0; void *v, *v_1 = p_1, *v_2 = p_2, *v_3 = p_3; uint32_t *u32p = &u32; - VA_ARGS_FOREACH(v, v_1, NULL, u32p, v_3, p_2, p_4, v_2, NULL) { - switch(i++) { + FOREACH_ARGUMENT(v, v_1, NULL, u32p, v_3, p_2, p_4, v_2, NULL) { + switch (i++) { case 0: assert_se(v == v_1); break; - case 1: assert_se(v == NULL); break; + case 1: ASSERT_NULL(v); break; case 2: assert_se(v == u32p); break; case 3: assert_se(v == v_3); break; case 4: assert_se(v == p_2); break; case 5: assert_se(v == p_4); break; case 6: assert_se(v == v_2); break; - case 7: assert_se(v == NULL); break; + case 7: ASSERT_NULL(v); break; default: assert_se(false); } } assert_se(i == 8); i = 0; - VA_ARGS_FOREACH(v, NULL) { - assert_se(v == NULL); + FOREACH_ARGUMENT(v, NULL) { + ASSERT_NULL(v); assert_se(i++ == 0); } assert_se(i == 1); i = 0; - VA_ARGS_FOREACH(v, v_1) { + FOREACH_ARGUMENT(v, v_1) { assert_se(v == v_1); assert_se(i++ == 0); } assert_se(i == 1); - VA_ARGS_FOREACH(v) + FOREACH_ARGUMENT(v) assert_se(false); } @@ -1037,4 +1107,80 @@ TEST(u64_multiply_safe) { assert_se(u64_multiply_safe(UINT64_MAX, UINT64_MAX) == 0); } +TEST(ASSERT) { + char *null = NULL; + + ASSERT_OK(0); + ASSERT_OK(255); + ASSERT_OK(printf("Hello world\n")); + ASSERT_SIGNAL(ASSERT_OK(-1), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK(-ENOANO), SIGABRT); + + ASSERT_OK_ERRNO(0 >= 0); + ASSERT_OK_ERRNO(255 >= 0); + ASSERT_OK_ERRNO(printf("Hello world\n")); + ASSERT_SIGNAL(ASSERT_OK_ERRNO(-1), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_ERRNO(-ENOANO), SIGABRT); + + ASSERT_ERROR(-ENOENT, ENOENT); + ASSERT_ERROR(RET_NERRNO(mkdir("/i/will/fail/with/enoent", 666)), ENOENT); + ASSERT_SIGNAL(ASSERT_ERROR(0, ENOENT), SIGABRT); + ASSERT_SIGNAL(ASSERT_ERROR(RET_NERRNO(mkdir("/i/will/fail/with/enoent", 666)), ENOANO), SIGABRT); + + errno = ENOENT; + ASSERT_ERROR_ERRNO(-1, ENOENT); + errno = 0; + ASSERT_ERROR_ERRNO(mkdir("/i/will/fail/with/enoent", 666), ENOENT); + ASSERT_SIGNAL(ASSERT_ERROR_ERRNO(0, ENOENT), SIGABRT); + errno = 0; + ASSERT_SIGNAL(ASSERT_ERROR_ERRNO(mkdir("/i/will/fail/with/enoent", 666), ENOANO), SIGABRT); + + ASSERT_TRUE(true); + ASSERT_TRUE(255); + ASSERT_TRUE(getpid()); + ASSERT_SIGNAL(ASSERT_TRUE(1 == 0), SIGABRT); + + ASSERT_FALSE(false); + ASSERT_FALSE(1 == 0); + ASSERT_SIGNAL(ASSERT_FALSE(1 > 0), SIGABRT); + + ASSERT_NULL(NULL); + ASSERT_SIGNAL(ASSERT_NULL(signal_to_string(SIGINT)), SIGABRT); + + ASSERT_NOT_NULL(signal_to_string(SIGTERM)); + ASSERT_SIGNAL(ASSERT_NOT_NULL(NULL), SIGABRT); + + ASSERT_STREQ(NULL, null); + ASSERT_STREQ("foo", "foo"); + ASSERT_SIGNAL(ASSERT_STREQ(null, "bar"), SIGABRT); + ASSERT_SIGNAL(ASSERT_STREQ("foo", "bar"), SIGABRT); + + ASSERT_EQ(0, 0); + ASSERT_EQ(-1, -1); + ASSERT_SIGNAL(ASSERT_EQ(255, -1), SIGABRT); + + ASSERT_GE(0, 0); + ASSERT_GE(1, -1); + ASSERT_SIGNAL(ASSERT_GE(-1, 1), SIGABRT); + + ASSERT_LE(0, 0); + ASSERT_LE(-1, 1); + ASSERT_SIGNAL(ASSERT_LE(1, -1), SIGABRT); + + ASSERT_NE(0, (int64_t) UINT_MAX); + ASSERT_NE(-1, 1); + ASSERT_SIGNAL(ASSERT_NE(0, 0), SIGABRT); + ASSERT_SIGNAL(ASSERT_NE(-1, -1), SIGABRT); + + ASSERT_GT(1, 0); + ASSERT_GT(1, -1); + ASSERT_SIGNAL(ASSERT_GT(0, 0), SIGABRT); + ASSERT_SIGNAL(ASSERT_GT(-1, 1), SIGABRT); + + ASSERT_LT(0, 1); + ASSERT_LT(-1, 1); + ASSERT_SIGNAL(ASSERT_LT(0, 0), SIGABRT); + ASSERT_SIGNAL(ASSERT_LT(1, -1), SIGABRT); +} + DEFINE_TEST_MAIN(LOG_INFO); |