Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 11 additions & 14 deletions packages/platform-apple/src/__tests__/session-observation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const { snapshot, runningApp } = vi.hoisted(() => ({
snapshot: vi.fn(),
runningApp: vi.fn(),
}));
vi.mock('../core/runner-client.ts', () => ({ getRunnerSessionSnapshot: snapshot }));
vi.mock('../core/runner-client.ts', () => ({ readRunnerSessionLiveness: snapshot }));
vi.mock('../core/app-resolution.ts', () => ({ detectSoleRunningIosSimulatorApp: runningApp }));

const host = {
Expand All @@ -19,22 +19,19 @@ beforeEach(() => {
vi.resetAllMocks();
});

test.each([true, false])(
'runner observation preserves liveness %s and session identity',
async (alive) => {
snapshot.mockResolvedValue({ sessionId: 'runner-1', alive, ready: false });
test('runner observation reports a registered runner, whatever lifecycle state it is in', async () => {
snapshot.mockReturnValue({ sessionId: 'runner-1', liveness: 'starting' });

await expect(observation.observeRunnerSession('sim-1')).resolves.toEqual({
alive,
sessionId: 'runner-1',
});
expect(snapshot).toHaveBeenCalledWith('sim-1');
expect(host.listLocalDevices).not.toHaveBeenCalled();
},
);
await expect(observation.observeRunnerSession('sim-1')).resolves.toEqual({
alive: true,
sessionId: 'runner-1',
});
expect(snapshot).toHaveBeenCalledWith('sim-1');
expect(host.listLocalDevices).not.toHaveBeenCalled();
});

test('a missing runner session has no observation', async () => {
snapshot.mockResolvedValue(null);
snapshot.mockReturnValue(null);
await expect(observation.observeRunnerSession('sim-1')).resolves.toBeUndefined();
});

Expand Down
4 changes: 2 additions & 2 deletions packages/platform-apple/src/core/runner-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ export const hasCachedAppleRunnerArtifact: AppleRunnerClient['hasCachedAppleRunn
client.hasCachedAppleRunnerArtifact;
export const detachIosSimulatorRunnerSessionsForShutdown: AppleRunnerClient['detachIosSimulatorRunnerSessionsForShutdown'] =
client.detachIosSimulatorRunnerSessionsForShutdown;
export const getRunnerSessionSnapshot: AppleRunnerClient['getRunnerSessionSnapshot'] =
client.getRunnerSessionSnapshot;
export const readRunnerSessionLiveness: AppleRunnerClient['readRunnerSessionLiveness'] =
client.readRunnerSessionLiveness;
export const releaseIosRunnerOnClose: AppleRunnerClient['releaseIosRunnerOnClose'] =
client.releaseIosRunnerOnClose;
export const stopIosRunnerSession: AppleRunnerClient['stopIosRunnerSession'] =
Expand Down
2 changes: 1 addition & 1 deletion packages/platform-apple/src/runner-operations-facade.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
export {
applyXctestRunnerAppIconFromDerivedPath,
detachIosSimulatorRunnerSessionsForShutdown,
getRunnerSessionSnapshot,
hasLiveIosRunnerSession,
notifyIosRunnerAppRelaunched,
prepareIosRunner,
prewarmAppleRunnerCache,
prewarmIosRunnerSession,
readRunnerSessionLiveness,
readStaleRunnerLease,
releaseIosRunnerOnClose,
releaseSpeculativeIosRunnerSessionFor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ test('adoption succeeds for a live, matching, probe-healthy runner', async () =>

expect(session).not.toBeNull();
expect(session?.port).toBe(lease.port);
expect(session?.ready).toBe(true);
expect(session?.state).toBe('ready');
expect(session?.child.pid).toBe(424242);
expect(session?.sessionId).toBe(lease.sessionId);
expect(session?.xctestrunArtifact?.reason).toBe('adopted_from_lease');
Expand Down Expand Up @@ -252,7 +252,7 @@ test('adoption accepts a legacy lease whose live pid is runner-shaped', async ()

const session = await tryAdoptRunnerSessionFromLease(simulator, {});

expect(session?.ready).toBe(true);
expect(session?.state).toBe('ready');
expect(session?.child.pid).toBe(424242);
});

Expand Down
24 changes: 12 additions & 12 deletions packages/platform-apple/src/runner/__tests__/runner-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ test('parseRunnerResponse preserves runner unsupported-operation codes', async (
},
}),
);
const session = { ready: false };
const session = { state: 'starting' } as const;

await assert.rejects(
() => parseRunnerResponse(response, session, '/tmp/runner.log'),
Expand All @@ -523,7 +523,7 @@ test('parseRunnerResponse surfaces the keyboard-dismiss hint naming the occlusio
},
}),
);
const session = { ready: false };
const session = { state: 'starting' } as const;

