Making Test Determinator parametric to Java and Clang

Reviewed By: martinoluca

Differential Revision: D8010835

fbshipit-source-id: 3182c79
master
Dino Distefano 7 years ago committed by Facebook Github Bot
parent 9ca945aa2f
commit d922b37ab8

@ -1544,6 +1544,14 @@ and max_nesting =
skipped. If omitted, all levels are shown." skipped. If omitted, all levels are shown."
and method_decls_info =
CLOpt.mk_string_opt ~long:"method-decls-info"
"Specifies the file containing the method declarations info (eg. start line, end line, \
class, method name, etc.) when Infer is run Test Determinator mode. Used in combination with \
other options as follows: $(b,--test-determinator --modified-lines modified_line_file \
--profiler-sample profiler_sample_file --method-decls-info minfo.json)"
and merge = and merge =
CLOpt.mk_bool ~deprecated:["merge"] ~long:"merge" CLOpt.mk_bool ~deprecated:["merge"] ~long:"merge"
~in_help:InferCommand.[(Analyze, manual_buck_flavors)] ~in_help:InferCommand.[(Analyze, manual_buck_flavors)]
@ -1561,10 +1569,11 @@ and ml_buckets =
and modified_lines = and modified_lines =
CLOpt.mk_string ~long:"modified-lines" ~default:"" CLOpt.mk_string_opt ~long:"modified-lines"
"Specifies the file containing the modified lines when Infer is run Test Determinator mode. \ "Specifies the file containing the modified lines when Infer is run Test Determinator mode. \
--test-determinator --modified-lines modified_lines_file --profiler-sample \ Used in combination with other options as follows:\n \
profiler_sample_file" $(b, --test-determinator --modified-lines modified_lines_file --profiler-sample \
profiler_sample_file)"
and modified_targets = and modified_targets =
@ -2031,9 +2040,8 @@ and symops_per_iteration =
and test_determinator = and test_determinator =
CLOpt.mk_bool ~long:"test-determinator" ~default:false CLOpt.mk_bool ~long:"test-determinator" ~default:false
"Run infer in Test Determinator mode. It is used together with the --modified-lines and \ "Run infer in Test Determinator mode. It is used together with the --modified-lines and \
--test-profiler flags \n \ --test-profiler flags which speficy the relevant arguments. E.g. $(b, --test-determinator \
which speficy the relevant arguments. E.g. --test-determinator --modified-lines \ --modified-lines modified_line_file --profiler-sample profiler_sample_file)"
modified_line_file --profiler-sample profiler_sample_file"
and test_filtering = and test_filtering =
@ -2041,11 +2049,12 @@ and test_filtering =
"List all the files Infer can report on (should be called from the root of the project)" "List all the files Infer can report on (should be called from the root of the project)"
and profiler_sample = and profiler_samples =
CLOpt.mk_string ~long:"profiler-sample" ~default:"" CLOpt.mk_string_opt ~long:"profiler-samples"
"Specifies the file containing the profiler samples when Infer is run Test Determinator mode. \ "Specifies the file containing the profiler samples when Infer is run Test Determinator mode. \
--test-determinator --modified-lines modified_line_file --profiler-sample \ Used in combination with other options as follows:\n \
profiler_samples_file" $(b,--test-determinator --modified-lines modified_line_file --profiler-samples \
profiler_samples_file)"
and testing_mode = and testing_mode =
@ -2650,6 +2659,8 @@ and log_file = !log_file
and max_nesting = !max_nesting and max_nesting = !max_nesting
and method_decls_info = !method_decls_info
and merge = !merge and merge = !merge
and ml_buckets = !ml_buckets and ml_buckets = !ml_buckets
@ -2824,7 +2835,7 @@ and test_determinator = !test_determinator
and test_filtering = !test_filtering and test_filtering = !test_filtering
and profiler_sample = !profiler_sample and profiler_samples = !profiler_samples
and testing_mode = !testing_mode and testing_mode = !testing_mode

@ -493,6 +493,8 @@ val log_file : string
val max_nesting : int option val max_nesting : int option
val method_decls_info : string option
val merge : bool val merge : bool
val ml_buckets : val ml_buckets :
@ -500,7 +502,7 @@ val ml_buckets :
val models_mode : bool val models_mode : bool
val modified_lines : string val modified_lines : string option
val modified_targets : string option val modified_targets : string option
@ -626,7 +628,7 @@ val test_determinator : bool
val test_filtering : bool val test_filtering : bool
val profiler_sample : string val profiler_samples : string option
val testing_mode : bool val testing_mode : bool

