示例#1
0
def test_land_commit(env, git_gecko, git_wpt, git_wpt_upstream, pull_request, set_pr_status,
                     hg_gecko_try, mock_mach, mock_tasks):
    pr = pull_request([(b"Test commit", {"README": b"example_change"})])
    head_rev = pr._commits[0]["sha"]

    trypush.Mach = mock_mach

    downstream.new_wpt_pr(git_gecko, git_wpt, pr)
    downstream_sync = set_pr_status(pr.number, "success")

    git_wpt_upstream.head.commit = head_rev
    git_wpt.remotes.origin.fetch()
    landing.wpt_push(git_gecko, git_wpt, [head_rev], create_missing=False)

    with SyncLock.for_process(downstream_sync.process_name) as downstream_lock:
        with downstream_sync.as_mut(downstream_lock):
            downstream_sync.data["force-metadata-ready"] = True

    tree.is_open = lambda x: True
    sync = landing.update_landing(git_gecko, git_wpt)

    assert ("Setting bug %s add_blocks %s" % (sync.bug, downstream_sync.bug)
            in env.bz.output.getvalue())

    try_push = sync.latest_try_push
    with SyncLock.for_process(sync.process_name) as lock:
        with sync.as_mut(lock), try_push.as_mut(lock):
            try_push.taskgroup_id = "abcdef"
            with patch.object(try_push, "download_logs", Mock(return_value=[])):
                with patch.object(tc.TaskGroup, "tasks",
                                  property(Mock(return_value=mock_tasks(completed=["foo"])))):
                    landing.try_push_complete(git_gecko, git_wpt, try_push, sync)

    assert "Pushed to try (stability)" in env.bz.output.getvalue()
    assert try_push.status == "complete"
    assert sync.status == "open"

    try_push = sync.latest_try_push
    with SyncLock.for_process(sync.process_name) as lock:
        with sync.as_mut(lock), try_push.as_mut(lock):
            try_push.taskgroup_id = "abcdef2"
            with patch.object(try_push, "download_logs", Mock(return_value=[])):
                with patch.object(tc.TaskGroup, "tasks",
                                  property(Mock(return_value=mock_tasks(completed=["foo"])))):
                    landing.try_push_complete(git_gecko, git_wpt, try_push, sync)

    new_head = git_gecko.remotes.mozilla.refs["bookmarks/mozilla/autoland"].commit
    assert "Update web-platform-tests to %s" % head_rev in new_head.message
    assert (new_head.tree["testing/web-platform/tests/README"].data_stream.read() ==
            b"example_change")
    sync_point = landing.load_sync_point(git_gecko, git_wpt)
    assert sync_point["upstream"] == head_rev
    # Update central to contain the landing
    git_gecko.refs["mozilla/bookmarks/mozilla/central"].commit = new_head
    with patch("sync.landing.start_next_landing") as start_next_landing:
        landing.gecko_push(git_gecko, git_wpt, "mozilla-central",
                           git_gecko.cinnabar.git2hg(new_head))
        assert start_next_landing.call_count == 1
    assert sync.status == "complete"
示例#2
0
def test_no_download_logs_after_all_try_tasks_success(git_gecko, git_wpt,
                                                      try_push, mock_tasks,
                                                      env):
    tasks = Mock(return_value=mock_tasks(completed=["bar", "baz", "boo"]))
    with patch.object(tc.TaskGroup, "tasks", property(tasks)):
        sync = landing.update_landing(git_gecko, git_wpt)
        try_push.download_logs = Mock(return_value=[])
        landing.try_push_complete(git_gecko, git_wpt, try_push, sync)
        # no intermittents in the try push
        try_push.download_logs.assert_not_called()
        assert sync.status == "open"
        assert try_push.status == "complete"
示例#3
0
def test_try_push_exceeds_failure_threshold(git_gecko, git_wpt, landing_with_try_push, mock_tasks):
    # 2/3 failure rate, too high
    sync = landing_with_try_push
    try_push = sync.latest_try_push
    with patch.object(tc.TaskGroup, "tasks",
                      property(Mock(return_value=mock_tasks(failed=["foo", "foobar"],
                                                            completed=["bar"])))):
        with SyncLock.for_process(sync.process_name) as lock:
            with sync.as_mut(lock), try_push.as_mut(lock):
                with pytest.raises(AbortError):
                    landing.try_push_complete(git_gecko, git_wpt, try_push, sync)
    assert try_push.status == "open"
    assert "too many test failures" in sync.error["message"]
