26#include <freeradius-devel/util/sbuff.h>
28#define TEST_SBUFF_LEN(_sbuff, _num) \
31 _len = talloc_array_length((_sbuff)->buff); \
32 TEST_CHECK(_len == (size_t)_num); \
33 TEST_MSG("Expected length : %zu", (size_t)_num); \
34 TEST_MSG("Got length : %zu", _len); \
37#define TEST_SBUFF_USED(_sbuff, _num) \
40 _len = fr_sbuff_used(_sbuff); \
41 TEST_CHECK(_len == (size_t)_num); \
42 TEST_MSG("Expected length : %zu", (size_t)_num); \
43 TEST_MSG("Got length : %zu", _len); \
48 char const in[] =
"i am a test string";
75 char const in[] =
"i am a test string";
89 fr_sbuff_marker(&marker, &sbuff);
104 char const in[] =
"i am a test string";
105 char const in_long[] =
"i am a longer test string";
106 char out[18 + 1] =
"";
130 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
138 fr_sbuff_set_to_start(&sbuff);
146 fr_sbuff_set_to_start(&sbuff);
156 char const in[] =
"i am a test string";
157 char const in_long[] =
"i am a longer test string";
158 char out[18 + 1] =
"";
182 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
190 fr_sbuff_set_to_start(&sbuff);
198 fr_sbuff_set_to_start(&sbuff);
207 [
'a'] =
true, [
'b'] =
true, [
'c'] =
true, [
'd'] =
true, [
'e'] =
true,
208 [
'f'] =
true, [
'g'] =
true, [
'h'] =
true, [
'i'] =
true, [
'j'] =
true,
209 [
'k'] =
true, [
'l'] =
true, [
'm'] =
true, [
'n'] =
true, [
'o'] =
true,
210 [
'p'] =
true, [
'q'] =
true, [
'r'] =
true, [
's'] =
true, [
't'] =
true,
211 [
'u'] =
true, [
'v'] =
true, [
'w'] =
true, [
'x'] =
true, [
'y'] =
true,
212 [
'z'] =
true, [
' '] =
true
216 [
'a'] =
true, [
'b'] =
true, [
'c'] =
true, [
'd'] =
true, [
'e'] =
true,
217 [
'f'] =
true, [
'g'] =
true, [
'h'] =
true, [
'i'] =
true, [
'j'] =
true,
218 [
'k'] =
true, [
'l'] =
true, [
'm'] =
true, [
'n'] =
true, [
'o'] =
true,
219 [
'p'] =
true, [
'q'] =
true, [
'r'] =
true, [
's'] =
true, [
't'] =
false,
220 [
'u'] =
true, [
'v'] =
true, [
'w'] =
true, [
'x'] =
true, [
'y'] =
true,
221 [
'z'] =
true, [
' '] =
true
226 char const in[] =
"i am a test string";
227 char const in_long[] =
"i am a longer test string";
228 char out[18 + 1] =
"";
257 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
265 fr_sbuff_set_to_start(&sbuff);
273 fr_sbuff_set_to_start(&sbuff);
284 fr_sbuff_set_to_start(&sbuff);
290 TEST_CASE(
"Copy until first t with length constraint (same len as token)");
291 fr_sbuff_set_to_start(&sbuff);
297 TEST_CASE(
"Copy until first t with length constraint (one shorter than token)");
298 fr_sbuff_set_to_start(&sbuff);
304 TEST_CASE(
"Zero length token (should still be terminated)");
305 fr_sbuff_set_to_start(&sbuff);
314 char const in[] =
"i am a test string";
315 char const in_long[] =
"i am a longer test string";
346 fr_sbuff_set_to_start(&sbuff);
353 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
361 fr_sbuff_set_to_start(&sbuff);
369 fr_sbuff_set_to_start(&sbuff);
380 fr_sbuff_set_to_start(&sbuff);
385 TEST_CASE(
"Copy until first t with length constraint (same len as token)");
386 fr_sbuff_set_to_start(&sbuff);
391 TEST_CASE(
"Copy until first t with length constraint (one shorter than token)");
392 fr_sbuff_set_to_start(&sbuff);
397 TEST_CASE(
"Zero length token (should still be terminated)");
398 fr_sbuff_set_to_start(&sbuff);
406 char const in[] =
"i am a test string";
407 char const in_long[] =
"i am a longer test string";
408 char const in_escapes[] =
"i am a |t|est strin|g";
409 char const in_escapes_seq[] =
"i |x|0am a |t|est strin|g|x20|040";
410 char out[18 + 1] =
"";
411 char escape_out[20 + 1];
422 .subs = { [
'g'] =
'g', [
'|'] =
'|' }
426 .
chr =
'|', .subs = { [
'g'] =
'h', [
'|'] =
'|' }
431 .subs = { [
'g'] =
'h', [
'|'] =
'|' },
437 .subs = { [
'g'] =
'h', [
'|'] =
'|' },
443 .subs = { [
'g'] =
'h', [
'|'] =
'|' },
472 TEST_CASE(
"Copy would overrun output (and SIZE_MAX special value)");
480 fr_sbuff_set_to_start(&sbuff);
488 fr_sbuff_set_to_start(&sbuff);
499 fr_sbuff_set_to_start(&sbuff);
505 TEST_CASE(
"Copy until first t with length constraint (same len as token)");
506 fr_sbuff_set_to_start(&sbuff);
512 TEST_CASE(
"Copy until first t with length constraint (one shorter than token)");
513 fr_sbuff_set_to_start(&sbuff);
519 TEST_CASE(
"Zero length token (should still be terminated)");
520 fr_sbuff_set_to_start(&sbuff);
529 TEST_CASE(
"Escape with substitution to same char");
537 TEST_CASE(
"Escape with substitution to different char");
546 char tmp_out[24 + 1];
548 TEST_CASE(
"Escape with hex substitutions (insufficient output space)");
558 char tmp_out[25 + 1];
560 TEST_CASE(
"Escape with hex substitutions (sufficient output space)");
570 char tmp_out[28 + 1];
572 TEST_CASE(
"Escape with oct substitutions (insufficient output space)");
582 char tmp_out[29 + 1];
584 TEST_CASE(
"Escape with oct substitutions (sufficient output space)");
594 char tmp_out[26 + 1];
596 TEST_CASE(
"Escape with hex and oct substitutions (sufficient output space)");
607 char const in_escapes_collapse[] =
"||";
610 fr_sbuff_init_in(&sbuff, in_escapes_collapse,
sizeof(in_escapes_collapse) - 1);
612 &sbuff, SIZE_MAX, NULL, &pipe_rules);
619 char in_escapes_collapse[] =
"||foo||";
621 TEST_CASE(
"Collapse double escapes overlapping");
622 fr_sbuff_init_in(&sbuff, in_escapes_collapse,
sizeof(in_escapes_collapse) - 1);
624 &sbuff, SIZE_MAX, NULL, &pipe_rules);
631 char tmp_out[30 + 1];
650 char const in_escapes_unit[] =
659 char const expected[] = {
660 '0',
'x',
'0',
'1',
'\001',
661 '0',
'x',
'0',
'7',
'\007',
662 '0',
'x',
'0',
'A',
'\n',
663 '0',
'x',
'0',
'D',
'\r',
669 TEST_CASE(
"Check unit test test strings");
672 NULL, &double_quote_rules);
684 char const in_zero[] =
"";
686 len = fr_sbuff_out_aunescape_until(NULL, &
buff, &
FR_SBUFF_IN(in_zero,
sizeof(in_zero) - 1), SIZE_MAX,
689 talloc_get_type_abort(
buff,
char);
697 char const in[] =
"foo, bar, baz```";
732 char const in[] =
"foo, bar";
776 char const in[] =
"abc}xyz";
805 size_t const len = 4;
806 char *
buff = malloc(len);
815 memcpy(
buff,
"abcd", len);
887 for (i = 0; i < result->
len; i++) {
896 char const *
in =
"i am a test string";
897 char out[18 + 1] =
"";
903 TEST_CASE(
"Copy 5 bytes to out - no advance");
917 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 32, 50) == &sbuff);
926 TEST_CASE(
"Print string - Should realloc to init");
936 TEST_CASE(
"Print string - Should realloc to init");
946 TEST_CASE(
"Print string - Should realloc to double buffer len");
952 TEST_CASE(
"Print string - Should only add a single char, should not extend the buffer");
958 TEST_CASE(
"Print string - Use all available buffer data");
964 TEST_CASE(
"Print string - Add single char, should trigger doubling constrained by max");
970 TEST_CASE(
"Print string - Add data to take us up to max");
976 TEST_CASE(
"Print string - Add single char, should fail");
982 TEST_CASE(
"Trim to strlen (should be noop)");
997 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 0, 50) == &sbuff);
1001 TEST_CASE(
"Print string - Should alloc one byte");
1007 TEST_CASE(
"Print string - Should alloc two bytes");
1013 TEST_CASE(
"Print string - Should alloc three bytes");
1028 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff_0, &tctx, 0, 50) == &sbuff_0);
1033 TEST_CASE(
"Check sbuff_1 has extend fields set");
1034 TEST_CHECK(sbuff_0.extend == sbuff_1.extend);
1040 TEST_CASE(
"Print string - Should alloc one byte");
1062 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff_0, &tctx, 0, 50) == &sbuff_0);
1066 TEST_CASE(
"Print string - Should alloc one byte");
1072 fr_sbuff_marker(&marker_0, &sbuff_0);
1073 TEST_CHECK((marker_0.p - sbuff_0.start) == 1);
1075 TEST_CASE(
"Print string - Ensure marker is updated");
1080 TEST_CHECK((marker_0.p - sbuff_0.start) == 1);
1085 fr_sbuff_marker(&marker_1, &sbuff_1);
1087 TEST_CHECK((marker_1.p - sbuff_1.start) == 0);
1088 TEST_CHECK((marker_1.p - sbuff_0.start) == 2);
1091 TEST_CASE(
"Print string - Trigger re-alloc, ensure all pointers are updated");
1096 TEST_CHECK((marker_1.p - sbuff_1.start) == 0);
1097 TEST_CHECK((marker_1.p - sbuff_0.start) == 2);
1110 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 4, 8) == &sbuff);
1130 const char PATTERN[] =
"xyzzy";
1131#define PATTERN_LEN (sizeof(PATTERN) - 1)
1135 static_assert(
sizeof(
buff) >=
PATTERN_LEN,
"Buffer must be sufficiently large to hold the pattern");
1136 static_assert((
sizeof(fbuff) %
sizeof(
buff)) > 0,
"sizeof buff must not be a multiple of fbuff");
1137 static_assert((
sizeof(fbuff) %
sizeof(
buff)) <
PATTERN_LEN,
"remainder of sizeof(fbuff)/sizeof(buff) must be less than sizeof pattern");
1140 memset(fbuff,
' ',
sizeof(fbuff));
1143 fp = fmemopen(fbuff,
sizeof(fbuff),
"r");
1144#ifdef __clang_analyzer__
1145 if (fp == NULL)
return;
1149 TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx,
buff,
sizeof(
buff), fp, 128) == &sbuff);
1152 TEST_CASE(
"Advance past whitespace, which will require shift/extend");
1154 TEST_CASE(
"Verify extend on unused child buffer");
1155 child_sbuff =
FR_SBUFF(&our_sbuff);
1158 TEST_CASE(
"Verify that we passed all and only whitespace");
1159 (void) fr_sbuff_out_abstrncpy(NULL, &post_ws, &our_sbuff, 24);
1165 TEST_CASE(
"Verify that we do not read shifted buffer past eof");
1177 TEST_CASE(
"Verify fr_sbuff_out_bstrncpy_until() extends from file properly");
1178 fp = fmemopen(fbuff,
sizeof(fbuff),
"r");
1179#ifdef __clang_analyzer__
1180 if (fp == NULL)
return;
1184 TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx,
buff,
sizeof(
buff), fp, 128) == &sbuff);
1198 char fbuff[] =
" xyzzy";
1202 fp = fmemopen(fbuff,
sizeof(fbuff) - 1,
"r");
1203#ifdef __clang_analyzer__
1204 if (fp == NULL)
return;
1207 TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx,
buff,
sizeof(
buff), fp,
sizeof(fbuff) - 8) == &sbuff);
1209 TEST_CASE(
"Confirm that max stops us from seeing xyzzy");
1211 TEST_CHECK_SLEN(fr_sbuff_out_abstrncpy(NULL, &post_ws, &sbuff, 24), 0);
1220 char const in[] =
"i am a test string";
1222 TEST_CASE(
"Check for token at beginning of string");
1227 TEST_CASE(
"Check for token not at beginning of string");
1232 TEST_CASE(
"Check for token larger than the string");
1237 TEST_CASE(
"Check for token with zero length string");
1241 TEST_CASE(
"Check for token that is the string");
1251 char const in[] =
"i am a test string";
1253 TEST_CASE(
"Check for token at beginning of string");
1258 TEST_CASE(
"Check for token not at beginning of string");
1263 TEST_CASE(
"Check for token larger than the string");
1268 TEST_CASE(
"Check for token with zero length string");
1272 TEST_CASE(
"Check for token that is the string");
1282 char const in[] =
" i am a test string";
1283 char const in_ns[] =
"i am a test string";
1284 char const in_ws[] =
" ";
1286 TEST_CASE(
"Check for token at beginning of string");
1291 TEST_CASE(
"Check for token not at beginning of string");
1296 TEST_CASE(
"Check for token with zero length string");
1300 TEST_CASE(
"Check for token that is the string");
1304 TEST_CASE(
"Length constraint with token match");
1309 TEST_CASE(
"Length constraint without token match");
1318 char const in[] =
" i am a test string";
1319 char const in_ns[] =
"i am a test string";
1320 char const in_ws[] =
" ";
1322 TEST_CASE(
"Check for token at beginning of string");
1327 TEST_CASE(
"Check for token not at beginning of string");
1332 TEST_CASE(
"Check for token with zero length string");
1337 TEST_CASE(
"Check for token at the end of the string");
1342 TEST_CASE(
"Length constraint with token match");
1347 TEST_CASE(
"Length constraint with token match");
1356 char const in[] =
" abcdefgh ijklmnopp";
1358 TEST_CASE(
"Check for token at beginning of string");
1363 TEST_CASE(
"Check for token not at beginning of string");
1368 TEST_CASE(
"Check for token with zero length string");
1373 TEST_CASE(
"Check for token that is not in the string");
1383 TEST_CASE(
"Check for token that is not in the string with length constraint");
1392 char const in[] =
"🥺🥺🥺🥺🍪😀";
1395 TEST_CASE(
"Check for token at beginning of string");
1401 TEST_CASE(
"Check for token not at beginning of string");
1404 TEST_CHECK(p == (sbuff.start + (
sizeof(
"🥺🥺🥺🥺") - 1)));
1407 TEST_CASE(
"Check for token with zero length string");
1413 TEST_CASE(
"Check for token at the end of the string");
1416 TEST_CHECK(p == sbuff.start + (
sizeof(
"🥺🥺🥺🥺🍪") - 1));
1418 TEST_CASE(
"Check for token not in the string");
1423 TEST_CASE(
"Check for token at the end of the string within len constraints");
1426 TEST_CHECK(p == sbuff.start + (
sizeof(
"🥺🥺🥺🥺🍪") - 1));
1428 TEST_CASE(
"Check for token at the end of the string outside len constraints #1");
1433 TEST_CASE(
"Check for token at the end of the string outside len constraints #2");
1438 TEST_CASE(
"Check for token at the end of the string outside len constraints #3");
1443 TEST_CASE(
"Check for token at the end of the string outside len constraints #4");
1452 char const in[] =
"AAAAbC";
1455 TEST_CASE(
"Check for token at beginning of string");
1461 TEST_CASE(
"Check for token not at beginning of string");
1464 TEST_CHECK(p == (sbuff.start + (
sizeof(
"AAAA") - 1)));
1467 TEST_CASE(
"Check for token with zero length string");
1472 TEST_CASE(
"Check for token at the end of the string");
1475 TEST_CHECK(p == sbuff.start + (
sizeof(
"AAAAb") - 1));
1477 TEST_CASE(
"Check for token not in the string");
1482 TEST_CASE(
"Check for token not at beginning of string within length constraints");
1485 TEST_CHECK(p == (sbuff.start + (
sizeof(
"AAAA") - 1)));
1488 TEST_CASE(
"Check for token not at beginning of string outside length constraints");
1497 char const in[] =
"i am a test string";
1500 TEST_CASE(
"Check for token at beginning of string");
1506 TEST_CASE(
"Check for token not at beginning of string");
1512 TEST_CASE(
"Check for token at the end of string");
1518 TEST_CASE(
"Check for token larger than the string");
1524 TEST_CASE(
"Check for token shorter than string, not in the string");
1530 TEST_CASE(
"Check for token with zero length string");
1536 TEST_CASE(
"Check for token that is the string");
1543 TEST_CASE(
"Check for token not at beginning of string within length constraints");
1549 TEST_CASE(
"Check for token not at beginning of string outside length constraints");
1558 char const in[] =
"i am a test string";
1561 TEST_CASE(
"Check for token at beginning of string");
1567 TEST_CASE(
"Check for token not at beginning of string");
1573 TEST_CASE(
"Check for token at the end of string");
1579 TEST_CASE(
"Check for token larger than the string");
1585 TEST_CASE(
"Check for token shorter than string, not in the string");
1591 TEST_CASE(
"Check for token with zero length string");
1597 TEST_CASE(
"Check for token that is the string");
1604 TEST_CASE(
"Check for token not at beginning of string within length constraints");
1610 TEST_CASE(
"Check for token not at beginning of string outside length constraints");
1619 char const in[] =
"i ";
1621 TEST_CASE(
"Check for advancement on match");
1626 TEST_CASE(
"Check for non-advancement on non-match");
1630 TEST_CASE(
"Check for advancement at end");
1634 TEST_CASE(
"Check we can't advance off the end of the buffer");
1642 char const in[] =
"i ";
1644 TEST_CASE(
"Check for advancement on non-match");
1649 TEST_CASE(
"Check for non-advancement on match");
1653 TEST_CASE(
"Check for advancement at end");
1657 TEST_CASE(
"Check we can't advance off the end of the buffer");
#define TEST_CHECK_SLEN(_got, _exp)
#define TEST_CHECK_SLEN_RETURN(_got, _exp)
#define TEST_CHECK_LEN(_got, _exp)
#define TEST_CHECK_STRCMP(_got, _exp)
#define L(_str)
Helper for initialising arrays of string literals.
size_t fr_sbuff_out_unescape_until(fr_sbuff_t *out, fr_sbuff_t *in, size_t len, fr_sbuff_term_t const *tt, fr_sbuff_unescape_rules_t const *u_rules)
ssize_t fr_sbuff_out_bstrncpy_exact(fr_sbuff_t *out, fr_sbuff_t *in, size_t len)
size_t fr_sbuff_out_bstrncpy_until(fr_sbuff_t *out, fr_sbuff_t *in, size_t len, fr_sbuff_term_t const *tt, fr_sbuff_unescape_rules_t const *u_rules)
size_t fr_sbuff_out_bstrncpy_allowed(fr_sbuff_t *out, fr_sbuff_t *in, size_t len, bool const allowed[static SBUFF_CHAR_CLASS])
size_t fr_sbuff_adv_past_allowed(fr_sbuff_t *sbuff, size_t len, bool const allowed[static SBUFF_CHAR_CLASS], fr_sbuff_term_t const *tt)
Wind position past characters in the allowed set.
int fr_sbuff_trim_talloc(fr_sbuff_t *sbuff, size_t len)
Trim a talloced sbuff to the minimum length required to represent the contained string.
ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
char * fr_sbuff_adv_to_chr_utf8(fr_sbuff_t *sbuff, size_t len, char const *chr)
Wind position to first instance of specified multibyte utf8 char.
char * fr_sbuff_adv_to_str(fr_sbuff_t *sbuff, size_t len, char const *needle, size_t needle_len)
Wind position to the first instance of the specified needle.
char * fr_sbuff_adv_to_strcase(fr_sbuff_t *sbuff, size_t len, char const *needle, size_t needle_len)
Wind position to the first instance of the specified needle.
size_t fr_sbuff_extend_file(fr_sbuff_extend_status_t *status, fr_sbuff_t *sbuff, size_t extension)
Refresh the buffer with more data from the file.
size_t fr_sbuff_adv_past_str(fr_sbuff_t *sbuff, char const *needle, size_t needle_len)
Return true and advance past the end of the needle if needle occurs next in the sbuff.
size_t fr_sbuff_shift(fr_sbuff_t *sbuff, size_t shift, bool move_end)
Shift the contents of the sbuff, returning the number of bytes we managed to shift.
char * fr_sbuff_adv_to_chr(fr_sbuff_t *sbuff, size_t len, char c)
Wind position to first instance of specified char.
bool fr_sbuff_is_terminal(fr_sbuff_t *in, fr_sbuff_term_t const *tt)
Efficient terminal string search.
size_t fr_sbuff_adv_past_strcase(fr_sbuff_t *sbuff, char const *needle, size_t needle_len)
Return true and advance past the end of the needle if needle occurs next in the sbuff.
bool fr_sbuff_next_unless_char(fr_sbuff_t *sbuff, char c)
Return true and advance if the next char does not match.
size_t fr_sbuff_adv_until(fr_sbuff_t *sbuff, size_t len, fr_sbuff_term_t const *tt, char escape_chr)
Wind position until we hit a character in the terminal set.
size_t fr_sbuff_out_bstrncpy(fr_sbuff_t *out, fr_sbuff_t *in, size_t len)
Copy as many bytes as possible from a sbuff to a sbuff.
fr_sbuff_term_t * fr_sbuff_terminals_amerge(TALLOC_CTX *ctx, fr_sbuff_term_t const *a, fr_sbuff_term_t const *b)
Merge two sets of terminal strings.
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_IN(_start, _len_or_end)
#define FR_SBUFF_BIND_CURRENT(_sbuff_or_marker)
#define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt)
char const * str
Terminal string.
char chr
Character at the start of an escape sequence.
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
size_t len
Length of the list.
#define fr_sbuff_is_char(_sbuff_or_marker, _c)
#define FR_SBUFF(_sbuff_or_marker)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_init_in(_out, _start, _len_or_end)
#define FR_SBUFF_OUT(_start, _len_or_end)
fr_sbuff_term_elem_t * elem
A sorted list of terminal strings.
#define FR_SBUFF_TERM(_str)
Initialise a terminal structure with a single string.
Set of terminal elements.
File sbuff extension structure.
Talloc sbuff extension structure.
Set of parsing rules for *unescape_until functions.
static void test_adv_past_allowed(void)
static void test_terminal_search_past_visible_end(void)
static void test_no_advance(void)
static void test_file_extend_max(void)
static void test_talloc_extend_multi_level(void)
static void test_adv_past_strcase(void)
static void test_adv_to_strcase(void)
static void test_talloc_extend(void)
static void test_bstrncpy_until(void)
static void test_bstrncpy_allowed(void)
static bool allow_lowercase_and_space_no_t[SBUFF_CHAR_CLASS]
#define TEST_SBUFF_USED(_sbuff, _num)
static void test_adv_until(void)
static void test_is_char(void)
static void test_bstrncpy(void)
static void test_bstrncpy_exact(void)
static void test_adv_to_utf8(void)
static void test_adv_to_chr(void)
static void test_eof_terminal(void)
static void test_next_unless_char(void)
static void test_adv_past_whitespace(void)
static void test_next_if_char(void)
static void test_terminal_search_at_end_no_overrun(void)
static void test_unescape_until(void)
static void test_adv_past_str(void)
static void test_talloc_extend_with_shift(void)
static void test_unescape_multi_char_terminals(void)
#define TEST_SBUFF_LEN(_sbuff, _num)
static void test_file_extend(void)
static void test_terminal_merge(void)
static void test_parse_init(void)
static bool allow_lowercase_and_space[SBUFF_CHAR_CLASS]
static void test_adv_to_str(void)
static void test_talloc_extend_init_zero(void)
static void test_talloc_extend_with_marker(void)
static char buff[sizeof("18446744073709551615")+3]
static size_t char ** out