|
1 | 1 | // SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. |
2 | 2 | // SPDX-License-Identifier: Apache-2.0 |
3 | 3 |
|
4 | | -#![cfg(feature = "e2e-podman")] |
5 | | - |
6 | | -//! Podman driver daemon-unavailable e2e tests. |
| 4 | +//! Podman driver daemon-unavailable integration tests. |
7 | 5 | //! |
8 | 6 | //! These tests verify that `openshell-driver-podman` fails fast with an |
9 | 7 | //! actionable error when it cannot reach a Podman API socket, instead of |
10 | 8 | //! hanging or silently serving gRPC against a dead connection. |
11 | 9 | //! |
12 | | -//! The tests do NOT require a running Podman daemon or gateway — they point |
| 10 | +//! They do NOT require a running Podman daemon or gateway — they point |
13 | 11 | //! `--podman-socket` at a path that is guaranteed not to exist to simulate |
14 | | -//! the daemon being unavailable. |
| 12 | +//! the daemon being unavailable. As a plain Cargo integration test in this |
| 13 | +//! crate, this runs via the normal `cargo test -p openshell-driver-podman` |
| 14 | +//! lane with no special CI wiring: Cargo provides `CARGO_BIN_EXE_<name>` for |
| 15 | +//! this crate's own `[[bin]]` target automatically. |
15 | 16 |
|
16 | | -use std::path::{Path, PathBuf}; |
| 17 | +use std::path::PathBuf; |
17 | 18 | use std::time::{Duration, Instant}; |
18 | 19 |
|
19 | | -use openshell_e2e::harness::output::strip_ansi; |
20 | | - |
21 | | -/// Locate the workspace root by walking up from this crate's manifest directory. |
22 | | -fn workspace_root() -> PathBuf { |
23 | | - Path::new(env!("CARGO_MANIFEST_DIR")) |
24 | | - .ancestors() |
25 | | - .nth(2) |
26 | | - .expect("failed to resolve workspace root from CARGO_MANIFEST_DIR") |
27 | | - .to_path_buf() |
28 | | -} |
29 | | - |
30 | | -/// Return the path to the `openshell-driver-podman` binary. |
31 | | -/// |
32 | | -/// Uses `OPENSHELL_EXTERNAL_DRIVER_BIN` when set (the same env var the shell |
33 | | -/// e2e harness uses for prebuilt standalone driver artifacts), otherwise |
34 | | -/// expects the binary at `<workspace>/target/debug/openshell-driver-podman`. |
35 | | -fn driver_podman_bin() -> PathBuf { |
36 | | - let bin = std::env::var_os("OPENSHELL_EXTERNAL_DRIVER_BIN").map_or_else( |
37 | | - || workspace_root().join("target/debug/openshell-driver-podman"), |
38 | | - PathBuf::from, |
39 | | - ); |
40 | | - assert!( |
41 | | - bin.is_file(), |
42 | | - "openshell-driver-podman binary not found at {} — set OPENSHELL_EXTERNAL_DRIVER_BIN \ |
43 | | - or run `cargo build -p openshell-driver-podman` first", |
44 | | - bin.display() |
45 | | - ); |
46 | | - bin |
47 | | -} |
48 | | - |
49 | 20 | /// Run `openshell-driver-podman` pointed at a Podman socket that does not |
50 | 21 | /// exist, and wait for it to exit. |
51 | 22 | /// |
52 | 23 | /// The driver retries a handful of times before giving up (to tolerate the |
53 | 24 | /// socket briefly re-activating), so this can take several seconds. |
54 | 25 | async fn run_with_unreachable_podman_socket() -> (String, i32, Duration, PathBuf) { |
55 | 26 | let tmpdir = tempfile::tempdir().expect("create isolated socket dir"); |
56 | | - let missing_socket = tmpdir.path().join("openshell-e2e-nonexistent-podman.sock"); |
| 27 | + // Use a short relative path so miette cannot insert a line-wrap gutter |
| 28 | + // inside it on platforms with long temporary-directory paths. |
| 29 | + let missing_socket = PathBuf::from("missing-podman.sock"); |
57 | 30 |
|
58 | 31 | let start = Instant::now(); |
59 | | - let mut cmd = tokio::process::Command::new(driver_podman_bin()); |
| 32 | + let mut cmd = tokio::process::Command::new(env!("CARGO_BIN_EXE_openshell-driver-podman")); |
60 | 33 | cmd.arg("--podman-socket") |
61 | 34 | .arg(&missing_socket) |
| 35 | + .current_dir(tmpdir.path()) |
62 | 36 | .kill_on_drop(true) |
63 | 37 | .stdout(std::process::Stdio::piped()) |
64 | 38 | .stderr(std::process::Stdio::piped()); |
65 | 39 |
|
66 | | - let output = tokio::time::timeout(Duration::from_secs(60), cmd.output()) |
| 40 | + let output = tokio::time::timeout(Duration::from_mins(1), cmd.output()) |
67 | 41 | .await |
68 | 42 | .expect("openshell-driver-podman should exit instead of hanging") |
69 | 43 | .expect("spawn openshell-driver-podman"); |
@@ -102,15 +76,14 @@ async fn driver_error_names_unreachable_socket() { |
102 | 76 | let (output, code, _, missing_socket) = run_with_unreachable_podman_socket().await; |
103 | 77 |
|
104 | 78 | assert_ne!(code, 0); |
105 | | - let clean = strip_ansi(&output); |
106 | 79 |
|
107 | 80 | assert!( |
108 | | - clean.contains("connection error"), |
109 | | - "driver error should describe a connection failure:\n{clean}" |
| 81 | + output.contains("connection error"), |
| 82 | + "driver error should describe a connection failure:\n{output}" |
110 | 83 | ); |
111 | 84 | assert!( |
112 | | - clean.contains(missing_socket.to_str().expect("socket path is utf-8")), |
113 | | - "driver error should name the unreachable socket path {}:\n{clean}", |
| 85 | + output.contains(missing_socket.to_str().expect("socket path is utf-8")), |
| 86 | + "driver error should name the unreachable socket path {}:\n{output}", |
114 | 87 | missing_socket.display() |
115 | 88 | ); |
116 | 89 | } |
0 commit comments