-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcheck_command_docker_integration.rs
More file actions
144 lines (122 loc) · 4.84 KB
/
Copy pathcheck_command_docker_integration.rs
File metadata and controls
144 lines (122 loc) · 4.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//! Integration tests for the dependency-installer CLI using Docker containers.
//!
//! These tests verify that the CLI binary works correctly in a clean Ubuntu 24.04
//! environment. They use testcontainers to spin up isolated Docker containers.
use std::path::PathBuf;
mod containers;
use containers::ubuntu_container_builder::UbuntuContainerBuilder;
/// Test that the check command correctly identifies missing dependencies
/// in a fresh Ubuntu 24.04 container
#[tokio::test]
async fn it_should_report_missing_dependencies_when_checking_all_in_fresh_ubuntu_container() {
// Get the binary path (built by cargo before running tests)
let binary_path = get_binary_path();
// Start Ubuntu container with the binary
let container = UbuntuContainerBuilder::new(&binary_path).start().await;
// Verify exit code is non-zero (failure) when dependencies are missing
let exit_code =
container.exec_with_exit_code(&["dependency-installer", "check", "--log-level", "off"]);
assert_eq!(
exit_code, 1,
"check command should exit with 1 when dependencies missing"
);
}
/// Test that the check command works for specific dependencies
#[tokio::test]
async fn it_should_exit_with_error_code_when_checking_missing_specific_dependency() {
let binary_path = get_binary_path();
let container = UbuntuContainerBuilder::new(&binary_path).start().await;
// Verify exit code when checking missing specific dependency
let exit_code = container.exec_with_exit_code(&[
"dependency-installer",
"check",
"--dependency",
"opentofu",
"--log-level",
"off",
]);
assert_eq!(
exit_code, 1,
"check command should exit with 1 for missing specific dependency"
);
}
/// Test that the list command works correctly
#[tokio::test]
async fn it_should_list_all_dependencies_with_their_installation_status() {
let binary_path = get_binary_path();
let container = UbuntuContainerBuilder::new(&binary_path).start().await;
// Run list command with default log level (info) to verify logging output
let output = container.exec(&["dependency-installer", "list"]);
// Verify all tools are listed in the logging output
assert!(
output.contains("cargo-machete"),
"Expected cargo-machete to be listed, got: {output}"
);
assert!(
output.contains("OpenTofu"),
"Expected OpenTofu to be listed, got: {output}"
);
assert!(
output.contains("Ansible"),
"Expected Ansible to be listed, got: {output}"
);
assert!(
output.contains("LXD"),
"Expected LXD to be listed, got: {output}"
);
// Verify status is shown
assert!(
output.contains("not installed"),
"Expected 'not installed' status to be shown, got: {output}"
);
}
/// Test verbose output flag
#[tokio::test]
async fn it_should_display_debug_logs_when_verbose_flag_is_enabled() {
let binary_path = get_binary_path();
let container = UbuntuContainerBuilder::new(&binary_path).start().await;
let output = container.exec(&["dependency-installer", "check", "--verbose"]);
// Verify debug/info logs are present
// The CLI uses tracing, so we should see timestamp-prefixed log messages
assert!(
output.contains("INFO") || output.contains("Checking"),
"Expected verbose output to contain INFO logs or 'Checking' message, got: {output}"
);
}
/// Get the path to the compiled binary
///
/// This function assumes the binary was built before running tests.
/// Run `cargo build --bin dependency-installer` before running these tests.
///
/// # Implementation Note
///
/// We use `CARGO_MANIFEST_DIR` and navigate up to the workspace root, then into
/// the target directory. This works because:
/// 1. `CARGO_MANIFEST_DIR` points to packages/dependency-installer
/// 2. The workspace root is two directories up
/// 3. The target directory is in the workspace root
///
/// Alternative approaches considered:
/// - `CARGO_TARGET_DIR`: Not always set
/// - `OUT_DIR`: Points to build script output, not target/debug
/// - Searching for target dir: Too expensive
fn get_binary_path() -> PathBuf {
// Get the package manifest directory (packages/dependency-installer)
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
// Navigate to workspace root (two levels up from packages/dependency-installer)
let workspace_root = manifest_dir
.parent() // packages/
.and_then(|p| p.parent()) // workspace root
.expect("Failed to find workspace root");
// Build path to the binary in target/debug
let path = workspace_root
.join("target")
.join("debug")
.join("dependency-installer");
assert!(
path.exists(),
"Binary not found at {}. Run 'cargo build --bin dependency-installer' first",
path.display()
);
path
}