Parolin 0.7.9 6796
Console (soon DLLs) to do a tar like job
Loading...
Searching...
No Matches
tuktest.h
Go to the documentation of this file.
1// SPDX-License-Identifier: 0BSD
2
4//
124//
125// Author: Lasse Collin
126//
128
129#ifndef TUKTEST_H
130#define TUKTEST_H
131
132#include <stddef.h>
133
134// On some (too) old systems inttypes.h doesn't exist or isn't good enough.
135// Include it conditionally so that any portability tricks can be done before
136// tuktest.h is included. On any modern system inttypes.h is fine as is.
137#ifndef PRIu64
138# include <inttypes.h>
139#endif
140
141#include <setjmp.h>
142#include <stdlib.h>
143#include <string.h>
144#include <stdio.h>
145
146
147#if defined(__GNUC__) && defined(__GNUC_MINOR__)
148# define TUKTEST_GNUC_REQ(major, minor) \
149 ((__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)) \
150 || __GNUC__ > (major))
151#else
152# define TUKTEST_GNUC_REQ(major, minor) 0
153#endif
154
155
156// This is silencing warnings about unused functions. Not all test programs
157// need all functions from this header.
158#if TUKTEST_GNUC_REQ(3, 0) || defined(__clang__)
159# define tuktest_maybe_unused __attribute__((__unused__))
160#else
161# define tuktest_maybe_unused
162#endif
163
164// We need printf("") so silence the warning about empty format string.
165#if TUKTEST_GNUC_REQ(4, 2) || defined(__clang__)
166# pragma GCC diagnostic ignored "-Wformat-zero-length"
167#endif
168
169
170// Types and printf format macros to use in integer assertions and also for
171// printing size_t values (C99's %zu isn't available on very old systems).
172typedef int64_t tuktest_int;
173typedef uint64_t tuktest_uint;
174#define TUKTEST_PRId PRId64
175#define TUKTEST_PRIu PRIu64
176#define TUKTEST_PRIX PRIX64
177
178
179// When TAP mode isn't used, Automake-compatible exit statuses are used.
180#define TUKTEST_EXIT_PASS EXIT_SUCCESS
181#define TUKTEST_EXIT_FAIL EXIT_FAILURE
182#define TUKTEST_EXIT_SKIP 77
183#define TUKTEST_EXIT_ERROR 99
184
185
192
193
194#ifdef TUKTEST_TAP
195# undef TUKTEST_QUIET
196# undef TUKTEST_COLOR
197# undef TUKTEST_TAP
198# define TUKTEST_TAP 1
199# define TUKTEST_STR_PASS "ok -"
200# define TUKTEST_STR_FAIL "not ok -"
201# define TUKTEST_STR_SKIP "ok - # SKIP"
202# define TUKTEST_STR_ERROR "Bail out!"
203#else
204# define TUKTEST_TAP 0
205# ifdef TUKTEST_COLOR
206# define TUKTEST_COLOR_PASS "\x1B[0;32m"
207# define TUKTEST_COLOR_FAIL "\x1B[0;31m"
208# define TUKTEST_COLOR_SKIP "\x1B[1;34m"
209# define TUKTEST_COLOR_ERROR "\x1B[0;35m"
210# define TUKTEST_COLOR_TOTAL "\x1B[1m"
211# define TUKTEST_COLOR_OFF "\x1B[m"
212# define TUKTEST_COLOR_IF(cond, color) ((cond) ? (color) : "" )
213# else
214# define TUKTEST_COLOR_PASS ""
215# define TUKTEST_COLOR_FAIL ""
216# define TUKTEST_COLOR_SKIP ""
217# define TUKTEST_COLOR_ERROR ""
218# define TUKTEST_COLOR_TOTAL ""
219# define TUKTEST_COLOR_OFF ""
220# define TUKTEST_COLOR_IF(cond, color) ""
221# endif
222# define TUKTEST_COLOR_ADD(str, color) color str TUKTEST_COLOR_OFF
223# define TUKTEST_STR_PASS \
224 TUKTEST_COLOR_ADD("PASS:", TUKTEST_COLOR_PASS)
225# define TUKTEST_STR_FAIL \
226 TUKTEST_COLOR_ADD("FAIL:", TUKTEST_COLOR_FAIL)
227# define TUKTEST_STR_SKIP \
228 TUKTEST_COLOR_ADD("SKIP:", TUKTEST_COLOR_SKIP)
229# define TUKTEST_STR_ERROR \
230 TUKTEST_COLOR_ADD("ERROR:", TUKTEST_COLOR_ERROR)
231#endif
232
233// NOTE: If TUKTEST_TAP is defined then TUKTEST_QUIET will get undefined above.
234#ifndef TUKTEST_QUIET
235# define TUKTEST_QUIET 0
236#else
237# undef TUKTEST_QUIET
238# define TUKTEST_QUIET 1
239#endif
240
241
242// Counts of the passed, failed, skipped, and hard-errored tests.
243// This is indexed with the enumeration constants from enum tuktest_result.
244static unsigned tuktest_stats[4] = { 0, 0, 0, 0 };
245
246// Copy of argc and argv from main(). These are set by tuktest_start().
247static int tuktest_argc = 0;
248static char **tuktest_argv = NULL;
249
250// Name of the currently-running test. This exists because it's nice
251// to print the main test function name even if the failing test-assertion
252// fails in a function called by the main test function.
253static const char *tuktest_name = NULL;
254
255// longjmp() target for when a test-assertion fails.
256static jmp_buf tuktest_jmpenv;
257
258
259// This declaration is needed for tuktest_malloc().
260static int tuktest_end(void);
261
262
263// Internal helper for handling hard errors both inside and
264// outside tuktest_run().
265#define tuktest_error_impl(filename, line, ...) \
266do { \
267 tuktest_print_result_prefix(TUKTEST_ERROR, filename, line); \
268 printf(__VA_ARGS__); \
269 printf("\n"); \
270 ++tuktest_stats[TUKTEST_ERROR]; \
271 exit(tuktest_end()); \
272} while (0)
273
274
275// printf() is without checking its return value in many places. This function
276// is called before exiting to check the status of stdout and catch errors.
277static void
278tuktest_catch_stdout_errors(void)
279{
280 if (ferror(stdout) || fclose(stdout)) {
281 fputs("Error while writing to stdout\n", stderr);
282 exit(TUKTEST_EXIT_ERROR);
283 }
284}
285
286
287// A simplified basename()-like function that is good enough for
288// cleaning up __FILE__. This supports / and \ as path separator.
289// If the path separator is wrong then the full path will be printed;
290// it's a cosmetic problem only.
291static const char *
292tuktest_basename(const char *filename)
293{
294 for (const char *p = filename + strlen(filename); p > filename; --p)
295 if (*p == '/' || *p == '\\')
296 return p + 1;
297
298 return filename;
299}
300
301
302// Internal helper that prints the prefix of the fail/skip/error message line.
303static void
304tuktest_print_result_prefix(enum tuktest_result result,
305 const char *filename, unsigned line)
306{
307 // This is never called with TUKTEST_PASS but I kept it here anyway.
308 const char *result_str
309 = result == TUKTEST_PASS ? TUKTEST_STR_PASS
310 : result == TUKTEST_FAIL ? TUKTEST_STR_FAIL
311 : result == TUKTEST_SKIP ? TUKTEST_STR_SKIP
313
314 const char *short_filename = tuktest_basename(filename);
315
316 if (tuktest_name != NULL)
317 printf("%s %s [%s:%u] ", result_str, tuktest_name,
318 short_filename, line);
319 else
320 printf("%s [%s:%u] ", result_str, short_filename, line);
321}
322
323
324// An entry for linked list of memory allocations.
327 void *p;
328};
329
330// Linked list of per-test allocations. This is used when under tuktest_run().
331// These allocations are freed in tuktest_run() and, in case of a hard error,
332// also in tuktest_end().
333static struct tuktest_malloc_record *tuktest_malloc_test = NULL;
334
335// Linked list of global allocations. This is used allocations are made
336// outside tuktest_run(). These are freed in tuktest_end().
337static struct tuktest_malloc_record *tuktest_malloc_global = NULL;
338
339
347#define tuktest_malloc(size) tuktest_malloc_impl(size, __FILE__, __LINE__)
348
349static void *
350tuktest_malloc_impl(size_t size, const char *filename, unsigned line)
351{
352 void *p = malloc(size == 0 ? 1 : size);
353 struct tuktest_malloc_record *r = malloc(sizeof(*r));
354
355 if (p == NULL || r == NULL) {
356 free(r);
357 free(p);
358
359 // Avoid %zu for portability to very old systems that still
360 // can compile C99 code.
361 tuktest_error_impl(filename, line,
362 "tuktest_malloc(%" TUKTEST_PRIu ") failed",
364 }
365
366 r->p = p;
367
368 if (tuktest_name == NULL) {
369 // We were called outside tuktest_run().
370 r->next = tuktest_malloc_global;
371 tuktest_malloc_global = r;
372 } else {
373 // We were called under tuktest_run().
374 r->next = tuktest_malloc_test;
375 tuktest_malloc_test = r;
376 }
377
378 return p;
379}
380
381
390#define tuktest_free(ptr) tuktest_free_impl(ptr, __FILE__, __LINE__)
391
392static void
393tuktest_free_impl(void *p, const char *filename, unsigned line)
394{
395 if (p == NULL)
396 return;
397
398 struct tuktest_malloc_record **r = tuktest_name != NULL
399 ? &tuktest_malloc_test : &tuktest_malloc_global;
400
401 while (*r != NULL) {
402 struct tuktest_malloc_record *tmp = *r;
403
404 if (tmp->p == p) {
405 *r = tmp->next;
406 free(p);
407 free(tmp);
408 return;
409 }
410
411 r = &tmp->next;
412 }
413
414 tuktest_error_impl(filename, line, "tuktest_free: "
415 "Allocation matching the pointer was not found");
416}
417
418
419// Frees all allocates in the given record list. The argument must be
420// either &tuktest_malloc_test or &tuktest_malloc_global.
421static void
422tuktest_free_all(struct tuktest_malloc_record **r)
423{
424 while (*r != NULL) {
425 struct tuktest_malloc_record *tmp = *r;
426 *r = tmp->next;
427 free(tmp->p);
428 free(tmp);
429 }
430}
431
432
439#define tuktest_start(argc, argv) \
440do { \
441 tuktest_argc = argc; \
442 tuktest_argv = argv; \
443 if (!TUKTEST_TAP && !TUKTEST_QUIET) \
444 printf("=== %s ===\n", tuktest_basename(__FILE__)); \
445} while (0)
446
447
455#define tuktest_early_skip(...) \
456do { \
457 printf("%s [%s:%u] ", \
458 TUKTEST_TAP ? "1..0 # SKIP" : TUKTEST_STR_SKIP, \
459 tuktest_basename(__FILE__), __LINE__); \
460 printf(__VA_ARGS__); \
461 printf("\n"); \
462 if (!TUKTEST_TAP && !TUKTEST_QUIET) \
463 printf("=== END ===\n"); \
464 tuktest_catch_stdout_errors(); \
465 exit(TUKTEST_TAP ? EXIT_SUCCESS : TUKTEST_EXIT_SKIP); \
466} while (0)
467
468
484#define tuktest_error(...) tuktest_error_impl(__FILE__, __LINE__, __VA_ARGS__)
485
486
494static int
495tuktest_end(void)
496{
497 tuktest_free_all(&tuktest_malloc_test);
498 tuktest_free_all(&tuktest_malloc_global);
499
500 unsigned total_tests = 0;
501 for (unsigned i = 0; i <= TUKTEST_ERROR; ++i)
502 total_tests += tuktest_stats[i];
503
504 if (tuktest_stats[TUKTEST_ERROR] == 0 && tuktest_argc > 1
505 && (unsigned)(tuktest_argc - 1) > total_tests) {
506 printf(TUKTEST_STR_ERROR " Fewer tests were run than "
507 "specified on the command line. "
508 "Was a test name mistyped?\n");
509 ++tuktest_stats[TUKTEST_ERROR];
510 }
511
512#if TUKTEST_TAP
513 // Print the plan only if no "Bail out!" has occurred.
514 // Print the skip directive if no tests were run.
515 // We cannot know the reason for the skip here though
516 // (see tuktest_early_skip()).
517 if (tuktest_stats[TUKTEST_ERROR] == 0)
518 printf("1..%u%s\n", total_tests,
519 total_tests == 0 ? " # SKIP" : "");
520
521 tuktest_catch_stdout_errors();
522 return EXIT_SUCCESS;
523#else
524 if (!TUKTEST_QUIET)
525 printf("---\n"
526 "%s# TOTAL: %u" TUKTEST_COLOR_OFF "\n"
527 "%s# PASS: %u" TUKTEST_COLOR_OFF "\n"
528 "%s# SKIP: %u" TUKTEST_COLOR_OFF "\n"
529 "%s# FAIL: %u" TUKTEST_COLOR_OFF "\n"
530 "%s# ERROR: %u" TUKTEST_COLOR_OFF "\n"
531 "=== END ===\n",
533 total_tests,
535 tuktest_stats[TUKTEST_PASS] > 0,
537 tuktest_stats[TUKTEST_PASS],
539 tuktest_stats[TUKTEST_SKIP] > 0,
541 tuktest_stats[TUKTEST_SKIP],
543 tuktest_stats[TUKTEST_FAIL] > 0,
545 tuktest_stats[TUKTEST_FAIL],
547 tuktest_stats[TUKTEST_ERROR] > 0,
549 tuktest_stats[TUKTEST_ERROR]);
550
551 tuktest_catch_stdout_errors();
552
553 if (tuktest_stats[TUKTEST_ERROR] > 0)
554 return TUKTEST_EXIT_ERROR;
555
556 if (tuktest_stats[TUKTEST_FAIL] > 0)
557 return TUKTEST_EXIT_FAIL;
558
559 if (tuktest_stats[TUKTEST_SKIP] > 0 || total_tests == 0)
560 return TUKTEST_EXIT_SKIP;
561
562 return TUKTEST_EXIT_PASS;
563#endif
564}
565
566
569#define tuktest_run(testfunc) \
570 tuktest_run_test(&(testfunc), #testfunc)
571
573static void
574tuktest_run_test(void (*testfunc)(void), const char *testfunc_str)
575{
576 // If any command line arguments were given, only the test functions
577 // named on the command line will be run.
578 if (tuktest_argc > 1) {
579 int i = 1;
580 while (strcmp(tuktest_argv[i], testfunc_str) != 0)
581 if (++i == tuktest_argc)
582 return;
583 }
584
585 // This is set so that failed assertions can print the correct
586 // test name even when the assertion is in a helper function
587 // called by the test function.
588 tuktest_name = testfunc_str;
589
590 // The way setjmp() may be called is very restrictive.
591 // A switch statement is one of the few conforming ways
592 // to get the value passed to longjmp(); doing something
593 // like "int x = setjmp(env)" is NOT allowed (undefined behavior).
594 switch (setjmp(tuktest_jmpenv)) {
595 case 0:
596 testfunc();
597 ++tuktest_stats[TUKTEST_PASS];
598 if (!TUKTEST_QUIET)
599 printf(TUKTEST_STR_PASS " %s\n", tuktest_name);
600 break;
601
602 case TUKTEST_FAIL:
603 ++tuktest_stats[TUKTEST_FAIL];
604 break;
605
606 case TUKTEST_SKIP:
607 ++tuktest_stats[TUKTEST_SKIP];
608 break;
609
610 default:
611 ++tuktest_stats[TUKTEST_ERROR];
612 exit(tuktest_end());
613 }
614
615 tuktest_free_all(&tuktest_malloc_test);
616 tuktest_name = NULL;
617}
618
619
620// Maximum allowed file size in tuktest_file_from_* macros and functions.
621#ifndef TUKTEST_FILE_SIZE_MAX
622# define TUKTEST_FILE_SIZE_MAX (64L << 20)
623#endif
624
642#define tuktest_file_from_srcdir(filename, sizeptr) \
643 tuktest_file_from_x(getenv("srcdir"), filename, sizeptr, \
644 __FILE__, __LINE__)
645
647#define tuktest_file_from_builddir(filename, sizeptr) \
648 tuktest_file_from_x(NULL, filename, sizeptr, __FILE__, __LINE__)
649
650// Internal helper for the macros above.
652static void *
653tuktest_file_from_x(const char *prefix, const char *filename, size_t *size,
654 const char *prog_filename, unsigned prog_line)
655{
656 // If needed: buffer for holding prefix + '/' + filename + '\0'.
657 char *alloc_name = NULL;
658
659 // Buffer for the data read from the file.
660 void *buf = NULL;
661
662 // File being read
663 FILE *f = NULL;
664
665 // Error message to use under the "error:" label.
666 const char *error_msg = NULL;
667
668 if (filename == NULL) {
669 error_msg = "Filename is NULL";
670 filename = "(NULL)";
671 goto error;
672 }
673
674 if (filename[0] == '\0') {
675 error_msg = "Filename is an empty string";
676 filename = "(empty string)";
677 goto error;
678 }
679
680 if (size == NULL) {
681 error_msg = "The size argument is NULL";
682 goto error;
683 }
684
685 // If a prefix was given, construct the full filename.
686 if (prefix != NULL && prefix[0] != '\0') {
687 const size_t prefix_len = strlen(prefix);
688 const size_t filename_len = strlen(filename);
689
690 const size_t alloc_name_size
691 = prefix_len + 1 + filename_len + 1;
692 alloc_name = tuktest_malloc_impl(alloc_name_size,
693 prog_filename, prog_line);
694
695 memcpy(alloc_name, prefix, prefix_len);
696 alloc_name[prefix_len] = '/';
697 memcpy(alloc_name + prefix_len + 1, filename, filename_len);
698 alloc_name[prefix_len + 1 + filename_len] = '\0';
699
700 // Set filename to point to the new string. alloc_name
701 // can be freed unconditionally as it is NULL if a prefix
702 // wasn't specified.
703 filename = alloc_name;
704 }
705
706 f = fopen(filename, "rb");
707 if (f == NULL) {
708 error_msg = "Failed to open the file";
709 goto error;
710 }
711
712 // Get the size of the file and store it in *size.
713 //
714 // We assume that the file isn't big and even reject very big files.
715 // There is no need to use fseeko/ftello from POSIX to support
716 // large files. Using standard C functions is portable outside POSIX.
717 if (fseek(f, 0, SEEK_END) != 0) {
718 error_msg = "Seeking failed (fseek end)";
719 goto error;
720 }
721
722 const long end = ftell(f);
723 if (end < 0) {
724 error_msg = "Seeking failed (ftell)";
725 goto error;
726 }
727
728 if (end == 0) {
729 error_msg = "File is empty";
730 goto error;
731 }
732
733 if (end > TUKTEST_FILE_SIZE_MAX) {
734 error_msg = "File size exceeds TUKTEST_FILE_SIZE_MAX";
735 goto error;
736 }
737
738 *size = (size_t)end;
739 rewind(f);
740
741 buf = tuktest_malloc_impl(*size, prog_filename, prog_line);
742
743 const size_t amount = fread(buf, 1, *size, f);
744 if (ferror(f)) {
745 error_msg = "Read error";
746 goto error;
747 }
748
749 if (amount != *size) {
750 error_msg = "File is smaller than indicated by ftell()";
751 goto error;
752 }
753
754 const int fclose_ret = fclose(f);
755 f = NULL;
756 if (fclose_ret != 0) {
757 error_msg = "Error closing the file";
758 goto error;
759 }
760
761 tuktest_free(alloc_name);
762 return buf;
763
764error:
765 if (f != NULL)
766 (void)fclose(f);
767
768 tuktest_error_impl(prog_filename, prog_line,
769 "tuktest_file_from_x: %s: %s\n", filename, error_msg);
770}
771
772
773// Internal helper for assert_fail, assert_skip, and assert_error.
774#define tuktest_print_and_jump(result, ...) \
775do { \
776 tuktest_print_result_prefix(result, __FILE__, __LINE__); \
777 printf(__VA_ARGS__); \
778 printf("\n"); \
779 longjmp(tuktest_jmpenv, result); \
780} while (0)
781
782
788#define assert_fail(...) tuktest_print_and_jump(TUKTEST_FAIL, __VA_ARGS__)
789
790
803#define assert_skip(...) tuktest_print_and_jump(TUKTEST_SKIP, __VA_ARGS__)
804
805
811#define assert_error(...) tuktest_print_and_jump(TUKTEST_ERROR, __VA_ARGS__)
812
813
815#define assert_false(test_expr) \
816do { \
817 if (test_expr) \
818 assert_fail("assert_fail: '%s' is true but should be false", \
819 #test_expr); \
820} while (0)
821
822
824#define assert_true(test_expr) \
825do { \
826 if (!(test_expr)) \
827 assert_fail("assert_true: '%s' is false but should be true", \
828 #test_expr); \
829} while (0)
830
831
840#define assert_int(test_expr, cmp_op, ref_value) \
841do { \
842 const tuktest_int v_test_ = (test_expr); \
843 const tuktest_int v_ref_ = (ref_value); \
844 if (!(v_test_ cmp_op v_ref_)) \
845 assert_fail("assert_int: '%s == %" TUKTEST_PRId \
846 "' but expected '... %s %" TUKTEST_PRId "'", \
847 #test_expr, v_test_, #cmp_op, v_ref_); \
848} while (0)
849
850
855#define assert_uint(test_expr, cmp_op, ref_value) \
856do { \
857 const tuktest_uint v_test_ = (test_expr); \
858 const tuktest_uint v_ref_ = (ref_value); \
859 if (!(v_test_ cmp_op v_ref_)) \
860 assert_fail("assert_uint: '%s == %" TUKTEST_PRIu \
861 "' but expected '... %s %" TUKTEST_PRIu "'", \
862 #test_expr, v_test_, #cmp_op, v_ref_); \
863} while (0)
864
865
868#define assert_int_eq(test_expr, ref_value) \
869 assert_int(test_expr, ==, ref_value)
870
871
874#define assert_uint_eq(test_expr, ref_value) \
875 assert_uint(test_expr, ==, ref_value)
876
877
894#define assert_enum_eq(test_expr, ref_value, enum_strings) \
895do { \
896 const tuktest_int v_test_ = (test_expr); \
897 const tuktest_int v_ref_ = (ref_value); \
898 if (v_test_ != v_ref_) { \
899 const int array_len_ = (int)(sizeof(enum_strings) \
900 / sizeof((enum_strings)[0])); \
901 if (v_ref_ < 0 || v_ref_ >= array_len_) \
902 assert_fail("assert_enum_eq: '%s == %" TUKTEST_PRId \
903 "' but expected " \
904 "'... == %" TUKTEST_PRId "'", \
905 #test_expr, v_test_, v_ref_); \
906 else if (v_test_ < 0 || v_test_ >= array_len_) \
907 assert_fail("assert_enum_eq: '%s == %" TUKTEST_PRId \
908 "' but expected '... == %s'", \
909 #test_expr, v_test_, \
910 (enum_strings)[v_ref_]); \
911 else \
912 assert_fail("assert_enum_eq: '%s == %s' " \
913 "but expected '... = %s'", \
914 #test_expr, (enum_strings)[v_test_], \
915 (enum_strings)[v_ref_]); \
916 } \
917} while (0)
918
919
921#define assert_bit_set(test_expr, bit) \
922do { \
923 const tuktest_uint v_test_ = (test_expr); \
924 const unsigned v_bit_ = (bit); \
925 const tuktest_uint v_mask_ = (tuktest_uint)1 << v_bit_; \
926 if (!(v_test_ & v_mask_)) \
927 assert_fail("assert_bit_set: '%s == 0x%" TUKTEST_PRIX \
928 "' but bit %u (0x%" TUKTEST_PRIX ") " \
929 "is not set", \
930 #test_expr, v_test_, v_bit_, v_mask_); \
931} while (0)
932
933
935#define assert_bit_not_set(test_expr, bit) \
936do { \
937 const tuktest_uint v_test_ = (test_expr); \
938 const unsigned v_bit_ = (bit); \
939 const tuktest_uint v_mask_ = (tuktest_uint)1 << v_bit_; \
940 if (v_test_ & v_mask_) \
941 assert_fail("assert_bit_not_set: '%s == 0x%" TUKTEST_PRIX \
942 "' but bit %u (0x%" TUKTEST_PRIX ") is set", \
943 #test_expr, v_test_, v_bit_, v_mask_); \
944} while (0)
945
946
949#define assert_bitmask_set(test_expr, mask) \
950do { \
951 const tuktest_uint v_mask_ = (mask); \
952 const tuktest_uint v_test_ = (test_expr) & v_mask_; \
953 if (v_test_ != v_mask_) \
954 assert_fail("assert_bitmask_set: " \
955 "'((%s) & 0x%" TUKTEST_PRIX ") == " \
956 "0x%" TUKTEST_PRIX "' but expected " \
957 "'... == 0x%" TUKTEST_PRIX "'", \
958 #test_expr, v_mask_, v_test_, v_mask_); \
959} while (0)
960
961
964#define assert_bitmask_not_set(test_expr, mask) \
965do { \
966 const tuktest_uint v_mask_ = (mask); \
967 const tuktest_uint v_test_ = (test_expr) & v_mask_; \
968 if (v_test_ != 0) \
969 assert_fail("assert_bitmask_not_set: "\
970 "'((%s) & 0x%" TUKTEST_PRIX ") == " \
971 "0x%" TUKTEST_PRIX "' but expected " \
972 "'... == 0'", \
973 #test_expr, v_mask_, v_test_); \
974} while (0)
975
976
977// Internal helper to add common code for string assertions.
978#define tuktest_str_helper1(macro_name, test_expr, ref_value) \
979 const char *v_test_ = (test_expr); \
980 const char *v_ref_ = (ref_value); \
981 if (v_test_ == NULL) \
982 assert_fail(macro_name ": Test expression '%s' is NULL", \
983 #test_expr); \
984 if (v_ref_ == NULL) \
985 assert_fail(macro_name ": Reference value '%s' is NULL", \
986 #ref_value)
987
988
989// Internal helper to add common code for string assertions and to check
990// that the reference value isn't an empty string.
991#define tuktest_str_helper2(macro_name, test_expr, ref_value) \
992 tuktest_str_helper1(macro_name, test_expr, ref_value); \
993 if (v_ref_[0] == '\0') \
994 assert_fail(macro_name ": Reference value is an empty string")
995
996
999#define assert_str_eq(test_expr, ref_value) \
1000do { \
1001 tuktest_str_helper1("assert_str_eq", test_expr, ref_value); \
1002 if (strcmp(v_ref_, v_test_) != 0) \
1003 assert_fail("assert_str_eq: '%s' evaluated to '%s' " \
1004 "but expected '%s'", \
1005 #test_expr, v_test_, v_ref_); \
1006} while (0)
1007
1008
1012#define assert_str_contains(test_expr, ref_value) \
1013do { \
1014 tuktest_str_helper2("assert_str_contains", test_expr, ref_value); \
1015 if (strstr(v_test_, v_ref_) == NULL) \
1016 assert_fail("assert_str_contains: '%s' evaluated to '%s' " \
1017 "which doesn't contain '%s'", \
1018 #test_expr, v_test_, v_ref_); \
1019} while (0)
1020
1021
1025#define assert_str_doesnt_contain(test_expr, ref_value) \
1026do { \
1027 tuktest_str_helper2("assert_str_doesnt_contain", \
1028 test_expr, ref_value); \
1029 if (strstr(v_test_, v_ref_) != NULL) \
1030 assert_fail("assert_str_doesnt_contain: " \
1031 "'%s' evaluated to '%s' which contains '%s'", \
1032 #test_expr, v_test_, v_ref_); \
1033} while (0)
1034
1035
1041#define assert_array_eq(test_array, correct_array, array_size) \
1042do { \
1043 for (size_t i_ = 0; i_ < (array_size); ++i_) \
1044 if ((test_array)[i_] != (correct_array)[i_]) \
1045 assert_fail("assert_array_eq: " \
1046 "%s[%" TUKTEST_PRIu "] != "\
1047 "%s[%" TUKTEST_PRIu "] " \
1048 "but should be equal", \
1049 #test_array, (tuktest_uint)i_, \
1050 #correct_array, (tuktest_uint)i_); \
1051} while (0)
1052
1053#endif
#define fseek
#define ftell
char buf[N_BUF]
Definition spewG.c:36
Definition tuktest.h:325
void * p
Definition tuktest.h:327
struct tuktest_malloc_record * next
Definition tuktest.h:326
size_t size
Definition platform.h:559
#define SEEK_END
Definition zconf.h:500
#define f(i)
Definition sha256.c:46
lzma_index ** i
Definition index.h:629
#define NULL
Definition getopt1.c:37
#define TUKTEST_COLOR_SKIP
Definition tuktest.h:216
#define tuktest_maybe_unused
Definition tuktest.h:161
#define TUKTEST_COLOR_IF(cond, color)
Definition tuktest.h:220
#define TUKTEST_EXIT_PASS
Definition tuktest.h:180
#define tuktest_error_impl(filename, line,...)
Definition tuktest.h:265
uint64_t tuktest_uint
Definition tuktest.h:173
#define TUKTEST_STR_PASS
Definition tuktest.h:223
#define TUKTEST_PRIu
Definition tuktest.h:175
#define tuktest_free(ptr)
Definition tuktest.h:390
tuktest_result
Definition tuktest.h:186
@ TUKTEST_ERROR
Definition tuktest.h:190
@ TUKTEST_FAIL
Definition tuktest.h:188
@ TUKTEST_SKIP
Definition tuktest.h:189
@ TUKTEST_PASS
Definition tuktest.h:187
#define TUKTEST_STR_FAIL
Definition tuktest.h:225
#define TUKTEST_QUIET
Definition tuktest.h:235
#define TUKTEST_COLOR_TOTAL
Definition tuktest.h:218
#define TUKTEST_COLOR_ERROR
Definition tuktest.h:217
#define TUKTEST_EXIT_ERROR
Definition tuktest.h:183
#define TUKTEST_COLOR_FAIL
Definition tuktest.h:215
#define TUKTEST_FILE_SIZE_MAX
Definition tuktest.h:622
#define TUKTEST_COLOR_OFF
Definition tuktest.h:219
#define TUKTEST_EXIT_FAIL
Definition tuktest.h:181
#define TUKTEST_EXIT_SKIP
Definition tuktest.h:182
#define TUKTEST_STR_SKIP
Definition tuktest.h:227
#define TUKTEST_STR_ERROR
Definition tuktest.h:229
#define TUKTEST_COLOR_PASS
Definition tuktest.h:214
int64_t tuktest_int
Definition tuktest.h:172
void error(char *msg) const
Definition minigzip.c:356