Skip to content

Commit 805ffb4

Browse files
authored
fix(ios): budget snapshot bridge test compile from the build ceiling (#2454)
The host bridge unit test compiled the snapshot bridge under a fixed 45 s budget that a cold macOS runner trips on during the first `xcrun` (the signature-scan stall plus clang). Budget both `beforeAll` compiles from a deadline sized to production's build ceiling via `createSnapshotSourceDeadline` and `remainingSnapshotSourceMs`, so the unit lane is never stricter than the preparation path it mirrors. `BUILD_TIMEOUT_MS` is now `@internal`-exported as the single source of truth for that ceiling instead of a second magic number. Closes #2439
1 parent c99b450 commit 805ffb4

2 files changed

Lines changed: 58 additions & 46 deletions

File tree

packages/platform-apple/src/snapshot-source/cache.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,13 @@ type SnapshotBridgeCacheManifest = Readonly<{
2929
const CACHE_SCHEMA_VERSION = 1 as const;
3030
const BRIDGE_FILENAME = 'snapshot-bridge';
3131
const MANIFEST_FILENAME = 'manifest.json';
32-
const BUILD_TIMEOUT_MS = 120_000;
32+
33+
/**
34+
* @internal Upper bound on a single snapshot-bridge clang invocation, exposed for the host bridge
35+
* tests so they budget their own compile from the same ceiling instead of a stricter constant. The
36+
* live build also stays under the caller's snapshot-source deadline, which can bind tighter.
37+
*/
38+
export const BUILD_TIMEOUT_MS = 120_000;
3339

3440
export async function ensureSnapshotBridgeBinary(
3541
input: Readonly<{

packages/platform-apple/src/snapshot-source/native-runtime.test.ts

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,48 @@ import path from 'node:path';
44
import { beforeAll, describe, test } from 'vitest';
55
import { runCmd } from '@agent-device/host-kit/command';
66
import { mkdtempForTest } from '../__tests__/tmp-dir.ts';
7+
import { BUILD_TIMEOUT_MS } from './cache.ts';
8+
import { createSnapshotSourceDeadline, remainingSnapshotSourceMs } from './deadline.ts';
9+
10+
// The host bridge compile is budgeted from a deadline sized to production's build ceiling, not a
11+
// stricter warm-host constant, so a cold runner's first `xcrun` (signature-scan stall plus clang)
12+
// is not tripped before the compile finishes (#2439). The hook budget leaves headroom beyond that.
13+
const COMPILE_HOOK_TIMEOUT_MS = BUILD_TIMEOUT_MS + 30_000;
14+
15+
async function compileSnapshotBridgeFixture(clangArgs: readonly string[]): Promise<void> {
16+
const deadline = createSnapshotSourceDeadline(BUILD_TIMEOUT_MS, undefined);
17+
const compiled = await runCmd('xcrun', [...clangArgs], {
18+
allowFailure: true,
19+
timeoutMs: remainingSnapshotSourceMs(deadline, 'native-build-deadline'),
20+
});
21+
assert.equal(compiled.exitCode, 0, compiled.stderr);
22+
}
723

824
describe.skipIf(process.platform !== 'darwin')('native snapshot capture', () => {
925
let binary: string;
1026
beforeAll(async () => {
1127
binary = path.join(await mkdtempForTest('snapshot-foreground-'), 'foreground-owner');
1228
const nativeRoot = path.resolve(import.meta.dirname, '../../../../apple/snapshot-bridge');
13-
const compiled = await runCmd(
14-
'xcrun',
15-
[
16-
'--sdk',
17-
'macosx',
18-
'clang',
19-
'-fobjc-arc',
20-
'-Ddlopen=fixtureDlopen',
21-
'-Ddlsym=fixtureDlsym',
22-
'-framework',
23-
'Foundation',
24-
'-framework',
25-
'CoreGraphics',
26-
'-I',
27-
nativeRoot,
28-
path.join(nativeRoot, 'SnapshotBridgeRuntime.m'),
29-
path.join(nativeRoot, 'SnapshotBridgeCapture.m'),
30-
path.join(import.meta.dirname, 'fixtures/foreground-owner.m'),
31-
'-o',
32-
binary,
33-
],
34-
{ allowFailure: true, timeoutMs: 45_000 },
35-
);
36-
assert.equal(compiled.exitCode, 0, compiled.stderr);
37-
}, 60_000);
29+
await compileSnapshotBridgeFixture([
30+
'--sdk',
31+
'macosx',
32+
'clang',
33+
'-fobjc-arc',
34+
'-Ddlopen=fixtureDlopen',
35+
'-Ddlsym=fixtureDlsym',
36+
'-framework',
37+
'Foundation',
38+
'-framework',
39+
'CoreGraphics',
40+
'-I',
41+
nativeRoot,
42+
path.join(nativeRoot, 'SnapshotBridgeRuntime.m'),
43+
path.join(nativeRoot, 'SnapshotBridgeCapture.m'),
44+
path.join(import.meta.dirname, 'fixtures/foreground-owner.m'),
45+
'-o',
46+
binary,
47+
]);
48+
}, COMPILE_HOOK_TIMEOUT_MS);
3849

3950
test.each([
4051
'stable',
@@ -90,26 +101,21 @@ describe.skipIf(process.platform !== 'darwin')(
90101
beforeAll(async () => {
91102
binary = path.join(await mkdtempForTest('snapshot-recovery-'), 'recovery-conformance');
92103
const nativeRoot = path.resolve(import.meta.dirname, '../../../../apple/snapshot-bridge');
93-
const compiled = await runCmd(
94-
'xcrun',
95-
[
96-
'--sdk',
97-
'macosx',
98-
'clang',
99-
'-fobjc-arc',
100-
'-framework',
101-
'Foundation',
102-
'-I',
103-
nativeRoot,
104-
path.join(nativeRoot, 'SnapshotBridgeCapture.m'),
105-
path.join(import.meta.dirname, 'fixtures/recovery-conformance.m'),
106-
'-o',
107-
binary,
108-
],
109-
{ allowFailure: true, timeoutMs: 45_000 },
110-
);
111-
assert.equal(compiled.exitCode, 0, compiled.stderr);
112-
}, 60_000);
104+
await compileSnapshotBridgeFixture([
105+
'--sdk',
106+
'macosx',
107+
'clang',
108+
'-fobjc-arc',
109+
'-framework',
110+
'Foundation',
111+
'-I',
112+
nativeRoot,
113+
path.join(nativeRoot, 'SnapshotBridgeCapture.m'),
114+
path.join(import.meta.dirname, 'fixtures/recovery-conformance.m'),
115+
'-o',
116+
binary,
117+
]);
118+
}, COMPILE_HOOK_TIMEOUT_MS);
113119

114120
assert.equal(recoveryFixture.version, 1);
115121
test.each(recoveryFixture.recoveryCases.map((recoveryCase) => recoveryCase.name))(

0 commit comments

Comments
 (0)