Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/taskcluster/gecko_taskgraph/test/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 34 kB image not shown  

Quelle  test_actions.py

  Sprache: Python
 

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.


import pytest
import yaml
from mozunit import main
from pytest_taskgraph import make_graph, make_task
from taskgraph import create
from taskgraph.util import json
from taskgraph.util.taskcluster import _task_definitions_cache

from gecko_taskgraph import decision
from gecko_taskgraph.actions import trigger_action_callback

ROOT_URL = "https://taskcluster.example.com"


@pytest.fixture(autouse=True)
def mock_root_url(monkeypatch):
    monkeypatch.delenv("TASKCLUSTER_PROXY_URL", raising=False)
    monkeypatch.setenv("TASKCLUSTER_ROOT_URL", ROOT_URL)


@pytest.fixture(autouse=True)
def clear_caches():
    yield
    _task_definitions_cache.cache.clear()


@pytest.fixture
def artifact_dir(monkeypatch, tmp_path):
    artifact_dir = tmp_path / "artifacts"
    monkeypatch.setattr(decision, "ARTIFACTS_DIR", str(artifact_dir))
    return artifact_dir


@pytest.fixture
def get_artifact(artifact_dir):
    def inner(artifact_name):
        return json.loads((artifact_dir / artifact_name).read_text())

    return inner


@pytest.fixture
def run_action(mocker, monkeypatch, parameters, graph_config):
    monkeypatch.setattr(create, "testing"True)
    mocker.patch("gecko_taskgraph.actions.registry.sanity_check_task_scope")

    def inner(name, params=None, **kwargs):
        if params:
            parameters.update(params)

        kwargs.setdefault("task_group_id""gid")
        kwargs.setdefault("task_id""tid")
        kwargs.setdefault("input"None)
        ret = trigger_action_callback(
            callback=name,
            parameters=parameters,
            root=graph_config.root_dir,
            **kwargs,
        )
        return ret

    return inner


def test_cancel(responses, run_action):
    task_id = "abc"

    responses.post(f"{ROOT_URL}/api/queue/v1/task/{task_id}/cancel", status=200)

    run_action("cancel", task_id=task_id, input={"task_id": task_id})


def test_cancel_all(monkeypatch, responses, run_action):
    group_id = "abc"

    # Validate action task doesn't cancel itself.
    monkeypatch.setenv("TASK_ID", group_id)

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task-group/{group_id}/list",
        status=200,
        json={
            "tasks": [
                {"status": {"taskId": group_id, "state""running"}},
                {"status": {"taskId""a""state""running"}},
                {"status": {"taskId""b""state""completed"}},
                {"status": {"taskId""c""state""pending"}},
                {"status": {"taskId""d""state""unscheduled"}},
            ]
        },
    )

    responses.post(f"{ROOT_URL}/api/queue/v1/task/a/cancel", status=200)
    responses.post(f"{ROOT_URL}/api/queue/v1/task/c/cancel", status=200)
    responses.post(f"{ROOT_URL}/api/queue/v1/task/d/cancel", status=200)

    run_action(
        "cancel-all",
        task_group_id=group_id,
        input={"task_group_id": group_id},
    )


def test_rebuild_cached_tasks(mocker, run_action, get_artifact):
    graph = make_graph(
        make_task(
            label="foo", attributes={"cached_task"True}, task_def={"name""foo"}
        ),
        make_task(label="bar", task_def={"name""bar"}),
    )
    m = mocker.patch(
        "gecko_taskgraph.actions.rebuild_cached_tasks.fetch_graph_and_labels"
    )
    m.return_value = (
        "gid",
        graph,
        {label: "tid" for label in graph.tasks.keys()},
        None,
    )

    run_action("rebuild-cached-tasks")
    to_run = get_artifact("to-run.json")
    assert "foo" in to_run
    assert "bar" not in to_run


