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";
849 for (i = 0; i < result->
len; i++) {
858 char const *
in =
"i am a test string";
859 char out[18 + 1] =
"";
865 TEST_CASE(
"Copy 5 bytes to out - no advance");
879 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 32, 50) == &sbuff);
888 TEST_CASE(
"Print string - Should realloc to init");
898 TEST_CASE(
"Print string - Should realloc to init");
908 TEST_CASE(
"Print string - Should realloc to double buffer len");
914 TEST_CASE(
"Print string - Should only add a single char, should not extend the buffer");
920 TEST_CASE(
"Print string - Use all available buffer data");
926 TEST_CASE(
"Print string - Add single char, should trigger doubling constrained by max");
932 TEST_CASE(
"Print string - Add data to take us up to max");
938 TEST_CASE(
"Print string - Add single char, should fail");
944 TEST_CASE(
"Trim to strlen (should be noop)");
959 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 0, 50) == &sbuff);
963 TEST_CASE(
"Print string - Should alloc one byte");
969 TEST_CASE(
"Print string - Should alloc two bytes");
975 TEST_CASE(
"Print string - Should alloc three bytes");
990 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff_0, &tctx, 0, 50) == &sbuff_0);
995 TEST_CASE(
"Check sbuff_1 has extend fields set");
1002 TEST_CASE(
"Print string - Should alloc one byte");
1024 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff_0, &tctx, 0, 50) == &sbuff_0);
1028 TEST_CASE(
"Print string - Should alloc one byte");
1034 fr_sbuff_marker(&marker_0, &sbuff_0);
1035 TEST_CHECK((marker_0.p - sbuff_0.start) == 1);
1037 TEST_CASE(
"Print string - Ensure marker is updated");
1042 TEST_CHECK((marker_0.p - sbuff_0.start) == 1);
1047 fr_sbuff_marker(&marker_1, &sbuff_1);
1049 TEST_CHECK((marker_1.p - sbuff_1.start) == 0);
1050 TEST_CHECK((marker_1.p - sbuff_0.start) == 2);
1053 TEST_CASE(
"Print string - Trigger re-alloc, ensure all pointers are updated");
1058 TEST_CHECK((marker_1.p - sbuff_1.start) == 0);
1059 TEST_CHECK((marker_1.p - sbuff_0.start) == 2);
1072 TEST_CHECK(fr_sbuff_init_talloc(NULL, &sbuff, &tctx, 4, 8) == &sbuff);
1092 const char PATTERN[] =
"xyzzy";
1093#define PATTERN_LEN (sizeof(PATTERN) - 1)
1097 static_assert(
sizeof(
buff) >=
PATTERN_LEN,
"Buffer must be sufficiently large to hold the pattern");
1098 static_assert((
sizeof(fbuff) %
sizeof(
buff)) > 0,
"sizeof buff must not be a multiple of fbuff");
1099 static_assert((
sizeof(fbuff) %
sizeof(
buff)) <
PATTERN_LEN,
"remainder of sizeof(fbuff)/sizeof(buff) must be less than sizeof pattern");
1102 memset(fbuff,
' ',
sizeof(fbuff));
1105 fp = fmemopen(fbuff,
sizeof(fbuff),
"r");
1106#ifdef __clang_analyzer__
1107 if (fp == NULL)
return;
1111 TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx,
buff,
sizeof(
buff), fp, 128) == &sbuff);
1114 TEST_CASE(
"Advance past whitespace, which will require shift/extend");
1116 TEST_CASE(
"Verify extend on unused child buffer");
1117 child_sbuff =
FR_SBUFF(&our_sbuff);
1120 TEST_CASE(
"Verify that we passed all and only whitespace");
1121 (void) fr_sbuff_out_abstrncpy(NULL, &post_ws, &our_sbuff, 24);
1127 TEST_CASE(
"Verify that we do not read shifted buffer past eof");
1139 TEST_CASE(
"Verify fr_sbuff_out_bstrncpy_until() extends from file properly");
1140 fp = fmemopen(fbuff,
sizeof(fbuff),
"r");
1141#ifdef __clang_analyzer__
1142 if (fp == NULL)
return;
1146 TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx,
buff,
sizeof(
buff), fp, 128) == &sbuff);
1160 char fbuff[] =
" xyzzy";
1164 fp = fmemopen(fbuff,
sizeof(fbuff) - 1,
"r");
1165#ifdef __clang_analyzer__
1166 if (fp == NULL)
return;
1169 TEST_CHECK(fr_sbuff_init_file(&sbuff, &fctx,
buff,
sizeof(
buff), fp,
sizeof(fbuff) - 8) == &sbuff);
1171 TEST_CASE(
"Confirm that max stops us from seeing xyzzy");
1173 TEST_CHECK_SLEN(fr_sbuff_out_abstrncpy(NULL, &post_ws, &sbuff, 24), 0);
1182 char const in[] =
"i am a test string";
1184 TEST_CASE(
"Check for token at beginning of string");
1189 TEST_CASE(
"Check for token not at beginning of string");
1194 TEST_CASE(
"Check for token larger than the string");
1199 TEST_CASE(
"Check for token with zero length string");
1203 TEST_CASE(
"Check for token that is the string");
1213 char const in[] =
"i am a test string";
1215 TEST_CASE(
"Check for token at beginning of string");
1220 TEST_CASE(
"Check for token not at beginning of string");
1225 TEST_CASE(
"Check for token larger than the string");
1230 TEST_CASE(
"Check for token with zero length string");
1234 TEST_CASE(
"Check for token that is the string");
1244 char const in[] =
" i am a test string";
1245 char const in_ns[] =
"i am a test string";
1246 char const in_ws[] =
" ";
1248 TEST_CASE(
"Check for token at beginning of string");
1253 TEST_CASE(
"Check for token not at beginning of string");
1258 TEST_CASE(
"Check for token with zero length string");
1262 TEST_CASE(
"Check for token that is the string");
1266 TEST_CASE(
"Length constraint with token match");
1271 TEST_CASE(
"Length constraint without token match");
1280 char const in[] =
" i am a test string";
1281 char const in_ns[] =
"i am a test string";
1282 char const in_ws[] =
" ";
1284 TEST_CASE(
"Check for token at beginning of string");
1289 TEST_CASE(
"Check for token not at beginning of string");
1294 TEST_CASE(
"Check for token with zero length string");
1299 TEST_CASE(
"Check for token at the end of the string");
1304 TEST_CASE(
"Length constraint with token match");
1309 TEST_CASE(
"Length constraint with token match");
1318 char const in[] =
" abcdefgh ijklmnopp";
1320 TEST_CASE(
"Check for token at beginning of string");
1325 TEST_CASE(
"Check for token not at beginning of string");
1330 TEST_CASE(
"Check for token with zero length string");
1335 TEST_CASE(
"Check for token that is not in the string");
1345 TEST_CASE(
"Check for token that is not in the string with length constraint");
1354 char const in[] =
"🥺🥺🥺🥺🍪😀";
1357 TEST_CASE(
"Check for token at beginning of string");
1363 TEST_CASE(
"Check for token not at beginning of string");
1366 TEST_CHECK(p == (sbuff.start + (
sizeof(
"🥺🥺🥺🥺") - 1)));
1369 TEST_CASE(
"Check for token with zero length string");
1375 TEST_CASE(
"Check for token at the end of the string");
1378 TEST_CHECK(p == sbuff.start + (
sizeof(
"🥺🥺🥺🥺🍪") - 1));
1380 TEST_CASE(
"Check for token not in the string");
1385 TEST_CASE(
"Check for token at the end of the string within len constraints");
1388 TEST_CHECK(p == sbuff.start + (
sizeof(
"🥺🥺🥺🥺🍪") - 1));
1390 TEST_CASE(
"Check for token at the end of the string outside len constraints #1");
1395 TEST_CASE(
"Check for token at the end of the string outside len constraints #2");
1400 TEST_CASE(
"Check for token at the end of the string outside len constraints #3");
1405 TEST_CASE(
"Check for token at the end of the string outside len constraints #4");
1414 char const in[] =
"AAAAbC";
1417 TEST_CASE(
"Check for token at beginning of string");
1423 TEST_CASE(
"Check for token not at beginning of string");
1426 TEST_CHECK(p == (sbuff.start + (
sizeof(
"AAAA") - 1)));
1429 TEST_CASE(
"Check for token with zero length string");
1434 TEST_CASE(
"Check for token at the end of the string");
1437 TEST_CHECK(p == sbuff.start + (
sizeof(
"AAAAb") - 1));
1439 TEST_CASE(
"Check for token not in the string");
1444 TEST_CASE(
"Check for token not at beginning of string within length constraints");
1447 TEST_CHECK(p == (sbuff.start + (
sizeof(
"AAAA") - 1)));
1450 TEST_CASE(
"Check for token not at beginning of string outside length constraints");
1459 char const in[] =
"i am a test string";
1462 TEST_CASE(
"Check for token at beginning of string");
1468 TEST_CASE(
"Check for token not at beginning of string");
1474 TEST_CASE(
"Check for token at the end of string");
1480 TEST_CASE(
"Check for token larger than the string");
1486 TEST_CASE(
"Check for token shorter than string, not in the string");
1492 TEST_CASE(
"Check for token with zero length string");
1498 TEST_CASE(
"Check for token that is the string");
1505 TEST_CASE(
"Check for token not at beginning of string within length constraints");
1511 TEST_CASE(
"Check for token not at beginning of string outside length constraints");
1520 char const in[] =
"i am a test string";
1523 TEST_CASE(
"Check for token at beginning of string");
1529 TEST_CASE(
"Check for token not at beginning of string");
1535 TEST_CASE(
"Check for token at the end of string");
1541 TEST_CASE(
"Check for token larger than the string");
1547 TEST_CASE(
"Check for token shorter than string, not in the string");
1553 TEST_CASE(
"Check for token with zero length string");
1559 TEST_CASE(
"Check for token that is the string");
1566 TEST_CASE(
"Check for token not at beginning of string within length constraints");
1572 TEST_CASE(
"Check for token not at beginning of string outside length constraints");
1581 char const in[] =
"i ";
1583 TEST_CASE(
"Check for advancement on match");
1588 TEST_CASE(
"Check for non-advancement on non-match");
1592 TEST_CASE(
"Check for advancement at end");
1596 TEST_CASE(
"Check we can't advance off the end of the buffer");
1604 char const in[] =
"i ";
1606 TEST_CASE(
"Check for advancement on non-match");
1611 TEST_CASE(
"Check for non-advancement on match");
1615 TEST_CASE(
"Check for advancement at end");
1619 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_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