@ -120,56 +120,61 @@ let () =
prepare_events_logging () ; prepare_events_logging () ;
if Config.debug_mode && CLOpt.is_originator then if Config.debug_mode && CLOpt.is_originator then
L.progress "Logs in %s@." (Config.results_dir ^/ Config.log_file) ; L.progress "Logs in %s@." (Config.results_dir ^/ Config.log_file) ;
( match Config.command with ( if Config.test_determinator then (
| Analyze -> TestDeterminator.test_to_run_java Config.modified_lines Config.profiler_samples
run Driver.Analyze Config.method_decls_info ;
| Capture | Compile | Run -> TestDeterminator.print_test_to_run () )
run (Lazy.force Driver.mode_from_command_line) else
| Report -> match Config.command with
InferPrint.main ~report_json:None | Analyze ->
| ReportDiff -> run Driver.Analyze
(* at least one report must be passed in input to compute differential *) | Capture | Compile | Run ->
( match (Config.report_current, Config.report_previous) with run (Lazy.force Driver.mode_from_command_line)
| None, None -> | Report ->
L.(die UserError) InferPrint.main ~report_json:None
"Expected at least one argument among '--report-current' and '--report-previous'" | ReportDiff ->
| _ -> (* at least one report must be passed in input to compute differential *)
() ) ; ( match (Config.report_current, Config.report_previous) with
ReportDiff.reportdiff ~current_report:Config.report_current | None, None ->
~previous_report:Config.report_previous L.(die UserError)
| Diff -> "Expected at least one argument among '--report-current' and '--report-previous'"
Diff.diff (Lazy.force Driver.mode_from_command_line) | _ ->
| Explore when Config.procedures -> () ) ;
L.result "%a" ReportDiff.reportdiff ~current_report:Config.report_current
Config.( ~previous_report:Config.report_previous
Procedures.pp_all ?filter:procedures_filter ~proc_name:procedures_name | Diff ->
~attr_kind:procedures_definedness ~source_file:procedures_source_file Diff.diff (Lazy.force Driver.mode_from_command_line)
~proc_attributes:procedures_attributes) | Explore when Config.procedures ->
() L.result "%a"
| Explore when Config.source_files -> Config.(
L.result "%a" Procedures.pp_all ?filter:procedures_filter ~proc_name:procedures_name
(SourceFiles.pp_all ?filter:Config.source_files_filter ~cfgs:Config.source_files_cfgs ~attr_kind:procedures_definedness ~source_file:procedures_source_file
~type_environment:Config.source_files_type_environment ~proc_attributes:procedures_attributes)
~procedure_names:Config.source_files_procedure_names ()
~freshly_captured:Config.source_files_freshly_captured) | Explore when Config.source_files ->
() L.result "%a"
| Explore -> (SourceFiles.pp_all ?filter:Config.source_files_filter ~cfgs:Config.source_files_cfgs
let if_some key opt args = ~type_environment:Config.source_files_type_environment
match opt with None -> args | Some arg -> key :: string_of_int arg :: args ~procedure_names:Config.source_files_procedure_names
in ~freshly_captured:Config.source_files_freshly_captured)
let if_true key opt args = if not opt then args else key :: args in ()
let if_false key opt args = if opt then args else key :: args in | Explore ->
let args = let if_some key opt args =
if_some "--max-level" Config.max_nesting @@ if_true "--only-show" Config.only_show match opt with None -> args | Some arg -> key :: string_of_int arg :: args
@@ if_false "--no-source" Config.source_preview @@ if_true "--html" Config.html in
@@ if_some "--select" Config.select ["-o"; Config.results_dir] let if_true key opt args = if not opt then args else key :: args in
in let if_false key opt args = if opt then args else key :: args in
let prog = Config.lib_dir ^/ "python" ^/ "inferTraceBugs" in let args =
if is_error (Unix.waitpid (Unix.fork_exec ~prog ~argv:(prog :: args) ())) then if_some "--max-level" Config.max_nesting @@ if_true "--only-show" Config.only_show
L.external_error @@ if_false "--no-source" Config.source_preview @@ if_true "--html" Config.html
"** Error running the reporting script:@\n** %s %s@\n** See error above@." prog @@ if_some "--select" Config.select ["-o"; Config.results_dir]
(String.concat ~sep:" " args) in
| Events -> let prog = Config.lib_dir ^/ "python" ^/ "inferTraceBugs" in
EventLogger.dump () ) ; if is_error (Unix.waitpid (Unix.fork_exec ~prog ~argv:(prog :: args) ())) then
L.external_error
"** Error running the reporting script:@\n** %s %s@\n** See error above@." prog
(String.concat ~sep:" " args)
| Events ->
EventLogger.dump () ) ;
(* to make sure the exitcode=0 case is logged, explicitly invoke exit *) (* to make sure the exitcode=0 case is logged, explicitly invoke exit *)
L.exit 0 L.exit 0

