#![allow(deprecated)]
#![allow(clippy::unwrap_used)]
#![allow(clippy::expect_used)]
#![allow(non_snake_case)]
use assert_cmd::Command;
use std::fs;
use std::io::Write;
use tempfile::{NamedTempFile, TempDir};
#[allow(deprecated)]
fn bashrs_cmd() -> Command {
assert_cmd::cargo_bin_cmd!("bashrs")
}
fn create_temp_dockerfile(content: &str) -> NamedTempFile {
let mut file = NamedTempFile::new().expect("Failed to create temp file");
file.write_all(content.as_bytes())
.expect("Failed to write to temp file");
file
}
#[test]
fn test_integration_all_transformations_combined() {
let dockerfile = r#"FROM ubuntu:latest
RUN apt-get update && apt-get install -y curl wget
ADD https://example.com/file.tar.gz /tmp/
ADD local-file.txt /app/
COPY app.py /app/
"#;
let input_file = create_temp_dockerfile(dockerfile);
let output_dir = TempDir::new().expect("Failed to create temp dir");
let output_file = output_dir.path().join("Dockerfile.purified");
bashrs_cmd()
.arg("dockerfile")
.arg("purify")
.arg(input_file.path())
.arg("-o")
.arg(&output_file)
.assert()
.success();
let purified = fs::read_to_string(&output_file).expect("Failed to read purified file");
assert!(
purified.contains("FROM ubuntu:22.04") || purified.contains("FROM ubuntu:20.04"),
"DOCKER001 transformation failed: {}",
purified
);
assert!(
purified.contains("--no-install-recommends"),
"DOCKER005 transformation failed"
);
assert!(
purified.contains("/var/lib/apt/lists"),
"DOCKER003 transformation failed"
);
assert!(
purified.contains("COPY local-file.txt"),
"DOCKER006 transformation failed (local file)"
);
assert!(
purified.contains("ADD https://example.com"),
"DOCKER006 transformation failed (URL preservation)"
);
}
#[test]
fn test_integration_nodejs_dockerfile() {
let dockerfile = r#"FROM node:latest
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
"#;
let input_file = create_temp_dockerfile(dockerfile);
let output_dir = TempDir::new().expect("Failed to create temp dir");
let output_file = output_dir.path().join("Dockerfile");
bashrs_cmd()
.arg("dockerfile")
.arg("purify")
.arg(input_file.path())
.arg("-o")
.arg(&output_file)
.assert()
.success();
let purified = fs::read_to_string(&output_file).expect("Failed to read purified file");
assert!(
!purified.contains("node:latest"),
"Node.js Dockerfile should not have :latest tag"
);
assert!(purified.contains("WORKDIR /app"));
assert!(purified.contains("EXPOSE 3000"));
assert!(purified.contains("CMD"));
}
#[test]
fn test_integration_python_dockerfile() {
let dockerfile = r#"FROM python:latest
WORKDIR /app
RUN apt-get update && apt-get install -y gcc g++ make
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
"#;
let input_file = create_temp_dockerfile(dockerfile);
let output_dir = TempDir::new().expect("Failed to create temp dir");
let output_file = output_dir.path().join("Dockerfile");
bashrs_cmd()
.arg("dockerfile")
.arg("purify")
.arg(input_file.path())
.arg("-o")
.arg(&output_file)
.assert()
.success();
let purified = fs::read_to_string(&output_file).expect("Failed to read purified file");
assert!(!purified.contains("python:latest"));
assert!(purified.contains("--no-install-recommends"));
assert!(purified.contains("/var/lib/apt/lists"));
}
#[test]
fn test_integration_idempotency_purify_twice() {
let dockerfile = r#"FROM ubuntu:latest
RUN apt-get install -y nginx
"#;
let input_file = create_temp_dockerfile(dockerfile);
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let output1 = temp_dir.path().join("Dockerfile.purified1");
bashrs_cmd()
.arg("dockerfile")
.arg("purify")
.arg(input_file.path())
.arg("-o")
.arg(&output1)
.assert()
.success();
let purified1 = fs::read_to_string(&output1).expect("Failed to read first purified file");
let output2 = temp_dir.path().join("Dockerfile.purified2");
bashrs_cmd()
.arg("dockerfile")
.arg("purify")
.arg(&output1)
.arg("-o")
.arg(&output2)
.assert()
.success();
let purified2 = fs::read_to_string(&output2).expect("Failed to read second purified file");
assert_eq!(
purified1, purified2,
"Purification should be idempotent (same result when applied twice)"
);
}
#[test]
fn test_integration_comments_preserved() {
let dockerfile = r#"# Base image
FROM ubuntu:latest
# Update and install packages
RUN apt-get update && apt-get install -y curl
# Copy application files
COPY app.py /app/
"#;
let input_file = create_temp_dockerfile(dockerfile);
let output_dir = TempDir::new().expect("Failed to create temp dir");
let output_file = output_dir.path().join("Dockerfile");
bashrs_cmd()
.arg("dockerfile")
.arg("purify")
.arg(input_file.path())
.arg("-o")
.arg(&output_file)
.assert()
.success();
let purified = fs::read_to_string(&output_file).expect("Failed to read purified file");
assert!(purified.contains("# Base image"));
assert!(purified.contains("# Update and install packages"));
assert!(purified.contains("# Copy application files"));
assert!(!purified.contains("ubuntu:latest"));
}
#[test]
fn test_integration_complex_multiline_run() {
let dockerfile = r#"FROM ubuntu:latest
RUN apt-get update && \
apt-get install -y \
curl \
wget \
git && \
rm -rf /var/cache/apt/*
"#;
let input_file = create_temp_dockerfile(dockerfile);
let output_dir = TempDir::new().expect("Failed to create temp dir");
let output_file = output_dir.path().join("Dockerfile");
bashrs_cmd()
.arg("dockerfile")
.arg("purify")
.arg(input_file.path())
.arg("-o")
.arg(&output_file)
.assert()
.success();
let purified = fs::read_to_string(&output_file).expect("Failed to read purified file");
assert!(
purified.contains("apt-get update && \\"),
"Multi-line structure should be preserved"
);
assert!(
purified.contains("apt-get install -y \\"),
"Multi-line continuation should be preserved"
);
assert!(!purified.contains("ubuntu:latest"));
}
#[test]
fn test_integration_alpine_apk_workflow() {
let dockerfile = r#"FROM alpine:latest
RUN apk update && apk add curl wget
COPY app.sh /app/
"#;
let input_file = create_temp_dockerfile(dockerfile);
let output_dir = TempDir::new().expect("Failed to create temp dir");
let output_file = output_dir.path().join("Dockerfile");
bashrs_cmd()
.arg("dockerfile")
.arg("purify")
.arg(input_file.path())
.arg("-o")
.arg(&output_file)
.assert()
.success();
let purified = fs::read_to_string(&output_file).expect("Failed to read purified file");
assert!(!purified.contains("alpine:latest"));
assert!(purified.contains("/var/cache/apk"));
}
#[test]
fn test_integration_empty_dockerfile() {
let dockerfile = "# Just a comment\n";
let input_file = create_temp_dockerfile(dockerfile);
let output_dir = TempDir::new().expect("Failed to create temp dir");
let output_file = output_dir.path().join("Dockerfile");
bashrs_cmd()
.arg("dockerfile")
.arg("purify")
.arg(input_file.path())
.arg("-o")
.arg(&output_file)
.assert()
.success();
let purified = fs::read_to_string(&output_file).expect("Failed to read purified file");
assert!(purified.contains("# Just a comment"));
}
#[test]
fn test_integration_determinism_multiple_runs() {
let dockerfile = r#"FROM ubuntu:latest
RUN apt-get update && apt-get install -y nginx curl
ADD local.txt /app/
"#;
let input_file = create_temp_dockerfile(dockerfile);
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let mut outputs = Vec::new();
for i in 0..3 {
let output = temp_dir.path().join(format!("Dockerfile.purified{}", i));
bashrs_cmd()
.arg("dockerfile")
.arg("purify")
.arg(input_file.path())
.arg("-o")
.arg(&output)
.assert()
.success();
let content = fs::read_to_string(&output).expect("Failed to read purified file");
outputs.push(content);
}
assert_eq!(
outputs[0], outputs[1],
"Run 1 and 2 should produce identical results"
);
assert_eq!(
outputs[1], outputs[2],
"Run 2 and 3 should produce identical results"
);
}
#[test]
fn test_integration_large_dockerfile_performance() {
let mut dockerfile = String::from("FROM ubuntu:latest\n");
for i in 0..50 {
dockerfile.push_str(&format!("RUN apt-get install -y package{}\n", i));
}
let input_file = create_temp_dockerfile(&dockerfile);
let output_dir = TempDir::new().expect("Failed to create temp dir");
let output_file = output_dir.path().join("Dockerfile");
bashrs_cmd()
.arg("dockerfile")
.arg("purify")
.arg(input_file.path())
.arg("-o")
.arg(&output_file)
.assert()
.success();
let purified = fs::read_to_string(&output_file).expect("Failed to read purified file");
assert_eq!(
purified.matches("--no-install-recommends").count(),
50,
"All 50 RUN commands should have --no-install-recommends"
);
}