Skip to content

Commit 03b6858

Browse files
committed
Fix test framework to compare strings with embedded nulls
The TEST_EQUIV comparison used strcmp on ast_get_print(), which stops at the first null byte. This meant any test comparing string literals with embedded nulls (\x00) would silently pass even if the content after the null differed — strcmp sees both sides as equal at the truncation point. Add a TK_STRING special case in compare_asts that uses ast_name_len and memcmp for length-aware comparison. This is needed to properly test compile-time folding of strings containing embedded nulls. Add StringConcatEmbeddedNull test verifying that "ab\x00cd" + "ef" folds to "ab\x00cdef" with the correct 7-byte length.
1 parent 2c6bbb8 commit 03b6858

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

test/libponyc/sugar.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2228,3 +2228,22 @@ TEST_F(SugarTest, StringConcatChainMultipleVars)
22282228

22292229
TEST_EQUIV(short_form, full_form);
22302230
}
2231+
2232+
2233+
TEST_F(SugarTest, StringConcatEmbeddedNull)
2234+
{
2235+
const char* short_form =
2236+
"class Foo\n"
2237+
" var create: U32\n"
2238+
" fun f(): String val =>\n"
2239+
" \"ab\\x00cd\" + \"ef\"";
2240+
2241+
const char* full_form =
2242+
"use \"builtin\"\n"
2243+
"class ref Foo\n"
2244+
" var create: U32\n"
2245+
" fun box f(): String val =>\n"
2246+
" \"ab\\x00cdef\"";
2247+
2248+
TEST_EQUIV(short_form, full_form);
2249+
}

test/libponyc/util.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,20 @@ static bool compare_asts(ast_t* expected, ast_t* actual, errors_t *errors)
155155
{
156156
// Allow expected and actual hygenic names to match.
157157
}
158+
else if(expected_id == TK_STRING)
159+
{
160+
// Use length-aware comparison for strings so embedded nulls are compared
161+
// correctly. strcmp would stop at the first null byte.
162+
size_t expected_len = ast_name_len(expected);
163+
size_t actual_len = ast_name_len(actual);
164+
if(expected_len != actual_len ||
165+
memcmp(ast_name(expected), ast_name(actual), expected_len) != 0)
166+
{
167+
ast_error(errors, expected, "AST string mismatch, got %s, expected %s",
168+
ast_get_print(actual), ast_get_print(expected));
169+
return false;
170+
}
171+
}
158172
else if(strcmp(ast_get_print(expected), ast_get_print(actual)) != 0)
159173
{
160174
ast_error(errors, expected, "AST text mismatch, got %s, expected %s",

0 commit comments

Comments
 (0)