await assert.rejects(
() => parseRunnerResponse(response, session, '/tmp/runner.log'),
Expand Down Expand Up @@ -552,7 +552,7 @@ test('parseRunnerResponse preserves iOS AX snapshot failure code and hint', asyn
},
}),
);
const session = { ready: true };
const session = { state: 'ready' } as const;

await assert.rejects(
() => parseRunnerResponse(response, session, '/tmp/runner.log'),
Expand Down Expand Up @@ -581,7 +581,7 @@ test('parseRunnerResponse preserves XCTest recorded failure code and hint', asyn
},
}),
);
const session = { ready: true };
const session = { state: 'ready' } as const;

await assert.rejects(
() => parseRunnerResponse(response, session, '/tmp/runner.log'),
Expand All @@ -608,7 +608,7 @@ test('parseRunnerResponse maps RUNNER_BUSY to retriable command failure', async
},
}),
);
const session = { ready: true };
const session = { state: 'ready' } as const;

await assert.rejects(
() => parseRunnerResponse(response, session, '/tmp/runner.log'),
Expand All @@ -635,7 +635,7 @@ test('parseRunnerResponse preserves RUNNER_WEDGED as a fatal runner code', async
},
}),
);
const session = { ready: true };
const session = { state: 'ready' } as const;

await assert.rejects(
() => parseRunnerResponse(response, session, '/tmp/runner.log'),
Expand Down Expand Up @@ -667,7 +667,7 @@ Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
},
}),
);
const session = { ready: true };
const session = { state: 'ready' } as const;

await assert.rejects(
() => parseRunnerResponse(response, session, logPath),
Expand Down Expand Up @@ -697,7 +697,7 @@ The application under test terminated unexpectedly.
},
}),
);
const session = { ready: true };
const session = { state: 'ready' } as const;

await assert.rejects(
() => parseRunnerResponse(response, session, logPath),
Expand Down Expand Up @@ -726,7 +726,7 @@ AGENT_DEVICE_RUNNER_COMMAND_FAILED command=snapshot error=fetch failed
},
}),
);
const session = { ready: true };
const session = { state: 'ready' } as const;

await assert.rejects(
() => parseRunnerResponse(response, session, logPath),
Expand Down Expand Up @@ -754,7 +754,7 @@ test('parseRunnerResponse hints when XCTest main-thread execution times out', as
},
}),
);
const session = { ready: true };
const session = { state: 'ready' } as const;

await assert.rejects(
() => parseRunnerResponse(response, session, logPath),
Expand Down Expand Up @@ -782,14 +782,14 @@ test('parseRunnerResponse emits diagnostics for runner gesture fallbacks', async
},
}),
);
const session = { ready: false };
const session = { state: 'starting' } as const;
const diagnosticEvents: DiagnosticEventInput[] = [];
appleRunnerTestHost.update({ emitDiagnostic: (event) => diagnosticEvents.push(event) });

const data = await parseRunnerResponse(response, session, '/tmp/runner.log');
assert.equal(data.gestureFallback, 'xctest-coordinate-drag');

