|
| 1 | +#!/usr/bin/env bash |
| 2 | +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. |
| 3 | +# SPDX-License-Identifier: Apache-2.0 |
| 4 | + |
| 5 | +set -euo pipefail |
| 6 | + |
| 7 | +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" |
| 8 | +WORK="$(mktemp -d)" |
| 9 | +trap 'rm -rf "${WORK}"' EXIT |
| 10 | + |
| 11 | +# Exercise the real entrypoint and its recursive invocation without a cluster, |
| 12 | +# Rust builds, or writes to the checkout's results directory. |
| 13 | +export REPORT_TEST_ROOT="${WORK}/repo" |
| 14 | +mkdir -p "${REPORT_TEST_ROOT}/e2e/rust" "${REPORT_TEST_ROOT}/e2e/support" "${WORK}/bin" |
| 15 | +cp "${ROOT}/e2e/rust/e2e-kubernetes.sh" "${REPORT_TEST_ROOT}/e2e/rust/" |
| 16 | +cp "${ROOT}/e2e/support/conformance.sh" "${REPORT_TEST_ROOT}/e2e/support/" |
| 17 | + |
| 18 | +cat >"${REPORT_TEST_ROOT}/e2e/with-kube-gateway.sh" <<'EOF' |
| 19 | +#!/usr/bin/env bash |
| 20 | +set -euo pipefail |
| 21 | +echo "gateway ${OPENSHELL_E2E_CREDENTIAL_DRIVER:-default}" >>"${REPORT_TEST_ROOT}/calls" |
| 22 | +if [ "${REPORT_TEST_GATEWAY_STATUS}" != 0 ]; then |
| 23 | + exit "${REPORT_TEST_GATEWAY_STATUS}" |
| 24 | +fi |
| 25 | +"$@" |
| 26 | +EOF |
| 27 | + |
| 28 | +cat >"${WORK}/bin/cargo" <<'EOF' |
| 29 | +#!/usr/bin/env bash |
| 30 | +set -euo pipefail |
| 31 | +echo "$1 ${OPENSHELL_E2E_CREDENTIAL_DRIVER:-default}" >>"${REPORT_TEST_ROOT}/calls" |
| 32 | +case "$1" in |
| 33 | + test) exit 0 ;; |
| 34 | + nextest) |
| 35 | + if [ "${OPENSHELL_E2E_CREDENTIAL_DRIVER:-default}" != "${REPORT_TEST_NO_XML_DRIVER}" ]; then |
| 36 | + printf '<testsuite name="fresh-%s"/>\n' "${OPENSHELL_E2E_CREDENTIAL_DRIVER:-default}" \ |
| 37 | + >"${REPORT_TEST_ROOT}/results/e2e-kubernetes.xml" |
| 38 | + fi |
| 39 | + exit "${REPORT_TEST_NEXTEST_STATUS}" |
| 40 | + ;; |
| 41 | + *) echo "unexpected cargo command: $*" >&2; exit 99 ;; |
| 42 | +esac |
| 43 | +EOF |
| 44 | + |
| 45 | +cat >"${WORK}/bin/xsltproc" <<'EOF' |
| 46 | +#!/usr/bin/env bash |
| 47 | +set -euo pipefail |
| 48 | +echo "render $3" >>"${REPORT_TEST_ROOT}/calls" |
| 49 | +printf '<html><title>%s</title>\n' "$3" |
| 50 | +cat "$5" |
| 51 | +echo '</html>' |
| 52 | +EOF |
| 53 | + |
| 54 | +cat >"${WORK}/bin/mv" <<'EOF' |
| 55 | +#!/usr/bin/env bash |
| 56 | +set -euo pipefail |
| 57 | +if [ "${REPORT_TEST_MOVE_FAIL}" = 1 ]; then |
| 58 | + exit 13 |
| 59 | +fi |
| 60 | +exec /bin/mv "$@" |
| 61 | +EOF |
| 62 | +chmod +x "${REPORT_TEST_ROOT}/e2e/with-kube-gateway.sh" "${WORK}/bin/"* |
| 63 | + |
| 64 | +export PATH="${WORK}/bin:${PATH}" |
| 65 | +export OPENSHELL_BIN="${WORK}/bin/openshell" |
| 66 | +cp /usr/bin/true "${OPENSHELL_BIN}" |
| 67 | + |
| 68 | +fail() { |
| 69 | + echo "FAIL: $*" >&2 |
| 70 | + cat "${REPORT_TEST_ROOT}/output" >&2 |
| 71 | + exit 1 |
| 72 | +} |
| 73 | + |
| 74 | +reset_case() { |
| 75 | + rm -rf "${REPORT_TEST_ROOT}/results" |
| 76 | + mkdir "${REPORT_TEST_ROOT}/results" |
| 77 | + : >"${REPORT_TEST_ROOT}/calls" |
| 78 | + : >"${REPORT_TEST_ROOT}/output" |
| 79 | + export OPENSHELL_E2E_KUBERNETES_FEATURES=e2e |
| 80 | + export OPENSHELL_E2E_REPORT_NAME=e2e-kubernetes |
| 81 | + export OPENSHELL_E2E_CREDENTIAL_DRIVERS=0 |
| 82 | + export OPENSHELL_E2E_CREDENTIAL_DRIVER="" |
| 83 | + export REPORT_TEST_GATEWAY_STATUS=0 |
| 84 | + export REPORT_TEST_NEXTEST_STATUS=0 |
| 85 | + export REPORT_TEST_NO_XML_DRIVER="" |
| 86 | + export REPORT_TEST_MOVE_FAIL=0 |
| 87 | +} |
| 88 | + |
| 89 | +seed_stale_reports() { |
| 90 | + local name |
| 91 | + for name in e2e-kubernetes "${OPENSHELL_E2E_REPORT_NAME}"; do |
| 92 | + echo '<testsuite name="stale"/>' >"${REPORT_TEST_ROOT}/results/${name}.xml" |
| 93 | + echo 'stale HTML' >"${REPORT_TEST_ROOT}/results/${name}.html" |
| 94 | + done |
| 95 | + echo 'unrelated report' >"${REPORT_TEST_ROOT}/results/unrelated.xml" |
| 96 | + echo 'unrelated HTML' >"${REPORT_TEST_ROOT}/results/unrelated.html" |
| 97 | +} |
| 98 | + |
| 99 | +run_wrapper() { |
| 100 | + local expected=$1 status=0 |
| 101 | + bash "${REPORT_TEST_ROOT}/e2e/rust/e2e-kubernetes.sh" \ |
| 102 | + >"${REPORT_TEST_ROOT}/output" 2>&1 || status=$? |
| 103 | + [ "${status}" = "${expected}" ] || fail "expected status ${expected}, got ${status}" |
| 104 | + [ "$(cat "${REPORT_TEST_ROOT}/results/unrelated.xml")" = 'unrelated report' ] \ |
| 105 | + || fail 'modified an unrelated XML report' |
| 106 | + [ "$(cat "${REPORT_TEST_ROOT}/results/unrelated.html")" = 'unrelated HTML' ] \ |
| 107 | + || fail 'modified an unrelated HTML report' |
| 108 | +} |
| 109 | + |
| 110 | +assert_absent() { |
| 111 | + [ ! -e "${REPORT_TEST_ROOT}/results/$1" ] || fail "unexpected report: $1" |
| 112 | +} |
| 113 | + |
| 114 | +assert_no_render() { |
| 115 | + if grep -q '^render ' "${REPORT_TEST_ROOT}/calls"; then |
| 116 | + fail 'rendered XML when none was produced' |
| 117 | + fi |
| 118 | +} |
| 119 | + |
| 120 | +# Reproduction for #3668: conformance-only skips Nextest even with stale default |
| 121 | +# XML and a stale destination report. Cover both default and custom names. |
| 122 | +for name in e2e-kubernetes custom; do |
| 123 | + reset_case |
| 124 | + export OPENSHELL_E2E_REPORT_NAME="${name}" |
| 125 | + export OPENSHELL_E2E_KUBERNETES_FEATURES=e2e-conformance-only |
| 126 | + seed_stale_reports |
| 127 | + run_wrapper 0 |
| 128 | + assert_absent e2e-kubernetes.xml |
| 129 | + assert_absent "${name}.xml" |
| 130 | + assert_absent "${name}.html" |
| 131 | + grep -q '^test ' "${REPORT_TEST_ROOT}/calls" || fail 'did not run conformance' |
| 132 | + if grep -q '^nextest ' "${REPORT_TEST_ROOT}/calls"; then |
| 133 | + fail 'conformance-only unexpectedly ran Nextest' |
| 134 | + fi |
| 135 | + assert_no_render |
| 136 | +done |
| 137 | + |
| 138 | +# Setup failures must not publish stale reports or lose their exit status. |
| 139 | +for name in e2e-kubernetes custom; do |
| 140 | + reset_case |
| 141 | + export OPENSHELL_E2E_REPORT_NAME="${name}" |
| 142 | + export REPORT_TEST_GATEWAY_STATUS=17 |
| 143 | + seed_stale_reports |
| 144 | + run_wrapper 17 |
| 145 | + assert_absent e2e-kubernetes.xml |
| 146 | + assert_absent "${name}.xml" |
| 147 | + assert_absent "${name}.html" |
| 148 | + assert_no_render |
| 149 | +done |
| 150 | + |
| 151 | +# Fresh output is rendered even when Nextest fails, with the selected title. |
| 152 | +for name in e2e-kubernetes custom; do |
| 153 | + for status in 0 100; do |
| 154 | + reset_case |
| 155 | + export OPENSHELL_E2E_REPORT_NAME="${name}" |
| 156 | + export REPORT_TEST_NEXTEST_STATUS="${status}" |
| 157 | + seed_stale_reports |
| 158 | + run_wrapper "${status}" |
| 159 | + grep -q 'fresh-default' "${REPORT_TEST_ROOT}/results/${name}.xml" || fail 'missing fresh XML' |
| 160 | + grep -q 'fresh-default' "${REPORT_TEST_ROOT}/results/${name}.html" || fail 'missing fresh HTML' |
| 161 | + grep -Fq "<title>${name}</title>" "${REPORT_TEST_ROOT}/results/${name}.html" || fail 'incorrect title' |
| 162 | + if [ "${name}" != e2e-kubernetes ]; then |
| 163 | + assert_absent e2e-kubernetes.xml |
| 164 | + fi |
| 165 | + done |
| 166 | +done |
| 167 | + |
| 168 | +# A failed rename must not fall through to rendering the destination. |
| 169 | +for status in 0 100; do |
| 170 | + reset_case |
| 171 | + export OPENSHELL_E2E_REPORT_NAME=custom |
| 172 | + export REPORT_TEST_MOVE_FAIL=1 |
| 173 | + export REPORT_TEST_NEXTEST_STATUS="${status}" |
| 174 | + seed_stale_reports |
| 175 | + run_wrapper "${status}" |
| 176 | + assert_absent custom.xml |
| 177 | + assert_absent custom.html |
| 178 | + assert_no_render |
| 179 | + grep -q 'WARNING:.*report' "${REPORT_TEST_ROOT}/output" || fail 'missing rename warning' |
| 180 | +done |
| 181 | + |
| 182 | +# Cleanup errors must stop the run before starting the gateway. |
| 183 | +reset_case |
| 184 | +seed_stale_reports |
| 185 | +rm "${REPORT_TEST_ROOT}/results/e2e-kubernetes.xml" |
| 186 | +mkdir "${REPORT_TEST_ROOT}/results/e2e-kubernetes.xml" |
| 187 | +run_wrapper 1 |
| 188 | +[ ! -s "${REPORT_TEST_ROOT}/calls" ] || fail 'started a run after cleanup failed' |
| 189 | + |
| 190 | +# A later credential-driver invocation that emits no XML must not reuse its |
| 191 | +# predecessor's report, or an older report under its own name. |
| 192 | +reset_case |
| 193 | +export OPENSHELL_E2E_CREDENTIAL_DRIVERS=1 |
| 194 | +export REPORT_TEST_NO_XML_DRIVER=vault |
| 195 | +seed_stale_reports |
| 196 | +echo '<testsuite name="stale-vault"/>' >"${REPORT_TEST_ROOT}/results/e2e-kubernetes-vault.xml" |
| 197 | +echo 'stale vault HTML' >"${REPORT_TEST_ROOT}/results/e2e-kubernetes-vault.html" |
| 198 | +run_wrapper 0 |
| 199 | +grep -q 'fresh-kubernetes-secrets' "${REPORT_TEST_ROOT}/results/e2e-kubernetes-secrets.xml" \ |
| 200 | + || fail 'missing first credential-driver XML' |
| 201 | +grep -q 'fresh-kubernetes-secrets' "${REPORT_TEST_ROOT}/results/e2e-kubernetes-secrets.html" \ |
| 202 | + || fail 'missing first credential-driver HTML' |
| 203 | +grep -q '^nextest vault$' "${REPORT_TEST_ROOT}/calls" || fail 'did not run the second driver' |
| 204 | +assert_absent e2e-kubernetes.xml |
| 205 | +assert_absent e2e-kubernetes-vault.xml |
| 206 | +assert_absent e2e-kubernetes-vault.html |
| 207 | +if grep -q '^render e2e-kubernetes-vault$' "${REPORT_TEST_ROOT}/calls"; then |
| 208 | + fail 'rendered a stale credential-driver report' |
| 209 | +fi |
| 210 | + |
| 211 | +echo 'Kubernetes E2E report tests passed' |
0 commit comments