Skip to content

Commit e55d76d

Browse files
prekshivyascv
andauthored
test(e2e): wait for portable gateway serve record (#9379)
<!-- markdownlint-disable MD041 --> ## Summary An injected gateway record failure can return before the asynchronous gateway process records its `serve` command. The regression test now waits for that required command. It still validates the launch-record PID, active process, and cleanup behavior. ## Related Issue Related to #9208. ## Changes - Use bounded Vitest polling for the expected `generate-certs` and `serve` sequence. - Keep the launch-record PID, active-process, and cleanup assertions after the command sequence appears. ## Type of Change - [x] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates - [x] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [ ] Tests not applicable — justification: - [ ] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [ ] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## DGX Station Hardware Evidence - [ ] Tested on DGX Station - Tested commit: - Station profile/scenario: - Result: - Supporting evidence: ## Verification - [x] PR description includes a `Signed-off-by:` line and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run validate:pr` passed after refreshing `origin/main` when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: `npx vitest run --project e2e-support test/e2e/support/portable-profile-systemctl-shim.test.ts --reporter=verbose` passed 36/36 on `f33c18283`. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) - [ ] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) --- Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved reliability when handling gateway cleanup failures by ensuring required activity is recorded before results are validated. * **Tests** * Increased stability across gateway startup, cleanup-failure, and launch-failure scenarios. * Added consistent waiting and log verification to reduce timing-related test failures and produce more dependable validation results. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com> Co-authored-by: Carlos Villela <cvillela@nvidia.com>
1 parent b715fc7 commit e55d76d

1 file changed

Lines changed: 22 additions & 18 deletions

File tree

test/e2e/support/portable-profile-systemctl-shim.test.ts

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,25 @@ async function waitForFileText(filePath: string, text: string): Promise<void> {
360360
});
361361
}
362362

363+
function readGatewayCommands(scope: FixtureScope): Record<string, unknown>[] {
364+
return fs
365+
.readFileSync(scope.gatewayCommandLog, "utf8")
366+
.trim()
367+
.split("\n")
368+
.map((line) => JSON.parse(line) as Record<string, unknown>);
369+
}
370+
371+
async function waitForGatewayCommands(
372+
scope: FixtureScope,
373+
expectedKinds: string[],
374+
): Promise<Record<string, unknown>[]> {
375+
return vi.waitFor(() => {
376+
const commands = readGatewayCommands(scope);
377+
expect(commands.map((command) => command.kind)).toEqual(expectedKinds);
378+
return commands;
379+
}, { timeout: 5_000 });
380+
}
381+
363382
function pidIsActive(pid: number): boolean {
364383
try {
365384
process.kill(pid, 0);
@@ -655,12 +674,7 @@ describe("portable profile systemctl fixture", () => {
655674
expect(activeIdentity.stdout).toContain("ActiveState=active\n");
656675
expect(activeIdentity.stdout).toContain(`MainPID=${String(gatewayProcess.pid)}\n`);
657676

658-
const commands = fs
659-
.readFileSync(scope.gatewayCommandLog, "utf8")
660-
.trim()
661-
.split("\n")
662-
.map((line) => JSON.parse(line) as Record<string, unknown>);
663-
expect(commands.map((command) => command.kind)).toEqual(["generate-certs", "serve"]);
677+
const commands = await waitForGatewayCommands(scope, ["generate-certs", "serve"]);
664678
expect(commands[0]).toMatchObject({
665679
args: [
666680
"generate-certs",
@@ -747,12 +761,7 @@ describe("portable profile systemctl fixture", () => {
747761
);
748762
expect(fs.existsSync(scope.gatewayPidFile)).toBe(false);
749763
expect(fs.existsSync(gatewayLaunchPidFile)).toBe(true);
750-
const commands = fs
751-
.readFileSync(scope.gatewayCommandLog, "utf8")
752-
.trim()
753-
.split("\n")
754-
.map((line) => JSON.parse(line) as Record<string, unknown>);
755-
expect(commands.map((command) => command.kind)).toEqual(["generate-certs", "serve"]);
764+
const commands = await waitForGatewayCommands(scope, ["generate-certs", "serve"]);
756765
const gatewayPid = commands[1]!.pid as number;
757766
expect(readFixtureProcessRecord(gatewayLaunchPidFile).pid).toBe(gatewayPid);
758767
expect(pidIsActive(gatewayPid)).toBe(true);
@@ -805,12 +814,7 @@ describe("portable profile systemctl fixture", () => {
805814
expect(launchedPid).not.toBeNull();
806815
const gatewayPid = Number(launchedPid![1]);
807816
await vi.waitFor(() => expect(pidIsActive(gatewayPid)).toBe(false));
808-
const commands = fs
809-
.readFileSync(scope.gatewayCommandLog, "utf8")
810-
.trim()
811-
.split("\n")
812-
.map((line) => JSON.parse(line) as Record<string, unknown>);
813-
expect(commands.map((command) => command.kind)).toEqual(["generate-certs"]);
817+
await waitForGatewayCommands(scope, ["generate-certs"]);
814818
} finally {
815819
await cleanFixture(scope);
816820
}

0 commit comments

Comments
 (0)