Skip to content

Commit 49a20bf

Browse files
authored
Merge pull request #117 from pks-t/pks-integer-comparisons
clar: introduce type-safe integer comparisons
2 parents 9757857 + 06f0c35 commit 49a20bf

File tree

9 files changed

+347
-17
lines changed

9 files changed

+347
-17
lines changed

clar.c

Lines changed: 141 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@
2424
#include <sys/types.h>
2525
#include <sys/stat.h>
2626

27+
#ifndef va_copy
28+
# ifdef __va_copy
29+
# define va_copy(dst, src) __va_copy(dst, src)
30+
# else
31+
# define va_copy(dst, src) ((dst) = (src))
32+
# endif
33+
#endif
34+
2735
#if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_WCHAR__)
2836
/*
2937
* uClibc can optionally be built without wchar support, in which case
@@ -76,8 +84,10 @@
7684
# define S_ISDIR(x) ((x & _S_IFDIR) != 0)
7785
# endif
7886
# define p_snprintf(buf,sz,fmt,...) _snprintf_s(buf,sz,_TRUNCATE,fmt,__VA_ARGS__)
87+
# define p_vsnprintf _vsnprintf
7988
# else
8089
# define p_snprintf snprintf
90+
# define p_vsnprintf vsnprintf
8191
# endif
8292

8393
# define localtime_r(timer, buf) (localtime_s(buf, timer) == 0 ? buf : NULL)
@@ -86,6 +96,7 @@
8696
# include <unistd.h>
8797
# define _MAIN_CC
8898
# define p_snprintf snprintf
99+
# define p_vsnprintf vsnprintf
89100
typedef struct stat STAT_T;
90101
#endif
91102

@@ -699,13 +710,14 @@ void clar__skip(void)
699710
abort_test();
700711
}
701712

702-
void clar__fail(
713+
static void clar__failv(
703714
const char *file,
704715
const char *function,
705716
size_t line,
717+
int should_abort,
706718
const char *error_msg,
707719
const char *description,
708-
int should_abort)
720+
va_list args)
709721
{
710722
struct clar_error *error;
711723

@@ -725,9 +737,19 @@ void clar__fail(
725737
error->line_number = _clar.invoke_line ? _clar.invoke_line : line;
726738
error->error_msg = error_msg;
727739

728-
if (description != NULL &&
729-
(error->description = strdup(description)) == NULL)
730-
clar_abort("Failed to allocate description.\n");
740+
if (description != NULL) {
741+
va_list args_copy;
742+
int len;
743+
744+
va_copy(args_copy, args);
745+
if ((len = p_vsnprintf(NULL, 0, description, args_copy)) < 0)
746+
clar_abort("Failed to compute description.");
747+
va_end(args_copy);
748+
749+
if ((error->description = calloc(1, len + 1)) == NULL)
750+
clar_abort("Failed to allocate buffer.");
751+
p_vsnprintf(error->description, len + 1, description, args);
752+
}
731753

732754
_clar.total_errors++;
733755
_clar.last_report->status = CL_TEST_FAILURE;
@@ -736,6 +758,34 @@ void clar__fail(
736758
abort_test();
737759
}
738760

761+
void clar__failf(
762+
const char *file,
763+
const char *function,
764+
size_t line,
765+
int should_abort,
766+
const char *error_msg,
767+
const char *description,
768+
...)
769+
{
770+
va_list args;
771+
va_start(args, description);
772+
clar__failv(file, function, line, should_abort, error_msg,
773+
description, args);
774+
va_end(args);
775+
}
776+
777+
void clar__fail(
778+
const char *file,
779+
const char *function,
780+
size_t line,
781+
const char *error_msg,
782+
const char *description,
783+
int should_abort)
784+
{
785+
clar__failf(file, function, line, should_abort, error_msg,
786+
description ? "%s" : NULL, description);
787+
}
788+
739789
void clar__assert(
740790
int condition,
741791
const char *file,
@@ -889,6 +939,92 @@ void clar__assert_equal(
889939
clar__fail(file, function, line, err, buf, should_abort);
890940
}
891941

942+
void clar__assert_compare_i(
943+
const char *file,
944+
const char *func,
945+
size_t line,
946+
int should_abort,
947+
enum clar_comparison cmp,
948+
intmax_t value1,
949+
intmax_t value2,
950+
const char *error,
951+
const char *description,
952+
...)
953+
{
954+
int fulfilled;
955+
switch (cmp) {
956+
case CLAR_COMPARISON_EQ:
957+
fulfilled = value1 == value2;
958+
break;
959+
case CLAR_COMPARISON_LT:
960+
fulfilled = value1 < value2;
961+
break;
962+
case CLAR_COMPARISON_LE:
963+
fulfilled = value1 <= value2;
964+
break;
965+
case CLAR_COMPARISON_GT:
966+
fulfilled = value1 > value2;
967+
break;
968+
case CLAR_COMPARISON_GE:
969+
fulfilled = value1 >= value2;
970+
break;
971+
default:
972+
cl_assert(0);
973+
return;
974+
}
975+
976+
if (!fulfilled) {
977+
va_list args;
978+
va_start(args, description);
979+
clar__failv(file, func, line, should_abort, error,
980+
description, args);
981+
va_end(args);
982+
}
983+
}
984+
985+
void clar__assert_compare_u(
986+
const char *file,
987+
const char *func,
988+
size_t line,
989+
int should_abort,
990+
enum clar_comparison cmp,
991+
uintmax_t value1,
992+
uintmax_t value2,
993+
const char *error,
994+
const char *description,
995+
...)
996+
{
997+
int fulfilled;
998+
switch (cmp) {
999+
case CLAR_COMPARISON_EQ:
1000+
fulfilled = value1 == value2;
1001+
break;
1002+
case CLAR_COMPARISON_LT:
1003+
fulfilled = value1 < value2;
1004+
break;
1005+
case CLAR_COMPARISON_LE:
1006+
fulfilled = value1 <= value2;
1007+
break;
1008+
case CLAR_COMPARISON_GT:
1009+
fulfilled = value1 > value2;
1010+
break;
1011+
case CLAR_COMPARISON_GE:
1012+
fulfilled = value1 >= value2;
1013+
break;
1014+
default:
1015+
cl_assert(0);
1016+
return;
1017+
}
1018+
1019+
if (!fulfilled) {
1020+
va_list args;
1021+
va_start(args, description);
1022+
clar__failv(file, func, line, should_abort, error,
1023+
description, args);
1024+
va_end(args);
1025+
}
1026+
}
1027+
8921028
void cl_set_cleanup(void (*cleanup)(void *), void *opaque)
8931029
{
8941030
_clar.local_cleanup = cleanup;

clar.h

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#ifndef __CLAR_TEST_H__
88
#define __CLAR_TEST_H__
99

10+
#include <inttypes.h>
1011
#include <stdlib.h>
1112
#include <limits.h>
1213

@@ -149,6 +150,7 @@ const char *cl_fixture_basename(const char *fixture_name);
149150
* Forced failure/warning
150151
*/
151152
#define cl_fail(desc) clar__fail(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Test failed.", desc, 1)
153+
#define cl_failf(desc,...) clar__failf(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, 1, "Test failed.", desc, __VA_ARGS__)
152154
#define cl_warning(desc) clar__fail(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Warning during test execution:", desc, 0)
153155

