[reportdiff] add filtered out bugs to preexisting

Summary:
Once the fixed/preexisting/introduced sets have been computed, they endure
further filtering which may decide that more of them are equal. These bugs just
get dropped on the floor. Put these into preexisting as well instead, at least
in the case of the "skip_duplicated_types_on_filenames" filter.

Reviewed By: martinoluca

Differential Revision: D5274248

fbshipit-source-id: 99b3f3d
master
Jules Villard 8 years ago committed by Facebook Github Bot
parent 72802024b3
commit b158f5cd30

@ -138,7 +138,7 @@ EXTRA_DEPS = opensource
endif endif
DEPENDENCIES = \ DEPENDENCIES = \
absint backend base bufferoverrun checkers eradicate harness integration IR labs quandary \ absint backend base bufferoverrun checkers eradicate harness integration IR labs quandary unit \
$(EXTRA_DEPS) $(EXTRA_DEPS)
# ocamlbuild command with options common to all build targets # ocamlbuild command with options common to all build targets

@ -55,28 +55,30 @@ module FileRenamings = struct
end end
end end
(* Remove duplicates between two lists whenever pred is true for such element *) (** Returns a triple [(l1', dups, l2')] where [dups] is the set of elements of that are in the
intersection of [l1] and [l2] according to [cmd] and additionally satisfy [pred], and [lN'] is
[lN] minus [dups]. [dups] contains only one witness for each removed issue, taken from [l1]. *)
let relative_complements ~cmp ?(pred=(fun _ -> true)) l1 l2 = let relative_complements ~cmp ?(pred=(fun _ -> true)) l1 l2 =
let rec aux last_dup ((out_l1, out_l2) as out) in_l1 in_l2 = let rec aux ((out_l1, dups, out_l2) as out) in_l1 in_l2 =
let is_last_seen_dup v = match last_dup with let is_last_seen_dup v = match dups with
| Some ld -> Int.equal (cmp ld v) 0 | ld::_ -> Int.equal (cmp ld v) 0
| None -> false in | [] -> false in
match in_l1, in_l2 with match in_l1, in_l2 with
| i::is, f::fs when Int.equal (cmp i f) 0 -> (* i = f *) | i::is, f::fs when Int.equal (cmp i f) 0 -> (* i = f *)
if pred i then aux (Some i) (out_l1, out_l2) is fs if pred i then aux (out_l1, i::dups, out_l2) is fs
else aux None (i::out_l1, f::out_l2) is fs else aux (i::out_l1, dups, f::out_l2) is fs
| i::is, f::_ when cmp i f < 0 -> (* i < f *) | i::is, f::_ when cmp i f < 0 -> (* i < f *)
let out_l1' = if is_last_seen_dup i then out_l1 else i::out_l1 in let out_l1' = if is_last_seen_dup i then out_l1 else i::out_l1 in
aux last_dup (out_l1', out_l2) is in_l2 aux (out_l1', dups, out_l2) is in_l2
| _::_, f::fs -> (* i > f *) | _::_, f::fs -> (* i > f *)
let out_l2' = if is_last_seen_dup f then out_l2 else f::out_l2 in let out_l2' = if is_last_seen_dup f then out_l2 else f::out_l2 in
aux last_dup (out_l1, out_l2') in_l1 fs aux (out_l1, dups, out_l2') in_l1 fs
| i::is, [] when is_last_seen_dup i -> aux last_dup out is in_l2 | i::is, [] when is_last_seen_dup i -> aux out is in_l2
| [], f::fs when is_last_seen_dup f -> aux last_dup out in_l1 fs | [], f::fs when is_last_seen_dup f -> aux out in_l1 fs
| _, _ -> List.rev_append in_l1 out_l1, List.rev_append in_l2 out_l2 in | _, _ -> List.rev_append in_l1 out_l1, dups, List.rev_append in_l2 out_l2 in
let l1_sorted = List.sort ~cmp l1 in let l1_sorted = List.sort ~cmp l1 in
let l2_sorted = List.sort ~cmp l2 in let l2_sorted = List.sort ~cmp l2 in
aux None ([], []) l1_sorted l2_sorted aux ([], [], []) l1_sorted l2_sorted
type issue_file_with_renaming = Jsonbug_t.jsonbug * (string option) type issue_file_with_renaming = Jsonbug_t.jsonbug * (string option)
@ -92,7 +94,7 @@ let skip_duplicated_types_on_filenames
[%compare : string * issue_file_with_renaming] [%compare : string * issue_file_with_renaming]
(issue1.Jsonbug_t.bug_type, issue_with_previous_file1) (issue1.Jsonbug_t.bug_type, issue_with_previous_file1)
(issue2.Jsonbug_t.bug_type, issue_with_previous_file2) in (issue2.Jsonbug_t.bug_type, issue_with_previous_file2) in
let introduced, fixed = let introduced, preexisting, fixed =
(* All comparisons will be made against filenames *before* renamings. (* All comparisons will be made against filenames *before* renamings.
This way, all introduced and fixed issues can be sorted independently This way, all introduced and fixed issues can be sorted independently
over the same domain. *) over the same domain. *)
@ -100,10 +102,13 @@ let skip_duplicated_types_on_filenames
List.map diff.introduced List.map diff.introduced
~f:(fun i -> i, FileRenamings.find_previous renamings i.Jsonbug_t.file) in ~f:(fun i -> i, FileRenamings.find_previous renamings i.Jsonbug_t.file) in
let fixed_normalized = List.map diff.fixed ~f:(fun f -> f, None) in let fixed_normalized = List.map diff.fixed ~f:(fun f -> f, None) in
let introduced_normalized', fixed_normalized' = let introduced_normalized', preexisting', fixed_normalized' =
relative_complements ~cmp introduced_normalized fixed_normalized in relative_complements ~cmp introduced_normalized fixed_normalized in
List.map ~f:fst introduced_normalized', List.map ~f:fst fixed_normalized' in let list_map_fst = List.map ~f:fst in
{introduced; fixed; preexisting = diff.preexisting} list_map_fst introduced_normalized',
(list_map_fst preexisting') @ diff.preexisting,
list_map_fst fixed_normalized' in
{introduced; fixed; preexisting}
let java_anon_class_pattern = Str.regexp "\\$[0-9]+" let java_anon_class_pattern = Str.regexp "\\$[0-9]+"
@ -168,8 +173,8 @@ let skip_anonymous_class_renamings (diff: Differential.t) : Differential.t =
true true
with Not_found -> false in with Not_found -> false in
is_java_file () && has_anonymous_class_token () in is_java_file () && has_anonymous_class_token () in
let introduced, fixed = relative_complements ~cmp ~pred diff.introduced diff.fixed in let introduced, preexisting, fixed = relative_complements ~cmp ~pred diff.introduced diff.fixed in
{introduced; fixed; preexisting = diff.preexisting} {introduced; fixed; preexisting = preexisting @ diff.preexisting}
(* Filter out null dereferences reported by infer if file has eradicate (* Filter out null dereferences reported by infer if file has eradicate
enabled, to avoid double reporting. *) enabled, to avoid double reporting. *)

@ -33,7 +33,7 @@ val do_filter : Differential.t -> FileRenamings.t -> skip_duplicated_types:bool
module VISIBLE_FOR_TESTING_DO_NOT_USE_DIRECTLY : sig module VISIBLE_FOR_TESTING_DO_NOT_USE_DIRECTLY : sig
val relative_complements : val relative_complements :
cmp:('a -> 'a -> int) -> ?pred:('a -> bool) -> 'a list -> 'a list -> 'a list * 'a list cmp:('a -> 'a -> int) -> ?pred:('a -> bool) -> 'a list -> 'a list -> 'a list * 'a list * 'a list
val skip_duplicated_types_on_filenames : FileRenamings.t -> Differential.t -> Differential.t val skip_duplicated_types_on_filenames : FileRenamings.t -> Differential.t -> Differential.t
val java_anon_class_pattern : Str.regexp val java_anon_class_pattern : Str.regexp
val value_of_qualifier_tag : Jsonbug_t.tag_value_record list -> string -> string option val value_of_qualifier_tag : Jsonbug_t.tag_value_record list -> string -> string option

@ -115,94 +115,96 @@ let test_file_renamings_find_previous =
name >:: create_test test_input expected_output) name >:: create_test test_input expected_output)
let test_relative_complements = let test_relative_complements =
let create_test pred (l1, l2) (expected_l1, expected_l2) _ = let create_test pred (l1, l2) (expected_l1, expected_l2, expected_l3) _ =
let cmp = Int.compare in let cmp = Int.compare in
let output_l1, output_l2 = let output_l1, output_l2, output_l3 =
DifferentialFilters.VISIBLE_FOR_TESTING_DO_NOT_USE_DIRECTLY.relative_complements DifferentialFilters.VISIBLE_FOR_TESTING_DO_NOT_USE_DIRECTLY.relative_complements
~cmp ~pred l1 l2 in ~cmp ~pred l1 l2 in
let list_equal l1 l2 = List.equal ~equal:(fun v1 v2 -> Int.equal (cmp v1 v2) 0) l1 l2 in let list_equal l1 l2 = List.equal ~equal:(fun v1 v2 -> Int.equal (cmp v1 v2) 0) l1 l2 in
assert_equal assert_equal
~pp_diff:(pp_diff_of_int_list "First list") ~cmp:list_equal expected_l1 output_l1; ~pp_diff:(pp_diff_of_int_list "First list") ~cmp:list_equal expected_l1 output_l1;
assert_equal assert_equal
~pp_diff:(pp_diff_of_int_list "Second list") ~cmp:list_equal expected_l2 output_l2 in ~pp_diff:(pp_diff_of_int_list "Second list") ~cmp:list_equal expected_l2 output_l2;
assert_equal
~pp_diff:(pp_diff_of_int_list "Third list") ~cmp:list_equal expected_l3 output_l3 in
[ [
( (
"test_relative_complements_with_always_true_pred", "test_relative_complements_with_always_true_pred",
(fun _ -> true), (fun _ -> true),
([0;1;2;3;4;5], [5;3;7;1;1;2]), ([0;1;2;3;4;5], [5;3;7;1;1;2]),
([4;0], [7]) ([4;0], [5;3;2;1], [7])
); );
( (
"test_relative_complements_with_even_numbers_pred", "test_relative_complements_with_even_numbers_pred",
(fun i -> Int.equal (i mod 2) 0), (* skip when even, keep odd *) (fun i -> Int.equal (i mod 2) 0), (* skip when even, keep odd *)
([0;1;2;3;4;5], [5;3;7;1;1;2]), ([0;1;2;3;4;5], [5;3;7;1;1;2]),
([5;4;3;1;0], [7;5;3;1;1]) ([5;4;3;1;0], [2], [7;5;3;1;1])
); );
( (
"test_relative_complements_with_even_numbers_pred_2", "test_relative_complements_with_even_numbers_pred_2",
(fun i -> Int.equal (i mod 2) 0), (* skip when even, keep odd *) (fun i -> Int.equal (i mod 2) 0), (* skip when even, keep odd *)
([0;1;2;3;5;5], [1;1;2;3;4;7]), ([0;1;2;3;5;5], [1;1;2;3;4;7]),
([5;5;3;1;0], [7;4;3;1;1]) ([5;5;3;1;0], [2], [7;4;3;1;1])
); );
( (
"test_relative_complements_with_always_true_pred_and_disjoint_lists_of_different_length", "test_relative_complements_with_always_true_pred_and_disjoint_lists_of_different_length",
(fun _ -> true), (fun _ -> true),
([0;3;2;3;5], [9;7;6;8;4;6;9]), ([0;3;2;3;5], [9;7;6;8;4;6;9]),
([5;3;3;2;0], [9;9;8;7;6;6;4]) ([5;3;3;2;0], [], [9;9;8;7;6;6;4])
); );
( (
"test_relative_complements_with_always_true_pred_and_lists_of_different_length", "test_relative_complements_with_always_true_pred_and_lists_of_different_length",
(fun _ -> true), (fun _ -> true),
([0;3;2;3], [9;7;3;8;0;6;9;4]), ([0;3;2;3], [9;7;3;8;0;6;9;4]),
([2], [9;9;8;7;6;4]) ([2], [3;0], [9;9;8;7;6;4])
); );
( (
"test_relative_complements_with_odd_numbers_on_lists_of_different_length", "test_relative_complements_with_odd_numbers_on_lists_of_different_length",
(fun i -> Int.equal (i mod 2) 1), (* skip when odd, keep even *) (fun i -> Int.equal (i mod 2) 1), (* skip when odd, keep even *)
([0;3;2;3], [9;7;3;8;0;6;9;4]), ([0;3;2;3], [9;7;3;8;0;6;9;4]),
([2;0], [9;9;8;7;6;4;0]) ([2;0], [3], [9;9;8;7;6;4;0])
); );
( (
"test_relative_complements_with_singleton_lists1", "test_relative_complements_with_singleton_lists1",
(fun _ -> true), (fun _ -> true),
([0], [0;1;0;0]), ([0], [0;1;0;0]),
([], [1]) ([], [0], [1])
); );
( (
"test_relative_complements_with_singleton_lists2", "test_relative_complements_with_singleton_lists2",
(fun _ -> true), (fun _ -> true),
([0;1;0;0], [0]), ([0;1;0;0], [0]),
([1], []) ([1], [0], [])
); );
( (
"test_relative_complements_with_singleton_lists3", "test_relative_complements_with_singleton_lists3",
(fun _ -> true), (fun _ -> true),
([0], [0]), ([0], [0]),
([], []) ([], [0], [])
); );
( (
"test_relative_complements_with_singleton_lists4", "test_relative_complements_with_singleton_lists4",
(fun _ -> true), (fun _ -> true),
([0], [1]), ([0], [1]),
([0], [1]) ([0], [], [1])
); );
( (
"test_relative_complements_with_empty_lists1", "test_relative_complements_with_empty_lists1",
(fun _ -> true), (fun _ -> true),
([], [0;1;0;0]), ([], [0;1;0;0]),
([], [1;0;0;0]) ([], [], [1;0;0;0])
); );
( (
"test_relative_complements_with_empty_lists2", "test_relative_complements_with_empty_lists2",
(fun _ -> true), (fun _ -> true),
([0;1;0;0], []), ([0;1;0;0], []),
([1;0;0;0], []) ([1;0;0;0], [], [])
); );
( (
"test_relative_complements_with_empty_lists3", "test_relative_complements_with_empty_lists3",
(fun _ -> true), (fun _ -> true),
([], []), ([], []),
([], []) ([], [], [])
); );
] ]
|> List.map |> List.map
@ -243,7 +245,7 @@ let test_skip_duplicated_types_on_filenames =
[3] (sorted_hashes_of_issues diff'.fixed); [3] (sorted_hashes_of_issues diff'.fixed);
assert_equal assert_equal
~pp_diff:(pp_diff_of_int_list "Hashes of preexisting") ~pp_diff:(pp_diff_of_int_list "Hashes of preexisting")
[222] (sorted_hashes_of_issues diff'.preexisting) in [22; 55; 111; 222] (sorted_hashes_of_issues diff'.preexisting) in
"test_skip_duplicated_types_on_filenames" >:: do_assert "test_skip_duplicated_types_on_filenames" >:: do_assert
let test_value_of_qualifier_tag = let test_value_of_qualifier_tag =
@ -340,7 +342,7 @@ let test_skip_anonymous_class_renamings =
~key:2 ~key:2
~hash:2 (); ~hash:2 ();
], ],
([4;5], [2], [])); ([4;5], [2], [3]));
("test_skip_anonymous_class_renamings_with_empty_qualifier_tags", ("test_skip_anonymous_class_renamings_with_empty_qualifier_tags",
Differential.of_reports Differential.of_reports
~current_report:[ ~current_report:[
@ -372,7 +374,7 @@ let test_skip_anonymous_class_renamings =
~key:1 ~key:1
~hash:4 (); ~hash:4 ();
], ],
([1], [2], [])); ([1], [2], [3]));
("test_skip_anonymous_class_renamings_with_matching_non_anonymous_procedure_ids", ("test_skip_anonymous_class_renamings_with_matching_non_anonymous_procedure_ids",
Differential.of_reports Differential.of_reports
~current_report:[ ~current_report:[
@ -436,7 +438,7 @@ let test_skip_anonymous_class_renamings =
~key:1 ~key:1
~hash:4 (); ~hash:4 ();
], ],
([3], [4], [])); ([3], [4], [1]));
("test_skip_anonymous_class_renamings_with_different_call_procedure_qualifier_tags", ("test_skip_anonymous_class_renamings_with_different_call_procedure_qualifier_tags",
Differential.of_reports Differential.of_reports
~current_report:[ ~current_report:[

@ -0,0 +1 @@
NULL_DEREFERENCE, src/DiffExample.java, int DiffExample$4.aaa(), 0, DiffExample$4.aaa():int.a7bd5e834e7a8fb4284c75f621544e3e, DiffExample$4.aaa():int

@ -0,0 +1 @@
NULL_DEREFERENCE, src/DiffExample.java, int DiffExample.triggerNpeRenamed(), 1, DiffExample.triggerNpeRenamed():int.3e4070b89fdefd2c64fd437530b8dda9, DiffExample.triggerNpeRenamed():int

@ -0,0 +1,2 @@
NULL_DEREFERENCE, src/DiffExampleRenamed.java, int DiffExampleRenamed.triggerNpe(), 1, DiffExampleRenamed.triggerNpe():int.708d86c0dc5dc4e5dbbbcd38276ce86f, DiffExampleRenamed.triggerNpe():int
RESOURCE_LEAK, src/DiffExampleRenamed.java, void DiffExampleRenamed.openResource(), 5, DiffExampleRenamed.openResource():void.715df29eeb5b62c29d4081c6dc9d407a, DiffExampleRenamed.openResource():void
Loading…
Cancel
Save