Tests: tuktest.h: Add tuktest_error_impl to help with error conditions.

This commit is contained in:
Lasse Collin 2022-06-16 14:12:14 +03:00
parent b339892668
commit 5ba9459e6c
1 changed files with 32 additions and 40 deletions

View File

@ -88,14 +88,16 @@
/// (The assert_CONDITION() macros depend on setup code in tuktest_run() /// (The assert_CONDITION() macros depend on setup code in tuktest_run()
/// and other use results in undefined behavior.) /// and other use results in undefined behavior.)
/// ///
/// - tuktest_start(), tuktest_early_skip, tuktest_error(), tuktest_run(), /// - tuktest_start(), tuktest_early_skip, tuktest_run(), and tuktest_end()
/// and tuktest_end() must not be used in the tests called via /// must not be used in the tests called via tuktest_run()! (tuktest_end()
/// tuktest_run()! (tuktest_end() is called more freely internally /// is called more freely internally by this file but such use isn't part
/// by this file but such use isn't part of the API.) /// of the API.)
/// ///
/// - tuktest_malloc(), tuktest_free(), tuktest_file_from_srcdir(), and /// - tuktest_error(), tuktest_malloc(), tuktest_free(),
/// tuktest_file_from_builddir() can be used everywhere after /// tuktest_file_from_srcdir(), and tuktest_file_from_builddir()
/// tuktest_start() has been called. /// can be used everywhere after tuktest_start() has been called.
/// (In tests running under tuktest_run(), assert_error() can be used
/// instead of tuktest_error() when a hard error occurs.)
/// ///
/// - Everything else is for internal use only. /// - Everything else is for internal use only.
/// ///
@ -250,6 +252,18 @@ static jmp_buf tuktest_jmpenv;
static int tuktest_end(void); static int tuktest_end(void);
// Internal helper for handling hard errors both inside and
// outside tuktest_run().
#define tuktest_error_impl(filename, line, ...) \
do { \
tuktest_print_result_prefix(TUKTEST_ERROR, filename, line); \
printf(__VA_ARGS__); \
printf("\n"); \
++tuktest_stats[TUKTEST_ERROR]; \
exit(tuktest_end()); \
} while (0)
// printf() is without checking its return value in many places. This function // printf() is without checking its return value in many places. This function
// is called before exiting to check the status of stdout and catch errors. // is called before exiting to check the status of stdout and catch errors.
static void static void
@ -334,15 +348,11 @@ tuktest_malloc_impl(size_t size, const char *filename, unsigned line)
free(r); free(r);
free(p); free(p);
tuktest_print_result_prefix(TUKTEST_ERROR, filename, line);
// Avoid %zu for portability to very old systems that still // Avoid %zu for portability to very old systems that still
// can compile C99 code. // can compile C99 code.
printf("tuktest_malloc(%" TUKTEST_PRIu ") failed\n", tuktest_error_impl(filename, line,
"tuktest_malloc(%" TUKTEST_PRIu ") failed",
(tuktest_uint)size); (tuktest_uint)size);
++tuktest_stats[TUKTEST_ERROR];
exit(tuktest_end());
} }
r->p = p; r->p = p;
@ -393,11 +403,8 @@ tuktest_free_impl(void *p, const char *filename, unsigned line)
r = &tmp->next; r = &tmp->next;
} }
tuktest_print_result_prefix(TUKTEST_ERROR, filename, line); tuktest_error_impl(filename, line, "tuktest_free: "
printf("tuktest_free: Allocation matching the pointer " "Allocation matching the pointer was not found");
"was not found\n");
++tuktest_stats[TUKTEST_ERROR];
exit(tuktest_end());
} }
@ -464,18 +471,9 @@ do { \
/// ///
/// NOTE: tuktest_start() must have been called before tuktest_error(). /// NOTE: tuktest_start() must have been called before tuktest_error().
/// ///
/// NOTE: This macro MUST NOT be called from test functions running under /// NOTE: This macro can be called from test functions running under
/// tuktest_run()! Use assert_error() to report a hard error in code that /// tuktest_run() but assert_error() is somewhat preferred in that context.
/// is running under tuktest_run(). #define tuktest_error(...) tuktest_error_impl(__FILE__, __LINE__, __VA_ARGS__)
#define tuktest_error(...) \
do { \
++tuktest_stats[TUKTEST_ERROR]; \
printf(TUKTEST_STR_ERROR " [%s:%u] ", \
tuktest_basename(__FILE__), __LINE__); \
printf(__VA_ARGS__); \
printf("\n"); \
exit(tuktest_end()); \
} while (0)
/// At the end of main() one should have "return tuktest_end();" which /// At the end of main() one should have "return tuktest_end();" which
@ -659,12 +657,13 @@ tuktest_file_from_x(const char *prefix, const char *filename, size_t *size,
if (filename == NULL) { if (filename == NULL) {
error_msg = "Filename is NULL"; error_msg = "Filename is NULL";
filename = "(NULL)";
goto error; goto error;
} }
if (filename[0] == '\0') { if (filename[0] == '\0') {
error_msg = "Filename is an empty string"; error_msg = "Filename is an empty string";
filename = NULL; filename = "(empty string)";
goto error; goto error;
} }
@ -756,15 +755,8 @@ error:
if (f != NULL) if (f != NULL)
(void)fclose(f); (void)fclose(f);
tuktest_print_result_prefix(TUKTEST_ERROR, prog_filename, prog_line); tuktest_error_impl(prog_filename, prog_line,
"tuktest_file_from_x: %s: %s\n", filename, error_msg);
if (filename == NULL)
printf("tuktest_file_from_x: %s\n", error_msg);
else
printf("tuktest_file_from_x: %s: %s\n", filename, error_msg);
++tuktest_stats[TUKTEST_ERROR];
exit(tuktest_end());
} }