mathematical 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/Rakefile +4 -0
  4. data/ext/mathematical/extconf.rb +9 -15
  5. data/ext/mathematical/mtex2MML/build/mtex2MML.h +73 -0
  6. data/ext/mathematical/mtex2MML/{src/deps → deps}/uthash/utarray.h +0 -0
  7. data/ext/mathematical/mtex2MML/{src/deps → deps}/uthash/uthash.h +0 -0
  8. data/ext/mathematical/mtex2MML/{src/deps → deps}/uthash/utlist.h +0 -0
  9. data/ext/mathematical/mtex2MML/{src/deps → deps}/uthash/utstring.h +0 -0
  10. data/ext/mathematical/mtex2MML/src/color_definitions.c +1 -1
  11. data/ext/mathematical/mtex2MML/src/lex.yy.c +1100 -1098
  12. data/ext/mathematical/mtex2MML/src/main.c +137 -0
  13. data/ext/mathematical/mtex2MML/src/mtex2MML.h +11 -1
  14. data/ext/mathematical/mtex2MML/src/parse_extras.c +2 -2
  15. data/ext/mathematical/mtex2MML/src/parse_extras.h +36 -36
  16. data/ext/mathematical/mtex2MML/src/string_extras.c +0 -6
  17. data/ext/mathematical/mtex2MML/src/string_extras.h +1 -1
  18. data/ext/mathematical/mtex2MML/src/y.tab.c +3904 -3583
  19. data/ext/mathematical/mtex2MML/tests/array.c +127 -0
  20. data/ext/mathematical/mtex2MML/tests/basic.c +85 -0
  21. data/ext/mathematical/mtex2MML/tests/clar.c +642 -0
  22. data/ext/mathematical/mtex2MML/tests/clar.h +163 -0
  23. data/ext/mathematical/mtex2MML/tests/clar/fixtures.h +38 -0
  24. data/ext/mathematical/mtex2MML/tests/clar/fs.h +333 -0
  25. data/ext/mathematical/mtex2MML/tests/clar/print.h +66 -0
  26. data/ext/mathematical/mtex2MML/tests/clar/sandbox.h +139 -0
  27. data/ext/mathematical/mtex2MML/tests/clar_test.h +20 -0
  28. data/ext/mathematical/mtex2MML/tests/cornercases.c +45 -0
  29. data/ext/mathematical/mtex2MML/tests/deps/file2str/file2str.c +64 -0
  30. data/ext/mathematical/mtex2MML/tests/deps/file2str/file2str.h +12 -0
  31. data/ext/mathematical/mtex2MML/tests/deps/trim/trim.c +24 -0
  32. data/ext/mathematical/mtex2MML/tests/deps/trim/trim.h +7 -0
  33. data/ext/mathematical/mtex2MML/tests/env.c +333 -0
  34. data/ext/mathematical/mtex2MML/tests/functions.c +45 -0
  35. data/ext/mathematical/mtex2MML/tests/helpers.c +27 -0
  36. data/ext/mathematical/mtex2MML/tests/helpers.h +8 -0
  37. data/ext/mathematical/mtex2MML/tests/main.c +35 -0
  38. data/ext/mathematical/mtex2MML/tests/maliciousness.c +82 -0
  39. data/ext/mathematical/mtex2MML/tests/mathjax.c +2030 -0
  40. data/ext/mathematical/mtex2MML/tests/numbered_equations.c +47 -0
  41. data/lib/mathematical.rb +3 -48
  42. data/lib/mathematical/validator.rb +52 -0
  43. data/lib/mathematical/version.rb +1 -1
  44. data/test/mathematical/basic_test.rb +7 -0
  45. data/test/mathematical/maliciousness_test.rb +26 -1
  46. data/test/mathematical/mathjax_test.rb +2 -2
  47. metadata +31 -7
  48. data/ext/mathematical/mtex2MML/ext/extconf.rb +0 -4