@ -264,7 +264,7 @@ module JNI = struct
end end
end end
let create ~classname ~methodname ~signature ~kind = let create ~classname ~methodname ~signature =
let name = Typ.Name.Java.from_string classname in let name = Typ.Name.Java.from_string classname in
let args, ret_typ = JNI.parse_method_str signature in let args, ret_typ = JNI.parse_method_str signature in
let java_type_args = List.map ~f:JNI.to_java_type args in let java_type_args = List.map ~f:JNI.to_java_type args in
@ -275,7 +275,9 @@ let create ~classname ~methodname ~signature ~kind =
then None then None
else Some (JNI.to_java_type ret_typ) else Some (JNI.to_java_type ret_typ)
in in
Typ.Procname.Java (Typ.Procname.Java.make name java_type_ret_typ methodname java_type_args kind) Typ.Procname.Java
(Typ.Procname.Java.make name java_type_ret_typ methodname java_type_args
Typ.Procname.Java.Non_Static)
type labeled_profiler_sample = string * ProfilerSample.t [@@deriving compare] type labeled_profiler_sample = string * ProfilerSample.t [@@deriving compare]
@ -300,9 +302,7 @@ let from_json j =
; ("signature", `String signature) ; ("signature", `String signature)
; _ ] ; _ ]
:: tl -> :: tl ->
let procname = let procname = create ~classname ~methodname ~signature in
create ~kind:Typ.Procname.Java.Non_Static ~classname ~methodname ~signature
in
parse_json tl (procname :: acc) parse_json tl (procname :: acc)
| [] -> | [] ->
acc acc

@ -48,3 +48,5 @@ val equal_labeled_profiler_sample : labeled_profiler_sample -> labeled_profiler_
val from_json_string : string -> labeled_profiler_sample list val from_json_string : string -> labeled_profiler_sample list
val from_json_file : string -> labeled_profiler_sample list val from_json_file : string -> labeled_profiler_sample list
val create : classname:string -> methodname:string -> signature:string -> ProfilerSample.elt

@ -36,8 +36,6 @@ let do_source_file linereader classes program tenv source_basename package_opt s
JFrontend.compute_source_icfg linereader classes program tenv source_basename package_opt JFrontend.compute_source_icfg linereader classes program tenv source_basename package_opt
source_file source_file
in in
if Config.test_determinator then
TestDeterminator.test_to_run source_file cfg Config.modified_lines Config.profiler_sample ;
store_icfg source_file cfg store_icfg source_file cfg

