def test_flake8_rules(mock_config, mock_repository, mock_revision): ''' Check flake8 rule detection ''' from static_analysis_bot.lint import MozLintIssue # Build fake python files path = os.path.join(mock_config.repo_dir, 'test.py') with open(path, 'w') as f: f.write('print("TEST")') path = os.path.join(mock_config.repo_dir, 'test/dummy/XXX.py') os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, 'w') as f: f.write('print("TEST 2")') # Valid issue issue = MozLintIssue('test.py', 1, 'error', 1, 'flake8', 'Dummy test', 'dummy rule', mock_revision) assert not issue.is_disabled_rule() assert issue.validates() # 3rd party issue = MozLintIssue('test/dummy/XXX.py', 1, 'error', 1, 'flake8', 'Dummy test', 'dummy rule', mock_revision) assert not issue.is_disabled_rule() assert issue.is_third_party() assert not issue.validates() # Flake8 bad quotes issue = MozLintIssue('test.py', 1, 'error', 1, 'flake8', 'Remove bad quotes or whatever.', 'Q000', mock_revision) assert issue.is_disabled_rule() assert not issue.validates()
def test_as_text(mock_revision): ''' Test text export for ClangTidyIssue ''' from static_analysis_bot.lint import MozLintIssue issue = MozLintIssue('test.py', 1, 'error', 1, 'flake8', 'dummy test withUppercaseChars', 'dummy rule', mock_revision) assert issue.as_text() == 'Error: Dummy test withUppercaseChars [flake8: dummy rule]'
def test_as_text(mock_config, mock_revision, mock_repository): ''' Test text export for ClangTidyIssue ''' from static_analysis_bot.lint import MozLintIssue path = os.path.join(mock_config.repo_dir, 'test.py') with open(path, 'w') as f: f.write('print("TEST")') issue = MozLintIssue('test.py', 1, 'error', 1, 'flake8', 'dummy test withUppercaseChars', 'dummy rule', mock_revision) assert issue.as_text() == 'Error: Dummy test withUppercaseChars [flake8: dummy rule]'
def test_issue_path(mock_repository, mock_config, mock_revision): ''' A mozlint issue can be absolute or relative But the path sent to reporters must always be relative ''' from static_analysis_bot.lint import MozLintIssue relative_path = 'test.txt' issue = MozLintIssue(relative_path, 1, 'error', 1, 'dummy', 'Any error', 'XXX', mock_revision) assert issue.path == 'test.txt' absolute_path = os.path.join(mock_config.repo_dir, relative_path) issue = MozLintIssue(absolute_path, 1, 'error', 1, 'dummy', 'Any error', 'XXX', mock_revision) assert issue.path == 'test.txt'
def _test_reporter(api, analyzers): # Always use the same setup, only varies the analyzers revision = PhabricatorRevision('PHID-DIFF-abcdef', api) revision.lines = { 'test.cpp': [41, 42, 43], } reporter = PhabricatorReporter({'analyzers': analyzers}, api=api) issues = [ ClangFormatIssue('test.cpp', 42, 1, revision), ClangTidyIssue(('test.cpp', '42', '51', 'error', 'dummy message', 'modernize-use-nullptr'), revision), InferIssue({ 'file': 'test.cpp', 'line': 42, 'column': 1, 'bug_type': 'dummy', 'kind': 'whatever', 'qualifier': 'dummy message.', }, revision), MozLintIssue('test.cpp', 1, 'danger', 42, 'flake8', 'Python error', 'EXXX', revision), ] assert all(i.is_publishable() for i in issues) revision.improvement_patches = { 'dummy': 'not gonna work', 'clang-format': 'https://diff.url/clang-format', 'clang-tidy': 'https://diff.url/clang-tidy', 'mozlint': 'https://diff.url/mozlint', 'infer': 'https://diff.url/infer', } return reporter.publish(issues, revision)
def build_issue(self, task_name, issue, revision): ''' Convert a raw text issue into an Issue instance TODO: this should be simplified by using mach JSON output ''' if task_name.startswith(MozLintIssue.TRY_PREFIX): return MozLintIssue.from_try(task_name, issue, revision) else: logger.warn('Unsupported task type', name=task_name)
def test_as_text(mock_config, mock_revision, mock_repository): ''' Test text export for ClangTidyIssue ''' from static_analysis_bot.lint import MozLintIssue path = os.path.join(mock_config.repo_dir, 'test.py') with open(path, 'w') as f: f.write('print("TEST")') issue = MozLintIssue('test.py', 1, 'error', 1, 'flake8', 'dummy test withUppercaseChars', 'dummy rule', mock_revision) assert issue.as_text() == 'Error: Dummy test withUppercaseChars [flake8: dummy rule]' assert issue.as_phabricator_lint() == { 'char': 1, 'code': 'flake8.dummy rule', 'line': 1, 'name': 'MozLint Flake8 - dummy rule', 'description': 'dummy test withUppercaseChars', 'path': 'test.py', 'severity': 'error', }
def test_from_try(mock_revision, mock_config): ''' Test issue building from try lines ''' mock_config.has_local_clone = False from static_analysis_bot.lint import MozLintIssue line = """/builds/worker/checkouts/gecko/tools/tryselect/cli.py:14:1 | block comment should start with '# ' (E265)""" # noqa issue = MozLintIssue.from_try('source-test-mozlint-py-flake8', line, mock_revision) assert issue.path == 'gecko/tools/tryselect/cli.py' assert issue.line == 14 assert issue.column == 1 assert issue.message == "block comment should start with '# '" assert issue.linter == 'py-flake8' assert issue.rule == 'E265'
def _test_reporter(api, analyzers): # Always use the same setup, only varies the analyzers revision = PhabricatorRevision(api, 'PHID-DIFF-abcdef') revision.lines = { 'test.cpp': [0, 41, 42, 43], 'dom/test.cpp': [ 42, ], } reporter = PhabricatorReporter({'analyzers': analyzers}, api=api) issues = [ ClangFormatIssue('dom/test.cpp', 42, 1, revision), ClangTidyIssue(('test.cpp', '42', '51', 'error', 'dummy message', 'modernize-use-nullptr'), revision), InferIssue( { 'file': 'test.cpp', 'line': 42, 'column': 1, 'bug_type': 'dummy', 'kind': 'whatever', 'qualifier': 'dummy message.', }, revision), MozLintIssue('test.cpp', 1, 'danger', 42, 'flake8', 'Python error', 'EXXX', revision), CoverageIssue('test.cpp', 0, 'This file is uncovered', revision), ] assert all(i.is_publishable() for i in issues) revision.improvement_patches = [ ImprovementPatch('dummy', repr(revision), 'Whatever'), ImprovementPatch('clang-tidy', repr(revision), 'Some C fixes'), ImprovementPatch('clang-format', repr(revision), 'Some lint fixes'), ImprovementPatch('infer', repr(revision), 'Some java fixes'), ImprovementPatch('mozlint', repr(revision), 'Some js fixes'), ] list(map(lambda p: p.write(), revision.improvement_patches)) # trigger local write return reporter.publish(issues, revision)
def test_flake8_rules(tmpdir, mock_config, mock_revision): ''' Check flake8 rule detection ''' from static_analysis_bot.lint import MozLintIssue # Build fake python files path = os.path.join(mock_config.repo_dir, 'test.py') with open(path, 'w') as f: f.write('print("TEST")') path = os.path.join(mock_config.repo_dir, 'test/dummy/XXX.py') os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, 'w') as f: f.write('print("TEST 2")') # Valid issue issue = MozLintIssue('test.py', 1, 'error', 1, 'flake8', 'Dummy test', 'dummy rule', mock_revision) assert not issue.is_disabled_rule() assert issue.validates() # 3rd party issue = MozLintIssue('test/dummy/XXX.py', 1, 'error', 1, 'flake8', 'Dummy test', 'dummy rule', mock_revision) assert not issue.is_disabled_rule() assert issue.is_third_party() assert not issue.validates() # Flake8 bad quotes issue = MozLintIssue('test.py', 1, 'error', 1, 'flake8', 'Remove bad quotes or whatever.', 'Q000', mock_revision) assert issue.is_disabled_rule() assert not issue.validates()
def test_comment(mock_mozreview, test_cpp, mock_revision): ''' Test comment creation for specific issues ''' from static_analysis_bot.clang.tidy import ClangTidyIssue from static_analysis_bot.clang.format import ClangFormatIssue from static_analysis_bot.lint import MozLintIssue from static_analysis_bot.report.base import Reporter # Init dummy reporter class TestReporter(Reporter): def __init__(self): pass reporter = TestReporter() # Build clang tidy fake issue, while forcing publication status header = ('test.cpp', 1, 1, 'error', 'Dummy message', 'test-check') clang_tidy_publishable = ClangTidyIssue(header, mock_revision) clang_tidy_publishable.is_publishable = lambda: True assert clang_tidy_publishable.is_publishable() issues = [ clang_tidy_publishable, ] assert reporter.build_comment(issues, 'https://report.example.com') == ''' Code analysis found 1 defect in this patch: - 1 defect found by clang-tidy You can run this analysis locally with: - `./mach static-analysis check path/to/file.cpp` (C/C++) If you see a problem in this automated review, please report it here: https://report.example.com ''' # Now add a clang-format issue clang_format_publishable = ClangFormatIssue('test.cpp', '', '', ('delete', 1, 2, 3, 4), mock_revision) clang_format_publishable.is_publishable = lambda: True assert clang_tidy_publishable.is_publishable() issues.append(clang_format_publishable) assert reporter.build_comment(issues, 'https://report.example.com') == ''' Code analysis found 2 defects in this patch: - 1 defect found by clang-format - 1 defect found by clang-tidy You can run this analysis locally with: - `./mach clang-format -p path/to/file.cpp` (C/C++) - `./mach static-analysis check path/to/file.cpp` (C/C++) If you see a problem in this automated review, please report it here: https://report.example.com ''' # Now add a mozlint issue mozlint_publishable = MozLintIssue('test.cpp', 1, 'error', 1, 'test', 'Dummy test', 'dummy rule', mock_revision) mozlint_publishable.is_publishable = lambda: True assert mozlint_publishable.is_publishable() issues.append(mozlint_publishable) assert reporter.build_comment(issues, 'https://report.example.com') == '''