def test_add_new_jobs(mocker, run_action, get_artifact):
    graph = make_graph(
        make_task(label="foo", task_def={"name""foo"}),
        make_task(label="bar", task_def={"name""bar"}),
    )
    m = mocker.patch("gecko_taskgraph.actions.add_new_jobs.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {}, None)

    run_action("add-new-jobs", input={"tasks": ["foo"], "times"1})

    to_run = get_artifact("to-run.json")
    assert "foo" in to_run
    assert "bar" not in to_run


def test_add_talos(mocker, run_action, get_artifact):
    graph = make_graph(
        make_task(
            label="test-linux-talos",
            attributes={"talos_try_name""talos"},
            task_def={"name""test-linux-talos"},
        ),
        make_task(label="build", task_def={"name""build"}),
    )
    m = mocker.patch("gecko_taskgraph.actions.add_talos.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {}, None)
    mocker.patch("gecko_taskgraph.actions.add_talos.standard_filter", return_value=True)

    run_action("run-all-talos", input={"times"1})

    to_run = get_artifact("to-run.json")
    assert "test-linux-talos" in to_run
    assert "build" not in to_run


def test_purge_caches(responses, run_action):
    task_id = "abc"
    task_def = {
        "payload": {"cache": {"cache1""path1"}},
        "provisionerId""proj-gecko",
        "workerType""linux",
    }

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/{task_id}",
        status=200,
        json=task_def,
    )
    responses.post(
        f"{ROOT_URL}/api/purge-cache/v1/purge-cache/proj-gecko%2Flinux",
        status=200,
        json={},
    )

    run_action("purge-cache", task_id=task_id)


def test_openh264(mocker, run_action, get_artifact):
    graph = make_graph(
        make_task(
            label="openh264-build", kind="openh264", task_def={"name""openh264-build"}
        ),
        make_task(label="build", kind="build", task_def={"name""build"}),
    )
    m = mocker.patch("gecko_taskgraph.actions.openh264.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {}, None)

    run_action("openh264")

    to_run = get_artifact("to-run.json")
    assert "openh264-build" in to_run
    assert "build" not in to_run


def test_googleplay(mocker, run_action, get_artifact):
    graph = make_graph(
        make_task(
            label="push-fenix",
            kind="push-bundle",
            attributes={"build-type""fenix-nightly"},
            task_def={"name""push-fenix"},
        ),
        make_task(label="build", kind="build", task_def={"name""build"}),
    )
    m = mocker.patch("gecko_taskgraph.actions.googleplay.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {}, None)

    run_action("googleplay", params={"project""mozilla-central"})

    to_run = get_artifact("to-run.json")
    assert "push-fenix" in to_run
    assert "build" not in to_run


def test_raptor_extra_options(mocker, responses, run_action, get_artifact):
    task_id = "tid"
    task_def = {
        "metadata": {"name""test-raptor"},
        "payload": {"env": {}},
        "extra": {"treeherder": {"symbol""rap""groupName""Raptor"}},
    }
    graph = make_graph(make_task(label="test-raptor", task_def=task_def))

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/{task_id}",
        status=200,
        json=task_def,
    )
    m = mocker.patch(
        "gecko_taskgraph.actions.raptor_extra_options.fetch_graph_and_labels"
    )
    m.return_value = ("gid", graph, {"test-raptor""tid"}, None)

    run_action(
        "raptor-extra-options", task_id=task_id, input={"extra_options""verbose"}
    )

    to_run = get_artifact("to-run.json")
    assert "test-raptor" in to_run


def test_run_missing_tests(mocker, responses, run_action, get_artifact):
    graph = make_graph(
        make_task(label="test-foo", kind="test", task_def={"name""test-foo"}),
        make_task(label="test-bar", kind="test", task_def={"name""test-bar"}),
        make_task(label="build", kind="build", task_def={"name""build"}),
    )
    m = mocker.patch("gecko_taskgraph.actions.run_missing_tests.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {"test-foo""tid1"}, None)

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/gid/artifacts/public%2Ftarget-tasks.json",
        status=303,
        json={"url": f"{ROOT_URL}/artifacts/target-tasks.json"},
    )
    responses.get(
        f"{ROOT_URL}/artifacts/target-tasks.json",
        status=200,
        json={"test-foo": {}, "test-bar": {}},
    )

    run_action("run-missing-tests")

    to_run = get_artifact("to-run.json")
    assert "test-bar" in to_run
    assert "test-foo" not in to_run
    assert "build" not in to_run


def test_scriptworker_canary(mocker, run_action, graph_config):
    m = mocker.patch("gecko_taskgraph.actions.scriptworker_canary.taskgraph_decision")

    run_action("scriptworker-canary", input={"scriptworkers": ["balrog""shipit"]})

    m.assert_called_once()
    args, kwargs = m.call_args
    assert args[0] == {"root": graph_config.root_dir}
    assert kwargs["parameters"]["target_tasks_method"] == "scriptworker_canary"
    assert kwargs["parameters"]["try_task_config"] == {
        "scriptworker-canary-workers": ["balrog""shipit"]
    }
    assert kwargs["parameters"]["tasks_for"] == "action"


def test_merge_automation(mocker, run_action, graph_config):
    m = mocker.patch("gecko_taskgraph.actions.merge_automation.taskgraph_decision")

    run_action(
        "merge-automation",
        params={"project""mozilla-central"},
        input={"behavior""bump-main""merge-automation-id"123},
    )

    m.assert_called_once()
    args, kwargs = m.call_args
    assert args[0] == {"root": graph_config.root_dir}
    assert kwargs["parameters"]["target_tasks_method"] == "merge_automation"
    assert kwargs["parameters"]["merge_config"] == {
        "force-dry-run"False,
        "behavior""bump-main",
        "merge-automation-id"123,
    }
    assert kwargs["parameters"]["tasks_for"] == "action"


def test_retrigger(mocker, responses, run_action, get_artifact):
    task_def = {
        "metadata": {"name""test-task"},
        "payload": {},
    }
    graph = make_graph(
        make_task(label="test-task", attributes={"retrigger"True}, task_def=task_def)
    )

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/tid",
        status=200,
        json=task_def,
    )
    m = mocker.patch("gecko_taskgraph.actions.retrigger.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {}, None)

    run_action("retrigger", input={"force"True})

    to_run = get_artifact("to-run.json")
    assert "test-task" in to_run


def test_retrigger_custom(mocker, responses, run_action, capsys):
    task_def = {
        "metadata": {"name""test-mochitest"},
        "payload": {"command": ["run"], "env": {}},
        "tags": {"test-type""mochitest"},
        "extra": {"treeherder": {"symbol""M"}},
    }
    graph = make_graph(make_task(label="test-mochitest", task_def=task_def))

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/tid",
        status=200,
        json=task_def,
    )
    m = mocker.patch("gecko_taskgraph.actions.retrigger_custom.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {"test-mochitest""dtid"}, None)

    run_action("retrigger-custom", input={"path""test/path"})

    captured = capsys.readouterr()
    assert "test-mochitest" in captured.out
    assert "--no-run-tests" in captured.out
    assert "test/path" in captured.out
    assert "M-custom" in captured.out


def test_create_interactive(mocker, responses, monkeypatch, run_action, get_artifact):
    monkeypatch.setenv("TASK_ID""action-task-id")
    task_def = {
        "metadata": {"name""test-task"},
        "payload": {
            "env": {},
            "maxRunTime"3600,
            "cache": {},
            "artifacts": {},
        },
        "scopes": [],
        "extra": {"treeherder": {"symbol""T"}},
    }
    graph = make_graph(make_task(label="test-task", task_def=task_def))

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/tid",
        status=200,
        json=task_def,
    )
    m = mocker.patch(
        "gecko_taskgraph.actions.create_interactive.fetch_graph_and_labels"
    )
    m.return_value = ("gid", graph, {}, None)

    run_action("create-interactive", input={"notify""test@example.com"})

    to_run = get_artifact("to-run.json")
    assert "test-task" in to_run


def test_backfill_task(mocker, run_action, get_artifact):
    graph = make_graph(
        make_task(label="test-task", task_def={"name""test-task"}),
    )
    m = mocker.patch("gecko_taskgraph.actions.backfill.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {}, None)
    mocker.patch("gecko_taskgraph.actions.backfill.combine_task_graph_files")

    run_action(
        "backfill-task",
        input={"label""test-task""revision""abc123""symbol""T"},
    )

    to_run = get_artifact("to-run-0.json")
    assert "test-task" in to_run


def test_backfill_task_chunk_not_found(mocker, run_action, get_artifact):
    """When the original chunk doesn't exist in the target push, the backfill
    should still apply the original manifests via MOZHARNESS_TEST_PATHS."""
    task_def = {
        "name""test-linux-wpt-1",
        "payload": {"env": {}},
        "metadata": {"name""test-linux-wpt-1"},
        "extra": {"treeherder": {"symbol""wpt1""groupSymbol""W"}},
        "tags": {},
    }
    graph = make_graph(
        make_task(label="test-linux-wpt-1", task_def=task_def),
    )
    m = mocker.patch("gecko_taskgraph.actions.backfill.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {}, None)
    mocker.patch("gecko_taskgraph.actions.backfill.combine_task_graph_files")

    original_manifests = {"web-platform-tests": ["/css/test1.html""/dom/test2.html"]}
    run_action(
        "backfill-task",
        input={
            "label""test-linux-wpt-9",
            "revision""abc123",
            "symbol""wpt9",
            "test_manifests": original_manifests,
        },
    )

    to_run = get_artifact("to-run-0.json")
    assert "test-linux-wpt-1" in to_run

    task_graph = get_artifact("task-graph-0.json")
    task_data = list(task_graph.values())[0]
    task_def = task_data.get("task", task_data)
    assert task_def["payload"]["env"]["MOZHARNESS_TEST_PATHS"] == json.dumps(
        original_manifests
    )
    assert task_def["metadata"]["name"] == "test-linux-wpt-9"
    assert task_def["extra"]["treeherder"]["symbol"] == "wpt9-abc123-bk"


def test_confirm_failures(mocker, responses, run_action, get_artifact):
    task_id = "test-task-id"
    task_def = {
        "metadata": {"name""test-mochitest"},
        "extra": {"suite""mochitest"},
        "payload": {"command": ["run-tests"], "env": {}},
    }
    graph = make_graph(
        make_task(
            label="test-mochitest-cf",
            task_def={
                "name""test-mochitest-cf",
                "payload": {"command": ["run-tests"], "env": {}},
                "metadata": {"name""test-mochitest-cf"},
                "tags": {},
            },
        ),
    )

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/{task_id}/artifacts",
        status=200,
        json={
            "artifacts": [
                {"name""public/logs/live_backing.log"},
                {"name""public/logs/errorsummary.log"},
            ]
        },
    )

    errorsummary_content = b"\n".join([
        b'{"test": "dom/tests/test_example.html", "status": "FAIL", "expected": "PASS", "group": "dom/tests"}',
        b'{"test": "dom/tests/test_another.html", "status": "FAIL", "expected": "PASS", "group": "dom/tests"}',
    ])
    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/{task_id}/artifacts/public%2Flogs%2Ferrorsummary.log",
        status=303,
        json={"url": f"{ROOT_URL}/artifacts/errorsummary.log"},
    )
    responses.get(
        f"{ROOT_URL}/artifacts/errorsummary.log",
        status=200,
        body=errorsummary_content,
    )

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/{task_id}",
        status=200,
        json=task_def,
    )
    m = mocker.patch("gecko_taskgraph.actions.confirm_failure.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {}, None)

    run_action("confirm-failures", task_id=task_id)

    to_run = get_artifact("to-run.json")
    assert "test-mochitest-cf" in to_run


def test_confirm_failures_retrigger(mocker, responses, run_action):
    task_id = "test-task-id"
    task_def = {
        "metadata": {"name""test-mochitest"},
        "extra": {"suite""mochitest"},
    }
    graph = make_graph(
        make_task(
            label="test-mochitest",
            attributes={"retrigger"True},
            task_def={"name""test-mochitest"},
        ),
        make_task(label="test-mochitest-cf", task_def={"name""test-mochitest-cf"}),
    )

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/{task_id}/artifacts",
        status=200,
        json={"artifacts": [{"name""public/logs/live_backing.log"}]},
    )

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/{task_id}",
        status=200,
        json=task_def,
    )
    m = mocker.patch("gecko_taskgraph.actions.confirm_failure.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {}, None)
    retrigger_mock = mocker.patch(
        "gecko_taskgraph.actions.confirm_failure.retrigger_action"
    )

    run_action("confirm-failures", task_id=task_id)

    retrigger_mock.assert_called_once()


def test_rerun(mocker, responses, run_action):
    task_id = "tid"
    task_def = {"metadata": {"name""test-task"}}

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/{task_id}",
        status=200,
        json=task_def,
    )
    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/{task_id}/status",
        status=200,
        json={"status": {"state""failed"}},
    )
    responses.post(f"{ROOT_URL}/api/queue/v1/task/{task_id}/rerun", status=200)

    graph = make_graph(make_task(label="test-task", task_def=task_def))
    m = mocker.patch("gecko_taskgraph.actions.retrigger.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {"test-task": [task_id]}, {"test-task": [task_id]})

    run_action("rerun", task_id=task_id)


def test_retrigger_decision(responses, run_action, capsys):
    task_def = {
        "taskGroupId""tgid",
        "schedulerId""scheduler",
        "provisionerId""provisioner",
        "workerType""worker",
        "created""2024-01-01T00:00:00.000Z",
        "deadline""2024-01-01T01:00:00.000Z",
        "expires""2024-01-02T00:00:00.000Z",
        "metadata": {"name""decision-task"},
        "payload": {},
        "tags": {},
        "extra": {},
    }

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/tid",
        status=200,
        json=task_def,
    )

    run_action("retrigger-decision", params={"level""1"})

    captured = capsys.readouterr()
    assert "decision-task" in captured.out
    assert "gecko-level-1" in captured.out
    assert "retrigger-decision-task" in captured.out


