示例#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
示例#2
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
示例#3
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))
示例#4
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))
示例#5
0
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
示例#6
0
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
示例#7
0
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
示例#8
0
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