Skip to content

Commit 10c4b11

Browse files
committed
[CN-Test-Gen] Expose static hack via CLI flag
1 parent 6fc4ec4 commit 10c4b11

10 files changed

+373
-169
lines changed

backend/cn/bin/main.ml

+58-48
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ let frontend ~macros ~incl_dirs ~incl_files astprints ~filename ~magic_comment_c
7373
idents = [ Alloc.History.(str, sym, None) ]
7474
}
7575
in
76-
let@ _, ail_prog_opt, prog0 =
76+
let@ cabs_tunit_opt, ail_prog_opt, prog0 =
7777
c_frontend_and_elaboration ~cn_init_scope (conf, io) (stdlib, impl) ~filename
7878
in
7979
let@ () =
@@ -83,6 +83,7 @@ let frontend ~macros ~incl_dirs ~incl_files astprints ~filename ~magic_comment_c
8383
else
8484
return ()
8585
in
86+
let cabs_tunit = Option.get cabs_tunit_opt in
8687
let markers_env, ail_prog = Option.get ail_prog_opt in
8788
Tags.set_tagDefs prog0.Core.tagDefs;
8889
let prog1 = Remove_unspecs.rewrite_file prog0 in
@@ -91,7 +92,7 @@ let frontend ~macros ~incl_dirs ~incl_files astprints ~filename ~magic_comment_c
9192
let statement_locs = CStatements.search (snd ail_prog) in
9293
print_log_file ("original", CORE prog0);
9394
print_log_file ("without_unspec", CORE prog1);
94-
return (prog3, (markers_env, ail_prog), statement_locs)
95+
return (cabs_tunit, prog3, (markers_env, ail_prog), statement_locs)
9596

9697