def test_retrigger_multiple(mocker, run_action, get_artifact):
    graph = make_graph(
        make_task(
            label="test-task",
            attributes={"retrigger"True},
            task_def={"name""test-task"},
        ),
    )

    m = mocker.patch("gecko_taskgraph.actions.retrigger.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {}, {"test-task": ["tid"]})

    run_action(
        "retrigger-multiple",
        input={"requests": [{"tasks": ["test-task"], "times"2}]},
    )

    to_run = get_artifact("to-run.json")
    assert "test-task" in to_run


def test_retrigger_multiple_rerun(mocker, responses, run_action):
    task_id = "rerun-task-id"
    graph = make_graph(
        make_task(
            label="test-task",
            attributes={"retrigger"False},
            task_def={"name""test-task"},
        ),
    )

    m = mocker.patch("gecko_taskgraph.actions.retrigger.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {}, {"test-task": [task_id]})

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/{task_id}/status",
        status=200,
        json={"status": {"state""failed"}},
    )
    responses.post(f"{ROOT_URL}/api/queue/v1/task/{task_id}/rerun", status=200)

    run_action(
        "retrigger-multiple",
        input={"requests": [{"tasks": ["test-task"], "times"2}]},
    )


def test_add_all_browsertime(mocker, run_action, get_artifact):
    graph = make_graph(
        make_task(
            label="raptor-browsertime",
            kind="test",
            attributes={
                "raptor_try_name""browsertime-firefox",
                "test_platform""linux64-shippable-qr/opt",
                "run_on_projects": ["mozilla-central"],
            },
            task_def={"name""raptor-browsertime""extra": {"suite""raptor"}},
        ),
        make_task(label="build", kind="build", task_def={"name""build"}),
    )

    m = mocker.patch("gecko_taskgraph.actions.backfill.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {}, None)

    run_action("add-all-browsertime", params={"project""mozilla-central"})

    to_run = get_artifact("to-run.json")
    assert "raptor-browsertime" in to_run
    assert "build" not in to_run


def test_gecko_profile(mocker, responses, run_action, get_artifact):
    task_id = "tid"
    task_def = {
        "metadata": {"name""test-raptor"},
        "payload": {
            "command": [["run-tests"]],
            "env": {"MOZ_FETCHES": {"task-reference""[]"}},
        },
        "extra": {
            "suite""raptor",
            "treeherder": {"symbol""R""groupName""Raptor"},
        },
    }
    graph = make_graph(
        make_task(
            label="test-raptor",
            kind="test",
            attributes={"unittest_suite""raptor"},
            task_def={
                "name""test-raptor",
                "deadline""",
                "payload": {
                    "command": [["run-tests"]],
                    "env": {"MOZ_FETCHES": {"task-reference""[]"}},
                },
                "extra": {
                    "suite""raptor",
                    "treeherder": {"symbol""R""groupName""Raptor"},
                },
            },
        ),
        make_task(
            label="toolchain-linux64-samply",
            kind="toolchain",
            task_def={"name""toolchain-linux64-samply"},
        ),
        make_task(
            label="toolchain-profiler-node-tools",
            kind="toolchain",
            task_def={"name""toolchain-profiler-node-tools"},
        ),
        make_task(
            label="toolchain-linux64-node-22",
            kind="toolchain",
            task_def={"name""toolchain-linux64-node-22"},
        ),
    )

    responses.get(
        "http://hg.example.com/json-pushes?version=2&startID=99&endID=100",
        status=200,
        json={"pushes": {"100": {"changesets": ["abc123"]}}},
    )

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/{task_id}",
        status=200,
        json=task_def,
    )

    responses.get(
        f"{ROOT_URL}/api/index/v1/task/gecko.v2.some-project.pushlog-id.100.decision/artifacts/public%2Fparameters.yml",
        status=303,
        headers={"Location": f"{ROOT_URL}/artifacts/gecko-profile-params.yml"},
    )
    responses.get(
        f"{ROOT_URL}/artifacts/gecko-profile-params.yml",
        status=200,
        body=yaml.dump({"pushlog_id""100""project""autoland""level""1"}),
        content_type="application/x-yaml",
    )
    m = mocker.patch("gecko_taskgraph.actions.gecko_profile.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {"test-raptor""tid"}, None)
    mocker.patch("gecko_taskgraph.actions.gecko_profile.combine_task_graph_files")

    run_action(
        "geckoprofile",
        task_id=task_id,
        params={"pushlog_id""100""head_repository""http://hg.example.com"},
        input={"depth"1"gecko_profile_interval"5},
    )

    to_run = get_artifact("to-run-100.json")
    assert "test-raptor" in to_run


def test_side_by_side(mocker, responses, run_action, get_artifact):
    task_id = "tid"
    task_def = {
        "metadata": {"name""linux/opt-browsertime-tp6"},
        "extra": {"treeherder": {"symbol""tp6"}},
        "payload": {"command": [["run"], ["perf-test {test_name}"]]},
    }
    graph = make_graph(
        make_task(
            label="perftest-linux-side-by-side",
            task_def={
                "name""perftest-linux-side-by-side",
                "payload": {"command": [["run"], ["perf-test {test_name}"]]},
                "extra": {"treeherder": {"symbol""sxs"}},
                "metadata": {"name""perftest-linux-side-by-side"},
            },
        )
    )

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/{task_id}",
        status=200,
        json=task_def,
    )
    m = mocker.patch("gecko_taskgraph.actions.side_by_side.fetch_graph_and_labels")
    m.return_value = ("gid", graph, {}, None)

    run_action(
        "side-by-side",
        task_id=task_id,
        params={"head_rev""newrev123""pushlog_id""100"},
        input={"revision""baserev456""project""autoland"},
    )

    to_run = get_artifact("to-run.json")
    assert "perftest-linux-side-by-side" in to_run


def test_release_promotion(
    mocker, monkeypatch, responses, run_action, parameters, graph_config
):
    m = mocker.patch("gecko_taskgraph.actions.release_promotion.taskgraph_decision")

    action_task_id = "action-task-id"
    monkeypatch.setenv("TASK_ID", action_task_id)

    responses.get(
        f"{ROOT_URL}/api/index/v1/task/gecko.v2.try.revision.abcdef.taskgraph.decision",
        status=200,
        json={"taskId""decision-task-id"},
    )

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/decision-task-id/artifacts/public%2Fparameters.yml",
        status=303,
        json={"url": f"{ROOT_URL}/artifacts/decision-parameters.yml"},
    )
    responses.get(
        f"{ROOT_URL}/artifacts/decision-parameters.yml",
        status=200,
        body=yaml.dump({
            "base_repository""http://hg.example.com",
            "head_repository""http://hg.example.com",
            "head_rev""abcdef",
            "project""try",
            "level""1",
            "pushlog_id""100",
            "release_product""firefox",
            "release_type""nightly",
        }),
        content_type="application/x-yaml",
    )
    responses.get(
        f"{ROOT_URL}/api/queue/v1/task/decision-task-id/artifacts/public%2Ffull-task-graph.json",
        status=303,
        json={"url": f"{ROOT_URL}/artifacts/full-task-graph.json"},
    )
    responses.get(
        f"{ROOT_URL}/artifacts/full-task-graph.json",
        status=200,
        json={},
    )

    responses.get(
        f"{ROOT_URL}/api/queue/v1/task-group/{action_task_id}/list",
        status=200,
        json={
            "tasks": [
                {"status": {"taskId": action_task_id, "state""running"}},
            ]
        },
    )

    mocker.patch(
        "gecko_taskgraph.actions.release_promotion.find_existing_tasks_from_previous_kinds",
        return_value={},
    )

    run_action(
        "release-promotion",
        params={
            "project""try",
            "level""1",
        },
        input={
            "release_promotion_flavor""promote_firefox",
            "build_number"1,
            "version""",
            "partial_updates": {},
            "release_enable_partner_repack"False,
            "release_enable_partner_attribution"False,
            "release_enable_emefree"False,
        },
    )

    m.assert_called_once()
    args, kwargs = m.call_args
    assert args[0] == {"root": graph_config.root_dir}
    assert kwargs["parameters"]["target_tasks_method"] == "promote_desktop"


