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

Quelle  raptor.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/.


from typing import Optional

from taskgraph.transforms.base import TransformSequence
from taskgraph.util.copy import deepcopy
from taskgraph.util.schema import Schema, optionally_keyed_by, resolve_keyed_by
from taskgraph.util.treeherder import join_symbol, split_symbol

from gecko_taskgraph.transforms.test import TestDescriptionSchema
from gecko_taskgraph.util.perftest import is_external_browser

transforms = TransformSequence()
task_transforms = TransformSequence()

SP3_CRITICAL_TESTS = [
    "test-windows11-64-24h2-shippable/opt-browsertime-benchmark-firefox-speedometer3",
    "test-linux2404-64-shippable/opt-browsertime-benchmark-firefox-speedometer3",
    "test-macosx1500-aarch64-shippable/opt-browsertime-benchmark-firefox-speedometer3",
    "test-android-hw-a55-14-0-aarch64-shippable/opt-browsertime-benchmark-speedometer3-mobile-fenix",
]


class RaptorSchema(Schema, kw_only=True):
    activity: Optional[optionally_keyed_by("app", str, use_msgspec=True)] = None  # type: ignore
    apps: Optional[  # type: ignore
        optionally_keyed_by("test-platform""subtest", list[str], use_msgspec=True)
    ] = None
    binary_path: Optional[optionally_keyed_by("app", str, use_msgspec=True)] = None  # type: ignore
    run_visual_metrics: Optional[  # type: ignore
        optionally_keyed_by("app""test-platform", bool, use_msgspec=True)
    ] = None
    subtests: Optional[  # type: ignore
        optionally_keyed_by(
            "app""test-platform""variant", list[object], use_msgspec=True
        )
    ] = None
    test: Optional[str] = None
    test_url_param: Optional[  # type: ignore
        optionally_keyed_by("subtest""test-platform", str, use_msgspec=True)
    ] = None
    lull_schedule: Optional[  # type: ignore
        optionally_keyed_by("subtest""test-platform", str, use_msgspec=True)
    ] = None
    network_conditions: Optional[  # type: ignore
        optionally_keyed_by("subtest", list[object], use_msgspec=True)
    ] = None


class RaptorDescriptionSchema(Schema, forbid_unknown_fields=False, kw_only=True):
    # Raptor specific configs.
    raptor: Optional[RaptorSchema] = None
    # Configs defined in the 'test_description_schema'.
    max_run_time: Optional[  # type: ignore
        optionally_keyed_by(
            "app",
            "subtest",
            "test-platform",
            TestDescriptionSchema.__annotations__["max_run_time"],
            use_msgspec=True,
        )
    ] = None
    run_on_projects: Optional[  # type: ignore
        optionally_keyed_by(
            "app",
            "test-name",
            "raptor.test",
            "subtest",
            "variant",
            TestDescriptionSchema.__annotations__["run_on_projects"],
            use_msgspec=True,
        )
    ] = None
    variants: TestDescriptionSchema.__annotations__["variants"] = None
    target: Optional[  # type: ignore
        optionally_keyed_by(
            "app", TestDescriptionSchema.__annotations__["target"], use_msgspec=True
        )
    ] = None
    tier: Optional[  # type: ignore
        optionally_keyed_by(
            "app",
            "raptor.test",
            "subtest",
            "variant",
            TestDescriptionSchema.__annotations__["tier"],
            use_msgspec=True,
        )
    ] = None
    test_name: TestDescriptionSchema.__annotations__["test_name"]  # noqa: F821
    test_platform: TestDescriptionSchema.__annotations__["test_platform"]  # noqa: F821
    require_signed_extensions: TestDescriptionSchema.__annotations__[
        "require_signed_extensions"  # noqa: F821
    ]
    treeherder_symbol: TestDescriptionSchema.__annotations__["treeherder_symbol"]  # noqa: F821


transforms.add_validate(RaptorDescriptionSchema)


