mirror of
https://github.com/imjasonh/krust
synced 2026-07-06 22:12:32 +00:00
Integration tests now skip instead of panicking when Docker or cargo-zigbuild aren't available. Also removed redundant make test-e2e step from CI since make test already includes e2e tests. https://claude.ai/code/session_01EcsZDNeWn56wFqryb4Wq7r
224 lines
7.3 KiB
Rust
224 lines
7.3 KiB
Rust
//! Integration tests for krust
|
|
//!
|
|
//! Most integration tests have been converted to testscripts in tests/testdata/*.txt
|
|
//! These tests remain here because they require Docker to run and verify the built images.
|
|
|
|
use anyhow::Result;
|
|
use assert_cmd::Command;
|
|
use std::env;
|
|
use std::process::Command as StdCommand;
|
|
|
|
#[test]
|
|
fn test_full_build_and_run_workflow() -> Result<()> {
|
|
// This test requires Docker and cargo-zigbuild
|
|
let docker_check = StdCommand::new("docker").arg("version").output();
|
|
match docker_check {
|
|
Ok(output) if output.status.success() => {}
|
|
_ => {
|
|
eprintln!("Skipping test_full_build_and_run_workflow: Docker not available");
|
|
return Ok(());
|
|
}
|
|
}
|
|
let zigbuild_check = StdCommand::new("cargo")
|
|
.args(["zigbuild", "--version"])
|
|
.output();
|
|
match zigbuild_check {
|
|
Ok(output) if output.status.success() => {}
|
|
_ => {
|
|
eprintln!("Skipping test_full_build_and_run_workflow: cargo-zigbuild not available");
|
|
return Ok(());
|
|
}
|
|
}
|
|
|
|
// Get the example project directory
|
|
let example_dir = env::current_dir()?.join("example").join("hello-krust");
|
|
|
|
// Build and push to ttl.sh
|
|
// For the full workflow test, build for the actual native platform so Docker can run it
|
|
let native_platform = if cfg!(target_arch = "aarch64") {
|
|
"linux/arm64"
|
|
} else {
|
|
"linux/amd64"
|
|
};
|
|
|
|
let mut cmd = Command::cargo_bin("krust")?;
|
|
let output = cmd
|
|
.arg("build")
|
|
.arg("--platform")
|
|
.arg(native_platform)
|
|
.arg(".")
|
|
.env("KRUST_REPO", "ttl.sh/krust-test")
|
|
.current_dir(&example_dir)
|
|
.output()?;
|
|
|
|
if !output.status.success() {
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
panic!("Build failed: {}", stderr);
|
|
}
|
|
|
|
// Get the image reference from stdout
|
|
let image_ref = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
|
assert!(image_ref.starts_with("ttl.sh/krust-test/hello-krust@sha256:"));
|
|
|
|
// Try to run the image
|
|
let docker_output = StdCommand::new("docker")
|
|
.args(&["run", "--rm", &image_ref])
|
|
.output()?;
|
|
|
|
if !docker_output.status.success() {
|
|
let stderr = String::from_utf8_lossy(&docker_output.stderr);
|
|
panic!("Docker run failed with image {}: {}", image_ref, stderr);
|
|
}
|
|
|
|
let docker_stdout = String::from_utf8_lossy(&docker_output.stdout);
|
|
assert!(docker_stdout.contains("Hello from krust example!"));
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_multi_arch_build_and_run() -> Result<()> {
|
|
// This test requires Docker and cargo-zigbuild
|
|
let docker_check = StdCommand::new("docker").arg("version").output();
|
|
match docker_check {
|
|
Ok(output) if output.status.success() => {}
|
|
_ => {
|
|
eprintln!("Skipping test_multi_arch_build_and_run: Docker not available");
|
|
return Ok(());
|
|
}
|
|
}
|
|
let zigbuild_check = StdCommand::new("cargo")
|
|
.args(["zigbuild", "--version"])
|
|
.output();
|
|
match zigbuild_check {
|
|
Ok(output) if output.status.success() => {}
|
|
_ => {
|
|
eprintln!("Skipping test_multi_arch_build_and_run: cargo-zigbuild not available");
|
|
return Ok(());
|
|
}
|
|
}
|
|
|
|
let example_dir = env::current_dir()?.join("example").join("hello-krust");
|
|
|
|
// Build multi-arch image and push to ttl.sh
|
|
let mut cmd = Command::cargo_bin("krust")?;
|
|
let output = cmd
|
|
.arg("build")
|
|
.arg("--platform")
|
|
.arg("linux/amd64,linux/arm64")
|
|
.arg(".")
|
|
.env("KRUST_REPO", "ttl.sh/krust-multiarch-test")
|
|
.current_dir(&example_dir)
|
|
.output()?;
|
|
|
|
if !output.status.success() {
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
// If it fails due to missing targets, that's expected in some environments
|
|
if stderr.contains("target may not be installed")
|
|
|| stderr.contains("linker")
|
|
|| stderr.contains("cross-compilation")
|
|
|| stderr.contains("not found")
|
|
{
|
|
eprintln!("Skipping multi-arch run test - build failed due to missing toolchain");
|
|
return Ok(());
|
|
}
|
|
panic!("Build failed unexpectedly: {}", stderr);
|
|
}
|
|
|
|
// Get the image reference from stdout
|
|
let image_ref = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
|
assert!(image_ref.starts_with("ttl.sh/krust-multiarch-test/hello-krust"));
|
|
|
|
// Try to run the image - it should work on the current architecture
|
|
let docker_output = StdCommand::new("docker")
|
|
.args(&["run", "--rm", &image_ref])
|
|
.output()?;
|
|
|
|
assert!(docker_output.status.success(), "Docker run failed");
|
|
let docker_stdout = String::from_utf8_lossy(&docker_output.stdout);
|
|
assert!(docker_stdout.contains("Hello from krust example!"));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_reproducible_builds() -> Result<()> {
|
|
// This test verifies that building the same project twice with SOURCE_DATE_EPOCH
|
|
// produces identical image digests
|
|
|
|
// This test requires cargo-zigbuild
|
|
let zigbuild_check = StdCommand::new("cargo")
|
|
.args(["zigbuild", "--version"])
|
|
.output();
|
|
match zigbuild_check {
|
|
Ok(output) if output.status.success() => {}
|
|
_ => {
|
|
eprintln!("Skipping test_reproducible_builds: cargo-zigbuild not available");
|
|
return Ok(());
|
|
}
|
|
}
|
|
|
|
// Get the example project directory
|
|
let example_dir = env::current_dir()?.join("example").join("hello-krust");
|
|
|
|
let native_platform = if cfg!(target_arch = "aarch64") {
|
|
"linux/arm64"
|
|
} else {
|
|
"linux/amd64"
|
|
};
|
|
|
|
// Fixed timestamp for reproducibility
|
|
let source_date_epoch = "1609459200"; // 2021-01-01 00:00:00 UTC
|
|
|
|
// Build the first time (pushing to ttl.sh for temporary storage)
|
|
let mut cmd1 = Command::cargo_bin("krust")?;
|
|
let output1 = cmd1
|
|
.arg("build")
|
|
.arg("--platform")
|
|
.arg(native_platform)
|
|
.arg(".")
|
|
.env("KRUST_REPO", "ttl.sh/krust-reproducible-test")
|
|
.env("SOURCE_DATE_EPOCH", source_date_epoch)
|
|
.current_dir(&example_dir)
|
|
.output()?;
|
|
|
|
if !output1.status.success() {
|
|
let stderr = String::from_utf8_lossy(&output1.stderr);
|
|
panic!("First build failed: {}", stderr);
|
|
}
|
|
|
|
let digest1 = String::from_utf8_lossy(&output1.stdout).trim().to_string();
|
|
|
|
// Build the second time with the same SOURCE_DATE_EPOCH
|
|
let mut cmd2 = Command::cargo_bin("krust")?;
|
|
let output2 = cmd2
|
|
.arg("build")
|
|
.arg("--platform")
|
|
.arg(native_platform)
|
|
.arg(".")
|
|
.env("KRUST_REPO", "ttl.sh/krust-reproducible-test")
|
|
.env("SOURCE_DATE_EPOCH", source_date_epoch)
|
|
.current_dir(&example_dir)
|
|
.output()?;
|
|
|
|
if !output2.status.success() {
|
|
let stderr = String::from_utf8_lossy(&output2.stderr);
|
|
panic!("Second build failed: {}", stderr);
|
|
}
|
|
|
|
let digest2 = String::from_utf8_lossy(&output2.stdout).trim().to_string();
|
|
|
|
// The digests should be identical
|
|
assert_eq!(
|
|
digest1, digest2,
|
|
"Builds with same SOURCE_DATE_EPOCH should produce identical digests.\nFirst: {}\nSecond: {}",
|
|
digest1, digest2
|
|
);
|
|
|
|
// Both should contain a valid digest
|
|
assert!(
|
|
digest1.contains("@sha256:"),
|
|
"Output should contain a digest"
|
|
);
|
|
|
|
Ok(())
|
|
}
|