From 89181651e61e8bdecd7c59e037e067f7e8290f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 28 Jun 2025 18:36:37 +0200 Subject: [PATCH 01/11] shared/tests: indent defines --- src/shared/tests.h | 104 ++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/src/shared/tests.h b/src/shared/tests.h index 33acbb7cdf..8ae09fc4eb 100644 --- a/src/shared/tests.h +++ b/src/shared/tests.h @@ -171,9 +171,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char unsigned long long: "%llu") #ifdef __COVERITY__ -#define ASSERT_OK(expr) __coverity_check__((expr) >= 0) +# define ASSERT_OK(expr) __coverity_check__((expr) >= 0) #else -#define ASSERT_OK(expr) \ +# define ASSERT_OK(expr) \ ({ \ typeof(expr) _result = (expr); \ if (_result < 0) \ @@ -183,9 +183,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char /* For functions that return a boolean on success and a negative errno on failure. */ #ifdef __COVERITY__ -#define ASSERT_OK_POSITIVE(expr) __coverity_check__((expr) > 0) +# define ASSERT_OK_POSITIVE(expr) __coverity_check__((expr) > 0) #else -#define ASSERT_OK_POSITIVE(expr) \ +# define ASSERT_OK_POSITIVE(expr) \ ({ \ typeof(expr) _result = (expr); \ if (_result < 0) \ @@ -196,9 +196,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_OK_ZERO(expr) __coverity_check__((expr) == 0) +# define ASSERT_OK_ZERO(expr) __coverity_check__((expr) == 0) #else -#define ASSERT_OK_ZERO(expr) \ +# define ASSERT_OK_ZERO(expr) \ ({ \ typeof(expr) _result = (expr); \ if (_result < 0) \ @@ -212,9 +212,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_OK_EQ(expr1, expr2) __coverity_check__((expr1) == (expr2)) +# define ASSERT_OK_EQ(expr1, expr2) __coverity_check__((expr1) == (expr2)) #else -#define ASSERT_OK_EQ(expr1, expr2) \ +# define ASSERT_OK_EQ(expr1, expr2) \ ({ \ typeof(expr1) _expr1 = (expr1); \ typeof(expr2) _expr2 = (expr2); \ @@ -231,9 +231,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_OK_ERRNO(expr) __coverity_check__((expr) >= 0) +# define ASSERT_OK_ERRNO(expr) __coverity_check__((expr) >= 0) #else -#define ASSERT_OK_ERRNO(expr) \ +# define ASSERT_OK_ERRNO(expr) \ ({ \ typeof(expr) _result = (expr); \ if (_result < 0) \ @@ -242,9 +242,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_OK_ZERO_ERRNO(expr) __coverity_check__((expr) == 0) +# define ASSERT_OK_ZERO_ERRNO(expr) __coverity_check__((expr) == 0) #else -#define ASSERT_OK_ZERO_ERRNO(expr) \ +# define ASSERT_OK_ZERO_ERRNO(expr) \ ({ \ typeof(expr) _result = (expr); \ if (_result < 0) \ @@ -258,9 +258,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_OK_EQ_ERRNO(expr1, expr2) __coverity_check__((expr1) == (expr2)) +# define ASSERT_OK_EQ_ERRNO(expr1, expr2) __coverity_check__((expr1) == (expr2)) #else -#define ASSERT_OK_EQ_ERRNO(expr1, expr2) \ +# define ASSERT_OK_EQ_ERRNO(expr1, expr2) \ ({ \ typeof(expr1) _expr1 = (expr1); \ typeof(expr2) _expr2 = (expr2); \ @@ -277,9 +277,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_FAIL(expr) __coverity_check__((expr) < 0) +# define ASSERT_FAIL(expr) __coverity_check__((expr) < 0) #else -#define ASSERT_FAIL(expr) \ +# define ASSERT_FAIL(expr) \ ({ \ typeof(expr) _result = (expr); \ if (_result >= 0) \ @@ -288,9 +288,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_ERROR(expr1, expr2) __coverity_check__((expr1) == -(expr2)) +# define ASSERT_ERROR(expr1, expr2) __coverity_check__((expr1) == -(expr2)) #else -#define ASSERT_ERROR(expr1, expr2) \ +# define ASSERT_ERROR(expr1, expr2) \ ({ \ int _expr1 = (expr1); \ int _expr2 = (expr2); \ @@ -304,9 +304,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_ERROR_ERRNO(expr1, expr2) __coverity_check__((expr1) < 0 && errno == (expr2)) +# define ASSERT_ERROR_ERRNO(expr1, expr2) __coverity_check__((expr1) < 0 && errno == (expr2)) #else -#define ASSERT_ERROR_ERRNO(expr1, expr2) \ +# define ASSERT_ERROR_ERRNO(expr1, expr2) \ ({ \ int _expr1 = (expr1); \ int _expr2 = (expr2); \ @@ -320,9 +320,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_TRUE(expr) __coverity_check__(!!(expr)) +# define ASSERT_TRUE(expr) __coverity_check__(!!(expr)) #else -#define ASSERT_TRUE(expr) \ +# define ASSERT_TRUE(expr) \ ({ \ if (!(expr)) \ log_test_failed("Expected \"%s\" to be true", #expr); \ @@ -330,9 +330,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_FALSE(expr) __coverity_check__(!(expr)) +# define ASSERT_FALSE(expr) __coverity_check__(!(expr)) #else -#define ASSERT_FALSE(expr) \ +# define ASSERT_FALSE(expr) \ ({ \ if ((expr)) \ log_test_failed("Expected \"%s\" to be false", #expr); \ @@ -340,9 +340,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_NULL(expr) __coverity_check__((expr) == NULL) +# define ASSERT_NULL(expr) __coverity_check__((expr) == NULL) #else -#define ASSERT_NULL(expr) \ +# define ASSERT_NULL(expr) \ ({ \ typeof(expr) _result = (expr); \ if (_result != NULL) \ @@ -351,9 +351,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_NOT_NULL(expr) __coverity_check__((expr) != NULL) +# define ASSERT_NOT_NULL(expr) __coverity_check__((expr) != NULL) #else -#define ASSERT_NOT_NULL(expr) \ +# define ASSERT_NOT_NULL(expr) \ ({ \ typeof(expr) _result = (expr); \ if (_result == NULL) \ @@ -363,9 +363,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_STREQ(expr1, expr2) __coverity_check__(streq_ptr((expr1), (expr2))) +# define ASSERT_STREQ(expr1, expr2) __coverity_check__(streq_ptr((expr1), (expr2))) #else -#define ASSERT_STREQ(expr1, expr2) \ +# define ASSERT_STREQ(expr1, expr2) \ ({ \ const char *_expr1 = (expr1), *_expr2 = (expr2); \ if (!streq_ptr(_expr1, _expr2)) \ @@ -375,9 +375,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_PTR_EQ(expr1, expr2) __coverity_check__((expr1) == (expr2)) +# define ASSERT_PTR_EQ(expr1, expr2) __coverity_check__((expr1) == (expr2)) #else -#define ASSERT_PTR_EQ(expr1, expr2) \ +# define ASSERT_PTR_EQ(expr1, expr2) \ ({ \ const void *_expr1 = (expr1), *_expr2 = (expr2); \ if (_expr1 != _expr2) \ @@ -390,9 +390,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char * input into strings first and then format those into the final assertion message. */ #ifdef __COVERITY__ -#define ASSERT_EQ(expr1, expr2) __coverity_check__((expr1) == (expr2)) +# define ASSERT_EQ(expr1, expr2) __coverity_check__((expr1) == (expr2)) #else -#define ASSERT_EQ(expr1, expr2) \ +# define ASSERT_EQ(expr1, expr2) \ ({ \ typeof(expr1) _expr1 = (expr1); \ typeof(expr2) _expr2 = (expr2); \ @@ -408,9 +408,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_GE(expr1, expr2) __coverity_check__((expr1) >= (expr2)) +# define ASSERT_GE(expr1, expr2) __coverity_check__((expr1) >= (expr2)) #else -#define ASSERT_GE(expr1, expr2) \ +# define ASSERT_GE(expr1, expr2) \ ({ \ typeof(expr1) _expr1 = (expr1); \ typeof(expr2) _expr2 = (expr2); \ @@ -426,9 +426,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_LE(expr1, expr2) __coverity_check__((expr1) <= (expr2)) +# define ASSERT_LE(expr1, expr2) __coverity_check__((expr1) <= (expr2)) #else -#define ASSERT_LE(expr1, expr2) \ +# define ASSERT_LE(expr1, expr2) \ ({ \ typeof(expr1) _expr1 = (expr1); \ typeof(expr2) _expr2 = (expr2); \ @@ -444,9 +444,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_NE(expr1, expr2) __coverity_check__((expr1) != (expr2)) +# define ASSERT_NE(expr1, expr2) __coverity_check__((expr1) != (expr2)) #else -#define ASSERT_NE(expr1, expr2) \ +# define ASSERT_NE(expr1, expr2) \ ({ \ typeof(expr1) _expr1 = (expr1); \ typeof(expr2) _expr2 = (expr2); \ @@ -462,9 +462,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_GT(expr1, expr2) __coverity_check__((expr1) > (expr2)) +# define ASSERT_GT(expr1, expr2) __coverity_check__((expr1) > (expr2)) #else -#define ASSERT_GT(expr1, expr2) \ +# define ASSERT_GT(expr1, expr2) \ ({ \ typeof(expr1) _expr1 = (expr1); \ typeof(expr2) _expr2 = (expr2); \ @@ -480,9 +480,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char #endif #ifdef __COVERITY__ -#define ASSERT_LT(expr1, expr2) __coverity_check__((expr1) < (expr2)) +# define ASSERT_LT(expr1, expr2) __coverity_check__((expr1) < (expr2)) #else -#define ASSERT_LT(expr1, expr2) \ +# define ASSERT_LT(expr1, expr2) \ ({ \ typeof(expr1) _expr1 = (expr1); \ typeof(expr2) _expr2 = (expr2); \ @@ -500,9 +500,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char int assert_signal_internal(void); #ifdef __COVERITY__ -#define ASSERT_SIGNAL(expr, signal) __coverity_check__(((expr), false)) +# define ASSERT_SIGNAL(expr, signal) __coverity_check__(((expr), false)) #else -#define ASSERT_SIGNAL(expr, signal) \ +# define ASSERT_SIGNAL(expr, signal) \ ({ \ ASSERT_TRUE(SIGNAL_VALID(signal)); \ int _r = assert_signal_internal(); \ @@ -518,9 +518,9 @@ int assert_signal_internal(void); #endif #ifdef __COVERITY__ -#define ASSERT_EQ_ID128(expr1, expr2) __coverity_check__(sd_id128_equal((expr1), (expr2))) +# define ASSERT_EQ_ID128(expr1, expr2) __coverity_check__(sd_id128_equal((expr1), (expr2))) #else -#define ASSERT_EQ_ID128(expr1, expr2) \ +# define ASSERT_EQ_ID128(expr1, expr2) \ ({ \ typeof(expr1) _expr1 = (expr1); \ typeof(expr2) _expr2 = (expr2); \ @@ -532,9 +532,9 @@ int assert_signal_internal(void); #endif #ifdef __COVERITY__ -#define ASSERT_NE_ID128(expr1, expr2) __coverity_check__(!sd_id128_equal((expr1), (expr2))) +# define ASSERT_NE_ID128(expr1, expr2) __coverity_check__(!sd_id128_equal((expr1), (expr2))) #else -#define ASSERT_NE_ID128(expr1, expr2) \ +# define ASSERT_NE_ID128(expr1, expr2) \ ({ \ typeof(expr1) _expr1 = (expr1); \ typeof(expr2) _expr2 = (expr2); \ @@ -551,9 +551,9 @@ int assert_signal_internal(void); (guid).Data4[4], (guid).Data4[5], (guid).Data4[6], (guid).Data4[7] \ #ifdef __COVERITY__ -#define ASSERT_EQ_EFI_GUID(expr1, expr2) __coverity_check__(efi_guid_equal((expr1), (expr2))) +# define ASSERT_EQ_EFI_GUID(expr1, expr2) __coverity_check__(efi_guid_equal((expr1), (expr2))) #else -#define ASSERT_EQ_EFI_GUID(expr1, expr2) \ +# define ASSERT_EQ_EFI_GUID(expr1, expr2) \ ({ \ typeof(expr1) _expr1 = (expr1); \ typeof(expr2) _expr2 = (expr2); \ From a1296fa5e53c8065dccd7c8e4796c40aa4d69791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 29 Jun 2025 22:15:29 +0200 Subject: [PATCH 02/11] test-tests: move assert tests to new file Those macros are defined in tests.[ch], so the tests should be in test-tests.c. --- src/test/meson.build | 1 + src/test/test-macro.c | 125 ---------------------------------------- src/test/test-tests.c | 130 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 125 deletions(-) create mode 100644 src/test/test-tests.c diff --git a/src/test/meson.build b/src/test/meson.build index e8e4a663d2..6bb9e3f40d 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -184,6 +184,7 @@ simple_tests += files( 'test-strxcpyx.c', 'test-sysctl-util.c', 'test-terminal-util.c', + 'test-tests.c', 'test-tmpfile-util.c', 'test-udev-util.c', 'test-uid-classification.c', diff --git a/src/test/test-macro.c b/src/test/test-macro.c index 2de70723aa..427a6b1490 100644 --- a/src/test/test-macro.c +++ b/src/test/test-macro.c @@ -1,10 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include -#include - -#include "sd-id128.h" - #include "errno-util.h" #include "tests.h" @@ -1107,124 +1102,4 @@ 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_POSITIVE(1); - ASSERT_OK_POSITIVE(255); - ASSERT_SIGNAL(ASSERT_OK_POSITIVE(0), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_POSITIVE(-1), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_POSITIVE(-ENOANO), SIGABRT); - - ASSERT_OK_ZERO(0); - ASSERT_SIGNAL(ASSERT_OK_ZERO(1), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_ZERO(255), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_ZERO(-1), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_ZERO(-ENOANO), SIGABRT); - - ASSERT_OK_EQ(0, 0); - ASSERT_SIGNAL(ASSERT_OK_EQ(1, 0), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_EQ(255, 5), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_EQ(-1, 0), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_EQ(-ENOANO, 0), 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_OK_ZERO_ERRNO(0); - ASSERT_SIGNAL(ASSERT_OK_ZERO_ERRNO(1), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_ZERO_ERRNO(255), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_ZERO_ERRNO(-1), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_ZERO_ERRNO(-ENOANO), SIGABRT); - - ASSERT_OK_EQ_ERRNO(0, 0); - ASSERT_SIGNAL(ASSERT_OK_EQ_ERRNO(1, 0), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_EQ_ERRNO(255, 5), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_EQ_ERRNO(-1, 0), SIGABRT); - ASSERT_SIGNAL(ASSERT_OK_EQ_ERRNO(-ENOANO, 0), SIGABRT); - - ASSERT_FAIL(-ENOENT); - ASSERT_FAIL(-EPERM); - ASSERT_SIGNAL(ASSERT_FAIL(0), SIGABRT); - ASSERT_SIGNAL(ASSERT_FAIL(255), 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); - - ASSERT_EQ_ID128(SD_ID128_NULL, SD_ID128_NULL); - ASSERT_NE_ID128(SD_ID128_MAKE(51,df,0b,4b,c3,b0,4c,97,80,e2,99,b9,8c,a3,73,b8), - SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e)); - ASSERT_SIGNAL( - ASSERT_EQ_ID128(SD_ID128_MAKE(51,df,0b,4b,c3,b0,4c,97,80,e2,99,b9,8c,a3,73,b8), - SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e)), - SIGABRT); - ASSERT_SIGNAL(ASSERT_NE_ID128(SD_ID128_NULL, SD_ID128_NULL), SIGABRT); -} - DEFINE_TEST_MAIN(LOG_INFO); diff --git a/src/test/test-tests.c b/src/test/test-tests.c new file mode 100644 index 0000000000..745fbeed3a --- /dev/null +++ b/src/test/test-tests.c @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include + +#include "sd-id128.h" + +#include "tests.h" + +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_POSITIVE(1); + ASSERT_OK_POSITIVE(255); + ASSERT_SIGNAL(ASSERT_OK_POSITIVE(0), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_POSITIVE(-1), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_POSITIVE(-ENOANO), SIGABRT); + + ASSERT_OK_ZERO(0); + ASSERT_SIGNAL(ASSERT_OK_ZERO(1), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_ZERO(255), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_ZERO(-1), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_ZERO(-ENOANO), SIGABRT); + + ASSERT_OK_EQ(0, 0); + ASSERT_SIGNAL(ASSERT_OK_EQ(1, 0), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_EQ(255, 5), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_EQ(-1, 0), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_EQ(-ENOANO, 0), 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_OK_ZERO_ERRNO(0); + ASSERT_SIGNAL(ASSERT_OK_ZERO_ERRNO(1), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_ZERO_ERRNO(255), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_ZERO_ERRNO(-1), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_ZERO_ERRNO(-ENOANO), SIGABRT); + + ASSERT_OK_EQ_ERRNO(0, 0); + ASSERT_SIGNAL(ASSERT_OK_EQ_ERRNO(1, 0), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_EQ_ERRNO(255, 5), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_EQ_ERRNO(-1, 0), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_EQ_ERRNO(-ENOANO, 0), SIGABRT); + + ASSERT_FAIL(-ENOENT); + ASSERT_FAIL(-EPERM); + ASSERT_SIGNAL(ASSERT_FAIL(0), SIGABRT); + ASSERT_SIGNAL(ASSERT_FAIL(255), 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); + + ASSERT_EQ_ID128(SD_ID128_NULL, SD_ID128_NULL); + ASSERT_NE_ID128(SD_ID128_MAKE(51,df,0b,4b,c3,b0,4c,97,80,e2,99,b9,8c,a3,73,b8), + SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e)); + ASSERT_SIGNAL( + ASSERT_EQ_ID128(SD_ID128_MAKE(51,df,0b,4b,c3,b0,4c,97,80,e2,99,b9,8c,a3,73,b8), + SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e)), + SIGABRT); + ASSERT_SIGNAL(ASSERT_NE_ID128(SD_ID128_NULL, SD_ID128_NULL), SIGABRT); +} + +DEFINE_TEST_MAIN(LOG_INFO); From 236f7ab07cbeba069fd739f7353458c11b9faac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 29 Jun 2025 22:57:08 +0200 Subject: [PATCH 03/11] tests: cast to intmax_t instead of printing to a temp buffer We can do this for int types, i.e. the variants where we expect a success/error code. The macros which do generating comparison operations also support floats so we shouldn't use intmax_t there. The code is shorter and calling printf once is certainly more efficient. --- src/shared/tests.h | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/src/shared/tests.h b/src/shared/tests.h index 8ae09fc4eb..7641b446b0 100644 --- a/src/shared/tests.h +++ b/src/shared/tests.h @@ -203,11 +203,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr) _result = (expr); \ if (_result < 0) \ log_test_failed("Expected \"%s\" to succeed, but got error: %s", #expr, STRERROR(_result)); \ - if (_result != 0) { \ - char _sexpr[DECIMAL_STR_MAX(typeof(expr))]; \ - xsprintf(_sexpr, DECIMAL_STR_FMT(_result), _result); \ - log_test_failed("Expected \"%s\" to be zero, but it is %s.", #expr, _sexpr); \ - } \ + if (_result != 0) \ + log_test_failed("Expected \"%s\" to be zero, but it is %"PRIiMAX".", \ + #expr, (intmax_t) _result); \ }) #endif @@ -220,13 +218,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr2) _expr2 = (expr2); \ if (_expr1 < 0) \ log_test_failed("Expected \"%s\" to succeed, but got error: %s", #expr1, STRERROR(_expr1)); \ - if (_expr1 != _expr2) { \ - char _sexpr1[DECIMAL_STR_MAX(typeof(expr1))]; \ - char _sexpr2[DECIMAL_STR_MAX(typeof(expr2))]; \ - xsprintf(_sexpr1, DECIMAL_STR_FMT(_expr1), _expr1); \ - xsprintf(_sexpr2, DECIMAL_STR_FMT(_expr2), _expr2); \ - log_test_failed("Expected \"%s == %s\", got %s != %s", #expr1, #expr2, _sexpr1, _sexpr2); \ - } \ + if (_expr1 != _expr2) \ + log_test_failed("Expected \"%s == %s\", got %"PRIiMAX" != %"PRIiMAX, \ + #expr1, #expr2, (intmax_t) _expr1, (intmax_t) _expr2); \ }) #endif @@ -249,11 +243,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr) _result = (expr); \ if (_result < 0) \ log_test_failed("Expected \"%s\" to succeed, but got error: %s", #expr, STRERROR(errno)); \ - if (_result != 0) { \ - char _sexpr[DECIMAL_STR_MAX(typeof(expr))]; \ - xsprintf(_sexpr, DECIMAL_STR_FMT(_result), _result); \ - log_test_failed("Expected \"%s\" to be zero, but it is %s.", #expr, _sexpr); \ - } \ + if (_result != 0) \ + log_test_failed("Expected \"%s\" to be zero, but it is %"PRIiMAX".", \ + #expr, (intmax_t) _result); \ }) #endif @@ -266,13 +258,9 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr2) _expr2 = (expr2); \ if (_expr1 < 0) \ log_test_failed("Expected \"%s\" to succeed, but got error: %s", #expr1, STRERROR(errno)); \ - if (_expr1 != _expr2) { \ - char _sexpr1[DECIMAL_STR_MAX(typeof(expr1))]; \ - char _sexpr2[DECIMAL_STR_MAX(typeof(expr2))]; \ - xsprintf(_sexpr1, DECIMAL_STR_FMT(_expr1), _expr1); \ - xsprintf(_sexpr2, DECIMAL_STR_FMT(_expr2), _expr2); \ - log_test_failed("Expected \"%s == %s\", but %s != %s", #expr1, #expr2, _sexpr1, _sexpr2); \ - } \ + if (_expr1 != _expr2) \ + log_test_failed("Expected \"%s == %s\", but %"PRIiMAX" != %"PRIiMAX, \ + #expr1, #expr2, (intmax_t) _expr1, (intmax_t) _expr2); \ }) #endif From 0adbb11b4e8d4e166cf60aa5fb5fffda5a05bd70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 28 Jun 2025 19:02:50 +0200 Subject: [PATCH 04/11] tests: print numeric error value too on failure The error message is not always meaningful. Also, sometimes we care about the sign of the value, and we ignore the sign of the error in the printing machinery. The messages for errno are changed to say "errno" instead of "error". The problem with the previous formalation is that our errors are always negative and errnos are positive, so when we print the numerical value, we cannot use the word for both. Example output: src/test/test-tests.c:15: Assertion failed: Expected "-1" to succeed, but got error: -1/Operation not permitted src/test/test-tests.c:16: Assertion failed: Expected "-ENOANO" to succeed, but got error: -55/No anode src/test/test-tests.c:61: Assertion failed: Expected "0" to fail with error -2/"No such file or directory", but it succeeded src/test/test-tests.c:62: Assertion failed: Expected "RET_NERRNO(mkdir("/i/will/fail/with/enoent", 666))" to fail with error -55/"No anode", but got the following error: -2/No such file or directory src/test/test-tests.c:68: Assertion failed: Expected "0" to fail with errno 2/"No such file or directory", but it succeeded src/test/test-tests.c:70: Assertion failed: Expected "mkdir("/i/will/fail/with/enoent", 666)" to fail with errno 55/"No anode", but got the following errno: 2/No such file or directory --- src/shared/tests.h | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/shared/tests.h b/src/shared/tests.h index 7641b446b0..d7c9250487 100644 --- a/src/shared/tests.h +++ b/src/shared/tests.h @@ -177,7 +177,8 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char ({ \ typeof(expr) _result = (expr); \ if (_result < 0) \ - log_test_failed("Expected \"%s\" to succeed, but got error: %s", #expr, STRERROR(_result)); \ + log_test_failed("Expected \"%s\" to succeed, but got error: %"PRIiMAX"/%s", \ + #expr, (intmax_t) _result, STRERROR(_result)); \ }) #endif @@ -189,7 +190,8 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char ({ \ typeof(expr) _result = (expr); \ if (_result < 0) \ - log_test_failed("Expected \"%s\" to succeed, but got error: %s", #expr, STRERROR(_result)); \ + log_test_failed("Expected \"%s\" to succeed, but got error: %"PRIiMAX"/%s", \ + #expr, (intmax_t) _result, STRERROR(_result)); \ if (_result == 0) \ log_test_failed("Expected \"%s\" to be positive, but it is zero.", #expr); \ }) @@ -202,7 +204,8 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char ({ \ typeof(expr) _result = (expr); \ if (_result < 0) \ - log_test_failed("Expected \"%s\" to succeed, but got error: %s", #expr, STRERROR(_result)); \ + log_test_failed("Expected \"%s\" to succeed, but got error: %"PRIiMAX"/%s", \ + #expr, (intmax_t) _result, STRERROR(_result)); \ if (_result != 0) \ log_test_failed("Expected \"%s\" to be zero, but it is %"PRIiMAX".", \ #expr, (intmax_t) _result); \ @@ -217,13 +220,15 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr1) _expr1 = (expr1); \ typeof(expr2) _expr2 = (expr2); \ if (_expr1 < 0) \ - log_test_failed("Expected \"%s\" to succeed, but got error: %s", #expr1, STRERROR(_expr1)); \ + log_test_failed("Expected \"%s\" to succeed, but got error: %"PRIiMAX"/%s", \ + #expr1, (intmax_t) _expr1, STRERROR(_expr1)); \ if (_expr1 != _expr2) \ log_test_failed("Expected \"%s == %s\", got %"PRIiMAX" != %"PRIiMAX, \ #expr1, #expr2, (intmax_t) _expr1, (intmax_t) _expr2); \ }) #endif +/* For functions that return a boolean on success and set errno on failure. */ #ifdef __COVERITY__ # define ASSERT_OK_ERRNO(expr) __coverity_check__((expr) >= 0) #else @@ -231,7 +236,8 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char ({ \ typeof(expr) _result = (expr); \ if (_result < 0) \ - log_test_failed("Expected \"%s\" to succeed, but got error: %s", #expr, STRERROR(errno)); \ + log_test_failed("Expected \"%s\" to succeed, but got errno: %d/%s", \ + #expr, errno, STRERROR(errno)); \ }) #endif @@ -242,7 +248,8 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char ({ \ typeof(expr) _result = (expr); \ if (_result < 0) \ - log_test_failed("Expected \"%s\" to succeed, but got error: %s", #expr, STRERROR(errno)); \ + log_test_failed("Expected \"%s\" to succeed, but got errno: %d/%s", \ + #expr, errno, STRERROR(errno)); \ if (_result != 0) \ log_test_failed("Expected \"%s\" to be zero, but it is %"PRIiMAX".", \ #expr, (intmax_t) _result); \ @@ -257,7 +264,8 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr1) _expr1 = (expr1); \ typeof(expr2) _expr2 = (expr2); \ if (_expr1 < 0) \ - log_test_failed("Expected \"%s\" to succeed, but got error: %s", #expr1, STRERROR(errno)); \ + log_test_failed("Expected \"%s\" to succeed, but got errno: %d/%s", \ + #expr1, errno, STRERROR(errno)); \ if (_expr1 != _expr2) \ log_test_failed("Expected \"%s == %s\", but %"PRIiMAX" != %"PRIiMAX, \ #expr1, #expr2, (intmax_t) _expr1, (intmax_t) _expr2); \ @@ -283,11 +291,11 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char int _expr1 = (expr1); \ int _expr2 = (expr2); \ if (_expr1 >= 0) \ - log_test_failed("Expected \"%s\" to fail with error \"%s\", but it succeeded", \ - #expr1, STRERROR(_expr2)); \ + log_test_failed("Expected \"%s\" to fail with error %d/\"%s\", but it succeeded", \ + #expr1, -_expr2, STRERROR(_expr2)); \ else if (-_expr1 != _expr2) \ - log_test_failed("Expected \"%s\" to fail with error \"%s\", but got the following error: %s", \ - #expr1, STRERROR(_expr2), STRERROR(_expr1)); \ + log_test_failed("Expected \"%s\" to fail with error %d/\"%s\", but got the following error: %d/%s", \ + #expr1, -_expr2, STRERROR(_expr2), _expr1, STRERROR(_expr1)); \ }) #endif @@ -299,11 +307,11 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char int _expr1 = (expr1); \ int _expr2 = (expr2); \ if (_expr1 >= 0) \ - log_test_failed("Expected \"%s\" to fail with error \"%s\", but it succeeded", \ - #expr1, STRERROR(_expr2)); \ + log_test_failed("Expected \"%s\" to fail with errno %d/\"%s\", but it succeeded", \ + #expr1, _expr2, STRERROR(_expr2)); \ else if (errno != _expr2) \ - log_test_failed("Expected \"%s\" to fail with error \"%s\", but got the following error: %s", \ - #expr1, STRERROR(_expr2), STRERROR(errno)); \ + log_test_failed("Expected \"%s\" to fail with errno %d/\"%s\", but got the following errno: %d/%s", \ + #expr1, _expr2, STRERROR(_expr2), errno, STRERROR(errno)); \ }) #endif From 367b32555448c1558770f942505d7d53c19ccb47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 28 Jun 2025 19:11:13 +0200 Subject: [PATCH 05/11] tests: add new ASSERT_OK_OR macro IN_SET() fails if __VA_ARGS__ is just one item. I inserted a bogus 0 item into the check to work around this. --- src/shared/tests.h | 16 ++++++++++++++++ src/test/test-tests.c | 10 ++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/shared/tests.h b/src/shared/tests.h index d7c9250487..5d1dccba9b 100644 --- a/src/shared/tests.h +++ b/src/shared/tests.h @@ -182,6 +182,22 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char }) #endif +#ifdef __COVERITY__ +# define ASSERT_OK_OR(expr, ...) \ + ({ \ + typeof(expr) _result = (expr); \ + __coverity_check__(_result >= 0 || IN_SET(_result, 0, __VA_ARGS__) \ + }) +#else +# define ASSERT_OK_OR(expr, ...) \ + ({ \ + typeof(expr) _result = (expr); \ + if (_result < 0 && !IN_SET(_result, 0, __VA_ARGS__)) \ + log_test_failed("\"%s\" failed with unexpected error: %"PRIiMAX"/%s", \ + #expr, (intmax_t) _result, STRERROR(_result)); \ + }) +#endif + /* For functions that return a boolean on success and a negative errno on failure. */ #ifdef __COVERITY__ # define ASSERT_OK_POSITIVE(expr) __coverity_check__((expr) > 0) diff --git a/src/test/test-tests.c b/src/test/test-tests.c index 745fbeed3a..40112a6762 100644 --- a/src/test/test-tests.c +++ b/src/test/test-tests.c @@ -127,4 +127,14 @@ TEST(ASSERT) { ASSERT_SIGNAL(ASSERT_NE_ID128(SD_ID128_NULL, SD_ID128_NULL), SIGABRT); } +TEST(ASSERT_OK_OR) { + ASSERT_OK_OR(0, -EINVAL, -EUCLEAN); + ASSERT_OK_OR(99, -EINVAL, -EUCLEAN); + ASSERT_OK_OR(-EINVAL, -EINVAL, -EUCLEAN); + ASSERT_OK_OR(-EUCLEAN, -EUCLEAN); + ASSERT_OK_OR(-1, -EPERM); + + ASSERT_SIGNAL(ASSERT_OK_OR(-1, -2), SIGABRT); +} + DEFINE_TEST_MAIN(LOG_INFO); From ea64d55080353c263998e8bd28a74ffa01b22393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 28 Jun 2025 20:12:32 +0200 Subject: [PATCH 06/11] tests: use new ASSERT_OK_OR macro --- src/test/test-audit-util.c | 8 ++------ src/test/test-cgroup-util.c | 21 +++++++-------------- src/test/test-execute.c | 17 ++++++----------- src/test/test-process-util.c | 12 +++--------- 4 files changed, 18 insertions(+), 40 deletions(-) diff --git a/src/test/test-audit-util.c b/src/test/test-audit-util.c index af2813d617..61521f3397 100644 --- a/src/test/test-audit-util.c +++ b/src/test/test-audit-util.c @@ -13,18 +13,14 @@ TEST(audit_loginuid_from_pid) { ASSERT_OK(pidref_set_pid(&pid1, 1)); uid_t uid; - r = audit_loginuid_from_pid(&self, &uid); - if (r != -ENODATA) - ASSERT_OK(r); + ASSERT_OK_OR(r = audit_loginuid_from_pid(&self, &uid), -ENODATA); if (r >= 0) log_info("self audit login uid: " UID_FMT, uid); ASSERT_ERROR(audit_loginuid_from_pid(&pid1, &uid), ENODATA); uint32_t sessionid; - r = audit_session_from_pid(&self, &sessionid); - if (r != -ENODATA) - ASSERT_OK(r); + ASSERT_OK_OR(r = audit_session_from_pid(&self, &sessionid), -ENODATA); if (r >= 0) log_info("self audit session id: %" PRIu32, sessionid); diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 0512532d0b..8debc21527 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -232,28 +232,21 @@ TEST(proc, .sd_booted = true) { continue; r = cg_pid_get_path_shifted(pid.pid, NULL, &path_shifted); - if (r != -ESRCH) - ASSERT_OK(r); + ASSERT_OK_OR(r, -ESRCH); r = cg_pidref_get_unit(&pid, &unit); - if (r != -ESRCH) - ASSERT_OK(r); + ASSERT_OK_OR(r, -ESRCH); r = cg_pid_get_slice(pid.pid, &slice); - if (r != -ESRCH) - ASSERT_OK(r); + ASSERT_OK_OR(r, -ESRCH); /* Not all processes belong to a specific user or a machine */ r = cg_pidref_get_owner_uid(&pid, &uid); - if (!IN_SET(r, -ESRCH, -ENXIO)) - ASSERT_OK(r); + ASSERT_OK_OR(r, -ESRCH, -ENXIO); r = cg_pidref_get_session(&pid, &session); - if (!IN_SET(r, -ESRCH, -ENXIO)) - ASSERT_OK(r); + ASSERT_OK_OR(r, -ESRCH, -ENXIO); r = cg_pid_get_user_unit(pid.pid, &user_unit); - if (!IN_SET(r, -ESRCH, -ENXIO)) - ASSERT_OK(r); + ASSERT_OK_OR(r, -ESRCH, -ENXIO); r = cg_pid_get_machine_name(pid.pid, &machine); - if (!IN_SET(r, -ESRCH, -ENOENT)) - ASSERT_OK(r); + ASSERT_OK_OR(r, -ESRCH, -ENOENT); log_debug(PID_FMT": %s, %s, "UID_FMT", %s, %s, %s, %s, %s", pid.pid, diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 621bbd4990..23c1fe2eed 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -223,9 +223,7 @@ static void start_parent_slices(Unit *unit) { slice = UNIT_GET_SLICE(unit); if (slice) { start_parent_slices(slice); - int r = unit_start(slice, NULL); - if (r != -EALREADY) - ASSERT_OK(r); + ASSERT_OK_OR(unit_start(slice, NULL), -EALREADY); } } @@ -1472,7 +1470,6 @@ static int prepare_ns(const char *process_name) { ASSERT_OK(r); if (r == 0) { _cleanup_free_ char *unit_dir = NULL, *build_dir = NULL, *build_dir_mount = NULL; - int ret; const char *coverage = getenv("COVERAGE_BUILD_DIR"); if (!coverage) @@ -1494,9 +1491,7 @@ static int prepare_ns(const char *process_name) { ASSERT_OK(copy_directory_at(AT_FDCWD, unit_dir, AT_FDCWD, PRIVATE_UNIT_DIR, COPY_MERGE_EMPTY)); /* Mount tmpfs on the following directories to make not StateDirectory= or friends disturb the host. */ - ret = get_build_exec_dir(&build_dir); - if (ret != -ENOEXEC) - ASSERT_OK(ret); + ASSERT_OK_OR(get_build_exec_dir(&build_dir), -ENOEXEC); if (build_dir) { /* Account for a build directory being in one of the soon-to-be-tmpfs directories. If we @@ -1512,11 +1507,11 @@ static int prepare_ns(const char *process_name) { ASSERT_OK(mount_nofollow_verbose(LOG_DEBUG, "tmpfs", p, "tmpfs", MS_NOSUID|MS_NODEV, NULL)); if (build_dir_mount) { - ret = RET_NERRNO(access(build_dir, F_OK)); - if (ret != -ENOENT) - ASSERT_OK(ret); + int k; - if (ret == -ENOENT) { + ASSERT_OK_OR(k = RET_NERRNO(access(build_dir, F_OK)), -ENOENT); + + if (k == -ENOENT) { /* The build directory got overmounted by tmpfs, so let's use the "backup" bind mount to * bring it back. */ ASSERT_OK(mkdir_p(build_dir, 0755)); diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c index 376b20b048..c0095a749c 100644 --- a/src/test/test-process-util.c +++ b/src/test/test-process-util.c @@ -86,9 +86,7 @@ static void test_pid_get_comm_one(pid_t pid) { ASSERT_TRUE(pid_is_kernel_thread(pid) == 0 || pid != 1); - r = get_process_exe(pid, &f); - if (r != -EACCES) - ASSERT_OK(r); + ASSERT_OK_OR(get_process_exe(pid, &f), -EACCES); log_info("PID"PID_FMT" exe: '%s'", pid, strna(f)); ASSERT_OK_ZERO(pid_get_uid(pid, &u)); @@ -97,9 +95,7 @@ static void test_pid_get_comm_one(pid_t pid) { ASSERT_OK_ZERO(get_process_gid(pid, &g)); log_info("PID"PID_FMT" GID: "GID_FMT, pid, g); - r = get_process_environ(pid, &env); - if (r != -EACCES) - ASSERT_OK(r); + ASSERT_OK_OR(get_process_environ(pid, &env), -EACCES); log_info("PID"PID_FMT" strlen(environ): %zi", pid, env ? (ssize_t)strlen(env) : (ssize_t)-errno); if (!detect_container() && pid == 1) @@ -166,9 +162,7 @@ TEST(pid_get_cmdline) { for (;;) { pid_t pid; - - r = proc_dir_read(d, &pid); - ASSERT_OK(r); + ASSERT_OK(r = proc_dir_read(d, &pid)); if (r == 0) /* EOF */ break; From 83e0e32944cc6960fe7c0e0674b48103a5ebf4ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 28 Jun 2025 20:14:06 +0200 Subject: [PATCH 07/11] test-cgroup-util: minor simplification --- src/test/test-cgroup-util.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 8debc21527..3f3562c878 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -370,10 +370,8 @@ TEST(cg_tests) { int all, hybrid, systemd, r; r = cg_unified(); - if (IN_SET(r, -ENOENT, -ENOMEDIUM)) { - log_tests_skipped("cgroup not mounted"); - return; - } + if (IN_SET(r, -ENOENT, -ENOMEDIUM)) + return (void) log_tests_skipped("cgroup not mounted"); assert_se(r >= 0); all = cg_all_unified(); From 145100836ec064a42989f157a0d11787c6130c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 28 Jun 2025 21:00:16 +0200 Subject: [PATCH 08/11] test-cgroup-util: ignore -ENXIO in more places In https://github.com/systemd/systemd/pull/38003, one test failed: Unit tests / build (CLANG_ASAN_UBSAN): src/test/test-cgroup-util.c:237: Assertion failed: Expected "r" to succeed, but got error: No such device or address Checks for specific errors were added in ca82f0cbe2db096bc7ff81280b5683ea1beae534, partially relaxed in e92d699dde746355bba893b2375b7937a52d9e05. cg_pidref_get_unit() and cg_pid_get_slice() enter a deep chain of calls, so it's hard to guess where the failure occurred. But those two calls expect the cgroup path to be "well formed". When we're running in CI, we don't have full control over what is happening on the machine, so let's suppress that error too. --- src/test/test-cgroup-util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 3f3562c878..8d6a4c39e7 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -234,9 +234,9 @@ TEST(proc, .sd_booted = true) { r = cg_pid_get_path_shifted(pid.pid, NULL, &path_shifted); ASSERT_OK_OR(r, -ESRCH); r = cg_pidref_get_unit(&pid, &unit); - ASSERT_OK_OR(r, -ESRCH); + ASSERT_OK_OR(r, -ESRCH, -ENXIO); r = cg_pid_get_slice(pid.pid, &slice); - ASSERT_OK_OR(r, -ESRCH); + ASSERT_OK_OR(r, -ESRCH, -ENXIO); /* Not all processes belong to a specific user or a machine */ r = cg_pidref_get_owner_uid(&pid, &uid); From 2d39c99fd834d212fc4891b50c4699ab51342175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 28 Jun 2025 21:08:19 +0200 Subject: [PATCH 09/11] test-cgroup-util: print info about process before asserting If this tests ever fails again, we should have at least a chance to figure out what went wrong. --- src/test/test-cgroup-util.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 8d6a4c39e7..44b7e6bd4f 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -231,22 +231,15 @@ TEST(proc, .sd_booted = true) { if (hidden_cgroup(path)) continue; - r = cg_pid_get_path_shifted(pid.pid, NULL, &path_shifted); - ASSERT_OK_OR(r, -ESRCH); - r = cg_pidref_get_unit(&pid, &unit); - ASSERT_OK_OR(r, -ESRCH, -ENXIO); - r = cg_pid_get_slice(pid.pid, &slice); - ASSERT_OK_OR(r, -ESRCH, -ENXIO); + int r1 = cg_pid_get_path_shifted(pid.pid, NULL, &path_shifted); + int r2 = cg_pidref_get_unit(&pid, &unit); + int r3 = cg_pid_get_slice(pid.pid, &slice); /* Not all processes belong to a specific user or a machine */ - r = cg_pidref_get_owner_uid(&pid, &uid); - ASSERT_OK_OR(r, -ESRCH, -ENXIO); - r = cg_pidref_get_session(&pid, &session); - ASSERT_OK_OR(r, -ESRCH, -ENXIO); - r = cg_pid_get_user_unit(pid.pid, &user_unit); - ASSERT_OK_OR(r, -ESRCH, -ENXIO); - r = cg_pid_get_machine_name(pid.pid, &machine); - ASSERT_OK_OR(r, -ESRCH, -ENOENT); + int r4 = cg_pidref_get_owner_uid(&pid, &uid); + int r5 = cg_pidref_get_session(&pid, &session); + int r6 = cg_pid_get_user_unit(pid.pid, &user_unit); + int r7 = cg_pid_get_machine_name(pid.pid, &machine); log_debug(PID_FMT": %s, %s, "UID_FMT", %s, %s, %s, %s, %s", pid.pid, @@ -258,6 +251,14 @@ TEST(proc, .sd_booted = true) { strna(user_unit), strna(machine), strna(slice)); + + ASSERT_OK_OR(r1, -ESRCH); + ASSERT_OK_OR(r2, -ESRCH, -ENXIO); + ASSERT_OK_OR(r3, -ESRCH, -ENXIO); + ASSERT_OK_OR(r4, -ESRCH, -ENXIO); + ASSERT_OK_OR(r5, -ESRCH, -ENXIO); + ASSERT_OK_OR(r6, -ESRCH, -ENXIO); + ASSERT_OK_OR(r7, -ESRCH, -ENOENT); } } From 6020ca2c23b8ab8fd7a8101bad4859c7ace19768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 28 Jun 2025 21:34:10 +0200 Subject: [PATCH 10/11] basic/errno-list: add helper to print errno names --- src/basic/errno-list.c | 11 ++++++++++- src/basic/errno-list.h | 7 +++++++ src/test/test-errno-list.c | 22 ++++++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/basic/errno-list.c b/src/basic/errno-list.c index 5bfd8aa076..8de9888083 100644 --- a/src/basic/errno-list.c +++ b/src/basic/errno-list.c @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include +#include #include #include "errno-list.h" @@ -33,7 +35,6 @@ const char* errno_to_name(int id) { # include "errno-to-name.inc" const char* errno_to_name(int id) { - if (id < 0) id = -id; @@ -43,3 +44,11 @@ const char* errno_to_name(int id) { return errno_names[id]; } #endif + +const char* errno_name_full(int id, char buf[static ERRNO_NAME_BUF_LEN]) { + const char *a = errno_to_name(id); + if (a) + return a; + snprintf(buf, ERRNO_NAME_BUF_LEN, "%d", abs(id)); + return buf; +} diff --git a/src/basic/errno-list.h b/src/basic/errno-list.h index 5b29642ce4..6ce2d75c09 100644 --- a/src/basic/errno-list.h +++ b/src/basic/errno-list.h @@ -9,3 +9,10 @@ int errno_from_name(const char *name) _pure_; static inline bool errno_is_valid(int n) { return n > 0 && n <= ERRNO_MAX; } + +#define ERRNO_NAME_BUF_LEN DECIMAL_STR_MAX(int) +/* Like errno_name, but always returns a string. */ +const char* errno_name_full(int id, char buf[static ERRNO_NAME_BUF_LEN]); + +/* A helper to print the errno "name" or number if name is not defined. */ +#define ERRNO_NAME_FULL(errnum) errno_name_full(errnum, (char[ERRNO_NAME_BUF_LEN]){}) diff --git a/src/test/test-errno-list.c b/src/test/test-errno-list.c index 3bd9ee232c..c72f657123 100644 --- a/src/test/test-errno-list.c +++ b/src/test/test-errno-list.c @@ -29,4 +29,26 @@ TEST(errno_list) { ASSERT_STREQ(errno_to_name(ECONNREFUSED), "ECONNREFUSED"); } +TEST(errno_name_full) { + char buf[ERRNO_NAME_BUF_LEN]; + + ASSERT_STREQ(errno_name_full(0, buf), "0"); + ASSERT_STREQ(errno_name_full(EPERM, buf), "EPERM"); + ASSERT_STREQ(errno_name_full(ENOENT, buf), "ENOENT"); + ASSERT_STREQ(errno_name_full(200, buf), "200"); + ASSERT_STREQ(errno_name_full(-200, buf), "200"); +} + +TEST(ERRNO_NAME_FULL) { + ASSERT_STREQ(ERRNO_NAME_FULL(0), "0"); + ASSERT_STREQ(ERRNO_NAME_FULL(EPERM), "EPERM"); + ASSERT_STREQ(ERRNO_NAME_FULL(ENOENT), "ENOENT"); + ASSERT_STREQ(ERRNO_NAME_FULL(200), "200"); + ASSERT_STREQ(ERRNO_NAME_FULL(-200), "200"); + + int x = 0; + ASSERT_STREQ(ERRNO_NAME_FULL(++x), "EPERM"); /* Confirm that eval happens just once. */ + ASSERT_EQ(x, 1); +} + DEFINE_TEST_MAIN(LOG_INFO); From 6b60354656169bea426062753c728657e84e6797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 1 Jul 2025 17:43:45 +0200 Subject: [PATCH 11/11] tests: print errno name rather than the message The tests are written and consumed by developers. Errno descriptions are good for users, but for developers the errno "name" is actually more useful, and we need to always map the description back to the name to compare with the code. Let's make things simpler for ourselves by printing the errno names directly. Example output: src/test/test-tests.c:15: Assertion failed: Expected "-1" to succeed, but got error: -1/EPERM src/test/test-tests.c:16: Assertion failed: Expected "-ENOANO" to succeed, but got error: -55/ENOANO src/test/test-tests.c:20: Assertion failed: Expected "0" to be positive, but it is zero. src/test/test-tests.c:62: Assertion failed: Expected "RET_NERRNO(mkdir("/i/will/fail/with/enoent", 666))" to fail with error -55/ENOANO, but got -2/ENOENT src/test/test-tests.c:68: Assertion failed: Expected "0" to fail with errno 2/ENOENT, but it succeeded src/test/test-tests.c:70: Assertion failed: Expected "mkdir("/i/will/fail/with/enoent", 666)" to fail with errno 55/ENOANO, but got 2/ENOENT --- src/shared/tests.h | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/shared/tests.h b/src/shared/tests.h index 5d1dccba9b..46c82f444c 100644 --- a/src/shared/tests.h +++ b/src/shared/tests.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include "errno-list.h" #include "errno-util.h" #include "forward.h" #include "log.h" @@ -178,7 +179,7 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr) _result = (expr); \ if (_result < 0) \ log_test_failed("Expected \"%s\" to succeed, but got error: %"PRIiMAX"/%s", \ - #expr, (intmax_t) _result, STRERROR(_result)); \ + #expr, (intmax_t) _result, ERRNO_NAME_FULL(_result)); \ }) #endif @@ -194,7 +195,7 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr) _result = (expr); \ if (_result < 0 && !IN_SET(_result, 0, __VA_ARGS__)) \ log_test_failed("\"%s\" failed with unexpected error: %"PRIiMAX"/%s", \ - #expr, (intmax_t) _result, STRERROR(_result)); \ + #expr, (intmax_t) _result, ERRNO_NAME_FULL(_result)); \ }) #endif @@ -207,7 +208,7 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr) _result = (expr); \ if (_result < 0) \ log_test_failed("Expected \"%s\" to succeed, but got error: %"PRIiMAX"/%s", \ - #expr, (intmax_t) _result, STRERROR(_result)); \ + #expr, (intmax_t) _result, ERRNO_NAME_FULL(_result)); \ if (_result == 0) \ log_test_failed("Expected \"%s\" to be positive, but it is zero.", #expr); \ }) @@ -221,7 +222,7 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr) _result = (expr); \ if (_result < 0) \ log_test_failed("Expected \"%s\" to succeed, but got error: %"PRIiMAX"/%s", \ - #expr, (intmax_t) _result, STRERROR(_result)); \ + #expr, (intmax_t) _result, ERRNO_NAME_FULL(_result)); \ if (_result != 0) \ log_test_failed("Expected \"%s\" to be zero, but it is %"PRIiMAX".", \ #expr, (intmax_t) _result); \ @@ -237,7 +238,7 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr2) _expr2 = (expr2); \ if (_expr1 < 0) \ log_test_failed("Expected \"%s\" to succeed, but got error: %"PRIiMAX"/%s", \ - #expr1, (intmax_t) _expr1, STRERROR(_expr1)); \ + #expr1, (intmax_t) _expr1, ERRNO_NAME_FULL(_expr1)); \ if (_expr1 != _expr2) \ log_test_failed("Expected \"%s == %s\", got %"PRIiMAX" != %"PRIiMAX, \ #expr1, #expr2, (intmax_t) _expr1, (intmax_t) _expr2); \ @@ -253,7 +254,7 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr) _result = (expr); \ if (_result < 0) \ log_test_failed("Expected \"%s\" to succeed, but got errno: %d/%s", \ - #expr, errno, STRERROR(errno)); \ + #expr, errno, ERRNO_NAME_FULL(errno)); \ }) #endif @@ -265,7 +266,7 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr) _result = (expr); \ if (_result < 0) \ log_test_failed("Expected \"%s\" to succeed, but got errno: %d/%s", \ - #expr, errno, STRERROR(errno)); \ + #expr, errno, ERRNO_NAME_FULL(errno)); \ if (_result != 0) \ log_test_failed("Expected \"%s\" to be zero, but it is %"PRIiMAX".", \ #expr, (intmax_t) _result); \ @@ -281,7 +282,7 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char typeof(expr2) _expr2 = (expr2); \ if (_expr1 < 0) \ log_test_failed("Expected \"%s\" to succeed, but got errno: %d/%s", \ - #expr1, errno, STRERROR(errno)); \ + #expr1, errno, ERRNO_NAME_FULL(errno)); \ if (_expr1 != _expr2) \ log_test_failed("Expected \"%s == %s\", but %"PRIiMAX" != %"PRIiMAX, \ #expr1, #expr2, (intmax_t) _expr1, (intmax_t) _expr2); \ @@ -307,11 +308,11 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char int _expr1 = (expr1); \ int _expr2 = (expr2); \ if (_expr1 >= 0) \ - log_test_failed("Expected \"%s\" to fail with error %d/\"%s\", but it succeeded", \ - #expr1, -_expr2, STRERROR(_expr2)); \ + log_test_failed("Expected \"%s\" to fail with error %d/%s, but it succeeded", \ + #expr1, -_expr2, ERRNO_NAME_FULL(_expr2)); \ else if (-_expr1 != _expr2) \ - log_test_failed("Expected \"%s\" to fail with error %d/\"%s\", but got the following error: %d/%s", \ - #expr1, -_expr2, STRERROR(_expr2), _expr1, STRERROR(_expr1)); \ + log_test_failed("Expected \"%s\" to fail with error %d/%s, but got %d/%s", \ + #expr1, -_expr2, ERRNO_NAME_FULL(_expr2), _expr1, ERRNO_NAME_FULL(_expr1)); \ }) #endif @@ -323,11 +324,11 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char int _expr1 = (expr1); \ int _expr2 = (expr2); \ if (_expr1 >= 0) \ - log_test_failed("Expected \"%s\" to fail with errno %d/\"%s\", but it succeeded", \ - #expr1, _expr2, STRERROR(_expr2)); \ + log_test_failed("Expected \"%s\" to fail with errno %d/%s, but it succeeded", \ + #expr1, _expr2, ERRNO_NAME_FULL(_expr2)); \ else if (errno != _expr2) \ - log_test_failed("Expected \"%s\" to fail with errno %d/\"%s\", but got the following errno: %d/%s", \ - #expr1, _expr2, STRERROR(_expr2), errno, STRERROR(errno)); \ + log_test_failed("Expected \"%s\" to fail with errno %d/%s, but got %d/%s", \ + #expr1, _expr2, ERRNO_NAME_FULL(_expr2), errno, ERRNO_NAME_FULL(errno)); \ }) #endif