9798
let handle_frontend_error = function
@@ -132,14 +133,15 @@ let with_well_formedness_check
132133
~(* Callbacks *)
133134
handle_error
134135
~(f :
136+
cabs_tunit:CF.Cabs.translation_unit ->
135137
prog5:unit Mucore.file ->
136138
ail_prog:CF.GenTypes.genTypeCategory A.ail_program ->
137139
statement_locs:Cerb_location.t CStatements.LocMap.t ->
138140
paused:_ Typing.pause ->
139141
unit Or_TypeError.t)
140142
=
141143
check_input_file filename;
142-
let prog, (markers_env, ail_prog), statement_locs =
144+
let cabs_tunit, prog, (markers_env, ail_prog), statement_locs =
143145
handle_frontend_error
144146
(frontend
145147
~macros
@@ -169,7 +171,7 @@ let with_well_formedness_check
169171
Typing.run_to_pause Context.empty (Check.check_decls_lemmata_fun_specs prog5)
170172
in
171173
Result.iter_error handle_error (Typing.pause_to_result paused);
172-
f ~prog5 ~ail_prog ~statement_locs ~paused
174+
f ~cabs_tunit ~prog5 ~ail_prog ~statement_locs ~paused
173175
in
174176
Pp.maybe_close_times_channel ();
175177
Result.fold ~ok:(fun () -> exit 0) ~error:handle_error result
@@ -250,7 +252,8 @@ let well_formed
250252
~no_inherit_loc
251253
~magic_comment_char_dollar
252254
~handle_error:(handle_type_error ~json ?output_dir ~serialize_json:json_trace)
253-
~f:(fun ~prog5:_ ~ail_prog:_ ~statement_locs:_ ~paused:_ -> Or_TypeError.return ())
255+
~f:(fun ~cabs_tunit:_ ~prog5:_ ~ail_prog:_ ~statement_locs:_ ~paused:_ ->
256+
Or_TypeError.return ())
254257

255258

256259
let verify
@@ -321,7 +324,7 @@ let verify
321324
~no_inherit_loc
322325
~magic_comment_char_dollar (* Callbacks *)
323326
~handle_error:(handle_type_error ~json ?output_dir ~serialize_json:json_trace)
324-
~f:(fun ~prog5:_ ~ail_prog:_ ~statement_locs:_ ~paused ->
327+
~f:(fun ~cabs_tunit:_ ~prog5:_ ~ail_prog:_ ~statement_locs:_ ~paused ->
325328
let check (functions, global_var_constraints, lemmas) =
326329
let open Typing in
327330
let@ errors = Check.time_check_c_functions (global_var_constraints, functions) in
@@ -413,7 +416,7 @@ let generate_executable_specs
413416
~no_inherit_loc
414417
~magic_comment_char_dollar (* Callbacks *)
415418
~handle_error:(handle_type_error ~json ?output_dir ~serialize_json:json_trace)
416-
~f:(fun ~prog5 ~ail_prog ~statement_locs ~paused:_ ->
419+
~f:(fun ~cabs_tunit:_ ~prog5 ~ail_prog ~statement_locs ~paused:_ ->
417420
Cerb_colour.without_colour
418421
(fun () ->
419422
(try
@@ -457,6 +460,7 @@ let run_tests
457460
max_backtracks
458461
max_unfolds
459462
max_array_length
463+
with_static_hack
460464
input_timeout
461465
null_in_every
462466
seed
@@ -495,25 +499,45 @@ let run_tests
495499
~no_inherit_loc
496500
~magic_comment_char_dollar (* Callbacks *)
497501
~handle_error
498-
~f:(fun ~prog5 ~ail_prog ~statement_locs ~paused:_ ->
502+
~f:(fun ~cabs_tunit ~prog5 ~ail_prog ~statement_locs ~paused:_ ->
503+
let config : TestGeneration.config =
504+
{ num_samples;
505+
max_backtracks;
506+
max_unfolds;
507+
max_array_length;
508+
with_static_hack;
509+
input_timeout;
510+
null_in_every;
511+
seed;
512+
logging_level;
513+
progress_level;
514+
interactive;
515+
until_timeout;
516+
exit_fast;
517+
max_stack_depth;
518+
allowed_depth_failures;
519+
max_generator_size;
520+
random_size_splits;
521+
allowed_size_split_backtracks;
522+
sized_null;
523+
coverage;
524+
disable_passes
525+
}
526+
in
527+
TestGeneration.set_config config;
528+
let _, sigma = ail_prog in
529+
if
530+
List.is_empty
531+
(TestGeneration.functions_under_test ~with_warning:true cabs_tunit sigma prog5)
532+
then (
533+
print_endline "No testable functions, trivially passing";
534+
exit 0);
535+
if not (Sys.file_exists output_dir) then (
536+
print_endline ("Directory \"" ^ output_dir ^ "\" does not exist.");
537+
Sys.mkdir output_dir 0o777;
538+
print_endline ("Created directory \"" ^ output_dir ^ "\" with full permissions."));
499539
Cerb_colour.without_colour
500540
(fun () ->
501-
if
502-
prog5
503-
|> Executable_spec_extract.collect_instrumentation
504-
|> fst
505-
|> List.filter (fun (inst : Executable_spec_extract.instrumentation) ->
506-
Option.is_some inst.internal)
507-
|> List.is_empty
508-
then (
509-
print_endline "No testable functions, trivially passing";
510-
exit 0);
511-
if not (Sys.file_exists output_dir) then (
512-
print_endline ("Directory \"" ^ output_dir ^ "\" does not exist.");
513-
Sys.mkdir output_dir 0o777;
514-
print_endline
515-
("Created directory \"" ^ output_dir ^ "\" with full permissions."));
516-
let _, sigma = ail_prog in
517541
Cn_internal_to_ail.augment_record_map (BaseTypes.Record []);
518542
(try
519543
Executable_spec.main
@@ -528,35 +552,12 @@ let run_tests
528552
statement_locs
529553
with
530554
| e -> handle_error_with_user_guidance ~label:"CN-Exec" e);
531-
let config : TestGeneration.config =
532-
{ num_samples;
533-
max_backtracks;
534-
max_unfolds;
535-
max_array_length;
536-
input_timeout;
537-
null_in_every;
538-
seed;
539-
logging_level;
540-
progress_level;
541-
interactive;
542-
until_timeout;
543-
exit_fast;
544-
max_stack_depth;
545-
allowed_depth_failures;
546-
max_generator_size;
547-
random_size_splits;
548-
allowed_size_split_backtracks;
549-
sized_null;
550-
coverage;
551-
disable_passes
552-
}
553-
in
554555
(try
555556
TestGeneration.run
556557
~output_dir
557558
~filename
558559
~without_ownership_checking
559-
config
560+
cabs_tunit
560561
sigma
561562
prog5
562563
with
@@ -949,6 +950,14 @@ module Testing_flags = struct
949950
& info [ "max-array-length" ] ~doc)
950951

951952

953+
let with_static_hack =
954+
let doc =
955+
"(HACK) Use an `#include` instead of linking to build testing. Necessary until \
956+
https://github.com/rems-project/cerberus/issues/784 or equivalent."
957+
in
958+
Arg.(value & flag & info [ "with-static-hack" ] ~doc)
959+
960+
952961
let input_timeout =
953962
let doc = "Timeout for discarding a generation attempt (ms)" in
954963
Arg.(
@@ -1104,6 +1113,7 @@ let testing_cmd =
11041113
$ Testing_flags.gen_backtrack_attempts
11051114
$ Testing_flags.gen_max_unfolds
11061115
$ Testing_flags.max_array_length
1116+
$ Testing_flags.with_static_hack
11071117
$ Testing_flags.input_timeout
11081118
$ Testing_flags.null_in_every
11091119
$ Testing_flags.seed

backend/cn/lib/testGeneration/buildScript.ml

+65-14
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ let attempt cmd success failure =
4141
^^ string "fi"
4242

4343

44-
let compile ~test_file =
44+
let compile ~filename_base =
4545
string "# Compile"
4646
^^ hardline
4747
^^ attempt
@@ -52,22 +52,65 @@ let compile ~test_file =
5252
"-c";
5353
"\"-I${RUNTIME_PREFIX}/include/\"";
5454
"-o";
55-
"\"./" ^ Filename.chop_extension test_file ^ ".o\"";
56-
"\"./" ^ test_file ^ "\""
55+
"\"./" ^ filename_base ^ "_test.o\"";
56+
"\"./" ^ filename_base ^ "_test.c\""
5757
]
5858
@
5959
if Config.is_coverage () then
6060
[ "--coverage" ]
6161
else
6262
[]))
63-
"Compiled C files."
64-
"Failed to compile C files in ${TEST_DIR}."
63+
("Compiled '" ^ filename_base ^ "_test.c'.")
64+
("Failed to compile '" ^ filename_base ^ "_test.c' in ${TEST_DIR}.")
65+
^^ (if Config.with_static_hack () then
66+
empty
67+
else
68+
twice hardline
69+
^^ attempt
70+
(String.concat
71+
" "
72+
([ "cc";
73+
"-g";
74+
"-c";
75+
"\"-I${RUNTIME_PREFIX}/include/\"";
76+
"-o";
77+
"\"./" ^ filename_base ^ "-exec.o\"";
78+
"\"./" ^ filename_base ^ "-exec.c\""
79+
]
80+
@
81+
if Config.is_coverage () then
82+
[ "--coverage" ]
83+
else
84+
[]))
85+
("Compiled '" ^ filename_base ^ "-exec.c'.")
86+
("Failed to compile '" ^ filename_base ^ "-exec.c' in ${TEST_DIR}.")
87+
^^ twice hardline
88+
^^ attempt
89+
(String.concat
90+
" "
91+
([ "cc";
92+
"-g";
93+
"-c";
94+
"\"-I${RUNTIME_PREFIX}/include/\"";
95+
"-o";
96+
"\"./cn.o\"";
97+
"\"./cn.c\""
98+
]
99+
@
100+
if Config.is_coverage () then
101+
[ "--coverage" ]
102+
else
103+
[]))
104+
"Compiled 'cn.c'."
105+
"Failed to compile 'cn.c' in ${TEST_DIR}.")
65106
^^ hardline
66107

67108

68-
let link ~test_file =
109+
let link ~filename_base =
69110
string "# Link"
70111
^^ hardline
112+
^^ string "echo"
113+
^^ twice hardline
71114
^^ attempt
72115
(String.concat
73116
" "
@@ -76,7 +119,13 @@ let link ~test_file =
76119
"\"-I${RUNTIME_PREFIX}/include\"";
77120
"-o";
78121
"\"./tests.out\"";
79-
Filename.chop_extension test_file ^ ".o";
122+
(filename_base
123+
^ "_test.o"
124+
^
125+
if Config.with_static_hack () then
126+
""
127+
else
128+
" " ^ filename_base ^ "-exec.o cn.o");
80129
"\"${RUNTIME_PREFIX}/libcn.a\""
81130
]
82131
@
@@ -157,17 +206,19 @@ let run () =
157206
in
158207
string "# Run"
159208
^^ hardline
209+
^^ string "echo"
210+
^^ twice hardline
160211
^^ cmd
161212
^^ hardline
162213
^^ string "test_exit_code=$? # Save tests exit code for later"
163214
^^ hardline
164215

165216

166-
let coverage ~test_file =
217+
let coverage ~filename_base =
167218
string "# Coverage"
168219
^^ hardline
169220
^^ attempt
170-
("gcov \"" ^ test_file ^ "\"")
221+
("gcov \"" ^ filename_base ^ "_test.c\"")
171222
"Recorded coverage via gcov."
172223
"Failed to record coverage."
173224
^^ twice hardline
@@ -178,22 +229,22 @@ let coverage ~test_file =
178229
^^ twice hardline
179230
^^ attempt
180231
"genhtml --output-directory html \"coverage.info\""
181-
"Generated HTML report at \\\"${TEST_DIR}/html/\\\"."
232+
"Generated HTML report at '${TEST_DIR}/html/'."
182233
"Failed to generate HTML report."
183234
^^ hardline
184235

185236

186-
let generate ~(output_dir : string) ~(test_file : string) : Pp.document =
237+
let generate ~(output_dir : string) ~(filename_base : string) : Pp.document =
187238
setup ~output_dir
188239
^^ hardline
189-
^^ compile ~test_file
240+
^^ compile ~filename_base
190241
^^ hardline
191-
^^ link ~test_file
242+
^^ link ~filename_base
192243
^^ hardline
193244
^^ run ()
194245
^^ hardline
195246
^^ (if Config.is_coverage () then
196-
coverage ~test_file ^^ hardline
247+
coverage ~filename_base ^^ hardline
197248
else
198249
empty)
199250
^^ string "popd > /dev/null"
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
val generate : output_dir:string -> test_file:string -> Pp.document
1+
val generate : output_dir:string -> filename_base:string -> Pp.document

0 commit comments

Comments
 (0)