def test_backfill_standard(mocker, run_action):
    task_id = "tid"
    task_def = {
        "metadata": {"name""raptor-browsertime-firefox-tp6"},
        "payload": {"env": {}},
        "extra": {"treeherder": {"symbol""tp6"}},
    }
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_task_definition",
        return_value=task_def,
    )

    pushes = ["200""201""202"]
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_pushes_from_params_input",
        return_value=pushes,
    )
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_decision_task_id",
        side_effect=lambda project, push_id: f"decision-{push_id}",
    )
    trigger_mock = mocker.patch("gecko_taskgraph.actions.backfill.trigger_action")

    run_action(
        "backfill",
        task_id=task_id,
        input={"depth"25"retrigger"False},
    )

    trigger_mock.assert_has_calls(
        [
            mocker.call(
                action_name="backfill-task",
                decision_task_id="decision-200",
                input=mocker.ANY,
            ),
            mocker.call(
                action_name="backfill-task",
                decision_task_id="decision-201",
                input=mocker.ANY,
            ),
            mocker.call(
                action_name="backfill-task",
                decision_task_id="decision-202",
                input=mocker.ANY,
            ),
        ],
        any_order=False,
    )
    assert trigger_mock.call_count == 3


def test_backfill_sliced(mocker, run_action):
    task_id = "tid"
    label = "raptor-browsertime-firefox-tp6"
    task_def = {
        "metadata": {"name": label},
        "payload": {"env": {}},
        "extra": {"treeherder": {"symbol""tp6"}},
    }
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_task_definition",
        return_value=task_def,
    )

    pushes = [str(i) for i in range(100125)]
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_pushes_in_gap",
        return_value=pushes,
    )
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_decision_task_id",
        side_effect=lambda project, push_id: f"decision-{push_id}",
    )
    trigger_mock = mocker.patch("gecko_taskgraph.actions.backfill.trigger_action")

    run_action(
        "backfill",
        task_id=task_id,
        input={"depth"25"retrigger"False"slices"3},
    )

    # slices=3 triggers only the 3 exact pivot pushes: n/4, 2n/4, 3n/4
    # n=25, so pivot indices are 6, 12, 18 -> push IDs 106, 112, 118
    assert trigger_mock.call_count == 3
    called_pids = []
    for call in trigger_mock.call_args_list:
        kwargs = call.kwargs
        assert kwargs["action_name"] == "backfill-task"
        decision = kwargs["decision_task_id"]  # decision-<pid>
        called_pids.append(decision.split("-")[1])

    # ensure no duplicate pushes are triggered
    assert len(called_pids) == len(set(called_pids))
    assert set(called_pids) == {"106""112""118"}


