Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ regex = "1"
linkme = "0.3.30"
paste = "1.0"
rand = { workspace = true }
scopeguard = "1"

[lints]
workspace = true
32 changes: 0 additions & 32 deletions crates/integration-tests/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
//! Integration tests for bcvk

use std::process::Output;

use camino::Utf8Path;

use color_eyre::eyre::{eyre, Context};
Expand Down Expand Up @@ -84,36 +82,6 @@ pub(crate) fn get_all_test_images() -> Vec<String> {
}
}

/// Captured output from a command with decoded stdout/stderr strings
pub(crate) struct CapturedOutput {
pub output: Output,
pub stdout: String,
pub stderr: String,
}

impl CapturedOutput {
/// Create from a raw Output
pub fn new(output: Output) -> Self {
let stdout = String::from_utf8_lossy(&output.stdout).into_owned();
let stderr = String::from_utf8_lossy(&output.stderr).into_owned();
Self {
output,
stdout,
stderr,
}
}

/// Get the exit code
pub fn exit_code(&self) -> Option<i32> {
self.output.status.code()
}

/// Check if the command succeeded
pub fn success(&self) -> bool {
self.output.status.success()
}
}

fn test_images_list() -> Result<()> {
println!("Running test: bcvk images list --json");

Expand Down
141 changes: 44 additions & 97 deletions crates/integration-tests/src/tests/libvirt_base_disks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

use color_eyre::Result;
use integration_tests::integration_test;
use scopeguard::defer;
use xshell::cmd;

use regex::Regex;
Expand Down Expand Up @@ -36,27 +37,21 @@ fn test_base_disk_creation_and_reuse() -> Result<()> {
cleanup_domain(&vm1_name);
cleanup_domain(&vm2_name);

// Set up cleanup guard that will run on scope exit (success or failure)
defer! {
cleanup_domain(&vm1_name);
cleanup_domain(&vm2_name);
}

// Create first VM - this should create a new base disk
println!("Creating first VM (should create base disk)...");
let vm1_output = cmd!(
let vm1_stdout = cmd!(
sh,
"{bck} libvirt run --name {vm1_name} --filesystem ext4 {test_image}"
)
.ignore_status()
.output()?;

let vm1_stdout = String::from_utf8_lossy(&vm1_output.stdout);
let vm1_stderr = String::from_utf8_lossy(&vm1_output.stderr);
.read()?;

println!("VM1 stdout: {}", vm1_stdout);
println!("VM1 stderr: {}", vm1_stderr);

if !vm1_output.status.success() {
cleanup_domain(&vm1_name);
cleanup_domain(&vm2_name);

panic!("Failed to create first VM: {}", vm1_stderr);
}

// Verify base disk was created
assert!(
Expand All @@ -66,26 +61,11 @@ fn test_base_disk_creation_and_reuse() -> Result<()> {

// Create second VM - this should reuse the base disk
println!("Creating second VM (should reuse base disk)...");
let vm2_output = cmd!(
let vm2_stdout = cmd!(
sh,
"{bck} libvirt run --name {vm2_name} --filesystem ext4 {test_image}"
)
.ignore_status()
.output()?;

let vm2_stdout = String::from_utf8_lossy(&vm2_output.stdout);
let vm2_stderr = String::from_utf8_lossy(&vm2_output.stderr);

println!("VM2 stdout: {}", vm2_stdout);
println!("VM2 stderr: {}", vm2_stderr);

// Cleanup before assertions
cleanup_domain(&vm1_name);
cleanup_domain(&vm2_name);

if !vm2_output.status.success() {
panic!("Failed to create second VM: {}", vm2_stderr);
}
.read()?;

// Verify base disk was reused (should be faster and mention using existing)
assert!(
Expand Down Expand Up @@ -129,35 +109,21 @@ fn test_base_disks_list_command() -> Result<()> {

println!("Testing base-disks list command");

let output = cmd!(sh, "{bck} libvirt base-disks list")
.ignore_status()
.output()?;
let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);

if output.status.success() {
println!("base-disks list output: {}", stdout);

// Should show table header or empty message
assert!(
stdout.contains("NAME")
|| stdout.contains("No base disk")
|| stdout.contains("no base disk")
|| stdout.is_empty(),
"Should show table format or empty message, got: {}",
stdout
);

println!("✓ base-disks list command works");
} else {
println!("base-disks list failed (may be expected): {}", stderr);

// Should fail gracefully
assert!(
stderr.contains("pool") || stderr.contains("libvirt") || stderr.contains("connect"),
"Should have meaningful error about libvirt connectivity"
);
}
let stdout = cmd!(sh, "{bck} libvirt base-disks list").read()?;

println!("base-disks list output: {}", stdout);

// Should show table header or empty message
assert!(
stdout.contains("NAME")
|| stdout.contains("No base disk")
|| stdout.contains("no base disk")
|| stdout.is_empty(),
"Should show table format or empty message, got: {}",
stdout
);

println!("✓ base-disks list command works");
Ok(())
}
integration_test!(test_base_disks_list_command);
Expand All @@ -169,31 +135,17 @@ fn test_base_disks_prune_dry_run() -> Result<()> {

println!("Testing base-disks prune --dry-run command");

let output = cmd!(sh, "{bck} libvirt base-disks prune --dry-run")
.ignore_status()
.output()?;
let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);

if output.status.success() {
println!("base-disks prune --dry-run output: {}", stdout);

// Should show what would be removed or indicate nothing to prune
assert!(
stdout.contains("Would remove") || stdout.contains("No") || stdout.is_empty(),
"Should show dry-run output"
);

println!("✓ base-disks prune --dry-run command works");
} else {
println!("base-disks prune failed (may be expected): {}", stderr);

// Should fail gracefully
assert!(
stderr.contains("pool") || stderr.contains("libvirt") || stderr.contains("connect"),
"Should have meaningful error about libvirt connectivity"
);
}
let stdout = cmd!(sh, "{bck} libvirt base-disks prune --dry-run").read()?;

println!("base-disks prune --dry-run output: {}", stdout);

// Should show what would be removed or indicate nothing to prune
assert!(
stdout.contains("Would remove") || stdout.contains("No") || stdout.is_empty(),
"Should show dry-run output"
);

println!("✓ base-disks prune --dry-run command works");
Ok(())
}
integration_test!(test_base_disks_prune_dry_run);
Expand All @@ -214,20 +166,17 @@ fn test_vm_disk_references_base() -> Result<()> {

cleanup_domain(&vm_name);

// Set up cleanup guard that will run on scope exit
defer! {
cleanup_domain(&vm_name);
}

// Create VM
let output = cmd!(
cmd!(
sh,
"{bck} libvirt run --name {vm_name} --filesystem ext4 {test_image}"
)
.ignore_status()
.output()?;

if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
cleanup_domain(&vm_name);

panic!("Failed to create VM: {}", stderr);
}
.run()?;

// Get VM disk path from domain XML
let sh = shell()?;
Expand All @@ -247,8 +196,6 @@ fn test_vm_disk_references_base() -> Result<()> {
.get("file")
.expect("No file attribute found in source element");

cleanup_domain(&vm_name);

println!("VM disk path: {}", disk_path);

// Disk should be named after the VM, not a base disk
Expand Down
Loading