@transforms.add
def set_defaults(config, tests):
    for test in tests:
        test.setdefault("raptor", {}).setdefault("run-visual-metrics"False)
        yield test


@transforms.add
def split_apps(config, tests):
    app_symbols = {
        "chrome""ChR",
        "chrome-m""ChR",
        "fenix""fenix",
        "refbrow""refbrow",
        "safari""Saf",
        "safari-tp""STP",
        "custom-car""CaR",
        "cstm-car-m""CaR",
    }

    for test in tests:
        apps = test["raptor"].pop("apps"None)
        if not apps:
            yield test
            continue

        for app in apps:
            # Ignore variants for non-Firefox or non-mobile applications.
            if app not in [
                "firefox",
                "geckoview",
                "fenix",
                "chrome-m",
                "cstm-car-m",
            ] and test["attributes"].get("unittest_variant"):
                continue

            atest = deepcopy(test)
            suffix = f"-{app}"
            atest["app"] = app
            atest["description"] += f" on {app.capitalize()}"

            name = atest["test-name"] + suffix
            atest["test-name"] = name
            atest["try-name"] = name

            if app in app_symbols:
                group, symbol = split_symbol(atest["treeherder-symbol"])
                group += f"-{app_symbols[app]}"
                atest["treeherder-symbol"] = join_symbol(group, symbol)

            yield atest


@transforms.add
def handle_keyed_by_prereqs(config, tests):
    """
    Only resolve keys for prerequisite fields here since the
    these keyed-by options might have keyed-by fields
    as well.
    """
    for test in tests:
        resolve_keyed_by(
            test,
            "raptor.subtests",
            item_name=test["test-name"],
            variant=test["attributes"].get("unittest_variant"),
        )
        yield test