示例#4
0
def test_try_push_exceeds_failure_threshold(git_gecko, git_wpt, try_push,
                                            mock_tasks):
    # 2/3 failure rate, too high
    with patch.object(
            tc.TaskGroup, "tasks",
            property(
                Mock(return_value=mock_tasks(failed=["foo", "foobar"],
                                             completed=["bar"])))):
        try_push.taskgroup_id = "abcdef"
        sync = try_push.sync(git_gecko, git_wpt)
        landing.try_push_complete(git_gecko, git_wpt, try_push, sync)
    assert try_push.status == "complete"
    assert "too many failures" in sync.error["message"]
示例#5
0
def test_no_download_logs_after_all_try_tasks_success(git_gecko, git_wpt, landing_with_try_push,
                                                      mock_tasks, env):
    tasks = Mock(return_value=mock_tasks(completed=["bar", "baz", "boo"]))
    sync = landing_with_try_push
    try_push = sync.latest_try_push
    with SyncLock.for_process(sync.process_name) as lock:
        with try_push.as_mut(lock), sync.as_mut(lock):
            with patch.object(tc.TaskGroup,
                              "tasks",
                              property(tasks)), patch(
                                  'sync.landing.push_to_gecko'):
                try_push.download_logs = Mock(return_value=[])
                landing.try_push_complete(git_gecko, git_wpt, try_push, sync)
                # no intermittents in the try push
                try_push.download_logs.assert_not_called()
                assert try_push.status == "complete"
示例#6
0
def test_land_commit(env, git_gecko, git_wpt, git_wpt_upstream, pull_request,
                     set_pr_status, hg_gecko_try, mock_mach, mock_tasks):
    pr = pull_request([("Test commit", {"README": "example_change"})])
    head_rev = pr._commits[0]["sha"]

    trypush.Mach = mock_mach

    downstream.new_wpt_pr(git_gecko, git_wpt, pr)
    downstream_sync = set_pr_status(pr, "success")

    git_wpt_upstream.head.commit = head_rev
    git_wpt.remotes.origin.fetch()
    landing.wpt_push(git_gecko, git_wpt, [head_rev], create_missing=False)

    downstream_sync.data["force-metadata-ready"] = True

    tree.is_open = lambda x: True
    sync = landing.update_landing(git_gecko, git_wpt)

    # Set the landing sync point to current central
    sync.last_sync_point(git_gecko, "mozilla-central",
                         env.config["gecko"]["refs"]["central"])

    try_push = sync.latest_try_push
    try_push.taskgroup_id = "abcdef"
    with patch.object(try_push, "download_logs", Mock(return_value=[])):
        with patch.object(
                tc.TaskGroup, "tasks",
                property(Mock(return_value=mock_tasks(completed=["foo"])))):
            landing.try_push_complete(git_gecko, git_wpt, try_push, sync)

    assert sync.status == "open"
    new_head = git_gecko.remotes.mozilla.refs[
        "bookmarks/mozilla/inbound"].commit
    assert "Update web-platform-tests to %s" % head_rev in new_head.message
    assert new_head.tree["testing/web-platform/tests/README"].data_stream.read(
    ) == "example_change"
    sync_point = landing.load_sync_point(git_gecko, git_wpt)
    assert sync_point["local"] == new_head.parents[0].hexsha
    assert sync_point["upstream"] == head_rev
    # Update central to contain the landing
    git_gecko.refs["mozilla/bookmarks/mozilla/central"].commit = new_head
    with patch("sync.landing.tasks.land.apply_async") as mock_apply:
        landing.gecko_push(git_gecko, git_wpt, "mozilla-central",
                           git_gecko.cinnabar.git2hg(new_head))
        assert mock_apply.call_count == 1
    assert sync.status == "complete"
示例#7
0
def test_try_push_retriggers_failures(git_gecko, git_wpt, landing_with_try_push, mock_tasks, env,
                                      mock_mach):
    # 20% failure rate, okay
    tasks = Mock(return_value=mock_tasks(
        failed=["foo"], completed=["bar", "baz", "boo", "faz"])
    )
    sync = landing_with_try_push
    try_push = sync.latest_try_push
    with SyncLock("landing", None) as lock:
        with sync.as_mut(lock), try_push.as_mut(lock):
            with patch.object(tc.TaskGroup, "tasks", property(tasks)):
                with patch('sync.trypush.auth_tc.retrigger',
                           return_value=["job"] * trypush.TryPushTasks._retrigger_count):
                    try_push.Mach = mock_mach
                    with try_push.as_mut(lock):
                        try_push["stability"] = True
                        try_push.taskgroup_id = "12345678"
                        landing.try_push_complete(git_gecko, git_wpt, try_push, sync)
                    assert "Retriggered failing web-platform-test tasks" in env.bz.output.getvalue()
                    assert try_push.status != "complete"
