aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--Misc/NEWS.d/next/Tests/2025-04-29-14-56-37.gh-issue-133131.1pchjl.rst2
-rw-r--r--iOS/testbed/__main__.py42
2 files changed, 41 insertions, 3 deletions
diff --git a/Misc/NEWS.d/next/Tests/2025-04-29-14-56-37.gh-issue-133131.1pchjl.rst b/Misc/NEWS.d/next/Tests/2025-04-29-14-56-37.gh-issue-133131.1pchjl.rst
new file mode 100644
index 00000000000..30b0f18f8dc
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2025-04-29-14-56-37.gh-issue-133131.1pchjl.rst
@@ -0,0 +1,2 @@
+The iOS testbed will now select the most recently released "SE-class" device
+for testing if a device isn't explicitly specified.
diff --git a/iOS/testbed/__main__.py b/iOS/testbed/__main__.py
index b436c9af99d..c05497ede3a 100644
--- a/iOS/testbed/__main__.py
+++ b/iOS/testbed/__main__.py
@@ -123,6 +123,36 @@ async def async_check_output(*args, **kwargs):
)
+# Select a simulator device to use.
+async def select_simulator_device():
+ # List the testing simulators, in JSON format
+ raw_json = await async_check_output(
+ "xcrun", "simctl", "--set", "testing", "list", "-j"
+ )
+ json_data = json.loads(raw_json)
+
+ # Any device will do; we'll look for "SE" devices - but the name isn't
+ # consistent over time. Older Xcode versions will use "iPhone SE (Nth
+ # generation)"; As of 2025, they've started using "iPhone 16e".
+ #
+ # When Xcode is updated after a new release, new devices will be available
+ # and old ones will be dropped from the set available on the latest iOS
+ # version. Select the one with the highest minimum runtime version - this
+ # is an indicator of the "newest" released device, which should always be
+ # supported on the "most recent" iOS version.
+ se_simulators = sorted(
+ (devicetype["minRuntimeVersion"], devicetype["name"])
+ for devicetype in json_data["devicetypes"]
+ if devicetype["productFamily"] == "iPhone"
+ and (
+ ("iPhone " in devicetype["name"] and devicetype["name"].endswith("e"))
+ or "iPhone SE " in devicetype["name"]
+ )
+ )
+
+ return se_simulators[-1][1]
+
+
# Return a list of UDIDs associated with booted simulators
async def list_devices():
try:
@@ -371,12 +401,16 @@ def update_plist(testbed_path, args):
plistlib.dump(info, f)
-async def run_testbed(simulator: str, args: list[str], verbose: bool=False):
+async def run_testbed(simulator: str | None, args: list[str], verbose: bool=False):
location = Path(__file__).parent
print("Updating plist...", end="", flush=True)
update_plist(location, args)
print(" done.", flush=True)
+ if simulator is None:
+ simulator = await select_simulator_device()
+ print(f"Running test on {simulator}", flush=True)
+
# We need to get an exclusive lock on simulator creation, to avoid issues
# with multiple simulators starting and being unable to tell which
# simulator is due to which testbed instance. See
@@ -453,8 +487,10 @@ def main():
)
run.add_argument(
"--simulator",
- default="iPhone SE (3rd Generation)",
- help="The name of the simulator to use (default: 'iPhone SE (3rd Generation)')",
+ help=(
+ "The name of the simulator to use (eg: 'iPhone 16e'). Defaults to ",
+ "the most recently released 'entry level' iPhone device."
+ )
)
run.add_argument(
"-v", "--verbose",