cauterize 0.0.1.pre13 → 0.0.1.pre14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +33 -33
  3. data/.rspec +1 -1
  4. data/.travisci.yml +4 -4
  5. data/Gemfile +4 -4
  6. data/LICENSE.txt +21 -21
  7. data/README.md +177 -177
  8. data/Rakefile +54 -54
  9. data/bin/cauterize +61 -61
  10. data/cauterize.gemspec +27 -27
  11. data/example/Cauterize +68 -68
  12. data/example/build.sh +25 -25
  13. data/example/c_example_support/empty_main.c +1 -1
  14. data/example/c_example_support/example_project_config.c +11 -11
  15. data/example/c_example_support/example_project_config.h +15 -15
  16. data/example/ruby_ex.rb +14 -14
  17. data/lib/cauterize.rb +117 -117
  18. data/lib/cauterize/base_type.rb +78 -78
  19. data/lib/cauterize/builders.rb +41 -41
  20. data/lib/cauterize/builders/c/buildable.rb +91 -91
  21. data/lib/cauterize/builders/c/builtin.rb +43 -43
  22. data/lib/cauterize/builders/c/composite.rb +57 -57
  23. data/lib/cauterize/builders/c/enumeration.rb +60 -60
  24. data/lib/cauterize/builders/c/fixed_array.rb +74 -74
  25. data/lib/cauterize/builders/c/group.rb +143 -143
  26. data/lib/cauterize/builders/c/scalar.rb +34 -34
  27. data/lib/cauterize/builders/c/variable_array.rb +98 -98
  28. data/lib/cauterize/builders/cs/buildable.rb +59 -59
  29. data/lib/cauterize/builders/cs/builtin.rb +22 -22
  30. data/lib/cauterize/builders/cs/composite.rb +21 -21
  31. data/lib/cauterize/builders/cs/csarray.rb +32 -32
  32. data/lib/cauterize/builders/cs/enumeration.rb +21 -21
  33. data/lib/cauterize/builders/cs/fixed_array.rb +27 -27
  34. data/lib/cauterize/builders/cs/group.rb +32 -32
  35. data/lib/cauterize/builders/cs/scalar.rb +10 -10
  36. data/lib/cauterize/builders/cs/variable_array.rb +40 -34
  37. data/lib/cauterize/builders/doc/buildable.rb +30 -30
  38. data/lib/cauterize/builders/doc/builtin.rb +21 -21
  39. data/lib/cauterize/builders/doc/composite.rb +23 -23
  40. data/lib/cauterize/builders/doc/enumeration.rb +24 -24
  41. data/lib/cauterize/builders/doc/fixed_array.rb +26 -26
  42. data/lib/cauterize/builders/doc/group.rb +29 -29
  43. data/lib/cauterize/builders/doc/scalar.rb +21 -21
  44. data/lib/cauterize/builders/doc/variable_array.rb +26 -26
  45. data/lib/cauterize/builders/ruby/buildable.rb +11 -11
  46. data/lib/cauterize/builders/ruby/builtin.rb +25 -25
  47. data/lib/cauterize/builders/ruby/composite.rb +26 -26
  48. data/lib/cauterize/builders/ruby/enumeration.rb +27 -27
  49. data/lib/cauterize/builders/ruby/fixed_array.rb +20 -20
  50. data/lib/cauterize/builders/ruby/group.rb +35 -35
  51. data/lib/cauterize/builders/ruby/scalar.rb +19 -19
  52. data/lib/cauterize/builders/ruby/variable_array.rb +22 -22
  53. data/lib/cauterize/builtin.rb +62 -62
  54. data/lib/cauterize/c_builder.rb +103 -103
  55. data/lib/cauterize/cauterize.rb +76 -76
  56. data/lib/cauterize/composite.rb +64 -64
  57. data/lib/cauterize/cs_builder.rb +58 -58
  58. data/lib/cauterize/doc_builder.rb +34 -34
  59. data/lib/cauterize/enumeration.rb +98 -98
  60. data/lib/cauterize/fixed_array.rb +50 -50
  61. data/lib/cauterize/formatter.rb +67 -67
  62. data/lib/cauterize/group.rb +81 -81
  63. data/lib/cauterize/representation.rb +32 -32
  64. data/lib/cauterize/ruby_builder.rb +44 -44
  65. data/lib/cauterize/scalar.rb +53 -53
  66. data/lib/cauterize/snake_case.rb +21 -21
  67. data/lib/cauterize/variable_array.rb +55 -55
  68. data/lib/cauterize/version.rb +3 -3
  69. data/spec/base_type_spec.rb +251 -251
  70. data/spec/builders/c/buildable_spec.rb +25 -25
  71. data/spec/builders/c/builtin_spec.rb +22 -22
  72. data/spec/builders/c/composite_spec.rb +50 -50
  73. data/spec/builders/c/enumeration_spec.rb +95 -95
  74. data/spec/builders/c/fixed_array_spec.rb +36 -36
  75. data/spec/builders/c/group_spec.rb +140 -140
  76. data/spec/builders/c/scalar_spec.rb +26 -26
  77. data/spec/builders/c/variable_array_spec.rb +48 -48
  78. data/spec/builders/cs/buildable_spec.rb +8 -8
  79. data/spec/builders/cs/composite_spec.rb +32 -32
  80. data/spec/builders/cs/enumeration_spec.rb +33 -33
  81. data/spec/builders/cs/fixed_array_spec.rb +41 -41
  82. data/spec/builders/cs/group_spec.rb +56 -56
  83. data/spec/builders/cs/scalar_spec.rb +7 -7
  84. data/spec/builders/cs/variable_array_spec.rb +49 -45
  85. data/spec/builders/doc/buildable_spec.rb +25 -25
  86. data/spec/builders_spec.rb +57 -57
  87. data/spec/builtin_spec.rb +43 -43
  88. data/spec/c_builder_spec.rb +176 -176
  89. data/spec/cauterize_spec.rb +15 -15
  90. data/spec/composite_spec.rb +77 -77
  91. data/spec/cs_builder_spec.rb +115 -115
  92. data/spec/doc_builder_spec.rb +260 -260
  93. data/spec/enumeration_spec.rb +145 -145
  94. data/spec/fixed_array_spec.rb +61 -61
  95. data/spec/group_spec.rb +111 -111
  96. data/spec/ruby_builder_spec.rb +83 -83
  97. data/spec/ruby_generated_spec.rb +735 -735
  98. data/spec/scalar_spec.rb +44 -44
  99. data/spec/spec_helper.rb +122 -122
  100. data/spec/support/shared_examples_for_array_buildables.rb +22 -22
  101. data/spec/support/shared_examples_for_c_buildables.rb +103 -103
  102. data/spec/support/shared_examples_for_sane_c_buildables.rb +22 -22
  103. data/spec/support/shared_examples_for_stubbed_functions.rb +18 -18
  104. data/spec/support/spec_sample_model.rb +74 -74
  105. data/spec/test_main.c +13 -13
  106. data/spec/variable_array_spec.rb +73 -73
  107. data/support/c/src/cauterize.c +75 -75
  108. data/support/c/src/cauterize.h +60 -60
  109. data/support/c/src/cauterize_debug.h +29 -29
  110. data/support/c/src/cauterize_util.h +8 -8
  111. data/support/c/test/greatest.h +536 -536
  112. data/support/c/test/test.c +166 -166
  113. data/support/cs/src/CauterizeCompositeFormatter.cs +0 -0
  114. data/support/cs/src/CauterizeContainerFormatter.cs +0 -0
  115. data/support/cs/src/CauterizeEnumFormatter.cs +0 -0
  116. data/support/cs/src/CauterizeException.cs +15 -15
  117. data/support/cs/src/CauterizeFixedArrayFormatter.cs +2 -2
  118. data/support/cs/src/CauterizeFormatter.cs +0 -0
  119. data/support/cs/src/CauterizeGroupFormatter.cs +0 -0
  120. data/support/cs/src/CauterizeTypeFormatterFactory.cs +0 -0
  121. data/support/cs/src/CauterizeTypes.cs +46 -12
  122. data/support/cs/src/CauterizeVariableArrayFormatter.cs +1 -1
  123. data/support/cs/src/ICauterizeTypeFormatter.cs +0 -0
  124. data/support/cs/src/OrderAttribute.cs +0 -0
  125. data/support/cs/src/PrimitiveSupport.cs +12 -0
  126. data/support/cs/test/CauterizeCompositeFormatterTest.cs +0 -0
  127. data/support/cs/test/CauterizeEnumFormatterTest.cs +0 -0
  128. data/support/cs/test/CauterizeFixedArrayFormatterTest.cs +0 -0
  129. data/support/cs/test/CauterizeFormatterTest.cs +0 -0
  130. data/support/cs/test/CauterizeGroupFormatterTest.cs +0 -0
  131. data/support/cs/test/CauterizeIntegrationTest.cs +0 -0
  132. data/support/cs/test/CauterizePrimitiveFormatterTest.cs +0 -0
  133. data/support/cs/test/CauterizeTypeFormatterFactoryTest.cs +0 -0
  134. data/support/cs/test/CauterizeVariableArrayFormatterTest.cs +0 -0
  135. data/support/cs/test/OrderAttributeTest.cs +0 -0
  136. data/support/ruby/src/cauterize_ruby_baseclasses.rb +367 -367
  137. data/support/ruby/src/cauterize_ruby_builtins.rb +148 -148
  138. metadata +20 -20
