fn test_d020_numeric_user() {
let dockerfile = r#"FROM debian:12-slim
USER 1000:1000
COPY app /app
CMD ["/app"]
"#;
let (_, output) = lint_dockerfile(dockerfile);
let has_user_warning = has_rule(&output, "DOCKER001");
if has_user_warning {
println!("D020: INFO - Numeric USER should be accepted");
}
}
#[test]
fn test_d021_apt_no_clean() {
let dockerfile = r#"FROM ubuntu:22.04
RUN apt-get update && apt-get install -y curl
"#;
let (_, output) = lint_dockerfile(dockerfile);
let has_warning = output.to_lowercase().contains("clean")
|| output.to_lowercase().contains("rm -rf")
|| has_rule(&output, "DOCKER003");
if !has_warning {
println!("D021: INFO - Could suggest apt-get clean after install");
}
}
#[test]
fn test_d022_apt_recommends() {
let dockerfile = r#"FROM ubuntu:22.04
RUN apt-get update && apt-get install -y curl
"#;
let (_, output) = lint_dockerfile(dockerfile);
let has_warning = output.to_lowercase().contains("recommend") || has_rule(&output, "DF005");
if !has_warning {
println!("D022: INFO - Could suggest --no-install-recommends");
}
}
#[test]
fn test_d023_apt_yes_missing() {
let dockerfile = r#"FROM ubuntu:22.04
RUN apt-get update && apt-get install curl
"#;
let (_, output) = lint_dockerfile(dockerfile);
if !output.contains("-y") && !output.to_lowercase().contains("interactive") {
println!("D023: INFO - Should use apt-get install -y for non-interactive");
}
}
#[test]
fn test_d024_apk_no_cache() {
let dockerfile = r#"FROM alpine:3.19
RUN apk add curl
"#;
let (_, output) = lint_dockerfile(dockerfile);
let has_warning =
output.to_lowercase().contains("cache") || output.to_lowercase().contains("apk");
if !has_warning {
println!("D024: INFO - Could suggest 'apk add --no-cache' for Alpine");
}
}
#[test]
fn test_d025_pip_no_cache() {
let dockerfile = r#"FROM python:3.11
RUN pip install requests
"#;
let (_, output) = lint_dockerfile(dockerfile);
let has_warning =
output.to_lowercase().contains("cache") || output.to_lowercase().contains("pip");
if !has_warning {
println!("D025: INFO - Could suggest 'pip install --no-cache-dir'");
}
}
#[test]
fn test_d026_arg_secret() {
let dockerfile = r#"FROM ubuntu:22.04
ARG API_KEY
ARG SECRET_TOKEN
RUN echo "Using key: $API_KEY"
"#;
let (_, output) = lint_dockerfile(dockerfile);
let has_warning = output.to_lowercase().contains("secret")
|| output.to_lowercase().contains("arg")
|| has_rule(&output, "DOCKER002");
if !has_warning {
println!("D026: WARNING - Should detect secrets in ARG");
}
}
#[test]
fn test_d027_sudo_usage() {
let dockerfile = r#"FROM ubuntu:22.04
RUN sudo apt-get update
"#;
let (_, output) = lint_dockerfile(dockerfile);
let has_warning = output.to_lowercase().contains("sudo");
if !has_warning {
println!("D027: INFO - Could warn about sudo usage in Dockerfile");
}
}
#[test]
fn test_d028_multiple_cmd() {
let dockerfile = r#"FROM ubuntu:22.04
CMD ["echo", "first"]
CMD ["echo", "second"]
"#;
let (_, output) = lint_dockerfile(dockerfile);
let has_warning =
output.to_lowercase().contains("cmd") || output.to_lowercase().contains("override");
if !has_warning {
println!("D028: INFO - Could warn about multiple CMD instructions");
}
}
#[test]
fn test_d029_entrypoint_cmd_both() {
let dockerfile = r#"FROM ubuntu:22.04
ENTRYPOINT ["python"]
CMD ["app.py"]
"#;
let (_, _output) = lint_dockerfile(dockerfile);
println!("D029: INFO - ENTRYPOINT + CMD is valid pattern");
}
#[test]
fn test_d030_large_base_image() {
let dockerfile = r#"FROM ubuntu:22.04
RUN echo hello
"#;
let (_, output) = lint_dockerfile(dockerfile);
let has_warning = output.to_lowercase().contains("alpine")
|| output.to_lowercase().contains("distroless")
|| output.to_lowercase().contains("slim")
|| has_rule(&output, "DF010");
if !has_warning {
println!("D030: INFO - Could suggest smaller base image");
}
}
#[test]
fn test_dcode_comprehensive_summary() {
println!("\n");
println!("╔══════════════════════════════════════════════════════════════════════════════╗");
println!("║ D-CODE DOCKERFILE TEST SUMMARY (SPEC-TB-2025-001 v2.1.0) ║");
println!("╠══════════════════════════════════════════════════════════════════════════════╣");
println!("║ ║");
println!("║ Implemented Lint Rules: ║");
println!("║ DOCKER001: Missing USER directive (security) ║");
println!("║ DOCKER002: Secrets in ENV/ARG ║");
println!("║ DOCKER003: Separate apt-get update ║");
println!("║ DOCKER004: Curl pipe to shell ║");
println!("║ DOCKER005: apt-get without cleanup ║");
println!("║ DOCKER006: Using :latest tag ║");
println!("║ ║");
println!("║ D-Codes test Dockerfile linting per Part VII of the spec. ║");
println!("║ ║");
println!("╚══════════════════════════════════════════════════════════════════════════════╝");
}