mathematical 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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"