@@ -1,60 +1,60 @@
1
- #ifndef CAUTERIZE_H
2
- #define CAUTERIZE_H
3
-
4
- #ifndef CUSTOM_TYPES
5
- #include <stdint.h>
6
- #include <stdbool.h>
7
- #include <stddef.h>
8
- #else
9
- #include "cauterize_custom_types.h"
10
- #endif
11
-
12
- #include "cauterize_util.h"
13
-
14
- typedef enum cauterize_status {
15
- CA_OK = 0,
16
- CA_ERR_ASSERT = 1,
17
- CA_ERR_NOT_ENOUGH_SPACE = 2,
18
- CA_ERR_NOT_ENOUGH_DATA = 3,
19
- CA_ERR_INVALID_LENGTH = 4,
20
- CA_ERR_INVALID_TYPE_TAG = 5,
21
- CA_ERR_INVALID_ENUM_VAL = 6,
22
- CA_ERR_GENERAL = INT32_MAX,
23
- } CAUTERIZE_STATUS_T;
24
-
25
- struct Cauterize {
26
- uint32_t size; // Size of the buffer in bytes
27
- uint32_t used; // Number of used bytes in the buffer
28
- uint32_t pos; // The next byte to be read
29
- uint8_t * buffer; // Buffer to hold data
30
- };
31
-
32
- #ifdef __cplusplus
33
- extern "C" {
34
- #endif
35
-
36
- CAUTERIZE_STATUS_T CauterizeInitAppend(
37
- struct Cauterize * m,
38
- uint8_t * buffer,
39
- uint32_t length);
40
-
41
- CAUTERIZE_STATUS_T CauterizeInitRead(
42
- struct Cauterize * m,
43
- uint8_t * buffer,
44
- uint32_t used);
45
-
46
- CAUTERIZE_STATUS_T CauterizeAppend(
47
- struct Cauterize * m,
48
- uint8_t * src,
49
- uint32_t length);
50
-
51
- CAUTERIZE_STATUS_T CauterizeRead(
52
- struct Cauterize * m,
53
- uint8_t * dst,
54
- uint32_t length);
55
-
56
- #ifdef __cplusplus
57
- }
58
- #endif
59
-
60
- #endif /* CAUTERIZE_H */
1
+ #ifndef CAUTERIZE_H
2
+ #define CAUTERIZE_H
3
+
4
+ #ifndef CUSTOM_TYPES
5
+ #include <stdint.h>
6
+ #include <stdbool.h>
7
+ #include <stddef.h>
8
+ #else
9
+ #include "cauterize_custom_types.h"
10
+ #endif
11
+
12
+ #include "cauterize_util.h"
13
+
14
+ typedef enum cauterize_status {
15
+ CA_OK = 0,
16
+ CA_ERR_ASSERT = 1,
17
+ CA_ERR_NOT_ENOUGH_SPACE = 2,
18
+ CA_ERR_NOT_ENOUGH_DATA = 3,
19
+ CA_ERR_INVALID_LENGTH = 4,
20
+ CA_ERR_INVALID_TYPE_TAG = 5,
21
+ CA_ERR_INVALID_ENUM_VAL = 6,
22
+ CA_ERR_GENERAL = INT32_MAX,
23
+ } CAUTERIZE_STATUS_T;
24
+
25
+ struct Cauterize {
26
+ uint32_t size; // Size of the buffer in bytes
27
+ uint32_t used; // Number of used bytes in the buffer
28
+ uint32_t pos; // The next byte to be read
29
+ uint8_t * buffer; // Buffer to hold data
30
+ };
31
+
32
+ #ifdef __cplusplus
33
+ extern "C" {
34
+ #endif
35
+
36
+ CAUTERIZE_STATUS_T CauterizeInitAppend(
37
+ struct Cauterize * m,
38
+ uint8_t * buffer,
39
+ uint32_t length);
40
+
41
+ CAUTERIZE_STATUS_T CauterizeInitRead(
42
+ struct Cauterize * m,
43
+ uint8_t * buffer,
44
+ uint32_t used);
45
+
46
+ CAUTERIZE_STATUS_T CauterizeAppend(
47
+ struct Cauterize * m,
48
+ uint8_t * src,
49
+ uint32_t length);
50
+
51
+ CAUTERIZE_STATUS_T CauterizeRead(
52
+ struct Cauterize * m,
53
+ uint8_t * dst,
54
+ uint32_t length);
55
+
56
+ #ifdef __cplusplus
57
+ }
58
+ #endif
59
+
60
+ #endif /* CAUTERIZE_H */
@@ -1,29 +1,29 @@
1
- #ifndef CAUTERIZE_DEBUG_H
2
- #define CAUTERIZE_DEBUG_H
3
-
4
- #ifndef CAUTERIZE_C
5
- #error "You should not include cauterize_debug.h."
6
- #endif
7
-
8
- #ifndef NDEBUG
9
-
10
- #include <stdio.h>
11
- #define CA_ASSERT_PRINT(msg) \
12
- fprintf(stderr, "ASSERT: %s (%s:%d)\n", msg, __FILE__, __LINE__);
13
-
14
- #define CA_ASSERT(cond) CA_ASSERTm(#cond, cond)
15
- #define CA_ASSERTm(msg, cond) \
16
- do { \
17
- if(!(cond)) { \
18
- CA_ASSERT_PRINT(msg); \
19
- return CA_ERR_ASSERT; \
20
- } \
21
- } while(0)
22
-
23
- #else
24
-
25
- #define CA_ASSERT(cond)
26
-
27
- #endif
28
-
29
- #endif /* CAUTERIZE_DEBUG_H */
1
+ #ifndef CAUTERIZE_DEBUG_H
2
+ #define CAUTERIZE_DEBUG_H
3
+
4
+ #ifndef CAUTERIZE_C
5
+ #error "You should not include cauterize_debug.h."
6
+ #endif
7
+
8
+ #ifndef NDEBUG
9
+
10
+ #include <stdio.h>
11
+ #define CA_ASSERT_PRINT(msg) \
12
+ fprintf(stderr, "ASSERT: %s (%s:%d)\n", msg, __FILE__, __LINE__);
13
+
14
+ #define CA_ASSERT(cond) CA_ASSERTm(#cond, cond)
15
+ #define CA_ASSERTm(msg, cond) \
16
+ do { \
17
+ if(!(cond)) { \
18
+ CA_ASSERT_PRINT(msg); \
19
+ return CA_ERR_ASSERT; \
20
+ } \
21
+ } while(0)
22
+
23
+ #else
24
+
25
+ #define CA_ASSERT(cond)
26
+
27
+ #endif
28
+
29
+ #endif /* CAUTERIZE_DEBUG_H */
@@ -1,8 +1,8 @@
1
- #ifndef CAUTERIZE_UTIL_H
2
- #define CAUTERIZE_UTIL_H
3
-
4
- #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
5
- #define CA_MIN(a, b) (((a) < (b)) ? (a) : (b))
6
- #define CA_MAX(a,b) ((a) > (b) ? (a) : (b))
7
-
8
- #endif /* CAUTERIZE_UTIL_H */
1
+ #ifndef CAUTERIZE_UTIL_H
2
+ #define CAUTERIZE_UTIL_H
3
+
4
+ #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
5
+ #define CA_MIN(a, b) (((a) < (b)) ? (a) : (b))
6
+ #define CA_MAX(a,b) ((a) > (b) ? (a) : (b))
7
+
8
+ #endif /* CAUTERIZE_UTIL_H */
@@ -1,536 +1,536 @@
1
- /*
2
- * Copyright (c) 2011 Scott Vokes <vokes.s@gmail.com>
3
- *
4
- * Permission to use, copy, modify, and/or distribute this software for any
5
- * purpose with or without fee is hereby granted, provided that the above
6
- * copyright notice and this permission notice appear in all copies.
7
- *
8
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
- */
16
-
17
- #ifndef GREATEST_H
18
- #define GREATEST_H
19
-
20
- #define GREATEST_VERSION 0.8
21
-
22
- /* A unit testing system for C, contained in 1 file.
23
- * It doesn't use dynamic allocation or depend on anything
24
- * beyond ANSI C89.
25
- *
26
- * If C99 is available, then suites can pass arguments to tests for
27
- * parametric testing. */
28
-
29
-
30
- /*********************************************************************
31
- * Minimal test runner template
32
- *********************************************************************/
33
- #if 0
34
-
35
- #include "greatest.h"
36
-
37
- TEST foo() {
38
- PASS();
39
- }
40
-
41
- SUITE(suite) {
42
- RUN_TEST(foo);
43
- }
44
-
45
- /* Add all the definitions that need to be in the test runner's main file. */
46
- GREATEST_MAIN_DEFS();
47
-
48
- int main(int argc, char **argv) {
49
- GREATEST_MAIN_BEGIN(); /* command-line arguments, initialization. */
50
- RUN_SUITE(suite);
51
- GREATEST_MAIN_END(); /* display results */
52
- }
53
-
54
- #endif
55
- /*********************************************************************/
56
-
57
-
58
- #include <stdlib.h>
59
- #include <stdio.h>
60
- #include <string.h>
61
- #include <time.h>
62
-
63
-
64
- /***********
65
- * Options *
66
- ***********/
67
-
68
- /* Default column width for non-verbose output. */
69
- #ifndef GREATEST_DEFAULT_WIDTH
70
- #define GREATEST_DEFAULT_WIDTH 72
71
- #endif
72
-
73
- /* FILE *, for test logging. */
74
- #ifndef GREATEST_STDOUT
75
- #define GREATEST_STDOUT stdout
76
- #endif
77
-
78
- /* Remove GREATEST_ prefix from most commonly used symbols? */
79
- #ifndef GREATEST_USE_ABBREVS
80
- #define GREATEST_USE_ABBREVS 1
81
- #endif
82
-
83
-
84
- /*********
85
- * Types *
86
- *********/
87
-
88
- /* Info for the current running suite. */
89
- typedef struct greatest_suite_info {
90
- unsigned int tests_run;
91
- unsigned int passed;
92
- unsigned int failed;
93
- unsigned int skipped;
94
-
95
- /* timers, pre/post running suite and individual tests */
96
- clock_t pre_suite;
97
- clock_t post_suite;
98
- clock_t pre_test;
99
- clock_t post_test;
100
- } greatest_suite_info;
101
-
102
- /* Type for a suite function. */
103
- typedef void (greatest_suite_cb)(void);
104
-
105
- /* Type for a teardown callback. If non-NULL, this will be
106
- * run after the current test case finishes (and then set to NULL). */
107
- typedef void (greatest_teardown_cb)(void *udata);
108
-
109
- typedef struct greatest_run_info {
110
- unsigned int verbose; /* verbose flag */
111
- unsigned int list_only; /* list suite/tests only flag */
112
- unsigned int tests_run; /* total test count */
113
-
114
- /* Overall pass/fail/skip counts. */
115
- unsigned int passed;
116
- unsigned int failed;
117
- unsigned int skipped;
118
-
119
- /* currently running test suite */
120
- greatest_suite_info suite;
121
-
122
- /* info to print about the most recent failure */
123
- char *fail_file;
124
- unsigned int fail_line;
125
- char *msg;
126
-
127
- /* current teardown hook and userdata */
128
- greatest_teardown_cb *teardown;
129
- void *teardown_udata;
130
-
131
- /* formatting info for ".....s...F"-style output */
132
- unsigned int col;
133
- unsigned int width;
134
-
135
- /* only run a specific suite or test */
136
- char *suite_filter;
137
- char *test_filter;
138
-
139
- /* overall timers */
140
- clock_t begin;
141
- clock_t end;
142
- } greatest_run_info;
143
-
144
- /* Global var for the current testing context.
145
- * Initialized by GREATEST_MAIN_DEFS(). */
146
- extern greatest_run_info greatest_info;
147
-
148
-
149
- /**********************
150
- * Exported functions *
151
- **********************/
152
-
153
- void greatest_do_pass(const char *name);
154
- void greatest_do_fail(const char *name);
155
- void greatest_do_skip(const char *name);
156
- int greatest_pre_test(const char *name);
157
- void greatest_post_test(const char *name, int res);
158
- void greatest_usage(const char *name);
159
- void GREATEST_SET_TEARDOWN_CB(greatest_teardown_cb *cb, void *udata);
160
-
161
-
162
- /**********
163
- * Macros *
164
- **********/
165
-
166
- /* Define a suite. */
167
- #define GREATEST_SUITE(NAME) void NAME()
168
-
169
- /* Start defining a test function.
170
- * The arguments are not included, to allow parametric testing. */
171
- #define GREATEST_TEST static int
172
-
173
- /* Run a suite. */
174
- #define GREATEST_RUN_SUITE(S_NAME) greatest_run_suite(S_NAME, #S_NAME)
175
-
176
- /* Run a test in the current suite.
177
- * If __VA_ARGS__ (C99) is supported, allow parametric testing. */
178
- #if __STDC_VERSION__ >= 19901L
179
- #define GREATEST_RUN_TESTp(TEST, ...) \
180
- do { \
181
- if (greatest_pre_test(#TEST) == 1) { \
182
- int res = TEST(__VA_ARGS__); \
183
- greatest_post_test(#TEST, res); \
184
- } else if (greatest_info.list_only) { \
185
- fprintf(GREATEST_STDOUT, " %s\n", #TEST); \
186
- } \
187
- } while (0)
188
- #endif
189
-
190
- #define GREATEST_RUN_TEST(TEST) \
191
- do { \
192
- if (greatest_pre_test(#TEST) == 1) { \
193
- int res = TEST(); \
194
- greatest_post_test(#TEST, res); \
195
- } else if (greatest_info.list_only) { \
196
- fprintf(GREATEST_STDOUT, " %s\n", #TEST); \
197
- } \
198
- } while (0)
199
-
200
- /* Check if the test runner is in verbose mode. */
201
- #define GREATEST_IS_VERBOSE() (greatest_info.verbose)
202
-
203
- /* Message-less forms. */
204
- #define GREATEST_PASS() GREATEST_PASSm(NULL)
205
- #define GREATEST_FAIL() GREATEST_FAILm(NULL)
206
- #define GREATEST_SKIP() GREATEST_SKIPm(NULL)
207
- #define GREATEST_ASSERT(COND) GREATEST_ASSERTm(#COND, COND)
208
- #define GREATEST_ASSERT_FALSE(COND) GREATEST_ASSERT_FALSEm(#COND, COND)
209
- #define GREATEST_ASSERT_EQ(EXP, GOT) GREATEST_ASSERT_EQm(#EXP " != " #GOT, EXP, GOT)
210
- #define GREATEST_ASSERT_STR_EQ(EXP, GOT) GREATEST_ASSERT_STR_EQm(#EXP " != " #GOT, EXP, GOT)
211
-
212
- /* If set, call and clear the teardown callback. */
213
- #define GREATEST_CALL_TEARDOWN() \
214
- do { \
215
- if (greatest_info.teardown) { \
216
- greatest_info.teardown(greatest_info.teardown_udata); \
217
- greatest_info.teardown = NULL; \
218
- greatest_info.teardown_udata = NULL; \
219
- } \
220
- } while (0) \
221
-
222
- /* The following forms take an additional message argument first,
223
- * to be displayed by the test runner. */
224
-
225
- /* Fail if a condition is not true, with message. */
226
- #define GREATEST_ASSERTm(MSG, COND) \
227
- do { \
228
- greatest_info.msg = MSG; \
229
- greatest_info.fail_file = __FILE__; \
230
- greatest_info.fail_line = __LINE__; \
231
- if (!(COND)) { \
232
- GREATEST_CALL_TEARDOWN(); \
233
- return -1; \
234
- } \
235
- greatest_info.msg = NULL; \
236
- } while (0)
237
-
238
- #define GREATEST_ASSERT_FALSEm(MSG, COND) \
239
- do { \
240
- greatest_info.msg = MSG; \
241
- greatest_info.fail_file = __FILE__; \
242
- greatest_info.fail_line = __LINE__; \
243
- if ((COND)) { \
244
- GREATEST_CALL_TEARDOWN(); \
245
- return -1; \
246
- } \
247
- greatest_info.msg = NULL; \
248
- } while (0)
249
-
250
- #define GREATEST_ASSERT_EQm(MSG, EXP, GOT) \
251
- do { \
252
- greatest_info.msg = MSG; \
253
- greatest_info.fail_file = __FILE__; \
254
- greatest_info.fail_line = __LINE__; \
255
- if ((EXP) != (GOT)) { \
256
- GREATEST_CALL_TEARDOWN(); \
257
- return -1; \
258
- } \
259
- greatest_info.msg = NULL; \
260
- } while (0)
261
-
262
- #define GREATEST_ASSERT_STR_EQm(MSG, EXP, GOT) \
263
- do { \
264
- char *exp_s = (EXP); \
265
- char *got_s = (GOT); \
266
- greatest_info.msg = MSG; \
267
- greatest_info.fail_file = __FILE__; \
268
- greatest_info.fail_line = __LINE__; \
269
- if (0 != strcmp(exp_s, got_s)) { \
270
- GREATEST_CALL_TEARDOWN(); \
271
- fprintf(GREATEST_STDOUT, \
272
- "Expected:\n####\n%s\n####\n", exp_s); \
273
- fprintf(GREATEST_STDOUT, \
274
- "Got:\n####\n%s\n####\n", got_s); \
275
- return -1; \
276
- } \
277
- greatest_info.msg = NULL; \
278
- } while (0)
279
-
280
- #define GREATEST_PASSm(MSG) \
281
- do { \
282
- GREATEST_CALL_TEARDOWN(); \
283
- greatest_info.msg = MSG; \
284
- return 0; \
285
- } while (0)
286
-
287
- #define GREATEST_FAILm(MSG) \
288
- do { \
289
- GREATEST_CALL_TEARDOWN(); \
290
- greatest_info.fail_file = __FILE__; \
291
- greatest_info.fail_line = __LINE__; \
292
- greatest_info.msg = MSG; \
293
- return -1; \
294
- } while (0)
295
-
296
- #define GREATEST_SKIPm(MSG) \
297
- do { \
298
- GREATEST_CALL_TEARDOWN(); \
299
- greatest_info.msg = MSG; \
300
- return 1; \
301
- } while (0)
302
-
303
- #define GREATEST_SET_TIME(NAME) \
304
- NAME = clock(); \
305
- if (NAME == (clock_t) -1) { \
306
- fprintf(GREATEST_STDOUT, \
307
- "clock error: %s\n", #NAME); \
308
- exit(EXIT_FAILURE); \
309
- }
310
-
311
- #define GREATEST_CLOCK_DIFF(C1, C2) \
312
- fprintf(GREATEST_STDOUT, " (%lu ticks, %.3f sec)", \
313
- (long unsigned int) (C2) - (C1), \
314
- ((C2) - (C1))/ (1.0 * CLOCKS_PER_SEC)) \
315
-
316
- /* Include several function definitions in the main test file. */
317
- #define GREATEST_MAIN_DEFS() \
318
- int greatest_pre_test(const char *name) { \
319
- if (!greatest_info.list_only \
320
- && (greatest_info.test_filter == NULL || \
321
- 0 == strcmp(name, greatest_info.test_filter))) { \
322
- GREATEST_SET_TIME(greatest_info.suite.pre_test); \
323
- return 1; /* test should be run */ \
324
- } else { \
325
- return 0; /* skipped */ \
326
- } \
327
- } \
328
- \
329
- void greatest_post_test(const char *name, int res) { \
330
- GREATEST_SET_TIME(greatest_info.suite.post_test); \
331
- if (res < 0) { \
332
- greatest_do_fail(name); \
333
- } else if (res > 0) { \
334
- greatest_do_skip(name); \
335
- } else if (res == 0) { \
336
- greatest_do_pass(name); \
337
- } \
338
- greatest_info.suite.tests_run++; \
339
- greatest_info.col++; \
340
- if (greatest_info.verbose) { \
341
- GREATEST_CLOCK_DIFF(greatest_info.suite.pre_test, \
342
- greatest_info.suite.post_test); \
343
- fprintf(GREATEST_STDOUT, "\n"); \
344
- } else if (greatest_info.col % greatest_info.width == 0) { \
345
- fprintf(GREATEST_STDOUT, "\n"); \
346
- greatest_info.col = 0; \
347
- } \
348
- if (GREATEST_STDOUT == stdout) fflush(stdout); \
349
- } \
350
- \
351
- static void greatest_run_suite(greatest_suite_cb *suite_cb, \
352
- char *suite_name) { \
353
- if (greatest_info.suite_filter && \
354
- 0 != strcmp(suite_name, greatest_info.suite_filter)) \
355
- return; \
356
- greatest_info.suite.tests_run = 0; \
357
- greatest_info.suite.failed = 0; \
358
- greatest_info.suite.passed = 0; \
359
- greatest_info.suite.skipped = 0; \
360
- greatest_info.suite.pre_suite = 0; \
361
- greatest_info.suite.post_suite = 0; \
362
- greatest_info.suite.pre_test = 0; \
363
- greatest_info.suite.post_test = 0; \
364
- greatest_info.col = 0; \
365
- fprintf(GREATEST_STDOUT, "\n* Suite %s:\n", suite_name); \
366
- GREATEST_SET_TIME(greatest_info.suite.pre_suite); \
367
- suite_cb(); \
368
- GREATEST_SET_TIME(greatest_info.suite.post_suite); \
369
- if (greatest_info.suite.tests_run > 0) { \
370
- fprintf(GREATEST_STDOUT, \
371
- "\n%u tests - %u pass, %u fail, %u skipped", \
372
- greatest_info.suite.tests_run, \
373
- greatest_info.suite.passed, \
374
- greatest_info.suite.failed, \
375
- greatest_info.suite.skipped); \
376
- GREATEST_CLOCK_DIFF(greatest_info.suite.pre_suite, \
377
- greatest_info.suite.post_suite); \
378
- fprintf(GREATEST_STDOUT, "\n"); \
379
- } \
380
- greatest_info.passed += greatest_info.suite.passed; \
381
- greatest_info.failed += greatest_info.suite.failed; \
382
- greatest_info.skipped += greatest_info.suite.skipped; \
383
- greatest_info.tests_run += greatest_info.suite.tests_run; \
384
- } \
385
- \
386
- void greatest_do_pass(const char *name) { \
387
- if (greatest_info.verbose) { \
388
- fprintf(GREATEST_STDOUT, "PASS %s: %s", \
389
- name, greatest_info.msg ? greatest_info.msg : ""); \
390
- } else { \
391
- fprintf(GREATEST_STDOUT, "."); \
392
- } \
393
- greatest_info.suite.passed++; \
394
- } \
395
- \
396
- void greatest_do_fail(const char *name) { \
397
- if (greatest_info.verbose) { \
398
- fprintf(GREATEST_STDOUT, \
399
- "FAIL %s: %s (%s:%u)", \
400
- name, greatest_info.msg ? greatest_info.msg : "", \
401
- greatest_info.fail_file, greatest_info.fail_line); \
402
- } else { \
403
- fprintf(GREATEST_STDOUT, "F"); \
404
- /* add linebreak if in line of '.'s */ \
405
- if (greatest_info.col % greatest_info.width != 0) \
406
- fprintf(GREATEST_STDOUT, "\n"); \
407
- greatest_info.col = 0; \
408
- fprintf(GREATEST_STDOUT, "FAIL %s: %s (%s:%u)\n", \
409
- name, \
410
- greatest_info.msg ? greatest_info.msg : "", \
411
- greatest_info.fail_file, greatest_info.fail_line); \
412
- } \
413
- greatest_info.suite.failed++; \
414
- } \
415
- \
416
- void greatest_do_skip(const char *name) { \
417
- if (greatest_info.verbose) { \
418
- fprintf(GREATEST_STDOUT, "SKIP %s: %s", \
419
- name, \
420
- greatest_info.msg ? \
421
- greatest_info.msg : "" ); \
422
- } else { \
423
- fprintf(GREATEST_STDOUT, "s"); \
424
- } \
425
- greatest_info.suite.skipped++; \
426
- } \
427
- \
428
- void greatest_usage(const char *name) { \
429
- fprintf(GREATEST_STDOUT, \
430
- "Usage: %s [-hlv] [-s SUITE] [-t TEST]\n" \
431
- " -h print this Help\n" \
432
- " -l List suites and their tests, then exit\n" \
433
- " -v Verbose output\n" \
434
- " -s SUITE only run suite named SUITE\n" \
435
- " -t TEST only run test named TEST\n", \
436
- name); \
437
- } \
438
- \
439
- /* Set the teardown callback. \
440
- * (Uppercase because it's part of the user interface.) */ \
441
- void GREATEST_SET_TEARDOWN_CB(greatest_teardown_cb *cb, void *udata) { \
442
- greatest_info.teardown = cb; \
443
- greatest_info.teardown_udata = udata; \
444
- } \
445
- \
446
- greatest_run_info greatest_info = {0, 0, 0, \
447
- 0, 0, 0, \
448
- {0, 0, 0, 0, \
449
- 0, 0, 0, 0}, \
450
- NULL, 0, NULL, NULL, NULL, \
451
- 0, GREATEST_DEFAULT_WIDTH, \
452
- NULL, NULL, \
453
- 0, 0}
454
-
455
- /* Handle command-line arguments, etc. */
456
- #define GREATEST_MAIN_BEGIN() \
457
- do { \
458
- int i = 0; \
459
- for (i = 1; i < argc; i++) { \
460
- if (0 == strcmp("-t", argv[i])) { \
461
- if (argc <= i + 1) { \
462
- greatest_usage(argv[0]); \
463
- exit(EXIT_FAILURE); \
464
- } \
465
- greatest_info.test_filter = argv[i+1]; \
466
- i++; \
467
- } else if (0 == strcmp("-s", argv[i])) { \
468
- if (argc <= i + 1) { \
469
- greatest_usage(argv[0]); \
470
- exit(EXIT_FAILURE); \
471
- } \
472
- greatest_info.suite_filter = argv[i+1]; \
473
- i++; \
474
- } else if (0 == strcmp("-v", argv[i])) { \
475
- greatest_info.verbose = 1; \
476
- } else if (0 == strcmp("-l", argv[i])) { \
477
- greatest_info.list_only = 1; \
478
- } else if (0 == strcmp("-h", argv[i])) { \
479
- greatest_usage(argv[0]); \
480
- exit(EXIT_SUCCESS); \
481
- } else { \
482
- fprintf(GREATEST_STDOUT, \
483
- "Unknown argument '%s'\n", argv[i]); \
484
- greatest_usage(argv[0]); \
485
- exit(EXIT_FAILURE); \
486
- } \
487
- } \
488
- } while (0); \
489
- GREATEST_SET_TIME(greatest_info.begin)
490
-
491
- #define GREATEST_MAIN_END() \
492
- do { \
493
- if (!greatest_info.list_only) { \
494
- GREATEST_SET_TIME(greatest_info.end); \
495
- fprintf(GREATEST_STDOUT, \
496
- "\nTotal: %u tests", greatest_info.tests_run); \
497
- GREATEST_CLOCK_DIFF(greatest_info.begin, \
498
- greatest_info.end); \
499
- fprintf(GREATEST_STDOUT, "\n"); \
500
- fprintf(GREATEST_STDOUT, \
501
- "Pass: %u, fail: %u, skip: %u.\n", \
502
- greatest_info.passed, \
503
- greatest_info.failed, greatest_info.skipped); \
504
- } \
505
- return (greatest_info.failed > 0 \
506
- ? EXIT_FAILURE : EXIT_SUCCESS); \
507
- } while (0)
508
-
509
- /* Make abbreviations without the GREATEST_ prefix for the
510
- * most commonly used symbols. */
511
- #if GREATEST_USE_ABBREVS
512
- #define TEST GREATEST_TEST
513
- #define SUITE GREATEST_SUITE
514
- #define RUN_TEST GREATEST_RUN_TEST
515
- #define RUN_SUITE GREATEST_RUN_SUITE
516
- #define ASSERT GREATEST_ASSERT
517
- #define ASSERTm GREATEST_ASSERTm
518
- #define ASSERT_FALSE GREATEST_ASSERT_FALSE
519
- #define ASSERT_EQ GREATEST_ASSERT_EQ
520
- #define ASSERT_STR_EQ GREATEST_ASSERT_STR_EQ
521
- #define ASSERT_FALSEm GREATEST_ASSERT_FALSEm
522
- #define ASSERT_EQm GREATEST_ASSERT_EQm
523
- #define ASSERT_STR_EQm GREATEST_ASSERT_STR_EQm
524
- #define PASS GREATEST_PASS
525
- #define FAIL GREATEST_FAIL
526
- #define SKIP GREATEST_SKIP
527
- #define PASSm GREATEST_PASSm
528
- #define FAILm GREATEST_FAILm
529
- #define SKIPm GREATEST_SKIPm
530
-
531
- #if __STDC_VERSION__ >= 19901L
532
- #endif /* C99 */
533
- #define RUN_TESTp GREATEST_RUN_TESTp
534
- #endif /* USE_ABBREVS */
535
-
536
- #endif
1
+ /*
2
+ * Copyright (c) 2011 Scott Vokes <vokes.s@gmail.com>
3
+ *
4
+ * Permission to use, copy, modify, and/or distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+ #ifndef GREATEST_H
18
+ #define GREATEST_H
19
+
20
+ #define GREATEST_VERSION 0.8
21
+
22
+ /* A unit testing system for C, contained in 1 file.
23
+ * It doesn't use dynamic allocation or depend on anything
24
+ * beyond ANSI C89.
25
+ *
26
+ * If C99 is available, then suites can pass arguments to tests for
27
+ * parametric testing. */
28
+
29
+
30
+ /*********************************************************************
31
+ * Minimal test runner template
32
+ *********************************************************************/
33
+ #if 0
34
+
35
+ #include "greatest.h"
36
+
37
+ TEST foo() {
38
+ PASS();
39
+ }
40
+
41
+ SUITE(suite) {
42
+ RUN_TEST(foo);
43
+ }
44
+
45
+ /* Add all the definitions that need to be in the test runner's main file. */
46
+ GREATEST_MAIN_DEFS();
47
+
48
+ int main(int argc, char **argv) {
49
+ GREATEST_MAIN_BEGIN(); /* command-line arguments, initialization. */
50
+ RUN_SUITE(suite);
51
+ GREATEST_MAIN_END(); /* display results */
52
+ }
53
+
54
+ #endif
55
+ /*********************************************************************/
56
+
57
+
58
+ #include <stdlib.h>
59
+ #include <stdio.h>
60
+ #include <string.h>
61
+ #include <time.h>
62
+
63
+
64
+ /***********
65
+ * Options *
66
+ ***********/
67
+
68
+ /* Default column width for non-verbose output. */
69
+ #ifndef GREATEST_DEFAULT_WIDTH
70
+ #define GREATEST_DEFAULT_WIDTH 72
71
+ #endif
72
+
73
+ /* FILE *, for test logging. */
74
+ #ifndef GREATEST_STDOUT
75
+ #define GREATEST_STDOUT stdout
76
+ #endif
77
+
78
+ /* Remove GREATEST_ prefix from most commonly used symbols? */
79
+ #ifndef GREATEST_USE_ABBREVS
80
+ #define GREATEST_USE_ABBREVS 1
81
+ #endif
82
+
83
+
84
+ /*********
85
+ * Types *
86
+ *********/
87
+
88
+ /* Info for the current running suite. */
89
+ typedef struct greatest_suite_info {
90
+ unsigned int tests_run;
91
+ unsigned int passed;
92
+ unsigned int failed;
93
+ unsigned int skipped;
94
+
95
+ /* timers, pre/post running suite and individual tests */
96
+ clock_t pre_suite;
97
+ clock_t post_suite;
98
+ clock_t pre_test;
99
+ clock_t post_test;
100
+ } greatest_suite_info;
101
+
102
+ /* Type for a suite function. */
103
+ typedef void (greatest_suite_cb)(void);
104
+
105
+ /* Type for a teardown callback. If non-NULL, this will be
106
+ * run after the current test case finishes (and then set to NULL). */
107
+ typedef void (greatest_teardown_cb)(void *udata);
108
+
109
+ typedef struct greatest_run_info {
110
+ unsigned int verbose; /* verbose flag */
111
+ unsigned int list_only; /* list suite/tests only flag */
112
+ unsigned int tests_run; /* total test count */
113
+
114
+ /* Overall pass/fail/skip counts. */
115
+ unsigned int passed;
116
+ unsigned int failed;
117
+ unsigned int skipped;
118
+
119
+ /* currently running test suite */
120
+ greatest_suite_info suite;
121
+
122
+ /* info to print about the most recent failure */
123
+ char *fail_file;
124
+ unsigned int fail_line;
125
+ char *msg;
126
+
127
+ /* current teardown hook and userdata */
128
+ greatest_teardown_cb *teardown;
129
+ void *teardown_udata;
130
+
131
+ /* formatting info for ".....s...F"-style output */
132
+ unsigned int col;
133
+ unsigned int width;
134
+
135
+ /* only run a specific suite or test */
136
+ char *suite_filter;
137
+ char *test_filter;
138
+
139
+ /* overall timers */
140
+ clock_t begin;
141
+ clock_t end;
142
+ } greatest_run_info;
143
+
144
+ /* Global var for the current testing context.
145
+ * Initialized by GREATEST_MAIN_DEFS(). */
146
+ extern greatest_run_info greatest_info;
147
+
148
+
149
+ /**********************
150
+ * Exported functions *
151
+ **********************/
152
+
153
+ void greatest_do_pass(const char *name);
154
+ void greatest_do_fail(const char *name);
155
+ void greatest_do_skip(const char *name);
156
+ int greatest_pre_test(const char *name);
157
+ void greatest_post_test(const char *name, int res);
158
+ void greatest_usage(const char *name);
159
+ void GREATEST_SET_TEARDOWN_CB(greatest_teardown_cb *cb, void *udata);
160
+
161
+
162
+ /**********
163
+ * Macros *
164
+ **********/
165
+
166
+ /* Define a suite. */
167
+ #define GREATEST_SUITE(NAME) void NAME()
168
+
169
+ /* Start defining a test function.
170
+ * The arguments are not included, to allow parametric testing. */
171
+ #define GREATEST_TEST static int
172
+
173
+ /* Run a suite. */
174
+ #define GREATEST_RUN_SUITE(S_NAME) greatest_run_suite(S_NAME, #S_NAME)
175
+
176
+ /* Run a test in the current suite.
177
+ * If __VA_ARGS__ (C99) is supported, allow parametric testing. */
178
+ #if __STDC_VERSION__ >= 19901L
179
+ #define GREATEST_RUN_TESTp(TEST, ...) \
180
+ do { \
181
+ if (greatest_pre_test(#TEST) == 1) { \
182
+ int res = TEST(__VA_ARGS__); \
183
+ greatest_post_test(#TEST, res); \
184
+ } else if (greatest_info.list_only) { \
185
+ fprintf(GREATEST_STDOUT, " %s\n", #TEST); \
186
+ } \
187
+ } while (0)
188
+ #endif
189
+
190
+ #define GREATEST_RUN_TEST(TEST) \
191
+ do { \
192
+ if (greatest_pre_test(#TEST) == 1) { \
193
+ int res = TEST(); \
194
+ greatest_post_test(#TEST, res); \
195
+ } else if (greatest_info.list_only) { \
196
+ fprintf(GREATEST_STDOUT, " %s\n", #TEST); \
197
+ } \
198
+ } while (0)
199
+
200
+ /* Check if the test runner is in verbose mode. */
201
+ #define GREATEST_IS_VERBOSE() (greatest_info.verbose)
202
+
203
+ /* Message-less forms. */
204
+ #define GREATEST_PASS() GREATEST_PASSm(NULL)
205
+ #define GREATEST_FAIL() GREATEST_FAILm(NULL)
206
+ #define GREATEST_SKIP() GREATEST_SKIPm(NULL)
207
+ #define GREATEST_ASSERT(COND) GREATEST_ASSERTm(#COND, COND)
208
+ #define GREATEST_ASSERT_FALSE(COND) GREATEST_ASSERT_FALSEm(#COND, COND)
209
+ #define GREATEST_ASSERT_EQ(EXP, GOT) GREATEST_ASSERT_EQm(#EXP " != " #GOT, EXP, GOT)
210
+ #define GREATEST_ASSERT_STR_EQ(EXP, GOT) GREATEST_ASSERT_STR_EQm(#EXP " != " #GOT, EXP, GOT)
211
+
212
+ /* If set, call and clear the teardown callback. */
213
+ #define GREATEST_CALL_TEARDOWN() \
214
+ do { \
215
+ if (greatest_info.teardown) { \
216
+ greatest_info.teardown(greatest_info.teardown_udata); \
217
+ greatest_info.teardown = NULL; \
218
+ greatest_info.teardown_udata = NULL; \
219
+ } \
220
+ } while (0) \
221
+
222
+ /* The following forms take an additional message argument first,
223
+ * to be displayed by the test runner. */
224
+
225
+ /* Fail if a condition is not true, with message. */
226
+ #define GREATEST_ASSERTm(MSG, COND) \
227
+ do { \
228
+ greatest_info.msg = MSG; \
229
+ greatest_info.fail_file = __FILE__; \
230
+ greatest_info.fail_line = __LINE__; \
231
+ if (!(COND)) { \
232
+ GREATEST_CALL_TEARDOWN(); \
233
+ return -1; \
234
+ } \
235
+ greatest_info.msg = NULL; \
236
+ } while (0)
237
+
238
+ #define GREATEST_ASSERT_FALSEm(MSG, COND) \
239
+ do { \
240
+ greatest_info.msg = MSG; \
241
+ greatest_info.fail_file = __FILE__; \
242
+ greatest_info.fail_line = __LINE__; \
243
+ if ((COND)) { \
244
+ GREATEST_CALL_TEARDOWN(); \
245
+ return -1; \
246
+ } \
247
+ greatest_info.msg = NULL; \
248
+ } while (0)
249
+
250
+ #define GREATEST_ASSERT_EQm(MSG, EXP, GOT) \
251
+ do { \
252
+ greatest_info.msg = MSG; \
253
+ greatest_info.fail_file = __FILE__; \
254
+ greatest_info.fail_line = __LINE__; \
255
+ if ((EXP) != (GOT)) { \
256
+ GREATEST_CALL_TEARDOWN(); \
257
+ return -1; \
258
+ } \
259
+ greatest_info.msg = NULL; \
260
+ } while (0)
261
+
262
+ #define GREATEST_ASSERT_STR_EQm(MSG, EXP, GOT) \
263
+ do { \
264
+ char *exp_s = (EXP); \
265
+ char *got_s = (GOT); \
266
+ greatest_info.msg = MSG; \
267
+ greatest_info.fail_file = __FILE__; \
268
+ greatest_info.fail_line = __LINE__; \
269
+ if (0 != strcmp(exp_s, got_s)) { \
270
+ GREATEST_CALL_TEARDOWN(); \
271
+ fprintf(GREATEST_STDOUT, \
272
+ "Expected:\n####\n%s\n####\n", exp_s); \
273
+ fprintf(GREATEST_STDOUT, \
274
+ "Got:\n####\n%s\n####\n", got_s); \
275
+ return -1; \
276
+ } \
277
+ greatest_info.msg = NULL; \
278
+ } while (0)
279
+
280
+ #define GREATEST_PASSm(MSG) \
281
+ do { \
282
+ GREATEST_CALL_TEARDOWN(); \
283
+ greatest_info.msg = MSG; \
284
+ return 0; \
285
+ } while (0)
286
+
287
+ #define GREATEST_FAILm(MSG) \
288
+ do { \
289
+ GREATEST_CALL_TEARDOWN(); \
290
+ greatest_info.fail_file = __FILE__; \
291
+ greatest_info.fail_line = __LINE__; \
292
+ greatest_info.msg = MSG; \
293
+ return -1; \
294
+ } while (0)
295
+
296
+ #define GREATEST_SKIPm(MSG) \
297
+ do { \
298
+ GREATEST_CALL_TEARDOWN(); \
299
+ greatest_info.msg = MSG; \
300
+ return 1; \
301
+ } while (0)
302
+
303
+ #define GREATEST_SET_TIME(NAME) \
304
+ NAME = clock(); \
305
+ if (NAME == (clock_t) -1) { \
306
+ fprintf(GREATEST_STDOUT, \
307
+ "clock error: %s\n", #NAME); \
308
+ exit(EXIT_FAILURE); \
309
+ }
310
+
311
+ #define GREATEST_CLOCK_DIFF(C1, C2) \
312
+ fprintf(GREATEST_STDOUT, " (%lu ticks, %.3f sec)", \
313
+ (long unsigned int) (C2) - (C1), \
314
+ ((C2) - (C1))/ (1.0 * CLOCKS_PER_SEC)) \
315
+
316
+ /* Include several function definitions in the main test file. */
317
+ #define GREATEST_MAIN_DEFS() \
318
+ int greatest_pre_test(const char *name) { \
319
+ if (!greatest_info.list_only \
320
+ && (greatest_info.test_filter == NULL || \
321
+ 0 == strcmp(name, greatest_info.test_filter))) { \
322
+ GREATEST_SET_TIME(greatest_info.suite.pre_test); \
323
+ return 1; /* test should be run */ \
324
+ } else { \
325
+ return 0; /* skipped */ \
326
+ } \
327
+ } \
328
+ \
329
+ void greatest_post_test(const char *name, int res) { \
330
+ GREATEST_SET_TIME(greatest_info.suite.post_test); \
331
+ if (res < 0) { \
332
+ greatest_do_fail(name); \
333
+ } else if (res > 0) { \
334
+ greatest_do_skip(name); \
335
+ } else if (res == 0) { \
336
+ greatest_do_pass(name); \
337
+ } \
338
+ greatest_info.suite.tests_run++; \
339
+ greatest_info.col++; \
340
+ if (greatest_info.verbose) { \
341
+ GREATEST_CLOCK_DIFF(greatest_info.suite.pre_test, \
342
+ greatest_info.suite.post_test); \
343
+ fprintf(GREATEST_STDOUT, "\n"); \
344
+ } else if (greatest_info.col % greatest_info.width == 0) { \
345
+ fprintf(GREATEST_STDOUT, "\n"); \
346
+ greatest_info.col = 0; \
347
+ } \
348
+ if (GREATEST_STDOUT == stdout) fflush(stdout); \
349
+ } \
350
+ \
351
+ static void greatest_run_suite(greatest_suite_cb *suite_cb, \
352
+ char *suite_name) { \
353
+ if (greatest_info.suite_filter && \
354
+ 0 != strcmp(suite_name, greatest_info.suite_filter)) \
355
+ return; \
356
+ greatest_info.suite.tests_run = 0; \
357
+ greatest_info.suite.failed = 0; \
358
+ greatest_info.suite.passed = 0; \
359
+ greatest_info.suite.skipped = 0; \
360
+ greatest_info.suite.pre_suite = 0; \
361
+ greatest_info.suite.post_suite = 0; \
362
+ greatest_info.suite.pre_test = 0; \
363
+ greatest_info.suite.post_test = 0; \
364
+ greatest_info.col = 0; \
365
+ fprintf(GREATEST_STDOUT, "\n* Suite %s:\n", suite_name); \
366
+ GREATEST_SET_TIME(greatest_info.suite.pre_suite); \
367
+ suite_cb(); \
368
+ GREATEST_SET_TIME(greatest_info.suite.post_suite); \
369
+ if (greatest_info.suite.tests_run > 0) { \
370
+ fprintf(GREATEST_STDOUT, \
371
+ "\n%u tests - %u pass, %u fail, %u skipped", \
372
+ greatest_info.suite.tests_run, \
373
+ greatest_info.suite.passed, \
374
+ greatest_info.suite.failed, \
375
+ greatest_info.suite.skipped); \
376
+ GREATEST_CLOCK_DIFF(greatest_info.suite.pre_suite, \
377
+ greatest_info.suite.post_suite); \
378
+ fprintf(GREATEST_STDOUT, "\n"); \
379
+ } \
380
+ greatest_info.passed += greatest_info.suite.passed; \
381
+ greatest_info.failed += greatest_info.suite.failed; \
382
+ greatest_info.skipped += greatest_info.suite.skipped; \
383
+ greatest_info.tests_run += greatest_info.suite.tests_run; \
384
+ } \
385
+ \
386
+ void greatest_do_pass(const char *name) { \
387
+ if (greatest_info.verbose) { \
388
+ fprintf(GREATEST_STDOUT, "PASS %s: %s", \
389
+ name, greatest_info.msg ? greatest_info.msg : ""); \
390
+ } else { \
391
+ fprintf(GREATEST_STDOUT, "."); \
392
+ } \
393
+ greatest_info.suite.passed++; \
394
+ } \
395
+ \
396
+ void greatest_do_fail(const char *name) { \
397
+ if (greatest_info.verbose) { \
398
+ fprintf(GREATEST_STDOUT, \
399
+ "FAIL %s: %s (%s:%u)", \
400
+ name, greatest_info.msg ? greatest_info.msg : "", \
401
+ greatest_info.fail_file, greatest_info.fail_line); \
402
+ } else { \
403
+ fprintf(GREATEST_STDOUT, "F"); \
404
+ /* add linebreak if in line of '.'s */ \
405
+ if (greatest_info.col % greatest_info.width != 0) \
406
+ fprintf(GREATEST_STDOUT, "\n"); \
407
+ greatest_info.col = 0; \
408
+ fprintf(GREATEST_STDOUT, "FAIL %s: %s (%s:%u)\n", \
409
+ name, \
410
+ greatest_info.msg ? greatest_info.msg : "", \
411
+ greatest_info.fail_file, greatest_info.fail_line); \
412
+ } \
413
+ greatest_info.suite.failed++; \
414
+ } \
415
+ \
416
+ void greatest_do_skip(const char *name) { \
417
+ if (greatest_info.verbose) { \
418
+ fprintf(GREATEST_STDOUT, "SKIP %s: %s", \
419
+ name, \
420
+ greatest_info.msg ? \
421
+ greatest_info.msg : "" ); \
422
+ } else { \
423
+ fprintf(GREATEST_STDOUT, "s"); \
424
+ } \
425
+ greatest_info.suite.skipped++; \
426
+ } \
427
+ \
428
+ void greatest_usage(const char *name) { \
429
+ fprintf(GREATEST_STDOUT, \
430
+ "Usage: %s [-hlv] [-s SUITE] [-t TEST]\n" \
431
+ " -h print this Help\n" \
432
+ " -l List suites and their tests, then exit\n" \
433
+ " -v Verbose output\n" \
434
+ " -s SUITE only run suite named SUITE\n" \
435
+ " -t TEST only run test named TEST\n", \
436
+ name); \
437
+ } \
438
+ \
439
+ /* Set the teardown callback. \
440
+ * (Uppercase because it's part of the user interface.) */ \
441
+ void GREATEST_SET_TEARDOWN_CB(greatest_teardown_cb *cb, void *udata) { \
442
+ greatest_info.teardown = cb; \
443
+ greatest_info.teardown_udata = udata; \
444
+ } \
445
+ \
446
+ greatest_run_info greatest_info = {0, 0, 0, \
447
+ 0, 0, 0, \
448
+ {0, 0, 0, 0, \
449
+ 0, 0, 0, 0}, \
450
+ NULL, 0, NULL, NULL, NULL, \
451
+ 0, GREATEST_DEFAULT_WIDTH, \
452
+ NULL, NULL, \
453
+ 0, 0}
454
+
455
+ /* Handle command-line arguments, etc. */
456
+ #define GREATEST_MAIN_BEGIN() \
457
+ do { \
458
+ int i = 0; \
459
+ for (i = 1; i < argc; i++) { \
460
+ if (0 == strcmp("-t", argv[i])) { \
461
+ if (argc <= i + 1) { \
462
+ greatest_usage(argv[0]); \
463
+ exit(EXIT_FAILURE); \
464
+ } \
465
+ greatest_info.test_filter = argv[i+1]; \
466
+ i++; \
467
+ } else if (0 == strcmp("-s", argv[i])) { \
468
+ if (argc <= i + 1) { \
469
+ greatest_usage(argv[0]); \
470
+ exit(EXIT_FAILURE); \
471
+ } \
472
+ greatest_info.suite_filter = argv[i+1]; \
473
+ i++; \
474
+ } else if (0 == strcmp("-v", argv[i])) { \
475
+ greatest_info.verbose = 1; \
476
+ } else if (0 == strcmp("-l", argv[i])) { \
477
+ greatest_info.list_only = 1; \
478
+ } else if (0 == strcmp("-h", argv[i])) { \
479
+ greatest_usage(argv[0]); \
480
+ exit(EXIT_SUCCESS); \
481
+ } else { \
482
+ fprintf(GREATEST_STDOUT, \
483
+ "Unknown argument '%s'\n", argv[i]); \
484
+ greatest_usage(argv[0]); \
485
+ exit(EXIT_FAILURE); \
486
+ } \
487
+ } \
488
+ } while (0); \
489
+ GREATEST_SET_TIME(greatest_info.begin)
490
+
491
+ #define GREATEST_MAIN_END() \
492
+ do { \
493
+ if (!greatest_info.list_only) { \
494
+ GREATEST_SET_TIME(greatest_info.end); \
495
+ fprintf(GREATEST_STDOUT, \
496
+ "\nTotal: %u tests", greatest_info.tests_run); \
497
+ GREATEST_CLOCK_DIFF(greatest_info.begin, \
498
+ greatest_info.end); \
499
+ fprintf(GREATEST_STDOUT, "\n"); \
500
+ fprintf(GREATEST_STDOUT, \
501
+ "Pass: %u, fail: %u, skip: %u.\n", \
502
+ greatest_info.passed, \
503
+ greatest_info.failed, greatest_info.skipped); \
504
+ } \
505
+ return (greatest_info.failed > 0 \
506
+ ? EXIT_FAILURE : EXIT_SUCCESS); \
507
+ } while (0)
508
+
509
+ /* Make abbreviations without the GREATEST_ prefix for the
510
+ * most commonly used symbols. */
511
+ #if GREATEST_USE_ABBREVS
512
+ #define TEST GREATEST_TEST
513
+ #define SUITE GREATEST_SUITE
514
+ #define RUN_TEST GREATEST_RUN_TEST
515
+ #define RUN_SUITE GREATEST_RUN_SUITE
516
+ #define ASSERT GREATEST_ASSERT
517
+ #define ASSERTm GREATEST_ASSERTm
518
+ #define ASSERT_FALSE GREATEST_ASSERT_FALSE
519
+ #define ASSERT_EQ GREATEST_ASSERT_EQ
520
+ #define ASSERT_STR_EQ GREATEST_ASSERT_STR_EQ
521
+ #define ASSERT_FALSEm GREATEST_ASSERT_FALSEm
522
+ #define ASSERT_EQm GREATEST_ASSERT_EQm
523
+ #define ASSERT_STR_EQm GREATEST_ASSERT_STR_EQm
524
+ #define PASS GREATEST_PASS
525
+ #define FAIL GREATEST_FAIL
526
+ #define SKIP GREATEST_SKIP
527
+ #define PASSm GREATEST_PASSm
528
+ #define FAILm GREATEST_FAILm
529
+ #define SKIPm GREATEST_SKIPm
530
+
531
+ #if __STDC_VERSION__ >= 19901L
532
+ #endif /* C99 */
533
+ #define RUN_TESTp GREATEST_RUN_TESTp
534
+ #endif /* USE_ABBREVS */
535
+
536
+ #endif