示例#8
0
def test_download_logs_after_retriggers_complete(git_gecko, git_wpt, try_push,
                                                 mock_tasks, env):
    # > 80% of retriggered "foo" tasks pass, so we consider the "foo" failure intermittent
    mock_tasks = Mock(
        return_value=mock_tasks(failed=["foo", "foo", "bar"],
                                completed=[
                                    "bar", "bar", "bar"
                                    "baz", "boo", "foo", "foo", "foo", "foo",
                                    "foo", "foobar", "foobar", "foobar"
                                ]))
    with patch.object(tc.TaskGroup, "tasks", property(mock_tasks)):
        sync = landing.update_landing(git_gecko, git_wpt)
        try_push.download_logs = Mock(return_value=[])
        try_push["stability"] = True
        landing.try_push_complete(git_gecko, git_wpt, try_push, sync)
        try_push.download_logs.assert_called_with(raw=False,
                                                  report=True,
                                                  exclude=["foo"])
        assert sync.status == "open"
        assert try_push.status == "complete"
示例#9
0
def test_download_logs_after_retriggers_complete(git_gecko, git_wpt, landing_with_try_push,
                                                 mock_tasks, env):
    # > 80% of retriggered "foo" tasks pass, so we consider the "foo" failure intermittent
    tasks = Mock(return_value=mock_tasks(
        failed=["foo", "foo", "bar"],
        completed=["bar", "bar", "bar" "baz", "boo", "foo", "foo", "foo", "foo", "foo",
                   "foobar", "foobar", "foobar"])
    )
    sync = landing_with_try_push
    try_push = sync.latest_try_push
    with SyncLock.for_process(sync.process_name) as lock:
        with try_push.as_mut(lock), sync.as_mut(lock):
            with patch.object(tc.TaskGroup,
                              "tasks",
                              property(tasks)), patch(
                                  'sync.landing.push_to_gecko'):
                try_push.download_logs = Mock(return_value=[])
                try_push["stability"] = True
                landing.try_push_complete(git_gecko, git_wpt, try_push, sync)
        try_push.download_logs.assert_called_with(ANY)
        assert try_push.status == "complete"
示例#10
0
def test_try_push_retriggers_failures(git_gecko, git_wpt, try_push, mock_tasks,
                                      env):
    # 20% failure rate, okay
    tasks = Mock(return_value=mock_tasks(
        failed=["foo"], completed=["bar", "baz", "boo", "faz"]))
    sync = try_push.sync(git_gecko, git_wpt)
    with patch.object(tc.TaskGroup, "tasks", property(tasks)):
        with patch('sync.trypush.auth_tc.retrigger',
                   return_value=["job"] * try_push._retrigger_count):
            landing.try_push_complete(git_gecko, git_wpt, try_push, sync)
            assert "Pushed to try (stability)" in env.bz.output.getvalue()
            assert try_push.status == "complete"
            assert sync.latest_try_push != try_push
            try_push = sync.latest_try_push
            # Give try push a fake taskgroup id
            try_push.taskgroup_id = "abcdef"
            assert try_push.stability
            landing.try_push_complete(git_gecko, git_wpt, try_push, sync)
            assert "Retriggered failing web-platform-test tasks" in env.bz.output.getvalue(
            )
            assert try_push.status != "complete"
