From d4c93661666834942ec1927af0d3eeccf8973731 Mon Sep 17 00:00:00 2001 From: Amaad Martin Date: Wed, 29 Jul 2026 11:11:27 -0700 Subject: [PATCH 1/2] test(integration): attribute cold AgentLoader discovery cost to beforeAll The discovery test in app_loader_test.ts intermittently timed out at 40s on the macos-latest CI leg. AgentLoader discovery is lazy: the constructor does no work, so the first listApps() call in the test body paid for four concurrent esbuild bundle-and-minify passes over the whole ADK dependency graph. The cost belonged to setup, not to an assertion. Warm the loader with preloadAgents() in the discovery beforeAll, and give the four install/IO-bound fixture hooks their own FIXTURE_SETUP_TIMEOUT budget. Every it() keeps the existing 40s TEST_EXECUTION_TIMEOUT, so a discovery assertion that ever needs more than that still fails loudly. --- .../integration/app_loader/app_loader_test.ts | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/integration/app_loader/app_loader_test.ts b/tests/integration/app_loader/app_loader_test.ts index 4367307b8..703a2152a 100644 --- a/tests/integration/app_loader/app_loader_test.ts +++ b/tests/integration/app_loader/app_loader_test.ts @@ -16,6 +16,15 @@ import {sendInput} from '../test_case_utils.js'; const execAsync = promisify(exec); const dirname = process.cwd(); const TEST_EXECUTION_TIMEOUT = 40000; +/** + * Budget for fixture hooks rather than assertions. These hooks shell out to + * `npm install`, warm the AgentLoader (which esbuild-bundles and minifies every + * fixture entrypoint against the whole ADK dependency graph), and recursively + * delete a fixture `node_modules` tree. That work is install- and IO-bound and + * is several times slower on a cold macOS CI runner than the assertions it sets + * up, so it gets its own ceiling. + */ +const FIXTURE_SETUP_TIMEOUT = 180000; describe('App loader CLI integration', () => { describe.each(['app_ts', 'app_js', 'app_default'])( @@ -29,7 +38,7 @@ describe('App loader CLI integration', () => { beforeAll(async () => { await execAsync('npm install', {cwd: projectPath}); - }, TEST_EXECUTION_TIMEOUT); + }, FIXTURE_SETUP_TIMEOUT); it( 'should run app via package.json start script and get responses', @@ -62,7 +71,7 @@ describe('App loader CLI integration', () => { await fs .unlink(path.join(projectPath, 'package-lock.json')) .catch(() => {}); - }, TEST_EXECUTION_TIMEOUT); + }, FIXTURE_SETUP_TIMEOUT); }, ); }); @@ -77,7 +86,11 @@ describe('AgentLoader discovery and loading integration', () => { beforeAll(async () => { await execAsync('npm install', {cwd: projectPath}); loader = new AgentLoader(projectPath); - }, TEST_EXECUTION_TIMEOUT); + // Discovery is lazy: the first listApps()/listAgents() call esbuild-bundles + // every fixture entrypoint. Warm it here so that one-time cost is charged + // to setup instead of to whichever test happens to run first. + await loader.preloadAgents(); + }, FIXTURE_SETUP_TIMEOUT); it( 'should discover apps vs agents across directories and standalone files', @@ -138,5 +151,5 @@ describe('AgentLoader discovery and loading integration', () => { await fs .unlink(path.join(projectPath, 'package-lock.json')) .catch(() => {}); - }, TEST_EXECUTION_TIMEOUT); + }, FIXTURE_SETUP_TIMEOUT); }); From 1eca3e0dd71e66b7f8017d97f86610dab812cc03 Mon Sep 17 00:00:00 2001 From: Amaad Martin Date: Wed, 29 Jul 2026 11:45:01 -0700 Subject: [PATCH 2/2] test(integration): condense fixture-timeout comments Address simplicity review: the rationale for FIXTURE_SETUP_TIMEOUT was 8 lines of prose for a one-line constant, and it described the loader warm-up that only one of the five hooks performs. Keep that detail at the call site where it applies and state the budget's rationale in one sentence. --- tests/integration/app_loader/app_loader_test.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/tests/integration/app_loader/app_loader_test.ts b/tests/integration/app_loader/app_loader_test.ts index 703a2152a..a6fb4332c 100644 --- a/tests/integration/app_loader/app_loader_test.ts +++ b/tests/integration/app_loader/app_loader_test.ts @@ -16,14 +16,9 @@ import {sendInput} from '../test_case_utils.js'; const execAsync = promisify(exec); const dirname = process.cwd(); const TEST_EXECUTION_TIMEOUT = 40000; -/** - * Budget for fixture hooks rather than assertions. These hooks shell out to - * `npm install`, warm the AgentLoader (which esbuild-bundles and minifies every - * fixture entrypoint against the whole ADK dependency graph), and recursively - * delete a fixture `node_modules` tree. That work is install- and IO-bound and - * is several times slower on a cold macOS CI runner than the assertions it sets - * up, so it gets its own ceiling. - */ +// Fixture hooks shell out to `npm install` and recursively delete node_modules. +// That install/IO-bound work is far slower on a cold macOS CI runner than the +// assertions it sets up, so it gets its own ceiling. const FIXTURE_SETUP_TIMEOUT = 180000; describe('App loader CLI integration', () => { @@ -86,9 +81,8 @@ describe('AgentLoader discovery and loading integration', () => { beforeAll(async () => { await execAsync('npm install', {cwd: projectPath}); loader = new AgentLoader(projectPath); - // Discovery is lazy: the first listApps()/listAgents() call esbuild-bundles - // every fixture entrypoint. Warm it here so that one-time cost is charged - // to setup instead of to whichever test happens to run first. + // Discovery is lazy; warm it here so the one-time bundling cost is charged + // to setup rather than to whichever test runs first. await loader.preloadAgents(); }, FIXTURE_SETUP_TIMEOUT);