libose
Loading...
Searching...
No Matches
test
ose_test
ose_test_unit.h
Go to the documentation of this file.
1
/*
2
Copyright (c) 2020-23 John MacCallum Permission is hereby granted,
3
free of charge, to any person obtaining a copy of this software
4
and associated documentation files (the "Software"), to deal in
5
the Software without restriction, including without limitation the
6
rights to use, copy, modify, merge, publish, distribute,
7
sublicense, and/or sell copies of the Software, and to permit
8
persons to whom the Software is furnished to do so, subject to the
9
following conditions:
10
11
The above copyright notice and this permission notice shall be
12
included in all copies or substantial portions of the Software.
13
14
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
DEALINGS IN THE SOFTWARE.
22
*/
23
60
#include "ose_test_bundle_literal.h"
61
#include "ose_test_vm_literal.h"
62
73
#define UNIT_TEST_FUNCTION(fn) TEST_FUNCTION(ut_, fn)
74
85
#define SKIP_UNIT_TEST_FUNCTION(fn) SKIP_TEST_FUNCTION(fn)
86
95
void
printb
(
const
char
*
const
b)
96
{
97
if
(b){
98
// prevent load of misaligned address runtime error
99
char
buf[8];
100
char
*p = align(buf);
101
for
(
int
i = 0; i < 4; i++){
102
p[i] = b[i];
103
}
104
int32_t s = htonl(*((int32_t *)p));
105
for
(int32_t i = 0; i < s + 4; i++){
106
if
(b[i] <= 32 || b[i] > 127){
107
printf(
"\\x%02x"
, b[i]);
108
}
else
{
109
printf(
"%c"
, b[i]);
110
}
111
}
112
}
else
{
113
printf(
"NULL"
);
114
}
115
}
116
135
/* A FAILING SUITE HAS TO STOP.
136
*
137
* On 2026-09-09 ut_ose_context printed one failing assertion -- the same
138
* line, over and over, at full speed -- into a redirected log for about two
139
* hours and filled a 1TB disk. The macro below prints ONCE per failure, so
140
* that cannot happen unless control returns to a UNIT_TEST that has already
141
* run: a longjmp into a frame that has gone. Whatever the route, the harness
142
* had no bound at all, and a test suite that can consume a disk is a worse
143
* failure than whatever it was trying to report.
144
*
145
* This is the bound, not the diagnosis. It costs nothing on a passing run
146
* and turns an unbounded spin into an exit with a message.
147
*/
148
#ifndef OSE_TEST_MAX_FAILURES
149
#define OSE_TEST_MAX_FAILURES 200
150
#endif
151
152
#define UNIT_TEST_IMPL(test, \
153
expected_result, \
154
desc, \
155
file, \
156
func, \
157
line) \
158
{ \
159
testctr++; \
160
int32_t r = ASSERTION_FAILED; \
161
if(!setjmp(env)){ \
162
r = test; \
163
} \
164
if(r != expected_result){ \
165
printf(ANSI_COLOR_RED \
166
"TEST %d FAILED: " \
167
ANSI_COLOR_RESET \
168
"%s:%s:%d:\n" \
169
"expected %d, but got %d\n", \
170
testctr, \
171
file, func, line, \
172
expected_result, r); \
173
failctr++; \
174
if(failctr > OSE_TEST_MAX_FAILURES){ \
175
printf("ABANDONED: %d failures in one test " \
176
"function -- see OSE_TEST_MAX_FAILURES\n", \
177
failctr); \
178
fflush(stdout); \
179
exit(1); \
180
} \
181
}else if(verbose){ \
182
printf(ANSI_COLOR_GREEN \
183
"TEST %d PASSED:\n" \
184
ANSI_COLOR_RESET \
185
"%s = %d\n", \
186
testctr, #test, expected_result); \
187
} \
188
} \
189
201
#define UNIT_TEST(test, expected_result, desc) \
202
UNIT_TEST_IMPL(test, expected_result, desc, \
203
__FILE__, __func__, __LINE__);
204
217
#define UNIT_TEST_WITH_SIMPLE_BUNDLE(b, \
218
test, \
219
expected_result, \
220
desc) \
221
{ \
222
char buf[MAX_BNDLSIZE] __attribute__ ((aligned (16))); \
223
char *p = NULL; \
224
ose_bundle bundle; \
225
if(b){ \
226
p = buf; \
227
memcpy(p, b, sizeof(b)); \
228
bundle = ose_makeBundle(p + 4); \
229
}else{ \
230
/* for testing NULL pointer input */
\
231
bundle = ose_makeBundle(p); \
232
} \
233
if(verbose){ \
234
printf("bundle = "); \
235
printb(b); \
236
printf("\n"); \
237
} \
238
UNIT_TEST(test, expected_result, desc); \
239
}
240
241
#define UNIT_TEST_WITH_CONTEXT_BUNDLE_IMPL(testbndl, \
242
bundle_literal, \
243
bundle_literal_size, \
244
copy_offset, \
245
call_offset, \
246
test, \
247
expected_result, \
248
desc) \
249
{ \
250
ose_bundle bundle = (ose_bundle){NULL}; \
251
char buf[bundle_literal_size + 4] \
252
__attribute__ ((aligned (16))); \
253
/* Start from a known state rather than whatever the stack holds. \
254
\
255
Note this is hygiene, not a fix for the cache: this fixture cannot \
256
be used with anything that touches the context cache at all. The \
257
cache slots are addressed 560 bytes below the working bundle \
258
pointer, and this literal places that pointer only 128 bytes into \
259
buf -- so cache reads and writes land 432 bytes *before* the \
260
array, outside it entirely, where zeroing cannot reach them. Since \
261
ose_context_getFirstOffsetForMatch calls whatever non-zero value \
262
it finds in that slot, the result is a segfault wherever that \
263
stack memory is not already zero. Measured, not inferred. */
\
264
memset(buf, 0, sizeof(buf)); \
265
if(testbndl){ \
266
memcpy(buf, bundle_literal, bundle_literal_size + 4); \
267
char *p = buf + copy_offset; \
268
bundle.b = buf + call_offset; \
269
int32_t sizeofb = sizeof(testbndl); \
270
int32_t size1 = ose_ntohl(*((int32_t *)(p - 4))); \
271
int32_t size2 = ose_ntohl(*((int32_t *)(p + size1))); \
272
*((int32_t *)(p + size1)) = 0; \
273
memcpy(p - 4, testbndl, sizeofb); \
274
*((int32_t *)(p + (sizeofb - 4))) \
275
= ose_htonl(size2 - (sizeofb - 20)); \
276
}else{ \
277
} \
278
UNIT_TEST(test, expected_result, desc); \
279
if(verbose){ \
280
printf("result bundle = "); \
281
printb(bundle.b); \
282
printf("\n"); \
283
} \
284
}
285
298
#define UNIT_TEST_WITH_CONTEXT_BUNDLE(testbndl, \
299
test, \
300
expected_result, \
301
desc) \
302
UNIT_TEST_WITH_CONTEXT_BUNDLE_IMPL(testbndl, \
303
ose_test_bundle_bytes, \
304
OSE_TEST_BUNDLE_TOTAL_SIZE - 4, \
305
OSE_TEST_BUNDLE_WORKING_OFFSET, \
306
OSE_TEST_BUNDLE_WORKING_OFFSET, \
307
test, \
308
expected_result, \
309
desc)
310
343
#define UNIT_TEST_WITH_VM(testbndl, \
344
test, \
345
expected_result, \
346
desc) \
347
UNIT_TEST_WITH_CONTEXT_BUNDLE_IMPL(testbndl, \
348
ose_test_vm_bytes, \
349
OSE_TEST_VM_TOTAL_SIZE - 4, \
350
OSE_TEST_VM_STACK_BUNDLE_OFFSET, \
351
OSE_TEST_VM_WORKING_BUNDLE_OFFSET, \
352
test, \
353
expected_result, \
354
desc)
355
369
#define UNIT_TEST_BUNDLE_TRANSFORM(testfn, \
370
testbndl, \
371
resultbndl, \
372
desc) \
373
if(verbose){ \
374
printf("test bundle = "); \
375
printb(testbndl); \
376
printf("\n"); \
377
printf("expected result = "); \
378
printb(resultbndl); \
379
printf("\n"); \
380
} \
381
UNIT_TEST_WITH_CONTEXT_BUNDLE( \
382
testbndl, \
383
(testfn(bundle), \
384
COMPARE_BUNDLES(resultbndl, \
385
ose_getBundlePtr(bundle) - 4)), \
386
0, \
387
desc);
388
421
#define UNIT_TEST_BUNDLE_ERRNO(testfn, \
422
testbndl, \
423
errno, \
424
desc) \
425
UNIT_TEST_WITH_CONTEXT_BUNDLE( \
426
testbndl, \
427
(testfn(bundle), \
428
ose_errno_get(bundle)), \
429
errno, \
430
desc);
431
449
#define UNIT_TEST_BUNDLE_TRANSFORM_ARGS(testfn, \
450
testbndl, \
451
resultbndl, \
452
desc, \
453
...) \
454
UNIT_TEST_WITH_CONTEXT_BUNDLE( \
455
testbndl, \
456
(testfn(bundle, __VA_ARGS__), \
457
COMPARE_BUNDLES(resultbndl, \
458
ose_getBundlePtr(bundle) - 4)), \
459
0, \
460
desc);
461
476
#define UNIT_TEST_BUNDLE_TRANSFORM_TRIGGER_ASSERTION(testfn, \
477
testbndl, \
478
desc) \
479
UNIT_TEST_WITH_CONTEXT_BUNDLE(testbndl, \
480
(testfn(bundle), 0), \
481
ASSERTION_FAILED, \
482
desc);
483
499
#define UNIT_TEST_BUNDLE_TRANSFORM_TRIGGER_ASSERTION_ARGS(testfn, \
500
testbndl, \
501
desc, \
502
...) \
503
UNIT_TEST_WITH_CONTEXT_BUNDLE(testbndl, \
504
(testfn(bundle, __VA_ARGS__), 0), \
505
ASSERTION_FAILED, \
506
desc);
507
522
#define UNIT_TEST_VM_ERRNO(testfn, \
523
testbndl, \
524
errno, \
525
desc) \
526
UNIT_TEST_WITH_VM(testbndl, \
527
(testfn(bundle), \
528
ose_errno_get(bundle)), \
529
errno, \
530
desc)
531
546
#define UNIT_TEST_VM_STACK_COMPARE(testfn, \
547
testbndl, \
548
resultbndl, \
549
desc) \
550
UNIT_TEST_WITH_VM(testbndl, \
551
(testfn(bundle), \
552
ose_errno_get(bundle) == OSE_ERR_NONE \
553
&& !COMPARE_BUNDLES(resultbndl, \
554
buf + OSE_TEST_VM_STACK_BUNDLE_OFFSET - 4)), \
555
1, \
556
desc)
557
565
#define SKIP_UNIT_TEST_WITH_BUNDLE(b, test, expected_result) \
566
SKIP_TEST(test, expected_result)
567
574
#define SKIP_UNIT_TEST(test, expected_result) \
575
SKIP_TEST(test, expected_result)
printb
void printb(const char *const b)
Print each byte of a bundle.
Definition
ose_test_unit.h:95
Generated by
1.9.8