소스 검색

test: restructure container smoke tests for interactive use

Replaces the inner test script with an outer driver that runs individual
podman/docker commands against a pre-built image. Tests sqlite-vec
loading and store unit tests under both node and bun runtimes.

Supports --build (image only), --shell (interactive), and -- CMD
(arbitrary command) for debugging install issues in isolation.
Tobi Lutke 3 달 전
부모
커밋
c7e8ea02a5
3개의 변경된 파일161개의 추가작업 그리고 80개의 파일을 삭제
  1. 12 4
      test/Containerfile
  2. 0 58
      test/smoke-install-test.sh
  3. 149 18
      test/smoke-install.sh

+ 12 - 4
test/Containerfile

@@ -13,9 +13,17 @@ ENV PATH="/root/.local/bin:$PATH"
 # Pre-install node and bun
 RUN mise use -g node@latest bun@latest
 
-# Copy the packed tarball and test script
+# Copy the packed tarball and install via both package managers
 COPY tobilu-qmd-*.tgz /tmp/
-COPY smoke-install-test.sh /tmp/
-RUN chmod +x /tmp/smoke-install-test.sh
+RUN mise exec node@latest -- npm install -g /tmp/tobilu-qmd-*.tgz
+RUN mise exec bun@latest -- bun install -g /tmp/tobilu-qmd-*.tgz
 
-CMD ["/tmp/smoke-install-test.sh"]
+# Copy test project (src + test + configs) and install deps
+COPY test-src/ /opt/qmd/
+RUN cd /opt/qmd && mise exec node@latest -- npm install 2>/dev/null
+RUN cd /opt/qmd && mise exec bun@latest -- bun install 2>/dev/null || true
+
+# Put everything on PATH
+ENV PATH="/root/.bun/bin:/root/.local/share/mise/shims:/root/.local/bin:$PATH"
+
+CMD ["bash"]

+ 0 - 58
test/smoke-install-test.sh

@@ -1,58 +0,0 @@
-#!/usr/bin/env bash
-# Smoke test: install @tobilu/qmd from tarball and verify it runs under node and bun.
-# Both runtimes need node on PATH (the bin uses #!/usr/bin/env node shebang).
-set -uo pipefail
-
-TARBALL=$(ls /tmp/tobilu-qmd-*.tgz | head -1)
-PASS=0
-FAIL=0
-TMP=$(mktemp)
-
-ok()   { printf "  %-44s OK\n" "$1"; PASS=$((PASS + 1)); }
-fail() { printf "  %-44s FAIL\n" "$1"; FAIL=$((FAIL + 1)); cat "$TMP" | sed 's/^/    /'; }
-
-NODE_BIN="$(mise where node@latest)/bin"
-BUN_BIN="$(mise where bun@latest)/bin"
-BASE_PATH="/root/.local/bin:/usr/local/bin:/usr/bin:/bin"
-
-# ---------------------------------------------------------------------------
-# Node: install via npm, runs with node (via shebang)
-# ---------------------------------------------------------------------------
-echo "=== Node $($NODE_BIN/node --version) ==="
-export PATH="$NODE_BIN:$BASE_PATH"
-
-if npm install -g "$TARBALL" >"$TMP" 2>&1; then ok "npm install -g"
-else fail "npm install -g"; fi
-
-timeout 10 qmd >"$TMP" 2>&1 || true
-if grep -q "Usage:" "$TMP"; then ok "qmd shows help"
-else fail "qmd shows help"; fi
-
-if timeout 10 qmd collection list >"$TMP" 2>&1; then ok "qmd collection list"
-else fail "qmd collection list"; fi
-
-# ---------------------------------------------------------------------------
-# Bun: install via bun, still runs with node (shebang)
-# ---------------------------------------------------------------------------
-echo ""
-echo "=== Bun $($BUN_BIN/bun --version) ==="
-export PATH="$BUN_BIN:$HOME/.bun/bin:$NODE_BIN:$BASE_PATH"
-
-if bun install -g "$TARBALL" >"$TMP" 2>&1; then ok "bun install -g"
-else fail "bun install -g"; fi
-
-timeout 10 "$HOME/.bun/bin/qmd" >"$TMP" 2>&1 || true
-if grep -q "Usage:" "$TMP"; then ok "qmd shows help (bun-installed)"
-else fail "qmd shows help (bun-installed)"; fi
-
-if timeout 10 "$HOME/.bun/bin/qmd" collection list >"$TMP" 2>&1; then ok "qmd collection list (bun-installed)"
-else fail "qmd collection list (bun-installed)"; fi
-
-rm -f "$TMP"
-
-# ---------------------------------------------------------------------------
-# Summary
-# ---------------------------------------------------------------------------
-echo ""
-echo "=== Results: $PASS passed, $FAIL failed ==="
-[[ $FAIL -eq 0 ]]