def test_backfill_sliced_small_gap_falls_back_to_standard(mocker, run_action):
    task_id = "tid"
    label = "raptor-browsertime-firefox-tp6"
    task_def = {
        "metadata": {"name": label},
        "payload": {"env": {}},
        "extra": {"treeherder": {"symbol""tp6"}},
    }
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_task_definition",
        return_value=task_def,
    )

    # gap=6 (< 7) should trigger all 6 pushes via standard mode
    pushes = [str(i) for i in range(100106)]
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_pushes_in_gap",
        return_value=pushes,
    )
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_decision_task_id",
        side_effect=lambda project, push_id: f"decision-{push_id}",
    )
    trigger_mock = mocker.patch("gecko_taskgraph.actions.backfill.trigger_action")

    run_action(
        "backfill",
        task_id=task_id,
        input={"depth"25"retrigger"False"slices"3},
    )

    # standard mode should be triggered for all gap 6 pushes
    assert trigger_mock.call_count == 6
    called_pids = []
    for call in trigger_mock.call_args_list:
        kwargs = call.kwargs
        assert kwargs["action_name"] == "backfill-task"
        decision = kwargs["decision_task_id"]  # decision-<pid>
        called_pids.append(decision.split("-")[1])

    # ensure no duplicate pushes are triggered
    assert len(called_pids) == len(set(called_pids))
    assert set(called_pids) == {str(i) for i in range(100106)}


