1# Copyright 2023 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5from __future__ import annotations 6 7import logging 8import pathlib 9import sys 10import tempfile 11from typing import Optional 12 13import pytest 14 15from crossbench import plt 16from crossbench.browsers import all as browsers 17from crossbench.parse import PathParser 18from crossbench.path import LocalPath 19from tests import test_helper 20 21# pytest.fixtures rely on params having the same name as the fixture function 22# pylint: disable=redefined-outer-name 23 24 25def pytest_addoption(parser): 26 parser.addoption( 27 "--test-browser-path", 28 "--browserpath", 29 default=None, 30 type=PathParser.path) 31 parser.addoption( 32 "--test-driver-path", "--driverpath", default=None, type=PathParser.path) 33 parser.addoption( 34 "--test-gsutil-path", "--gustilpath", default=None, type=PathParser.path) 35 parser.addoption("--adb-device-id", default=None, type=str) 36 parser.addoption("--adb-path", default=None, type=str) 37 parser.addoption("--ignore-tests", default=None, type=str) 38 39 40def pytest_xdist_auto_num_workers(config): 41 del config 42 if "linux" in sys.platform: 43 return 2 44 return 4 45 46 47def _get_app_path(request, option_key) -> Optional[pathlib.Path]: 48 app_path = request.config.getoption(option_key) 49 if app_path and plt.PLATFORM.is_win and app_path.suffix != ".exe": 50 return app_path.parent / (app_path.name + ".exe") 51 return app_path 52 53 54@pytest.fixture(scope="session", autouse=True) 55def driver_path(request) -> Optional[pathlib.Path]: 56 maybe_driver_path: Optional[LocalPath] = _get_app_path( 57 request, "--test-driver-path") 58 if maybe_driver_path: 59 logging.info("driver path: %s", maybe_driver_path) 60 assert maybe_driver_path.exists() 61 return maybe_driver_path 62 63 64@pytest.fixture(scope="session", autouse=True) 65def browser_path(request) -> Optional[pathlib.Path]: 66 maybe_browser_path: Optional[pathlib.Path] = _get_app_path( 67 request, "--test-browser-path") 68 if maybe_browser_path: 69 logging.info("browser path: %s", maybe_browser_path) 70 assert maybe_browser_path.exists() 71 return maybe_browser_path 72 logging.info("Trying default browser path for local runs.") 73 try: 74 return pathlib.Path(browsers.Chrome.stable_path(plt.PLATFORM)) 75 except ValueError as e: 76 logging.warning("Unable to find Chrome Stable on %s, error=%s", 77 plt.PLATFORM, e) 78 return None 79 80 81@pytest.fixture(scope="session", autouse=True) 82def gsutil_path(request) -> pathlib.Path: 83 maybe_gsutil_path: Optional[pathlib.Path] = _get_app_path( 84 request, "--test-gsutil-path") 85 if maybe_gsutil_path: 86 logging.info("gsutil path: %s", maybe_gsutil_path) 87 assert maybe_gsutil_path.exists() 88 return maybe_gsutil_path 89 logging.info("Trying default gsutil path for local runs.") 90 return default_gsutil_path() 91 92 93def default_gsutil_path() -> pathlib.Path: 94 if maybe_gsutil_path := plt.PLATFORM.which("gsutil"): 95 maybe_gsutil_path = plt.PLATFORM.local_path(maybe_gsutil_path) 96 assert maybe_gsutil_path, "could not find fallback gsutil" 97 assert maybe_gsutil_path.exists() 98 return maybe_gsutil_path 99 pytest.skip(f"Could not find gsutil on {plt.PLATFORM}") 100 return pathlib.Path() 101 102 103@pytest.fixture 104def output_dir(): 105 with tempfile.TemporaryDirectory() as tmpdirname: 106 yield pathlib.Path(tmpdirname) 107 108 109@pytest.fixture(scope="session") 110def root_dir() -> pathlib.Path: 111 return test_helper.root_dir() 112 113 114@pytest.fixture 115def cache_dir(output_dir) -> pathlib.Path: 116 path = output_dir / "cache" 117 assert not path.exists() 118 path.mkdir() 119 return path 120 121 122@pytest.fixture 123def archive_dir(output_dir) -> pathlib.Path: 124 path = output_dir / "archive" 125 assert not path.exists() 126 return path 127 128 129@pytest.fixture(scope="session", autouse=True) 130def device_id(request) -> Optional[str]: 131 maybe_device_id: Optional[str] = request.config.getoption( 132 "--adb-device-id") 133 if maybe_device_id: 134 logging.info("adb device id: %s", maybe_device_id) 135 return maybe_device_id 136 logging.info("No Android device detected.") 137 return None 138 139 140@pytest.fixture(scope="session", autouse=True) 141def adb_path(request) -> Optional[str]: 142 maybe_adb_path: Optional[str] = request.config.getoption( 143 "--adb-path") 144 if maybe_adb_path: 145 logging.info("adb path: %s", maybe_adb_path) 146 return maybe_adb_path 147 logging.info("No custom adb path.") 148 return None 149