def test_clang_tidy(mock_repository, mock_config, mock_clang, mock_stats, mock_revision): ''' Test clang-tidy runner ''' from static_analysis_bot.clang.tidy import ClangTidy, ClangTidyIssue from static_analysis_bot.config import settings # Init clang tidy runner ct = ClangTidy() # Write badly formatted c file bad_file = os.path.join(mock_config.repo_dir, 'bad.cpp') with open(bad_file, 'w') as f: f.write(BAD_CPP_TIDY) # Get issues found by clang-tidy mock_revision.files = [ 'bad.cpp', ] mock_revision.lines = { 'bad.cpp': range(len(BAD_CPP_TIDY.split('\n'))), } issues = ct.run(mock_revision) assert len(issues) == 3 assert isinstance(issues[0], ClangTidyIssue) assert issues[0].check == 'modernize-use-nullptr' assert issues[0].reason == 'Modernize our code base to C++11' assert issues[0].line == 3 assert isinstance(issues[1], ClangTidyIssue) assert issues[1].check == 'modernize-use-nullptr' assert issues[1].reason == 'Modernize our code base to C++11' assert issues[1].line == 8 assert isinstance(issues[2], ClangTidyIssue) assert issues[2].check == 'clang-analyzer-deadcode.DeadStores' assert issues[2].reason is None assert issues[2].line == 13 # Ensure the raw output dump exists clang_output_path = os.path.join( settings.taskcluster.results_dir, '{}-clang-tidy.txt'.format(repr(mock_revision)), ) assert os.path.isfile(clang_output_path) # Test stats mock_stats.flush() metrics = mock_stats.get_metrics('issues.clang-tidy') assert len(metrics) == 1 assert metrics[0][1] == 3 metrics = mock_stats.get_metrics('issues.clang-tidy.publishable') assert len(metrics) == 1 assert metrics[0][1] == 3 metrics = mock_stats.get_metrics('runtime.clang-tidy.avg') assert len(metrics) == 1 assert metrics[0][1] > 0
def test_clang_tidy(mock_repository, mock_config, mock_clang, mock_stats, mock_revision): ''' Test clang-tidy runner ''' from static_analysis_bot.clang.tidy import ClangTidy, ClangTidyIssue from static_analysis_bot.config import settings # Init clang tidy runner ct = ClangTidy() # Write badly formatted c file bad_file = os.path.join(mock_config.repo_dir, 'bad.cpp') with open(bad_file, 'w') as f: f.write(BAD_CPP_TIDY) # Get issues found by clang-tidy mock_revision.files = ['bad.cpp', ] mock_revision.lines = { 'bad.cpp': range(len(BAD_CPP_TIDY.split('\n'))), } issues = ct.run(mock_revision) assert len(issues) == 3 assert isinstance(issues[0], ClangTidyIssue) assert issues[0].check == 'modernize-use-nullptr' assert issues[0].reason == 'Modernize our code base to C++11' assert issues[0].line == 3 assert isinstance(issues[1], ClangTidyIssue) assert issues[1].check == 'modernize-use-nullptr' assert issues[1].reason == 'Modernize our code base to C++11' assert issues[1].line == 8 assert isinstance(issues[2], ClangTidyIssue) assert issues[2].check == 'clang-analyzer-deadcode.DeadStores' assert issues[2].reason is None assert issues[2].line == 13 # Ensure the raw output dump exists clang_output_path = os.path.join( settings.taskcluster.results_dir, '{}-clang-tidy.txt'.format(repr(mock_revision)), ) assert os.path.isfile(clang_output_path) # Test stats mock_stats.flush() metrics = mock_stats.get_metrics('issues.clang-tidy') assert len(metrics) == 1 assert metrics[0][1] == 3 metrics = mock_stats.get_metrics('issues.clang-tidy.publishable') assert len(metrics) == 1 assert metrics[0][1] == 3 metrics = mock_stats.get_metrics('runtime.clang-tidy.avg') assert len(metrics) == 1 assert metrics[0][1] > 0
def test_clang_tidy_checks(mock_config, mock_repository, mock_clang): ''' Test that all our clang-tidy checks actually exist ''' from static_analysis_bot.clang.tidy import ClangTidy from static_analysis_bot.config import CONFIG_URL, settings # Get the set of all available checks that the local clang-tidy offers clang_tidy = ClangTidy(validate_checks=False) # Verify that Firefox's clang-tidy configuration actually specifies checks assert len(settings.clang_checkers) > 0, \ 'Firefox clang-tidy configuration {} should specify > 0 clang_checkers'.format(CONFIG_URL) # Verify that the specified clang-tidy checks actually exist missing = clang_tidy.list_missing_checks() assert len(missing) == 0, \ 'Missing clang-tidy checks: {}'.format(', '.join(missing))
def test_clang_tidy_checks(mock_config, mock_repository, mock_clang): ''' Test that all our clang-tidy checks actually exist ''' from static_analysis_bot.clang.tidy import ClangTidy from static_analysis_bot.config import CONFIG_URL, settings # Get the set of all available checks that the local clang-tidy offers clang_tidy = ClangTidy(validate_checks=False) # Verify that Firefox's clang-tidy configuration actually specifies checks assert len(settings.clang_checkers) > 0, \ 'Firefox clang-tidy configuration {} should specify > 0 clang_checkers'.format(CONFIG_URL) # Verify that the specified clang-tidy checks actually exist missing = clang_tidy.list_missing_checks() assert len(missing) == 0, \ 'Missing clang-tidy checks: {}'.format(', '.join(missing))
def test_repeats(mock_clang_repeats, mock_revision, mock_config): ''' Test repeated issues are removed through set usage ''' from static_analysis_bot.clang.tidy import ClangTidy clang_tidy = ClangTidy() issues = clang_tidy.parse_issues(mock_clang_repeats, mock_revision) assert isinstance(issues, list) # We have 2 issues for modernize-loop-convert # on the same file/line/char assert len(issues) == 4 count = Counter(i.check for i in issues) assert count['modernize-loop-convert'] == 2 # A set should remove repeats issues = set(issues) assert len(issues) == 3 count = Counter(i.check for i in issues) assert count['modernize-loop-convert'] == 1
def test_repeats(mock_clang_repeats, mock_clang, mock_revision, mock_config, mock_repository): ''' Test repeated issues are removed through set usage ''' from static_analysis_bot.clang.tidy import ClangTidy clang_tidy = ClangTidy() issues = clang_tidy.parse_issues(mock_clang_repeats, mock_revision) assert isinstance(issues, list) # We have 2 issues for modernize-loop-convert # on the same file/line/char assert len(issues) == 4 count = Counter(i.check for i in issues) assert count['modernize-loop-convert'] == 2 # A set should remove repeats issues = set(issues) assert len(issues) == 3 count = Counter(i.check for i in issues) assert count['modernize-loop-convert'] == 1
def test_clang_tidy_parser(mock_config, mock_repository, mock_revision, mock_clang_output, mock_clang_issues): ''' Test the clang-tidy (or mach static-analysis) parser ''' from static_analysis_bot.clang.tidy import ClangTidy clang_tidy = ClangTidy() # Empty Output clang_output = 'Nothing.' issues = clang_tidy.parse_issues(clang_output, mock_revision) assert issues == [] # No warnings clang_output = 'Whatever text.\n0 warnings present.' issues = clang_tidy.parse_issues(clang_output, mock_revision) assert issues == [] # One warning, but no header clang_output = 'Whatever text.\n1 warnings present.' with pytest.raises(Exception): clang_tidy.parse_issues(clang_output, mock_revision) # One warning, One header clang_output = '/path/to/test.cpp:42:39: error: methods annotated with MOZ_NO_DANGLING_ON_TEMPORARIES cannot be && ref-qualified [mozilla-dangling-on-temporary]' # noqa clang_output += '\n1 warnings present.' issues = clang_tidy.parse_issues(clang_output, mock_revision) assert len(issues) == 1 assert issues[0].path == '/path/to/test.cpp' assert issues[0].line == 42 assert issues[0].check == 'mozilla-dangling-on-temporary' # Real case issues = clang_tidy.parse_issues(mock_clang_output, mock_revision) assert len(issues) == 13 sep = '\n' + '-' * 20 + '\n' summary = sep.join(issue.as_text() for issue in issues) assert summary == mock_clang_issues
def test_clang_tidy_parser(mock_config, mock_repository, mock_revision, mock_clang_output, mock_clang_issues): ''' Test the clang-tidy (or mach static-analysis) parser ''' from static_analysis_bot.clang.tidy import ClangTidy clang_tidy = ClangTidy() # Empty Output clang_output = 'Nothing.' issues = clang_tidy.parse_issues(clang_output, mock_revision) assert issues == [] # No warnings clang_output = 'Whatever text.\n0 warnings present.' issues = clang_tidy.parse_issues(clang_output, mock_revision) assert issues == [] # One warning, but no header clang_output = 'Whatever text.\n1 warnings present.' with pytest.raises(Exception): clang_tidy.parse_issues(clang_output, mock_revision) # One warning, One header clang_output = '/path/to/test.cpp:42:39: error: methods annotated with MOZ_NO_DANGLING_ON_TEMPORARIES cannot be && ref-qualified [mozilla-dangling-on-temporary]' # noqa clang_output += '\n1 warnings present.' issues = clang_tidy.parse_issues(clang_output, mock_revision) assert len(issues) == 1 assert issues[0].path == '/path/to/test.cpp' assert issues[0].line == 42 assert issues[0].check == 'mozilla-dangling-on-temporary' # Real case issues = clang_tidy.parse_issues(mock_clang_output, mock_revision) assert len(issues) == 13 sep = '\n' + '-'*20 + '\n' summary = sep.join(issue.as_text() for issue in issues) assert summary == mock_clang_issues