…ic tests
https://bugs.webkit.org/show_bug.cgi?id=310247
rdar://172887928
Reviewed by Jonathan Bedard.
This patch reduces the startup overhead of run-api-tests by addressing
several bottlenecks in the Python script's initialization path.
1. Defer default_configuration() in configuration_options() (~500ms)
The -t/--target option eagerly created a Config object and called
default_configuration(), which spawns a Perl subprocess
(webkit-build-directory) to determine the build directory. This
happened unconditionally at option-parse time, even when --debug or
--release was explicitly passed. Changed the default to None; the
port base class (base.py:168-169) already has a lazy fallback that
calls default_configuration() only when no configuration was set.
2. Make SDK resolution lazy in embedded port modules (~1-1.5s)
Six embedded port modules (ios_simulator, ios_device,
watch_simulator, watch_device, visionos_simulator, visionos_device)
called apple_additions().get_sdk() at class-definition time, which
triggered xcodebuild -showsdks (~1s+) the moment any of these
modules was imported by PortFactory.get(). Fixed by converting SDK
from a class-level attribute to a lazy @Property that defers the
lookup until first access. Each class now has a _DEFAULT_SDK class
attribute for the base SDK name and a @Property SDK that calls
apple_additions().get_sdk() only when needed. This aligns with the
EmbeddedPort base class, which already declares SDK as
@Property @AbstractMethod. Also updated EmbeddedDevicePort's
determine_full_port_name() classmethod to use cls._DEFAULT_SDK
instead of cls.SDK, since properties don't work on class references.
Additionally, PORT_CLASSES is restored to alphabetical order and
the import logic is extracted into a _load_port_class() helper.
3. Defer configuration_for_upload until needed (~100-200ms)
configuration_for_upload was computed unconditionally before test
collection, but is only needed when --report-urls is specified.
Moved it into the upload block.
4. Skip test collection when exact test names are provided.
Previously, `_collect_tests` always copied the test binary to "ToBeListed" and
spawned it with --gtest_list_tests to enumerate every available test, even when
the user specified exact test names on the command line (~0.5-1s of overhead).
Fix by adding `_try_collect_exact_tests`, which detects when all arguments are
fully-qualified test names (no glob wildcards) and resolves them directly
without listing. For the `<Binary>.<Suite>.<Test>` form, the name is used as-is.
For the `<Suite>.<Test>` form, the appropriate binary prefix is added. The method
falls back to the full listing path for glob patterns, partial matches like
`<Binary>.<Suite>`, or when no arguments are given.
5. Remove unnecessary preference reset from API test runs.
`_set_up_run` unconditionally called `reset_preferences()`, which runs two
sequential `defaults delete` commands for the DumpRenderTree and
WebKitTestRunner preference domains (~0.1s). These are layout test runner
preference domains and are not used by the API test binaries.
6. Skip build check when --no-build is set.
`check_api_test_build` was called unconditionally, resolving binary paths and
checking filesystem existence even when --no-build (the default) was passed.
Now the entire build check is skipped when build=False, deferring the first
build-directory resolution to `_collect_tests` where it's actually needed.
7. Lazy-import webkitscmpy in port/base.py (~150-200ms)
`from webkitscmpy import local` was a module-level import that loaded the
entire webkitscmpy dependency graph (registering dozens of AutoInstall
packages) on every run. Moved it into `commits_for_upload()`, the only
method that uses it.
8. Cache path_to_api_test_binaries() in check_api_test_build.
`check_api_test_build` called `path_to_api_test_binaries()` twice: once to
get the key list and once to iterate. Stored the result in a local variable
to avoid the redundant dict reconstruction.
9. Lazy-import Upload and remove dead imports in manager.py.
Moved `from webkitpy.results.upload import Upload` into the upload codepath
where it's actually used. Removed completely unused `DeviceRequest` and
`SimulatedDeviceManager` imports.
* Tools/Scripts/webkitpy/api_tests/manager.py:
(Manager):
(Manager._is_exact_test_name):
(Manager._try_collect_exact_tests):
(Manager._collect_tests):
(Manager._set_up_run):
(Manager.run):
* Tools/Scripts/webkitpy/api_tests/manager_unittest.py:
(test_is_exact_test_name):
* Tools/Scripts/webkitpy/port/base.py:
(Port.check_api_test_build):
(Port.commits_for_upload):
* Tools/Scripts/webkitpy/port/embedded_device.py:
(EmbeddedDevicePort.determine_full_port_name):
* Tools/Scripts/webkitpy/port/factory.py:
(configuration_options):
(PortFactory):
(PortFactory._load_port_class):
(PortFactory.get):
(PortFactory.get.in):
* Tools/Scripts/webkitpy/port/ios_device.py:
(IOSDevicePort):
(IOSDevicePort.SDK):
* Tools/Scripts/webkitpy/port/ios_simulator.py:
(IOSSimulatorPort):
(IOSSimulatorPort.SDK):
* Tools/Scripts/webkitpy/port/port_testcase.py:
(bind_mock_apple_additions.MockAppleAdditions):
(bind_mock_apple_additions.MockAppleAdditions.get_sdk):
* Tools/Scripts/webkitpy/port/visionos_device.py:
(VisionOSDevicePort):
(VisionOSDevicePort.SDK):
* Tools/Scripts/webkitpy/port/visionos_simulator.py:
(VisionOSSimulatorPort):
(VisionOSSimulatorPort.SDK):
* Tools/Scripts/webkitpy/port/watch_device.py:
(WatchDevicePort):
(WatchDevicePort.SDK):
* Tools/Scripts/webkitpy/port/watch_simulator.py:
(WatchSimulatorPort):
(WatchSimulatorPort.SDK):
Canonical link: https://commits.webkit.org/309636@main
a80da14
6e1cfbb
🛠 win🧪 win-tests🧪 ios-wk2🧪 api-mac🧪 ios-wk2-wpt🧪 api-mac-debug🧪 api-ios🧪 mac-wk1🧪 mac-wk2🧪 gtk-wk2🧪 mac-AS-debug-wk2🛠 🧪 merge🧪 mac-intel-wk2