From 858c5aab018698e32cd25bca313b97bce146fbf2 Mon Sep 17 00:00:00 2001 From: Martino Luca Date: Fri, 18 May 2018 05:03:08 -0700 Subject: [PATCH] [Test determinator] New format for the profiler samples passed in input to TD Reviewed By: ddino Differential Revision: D8041736 fbshipit-source-id: 5bd8ea0 --- infer/src/base/Config.ml | 4 +- infer/src/java/JavaProfilerSamples.ml | 70 ++++++---- infer/src/java/JavaProfilerSamples.mli | 8 +- infer/src/java/testDeterminator.ml | 22 +-- infer/src/unit/JavaProfilerSamplesTest.ml | 132 +++++++----------- .../test_determinator/test_samples | 2 - .../test_determinator/test_samples.json | 50 +++++++ .../codetoanalyze/test_determinator/ts1.json | 20 --- .../codetoanalyze/test_determinator/ts2.json | 20 --- 9 files changed, 155 insertions(+), 173 deletions(-) delete mode 100644 infer/tests/codetoanalyze/test_determinator/test_samples create mode 100644 infer/tests/codetoanalyze/test_determinator/test_samples.json delete mode 100644 infer/tests/codetoanalyze/test_determinator/ts1.json delete mode 100644 infer/tests/codetoanalyze/test_determinator/ts2.json diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index f917a4c61..aaaeba5eb 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -2043,9 +2043,9 @@ and test_filtering = and profiler_sample = CLOpt.mk_string ~long:"profiler-sample" ~default:"" - "Specifies the file containing the profiler sample 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 \ - profiler_sample_file" + profiler_samples_file" and testing_mode = diff --git a/infer/src/java/JavaProfilerSamples.ml b/infer/src/java/JavaProfilerSamples.ml index 48974e80f..be3688036 100644 --- a/infer/src/java/JavaProfilerSamples.ml +++ b/infer/src/java/JavaProfilerSamples.ml @@ -278,38 +278,46 @@ let create ~classname ~methodname ~signature ~kind = Typ.Procname.Java (Typ.Procname.Java.make name java_type_ret_typ methodname java_type_args kind) -let create_static = create ~kind:Typ.Procname.Java.Static - -let create_non_static = create ~kind:Typ.Procname.Java.Non_Static - -let from_json json = - let methods = - match json with - | `Assoc [_; ("methods", `List j); _] -> - j - | _ -> - L.(die UserError "Unexpected JSON input for the collection of methods") - in - let rec parse_json j acc = - match j with - | `Assoc - [ ("class", `String classname) - ; _ - ; ("method", `String methodname) - ; ("signature", `String signature) - ; _ ] - :: tl -> - let static_procname = create_static ~classname ~methodname ~signature in - let non_static_procname = create_non_static ~classname ~methodname ~signature in - parse_json tl (static_procname :: non_static_procname :: acc) - | [] -> - acc - | _ -> - L.(die UserError "Unexpected JSON input for the description of a single method") +type labeled_profiler_sample = string * ProfilerSample.t [@@deriving compare] + +let equal_labeled_profiler_sample = [%compare.equal : labeled_profiler_sample] + +let from_json j = + let parse_profiler_result label result = + let methods = + match result with + | `Assoc [_; _; _; _; ("methods", `List j); _; _] -> + j + | _ -> + L.(die UserError "Unexpected JSON input for the collection of methods") + in + let rec parse_json j acc = + match j with + | `Assoc + [ ("class", `String classname) + ; _ + ; ("method", `String methodname) + ; ("signature", `String signature) + ; _ ] + :: tl -> + let procname = + create ~kind:Typ.Procname.Java.Non_Static ~classname ~methodname ~signature + in + parse_json tl (procname :: acc) + | [] -> + acc + | _ -> + L.(die UserError "Unexpected JSON input for the description of a single method") + in + (label, ProfilerSample.of_list (parse_json methods [])) in - parse_json methods [] + match j with + | `Assoc pr -> + List.map ~f:(fun (label, result) -> parse_profiler_result label result) pr + | _ -> + L.(die UserError "Unexpected JSON input for the list of profiler results") -let from_json_string str = ProfilerSample.of_list (from_json (Yojson.Basic.from_string str)) +let from_json_string str = from_json (Yojson.Basic.from_string str) -let from_json_file file = ProfilerSample.of_list (from_json (Yojson.Basic.from_file file)) +let from_json_file file = from_json (Yojson.Basic.from_file file) diff --git a/infer/src/java/JavaProfilerSamples.mli b/infer/src/java/JavaProfilerSamples.mli index 0014980be..bf605c882 100644 --- a/infer/src/java/JavaProfilerSamples.mli +++ b/infer/src/java/JavaProfilerSamples.mli @@ -41,6 +41,10 @@ module JNI : sig end end -val from_json_string : string -> ProfilerSample.t +type labeled_profiler_sample = string * ProfilerSample.t [@@deriving compare] -val from_json_file : string -> ProfilerSample.t +val equal_labeled_profiler_sample : labeled_profiler_sample -> labeled_profiler_sample -> bool + +val from_json_string : string -> labeled_profiler_sample list + +val from_json_file : string -> labeled_profiler_sample list diff --git a/infer/src/java/testDeterminator.ml b/infer/src/java/testDeterminator.ml index 85ece5bbd..1ff77d9d9 100644 --- a/infer/src/java/testDeterminator.ml +++ b/infer/src/java/testDeterminator.ml @@ -78,20 +78,6 @@ let read_changed_lines_file changed_lines_file = String.Map.empty -let read_test_samples_file test_samples_file = - match Utils.read_file test_samples_file with - | Ok ts_list -> - let test_samples = - List.fold ts_list ~init:String.Map.empty ~f:(fun acc test_id -> - let test_name, path = String.lsplit2_exn ~on:':' test_id in - let tset = JavaProfilerSamples.from_json_file path in - String.Map.set acc ~key:test_name ~data:tset ) - in - test_samples - | Error _ -> - String.Map.empty - - let print_test_to_run test_to_run = L.result "@\n [Result Test Determinator:] Test to run = [" ; List.iter ~f:(L.result " %s ") test_to_run ; @@ -113,11 +99,11 @@ let test_to_run source_file cfg changed_lines_file test_samples_file = let fname = SourceFile.to_rel_path source_file in let changed_lines = read_changed_lines_file changed_lines_file in print_changed_lines changed_lines ; - let test_samples = read_test_samples_file test_samples_file in + let test_samples = JavaProfilerSamples.from_json_file test_samples_file in let affected_methods = compute_affected_methods fname cfg changed_lines in let test_to_run = - String.Map.fold test_samples ~init:[] ~f:(fun ~key ~data acc -> - let intersection = ProfilerSample.inter affected_methods data in - if ProfilerSample.is_empty intersection then acc else key :: acc ) + List.fold test_samples ~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 print_test_to_run test_to_run diff --git a/infer/src/unit/JavaProfilerSamplesTest.ml b/infer/src/unit/JavaProfilerSamplesTest.ml index 07402dc9f..db64ff8dc 100644 --- a/infer/src/unit/JavaProfilerSamplesTest.ml +++ b/infer/src/unit/JavaProfilerSamplesTest.ml @@ -159,90 +159,66 @@ let test_jni_to_java_type_with_invalid_input = let test_from_json_string_with_valid_input = let create_test input expected _ = - let expected = JavaProfilerSamples.ProfilerSample.of_list expected in let found = JavaProfilerSamples.from_json_string input in - assert_equal ~cmp:JavaProfilerSamples.ProfilerSample.equal expected found + assert_equal + ~cmp:(List.equal ~equal:JavaProfilerSamples.equal_labeled_profiler_sample) + expected found in - let input1 = "{\"whatever\": {}, \"methods\": [], \"foo\": {}}" in - let expected1 = [] in + let input1 = + "{\"label1\": {\"field1\": {}, \"field2\": {}, \"field3\": {}, \"field4\": {}, \"methods\": \ + [], \"field6\": {},\"field7\": {}}}" + in + let expected1 = [("label1", JavaProfilerSamples.ProfilerSample.of_list [])] in let input2 = - "{\"whatever\": {}, \"methods\": [{\"class\": \"aaa.bbb.Ccc\", \"boo\": \"\", \"method\": \ - \"methodOne\", \"signature\": \"()V\", \"wat\": \"\"},{\"class\": \"ddd.eee.Fff\", \"boo\": \ - \"\", \"method\": \"methodTwo\", \"signature\": \"(Ljava/lang/String;[IJ)[[C\", \"wat\": \ - \"\"},{\"class\": \"ggg.hhh.Iii\", \"boo\": \"\", \"method\": \"\", \"signature\": \ + "{\"label1\": {\"field1\": {}, \"field2\": {}, \"field3\": {}, \"field4\": {}, \"methods\": \ + [{\"class\": \"ggg.hhh.Iii\", \"boo\": \"\", \"method\": \"\", \"signature\": \ \"(Ljava/lang/String;[IJ)V\", \"wat\": \"\"},{\"class\": \"lll.mmm.Nnn\", \"boo\": \"\", \ \"method\": \"\", \"signature\": \"(Ljava/lang/String;[IJ)V\", \"wat\": \"\"}], \ - \"foo\": {}}" + \"field6\": {},\"field7\": {}},\"label2\": {\"field1\": {}, \"field2\": {}, \"field3\": {}, \ + \"field4\": {}, \"methods\": [{\"class\": \"aaa.bbb.Ccc\", \"boo\": \"\", \"method\": \ + \"methodOne\", \"signature\": \"()V\", \"wat\": \"\"},{\"class\": \"ddd.eee.Fff\", \"boo\": \ + \"\", \"method\": \"methodTwo\", \"signature\": \"(Ljava/lang/String;[IJ)[[C\", \"wat\": \ + \"\"}], \"field6\": {},\"field7\": {}}}" in let expected2 = - [ Typ.Procname.( - Java - (Java.make - (Typ.Name.Java.from_string "lll.mmm.Nnn") - None "" - [ mk_split (Some "java.lang", "String") - ; mk_split (None, "int[]") - ; mk_split (None, "long") ] - Java.Static)) - ; Typ.Procname.( - Java - (Java.make - (Typ.Name.Java.from_string "lll.mmm.Nnn") - None "" - [ mk_split (Some "java.lang", "String") - ; mk_split (None, "int[]") - ; mk_split (None, "long") ] - Java.Non_Static)) - ; Typ.Procname.( - Java - (Java.make - (Typ.Name.Java.from_string "ggg.hhh.Iii") - None "" - [ mk_split (Some "java.lang", "String") - ; mk_split (None, "int[]") - ; mk_split (None, "long") ] - Java.Static)) - ; Typ.Procname.( - Java - (Java.make - (Typ.Name.Java.from_string "ggg.hhh.Iii") - None "" - [ mk_split (Some "java.lang", "String") - ; mk_split (None, "int[]") - ; mk_split (None, "long") ] - Java.Non_Static)) - ; Typ.Procname.( - Java - (Java.make - (Typ.Name.Java.from_string "ddd.eee.Fff") - (Some (mk_split (None, "char[][]"))) - "methodTwo" - [ mk_split (Some "java.lang", "String") - ; mk_split (None, "int[]") - ; mk_split (None, "long") ] - Java.Static)) - ; Typ.Procname.( - Java - (Java.make - (Typ.Name.Java.from_string "ddd.eee.Fff") - (Some (mk_split (None, "char[][]"))) - "methodTwo" - [ mk_split (Some "java.lang", "String") - ; mk_split (None, "int[]") - ; mk_split (None, "long") ] - Java.Non_Static)) - ; Typ.Procname.( - Java - (Java.make - (Typ.Name.Java.from_string "aaa.bbb.Ccc") - (Some (mk_split (None, "void"))) - "methodOne" [] Java.Static)) - ; Typ.Procname.( - Java - (Java.make - (Typ.Name.Java.from_string "aaa.bbb.Ccc") - (Some (mk_split (None, "void"))) - "methodOne" [] Java.Non_Static)) ] + [ ( "label1" + , JavaProfilerSamples.ProfilerSample.of_list + [ Typ.Procname.( + Java + (Java.make + (Typ.Name.Java.from_string "lll.mmm.Nnn") + None "" + [ mk_split (Some "java.lang", "String") + ; mk_split (None, "int[]") + ; mk_split (None, "long") ] + Java.Non_Static)) + ; Typ.Procname.( + Java + (Java.make + (Typ.Name.Java.from_string "ggg.hhh.Iii") + None "" + [ mk_split (Some "java.lang", "String") + ; mk_split (None, "int[]") + ; mk_split (None, "long") ] + Java.Non_Static)) ] ) + ; ( "label2" + , JavaProfilerSamples.ProfilerSample.of_list + [ Typ.Procname.( + Java + (Java.make + (Typ.Name.Java.from_string "ddd.eee.Fff") + (Some (mk_split (None, "char[][]"))) + "methodTwo" + [ mk_split (Some "java.lang", "String") + ; mk_split (None, "int[]") + ; mk_split (None, "long") ] + Java.Non_Static)) + ; Typ.Procname.( + Java + (Java.make + (Typ.Name.Java.from_string "aaa.bbb.Ccc") + (Some (mk_split (None, "void"))) + "methodOne" [] Java.Non_Static)) ] ) ] in [("test_from_json_string_1", input1, expected1); ("test_from_json_string_2", input2, expected2)] |> List.map ~f:(fun (name, test_input, expected_output) -> @@ -260,7 +236,7 @@ let test_from_json_string_with_invalid_input = ; ( "test_from_json_string_2" , "{\"whatever\": {}, \"methods\": [{\"class\": \"aaa.bbb.Ccc\", \"boo\": \"\", \"method\": \ \"methodOne\", \"signature\": \"()V\"}], \"foo\": {}}" - , Logging.InferUserError "Unexpected JSON input for the description of a single method" ) + , Logging.InferUserError "Unexpected JSON input for the collection of methods" ) ; ("test_from_json_string_3", "(", Yojson.Json_error "Line 1, bytes 0-1:\nInvalid token '('") ] |> List.map ~f:(fun (name, test_input, expected_exception) -> name >:: create_test test_input expected_exception ) diff --git a/infer/tests/codetoanalyze/test_determinator/test_samples b/infer/tests/codetoanalyze/test_determinator/test_samples deleted file mode 100644 index 87602083f..000000000 --- a/infer/tests/codetoanalyze/test_determinator/test_samples +++ /dev/null @@ -1,2 +0,0 @@ -test1:ts1.json -test2:ts2.json diff --git a/infer/tests/codetoanalyze/test_determinator/test_samples.json b/infer/tests/codetoanalyze/test_determinator/test_samples.json new file mode 100644 index 000000000..c0d3cb52a --- /dev/null +++ b/infer/tests/codetoanalyze/test_determinator/test_samples.json @@ -0,0 +1,50 @@ +{ + "label1": { + "field1": {}, + "field2": {}, + "field3": {}, + "field4": {}, + "methods": [ + { + "class": "MyFavouriteClassOne", + "id": "", + "method": "methodOne", + "signature": "()V", + "src_file": "" + }, + { + "class": "MyFavouriteClassTwo", + "id": "", + "method": "methodTwo", + "signature": "(I)I", + "src_file": "" + } + ], + "field6": {}, + "field7": {} + }, + "label2": { + "field1": {}, + "field2": {}, + "field3": {}, + "field4": {}, + "methods": [ + { + "class": "MyFavouriteClassXX", + "id": "", + "method": "methodOne", + "signature": "()V", + "src_file": "" + }, + { + "class": "MyFavouriteClassYY", + "id": "", + "method": "methodTwo", + "signature": "(I)I", + "src_file": "" + } + ], + "field6": {}, + "field7": {} + } + } \ No newline at end of file diff --git a/infer/tests/codetoanalyze/test_determinator/ts1.json b/infer/tests/codetoanalyze/test_determinator/ts1.json deleted file mode 100644 index eb8783588..000000000 --- a/infer/tests/codetoanalyze/test_determinator/ts1.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "date": "", - "methods": [ - { - "class": "MyFavouriteClassOne", - "id": "", - "method": "methodOne", - "signature": "()V", - "src_file": "" - }, - { - "class": "MyFavouriteClassTwo", - "id": "", - "method": "methodTwo", - "signature": "(I)I", - "src_file": "" - } - ], - "profiles": [] -} \ No newline at end of file diff --git a/infer/tests/codetoanalyze/test_determinator/ts2.json b/infer/tests/codetoanalyze/test_determinator/ts2.json deleted file mode 100644 index 9ca913c80..000000000 --- a/infer/tests/codetoanalyze/test_determinator/ts2.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "date": "", - "methods": [ - { - "class": "MyFavouriteClassXX", - "id": "", - "method": "methodOne", - "signature": "()V", - "src_file": "" - }, - { - "class": "MyFavouriteClassYY", - "id": "", - "method": "methodTwo", - "signature": "(I)I", - "src_file": "" - } - ], - "profiles": [] -} \ No newline at end of file