@@ -0,0 +1,127 @@
1
+ #include "clar.h"
2
+ #include "clar_test.h"
3
+ #include <stdio.h>
4
+ #include <string.h>
5
+
6
+ static char *fixture_tex;
7
+ static char *fixture_mml;
8
+ static char *result;
9
+
10
+ void test_array__initialize(void)
11
+ {
12
+ global_test_counter++;
13
+ }
14
+
15
+ void test_array__cleanup(void)
16
+ {
17
+ if (fixture_tex != NULL) {
18
+ free(fixture_tex);
19
+ }
20
+
21
+ if (fixture_mml != NULL) {
22
+ free(fixture_mml);
23
+ }
24
+
25
+ if (result != NULL) {
26
+ free(result);
27
+ }
28
+ }
29
+
30
+ void test_array__basic_array(void)
31
+ {
32
+ fixture_tex = read_fixture_tex("array/basic_array.txt");
33
+ fixture_mml = read_fixture_mml("array/basic_array.html");
34
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
35
+
36
+ cl_assert_equal_s(fixture_mml, result);
37
+ }
38
+
39
+ void test_array__array_with_hline(void)
40
+ {
41
+ fixture_tex = read_fixture_tex("array/array_with_hline.txt");
42
+ fixture_mml = read_fixture_mml("array/array_with_hline.html");
43
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
44
+
45
+ cl_assert_equal_s(fixture_mml, result);
46
+ }
47
+
48
+ void test_array__array_with_hline_and_hdashline(void)
49
+ {
50
+ fixture_tex = read_fixture_tex("array/array_with_hline_and_hdashline.txt");
51
+ fixture_mml = read_fixture_mml("array/array_with_hline_and_hdashline.html");
52
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
53
+
54
+ cl_assert_equal_s(fixture_mml, result);
55
+ }
56
+
57
+ void test_array__array_pos_alignment(void)
58
+ {
59
+ fixture_tex = read_fixture_tex("array/array_pos_alignment.txt");
60
+ fixture_mml = read_fixture_mml("array/array_pos_alignment.html");
61
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
62
+
63
+ cl_assert_equal_s(fixture_mml, result);
64
+ }
65
+
66
+ void test_array__array_pos_alignment_with_hline(void)
67
+ {
68
+ fixture_tex = read_fixture_tex("array/array_pos_alignment_with_hline.txt");
69
+ fixture_mml = read_fixture_mml("array/array_pos_alignment_with_hline.html");
70
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
71
+
72
+ cl_assert_equal_s(fixture_mml, result);
73
+ }
74
+
75
+ void test_array__array_vertical_column(void)
76
+ {
77
+ fixture_tex = read_fixture_tex("array/array_vertical_column.txt");
78
+ fixture_mml = read_fixture_mml("array/array_vertical_column.html");
79
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
80
+
81
+ cl_assert_equal_s(fixture_mml, result);
82
+ }
83
+
84
+ void test_array__array_vertical_column_with_align(void)
85
+ {
86
+ fixture_tex = read_fixture_tex("array/array_vertical_column_with_align.txt");
87
+ fixture_mml = read_fixture_mml("array/array_vertical_column_with_align.html");
88
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
89
+
90
+ cl_assert_equal_s(fixture_mml, result);
91
+ }
92
+
93
+ void test_array__array_with_vertical_and_horizontal_dashes(void)
94
+ {
95
+ fixture_tex = read_fixture_tex("array/array_with_vertical_and_horizontal_dashes.txt");
96
+ fixture_mml = read_fixture_mml("array/array_with_vertical_and_horizontal_dashes.html");
97
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
98
+
99
+ cl_assert_equal_s(fixture_mml, result);
100
+ }
101
+
102
+ void test_array__array_nesting(void)
103
+ {
104
+ fixture_tex = read_fixture_tex("array/array_nesting.txt");
105
+ fixture_mml = read_fixture_mml("array/array_nesting.html");
106
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
107
+
108
+ cl_assert_equal_s(fixture_mml, result);
109
+ }
110
+
111
+ void test_array__strip_excess_whitespace_in_array_attributes(void)
112
+ {
113
+ fixture_tex = read_fixture_tex("array/strip_excess_whitespace_in_array_attributes.txt");
114
+ fixture_mml = read_fixture_mml("array/strip_excess_whitespace_in_array_attributes.html");
115
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
116
+
117
+ cl_assert_equal_s(fixture_mml, result);
118
+ }
119
+
120
+ void test_array__augmented_matrix(void)
121
+ {
122
+ fixture_tex = read_fixture_tex("array/augmented_matrix.txt");
123
+ fixture_mml = read_fixture_mml("array/augmented_matrix.html");
124
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
125
+
126
+ cl_assert_equal_s(fixture_mml, result);
127
+ }
@@ -0,0 +1,85 @@
1
+ #include "clar.h"
2
+ #include "clar_test.h"
3
+ #include "deps/trim/trim.h"
4
+ #include <stdio.h>
5
+
6
+ static char *fixture_tex;
7
+ static char *fixture_mml;
8
+ static char *result;
9
+
10
+ void test_basic__initialize(void)
11
+ {
12
+ global_test_counter++;
13
+ }
14
+
15
+ void test_basic__cleanup(void)
16
+ {
17
+ if (fixture_tex != NULL) {
18
+ free(fixture_tex);
19
+ }
20
+
21
+ if (fixture_mml != NULL) {
22
+ free(fixture_mml);
23
+ }
24
+
25
+ if (result != NULL) {
26
+ free(result);
27
+ }
28
+ }
29
+
30
+ void test_basic__inline(void)
31
+ {
32
+ fixture_tex = read_fixture_tex("basic/inline.txt");
33
+ fixture_mml = read_fixture_mml("basic/inline.html");
34
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
35
+
36
+ cl_assert_equal_s(fixture_mml, result);
37
+ }
38
+
39
+ void test_basic__block(void)
40
+ {
41
+ fixture_tex = read_fixture_tex("basic/block.txt");
42
+ fixture_mml = read_fixture_mml("basic/block.html");
43
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
44
+
45
+ cl_assert_equal_s(fixture_mml, result);
46
+ }
47
+
48
+ void test_basic__comments(void)
49
+ {
50
+ fixture_tex = read_fixture_tex("basic/comments.txt");
51
+ fixture_mml = read_fixture_mml("basic/comments.html");
52
+ result = mtex2MML_parse(fixture_tex, strlen(fixture_tex));
53
+
54
+ cl_assert_equal_s(fixture_mml, result);
55
+ }
56
+
57
+ void test_basic__filter(void)
58
+ {
59
+ fixture_tex = read_fixture_tex("basic/filter.txt");
60
+ fixture_mml = read_fixture_mml("basic/filter.html");
61
+ int status = mtex2MML_filter(fixture_tex, strlen(fixture_tex));
62
+ result = mtex2MML_output();
63
+
64
+ cl_assert_equal_s(fixture_mml, result);
65
+ }
66
+
67
+ void test_basic__html_filter(void)
68
+ {
69
+ fixture_tex = read_fixture_tex("basic/html_filter.txt");
70
+ fixture_mml = read_fixture_mml("basic/html_filter.html");
71
+ mtex2MML_html_filter(fixture_tex, strlen(fixture_tex));
72
+ result = mtex2MML_output();
73
+
74
+ cl_assert_equal_s(fixture_mml, trim(result));
75
+ }
76
+
77
+ void test_basic__strict_html_filter(void)
78
+ {
79
+ fixture_tex = read_fixture_tex("basic/strict_html_filter.txt");
80
+ fixture_mml = read_fixture_mml("basic/strict_html_filter.html");
81
+ mtex2MML_strict_html_filter(fixture_tex, strlen(fixture_tex));
82
+ result = mtex2MML_output();
83
+
84
+ cl_assert_equal_s(fixture_mml, trim(result));
85
+ }
@@ -0,0 +1,642 @@
1
+ /*
2
+ * Copyright (c) Vicent Marti. All rights reserved.
3
+ *
4
+ * This file is part of clar, distributed under the ISC license.
5
+ * For full terms see the included COPYING file.
6
+ */
7
+ #include <assert.h>
8
+ #include <setjmp.h>
9
+ #include <stdlib.h>
10
+ #include <stdio.h>
11
+ #include <string.h>
12
+ #include <math.h>
13
+ #include <stdarg.h>
14
+ #include <wchar.h>
15
+
16
+ /* required for sandboxing */
17
+ #include <sys/types.h>
18
+ #include <sys/stat.h>
19
+
20
+ #ifdef _WIN32
21
+ # include <windows.h>
22
+ # include <io.h>
23
+ # include <shellapi.h>
24
+ # include <direct.h>
25
+
26
+ # define _MAIN_CC __cdecl
27
+
28
+ # ifndef stat
29
+ # define stat(path, st) _stat(path, st)
30
+ # endif
31
+ # ifndef mkdir
32
+ # define mkdir(path, mode) _mkdir(path)
33
+ # endif
34
+ # ifndef chdir
35
+ # define chdir(path) _chdir(path)
36
+ # endif
37
+ # ifndef access
38
+ # define access(path, mode) _access(path, mode)
39
+ # endif
40
+ # ifndef strdup
41
+ # define strdup(str) _strdup(str)
42
+ # endif
43
+ # ifndef strcasecmp
44
+ # define strcasecmp(a,b) _stricmp(a,b)
45
+ # endif
46
+
47
+ # ifndef __MINGW32__
48
+ # pragma comment(lib, "shell32")
49
+ # ifndef strncpy
50
+ # define strncpy(to, from, to_size) strncpy_s(to, to_size, from, _TRUNCATE)
51
+ # endif
52
+ # ifndef W_OK
53
+ # define W_OK 02
54
+ # endif
55
+ # ifndef S_ISDIR
56
+ # define S_ISDIR(x) ((x & _S_IFDIR) != 0)
57
+ # endif
58
+ # define p_snprintf(buf,sz,fmt,...) _snprintf_s(buf,sz,_TRUNCATE,fmt,__VA_ARGS__)
59
+ # else
60
+ # define p_snprintf snprintf
61
+ # endif
62
+
63
+ # ifndef PRIuZ
64
+ # define PRIuZ "Iu"
65
+ # endif
66
+ # ifndef PRIxZ
67
+ # define PRIxZ "Ix"
68
+ # endif
69
+
70
+ # ifdef _MSC_VER
71
+ typedef struct stat STAT_T;
72
+ # else
73
+ typedef struct _stat STAT_T;
74
+ # endif
75
+ #else
76
+ # include <sys/wait.h> /* waitpid(2) */
77
+ # include <unistd.h>
78
+ # define _MAIN_CC
79
+ # define p_snprintf snprintf
80
+ # ifndef PRIuZ
81
+ # define PRIuZ "zu"
82
+ # endif
83
+ # ifndef PRIxZ
84
+ # define PRIxZ "zx"
85
+ # endif
86
+ typedef struct stat STAT_T;
87
+ #endif
88
+
89
+ #include "clar.h"
90
+
91
+ static void fs_rm(const char *_source);
92
+ static void fs_copy(const char *_source, const char *dest);
93
+
94
+ static const char *
95
+ fixture_path(const char *base, const char *fixture_name);
96
+
97
+ struct clar_error {
98
+ const char *test;
99
+ int test_number;
100
+ const char *suite;
101
+ const char *file;
102
+ int line_number;
103
+ const char *error_msg;
104
+ char *description;
105
+
106
+ struct clar_error *next;
107
+ };
108
+
109
+ static struct {
110
+ int argc;
111
+ char **argv;
112
+
113
+ enum cl_test_status test_status;
114
+ const char *active_test;
115
+ const char *active_suite;
116
+
117
+ int total_skipped;
118
+ int total_errors;
119
+
120
+ int tests_ran;
121
+ int suites_ran;
122
+
123
+ int report_errors_only;
124
+ int exit_on_error;
125
+ int report_suite_names;
126
+
127
+ struct clar_error *errors;
128
+ struct clar_error *last_error;
129
+
130
+ void (*local_cleanup)(void *);
131
+ void *local_cleanup_payload;
132
+
133
+ jmp_buf trampoline;
134
+ int trampoline_enabled;
135
+
136
+ cl_trace_cb *pfn_trace_cb;
137
+ void *trace_payload;
138
+
139
+ } _clar;
140
+
141
+ struct clar_func {
142
+ const char *name;
143
+ void (*ptr)(void);
144
+ };
145
+
146
+ struct clar_suite {
147
+ const char *name;
148
+ struct clar_func initialize;
149
+ struct clar_func cleanup;
150
+ const struct clar_func *tests;
151
+ size_t test_count;
152
+ int enabled;
153
+ };
154
+
155
+ /* From clar_print_*.c */
156
+ static void clar_print_init(int test_count, int suite_count, const char *suite_names);
157
+ static void clar_print_shutdown(int test_count, int suite_count, int error_count);
158
+ static void clar_print_error(int num, const struct clar_error *error);
159
+ static void clar_print_ontest(const char *test_name, int test_number, enum cl_test_status failed);
160
+ static void clar_print_onsuite(const char *suite_name, int suite_index);
161
+ static void clar_print_onabort(const char *msg, ...);
162
+
163
+ /* From clar_sandbox.c */
164
+ static void clar_unsandbox(void);
165
+ static int clar_sandbox(void);
166
+
167
+ /* Load the declarations for the test suite */
168
+ #include "clar.suite"
169
+
170
+
171
+ #define CL_TRACE(ev) \
172
+ do { \
173
+ if (_clar.pfn_trace_cb) \
174
+ _clar.pfn_trace_cb(ev, \
175
+ _clar.active_suite, \
176
+ _clar.active_test, \
177
+ _clar.trace_payload); \
178
+ } while (0)
179
+
180
+ void cl_trace_register(cl_trace_cb *cb, void *payload)
181
+ {
182
+ _clar.pfn_trace_cb = cb;
183
+ _clar.trace_payload = payload;
184
+ }
185
+
186
+
187
+ /* Core test functions */
188
+ static void
189
+ clar_report_errors(void)
190
+ {
191
+ int i = 1;
192
+ struct clar_error *error, *next;
193
+
194
+ error = _clar.errors;
195
+ while (error != NULL) {
196
+ next = error->next;
197
+ clar_print_error(i++, error);
198
+ free(error->description);
199
+ free(error);
200
+ error = next;
201
+ }
202
+
203
+ _clar.errors = _clar.last_error = NULL;
204
+ }
205
+
206
+ static void
207
+ clar_run_test(
208
+ const struct clar_func *test,
209
+ const struct clar_func *initialize,
210
+ const struct clar_func *cleanup)
211
+ {
212
+ _clar.test_status = CL_TEST_OK;
213
+ _clar.trampoline_enabled = 1;
214
+
215
+ CL_TRACE(CL_TRACE__TEST__BEGIN);
216
+
217
+ if (setjmp(_clar.trampoline) == 0) {
218
+ if (initialize->ptr != NULL)
219
+ initialize->ptr();
220
+
221
+ CL_TRACE(CL_TRACE__TEST__RUN_BEGIN);
222
+ test->ptr();
223
+ CL_TRACE(CL_TRACE__TEST__RUN_END);
224
+ }
225
+
226
+ _clar.trampoline_enabled = 0;
227
+
228
+ if (_clar.local_cleanup != NULL)
229
+ _clar.local_cleanup(_clar.local_cleanup_payload);
230
+
231
+ if (cleanup->ptr != NULL)
232
+ cleanup->ptr();
233
+
234
+ CL_TRACE(CL_TRACE__TEST__END);
235
+
236
+ _clar.tests_ran++;
237
+
238
+ /* remove any local-set cleanup methods */
239
+ _clar.local_cleanup = NULL;
240
+ _clar.local_cleanup_payload = NULL;
241
+
242
+ if (_clar.report_errors_only) {
243
+ clar_report_errors();
244
+ } else {
245
+ clar_print_ontest(test->name, _clar.tests_ran, _clar.test_status);
246
+ }
247
+ }
248
+
249
+ static void
250
+ clar_run_suite(const struct clar_suite *suite, const char *filter)
251
+ {
252
+ const struct clar_func *test = suite->tests;
253
+ size_t i, matchlen;
254
+
255
+ if (!suite->enabled)
256
+ return;
257
+
258
+ if (_clar.exit_on_error && _clar.total_errors)
259
+ return;
260
+
261
+ if (!_clar.report_errors_only)
262
+ clar_print_onsuite(suite->name, ++_clar.suites_ran);
263
+
264
+ _clar.active_suite = suite->name;
265
+ _clar.active_test = NULL;
266
+ CL_TRACE(CL_TRACE__SUITE_BEGIN);
267
+
268
+ if (filter) {
269
+ size_t suitelen = strlen(suite->name);
270
+ matchlen = strlen(filter);
271
+ if (matchlen <= suitelen) {
272
+ filter = NULL;
273
+ } else {
274
+ filter += suitelen;
275
+ while (*filter == ':')
276
+ ++filter;
277
+ matchlen = strlen(filter);
278
+ }
279
+ }
280
+
281
+ for (i = 0; i < suite->test_count; ++i) {
282
+ if (filter && strncmp(test[i].name, filter, matchlen))
283
+ continue;
284
+
285
+ _clar.active_test = test[i].name;
286
+ clar_run_test(&test[i], &suite->initialize, &suite->cleanup);
287
+
288
+ if (_clar.exit_on_error && _clar.total_errors)
289
+ return;
290
+ }
291
+
292
+ _clar.active_test = NULL;
293
+ CL_TRACE(CL_TRACE__SUITE_END);
294
+ }
295
+
296
+ static void
297
+ clar_usage(const char *arg)
298
+ {
299
+ printf("Usage: %s [options]\n\n", arg);
300
+ printf("Options:\n");
301
+ printf(" -sname\tRun only the suite with `name` (can go to individual test name)\n");
302
+ printf(" -iname\tInclude the suite with `name`\n");
303
+ printf(" -xname\tExclude the suite with `name`\n");
304
+ printf(" -v \tIncrease verbosity (show suite names)\n");
305
+ printf(" -q \tOnly report tests that had an error\n");
306
+ printf(" -Q \tQuit as soon as a test fails\n");
307
+ printf(" -l \tPrint suite names\n");
308
+ exit(-1);
309
+ }
310
+
311
+ static void
312
+ clar_parse_args(int argc, char **argv)
313
+ {
314
+ int i;
315
+
316
+ for (i = 1; i < argc; ++i) {
317
+ char *argument = argv[i];
318
+
319
+ if (argument[0] != '-')
320
+ clar_usage(argv[0]);
321
+
322
+ switch (argument[1]) {
323
+ case 's':
324
+ case 'i':
325
+ case 'x': { /* given suite name */
326
+ int offset = (argument[2] == '=') ? 3 : 2, found = 0;
327
+ char action = argument[1];
328
+ size_t j, arglen, suitelen, cmplen;
329
+
330
+ argument += offset;
331
+ arglen = strlen(argument);
332
+
333
+ if (arglen == 0)
334
+ clar_usage(argv[0]);
335
+
336
+ for (j = 0; j < _clar_suite_count; ++j) {
337
+ suitelen = strlen(_clar_suites[j].name);
338
+ cmplen = (arglen < suitelen) ? arglen : suitelen;
339
+
340
+ if (strncmp(argument, _clar_suites[j].name, cmplen) == 0) {
341
+ int exact = (arglen >= suitelen);
342
+
343
+ ++found;
344
+
345
+ if (!exact)
346
+ _clar.report_suite_names = 1;
347
+
348
+ switch (action) {
349
+ case 's': _clar_suites[j].enabled = 1; clar_run_suite(&_clar_suites[j], argument); break;
350
+ case 'i': _clar_suites[j].enabled = 1; break;
351
+ case 'x': _clar_suites[j].enabled = 0; break;
352
+ }
353
+
354
+ if (exact)
355
+ break;
356
+ }
357
+ }
358
+
359
+ if (!found) {
360
+ clar_print_onabort("No suite matching '%s' found.\n", argument);
361
+ exit(-1);
362
+ }
363
+ break;
364
+ }
365
+
366
+ case 'q':
367
+ _clar.report_errors_only = 1;
368
+ break;
369
+
370
+ case 'Q':
371
+ _clar.exit_on_error = 1;
372
+ break;
373
+
374
+ case 'l': {
375
+ size_t j;
376
+ printf("Test suites (use -s<name> to run just one):\n");
377
+ for (j = 0; j < _clar_suite_count; ++j)
378
+ printf(" %3d: %s\n", (int)j, _clar_suites[j].name);
379
+
380
+ exit(0);
381
+ }
382
+
383
+ case 'v':
384
+ _clar.report_suite_names = 1;
385
+ break;
386
+
387
+ default:
388
+ clar_usage(argv[0]);
389
+ }
390
+ }
391
+ }
392
+
393
+ void
394
+ clar_test_init(int argc, char **argv)
395
+ {
396
+ clar_print_init(
397
+ (int)_clar_callback_count,
398
+ (int)_clar_suite_count,
399
+ ""
400
+ );
401
+
402
+ if (clar_sandbox() < 0) {
403
+ clar_print_onabort("Failed to sandbox the test runner.\n");
404
+ exit(-1);
405
+ }
406
+
407
+ _clar.argc = argc;
408
+ _clar.argv = argv;
409
+ }
410
+
411
+ int
412
+ clar_test_run()
413
+ {
414
+ if (_clar.argc > 1)
415
+ clar_parse_args(_clar.argc, _clar.argv);
416
+
417
+ if (!_clar.suites_ran) {
418
+ size_t i;
419
+ for (i = 0; i < _clar_suite_count; ++i)
420
+ clar_run_suite(&_clar_suites[i], NULL);
421
+ }
422
+
423
+ return _clar.total_errors;
424
+ }
425
+
426
+ void
427
+ clar_test_shutdown()
428
+ {
429
+ clar_print_shutdown(
430
+ _clar.tests_ran,
431
+ (int)_clar_suite_count,
432
+ _clar.total_errors
433
+ );
434
+
435
+ clar_unsandbox();
436
+ }
437
+
438
+ int
439
+ clar_test(int argc, char **argv)
440
+ {
441
+ int errors;
442
+
443
+ clar_test_init(argc, argv);
444
+ errors = clar_test_run();
445
+ clar_test_shutdown();
446
+
447
+ return errors;
448
+ }
449
+
450
+ static void abort_test(void)
451
+ {
452
+ if (!_clar.trampoline_enabled) {
453
+ clar_print_onabort(
454
+ "Fatal error: a cleanup method raised an exception.");
455
+ clar_report_errors();
456
+ exit(-1);
457
+ }
458
+
459
+ CL_TRACE(CL_TRACE__TEST__LONGJMP);
460
+ longjmp(_clar.trampoline, -1);
461
+ }
462
+
463
+ void clar__skip(void)
464
+ {
465
+ _clar.test_status = CL_TEST_SKIP;
466
+ _clar.total_skipped++;
467
+ abort_test();
468
+ }
469
+
470
+ void clar__fail(
471
+ const char *file,
472
+ int line,
473
+ const char *error_msg,
474
+ const char *description,
475
+ int should_abort)
476
+ {
477
+ struct clar_error *error = calloc(1, sizeof(struct clar_error));
478
+
479
+ if (_clar.errors == NULL)
480
+ _clar.errors = error;
481
+
482
+ if (_clar.last_error != NULL)
483
+ _clar.last_error->next = error;
484
+
485
+ _clar.last_error = error;
486
+
487
+ error->test = _clar.active_test;
488
+ error->test_number = _clar.tests_ran;
489
+ error->suite = _clar.active_suite;
490
+ error->file = file;
491
+ error->line_number = line;
492
+ error->error_msg = error_msg;
493
+
494
+ if (description != NULL)
495
+ error->description = strdup(description);
496
+
497
+ _clar.total_errors++;
498
+ _clar.test_status = CL_TEST_FAILURE;
499
+
500
+ if (should_abort)
501
+ abort_test();
502
+ }
503
+
504
+ void clar__assert(
505
+ int condition,
506
+ const char *file,
507
+ int line,
508
+ const char *error_msg,
509
+ const char *description,
510
+ int should_abort)
511
+ {
512
+ if (condition)
513
+ return;
514
+
515
+ clar__fail(file, line, error_msg, description, should_abort);
516
+ }
517
+
518
+ void clar__assert_equal(
519
+ const char *file,
520
+ int line,
521
+ const char *err,
522
+ int should_abort,
523
+ const char *fmt,
524
+ ...)
525
+ {
526
+ va_list args;
527
+ char buf[4096];
528
+ int is_equal = 1;
529
+
530
+ va_start(args, fmt);
531
+
532
+ if (!strcmp("%s", fmt)) {
533
+ const char *s1 = va_arg(args, const char *);
534
+ const char *s2 = va_arg(args, const char *);
535
+ is_equal = (!s1 || !s2) ? (s1 == s2) : !strcmp(s1, s2);
536
+
537
+ if (!is_equal) {
538
+ if (s1 && s2) {
539
+ int pos;
540
+ for (pos = 0; s1[pos] == s2[pos] && s1[pos] && s2[pos]; ++pos)
541
+ /* find differing byte offset */;
542
+ p_snprintf(buf, sizeof(buf), "'%s' != '%s' (at byte %d)",
543
+ s1, s2, pos);
544
+ } else {
545
+ p_snprintf(buf, sizeof(buf), "'%s' != '%s'", s1, s2);
546
+ }
547
+ }
548
+ }
549
+ else if(!strcmp("%.*s", fmt)) {
550
+ const char *s1 = va_arg(args, const char *);
551
+ const char *s2 = va_arg(args, const char *);
552
+ int len = va_arg(args, int);
553
+ is_equal = (!s1 || !s2) ? (s1 == s2) : !strncmp(s1, s2, len);
554
+
555
+ if (!is_equal) {
556
+ if (s1 && s2) {
557
+ int pos;
558
+ for (pos = 0; s1[pos] == s2[pos] && pos < len; ++pos)
559
+ /* find differing byte offset */;
560
+ p_snprintf(buf, sizeof(buf), "'%.*s' != '%.*s' (at byte %d)",
561
+ len, s1, len, s2, pos);
562
+ } else {
563
+ p_snprintf(buf, sizeof(buf), "'%.*s' != '%.*s'", len, s1, len, s2);
564
+ }
565
+ }
566
+ }
567
+ else if (!strcmp("%ls", fmt)) {
568
+ const wchar_t *wcs1 = va_arg(args, const wchar_t *);
569
+ const wchar_t *wcs2 = va_arg(args, const wchar_t *);
570
+ is_equal = (!wcs1 || !wcs2) ? (wcs1 == wcs2) : !wcscmp(wcs1, wcs2);
571
+
572
+ if (!is_equal) {
573
+ if (wcs1 && wcs2) {
574
+ int pos;
575
+ for (pos = 0; wcs1[pos] == wcs2[pos] && wcs1[pos] && wcs2[pos]; ++pos)
576
+ /* find differing byte offset */;
577
+ p_snprintf(buf, sizeof(buf), "'%ls' != '%ls' (at byte %d)",
578
+ wcs1, wcs2, pos);
579
+ } else {
580
+ p_snprintf(buf, sizeof(buf), "'%ls' != '%ls'", wcs1, wcs2);
581
+ }
582
+ }
583
+ }
584
+ else if(!strcmp("%.*ls", fmt)) {
585
+ const wchar_t *wcs1 = va_arg(args, const wchar_t *);
586
+ const wchar_t *wcs2 = va_arg(args, const wchar_t *);
587
+ int len = va_arg(args, int);
588
+ is_equal = (!wcs1 || !wcs2) ? (wcs1 == wcs2) : !wcsncmp(wcs1, wcs2, len);
589
+
590
+ if (!is_equal) {
591
+ if (wcs1 && wcs2) {
592
+ int pos;
593
+ for (pos = 0; wcs1[pos] == wcs2[pos] && pos < len; ++pos)
594
+ /* find differing byte offset */;
595
+ p_snprintf(buf, sizeof(buf), "'%.*ls' != '%.*ls' (at byte %d)",
596
+ len, wcs1, len, wcs2, pos);
597
+ } else {
598
+ p_snprintf(buf, sizeof(buf), "'%.*ls' != '%.*ls'", len, wcs1, len, wcs2);
599
+ }
600
+ }
601
+ }
602
+ else if (!strcmp("%"PRIuZ, fmt) || !strcmp("%"PRIxZ, fmt)) {
603
+ size_t sz1 = va_arg(args, size_t), sz2 = va_arg(args, size_t);
604
+ is_equal = (sz1 == sz2);
605
+ if (!is_equal) {
606
+ int offset = p_snprintf(buf, sizeof(buf), fmt, sz1);
607
+ strncat(buf, " != ", sizeof(buf) - offset);
608
+ p_snprintf(buf + offset + 4, sizeof(buf) - offset - 4, fmt, sz2);
609
+ }
610
+ }
611
+ else if (!strcmp("%p", fmt)) {
612
+ void *p1 = va_arg(args, void *), *p2 = va_arg(args, void *);
613
+ is_equal = (p1 == p2);
614
+ if (!is_equal)
615
+ p_snprintf(buf, sizeof(buf), "%p != %p", p1, p2);
616
+ }
617
+ else {
618
+ int i1 = va_arg(args, int), i2 = va_arg(args, int);
619
+ is_equal = (i1 == i2);
620
+ if (!is_equal) {
621
+ int offset = p_snprintf(buf, sizeof(buf), fmt, i1);
622
+ strncat(buf, " != ", sizeof(buf) - offset);
623
+ p_snprintf(buf + offset + 4, sizeof(buf) - offset - 4, fmt, i2);
624
+ }
625
+ }
626
+
627
+ va_end(args);
628
+
629
+ if (!is_equal)
630
+ clar__fail(file, line, err, buf, should_abort);
631
+ }
632
+
633
+ void cl_set_cleanup(void (*cleanup)(void *), void *opaque)
634
+ {
635
+ _clar.local_cleanup = cleanup;
636
+ _clar.local_cleanup_payload = opaque;
637
+ }
638
+
639
+ #include "clar/sandbox.h"
640
+ #include "clar/fixtures.h"
641
+ #include "clar/fs.h"
642
+ #include "clar/print.h"