[Infer][stats] Adding procedure stats to stats.json

Summary:
This will make it easier to write
tests for the procedure-level incremental functionality.
master
Sam Blackshear 9 years ago
parent 1a615a467b
commit f8cc0c2ba8

@ -269,6 +269,7 @@ def get_basic_stats(stats):
to_skip = { to_skip = {
'files', 'files',
'procedures',
'lines', 'lines',
'cores', 'cores',
'time', 'time',

@ -663,9 +663,12 @@ class Infer:
elapsed = utils.elapsed_time(start_time) elapsed = utils.elapsed_time(start_time)
self.timing['total'] = elapsed self.timing['total'] = elapsed
self.save_stats() self.save_stats()
procs_total = self.stats['int']['procedures']
files_total = self.stats['int']['files'] files_total = self.stats['int']['files']
files_plural = '' if files_total <= 1 else 's' procs_str = utils.get_plural('procedure', procs_total)
print('\n%d file%s analyzed' % (files_total, files_plural)) files_str = utils.get_plural('file', files_total)
print('\nAnalyzed %s in %s' % (procs_str, files_str))
return self.stats return self.stats
else: else:
return dict({}) return dict({})

@ -355,6 +355,11 @@ def create_json_report(out_dir):
json.dump(issues, file_out, indent=2) json.dump(issues, file_out, indent=2)
def get_plural(_str, count):
plural_str = _str if count == 1 else _str + 's'
return '%d %s' % (count, plural_str)
class AbsolutePathAction(argparse.Action): class AbsolutePathAction(argparse.Action):
"""Convert a path from relative to absolute in the arg parser""" """Convert a path from relative to absolute in the arg parser"""
def __call__(self, parser, namespace, values, option_string=None): def __call__(self, parser, namespace, values, option_string=None):

@ -356,8 +356,11 @@ let file_pname_to_cg file_pname =
let cg_fname = DB.source_dir_get_internal_file source_dir ".cg" in let cg_fname = DB.source_dir_get_internal_file source_dir ".cg" in
Cg.load_from_file cg_fname Cg.load_from_file cg_fname
let output_json_file_stats num_files num_lines = let output_json_file_stats num_files num_procs num_lines =
let file_stats = `Assoc [ ("files", `Int num_files); ("lines", `Int num_lines) ] in let file_stats =
`Assoc [ ("files", `Int num_files);
("procedures", `Int num_procs);
("lines", `Int num_lines) ] in
(* write stats file to disk, intentionally overwriting old file if it already exists *) (* write stats file to disk, intentionally overwriting old file if it already exists *)
let f = open_out (Filename.concat !Config.results_dir Config.stats_filename) in let f = open_out (Filename.concat !Config.results_dir Config.stats_filename) in
Yojson.Basic.pretty_to_channel f file_stats Yojson.Basic.pretty_to_channel f file_stats
@ -369,6 +372,7 @@ let create_minimal_clusters file_cg exe_env to_analyze_map : cluster list =
let seen = ref Procname.Set.empty in let seen = ref Procname.Set.empty in
let clusters = ref [] in let clusters = ref [] in
let total_files = ref 0 in let total_files = ref 0 in
let total_procs = ref 0 in
let total_LOC = ref 0 in let total_LOC = ref 0 in
let create_cluster_elem (file_pname, changed_procs) = (* create a cluster_elem for the file *) let create_cluster_elem (file_pname, changed_procs) = (* create a cluster_elem for the file *)
let source_file = source_file_from_pname file_pname in let source_file = source_file_from_pname file_pname in
@ -377,8 +381,6 @@ let create_minimal_clusters file_cg exe_env to_analyze_map : cluster list =
match file_pname_to_cg file_pname with match file_pname_to_cg file_pname with
| None -> { ce_file = source_file; ce_naprocs = 0; ce_active_procs = []; ce_source_map = Procname.Map.empty } | None -> { ce_file = source_file; ce_naprocs = 0; ce_active_procs = []; ce_source_map = Procname.Map.empty }
| Some cg -> | Some cg ->
total_files := !total_files + 1;
total_LOC := !total_LOC + (Cg.get_nLOC cg);
(* decide whether a proc is active using pname_to_fname, i.e. whether this is the file associated to it *) (* decide whether a proc is active using pname_to_fname, i.e. whether this is the file associated to it *)
let proc_is_selected pname = match !select_proc with let proc_is_selected pname = match !select_proc with
| None -> true | None -> true
@ -399,6 +401,9 @@ let create_minimal_clusters file_cg exe_env to_analyze_map : cluster list =
with Not_found -> () in with Not_found -> () in
list_iter do_proc all_procs; list_iter do_proc all_procs;
!mapr in !mapr in
total_files := !total_files + 1;
total_procs := !total_procs + naprocs;
total_LOC := !total_LOC + (Cg.get_nLOC cg);
{ ce_file = source_file; ce_naprocs = naprocs; ce_active_procs = active_procs; ce_source_map = source_map } in { ce_file = source_file; ce_naprocs = naprocs; ce_active_procs = active_procs; ce_source_map = source_map } in
let choose_next_file list = (* choose next file from the weakly ordered list *) let choose_next_file list = (* choose next file from the weakly ordered list *)
let file_has_no_unseen_dependents fname = let file_has_no_unseen_dependents fname =
@ -438,7 +443,7 @@ let create_minimal_clusters file_cg exe_env to_analyze_map : cluster list =
end; end;
build_clusters list'' in build_clusters list'' in
build_clusters sorted_files; build_clusters sorted_files;
output_json_file_stats !total_files !total_LOC; output_json_file_stats !total_files !total_procs !total_LOC;
list_rev !clusters list_rev !clusters
let cluster_nfiles cluster = list_length cluster let cluster_nfiles cluster = list_length cluster

@ -26,6 +26,9 @@ public class InferStats {
@JsonProperty(value = "files") @JsonProperty(value = "files")
int numFiles; int numFiles;
@JsonProperty(value = "procedures")
int numProcedures;
@JsonProperty(value = "lines") @JsonProperty(value = "lines")
int numLines; int numLines;
} }
@ -65,6 +68,10 @@ public class InferStats {
return intFields.numFiles; return intFields.numFiles;
} }
public int getNumProcedures() {
return intFields.numProcedures;
}
public int getNumLines() { public int getNumLines() {
return intFields.numLines; return intFields.numLines;
} }

@ -0,0 +1,52 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package utils.matchers;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import utils.InferError;
import utils.InferStats;
public class NumberOfProceduresAnalyzed extends BaseMatcher<InferStats> {
private int expectedNumProcedures;
private int actualNumProcedures;
public NumberOfProceduresAnalyzed(int expectedNumProcedures) {
this.expectedNumProcedures = expectedNumProcedures;
this.actualNumProcedures = -1;
}
@Override
public boolean matches(Object o) {
InferStats stats = (InferStats) o;
actualNumProcedures = stats.getNumProcedures();
return actualNumProcedures == expectedNumProcedures;
}
@Override
public void describeTo(Description description) {
description.appendText(expectedNumProcedures + " procedures analyzed by Infer.");
}
@Override
public void describeMismatch(Object item, Description description) {
InferStats stats = (InferStats) item;
description.appendText("found " + actualNumProcedures + " procedures analyzed by Infer.");
}
public static <T> Matcher<InferStats> numberOfProceduresAnalyzed(
int expectedNumProcedures) {
return new NumberOfProceduresAnalyzed(expectedNumProcedures);
}
}
Loading…
Cancel
Save