Exemplo n.º 1
0
def test_publication(monkeypatch, mock_taskcluster_config):
    """
    Check a patch publication through Taskcluster services
    """

    # Setup local config as running in a real Taskcluster task with proxy
    monkeypatch.setenv("TASK_ID", "fakeTaskId")
    monkeypatch.setenv("RUN_ID", "0")
    monkeypatch.setenv("TASKCLUSTER_PROXY_URL", "http://proxy")
    settings.setup("test", [])

    # Mock the storage response
    responses.add(
        responses.PUT,
        "http://storage.test/public/patch/mock-analyzer-test-improvement.diff",
        json={},
        headers={"ETag": "test123"},
    )

    patch = ImprovementPatch("mock-analyzer", "test-improvement", "This is good code")
    assert patch.url is None

    patch.publish()
    assert (
        patch.url
        == "https://firefox-ci-tc.services.mozilla.com/api/queue/v1/task/fakeTaskId/runs/0/artifacts/public/patch/mock-analyzer-test-improvement.diff"
    )

    # Check the mock has been called
    assert [c.request.url for c in responses.calls] == [
        "http://storage.test/public/patch/mock-analyzer-test-improvement.diff"
    ]
Exemplo n.º 2
0
    def _test_reporter(api, analyzers_skipped):
        # Always use the same setup, only varies the analyzers
        revision = Revision.from_try(mock_try_task, api)
        revision.lines = {"test.cpp": [0, 41, 42, 43], "dom/test.cpp": [42]}
        reporter = PhabricatorReporter(
            {"analyzers_skipped": analyzers_skipped}, api=api
        )

        issues = [
            ClangFormatIssue("mock-clang-format", "dom/test.cpp", 42, 1, revision),
            ClangTidyIssue(
                "mock-clang-tidy",
                revision,
                "test.cpp",
                "42",
                "51",
                "modernize-use-nullptr",
                "dummy message",
            ),
            InferIssue(
                "mock-infer",
                {
                    "file": "test.cpp",
                    "line": 42,
                    "column": 1,
                    "bug_type": "dummy",
                    "kind": "WARNING",
                    "qualifier": "dummy message.",
                },
                revision,
            ),
            MozLintIssue(
                "mock-lint-flake8",
                "test.cpp",
                1,
                "error",
                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("mock-clang-tidy", repr(revision), "Some C fixes"),
            ImprovementPatch("mock-clang-format", repr(revision), "Some lint fixes"),
            ImprovementPatch("mock-infer", repr(revision), "Some java fixes"),
            ImprovementPatch("mock-lint-flake8", repr(revision), "Some js fixes"),
        ]
        list(
            map(lambda p: p.write(), revision.improvement_patches)
        )  # trigger local write

        return reporter.publish(issues, revision, [])
Exemplo n.º 3
0
def test_mail(mock_config, mock_issues, mock_revision, mock_taskcluster_config,
              mock_task):
    """
    Test mail sending through Taskcluster
    """
    from code_review_bot.report.mail import MailReporter
    from code_review_bot.revisions import ImprovementPatch

    def _check_email(request):
        payload = json.loads(request.body)

        assert payload["subject"] in (
            "[test] New Static Analysis Phabricator #42 - PHID-DIFF-test", )
        assert payload["address"] == "*****@*****.**"
        assert payload["template"] == "fullscreen"
        assert payload["content"] == MAIL_CONTENT.format(
            results=mock_config.taskcluster.results_dir)

        return (200, {}, "")  # ack

    # Add mock taskcluster email to check output
    responses.add_callback(
        responses.POST,
        "http://taskcluster.test/api/notify/v1/email",
        callback=_check_email,
    )

    # Publish email
    conf = {"emails": ["*****@*****.**"]}
    r = MailReporter(conf)

    mock_revision.improvement_patches = [
        ImprovementPatch(
            mock_task(ClangTidyTask, "clang-tidy"),
            repr(mock_revision),
            "Some code fixes",
        ),
        ImprovementPatch(
            mock_task(ClangFormatTask, "clang-format"),
            repr(mock_revision),
            "Some lint fixes",
        ),
    ]
    list(map(lambda p: p.write(),
             mock_revision.improvement_patches))  # trigger local write
    r.publish(mock_issues, mock_revision, [])

    # Check stats
    assert r.calc_stats(mock_issues) == [{
        "analyzer":
        "mock-analyzer",
        "help":
        None,
        "total":
        5,
        "publishable":
        3,
        "publishable_paths": ["/path/to/file"],
    }]
Exemplo n.º 4
0
def test_phabricator_clang_format(mock_config, mock_phabricator, mock_try_task):
    """
    Test Phabricator reporter publication on a mock clang-format issue
    """
    from code_review_bot.report.phabricator import PhabricatorReporter
    from code_review_bot.revisions import Revision, ImprovementPatch
    from code_review_bot.tasks.clang_format import ClangFormatIssue

    def _check_comment(request):
        # Check the Phabricator main comment is well formed
        payload = urllib.parse.parse_qs(request.body)
        assert payload["output"] == ["json"]
        assert len(payload["params"]) == 1
        details = json.loads(payload["params"][0])
        assert details["message"] == VALID_CLANG_FORMAT_MESSAGE.format(
            results=mock_config.taskcluster.results_dir
        )

        # Outputs dummy empty response
        resp = {"error_code": None, "result": None}
        return (
            201,
            {"Content-Type": "application/json", "unittest": "clang-format"},
            json.dumps(resp),
        )

    responses.add_callback(
        responses.POST,
        "http://phabricator.test/api/differential.createcomment",
        callback=_check_comment,
    )

    with mock_phabricator as api:
        revision = Revision.from_try(mock_try_task, api)
        revision.lines = {
            # Add dummy lines diff
            "test.cpp": [41, 42, 43],
            "dom/test.cpp": [42],
        }
        reporter = PhabricatorReporter({"analyzers": ["clang-format"]}, api=api)

    issue = ClangFormatIssue(
        "source-test-clang-format", "dom/test.cpp", 42, 1, revision
    )
    assert issue.is_publishable()

    revision.improvement_patches = [
        ImprovementPatch("clang-format", repr(revision), "Some lint fixes")
    ]
    list(map(lambda p: p.write(), revision.improvement_patches))  # trigger local write

    issues, patches = reporter.publish([issue], revision, [])
    assert len(issues) == 1
    assert len(patches) == 1

    # Check the callback has been used
    assert len(responses.calls) > 0
    call = responses.calls[-1]
    assert call.request.url == "http://phabricator.test/api/differential.createcomment"
    assert call.response.headers.get("unittest") == "clang-format"
def test_phabricator_clang_format(mock_config, mock_phabricator, phab,
                                  mock_try_task, mock_task):
    """
    Test Phabricator reporter publication on a mock clang-format issue
    """

    with mock_phabricator as api:
        revision = Revision.from_try(mock_try_task, api)
        revision.mercurial_revision = "deadbeef1234"
        revision.repository = "https://hg.mozilla.org/try"
        revision.repository_try_name = "try"
        revision.lines = {
            # Add dummy lines diff
            "test.cpp": [41, 42, 43],
            "dom/test.cpp": [42],
        }
        reporter = PhabricatorReporter({"analyzers": ["clang-format"]},
                                       api=api)

    task = mock_task(ClangFormatTask, "source-test-clang-format")
    lines = [
        (41, 41, b"no change"),
        (42, None, b"deletion"),
        (None, 42, b"change here"),
    ]
    issue = ClangFormatIssue(task, "dom/test.cpp", lines, revision)
    assert issue.is_publishable()

    revision.improvement_patches = [
        ImprovementPatch(task, repr(revision), "Some lint fixes")
    ]
    list(map(lambda p: p.write(),
             revision.improvement_patches))  # trigger local write

    issues, patches = reporter.publish([issue], revision, [], [])
    assert len(issues) == 1
    assert len(patches) == 1

    # Check the comment has been posted
    assert phab.comments[51] == [
        VALID_CLANG_FORMAT_MESSAGE.format(
            results=mock_config.taskcluster.results_dir)
    ]
Exemplo n.º 6
0
def test_phabricator_analyzers(
    analyzers_skipped,
    valid_issues,
    valid_patches,
    mock_config,
    mock_phabricator,
    mock_try_task,
    mock_task,
):
    """
    Test analyzers filtering on phabricator reporter
    """
    with mock_phabricator as api:

        # Skip commenting on phabricator
        # we only care about filtering issues
        api.comment = unittest.mock.Mock(return_value=True)

        # Always use the same setup, only varies the analyzers
        revision = Revision.from_try(mock_try_task, api)
        revision.mercurial_revision = "deadbeef1234"
        revision.repository = "https://hg.mozilla.org/try"
        revision.repository_try_name = "try"
        revision.lines = {"test.cpp": [0, 41, 42, 43], "dom/test.cpp": [42]}
        reporter = PhabricatorReporter(
            {"analyzers_skipped": analyzers_skipped}, api=api
        )

    issues = [
        ClangFormatIssue(
            mock_task(ClangFormatTask, "mock-clang-format"),
            "dom/test.cpp",
            [
                (41, 41, b"no change"),
                (42, None, b"deletion"),
                (None, 42, b"change here"),
            ],
            revision,
        ),
        ClangTidyIssue(
            mock_task(ClangTidyTask, "mock-clang-tidy"),
            revision,
            "test.cpp",
            "42",
            "51",
            "modernize-use-nullptr",
            "dummy message",
        ),
        InferIssue(
            mock_task(InferTask, "mock-infer"),
            {
                "file": "test.cpp",
                "line": 42,
                "column": 1,
                "bug_type": "dummy",
                "kind": "WARNING",
                "qualifier": "dummy message.",
            },
            revision,
        ),
        MozLintIssue(
            mock_task(MozLintTask, "mock-lint-flake8"),
            "test.cpp",
            1,
            "error",
            42,
            "flake8",
            "Python error",
            "EXXX",
            revision,
        ),
        CoverageIssue(
            mock_task(ZeroCoverageTask, "coverage"),
            "test.cpp",
            0,
            "This file is uncovered",
            revision,
        ),
    ]

    assert all(i.is_publishable() for i in issues)

    revision.improvement_patches = [
        ImprovementPatch(mock_task(DefaultTask, "dummy"), repr(revision), "Whatever"),
        ImprovementPatch(
            mock_task(ClangTidyTask, "mock-clang-tidy"), repr(revision), "Some C fixes"
        ),
        ImprovementPatch(
            mock_task(ClangFormatTask, "mock-clang-format"),
            repr(revision),
            "Some lint fixes",
        ),
        ImprovementPatch(
            mock_task(InferTask, "mock-infer"), repr(revision), "Some java fixes"
        ),
        ImprovementPatch(
            mock_task(MozLintTask, "mock-lint-flake8"), repr(revision), "Some js fixes"
        ),
    ]
    list(map(lambda p: p.write(), revision.improvement_patches))  # trigger local write

    issues, patches = reporter.publish(issues, revision, [])

    # Check issues & patches analyzers
    assert len(issues) == len(valid_issues)
    assert len(patches) == len(valid_patches)
    assert [i.analyzer.name for i in issues] == valid_issues
    assert [p.analyzer.name for p in patches] == valid_patches