@transforms.add
def split_raptor_subtests(config, tests):
    for test in tests:
        # For tests that have 'subtests' listed, we want to create a separate
        # test job for every subtest (i.e. split out each page-load URL into its own job)
        subtests = test["raptor"].pop("subtests"None)
        if not subtests:
            if all(
                p not in test["test-platform"for p in ("macosx1400""macosx1500")
            ):
                yield test
            continue

        for chunk_number, subtest in enumerate(subtests):
            # Create new test job
            chunked = deepcopy(test)
            chunked["chunk-number"] = 1 + chunk_number
            chunked["subtest"] = subtest
            chunked["subtest-symbol"] = subtest
            if isinstance(chunked["subtest"], list):
                chunked["subtest"] = subtest[0]
                chunked["subtest-symbol"] = subtest[1]
            chunked = resolve_keyed_by(
                chunked, "tier", chunked["subtest"], defer=["variant"]
            )
            yield chunked


@transforms.add
def handle_keyed_by(config, tests):
    fields = [
        "raptor.test-url-param",
        "raptor.run-visual-metrics",
        "raptor.activity",
        "raptor.binary-path",
        "raptor.lull-schedule",
        "raptor.network-conditions",
        "limit-platforms",
        "fetches.fetch",
        "max-run-time",
        "run-on-projects",
        "target",
        "tier",
        "mozharness.extra-options",
    ]
    for test in tests:
        for field in fields:
            resolve_keyed_by(
                test, field, item_name=test["test-name"], defer=["variant"]
            )
        yield test


@transforms.add
def handle_network_conditions(config, tests):
    for test in tests:
        conditions = test["raptor"].pop("network-conditions"None)
        if not conditions:
            yield test
            continue

        for condition in conditions:
            new_test = deepcopy(test)
            network_type, packet_loss_rate = condition

            new_test.pop("chunk-number")
            subtest = new_test.pop("subtest")
            new_test["raptor"]["test"] = subtest

            group, _ = split_symbol(new_test["treeherder-symbol"])
            new_group = f"{group}-{network_type}"
            subtest_symbol = f"{new_test['subtest-symbol']}-{packet_loss_rate}"
            new_test["treeherder-symbol"] = join_symbol(new_group, subtest_symbol)

            mozharness = new_test.setdefault("mozharness", {})
            extra_options = mozharness.setdefault("extra-options", [])

            extra_options.extend([
                f"--browsertime-arg=network_type={network_type}",
                f"--browsertime-arg=pkt_loss_rate={packet_loss_rate}",
            ])

            new_test["test-name"] += f"-{subtest}-{network_type}-{packet_loss_rate}"
            new_test["try-name"] += f"-{subtest}-{network_type}-{packet_loss_rate}"
            new_test["description"] += (
                f" on {subtest} with {network_type} network type and "
                f" {packet_loss_rate} loss rate"
            )

            yield new_test

        yield test


@transforms.add
def split_page_load_by_url(config, tests):
    for test in tests:
        # `chunk-number` and 'subtest' only exists when the task had a
        # definition for `subtests`
        chunk_number = test.pop("chunk-number"None)
        subtest = test.get(
            "subtest"
        )  # don't pop as some tasks need this value after splitting variants
        subtest_symbol = test.pop("subtest-symbol"None)

        if not chunk_number or not subtest:
            yield test
            continue

        if len(subtest_symbol) > 10 and "ytp" not in subtest_symbol:
            raise Exception(
                "Treeherder symbol %s is larger than 10 char! Please use a different symbol."
                % subtest_symbol
            )

        if test["test-name"].startswith("browsertime-"):
            test["raptor"]["test"] = subtest

            # Remove youtube-playback in the test name to avoid duplication
            test["test-name"] = test["test-name"].replace("youtube-playback-""")
        else:
            # Use full test name if running on webextension
            test["raptor"]["test"] = "raptor-tp6-" + subtest + "-{}".format(test["app"])

        # Only run the subtest/single URL
        test["test-name"] += f"-{subtest}"
        test["try-name"] += f"-{subtest}"

        # Set treeherder symbol and description
        group, _ = split_symbol(test["treeherder-symbol"])
        test["treeherder-symbol"] = join_symbol(group, subtest_symbol)
        test["description"] += f" on {subtest}"

        yield test


@transforms.add
def modify_extra_options(config, tests):
    for test in tests:
        test_name = test.get("test-name"None)

        if "first-install" in test_name:
            # First-install tests should never use conditioned profiles
            extra_options = test.setdefault("mozharness", {}).setdefault(
                "extra-options", []
            )

            for i, opt in enumerate(extra_options):
                if "conditioned-profile" in opt:
                    if i:
                        extra_options.pop(i)
                    break

        if "-widevine" in test_name:
            extra_options = test.setdefault("mozharness", {}).setdefault(
                "extra-options", []
            )
            for i, opt in enumerate(extra_options):
                if "--conditioned-profile=settled" in opt:
                    if i:
                        extra_options[i] += "-youtube"
                    break

        if "unity-webgl" in test_name:
            # Disable the extra-profiler-run for unity-webgl tests.
            extra_options = test.setdefault("mozharness", {}).setdefault(
                "extra-options", []
            )
            for i, opt in enumerate(extra_options):
                if "extra-profiler-run" in opt:
                    if i:
                        extra_options.pop(i)
                    break

        if "jetstream" in test_name and test.get("app"""in ("chrome""custom-car"):
            # Bug 1996836 - Disable jetstream 2/3 extra profile runs
            extra_options = test.setdefault("mozharness", {}).setdefault(
                "extra-options", []
            )
            for i, opt in enumerate(extra_options):
                if "extra-profiler-run" in opt:
                    extra_options.pop(i)
                    break

        yield test


@transforms.add
def add_extra_options(config, tests):
    for test in tests:
        mozharness = test.setdefault("mozharness", {})
        if test.get("app""") == "chrome-m":
            mozharness["tooltool-downloads"] = "internal"

        extra_options = mozharness.setdefault("extra-options", [])

        # Adding device name if we're on android
        test_platform = test["test-platform"]
        if test_platform.startswith("android-hw-a55"):
            extra_options.append("--device-name=a55")
        elif test_platform.startswith("android-hw-p6"):
            extra_options.append("--device-name=p6_aarch64")
        elif test_platform.startswith("android-hw-s24"):
            extra_options.append("--device-name=s24_aarch64")

        if test["raptor"].pop("run-visual-metrics"False):
            extra_options.append("--browsertime-video")
            extra_options.append("--browsertime-visualmetrics")
            test["attributes"]["run-visual-metrics"] = True

        if "app" in test:
            extra_options.append(
                "--app={}".format(test["app"])
            )  # don't pop as some tasks need this value after splitting variants

        if "activity" in test["raptor"]:
            extra_options.append("--activity={}".format(test["raptor"].pop("activity")))

        if "binary-path" in test["raptor"]:
            extra_options.append(
                "--binary-path={}".format(test["raptor"].pop("binary-path"))
            )

        if "test" in test["raptor"]:
            extra_options.append("--test={}".format(test["raptor"].pop("test")))

        if test["require-signed-extensions"]:
            extra_options.append("--is-release-build")

        if "test-url-param" in test["raptor"]:
            param = test["raptor"].pop("test-url-param")
            if not param == []:
                extra_options.append(
                    "--test-url-params={}".format(param.replace(" """))
                )

        if (
            ("android-hw-p6" in test_platform or "android-hw-s24" in test_platform)
            and "speedometer2-" not in test["test-name"]
            # Bug 1943674 resolve why --power-test causes permafails on certain mobile platforms and browsers
        ):
            # Bug 2037511 Temporarily disable power-test option for tp6m on a55s
            if "--power-test" not in extra_options:
                extra_options.append("--power-test")
        elif "windows" in test_platform and any(
            t in test["test-name"for t in ("speedometer3""tp6")
        ):
            extra_options.append("--power-test")

        extra_options.append("--project={}".format(config.params.get("project")))

        yield test


@transforms.add
def modify_mozharness_configs(config, tests):
    for test in tests:
        if not is_external_browser(test["app"]):
            yield test
            continue

        test_platform = test["test-platform"]
        mozharness = test.setdefault("mozharness", {})
        if "mac" in test_platform:
            mozharness["config"] = ["raptor/mac_external_browser_config.py"]
        elif "windows" in test_platform:
            mozharness["config"] = ["raptor/windows_external_browser_config.py"]
        elif "linux" in test_platform:
            mozharness["config"] = ["raptor/linux_external_browser_config.py"]
        elif "android" in test_platform:
            test["target"] = "target.tar.xz"
            mozharness["config"] = ["raptor/android_hw_external_browser_config.py"]

        yield test


@transforms.add
def handle_lull_schedule(config, tests):
    # Setup lull schedule attribute here since the attributes
    # can't have any keyed by settings
    for test in tests:
        if "lull-schedule" in test["raptor"]:
            lull_schedule = test["raptor"].pop("lull-schedule")
            if lull_schedule:
                test.setdefault("attributes", {})["lull-schedule"] = lull_schedule
        yield test


@transforms.add
def apply_raptor_device_optimization(config, tests):
    # Bug 1919389
    # For now, only change the back stop optimization strategy for A55 devices
    for test in tests:
        if test["test-platform"].startswith("android-hw-a55"):
            test["optimization"] = {"skip-unless-backstop"None}
        yield test


@task_transforms.add
def add_scopes_and_proxy(config, tasks):
    for task in tasks:
        task.setdefault("worker", {})["taskcluster-proxy"] = True
        task.setdefault("scopes", []).append(
            "secrets:get:project/perftest/gecko/level-{level}/perftest-login"
        )
        yield task


@task_transforms.add
def setup_lull_schedule(config, tasks):
    for task in tasks:
        attrs = task.setdefault("attributes", {})
        if attrs.get("lull-schedule"Noneis not None:
            # Move the lull schedule attribute into the extras
            # so that it can be accessible through mozci
            lull_schedule = attrs.pop("lull-schedule")
            task.setdefault("extra", {})["lull-schedule"] = lull_schedule
        yield task


@task_transforms.add
def setup_autoland_retriggers(config, tasks):

    def _allow_task_duplicates(label):
        if "android" in label:
            return False
        if any(sp3_test in label for sp3_test in SP3_CRITICAL_TESTS):
            return True
        return False

    for task in tasks:
        attrs = task.setdefault("attributes", {})
        if config.params["project"] == "autoland" and _allow_task_duplicates(
            task["label"]
        ):
            attrs["task_duplicates"] = 12
        yield task


@task_transforms.add
def setup_internal_artifacts(config, tasks):
    for task in tasks:
        if (
            task["worker"]["os"] == "linux-bitbar"
            or task["worker"]["os"] == "linux-lambda"
        ):
            task["worker"].setdefault("artifacts", []).append({
                "name""perftest",
                "path""workspace/build/perftest",
                "type""directory",
            })
        else:
            task["worker"].setdefault("artifacts", []).append({
                "name""perftest",
                "path""build/perftest",
                "type""directory",
            })
        yield task


@task_transforms.add
def select_tasks_to_lambda(config, tasks):
    """
    all motionmark tests
    speedometer3 test
    unity-webgl test
    all youtube-playback tests (including power)
    all vpl (video-playback-latency) tests
    all pageload tests (ideally fenix/CaR/ChR)
    jetstream2/jetstream3 benchmarks
    background/foreground resource tests (browsertime-power idle/idle-bg)
    trr-* performance tests

    """
    tests_to_run_at_lambdatest = [
        "motionmark-1-3",
        "motionmark-htmlsuite-1-3",
        "speedometer3",
        "unity-webgl",
        "video-playback-latency",
        "youtube-playback-av1-sfr",
        "youtube-playback-hfr",
        "youtube-playback-vp9-sfr",
        "youtube-playback-h264-sfr",
        "youtube-playback-h264-720p60",
        "youtube-playback-vp9-720p60",
        "tp6m",
        "jetstream2",
        "jetstream3",
        "browsertime-power",
        "browsertime-trr-performance",
    ]

    # Bug 2017151 - newly-migrated tests run at tier 2 while stabilizing on LT
    tests_to_force_tier2 = [
        "youtube-playback-h264-sfr",
        "youtube-playback-h264-720p60",
        "youtube-playback-vp9-720p60",
        "jetstream2",
        "jetstream3",
        "browsertime-power",
        "browsertime-trr-performance",
    ]

    def redirect_to_lt(task):
        task["tags"]["os"] = "linux-lambda"
        task["worker"]["os"] = "linux-lambda"
        task["worker-type"] = "t-lambda-perf-a55"
        task["worker"]["env"]["TASKCLUSTER_WORKER_TYPE"] = "t-lambda-perf-a55"
        cmds = []
        for cmd in task["worker"]["command"]:
            # Bug 1981862 - issues with condprof setup @ lambdatest
            cmds.append([
                c.replace(
                    "/builds/taskcluster/script.py",
                    "/home/ltuser/taskcluster/script.py",
                )
                for c in cmd
                if not c.startswith("--conditioned-profile")
            ])
        task["worker"]["command"] = cmds
        task["worker"]["env"]["DISABLE_USB_POWER_METER_RESET"] = "1"
        # Bug 2017151 - newly-migrated tests run at tier 2 while stabilizing on LT
        if any(t in task["label"for t in tests_to_force_tier2):
            th = task.setdefault("treeherder", {})
            th["tier"] = max(th.get("tier"1), 2)
        return task

    def make_sp3_lt_copy(task):
        lt_task = deepcopy(task)
        lt_task["label"] = lt_task["label"].replace("-a55-""-a55-lt-")
        if "treeherder" in lt_task:
            group, symbol = split_symbol(lt_task["treeherder"]["symbol"])
            lt_task["treeherder"]["symbol"] = join_symbol(group, f"{symbol}-LT")
            lt_task["treeherder"]["platform"] = lt_task["treeherder"][
                "platform"
            ].replace("-a55-""-a55-lt-")
        return redirect_to_lt(lt_task)

    for task in tasks:
        if not ("android" in task["label"and "a55" in task["label"]):
            yield task
            continue
        if not any(t in task["label"for t in tests_to_run_at_lambdatest):
            yield task
            continue
        if task["worker-type"] != "t-bitbar-gw-perf-a55":
            yield task
            continue
        if "speedometer3" in task["label"]:
            # Bug 2017152 - temporary: run SP3 on both BitBar and LT for comparison
            # deepcopy must happen before yielding task, as downstream transforms
            # mutate task["routes"] in-place.
            # Copying after yield picks up those mutations.
            lt_task = make_sp3_lt_copy(task)
            yield task
            yield lt_task
        else:
            yield redirect_to_lt(task)


@transforms.add
def add_simpleperf(config, tests):
    is_native_profiling = config.params.get("try_task_config", {}).get(
        "native-profiling"False
    )
    app_packages = {
        "fenix""org.mozilla.fenix",
        "geckoview""org.mozilla.geckoview_example",
    }
    for test in tests:
        test_name = test.get("test-name"None)
        app = test.get("app")

        def _setup_simpleperf_profiling(test):
            extra_options = test.setdefault("mozharness", {}).setdefault(
                "extra-options", []
            )
            extra_options.extend([
                "--simpleperf",
                "--browsertime-arg=androidSimpleperf=$MOZ_FETCHES_DIR/android-simpleperf",
            ])
            app_data_dir = f"/storage/emulated/0/Android/data/{app_packages[app]}/files"
            extra_options.extend([
                "--setenv MOZ_USE_PERFORMANCE_MARKER_FILE=1",
                f"--setenv MOZ_PERFORMANCE_MARKER_DIR={app_data_dir}",
                f"--setenv PERF_SPEW_DIR={app_data_dir}",
                "--setenv IONPERF=func",
                "--setenv JIT_OPTION_onlyInlineSelfHosted=true",
            ])

            fetches = test.setdefault("fetches", {})
            fetches.setdefault("build", []).append({
                "artifact""target.crashreporter-symbols.zip",
                "extract"False,
            })
            toolchains = [
                "linux64-android-simpleperf-linux-repack",
                "linux64-samply",
            ]
            by_app = fetches.setdefault("toolchain", {}).setdefault("by-app", {})
            default_toolchains = by_app.setdefault("default", [])
            for toolchain in toolchains:
                if toolchain not in default_toolchains:
                    default_toolchains.append(toolchain)

        if app in app_packages and "speedometer3-mobile" in test_name:
            # On autoland, run a copy of the Speedometer 3 a55 Fenix task
            # with native (Simpleperf) profiling

            is_autoland_job = (
                config.params["project"] == "autoland"
                and app == "fenix"
                and "a55" in test.get("test-platform""")
                and test["attributes"].get("shippable"False)
                and "no-fission"
                not in (test.get("attributes", {}).get("unittest_variant"or "")
            )

            if is_autoland_job:
                # Modify a duplicate test
                autoland_test = deepcopy(test)
                autoland_test["run-on-projects"] = ["autoland-only"]
                autoland_test["test-name"] += "-native-profiling"
                autoland_test["try-name"] += "-native-profiling"
                _setup_simpleperf_profiling(autoland_test)
                yield autoland_test
            elif is_native_profiling:
                # Modify the test in-place
                _setup_simpleperf_profiling(test)

        yield test


@transforms.add
def handle_simpleperf_symbol(config, tests):
    for test in tests:
        extra_options = test.get("mozharness", {}).get("extra-options", [])
        if "--simpleperf" in extra_options:
            group, symbol = split_symbol(test["treeherder-symbol"])
            test["treeherder-symbol"] = join_symbol(group, f"{symbol}-p")
        yield test

Messung V0.5 in Prozent
C=87 H=89 G=87

¤ Dauer der Verarbeitung: 0.9 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.