def calculate_scores(result_directory): # Init scores = { 'compiler_and_sanitizer': {}, 'assertions': {}, 'cppcheck': {}, 'clang_tidy': {}, 'cyclomatic_complexity': {}, 'lizard_warnings': {}, 'unique': {}, 'kwstyle': {}, 'overall': {} } for score in scores: for folder in FOLDERS: scores[score][folder] = None # Get all the scores for folder in FOLDERS: # Get rates compiler_and_sanitizer_rate, assertion_rate, cppcheck_rate, clang_tidy_rate, ccn, lizard_rate, unique_rate, \ kwstyle_rate = get_result_rates(result_directory, folder) # Get scores scores['compiler_and_sanitizer'][ folder] = scoring.calculate_compiler_and_sanitizer_score( compiler_and_sanitizer_rate) scores['assertions'][folder] = scoring.calculate_assertion_score( assertion_rate) scores['cppcheck'][folder] = scoring.calculate_cppcheck_score( cppcheck_rate) scores['clang_tidy'][folder] = scoring.calculate_clang_tidy_score( clang_tidy_rate) scores['cyclomatic_complexity'][ folder] = scoring.calculate_cyclomatic_complexity_score(ccn) scores['lizard_warnings'][ folder] = scoring.calculate_lizard_warning_score(lizard_rate) scores['unique'][folder] = scoring.calculate_unique_score(unique_rate) scores['kwstyle'][folder] = scoring.calculate_kwstyle_score( kwstyle_rate) # Calculate the overall score list_of_scores = [ scores[score][folder] for score in scores.keys() if score != 'overall' ] scores['overall'][folder] = scoring.average_score(list_of_scores) return scores
def main(): add_kwstyle_to_path_variable() # Allow the user to auto-install the dependencies by just running "./softwipe.py" without any arguments if len(sys.argv) == 1: automatic_tool_installation.check_if_all_required_tools_are_installed() args = parse_arguments() # Normal check for the dependencies if len(sys.argv) != 1: automatic_tool_installation.check_if_all_required_tools_are_installed() add_user_paths_to_path_variable(args) if not args.allow_running_as_root: warn_if_user_is_root() cpp = True if args.cpp else False program_dir_abs = os.path.abspath(args.programdir) exclude = args.exclude[0] if args.exclude else None excluded_paths = util.get_excluded_paths(program_dir_abs, exclude) source_files = util.find_all_source_files(program_dir_abs, excluded_paths) lines_of_code = util.count_lines_of_code(source_files) compiler_and_sanitizer_score = compile_and_execute_program_with_sanitizers( args, lines_of_code, program_dir_abs, cpp, excluded_paths, args.no_execution) assertion_score, cppcheck_score, clang_tidy_score, cyclomatic_complexity_score, warning_score, \ unique_score, kwstyle_score = static_analysis(source_files, lines_of_code, cpp) all_scores = [ compiler_and_sanitizer_score, assertion_score, cppcheck_score, clang_tidy_score, cyclomatic_complexity_score, warning_score, unique_score, kwstyle_score ] overall_score = scoring.average_score(all_scores) scoring.print_score(overall_score, 'Overall program')
def calculate_scores(result_directory, absolute): # Init if absolute: scores = { 'loc': {}, 'functions': {}, 'compiler': {}, 'sanitizer': {}, 'assertions': {}, 'cppcheck': {}, 'clang_tidy': {}, 'cyclomatic_complexity': {}, 'lizard_warnings': {}, 'unique': {}, 'kwstyle': {}, 'infer': {}, TESTCOUNT_KEY: {} } else: scores = { 'overall': {}, 'compiler_and_sanitizer': {}, 'assertions': {}, 'cppcheck': {}, 'clang_tidy': {}, 'cyclomatic_complexity': {}, 'lizard_warnings': {}, 'unique': {}, 'kwstyle': {}, 'infer': {}, TESTCOUNT_KEY: {} } failed_tools_dict = {} for score in scores: for folder in FOLDERS: scores[score][folder] = None # Get all the scores for folder in FOLDERS: if absolute: # Get values loc, functions, compiler_warnings, sanitizer_warnings, assertions, cppcheck_warnings, clang_tidy_warnings, \ ccn, lizard_warnings, unique, kwstyle_warnings, infer_warnings, test_count_loc, failed_tools = get_result_values( result_directory, folder) scores['loc'][folder] = loc scores['functions'][folder] = functions scores['compiler'][folder] = compiler_warnings scores['sanitizer'][folder] = sanitizer_warnings scores['assertions'][folder] = assertions scores['cppcheck'][folder] = cppcheck_warnings scores['clang_tidy'][folder] = clang_tidy_warnings scores['cyclomatic_complexity'][folder] = ccn scores['lizard_warnings'][folder] = lizard_warnings scores['unique'][folder] = unique scores['kwstyle'][folder] = kwstyle_warnings scores['infer'][folder] = infer_warnings scores[TESTCOUNT_KEY][folder] = test_count_loc else: # Get rates compiler_and_sanitizer_rate, assertion_rate, cppcheck_rate, clang_tidy_rate, ccn, lizard_rate, \ unique_rate, kwstyle_rate, infer_rate, test_count_rate, failed_tools = get_result_rates(result_directory, folder) # Get scores if COMPILER_KEY not in failed_tools: scores['compiler_and_sanitizer'][folder] = \ scoring.calculate_compiler_and_sanitizer_score_absolute(compiler_and_sanitizer_rate) if ASSERTIONS_KEY not in failed_tools: scores['assertions'][ folder] = scoring.calculate_assertion_score_absolute( assertion_rate) if CPPCHECK_KEY not in failed_tools: scores['cppcheck'][ folder] = scoring.calculate_cppcheck_score_absolute( cppcheck_rate) if CLANG_TIDY_KEY not in failed_tools: scores['clang_tidy'][ folder] = scoring.calculate_clang_tidy_score_absolute( clang_tidy_rate) if CYCLOMATIC_COMPLEXITY_KEY not in failed_tools: scores['cyclomatic_complexity'][ folder] = scoring.calculate_cyclomatic_complexity_score_absolute( ccn) if LIZARD_WARNINGS_KEY not in failed_tools: scores['lizard_warnings'][ folder] = scoring.calculate_lizard_warning_score_absolute( lizard_rate) if UNIQUE_KEY not in failed_tools: scores['unique'][ folder] = scoring.calculate_unique_score_absolute( unique_rate) if KWSTYLE_KEY not in failed_tools: scores['kwstyle'][ folder] = scoring.calculate_kwstyle_score_absolute( kwstyle_rate) if INFER_KEY not in failed_tools: scores['infer'][ folder] = scoring.calculate_infer_score_absolute( infer_rate) if TESTCOUNT_KEY not in failed_tools: scores[TESTCOUNT_KEY][ folder] = scoring.calculate_testcount_score_absolute( test_count_rate) # Calculate the overall score list_of_scores = [ scores[score][folder] for score in scores.keys() if score != 'overall' and score not in failed_tools ] if None in list_of_scores: list_of_scores = [] if list_of_scores: scores['overall'][folder] = scoring.average_score( list_of_scores) else: scores['overall'][folder] = -1 failed_tools_dict[folder] = failed_tools return scores, failed_tools_dict
def main(): file_path = sys.argv[1] space_pattern = [ 22, 9, 16, 24, 12, 10, 12, 23, 17, 8, 9, 7, len("test_count") + 2 ] space_pattern_constant = [ 17, 8, 11, 10, 11, 12, 10, 12, 23, 17, 20, 9, 7, len("test_count") + 2 ] scores = defaultdict() scores["compiler_and_sanitizer"] = {} scores["assertions"] = {} scores["cppcheck"] = {} scores["clang_tidy"] = {} scores["cyclomatic_complexity"] = {} scores["lizard_warnings"] = {} scores["unique"] = {} scores["kwstyle"] = {} scores["infer"] = {} scores["test_count"] = {} scores["overall"] = {} scores_absolute = defaultdict() scores_absolute["relative_score"] = {} scores_absolute["compiler_and_sanitizer"] = {} scores_absolute["assertions"] = {} scores_absolute["cppcheck"] = {} scores_absolute["clang_tidy"] = {} scores_absolute["cyclomatic_complexity"] = {} scores_absolute["lizard_warnings"] = {} scores_absolute["unique"] = {} scores_absolute["kwstyle"] = {} scores_absolute["infer"] = {} scores_absolute["test_count"] = {} scores_absolute["overall"] = {} rates = { 'compiler_and_sanitizer': [], 'assertions': [], 'cppcheck': [], 'clang_tidy': [], 'cyclomatic_complexity': [], 'lizard_warnings': [], 'unique': [], 'kwstyle': [], 'infer': [], "test_count": [] } d = defaultdict() d_absolute = defaultdict() constants = defaultdict() available_categories = {} # | program | overall | relative score | compiler_and_sanitizer | assertions | cppcheck | clang_tidy | cyclomatic_complexity | lizard_warnings | unique | kwstyle | infer | # | program | loc | functions | compiler | sanitizer | assertions | cppcheck | clang_tidy | cyclomatic_complexity | lizard_warnings | unique | kwstyle | infer | folder_included = [] with open(file_path) as file: for line in file: line = line.rstrip().replace(" ", "").split("|") if len(line) < 15: continue skip_round = False for i in range( 1, 4 ): # if we can't even get the loc or function numbers, we just skip the tool if NA_SEQUENCE in line[i]: skip_round = True if skip_round: continue folder = line[1] loc = int(line[2]) functions = int(line[3]) compiler = int(line[4]) sanitizer = int(line[5]) if len( line ) == 15: # TODO: fix this, this was used to add a new category to the table line.append("") if not line[14]: line[14] = NA_SEQUENCE else: if folder in folder_included: folder_included.remove(folder) # update old value if folder in folder_included: continue folder_included.append(folder) available_categories[folder] = [] # TODO: turn this pile of shame into elegant code someday if NA_SEQUENCE not in line[6]: assertions = int(line[6]) assertion_rate = assertions / loc scores['assertions'][ folder] = scoring.calculate_assertion_score(assertion_rate) scores_absolute['assertions'][ folder] = scoring.calculate_assertion_score_absolute( assertion_rate) available_categories[folder].append('assertions') rates['assertions'].append((folder, assertion_rate)) if NA_SEQUENCE not in line[7]: cppcheck = int(line[7]) cppcheck_rate = cppcheck / loc scores['cppcheck'][folder] = scoring.calculate_cppcheck_score( cppcheck_rate) scores_absolute['cppcheck'][ folder] = scoring.calculate_cppcheck_score_absolute( cppcheck_rate) available_categories[folder].append('cppcheck') rates['cppcheck'].append((folder, cppcheck_rate)) if NA_SEQUENCE not in line[8]: clang_tidy = int(line[8]) clang_tidy_rate = clang_tidy / loc scores['clang_tidy'][ folder] = scoring.calculate_clang_tidy_score( clang_tidy_rate) scores_absolute['clang_tidy'][ folder] = scoring.calculate_clang_tidy_score_absolute( clang_tidy_rate) available_categories[folder].append('clang_tidy') rates['clang_tidy'].append((folder, clang_tidy_rate)) if NA_SEQUENCE not in line[9]: cyclomatic_complexity = float(line[9]) ccn = cyclomatic_complexity scores['cyclomatic_complexity'][ folder] = scoring.calculate_cyclomatic_complexity_score( ccn) scores_absolute['cyclomatic_complexity'][ folder] = scoring.calculate_cyclomatic_complexity_score_absolute( ccn) available_categories[folder].append('cyclomatic_complexity') rates['cyclomatic_complexity'].append((folder, ccn)) if NA_SEQUENCE not in line[10]: lizard_warnings = int(line[10]) lizard_rate = lizard_warnings / functions scores['lizard_warnings'][ folder] = scoring.calculate_lizard_warning_score( lizard_rate) scores_absolute['lizard_warnings'][ folder] = scoring.calculate_lizard_warning_score_absolute( lizard_rate) available_categories[folder].append('lizard_warnings') rates['lizard_warnings'].append((folder, lizard_rate)) if NA_SEQUENCE not in line[11]: unique = float(line[11]) unique_rate = unique scores['unique'][folder] = scoring.calculate_unique_score( unique_rate) scores_absolute['unique'][ folder] = scoring.calculate_unique_score_absolute( unique_rate) available_categories[folder].append('unique') rates['unique'].append((folder, unique_rate)) if NA_SEQUENCE not in line[12]: kwstyle = int(line[12]) kwstyle_rate = kwstyle / loc scores['kwstyle'][folder] = scoring.calculate_kwstyle_score( kwstyle_rate) scores_absolute['kwstyle'][ folder] = scoring.calculate_kwstyle_score_absolute( kwstyle_rate) available_categories[folder].append('kwstyle') rates['kwstyle'].append((folder, kwstyle_rate)) if NA_SEQUENCE not in line[13]: infer = int(line[13]) infer_rate = infer / loc scores['infer'][folder] = scoring.calculate_infer_score( infer_rate) scores_absolute['infer'][ folder] = scoring.calculate_infer_score_absolute( infer_rate) available_categories[folder].append('infer') rates['infer'].append((folder, infer_rate)) if NA_SEQUENCE not in line[14]: test_count = int(line[14]) test_count_rate = test_count / loc scores['test_count'][ folder] = scoring.calculate_testcount_score( test_count_rate) scores_absolute['test_count'][ folder] = scoring.calculate_testcount_score_absolute( test_count_rate) available_categories[folder].append('test_count') rates['test_count'].append((folder, test_count_rate)) compiler_and_sanitizer_rate = (compiler + sanitizer) / loc scores['compiler_and_sanitizer'][ folder] = scoring.calculate_compiler_and_sanitizer_score( compiler_and_sanitizer_rate) scores_absolute['compiler_and_sanitizer'][ folder] = scoring.calculate_compiler_and_sanitizer_score_absolute( compiler_and_sanitizer_rate) available_categories[folder].append('compiler_and_sanitizer') rates['compiler_and_sanitizer'].append( (folder, compiler_and_sanitizer_rate)) list_of_scores = [ scores[score][folder] for score in scores.keys() if score != 'overall' and score in available_categories[folder] ] scores['overall'][folder] = scoring.average_score(list_of_scores) scores_absolute['relative_score'][folder] = scores['overall'][ folder] available_categories[folder].append('relative_score') list_of_scores = [ scores_absolute[score][folder] for score in scores_absolute.keys() if score != 'overall' and score != 'relative_score' and score in available_categories[folder] ] scores_absolute['overall'][folder] = scoring.average_score( list_of_scores) d[folder] = scores['overall'][folder] d_absolute[folder] = scores_absolute['overall'][folder] constants[folder] = line[1:-1] sorted_list = sorted(d.items(), key=lambda x: x[1], reverse=True) sorted_list_absolute = sorted(d_absolute.items(), key=lambda x: x[1], reverse=True) sorted_list_constants = sorted(constants.items(), key=lambda x: int(x[1][1]), reverse=True) for (name, score) in sorted_list_constants: print("|", end="") counter = 0 for index in constants[name]: print(" {}".format(index).ljust(space_pattern_constant[counter]), end="|") counter += 1 print() print() for (name, score) in sorted_list_absolute: score_absolute = scores_absolute['overall'][name] print("| {}".format(name).ljust(space_pattern[0]), end="|") print(" {}".format(round(score_absolute, 1)).ljust(space_pattern[1]), end="|") counter = 2 for key in scores_absolute.keys(): if key == 'overall': continue if key not in available_categories[name]: print((" " + NA_SEQUENCE).ljust(space_pattern[counter]), end="|") else: print(" {0:0.1f}".format(round(scores_absolute[key][name], 1)).ljust( space_pattern[counter]), end="|") counter += 1 print() counter = 0 rc_d_squared_sum = 0 for (name, _) in sorted_list: counter2 = 0 for (name2, _) in sorted_list_absolute: if name == name2: rc_d_squared_sum += (counter - counter2) * (counter - counter2) counter2 += 1 counter += 1 n = counter rc = 1 - (6 * rc_d_squared_sum / (n * (n * n - 1))) print("Rank correlation: {}".format(rc)) sorted_rates = compare_results.sort_rates(rates) print() compare_results.print_best_rates(sorted_rates) compare_results.print_softwipe_scoring_values(sorted_rates) return 0
def main(): """ Main function: Runs compilation, static analysis and prints results. """ add_kwstyle_to_path_variable( ) # TODO: hopefully get a conda package for this sometime add_lizard_to_path_variable() # Allow the user to auto-install the dependencies by just running "./softwipe.py" without any arguments # Should not be needed if conda is used. TODO: maybe remove this if len(sys.argv) == 1: automatic_tool_installation.check_if_all_required_tools_are_installed() args = parse_arguments() for argument in sys.argv: print(argument, end=" ") print() # Normal check for the dependencies if len(sys.argv) != 1: automatic_tool_installation.check_if_all_required_tools_are_installed() # if args.use_infer: # add_infer_to_path_variable() add_user_paths_to_path_variable(args) if not args.allow_running_as_root: warn_if_user_is_root() use_cpp = args.cpp use_cmake = args.cmake use_make = args.make program_dir_abs = os.path.abspath(args.programdir) exclude = args.exclude[0] if args.exclude else None exclude_file = args.X[0] if args.X else None excluded_paths = util.get_excluded_paths(program_dir_abs, exclude, exclude_file) custom_asserts = args.custom_assert[0].split( ',') if args.custom_assert else None source_files = util.find_all_source_files(program_dir_abs, excluded_paths) lines_of_code = util.count_lines_of_code(source_files) analysis_tools = [ ] # TODO: maybe add valgrind at some point if we get its error counts normalized somehow all_scores = [] data = { "program_dir_abs": program_dir_abs, "args": args, "excluded_paths": excluded_paths, "use_cpp": use_cpp, "use_cmake": use_cmake, "use_make": use_make, "custom_asserts": custom_asserts, "source_files": source_files, "lines_of_code": lines_of_code, "executefile": args.executefile } if not args.exclude_compilation: compiler_and_sanitizer_score = compile_and_execute_program_with_sanitizers( args, lines_of_code, program_dir_abs, use_cpp, excluded_paths, args.no_execution) all_scores.append(compiler_and_sanitizer_score) if args.use_infer: # TODO: maybe completely remove Infer since it requires a lot of disk space add_infer_to_path_variable() analysis_tools.append(InferTool) if not args.exclude_assertions: analysis_tools.append(AssertionTool) if not args.exclude_clang_tidy: analysis_tools.append(ClangTidyTool) if not args.exclude_cppcheck: analysis_tools.append(CppcheckTool) if not args.exclude_lizard: analysis_tools.append(LizardTool) if not args.exclude_kwstyle: analysis_tools.append(KWStyleTool) analysis_tools.append(TestCountTool) for tool in analysis_tools: scores, log, success = tool.run(data) if success: print(log) all_scores.extend(scores) else: print("excluded {} from analysis\n".format(tool.name())) overall_score = scoring.average_score(all_scores) scoring.print_score(overall_score, 'Overall program absolute') if args.add_badge: add_badge_to_file(args.add_badge[0], overall_score) print("Added badge to file {}".format(args.add_badge[0]))