154156
#define cl_skip() clar__skip()
@@ -168,9 +170,34 @@ const char *cl_fixture_basename(const char *fixture_name);
168170
#define cl_assert_equal_wcsn(wcs1,wcs2,len) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2, 1, "%.*ls", (wcs1), (wcs2), (int)(len))
169171
#define cl_assert_equal_wcsn_(wcs1,wcs2,len,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%.*ls", (wcs1), (wcs2), (int)(len))
170172

171-
#define cl_assert_equal_i(i1,i2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2))
172-
#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2))
173-
#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2))
173+
/* The following three macros are essentially deprecated now in favor of the macros in subsequent blocks. */
174+
#define cl_assert_equal_i(i1,i2) cl_assert_compare_i(i1,i2,CLAR_COMPARISON_EQ,#i1 " != " #i2,"%"PRIdMAX " != %"PRIdMAX,(intmax_t)(i1),(intmax_t)(i2))
175+
#define cl_assert_equal_i_(i1,i2,note) cl_assert_compare_i(i1,i2,CLAR_COMPARISON_EQ,#i1 " != " #i2 " (" #note ")","%"PRIdMAX " != %"PRIdMAX,(intmax_t)(i1),(intmax_t)(i2))
176+
#define cl_assert_equal_i_fmt(i1,i2,fmt) cl_assert_compare_i(i1,i2,CLAR_COMPARISON_EQ,#i1 " != " #i2, fmt " != " fmt, (int)(i1), (int)(i2))
177+
178+
#define cl_assert_compare_i(i1,i2,cmp,error,description,...) clar__assert_compare_i(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,1,cmp,(i1),(i2),error,description,__VA_ARGS__)
179+
#define cl_assert_eq_i_(i1,i2,description,...) cl_assert_compare_i(i1,i2,CLAR_COMPARISON_EQ,"Expected comparison to hold: " #i1 " == " #i2,description,__VA_ARGS__)
180+
#define cl_assert_eq_i(i1,i2) cl_assert_eq_i_(i1,i2,"%"PRIdMAX " != %"PRIdMAX,(intmax_t)(i1),(intmax_t)(i2))
181+
#define cl_assert_lt_i_(i1,i2,description,...) cl_assert_compare_i(i1,i2,CLAR_COMPARISON_LT,"Expected comparison to hold: " #i1 " < " #i2,description,__VA_ARGS__)
182+
#define cl_assert_lt_i(i1,i2) cl_assert_lt_i_(i1,i2,"%"PRIdMAX " >= %"PRIdMAX,(intmax_t)(i1),(intmax_t)(i2))
183+
#define cl_assert_le_i_(i1,i2,description,...) cl_assert_compare_i(i1,i2,CLAR_COMPARISON_LE,"Expected comparison to hold: " #i1 " <= " #i2,description,__VA_ARGS__)
184+
#define cl_assert_le_i(i1,i2) cl_assert_le_i_(i1,i2,"%"PRIdMAX " > %"PRIdMAX,(intmax_t)(i1),(intmax_t)(i2))
185+
#define cl_assert_gt_i_(i1,i2,description,...) cl_assert_compare_i(i1,i2,CLAR_COMPARISON_GT,"Expected comparison to hold: " #i1 " > " #i2,description,__VA_ARGS__)
186+
#define cl_assert_gt_i(i1,i2) cl_assert_gt_i_(i1,i2,"%"PRIdMAX " <= %"PRIdMAX,(intmax_t)(i1),(intmax_t)(i2))
187+
#define cl_assert_ge_i_(i1,i2,description,...) cl_assert_compare_i(i1,i2,CLAR_COMPARISON_GE,"Expected comparison to hold: " #i1 " >= " #i2,description,__VA_ARGS__)
188+
#define cl_assert_ge_i(i1,i2) cl_assert_ge_i_(i1,i2,"%"PRIdMAX " < %"PRIdMAX,(intmax_t)(i1),(intmax_t)(i2))
189+
190+
#define cl_assert_compare_u(u1,u2,cmp,error,description,...) clar__assert_compare_u(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,1,cmp,(u1),(u2),error,description,__VA_ARGS__)
191+
#define cl_assert_eq_u_(u1,u2,description,...) cl_assert_compare_u(u1,u2,CLAR_COMPARISON_EQ,"Expected comparison to hold: " #u1 " == " #u2,description,__VA_ARGS__)
192+
#define cl_assert_eq_u(u1,u2) cl_assert_eq_u_(u1,u2,"%"PRIuMAX " != %"PRIuMAX,(uintmax_t)(u1),(uintmax_t)(u2))
193+
#define cl_assert_lt_u_(u1,u2,description,...) cl_assert_compare_u(u1,u2,CLAR_COMPARISON_LT,"Expected comparison to hold: " #u1 " < " #u2,description,__VA_ARGS__)
194+
#define cl_assert_lt_u(u1,u2) cl_assert_lt_u_(u1,u2,"%"PRIuMAX " >= %"PRIuMAX,(uintmax_t)(u1),(uintmax_t)(u2))
195+
#define cl_assert_le_u_(u1,u2,description,...) cl_assert_compare_u(u1,u2,CLAR_COMPARISON_LE,"Expected comparison to hold: " #u1 " <= " #u2,description,__VA_ARGS__)
196+
#define cl_assert_le_u(u1,u2) cl_assert_le_u_(u1,u2,"%"PRIuMAX " > %"PRIuMAX,(uintmax_t)(u1),(uintmax_t)(u2))
197+
#define cl_assert_gt_u_(u1,u2,description,...) cl_assert_compare_u(u1,u2,CLAR_COMPARISON_GT,"Expected comparison to hold: " #u1 " > " #u2,description,__VA_ARGS__)
198+
#define cl_assert_gt_u(u1,u2) cl_assert_gt_u_(u1,u2,"%"PRIuMAX " <= %"PRIuMAX,(uintmax_t)(u1),(uintmax_t)(u2))
199+
#define cl_assert_ge_u_(u1,u2,description,...) cl_assert_compare_u(u1,u2,CLAR_COMPARISON_GE,"Expected comparison to hold: " #u1 " >= " #u2,description,__VA_ARGS__)
200+
#define cl_assert_ge_u(u1,u2) cl_assert_ge_u_(u1,u2,"%"PRIuMAX " < %"PRIuMAX,(uintmax_t)(u1),(uintmax_t)(u2))
174201