assert.equal(session.ready, true);
assert.equal(session.state, 'ready');
const diagnostics = JSON.stringify(diagnosticEvents);
assert.match(diagnostics, /ios_runner_gesture_fallback/);
assert.match(diagnostics, /xctest-coordinate-drag/);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
abortAllIosRunnerSessions,
ensureRunnerSession,
executeRunnerCommandWithSession,
getRunnerSessionSnapshot,
readRunnerSessionLiveness,
releaseIosRunnerOnClose,
stopIosRunnerSession,
type RunnerSession,
Expand Down Expand Up @@ -195,7 +195,7 @@ test('a retained close over an idle runner keeps that runner warm for the next o
assert.deepEqual(events, ['release', 'released', 'alerts']);
assert.match(diagnostics, /"phase":"ios_runner_idle_stop_scheduled"/);
assert.doesNotMatch(diagnostics, /ios_runner_retain_skipped_busy/);
assert.equal(getRunnerSessionSnapshot(device.id)?.sessionId, session.sessionId);
assert.equal(readRunnerSessionLiveness(device.id)?.sessionId, session.sessionId);
assert.ok(runnerLeaseExists(device.id));
// The next open gets the same runner and launches nothing.
assert.equal((await ensureRunnerSession(device, {})).sessionId, session.sessionId);
Expand All @@ -216,7 +216,7 @@ test('a retained close disposes a runner still draining so the next open boots a
assert.deepEqual(events, ['release', 'released', 'alerts']);
assert.match(diagnostics, /"phase":"ios_runner_retain_skipped_busy"/);
assert.doesNotMatch(diagnostics, /"phase":"ios_runner_idle_stop_scheduled"/);
assert.equal(getRunnerSessionSnapshot(device.id), null);
assert.equal(readRunnerSessionLiveness(device.id), null);
assert.equal(runnerLeaseExists(device.id), false);
assert.notEqual((await ensureRunnerSession(device, {})).sessionId, session.sessionId);
assert.equal(mockRunCmdBackground.mock.calls.length, 2);
Expand All @@ -238,7 +238,7 @@ test('a non-retained close stops the runner and cancels the idle stop a retained

assert.match(diagnostics, /"phase":"ios_runner_idle_stop_scheduled"/);
assert.doesNotMatch(diagnostics, /"phase":"ios_runner_idle_stop"/);
assert.equal(getRunnerSessionSnapshot(device.id), null);
assert.equal(readRunnerSessionLiveness(device.id), null);
assert.equal(runnerLeaseExists(device.id), false);
});

Expand Down Expand Up @@ -267,7 +267,7 @@ test('a retained close with no runner in memory starts none and claims no lease
await lifecycle.finalizeApplicationClose(closeInput(true));

assert.deepEqual(events, ['release', 'released', 'alerts']);
assert.equal(getRunnerSessionSnapshot(device.id), null);
assert.equal(readRunnerSessionLiveness(device.id), null);
assert.equal(mockRunCmdBackground.mock.calls.length, 0);
assert.equal(runnerLeaseExists(device.id), false);
});
Expand All @@ -281,7 +281,7 @@ test('a daemon-shutdown close never issues the ordinary close release (#2615)',
await lifecycle.finalizeApplicationClose({ ...closeInput(true), daemonShutdown: true });

assert.deepEqual(events, ['alerts']);
assert.equal(getRunnerSessionSnapshot(device.id)?.sessionId, session.sessionId);
assert.equal(readRunnerSessionLiveness(device.id)?.sessionId, session.sessionId);
assert.ok(runnerLeaseExists(device.id));
});

Expand Down Expand Up @@ -331,7 +331,7 @@ test('a drain that lands after close is issued cannot return a busy runner to re
assert.equal(session.runnerMainThreadBusy, false);
assert.match(diagnostics, /"phase":"ios_runner_retain_skipped_busy"/);
assert.doesNotMatch(diagnostics, /"phase":"ios_runner_idle_stop_scheduled"/);
assert.equal(getRunnerSessionSnapshot(device.id), null);
assert.equal(readRunnerSessionLiveness(device.id), null);
});

/** The close path's Apple tools, composed exactly as the root's lazy tools compose them. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function makeRunnerSession(port: number): RunnerSession {
jsonPath: '/tmp/fake.json',
testPromise: new Promise<ExecResult>(() => {}),
child: { pid: process.pid, exitCode: null },
ready: true,
state: 'ready',
};
}

Expand Down
Loading
Loading