From d3b161d63be1522f362b88adf67b6a794662ac84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Fri, 6 Nov 2026 14:16:32 +0100 Subject: [PATCH 1/2] fix(apple): keep runner bridge test hooks out of the shipped package #4256 put RunnerSnapshotBridgeReadForTest and RunnerSnapshotBridgeDrainForTest under an #if AGENT_DEVICE_RUNNER_UNIT_TESTS block in the shipped RunnerSnapshotBridge.m. The packager strips that block only from Swift, so the macro survived packaging and check-package failed the Release Build job. Move the hooks to UnitTests/RunnerSnapshotBridgeTesting.m, which the package omits, and reach the read and the reader queue through a private UnitTests/RunnerSnapshotBridge+Internal.h. Co-Authored-By: Claude Opus 5.5 --- .../RunnerSnapshotBridge.m | 24 ++++++------------- .../UnitTests/RunnerSnapshotBridge+Internal.h | 18 ++++++++++++++ .../UnitTests/RunnerSnapshotBridgeTesting.m | 20 ++++++++++++++++ 3 files changed, 45 insertions(+), 17 deletions(-) create mode 100644 apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerSnapshotBridge+Internal.h create mode 100644 apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerSnapshotBridgeTesting.m diff --git a/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSnapshotBridge.m b/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSnapshotBridge.m index b224ab7290..771b536857 100644 --- a/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSnapshotBridge.m +++ b/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSnapshotBridge.m @@ -187,7 +187,9 @@ static NSUInteger RunnerSnapshotBridgeBudgetMs(NSDictionary *request) static NSTimeInterval RunnerSnapshotBridgeAbandonedAt = 0; static const NSTimeInterval RunnerSnapshotBridgeWedgeSeconds = 5; -static dispatch_queue_t RunnerSnapshotBridgeReaderQueue(void) +// The reader queue and RunnerSnapshotBridgeRead have external linkage so the runner unit bundle can +// drive them through UnitTests/RunnerSnapshotBridge+Internal.h. +dispatch_queue_t RunnerSnapshotBridgeReaderQueue(void) { static dispatch_queue_t queue; static dispatch_once_t onceToken; @@ -207,10 +209,10 @@ @implementation RunnerSnapshotBridgeAnswer /// Runs one read on the reader queue and waits for it up to `budgetMs`. A read that outlives the budget /// is abandoned, not stopped: its answer is dropped when it returns. -static NSDictionary *RunnerSnapshotBridgeRead(NSDictionary *request, - NSUInteger budgetMs, - NSDictionary * (^read)(void), - NSTimeInterval (^clock)(void)) +NSDictionary *RunnerSnapshotBridgeRead(NSDictionary *request, + NSUInteger budgetMs, + NSDictionary * (^read)(void), + NSTimeInterval (^clock)(void)) { NSUInteger sequence; @synchronized (RunnerSnapshotBridgeAnswer.class) { @@ -252,18 +254,6 @@ @implementation RunnerSnapshotBridgeAnswer return answer.value; } -#if defined(AGENT_DEVICE_RUNNER_UNIT_TESTS) -NSDictionary *RunnerSnapshotBridgeReadForTest(NSDictionary *request, NSUInteger budgetMs, - NSDictionary *(^read)(void), NSTimeInterval now) -{ - return RunnerSnapshotBridgeRead(request, budgetMs, read, ^{ return now; }); -} -void RunnerSnapshotBridgeDrainForTest(void) -{ - dispatch_sync(RunnerSnapshotBridgeReaderQueue(), ^{}); -} -#endif - uint32_t RunnerSnapshotBridgeMaximumFrameBytes(void) { return kMaximumFrameBytes; diff --git a/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerSnapshotBridge+Internal.h b/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerSnapshotBridge+Internal.h new file mode 100644 index 0000000000..a95b63bc8f --- /dev/null +++ b/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerSnapshotBridge+Internal.h @@ -0,0 +1,18 @@ +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +#if TARGET_OS_IOS && TARGET_OS_SIMULATOR + +// The snapshot bridge's read admission and reader queue, which RunnerSnapshotBridge.m defines for the +// runner unit bundle. The packaged runner omits UnitTests/. +NSDictionary *RunnerSnapshotBridgeRead(NSDictionary *request, + NSUInteger budgetMs, + NSDictionary * (^read)(void), + NSTimeInterval (^clock)(void)); +dispatch_queue_t RunnerSnapshotBridgeReaderQueue(void); + +#endif + +NS_ASSUME_NONNULL_END diff --git a/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerSnapshotBridgeTesting.m b/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerSnapshotBridgeTesting.m new file mode 100644 index 0000000000..4bb07a35f7 --- /dev/null +++ b/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerSnapshotBridgeTesting.m @@ -0,0 +1,20 @@ +#if defined(AGENT_DEVICE_RUNNER_UNIT_TESTS) +#import "RunnerSnapshotBridgeTesting.h" + +#if TARGET_OS_IOS && TARGET_OS_SIMULATOR + +#import "RunnerSnapshotBridge+Internal.h" + +NSDictionary *RunnerSnapshotBridgeReadForTest(NSDictionary *request, NSUInteger budgetMs, + NSDictionary *(^read)(void), NSTimeInterval now) +{ + return RunnerSnapshotBridgeRead(request, budgetMs, read, ^{ return now; }); +} + +void RunnerSnapshotBridgeDrainForTest(void) +{ + dispatch_sync(RunnerSnapshotBridgeReaderQueue(), ^{}); +} + +#endif +#endif From 1111bd2411b2b78aa78b56e12ab249e443539f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Fri, 6 Nov 2026 14:34:58 +0100 Subject: [PATCH 2/2] fix(apple): mark the runner bridge read's nil-able result nullable Co-Authored-By: Claude Opus 5.5 --- .../UnitTests/RunnerSnapshotBridge+Internal.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerSnapshotBridge+Internal.h b/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerSnapshotBridge+Internal.h index a95b63bc8f..d5c29fcb9b 100644 --- a/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerSnapshotBridge+Internal.h +++ b/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerSnapshotBridge+Internal.h @@ -6,11 +6,12 @@ NS_ASSUME_NONNULL_BEGIN #if TARGET_OS_IOS && TARGET_OS_SIMULATOR // The snapshot bridge's read admission and reader queue, which RunnerSnapshotBridge.m defines for the -// runner unit bundle. The packaged runner omits UnitTests/. -NSDictionary *RunnerSnapshotBridgeRead(NSDictionary *request, - NSUInteger budgetMs, - NSDictionary * (^read)(void), - NSTimeInterval (^clock)(void)); +// runner unit bundle. The packaged runner omits UnitTests/. A read answers with what `read` returns, +// nil included. +NSDictionary * _Nullable RunnerSnapshotBridgeRead(NSDictionary *request, + NSUInteger budgetMs, + NSDictionary * _Nullable (^read)(void), + NSTimeInterval (^clock)(void)); dispatch_queue_t RunnerSnapshotBridgeReaderQueue(void); #endif