175202
#define cl_assert_equal_b(b1,b2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0))
176203

@@ -186,6 +213,15 @@ void clar__fail(
186213
const char *description,
187214
int should_abort);
188215

216+
void clar__failf(
217+
const char *file,
218+
const char *func,
219+
size_t line,
220+
int should_abort,
221+
const char *error,
222+
const char *description,
223+
...);
224+
189225
void clar__assert(
190226
int condition,
191227
const char *file,
@@ -204,6 +240,38 @@ void clar__assert_equal(
204240
const char *fmt,
205241
...);
206242

243+
enum clar_comparison {
244+
CLAR_COMPARISON_EQ,
245+
CLAR_COMPARISON_LT,
246+
CLAR_COMPARISON_LE,
247+
CLAR_COMPARISON_GT,
248+
CLAR_COMPARISON_GE,
249+
};
250+
251+
void clar__assert_compare_i(
252+
const char *file,
253+
const char *func,
254+
size_t line,
255+
int should_abort,
256+
enum clar_comparison cmp,
257+
intmax_t value1,
258+
intmax_t value2,
259+
const char *error,
260+
const char *description,
261+
...);
262+
263+
void clar__assert_compare_u(
264+
const char *file,
265+
const char *func,
266+
size_t line,
267+
int should_abort,
268+
enum clar_comparison cmp,
269+
uintmax_t value1,
270+
uintmax_t value2,
271+
const char *error,
272+
const char *description,
273+
...);
274+
207275
void clar__set_invokepoint(
208276
const char *file,
209277
const char *func,

test/expected/quiet

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,18 @@ combined::null_string [file:42]
4242
String mismatch: "expected" != actual ("this one fails")
4343
'expected' != NULL
4444

45+
10) Failure:
46+
combined::failf [file:42]
47+
Test failed.
48+
some reason: foo
49+
50+
11) Failure:
51+
combined::compare_i [file:42]
52+
Expected comparison to hold: two < 1
53+
2 >= 1
54+
55+
12) Failure:
56+
combined::compare_u [file:42]
57+
Expected comparison to hold: two < 1
58+
2 >= 1
59+

