fn test_DOCKER_COV_008_expr_to_string_i32() {
let ast = make_simple_ast(vec![
Stmt::Expr(Expr::FunctionCall {
name: "from_image".to_string(),
args: vec![
Expr::Literal(Literal::Str("alpine".to_string())),
Expr::Literal(Literal::Str("3.18".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "label".to_string(),
args: vec![
Expr::Literal(Literal::Str("count".to_string())),
Expr::Literal(Literal::I32(-1)),
],
}),
]);
let result = emit_dockerfile(&ast).unwrap();
assert!(result.contains("-1"), "I32 label in: {result}");
}
#[test]
fn test_DOCKER_COV_009_expr_to_string_bool() {
let ast = make_simple_ast(vec![
Stmt::Expr(Expr::FunctionCall {
name: "from_image".to_string(),
args: vec![
Expr::Literal(Literal::Str("alpine".to_string())),
Expr::Literal(Literal::Str("3.18".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "label".to_string(),
args: vec![
Expr::Literal(Literal::Str("debug".to_string())),
Expr::Literal(Literal::Bool(true)),
],
}),
]);
let result = emit_dockerfile(&ast).unwrap();
assert!(result.contains("true"), "Bool label in: {result}");
}
#[test]
fn test_DOCKER_COV_010_expr_to_string_error() {
let ast = make_simple_ast(vec![
Stmt::Expr(Expr::FunctionCall {
name: "from_image".to_string(),
args: vec![
Expr::Literal(Literal::Str("alpine".to_string())),
Expr::Literal(Literal::Str("3.18".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "label".to_string(),
args: vec![
Expr::Literal(Literal::Str("key".to_string())),
Expr::Array(vec![Expr::Literal(Literal::Str("a".to_string()))]),
],
}),
]);
let err = emit_dockerfile(&ast).unwrap_err();
assert!(
format!("{err}").contains("Cannot convert expression"),
"Error: {err}"
);
}
#[test]
fn test_DOCKER_COV_011_instructions_before_from_image() {
let ast = make_simple_ast(vec![
Stmt::Expr(Expr::FunctionCall {
name: "workdir".to_string(),
args: vec![Expr::Literal(Literal::Str("/app".to_string()))],
}),
Stmt::Expr(Expr::FunctionCall {
name: "expose".to_string(),
args: vec![Expr::Literal(Literal::U16(8080))],
}),
Stmt::Expr(Expr::FunctionCall {
name: "user".to_string(),
args: vec![Expr::Literal(Literal::Str("root".to_string()))],
}),
Stmt::Expr(Expr::FunctionCall {
name: "healthcheck".to_string(),
args: vec![Expr::Literal(Literal::Str("curl localhost".to_string()))],
}),
Stmt::Expr(Expr::FunctionCall {
name: "comment".to_string(),
args: vec![Expr::Literal(Literal::Str("test".to_string()))],
}),
Stmt::Expr(Expr::FunctionCall {
name: "from_image".to_string(),
args: vec![
Expr::Literal(Literal::Str("alpine".to_string())),
Expr::Literal(Literal::Str("3.18".to_string())),
],
}),
]);
let result = emit_dockerfile(&ast).unwrap();
assert!(result.contains("FROM alpine:3.18"));
assert!(!result.contains("WORKDIR"), "No WORKDIR before FROM");
}
#[test]
fn test_DOCKER_COV_012_instructions_with_empty_args() {
let ast = make_simple_ast(vec![
Stmt::Expr(Expr::FunctionCall {
name: "from_image".to_string(),
args: vec![
Expr::Literal(Literal::Str("alpine".to_string())),
Expr::Literal(Literal::Str("3.18".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "workdir".to_string(),
args: vec![],
}),
Stmt::Expr(Expr::FunctionCall {
name: "expose".to_string(),
args: vec![],
}),
Stmt::Expr(Expr::FunctionCall {
name: "user".to_string(),
args: vec![],
}),
Stmt::Expr(Expr::FunctionCall {
name: "healthcheck".to_string(),
args: vec![],
}),
Stmt::Expr(Expr::FunctionCall {
name: "comment".to_string(),
args: vec![],
}),
]);
let result = emit_dockerfile(&ast).unwrap();
assert!(result.contains("FROM alpine:3.18"));
assert!(!result.contains("WORKDIR"), "No WORKDIR with empty args");
assert!(!result.contains("EXPOSE"), "No EXPOSE with empty args");
assert!(!result.contains("USER"), "No USER with empty args");
assert!(
!result.contains("HEALTHCHECK"),
"No HEALTHCHECK with empty args"
);
}
#[test]
fn test_DOCKER_COV_013_from_image_single_arg_with_tag() {
let ast = make_simple_ast(vec![Stmt::Expr(Expr::FunctionCall {
name: "from_image".to_string(),
args: vec![Expr::Literal(Literal::Str("alpine:3.18".to_string()))],
})]);
let result = emit_dockerfile(&ast).expect("single-arg with tag should succeed");
assert!(
result.contains("FROM alpine:3.18"),
"Expected FROM alpine:3.18, got: {result}"
);
}
#[test]
fn test_DOCKER_COV_014_from_image_as_two_args_no_tag() {
let ast = make_simple_ast(vec![Stmt::Expr(Expr::FunctionCall {
name: "from_image_as".to_string(),
args: vec![
Expr::Literal(Literal::Str("rust".to_string())),
Expr::Literal(Literal::Str("builder".to_string())),
],
})]);
let result = emit_dockerfile(&ast).expect("2-arg from_image_as should succeed");
assert!(
result.contains("FROM rust:latest AS builder"),
"Expected FROM rust:latest AS builder, got: {result}"
);
}
#[test]
fn test_DOCKER_COV_015_copy_too_few_args() {
let ast = make_simple_ast(vec![
Stmt::Expr(Expr::FunctionCall {
name: "from_image".to_string(),
args: vec![
Expr::Literal(Literal::Str("alpine".to_string())),
Expr::Literal(Literal::Str("3.18".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "copy".to_string(),
args: vec![Expr::Literal(Literal::Str("src".to_string()))],
}),
]);
let err = emit_dockerfile(&ast).unwrap_err();
assert!(format!("{err}").contains("2 arguments"), "Error: {err}");
}
#[test]
fn test_DOCKER_COV_016_copy_from_too_few_args() {
let ast = make_simple_ast(vec![
Stmt::Expr(Expr::FunctionCall {
name: "from_image".to_string(),
args: vec![
Expr::Literal(Literal::Str("alpine".to_string())),
Expr::Literal(Literal::Str("3.18".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "copy_from".to_string(),
args: vec![
Expr::Literal(Literal::Str("builder".to_string())),
Expr::Literal(Literal::Str("/src".to_string())),
],
}),
]);
let err = emit_dockerfile(&ast).unwrap_err();
assert!(format!("{err}").contains("3 arguments"), "Error: {err}");
}
#[test]
fn test_DOCKER_COV_017_env_too_few_args() {
let ast = make_simple_ast(vec![
Stmt::Expr(Expr::FunctionCall {
name: "from_image".to_string(),
args: vec![
Expr::Literal(Literal::Str("alpine".to_string())),
Expr::Literal(Literal::Str("3.18".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "env".to_string(),
args: vec![Expr::Literal(Literal::Str("KEY".to_string()))],
}),
]);
let err = emit_dockerfile(&ast).unwrap_err();
assert!(format!("{err}").contains("2 arguments"), "Error: {err}");
}
#[test]
fn test_DOCKER_COV_018_expose_u32() {
let ast = make_simple_ast(vec![
Stmt::Expr(Expr::FunctionCall {
name: "from_image".to_string(),
args: vec![
Expr::Literal(Literal::Str("alpine".to_string())),
Expr::Literal(Literal::Str("3.18".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "expose".to_string(),
args: vec![Expr::Literal(Literal::U32(3000))],
}),
]);
let result = emit_dockerfile(&ast).unwrap();
assert!(result.contains("EXPOSE 3000"), "U32 expose in: {result}");
}
#[test]
fn test_DOCKER_COV_019_expose_i32() {
let ast = make_simple_ast(vec![
Stmt::Expr(Expr::FunctionCall {
name: "from_image".to_string(),
args: vec![
Expr::Literal(Literal::Str("alpine".to_string())),
Expr::Literal(Literal::Str("3.18".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "expose".to_string(),
args: vec![Expr::Literal(Literal::I32(9090))],
}),
]);
let result = emit_dockerfile(&ast).unwrap();
assert!(result.contains("EXPOSE 9090"), "I32 expose in: {result}");
}
#[test]
fn test_DOCKER_COV_020_cmd_instruction() {
let ast = make_simple_ast(vec![
Stmt::Expr(Expr::FunctionCall {
name: "from_image".to_string(),
args: vec![
Expr::Literal(Literal::Str("alpine".to_string())),
Expr::Literal(Literal::Str("3.18".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "cmd".to_string(),
args: vec![Expr::Array(vec![
Expr::Literal(Literal::Str("/bin/sh".to_string())),
Expr::Literal(Literal::Str("-c".to_string())),
Expr::Literal(Literal::Str("echo hello".to_string())),
])],
}),
]);
let result = emit_dockerfile(&ast).unwrap();
assert!(result.contains("CMD"), "CMD in: {result}");
}
#[test]
fn test_DOCKER_COV_021_no_stage_run_copy_env() {
let ast = make_simple_ast(vec![
Stmt::Expr(Expr::FunctionCall {
name: "run".to_string(),
args: vec![Expr::Literal(Literal::Str("echo hi".to_string()))],
}),
Stmt::Expr(Expr::FunctionCall {
name: "copy".to_string(),
args: vec![
Expr::Literal(Literal::Str("src".to_string())),
Expr::Literal(Literal::Str("dst".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "env".to_string(),
args: vec![
Expr::Literal(Literal::Str("K".to_string())),
Expr::Literal(Literal::Str("V".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "label".to_string(),
args: vec![
Expr::Literal(Literal::Str("k".to_string())),
Expr::Literal(Literal::Str("v".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "entrypoint".to_string(),
args: vec![Expr::Literal(Literal::Str("/bin/sh".to_string()))],
}),
Stmt::Expr(Expr::FunctionCall {
name: "cmd".to_string(),
args: vec![Expr::Literal(Literal::Str("echo".to_string()))],
}),
Stmt::Expr(Expr::FunctionCall {
name: "copy_from".to_string(),
args: vec![
Expr::Literal(Literal::Str("builder".to_string())),
Expr::Literal(Literal::Str("/a".to_string())),
Expr::Literal(Literal::Str("/b".to_string())),
],
}),
Stmt::Expr(Expr::FunctionCall {
name: "from_image".to_string(),
args: vec![
Expr::Literal(Literal::Str("alpine".to_string())),
Expr::Literal(Literal::Str("3.18".to_string())),
],
}),
]);
let result = emit_dockerfile(&ast).unwrap();
assert!(result.contains("FROM alpine:3.18"));
assert!(!result.contains("RUN"), "No RUN before FROM");
}
#[test]
include!("dockerfile_tests_tests_DOCKER.rs");