def test_backfill_sliced_empty_gap(mocker, run_action):
    task_id = "tid"
    label = "raptor-browsertime-firefox-tp6"
    task_def = {
        "metadata": {"name": label},
        "payload": {"env": {}},
        "extra": {"treeherder": {"symbol""tp6"}},
    }
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_task_definition",
        return_value=task_def,
    )

    # no missing pushes found
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_pushes_in_gap",
        return_value=[],
    )
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_decision_task_id",
        side_effect=lambda project, push_id: f"decision-{push_id}",
    )
    trigger_mock = mocker.patch("gecko_taskgraph.actions.backfill.trigger_action")

    run_action(
        "backfill",
        task_id=task_id,
        input={"depth"25"retrigger"False"slices"3},
    )

    # No pushes should be triggered gap is 0 (no missing pushes found)
    assert trigger_mock.call_count == 0


def test_backfill_sliced_boundary_gap(mocker, run_action):
    task_id = "tid"
    label = "raptor-browsertime-firefox-tp6"
    task_def = {
        "metadata": {"name": label},
        "payload": {"env": {}},
        "extra": {"treeherder": {"symbol""tp6"}},
    }
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_task_definition",
        return_value=task_def,
    )

    # gap=7 (>= 7) should use sliced mode
    pushes = [str(i) for i in range(100107)]
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_pushes_in_gap",
        return_value=pushes,
    )
    mocker.patch(
        "gecko_taskgraph.actions.backfill.get_decision_task_id",
        side_effect=lambda project, push_id: f"decision-{push_id}",
    )
    trigger_mock = mocker.patch("gecko_taskgraph.actions.backfill.trigger_action")

    run_action(
        "backfill",
        task_id=task_id,
        input={"depth"25"retrigger"False"slices"3},
    )

    # slices=3 triggers only the 3 exact pivot pushes: n/4, 2n/4, 3n/4
    # n=7, so pivot indices are 1, 3, 5 -> push IDs 101, 103, 105
    assert trigger_mock.call_count == 3
    called_pids = []
    for call in trigger_mock.call_args_list:
        kwargs = call.kwargs
        assert kwargs["action_name"] == "backfill-task"
        decision = kwargs["decision_task_id"]  # decision-<pid>
        called_pids.append(decision.split("-")[1])

    # ensure no duplicate pushes are triggered
    assert len(called_pids) == len(set(called_pids))
    assert set(called_pids) == {"101""103""105"}


if __name__ == "__main__":
    main()

Messung V0.5 in Prozent
C=93 H=91 G=91

¤ Dauer der Verarbeitung: 0.24 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.