@ -7,103 +7,253 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*) *)
module L = Logging module L = Logging
module F = Format
open JavaProfilerSamples open JavaProfilerSamples
open! IStd open! IStd
module LineRangeMap = Caml.Map.Make (struct module RangeMap = Caml.Map.Make (struct
type t = Typ.Procname.t type t = Typ.Procname.t
let compare = Typ.Procname.compare let compare = Typ.Procname.compare
end) end)
let update_line_range_map pdesc map = let initialized_test_determinator = ref false
let start_node = Procdesc.get_start_node pdesc in
let exit_node = Procdesc.get_exit_node pdesc in
let range = (Procdesc.Node.get_loc start_node, Procdesc.Node.get_loc exit_node) in
let key = Procdesc.get_proc_name pdesc in
LineRangeMap.add key range map
let is_test_determinator_init () = !initialized_test_determinator
module MethodRangeMap = struct
let map : (Location.t * Location.t) RangeMap.t ref = ref RangeMap.empty
let method_range_map () = !map
let split_class_method_name qualified_method_name =
String.rsplit2_exn qualified_method_name ~on:'.'
let create_java_method_range_map code_graph_file' =
match code_graph_file' with
| Some code_graph_file ->
let open Java_method_decl_j in
let json_string =
match Utils.read_file code_graph_file with
| Ok cl_list ->
let json = List.fold cl_list ~init:"" ~f:(fun acc s -> acc ^ s) in
json
| Error _ ->
L.die UserError "Could not read file %s" code_graph_file
in
let method_decls = java_method_decls_of_string json_string in
let map' =
List.fold method_decls ~init:RangeMap.empty ~f:(fun acc decl ->
let start_location =
{ Location.line= decl.start_line
; col= -1
; file= SourceFile.create ~warn_on_error:false decl.source_file }
in
let end_location =
{ Location.line= decl.end_line
; col= -1
; file= SourceFile.create ~warn_on_error:false decl.source_file }
in
let range = (start_location, end_location) in
let classname, methodname = split_class_method_name decl.method_name in
let signature = match decl.signature with Some s -> s | _ -> "" in
let key = JavaProfilerSamples.create ~classname ~methodname ~signature in
RangeMap.add key range acc )
in
map := map'
| _ ->
L.die UserError "Missing method declaration info argument"
let create_clang_method_range_map cfg =
let update_method_range_map pdesc =
let start_node = Procdesc.get_start_node pdesc in
let exit_node = Procdesc.get_exit_node pdesc in
let range = (Procdesc.Node.get_loc start_node, Procdesc.Node.get_loc exit_node) in
let key = Procdesc.get_proc_name pdesc in
map := RangeMap.add key range !map
in
Typ.Procname.Hash.iter (fun _ pdesc -> update_method_range_map pdesc) cfg
let pp_map fmt () =
let pp_map' fmt m =
RangeMap.iter
(fun key range ->
F.fprintf fmt "@\n %a --> (%a,%a)" Typ.Procname.pp key Location.pp (fst range)
Location.pp (snd range) )
m
in
F.fprintf fmt "@\n--- Method Range Map ---%a@\n--- End Method Range Map --- @\n" pp_map' !map
end
module DiffLines = struct
(* This is a map
file name |--> {set of changed line }
*)
let map : int list String.Map.t ref = ref String.Map.empty
let changed_lines_map () = !map
(* Read the file containing info on changed lines and populate the map *)
let init_changed_lines_map changed_lines_file' =
match changed_lines_file' with
| Some changed_lines_file
-> (
L.progress "@\n Initializing modified lines map from file '%s'... " changed_lines_file ;
match Utils.read_file changed_lines_file with
| Ok cl_list ->
let changed_lines =
List.fold cl_list ~init:String.Map.empty ~f:(fun acc cl_item ->
let fname, cl = String.rsplit2_exn ~on:':' cl_item in
String.Map.set acc ~key:fname ~data:(FileDiff.parse_unix_diff cl) )
in
L.progress " done! @\n" ;
map := changed_lines
| Error _ ->
L.die UserError "Could not read file %s" changed_lines_file )
| _ ->
L.die UserError "Missing modified lines argument"
let print_changed_lines () =
L.(debug Analysis Medium) "@\n--- Changed Lines Map --- " ;
String.Map.iteri !map ~f:(fun ~key:k ~data:d ->
L.(debug Analysis Medium) "\n %s --> [" k ;
List.iter d ~f:(L.(debug Analysis Medium) " %i ") ;
L.(debug Analysis Medium) " ] " ) ;
L.(debug Analysis Medium) "@\n--- End Changed Lines Map --- @\n"
end
let pp_profiler_sample_set fmt s =
F.fprintf fmt "size = %i" (ProfilerSample.cardinal s) ;
ProfilerSample.iter (fun m -> F.fprintf fmt "@\n > %a " Typ.Procname.pp m) s
module TestSample = struct
let labeled_test_samples = ref []
let test_sample () = !labeled_test_samples
let init_test_sample test_samples_file' =
match test_samples_file' with
| Some test_samples_file ->
L.progress "@\nReading Profiler Samples File '%s'...." test_samples_file ;
let ts = JavaProfilerSamples.from_json_file test_samples_file in
labeled_test_samples := ts
| _ ->
L.die UserError "Missing profiler samples argument"
let pp_map fmt () =
List.iter !labeled_test_samples ~f:(fun (label, profiler_samples) ->
F.fprintf fmt "=== Samples for %s ===@\n%a@\n=== End Samples for %s ===@\n" label
pp_profiler_sample_set profiler_samples label )
end
let in_range l range = l >= (fst range).Location.line && l <= (snd range).Location.line let in_range l range = l >= (fst range).Location.line && l <= (snd range).Location.line
let affected_methods line_range_map changed_lines = let affected_methods method_range_map changed_lines =
LineRangeMap.fold RangeMap.fold
(fun key range acc -> (fun key range acc ->
if List.exists ~f:(fun l -> in_range l range) changed_lines then ProfilerSample.add key acc if List.exists ~f:(fun l -> in_range l range) changed_lines then
(*L.progress "@\n ADDING '%a' in affected methods..." Typ.Procname.pp key ; *)
ProfilerSample.add key acc
else acc ) else acc )
line_range_map ProfilerSample.empty method_range_map ProfilerSample.empty
let compute_affected_methods fname cfg files_changed_lines_map = let compute_affected_methods_java changed_lines_map method_range_map =
L.(debug Capture Verbose) "@\n Looking for file %s in files_changed_line_map @\n" fname ; let affected_methods =
match String.Map.find files_changed_lines_map fname with String.Map.fold changed_lines_map ~init:ProfilerSample.empty ~f:(fun ~key:_ ~data acc ->
let am = affected_methods method_range_map data in
ProfilerSample.union am acc )
in
L.progress "== Resulting Affected Methods ==@\n%a@\n== End Affected Methods ==@\n"
pp_profiler_sample_set affected_methods ;
affected_methods
let compute_affected_methods_clang source_file changed_lines_map method_range_map =
let fname = SourceFile.to_rel_path source_file in
L.progress "@\n Looking for file %s in changed-line map..." fname ;
match String.Map.find changed_lines_map fname with
| Some changed_lines -> | Some changed_lines ->
let line_range_map : (Location.t * Location.t) LineRangeMap.t = LineRangeMap.empty in L.progress " found!@\n" ;
let line_range_map' = let affected_methods = affected_methods method_range_map changed_lines in
Typ.Procname.Hash.fold L.progress "== Resulting Affected Methods ==@\n%a@\n== End Affected Methods ==@\n"
(fun _ pdesc acc -> update_line_range_map pdesc acc) pp_profiler_sample_set affected_methods ;
cfg line_range_map
in
L.(debug Capture Verbose) "@\n Line Range Map" ;
LineRangeMap.iter
(fun key range ->
L.(debug Capture Verbose)
"@\n %a --> (%a,%a)" Typ.Procname.pp key Location.pp (fst range) Location.pp
(snd range) )
line_range_map' ;
L.(debug Capture Verbose) "@\n End Line Range Map @\n" ;
let affected_methods = affected_methods line_range_map' changed_lines in
L.(debug Capture Verbose) "@\n == Start Printing Affected Methods == " ;
ProfilerSample.iter
(fun m -> L.(debug Capture Verbose) "@\n METHOD> %a " Typ.Procname.pp m)
affected_methods ;
L.(debug Capture Verbose) "@\n == End Printing Affected Methods == @\n" ;
affected_methods affected_methods
| None -> | None ->
L.(debug Capture Verbose) L.progress "@\n%s not found in changed-line map. Nothing else to do for it.@\n" fname ;
"@\n File name %s was not found in files_changed_line_map @\n" fname ;
ProfilerSample.empty ProfilerSample.empty
let read_changed_lines_file changed_lines_file = let relevant_tests = ref []
match Utils.read_file changed_lines_file with
| Ok cl_list ->
let changed_lines =
List.fold cl_list ~init:String.Map.empty ~f:(fun acc cl_item ->
let fname, cl = String.rsplit2_exn ~on:':' cl_item in
String.Map.set acc ~key:fname ~data:(FileDiff.parse_unix_diff cl) )
in
changed_lines
| Error _ ->
String.Map.empty
let _get_relevant_test_to_run () = !relevant_tests
let print_test_to_run test_to_run = let print_test_to_run () =
L.result "@\n [Result Test Determinator:] Test to run = [" ; L.progress "@\n [TEST DETERMINATOR] Relevant Tests to run = [" ;
List.iter ~f:(L.result " %s ") test_to_run ; List.iter ~f:(L.progress " %s ") !relevant_tests ;
L.result " ] @\n" L.progress " ] @\n" ;
let json = `List (List.map ~f:(fun t -> `String t) !relevant_tests) in
Yojson.Basic.to_file (Config.results_dir ^/ "test_determinator.json") json
let print_changed_lines changed_lines = let init_clang cfg changed_lines_file test_samples_file =
L.(debug Capture Verbose) "@\n Changed lines = {" ; DiffLines.init_changed_lines_map changed_lines_file ;
String.Map.iteri changed_lines ~f:(fun ~key:k ~data:d -> DiffLines.print_changed_lines () ;
L.(debug Capture Verbose) "\n %s --> [" k ; MethodRangeMap.create_clang_method_range_map cfg ;
List.iter d ~f:(L.(debug Capture Verbose) " %i ") ; L.(debug Analysis Medium) "%a@\n" MethodRangeMap.pp_map () ;
L.(debug Capture Verbose) " ] " ) ; TestSample.init_test_sample test_samples_file ;
L.(debug Capture Verbose) "@\n } @\n" L.(debug Analysis Medium) "%a@\n" TestSample.pp_map () ;
initialized_test_determinator := true
let init_java changed_lines_file test_samples_file code_graph_file =
DiffLines.init_changed_lines_map changed_lines_file ;
DiffLines.print_changed_lines () ;
MethodRangeMap.create_java_method_range_map code_graph_file ;
L.(debug Analysis Medium) "%a@\n" MethodRangeMap.pp_map () ;
TestSample.init_test_sample test_samples_file ;
L.(debug Analysis Medium) "%a@\n" TestSample.pp_map () ;
initialized_test_determinator := true
(* test_to_run = { n | Affected_Method /\ ts_n != 0 } *) (* test_to_run = { n | Affected_Method /\ ts_n != 0 } *)
let test_to_run source_file cfg changed_lines_file test_samples_file = let _test_to_run_clang source_file cfg changed_lines_file test_samples_file =
L.(debug Capture Verbose) "@\n ***** Start Test Determinator ***** @\n" ; L.progress "@\n ***** Start Test Determinator for %s ***** @\n"
let fname = SourceFile.to_rel_path source_file in (SourceFile.to_string source_file) ;
let changed_lines = read_changed_lines_file changed_lines_file in if is_test_determinator_init () then () else init_clang cfg changed_lines_file test_samples_file ;
print_changed_lines changed_lines ; let affected_methods =
let test_samples = JavaProfilerSamples.from_json_file test_samples_file in compute_affected_methods_clang source_file (DiffLines.changed_lines_map ())
let affected_methods = compute_affected_methods fname cfg changed_lines in (MethodRangeMap.method_range_map ())
in
let test_to_run =
if ProfilerSample.is_empty affected_methods then []
else
List.fold (TestSample.test_sample ()) ~init:[] ~f:(fun acc (label, profiler_samples) ->
let intersection = ProfilerSample.inter affected_methods profiler_samples in
if ProfilerSample.is_empty intersection then acc else label :: acc )
in
relevant_tests := List.append test_to_run !relevant_tests
let test_to_run_java changed_lines_file test_samples_file code_graph_file =
L.progress "@\n ***** Start Test Determinator ***** @\n" ;
if is_test_determinator_init () then ()
else init_java changed_lines_file test_samples_file code_graph_file ;
let affected_methods =
compute_affected_methods_java (DiffLines.changed_lines_map ())
(MethodRangeMap.method_range_map ())
in
let test_to_run = let test_to_run =
List.fold test_samples ~init:[] ~f:(fun acc (label, profiler_samples) -> if ProfilerSample.is_empty affected_methods then []
let intersection = ProfilerSample.inter affected_methods profiler_samples in else
if ProfilerSample.is_empty intersection then acc else label :: acc ) List.fold (TestSample.test_sample ()) ~init:[] ~f:(fun acc (label, profiler_samples) ->
let intersection = ProfilerSample.inter affected_methods profiler_samples in
if ProfilerSample.is_empty intersection then acc else label :: acc )
in in
print_test_to_run test_to_run relevant_tests := List.append test_to_run !relevant_tests

@ -7,4 +7,11 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*) *)
val test_to_run : SourceFile.t -> Procdesc.t Typ.Procname.Hash.t -> string -> string -> unit val test_to_run_java : string option -> string option -> string option -> unit
val _test_to_run_clang :
SourceFile.t -> Procdesc.t Typ.Procname.Hash.t -> string option -> string option -> unit
val print_test_to_run : unit -> unit
val _get_relevant_test_to_run : unit -> string list

Loading…
Cancel
Save