test/expected/summary_with_filename

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Loaded 1 suites:
22
Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
3-
FFFFFFFFF
3+
FFFFFFFFFFFF
44

55
1) Failure:
66
combined::1 [file:42]
@@ -46,4 +46,19 @@ combined::null_string [file:42]
4646
String mismatch: "expected" != actual ("this one fails")
4747
'expected' != NULL
4848

49+
10) Failure:
50+
combined::failf [file:42]
51+
Test failed.
52+
some reason: foo
53+
54+
11) Failure:
55+
combined::compare_i [file:42]
56+
Expected comparison to hold: two < 1
57+
2 >= 1
58+
59+
12) Failure:
60+
combined::compare_u [file:42]
61+
Expected comparison to hold: two < 1
62+
2 >= 1
63+
4964
written summary file to different.xml

test/expected/summary_without_filename

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Loaded 1 suites:
22
Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
3-
FFFFFFFFF
3+
FFFFFFFFFFFF
44

55
1) Failure:
66
combined::1 [file:42]
@@ -46,4 +46,19 @@ combined::null_string [file:42]
4646
String mismatch: "expected" != actual ("this one fails")
4747
'expected' != NULL
4848

49+
10) Failure:
50+
combined::failf [file:42]
51+
Test failed.
52+
some reason: foo
53+
54+
11) Failure:
55+
combined::compare_i [file:42]
56+
Expected comparison to hold: two < 1
57+
2 >= 1
58+
59+
12) Failure:
60+
combined::compare_u [file:42]
61+
Expected comparison to hold: two < 1
62+
2 >= 1
63+
4964
written summary file to summary.xml

0 commit comments

Comments
 (0)