示例#11
0
def test_landing_reapply(env, git_gecko, git_wpt, git_wpt_upstream, pull_request, set_pr_status,
                         hg_gecko_upstream, upstream_gecko_commit, upstream_wpt_commit,
                         hg_gecko_try, mock_mach, mock_tasks):
    # Test that we reapply the correct commits when landing patches on upstream
    # First we need to create 3 gecko commits:
    # Two that are landed
    # One that is still a PR
    # Then we create a landing that points at the first gecko commit that is landed
    # upstream. Locally we expect the code to reapply the two other gecko commits, so
    # we should end up with no overall change.

    trypush.Mach = mock_mach

    # Add first gecko change
    test_changes = {"change1": b"CHANGE1\n"}
    rev = upstream_gecko_commit(test_changes=test_changes, bug=1111,
                                message=b"Add change1 file")

    update_repositories(git_gecko, git_wpt, wait_gecko_commit=rev)
    pushed, _, _ = upstream.gecko_push(git_gecko, git_wpt, "autoland", rev,
                                       raise_on_error=True)
    sync_1 = pushed.pop()

    # Update central
    hg_gecko_upstream.bookmark("mozilla/central", "-r", rev)

    # Merge the upstream change
    with SyncLock.for_process(sync_1.process_name) as lock:
        with sync_1.as_mut(lock):
            remote_branch = sync_1.remote_branch
            git_wpt_upstream.git.checkout(remote_branch)
            git_wpt_upstream.git.rebase("master")
            git_wpt_upstream.git.checkout("master")
            git_wpt_upstream.git.merge(remote_branch, ff_only=True)

            sync_1.finish()

    # Add second gecko change
    test_changes = {"change2": b"CHANGE2\n"}
    rev = upstream_gecko_commit(test_changes=test_changes, bug=1112,
                                message=b"Add change2 file")

    update_repositories(git_gecko, git_wpt, wait_gecko_commit=rev)
    pushed, _, _ = upstream.gecko_push(git_gecko, git_wpt, "autoland", rev,
                                       raise_on_error=True)
    sync_2 = pushed.pop()

    hg_gecko_upstream.bookmark("mozilla/central", "-r", rev)

    # Merge the gecko change
    remote_branch = sync_2.remote_branch
    git_wpt_upstream.git.checkout(remote_branch)
    git_wpt_upstream.git.rebase("master")
    git_wpt_upstream.git.checkout("master")
    git_wpt_upstream.git.merge(remote_branch, ff_only=True)

    # Add an upstream commit that has metadata
    pr = pull_request([(b"Upstream change 1", {"upstream1": b"UPSTREAM1\n"})])
    head_rev = pr._commits[0]["sha"]
    downstream.new_wpt_pr(git_gecko, git_wpt, pr)
    downstream_sync = set_pr_status(pr.number, "success")
    git_wpt_upstream.head.commit = head_rev
    git_wpt_upstream.git.reset(hard=True)
    with SyncLock.for_process(downstream_sync.process_name) as downstream_lock:
        with downstream_sync.as_mut(downstream_lock):
            downstream_sync.data["force-metadata-ready"] = True

    # This is the commit we should land to
    landing_rev = git_wpt_upstream.git.rev_parse("HEAD")

    # Add an upstream commit that doesn't have metadata
    pr = pull_request([(b"Upstream change 2", {"upstream2": b"UPSTREAM2\n"})])
    head_rev = pr._commits[0]["sha"]
    downstream.new_wpt_pr(git_gecko, git_wpt, pr)
    downstream_sync = set_pr_status(pr.number, "success")
    git_wpt_upstream.head.commit = head_rev
    git_wpt_upstream.git.reset(hard=True)

    # Add third gecko change
    test_changes = {"change3": b"CHANGE3\n"}
    rev = upstream_gecko_commit(test_changes=test_changes, bug=1113,
                                message=b"Add change3 file")

    update_repositories(git_gecko, git_wpt, wait_gecko_commit=rev)
    pushed, _, _ = upstream.gecko_push(git_gecko, git_wpt, "autoland", rev,
                                       raise_on_error=True)

    # Now start a landing
    tree.is_open = lambda x: True
    sync = landing.update_landing(git_gecko, git_wpt)

    assert sync is not None

    for i in xrange(2):
        with SyncLock.for_process(sync.process_name) as lock:
            try_push = sync.latest_try_push
            with sync.as_mut(lock), try_push.as_mut(lock):
                try_push.taskgroup_id = "abcde" + str(i)
                try_push.download_logs = Mock(return_value=[])
                with patch.object(tc.TaskGroup, "tasks",
                                  property(Mock(return_value=mock_tasks(completed=["foo"])))):
                    landing.try_push_complete(git_gecko, git_wpt, try_push, sync)

    hg_gecko_upstream.update()
    gecko_root = hg_gecko_upstream.root().strip().decode("utf8")
    assert (hg_gecko_upstream
            .log("-l1", "--template={desc|firstline}")
            .strip()
            .endswith(b"[wpt-sync] Update web-platform-tests to %s, a=testonly" %
                      landing_rev.encode("utf8")))
    for file in ["change1", "change2", "change3", "upstream1"]:
        path = os.path.join(gecko_root,
                            env.config["gecko"]["path"]["wpt"],
                            file)
        assert os.path.exists(path)
        with open(path) as f:
            assert f.read() == file.upper() + "\n"
    assert not os.path.exists(os.path.join(gecko_root,
                                           env.config["gecko"]["path"]["wpt"],
                                           "upstream2"))
    sync_point = landing.load_sync_point(git_gecko, git_wpt)
    assert sync_point["upstream"] == landing_rev