FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
kernelscript/tests/test_string_codegen.ml at main · multikernel/kernelscript · GitHub
multikernel
/
kernelscript
Public
Notifications
You must be signed in to change notification settings
Fork
24
Star
508
Code
Issues
2
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
kernelscript
/
tests
/
test_string_codegen.ml
Copy path
More file actions
More file actions
Latest commit
History
History
History
389 lines (321 loc) · 14.6 KB
Breadcrumbs
kernelscript
/
tests
/
test_string_codegen.ml
Copy path
File metadata and controls
389 lines (321 loc) · 14.6 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
(*
* Copyright 2025 Multikernel Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
open
Alcotest
open
Kernelscript.Parse
(*
* Helper function to check if generated code contains a pattern
*)
let
contains_pattern
code
pattern
=
try
let
regex
=
Str.
regexp pattern
in
ignore (
Str.
search_forward regex code
0
);
true
with
Not_found
->
false
(*
* Helper function to generate userspace code from a program with proper IR generation
*)
let
generate_userspace_code_from_program
program_text
filename
=
let
ast
=
parse_string program_text
in
let
symbol_table
=
Kernelscript.Symbol_table.
build_symbol_table ast
in
let
(annotated_ast, _typed_programs)
=
Kernelscript.Type_checker.
type_check_and_annotate_ast ast
in
let
ir
=
Kernelscript.Ir_generator.
generate_ir annotated_ast symbol_table filename
in
let
temp_dir
=
Filename.
temp_file
"
test_string_codegen
"
"
"
in
Unix.
unlink temp_dir;
Unix.
mkdir temp_dir
0o755
;
let
_output_file
=
Kernelscript.Userspace_codegen.
generate_userspace_code_from_ir
ir
~output_dir:
temp_dir filename
in
let
generated_file
=
Filename.
concat temp_dir (filename
^
"
.c
"
)
in
if
Sys.
file_exists generated_file
then
(
let
ic
=
open_in generated_file
in
let
content
=
really_input_string ic (in_channel_length ic)
in
close_in ic;
(*
Cleanup
*)
Unix.
unlink generated_file;
Unix.
rmdir temp_dir;
content
)
else
(
failwith
"
Failed to generate userspace code file
"
)
(*
* Test 1: String assignment generates safe strcpy/strncpy code
*)
let
test_string_assignment_codegen
()
=
let
program_text
=
{
|
@
xdp fn test(ctx:
*xdp_md
) -> xdp_action {
return
2
}
fn main
()
-> i32 {
var
greeting
:
str
(
20
)
=
"Hello"
var
name
:
str
(
30
)
=
"World"
var
short
:
str
(
5
)
=
"Hi"
return
0
}
|
}
in
try
let
result
=
generate_userspace_code_from_program program_text
"
test_string_assignment
"
in
(*
Should generate runtime length checking to avoid truncation warnings
*)
check
bool
"
has strlen check
"
true
(contains_pattern result
"
strlen.*__src_len
"
);
check
bool
"
binds source literal
"
true
(contains_pattern result
"
__src =
\"
Hello
\"
"
);
check
bool
"
has strcpy for safe case
"
true
(contains_pattern result
"
strcpy.*var_.*__src
"
);
check
bool
"
has strncpy for truncation case
"
true
(contains_pattern result
"
strncpy.*var_
"
);
check
bool
"
has explicit null termination
"
true
(contains_pattern result
"
\\
[.*
\\
].*=.*'
\\\\
0'
"
);
(*
Should have proper bounds checking
*)
check
bool
"
has size comparison
"
true
(contains_pattern result
"
if.*__src_len.*<.*[0-9]+
"
);
with
|
exn
-> fail (
"
String assignment test failed:
"
^
Printexc.
to_string
exn
)
(*
* Test 2: String concatenation generates safe concatenation code
*)
let
test_string_concatenation_codegen
()
=
let
program_text
=
{
|
@
xdp fn test(ctx:
*xdp_md
) -> xdp_action {
return
2
}
fn main
()
-> i32 {
var
first
:
str
(
10
)
=
"Hello"
var
second
:
str
(
10
)
=
"World"
var
result
:
str
(
25
)
=
first
+
second
return
0
}
|
}
in
try
let
result
=
generate_userspace_code_from_program program_text
"
test_string_concat
"
in
(*
Should generate safe concatenation with helper functions
*)
check
bool
"
uses str_concat helper
"
true
(contains_pattern result
"
str_concat_[0-9]+
"
);
check
bool
"
has helper function definition
"
true
(contains_pattern result
"
static inline char
\\
* str_concat_[0-9]+
"
);
(*
The helper function should have safe concatenation operations
*)
check
bool
"
has strcpy in helper
"
true
(contains_pattern result
"
strcpy.*result.*left
"
);
check
bool
"
has strcat in helper
"
true
(contains_pattern result
"
strcat.*result.*right
"
);
check
bool
"
has truncation path
"
true
(contains_pattern result
"
strncpy
"
);
check
bool
"
bounds check for concat
"
true
(contains_pattern result
"
if.*len.*
\\
+.*len.*<
"
);
(*
Should call the helper function in assignment
*)
check
bool
"
calls helper in assignment
"
true
(contains_pattern result
"
str_concat_[0-9]+.*var_.*var_
"
);
with
|
exn
-> fail (
"
String concatenation test failed:
"
^
Printexc.
to_string
exn
)
(*
* Test 3: String comparison generates strcmp calls
*)
let
test_string_comparison_codegen
()
=
let
program_text
=
{
|
@
xdp fn test(ctx:
*xdp_md
) -> xdp_action {
return
2
}
fn main
()
-> i32 {
var
name
:
str
(
20
)
=
"Alice"
var
second
:
str
(
20
)
=
"Bob"
if
(
name
==
second
) {
return
1
}
return
0
}
|
}
in
try
let
ast
=
parse_string program_text
in
let
symbol_table
=
Kernelscript.Symbol_table.
build_symbol_table ast
in
let
(annotated_ast, _typed_programs)
=
Kernelscript.Type_checker.
type_check_and_annotate_ast ast
in
let
ir
=
Kernelscript.Ir_generator.
generate_ir annotated_ast symbol_table
"
test_string_compare
"
in
let
temp_dir
=
Filename.
temp_file
"
test_string_codegen
"
"
"
in
Unix.
unlink temp_dir;
Unix.
mkdir temp_dir
0o755
;
let
_output_file
=
Kernelscript.Userspace_codegen.
generate_userspace_code_from_ir
ir
~output_dir:
temp_dir
"
test_string_compare
"
in
let
generated_file
=
Filename.
concat temp_dir (
"
test_string_compare
"
^
"
.c
"
)
in
if
Sys.
file_exists generated_file
then
(
let
ic
=
open_in generated_file
in
let
content
=
really_input_string ic (in_channel_length ic)
in
close_in ic;
(*
Cleanup
*)
Unix.
unlink generated_file;
Unix.
rmdir temp_dir;
let
result
=
content
in
(*
Should generate strcmp for equality with variable assignment
*)
check
bool
"
equality uses strcmp
"
true
(contains_pattern result
"
strcmp.*var_.*var_.*==.*0
"
);
check
bool
"
has variable comparison
"
true
(contains_pattern result
"
strcmp.*var_.*var_
"
);
check
bool
"
assigns comparison result
"
true
(contains_pattern result
"
__binop_.*=.*(strcmp
"
);
check
bool
"
uses comparison variable in if
"
true
(contains_pattern result
"
if.*(__binop_
"
);
(*
Should have proper string assignments
*)
check
bool
"
has Alice assignment
"
true
(contains_pattern result
"
__src =
\"
Alice
\"
"
);
check
bool
"
has Bob assignment
"
true
(contains_pattern result
"
__src =
\"
Bob
\"
"
);
)
else
(
failwith
"
Failed to generate userspace code file
"
)
with
|
exn
->
fail (
"
String comparison test failed:
"
^
Printexc.
to_string
exn
)
(*
* Test 4: String indexing generates array access
*)
let
test_string_indexing_codegen
()
=
let
program_text
=
{
|
@
xdp fn test(ctx:
*xdp_md
) -> xdp_action {
return
2
}
fn main
()
-> i32 {
var
message
:
str
(
20
)
=
"Hello"
var
first
:
char
=
message
[
0
]
var
second
:
char
=
message
[
1
]
return
0
}
|
}
in
try
let
result
=
generate_userspace_code_from_program program_text
"
test_string_index
"
in
(*
Should generate direct array access
*)
check
bool
"
has array indexing syntax
"
true
(contains_pattern result
"
var_.*
\\
[0
\\
]
"
);
check
bool
"
second index access
"
true
(contains_pattern result
"
var_.*
\\
[1
\\
]
"
);
check
bool
"
char assignment
"
true
(contains_pattern result
"
var_first = __array_access
"
);
(*
Should not have complex bounds checking for simple indexing
*)
check
bool
"
direct array access
"
true
(contains_pattern result
"
__array_access.*= var_.*
\\
[.*
\\
]
"
);
with
|
exn
-> fail (
"
String indexing test failed:
"
^
Printexc.
to_string
exn
)
(*
* Test 5: String truncation edge cases
*)
let
test_string_truncation_edge_cases
()
=
let
program_text
=
{
|
@
xdp fn test(ctx:
*xdp_md
) -> xdp_action {
return
2
}
fn main
()
-> i32 {
var
short
:
str
(
6
)
=
"toolong"
//
Will
be
truncated
var
exact
:
str
(
6
)
=
"exact"
//
Fits
exactly
var
tiny
:
str
(
3
)
=
"hi"
//
Much
shorter
than
buffer
return
0
}
|
}
in
try
let
result
=
generate_userspace_code_from_program program_text
"
test_string_truncation
"
in
(*
Should handle all cases safely
*)
check
bool
"
has strlen checks
"
true
(contains_pattern result
"
__src =
\"
toolong
\"
"
);
check
bool
"
has safe strcpy path
"
true
(contains_pattern result
"
__src =
\"
exact
\"
"
);
check
bool
"
has truncation path
"
true
(contains_pattern result
"
strncpy.*var_.*__src.*[0-9]+.*-.*1
"
);
check
bool
"
explicit null termination
"
true
(contains_pattern result
"
var_.*
\\
[.*-.*1
\\
].*=.*'
\\\\
0'
"
);
(*
Should have proper size checking - the runtime checks use the declared buffer size
*)
check
bool
"
size check for short buffer
"
true
(contains_pattern result
"
__src_len.*<.*[0-9]+
"
);
check
bool
"
size check for tiny buffer
"
true
(contains_pattern result
"
__src_len.*<.*[0-9]+
"
);
with
|
exn
-> fail (
"
String truncation test failed:
"
^
Printexc.
to_string
exn
)
(*
* Test 6: Complex string operations together
*)
let
test_complex_string_operations
()
=
let
program_text
=
{
|
@
xdp fn test(ctx:
*xdp_md
) -> xdp_action {
return
2
}
fn main
()
-> i32 {
var
greeting
:
str
(
10
)
=
"Hello"
var
target
:
str
(
10
)
=
"World"
var
punctuation
:
str
(
5
)
=
"!"
var
message
:
str
(
25
)
=
greeting
+
target
var
final_msg
:
str
(
30
)
=
message
+
punctuation
if
(
final_msg
==
"HelloWorld!"
) {
var
first_char
:
char
=
final_msg
[
0
]
var
last_char
:
char
=
final_msg
[
10
]
return
1
}
return
0
}
|
}
in
try
let
result
=
generate_userspace_code_from_program program_text
"
test_complex_strings
"
in
(*
Should have all string operations
*)
check
bool
"
has string assignment
"
true
(contains_pattern result
"
strlen.*__src_len
"
);
check
bool
"
has concatenation
"
true
(contains_pattern result
"
str_concat_[0-9]+
"
);
check
bool
"
has comparison
"
true
(contains_pattern result
"
strcmp.*
\"
HelloWorld!
\"
.*==.*0
"
);
check
bool
"
has indexing
"
true
(contains_pattern result
"
var_.*
\\
[[0-9]+
\\
]
"
);
(*
Should be properly nested and structured
*)
check
bool
"
has conditional with comparison variable
"
true
(contains_pattern result
"
if.*var_
"
);
check
bool
"
has helper function usage
"
true
(contains_pattern result
"
str_concat_[0-9]+
"
);
with
|
exn
-> fail (
"
Complex string operations test failed:
"
^
Printexc.
to_string
exn
)
(*
* Test 7: Empty and single character strings
*)
let
test_empty_and_single_char_strings
()
=
let
program_text
=
{
|
@
xdp fn test(ctx:
*xdp_md
) -> xdp_action {
return
2
}
fn main
()
-> i32 {
var
single
:
str
(
2
)
=
"A"
var
empty_like
:
str
(
1
)
=
""
return
0
}
|
}
in
try
let
result
=
generate_userspace_code_from_program program_text
"
test_edge_strings
"
in
(*
Should handle small strings safely
*)
check
bool
"
handles single char
"
true
(contains_pattern result
"
__src =
\"
A
\"
"
);
check
bool
"
handles empty string
"
true
(contains_pattern result
"
__src =
\"\"
"
);
check
bool
"
size check for single
"
true
(contains_pattern result
"
__src_len.*<.*2
"
);
check
bool
"
size check for empty buffer
"
true
(contains_pattern result
"
__src_len.*<.*1
"
);
(*
Should still use safe string handling
*)
check
bool
"
safe assignment for single
"
true
(contains_pattern result
"
__src =
\"
A
\"
"
);
with
|
exn
-> fail (
"
Empty and single char strings test failed:
"
^
Printexc.
to_string
exn
)
(*
* Test 8: Variable declarations use correct C array syntax
*)
let
test_string_variable_declarations
()
=
let
program_text
=
{
|
@
xdp fn test(ctx:
*xdp_md
) -> xdp_action {
return
2
}
fn main
()
-> i32 {
var
small
:
str
(
16
)
=
"small"
var
medium
:
str
(
64
)
=
"medium"
var
large
:
str
(
256
)
=
"large"
return
0
}
|
}
in
try
let
result
=
generate_userspace_code_from_program program_text
"
test_string_declarations
"
in
(*
Should declare variables with proper C array syntax
*)
check
bool
"
declares char array 16
"
true
(contains_pattern result
"
char var_.*
\\
[16
\\
]
"
);
check
bool
"
declares char array 64
"
true
(contains_pattern result
"
char var_.*
\\
[64
\\
]
"
);
check
bool
"
declares char array 256
"
true
(contains_pattern result
"
char var_.*
\\
[256
\\
]
"
);
(*
Should NOT use incorrect syntax
*)
check
bool
"
no char[N] var syntax
"
false
(contains_pattern result
"
char
\\
[[0-9]+
\\
] var_
"
);
check
bool
"
no str_N_t typedefs
"
false
(contains_pattern result
"
str_[0-9]+_t var_
"
);
with
|
exn
-> fail (
"
String variable declarations test failed:
"
^
Printexc.
to_string
exn
)
(*
* Test 9: String literal and mixed comparisons
*)
let
test_string_literal_and_mixed_comparisons
()
=
let
program_text
=
{
|
@
xdp fn test(ctx:
*xdp_md
) -> xdp_action {
return
2
}
fn main
()
-> i32 {
var
name
:
str
(
20
)
=
"Alice"
var
other
:
str
(
20
)
=
"Bob"
if
(
name
==
"Alice"
) {
return
1
}
if
(
name
!=
other
) {
return
2
}
return
0
}
|
}
in
try
let
result
=
generate_userspace_code_from_program program_text
"
test_string_literal_compare
"
in
(*
Should generate strcmp for equality with string literals
*)
check
bool
"
equality uses strcmp
"
true
(contains_pattern result
"
strcmp.*var_.*
\"
Alice
\"
.*==.*0
"
);
check
bool
"
inequality uses strcmp
"
true
(contains_pattern result
"
strcmp.*var_.*var_.*!=.*0
"
);
check
bool
"
has string literal comparison
"
true
(contains_pattern result
"
strcmp.*var_.*
\"
Alice
\"
"
);
check
bool
"
has variable comparison
"
true
(contains_pattern result
"
strcmp.*var_.*var_
"
);
(*
Should be stored in temp variables then used in conditionals
*)
check
bool
"
assigns comparison result
"
true
(contains_pattern result
"
__binop_.*=.*strcmp
"
);
check
bool
"
uses comparison variable in if
"
true
(contains_pattern result
"
if.*__binop_
"
);
with
|
exn
-> fail (
"
String literal and mixed comparisons test failed:
"
^
Printexc.
to_string
exn
)
(*
* Test suite for string code generation
*)
let
tests
=
[
test_case
"
String assignment code generation
"
`Quick
test_string_assignment_codegen;
test_case
"
String indexing code generation
"
`Quick
test_string_indexing_codegen;
test_case
"
String comparison code generation
"
`Quick
test_string_comparison_codegen;
test_case
"
String concatenation code generation
"
`Quick
test_string_concatenation_codegen;
test_case
"
String truncation edge cases
"
`Quick
test_string_truncation_edge_cases;
test_case
"
Complex string operations
"
`Quick
test_complex_string_operations;
test_case
"
Empty and single character strings
"
`Quick
test_empty_and_single_char_strings;
test_case
"
String variable declarations
"
`Quick
test_string_variable_declarations;
test_case
"
String literal and mixed comparisons
"
`Quick
test_string_literal_and_mixed_comparisons;
]
(*
* Main test runner
*)
let
()
=
Alcotest.
run
"
String Code Generation Tests
"
[
(
"
string_codegen
"
, tests);
]
Back
|
FazBrowse Home
|
New Git URL