summaryrefslogtreecommitdiff
path: root/tests/model_validation.rs
blob: f94a656897be18c53916436c95d961dde6dfa6d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use std::fs;

use alt_controller_image::{BuildPlan, ImageSpec, OutputFormat};

fn write_spec(contents: &str) -> tempfile::TempDir {
    let directory = tempfile::tempdir().expect("temporary spec directory");
    fs::write(directory.path().join("image.toml"), contents).expect("write spec");
    directory
}

fn load(contents: &str) -> anyhow::Result<ImageSpec> {
    let directory = write_spec(contents);
    ImageSpec::load(&directory.path().join("image.toml"))
}

const VALID_SPEC: &str = r#"
[target]
name = "alt-controller"
architecture = "x86_64"
format = "tar"

[kernel]
flavour = "rt"

[boot]
initrd_features = ["rootfs"]
initrd_modules = ["ext4", "virtio_blk.ko"]

[packages]
base = ["basesystem"]
selectors = ["^kernel-image-rt$"]
"#;

#[test]
fn parses_a_typed_image_spec() {
    let spec = load(VALID_SPEC).expect("valid spec");

    assert_eq!(spec.target.name, "alt-controller");
    assert_eq!(spec.target.architecture.as_str(), "x86_64");
    assert_eq!(spec.target.format, OutputFormat::Tar);
    assert_eq!(spec.packages.selectors[0].as_str(), "^kernel-image-rt$");
}

#[test]
fn controller_spec_preserves_the_vendored_controller_package_set() {
    let spec = ImageSpec::load(std::path::Path::new("profiles/alt-controller.toml"))
        .expect("controller spec parses");

    assert_eq!(spec.packages.base.len(), 96);
    for package in [
        "make-initrd-multipath",
        "firmware-intel-ucode",
        "openssh-server-control",
        "systemd-analyze",
        "libiec61850",
        "rsyslog",
    ] {
        assert!(
            spec.packages.base.iter().any(|candidate| candidate == package),
            "controller package set must contain {package}"
        );
    }
}

#[test]
fn compiles_a_validated_spec_into_an_immutable_build_plan() {
    let spec = load(VALID_SPEC).expect("valid spec");
    let plan = BuildPlan::compile(spec).expect("plan compiles");

    assert_eq!(plan.spec().target.name, "alt-controller");
}

#[test]
fn rejects_an_unknown_target_format() {
    let error = load(&VALID_SPEC.replace("format = \"tar\"", "format = \"iso\""))
        .expect_err("unsupported format must fail");

    assert!(format!("{error:#}").contains("unsupported output format"));
}

#[test]
fn rejects_an_unsupported_architecture() {
    let error = load(&VALID_SPEC.replace("x86_64", "aarch64"))
        .expect_err("unsupported architecture must fail");

    assert!(format!("{error:#}").contains("unsupported architecture"));
}

#[test]
fn rejects_duplicate_package_selectors() {
    let error = load(&VALID_SPEC.replace(
        "selectors = [\"^kernel-image-rt$\"]",
        "selectors = [\"^kernel-image-rt$\", \"^kernel-image-rt$\"]",
    ))
    .expect_err("duplicate selector must fail");

    assert!(format!("{error:#}").contains("duplicate package selector"));
}

#[test]
fn rejects_an_invalid_initrd_module_name() {
    let error = load(&VALID_SPEC.replace("\"virtio_blk.ko\"", "\"../virtio_blk.ko\""))
        .expect_err("unsafe module name must fail");

    assert!(format!("{error:#}").contains("invalid initrd module"));
}