diff --git a/test/e2e-scenario/framework-tests/e2e-lib-helpers.test.ts b/test/e2e-scenario/framework-tests/e2e-lib-helpers.test.ts index e68eaff830..83d8ef741e 100644 --- a/test/e2e-scenario/framework-tests/e2e-lib-helpers.test.ts +++ b/test/e2e-scenario/framework-tests/e2e-lib-helpers.test.ts @@ -375,37 +375,6 @@ exit 0 expect(r.stdout).toContain("DEBIAN_FRONTEND=noninteractive"); }); - it("artifact_helper_should_collect_known_logs_without_failing_when_missing", () => { - const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "e2e-art-")); - const srcDir = path.join(tmp, "src"); - const dstDir = path.join(tmp, "out"); - fs.mkdirSync(srcDir); - fs.writeFileSync(path.join(srcDir, "present.log"), "hello\n"); - const r = runBash(` - set -euo pipefail - . "${RUNTIME_LIB}/artifacts.sh" - e2e_artifact_collect_file "${srcDir}/present.log" "${dstDir}/present.log" - e2e_artifact_collect_file "${srcDir}/missing.log" "${dstDir}/missing.log" || true - ls "${dstDir}" - `); - expect(r.status, r.stderr).toBe(0); - expect(fs.existsSync(path.join(dstDir, "present.log"))).toBe(true); - expect(fs.existsSync(path.join(dstDir, "missing.log"))).toBe(false); - expect(r.stderr + r.stdout).toMatch(/missing\.log|not found|skipping/i); - fs.rmSync(tmp, { recursive: true, force: true }); - }); - - it("gateway_helper_should_report_unhealthy_gateway_clearly", () => { - // Pick a port very unlikely to be bound. - const r = runBash(` - set -euo pipefail - . "${RUNTIME_LIB}/gateway.sh" - e2e_gateway_assert_healthy "http://127.0.0.1:65531" - `); - expect(r.status).not.toBe(0); - expect(r.stderr).toMatch(/65531|gateway|unhealthy/i); - }); - it("sandbox_helper_should_fail_for_missing_sandbox_name", () => { const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "e2e-sb-")); try { @@ -846,16 +815,13 @@ describe("Phase 1.C fixtures", () => { }); it("older_base_image_should_emit_dockerfile_pointing_at_tagged_base", () => { - const r = runBash( - ` + const r = runBash(` set -euo pipefail . "${FIXTURES}/older-base-image.sh" df="$(older_base_image_prepare v0.0.1-test)" echo "DF=$df" head -n1 "$df" - `, - { E2E_DRY_RUN: "1" }, - ); + `); expect(r.status, r.stderr).toBe(0); expect(r.stdout).toMatch(/^FROM .*:v0\.0\.1-test/m); }); diff --git a/test/e2e-scenario/nemoclaw_scenarios/probes/sandbox-absent.sh b/test/e2e-scenario/nemoclaw_scenarios/probes/sandbox-absent.sh index 5f08e39df0..dae814f8ee 100755 --- a/test/e2e-scenario/nemoclaw_scenarios/probes/sandbox-absent.sh +++ b/test/e2e-scenario/nemoclaw_scenarios/probes/sandbox-absent.sh @@ -6,9 +6,7 @@ # # Negative-state probe. Asserts that no sandbox was created by a # scenario whose expected_state declares sandbox.expected=absent -# (preflight failure, onboarding failures). Typed replacement for -# the legacy run-scenario.sh inline check -# `openshell sandbox list | grep -Fq "${sandbox_name}"`. +# (preflight failure, onboarding failures). set -euo pipefail diff --git a/test/e2e-scenario/runtime/lib/artifacts.sh b/test/e2e-scenario/runtime/lib/artifacts.sh deleted file mode 100755 index 761e618d0a..0000000000 --- a/test/e2e-scenario/runtime/lib/artifacts.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 -# -# Artifact collection helpers. Designed to be called from failure traps. -# All helpers are best-effort: missing sources are logged but do not abort. - -_E2E_ART_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -# e2e_artifact_collect_file -# Copies a single file. Returns 0 on success or when src is missing. -e2e_artifact_collect_file() { - local src="${1:-}" - local dst="${2:-}" - if [[ -z "${src}" || -z "${dst}" ]]; then - echo "e2e_artifact_collect_file: missing src or dst" >&2 - return 2 - fi - if [[ ! -f "${src}" ]]; then - echo "e2e_artifact_collect_file: ${src} not found, skipping" >&2 - return 0 - fi - mkdir -p "$(dirname "${dst}")" - cp -f "${src}" "${dst}" -} - -# e2e_artifact_collect_dir -# Recursively copies a directory. No-op if missing. -e2e_artifact_collect_dir() { - local src="${1:-}" - local dst="${2:-}" - if [[ ! -d "${src}" ]]; then - echo "e2e_artifact_collect_dir: ${src} not found, skipping" >&2 - return 0 - fi - mkdir -p "${dst}" - cp -rf "${src}/." "${dst}/" -} - -# e2e_artifact_preserve_exit -# Intended for failure traps. Collects artifacts (caller-defined function -# `_e2e_collect_artifacts` if present) but always returns the provided exit -# code so it can be passed to `exit`. -e2e_artifact_preserve_exit() { - local rc="${1:-1}" - if declare -F _e2e_collect_artifacts >/dev/null 2>&1; then - _e2e_collect_artifacts || true - fi - return "${rc}" -} diff --git a/test/e2e-scenario/runtime/lib/cleanup.sh b/test/e2e-scenario/runtime/lib/cleanup.sh deleted file mode 100755 index 8581e3c9e0..0000000000 --- a/test/e2e-scenario/runtime/lib/cleanup.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 -# -# Cleanup helpers. Wraps the existing sandbox-teardown.sh so scenario code -# gets a single, discoverable entrypoint. - -_E2E_CLEAN_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -# shellcheck source=sandbox-teardown.sh -. "${_E2E_CLEAN_LIB_DIR}/sandbox-teardown.sh" -# shellcheck source=context.sh -. "${_E2E_CLEAN_LIB_DIR}/context.sh" -# shellcheck source=env.sh -. "${_E2E_CLEAN_LIB_DIR}/env.sh" - -# e2e_cleanup_register_sandbox [name] -# Default to E2E_SANDBOX_NAME from context. -e2e_cleanup_register_sandbox() { - local name="${1:-}" - if [[ -z "${name}" ]]; then - name="$(e2e_context_get E2E_SANDBOX_NAME)" - fi - if [[ -z "${name}" ]]; then - echo "e2e_cleanup_register_sandbox: no sandbox name to register" >&2 - return 0 - fi - register_sandbox_for_teardown "${name}" -} diff --git a/test/e2e-scenario/runtime/lib/negative.sh b/test/e2e-scenario/runtime/lib/negative.sh deleted file mode 100755 index 95de65808d..0000000000 --- a/test/e2e-scenario/runtime/lib/negative.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -# Helpers for expected-failure E2E flows. - -e2e_negative_output_has_stack_trace() { - local output="$1" - printf '%s\n' "${output}" | grep -Eq '(^|[[:space:]])(TypeError|ReferenceError|SyntaxError):|^[[:space:]]+at ' -} - -e2e_negative_assert_failure() { - local log_file="$1" - local actual_exit="$2" - local expected_exit="$3" - local message_contains="$4" - local no_stack_trace="${5:-0}" - - if [[ "${actual_exit}" -ne "${expected_exit}" ]]; then - echo "expected failure exit ${expected_exit}, got ${actual_exit}" >&2 - cat "${log_file}" >&2 - return 1 - fi - if [[ -n "${message_contains}" ]] && ! grep -Fq "${message_contains}" "${log_file}"; then - echo "expected failure output to contain: ${message_contains}" >&2 - cat "${log_file}" >&2 - return 1 - fi - if [[ "${no_stack_trace}" == "1" ]] && e2e_negative_output_has_stack_trace "$(cat "${log_file}")"; then - echo "expected failure output not to contain a JavaScript stack trace" >&2 - cat "${log_file}" >&2 - return 1 - fi -} diff --git a/test/e2e-scenario/runtime/lib/port-holder.sh b/test/e2e-scenario/runtime/lib/port-holder.sh deleted file mode 100755 index cbffcd275a..0000000000 --- a/test/e2e-scenario/runtime/lib/port-holder.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env bash -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -# Local TCP listener helper for deterministic gateway port-conflict tests. - -E2E_PORT_HOLDER_PID="${E2E_PORT_HOLDER_PID:-}" - -e2e_port_holder_start() { - local port="$1" - if [[ -n "${E2E_PORT_HOLDER_PID}" ]]; then - e2e_port_holder_stop - fi - E2E_PORT_HOLDER_PID="" - node - "${port}" <<'NODE' >/tmp/nemoclaw-e2e-port-holder.log 2>&1 & -const net = require("node:net"); -const port = Number(process.argv[2]); -const server = net.createServer((socket) => socket.end()); -server.on("error", (err) => { - console.error(err && err.message ? err.message : err); - process.exit(2); -}); -server.listen(port, "127.0.0.1", () => { - console.log("ready"); -}); -setInterval(() => {}, 1000); -NODE - E2E_PORT_HOLDER_PID=$! - local _i - for _i in $(seq 1 40); do - if node -e 'const net=require("node:net"); const port=Number(process.argv[1]); const s=net.connect(port,"127.0.0.1"); s.once("connect",()=>{s.destroy(); process.exit(0);}); s.once("error",()=>process.exit(1)); setTimeout(()=>process.exit(1),250);' "${port}" >/dev/null 2>&1; then - return 0 - fi - if ! kill -0 "${E2E_PORT_HOLDER_PID}" >/dev/null 2>&1; then - E2E_PORT_HOLDER_PID="" - return 1 - fi - sleep 0.25 - done - if [[ -n "${E2E_PORT_HOLDER_PID}" ]]; then - kill "${E2E_PORT_HOLDER_PID}" >/dev/null 2>&1 || true - wait "${E2E_PORT_HOLDER_PID}" >/dev/null 2>&1 || true - E2E_PORT_HOLDER_PID="" - fi - return 1 -} - -e2e_port_holder_stop() { - if [[ -n "${E2E_PORT_HOLDER_PID}" ]]; then - kill "${E2E_PORT_HOLDER_PID}" >/dev/null 2>&1 || true - wait "${E2E_PORT_HOLDER_PID}" >/dev/null 2>&1 || true - E2E_PORT_HOLDER_PID="" - fi -} diff --git a/test/e2e-scenario/runtime/run-scenario.sh b/test/e2e-scenario/runtime/run-scenario.sh deleted file mode 100755 index 2477ce79ec..0000000000 --- a/test/e2e-scenario/runtime/run-scenario.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 -# -# DEPRECATED. The hybrid scenario architecture has a single supported runtime -# entrypoint: test/e2e-scenario/scenarios/run.ts. This bash runner duplicated -# install/onboard/gateway-check/suite-execution that now belongs in TS phase -# orchestrators (EnvironmentOrchestrator, OnboardingOrchestrator, -# RuntimeOrchestrator) and shared clients (HostCliClient, GatewayClient, -# SandboxClient). It is fail-fast so the deprecation is loud, not silent. - -set -euo pipefail - -cat >&2 <<'MSG' -run-scenario.sh is deprecated. Use the TS runner instead: - - npx tsx test/e2e-scenario/scenarios/run.ts --scenarios - -Other run.ts modes (read-only): - --list List canonical scenario ids - --emit-matrix Emit GitHub Actions matrix payload from the registry - --plan-only Local debug: print the compiled plan, do not execute - (must NOT appear in any CI workflow) -MSG -exit 2 diff --git a/test/e2e-scenario/runtime/run-suites.sh b/test/e2e-scenario/runtime/run-suites.sh deleted file mode 100755 index dac69cd422..0000000000 --- a/test/e2e-scenario/runtime/run-suites.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 -# -# DEPRECATED. Suite execution is now driven directly by the TS phase -# orchestrator (RuntimeOrchestrator -> PhaseOrchestrator.runShellStep) which -# spawns each migrated assertion step's implementation.ref shell script. -# There is no longer a YAML-walking bash suite runner. - -set -euo pipefail - -cat >&2 <<'MSG' -run-suites.sh is deprecated. Suite assertions are now executed by -test/e2e-scenario/scenarios/orchestrators/phase.ts via child_process.spawn, -walking the typed assertionGroups defined in the scenario registry. - -Run scenarios via: - - npx tsx test/e2e-scenario/scenarios/run.ts --scenarios -MSG -exit 2