+ 149 - 18
test/smoke-install.sh

@@ -1,6 +1,12 @@
 #!/usr/bin/env bash
-# Build, pack, and smoke-test qmd in a container with mise + node + bun.
+# Build a container image with qmd installed via npm and bun, then run smoke tests.
 # Works with docker or podman (whichever is available).
+#
+# Usage:
+#   test/smoke-install.sh              # build + run all smoke tests
+#   test/smoke-install.sh --build      # build image only
+#   test/smoke-install.sh --shell      # drop into container shell
+#   test/smoke-install.sh -- CMD...    # run arbitrary command in container
 set -euo pipefail
 
 cd "$(dirname "$0")/.."
@@ -14,25 +20,150 @@ else
   echo "Error: neither podman nor docker found" >&2
   exit 1
 fi
-echo "Using: $CTR"
 
-# Build TypeScript
-echo "==> Building TypeScript..."
-npm run build --silent
+IMAGE=qmd-smoke
 
-# Pack tarball into test/ (the build context)
-echo "==> Packing tarball..."
-rm -f test/tobilu-qmd-*.tgz
-TARBALL=$(npm pack --pack-destination test/ 2>/dev/null | tail -1)
-echo "    $TARBALL"
+build_image() {
+  echo "==> Building TypeScript..."
+  npm run build --silent
 
-# Build container image
-echo "==> Building container..."
-$CTR build -f test/Containerfile -t qmd-smoke test/
+  echo "==> Packing tarball..."
+  rm -f test/tobilu-qmd-*.tgz
+  TARBALL=$(npm pack --pack-destination test/ 2>/dev/null | tail -1)
+  echo "    $TARBALL"
 
-# Run smoke tests
-echo "==> Running smoke tests..."
-$CTR run --rm qmd-smoke
+  # Copy project files into build context so vitest/bun tests can run inside
+  rm -rf test/test-src
+  mkdir -p test/test-src/src test/test-src/test
+  cp src/*.ts test/test-src/src/
+  cp -r dist test/test-src/
+  cp test/*.test.ts test/test-src/test/
+  cp package.json tsconfig.json tsconfig.build.json test/test-src/
 
-# Clean up tarball
-rm -f test/tobilu-qmd-*.tgz
+  echo "==> Building container image ($CTR)..."
+  $CTR build -f test/Containerfile -t "$IMAGE" test/
+
+  # Clean up
+  rm -f test/tobilu-qmd-*.tgz
+  rm -rf test/test-src
+  echo "==> Image ready: $IMAGE"
+}
+
+run() {
+  $CTR run --rm "$IMAGE" bash -c "$*"
+}
+
+PASS=0
+FAIL=0
+
+ok()   { printf "  %-50s OK\n" "$1"; PASS=$((PASS + 1)); }
+fail() { printf "  %-50s FAIL\n" "$1"; FAIL=$((FAIL + 1)); echo "$2" | sed 's/^/    /'; }
+
+smoke_test() {
+  local label="$1"; shift
+  local out
+  if out=$(run "$@" 2>&1); then
+    ok "$label"
+  else
+    fail "$label" "$out"
+  fi
+}
+
+smoke_test_output() {
+  local label="$1"; local expect="$2"; shift 2
+  local out
+  out=$(run "$@" 2>&1) || true
+  if echo "$out" | grep -q "$expect"; then
+    ok "$label"
+  else
+    fail "$label" "$out"
+  fi
+}
+
+run_smoke_tests() {
+  # ------------------------------------------------------------------
+  # Node (npm-installed qmd)
+  # ------------------------------------------------------------------
+  local NODE_BIN='$(mise where node@latest)/bin'
+  echo "=== Node (npm install) ==="
+
+  smoke_test_output "qmd shows help" "Usage:" \
+    "export PATH=$NODE_BIN:\$PATH; qmd"
+
+  smoke_test "qmd collection list" \
+    "export PATH=$NODE_BIN:\$PATH; qmd collection list"
+
+  smoke_test "qmd status" \
+    "export PATH=$NODE_BIN:\$PATH; qmd status"
+
+  smoke_test "sqlite-vec loads" \
+    "export PATH=$NODE_BIN:\$PATH;
+     NPM_GLOBAL=\$(npm root -g);
+     node -e \"
+      const {openDatabase, loadSqliteVec} = await import('\$NPM_GLOBAL/@tobilu/qmd/dist/db.js');
+      const db = openDatabase(':memory:');
+      loadSqliteVec(db);
+      const r = db.prepare('SELECT vec_version() as v').get();
+      console.log('sqlite-vec', r.v);
+      if (!r.v) process.exit(1);
+    \""
+
+  smoke_test "vitest (node)" \
+    "export PATH=$NODE_BIN:\$PATH; cd /opt/qmd && npx vitest run --reporter=verbose test/store.test.ts 2>&1 | tail -5"
+
+  # ------------------------------------------------------------------
+  # Bun (bun-installed qmd)
+  # ------------------------------------------------------------------
+  local BUN_BIN='$(mise where bun@latest)/bin'
+  echo ""
+  echo "=== Bun (bun install) ==="
+
+  smoke_test_output "qmd shows help" "Usage:" \
+    "export PATH=$BUN_BIN:$NODE_BIN:\$PATH; \$HOME/.bun/bin/qmd"
+
+  smoke_test "qmd collection list" \
+    "export PATH=$BUN_BIN:$NODE_BIN:\$PATH; \$HOME/.bun/bin/qmd collection list"
+
+  smoke_test "qmd status" \
+    "export PATH=$BUN_BIN:$NODE_BIN:\$PATH; \$HOME/.bun/bin/qmd status"
+
+  smoke_test "sqlite-vec loads (bun)" \
+    "export PATH=$BUN_BIN:\$PATH; bun -e \"
+      const {openDatabase, loadSqliteVec} = await import('\$HOME/.bun/install/global/node_modules/@tobilu/qmd/dist/db.js');
+      const db = openDatabase(':memory:');
+      loadSqliteVec(db);
+      const r = db.prepare('SELECT vec_version() as v').get();
+      console.log('sqlite-vec', r.v);
+      if (!r.v) process.exit(1);
+    \""
+
+  smoke_test "bun test store" \
+    "export PATH=$BUN_BIN:\$PATH; cd /opt/qmd && bun test --preload ./src/test-preload.ts --timeout 30000 test/store.test.ts 2>&1 | tail -10"
+
+  # ------------------------------------------------------------------
+  echo ""
+  echo "=== Results: $PASS passed, $FAIL failed ==="
+  [[ $FAIL -eq 0 ]]
+}
+
+# Parse arguments
+case "${1:-}" in
+  --build)
+    build_image
+    ;;
+  --shell)
+    build_image
+    echo "==> Dropping into container shell..."
+    $CTR run --rm -it "$IMAGE" bash
+    ;;
+  --)
+    shift
+    run "$@"
+    ;;
+  *)
+    build_image
+    echo ""
+    echo "==> Running smoke tests..."
+    run_smoke_tests
+    ;;
+esac