summaryrefslogtreecommitdiff
path: root/tests/build.rs
blob: fd919a00081f78add9f33cb50ebc6f51c33ed6e0 (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
use std::cell::RefCell;
use std::fs;

use alt_controller_image::build::BuildExecutor;
use alt_controller_image::initramfs::{InitramfsBuilder, InitramfsRequest, InitramfsResult};
use alt_controller_image::manifest::ArtifactManifest;
use alt_controller_image::package_installer::{PackageInstaller, PackageRequest};
use alt_controller_image::{BuildPlan, ImageSpec};
use tempfile::tempdir;

#[derive(Default)]
struct FixtureInstaller {
    requests: RefCell<Vec<PackageRequest>>,
}

impl PackageInstaller for FixtureInstaller {
    fn install(&self, request: &PackageRequest) -> anyhow::Result<()> {
        self.requests.borrow_mut().push(request.clone());
        let boot = request.workdir().join("chroot/boot");
        fs::create_dir_all(&boot)?;
        fs::write(boot.join("vmlinuz-6.12.0-rt1"), "kernel")?;
        Ok(())
    }
}

#[derive(Default)]
struct FixtureInitramfsBuilder;

impl InitramfsBuilder for FixtureInitramfsBuilder {
    fn build(&mut self, request: &InitramfsRequest) -> anyhow::Result<InitramfsResult> {
        fs::write(
            request
                .rootfs()
                .join(format!("boot/initrd-{}.img", request.kernel().as_str())),
            "initrd",
        )?;
        InitramfsResult::from_rootfs(request.rootfs(), request.kernel())
    }
}

#[test]
fn executes_the_native_build_stages_and_writes_a_companion_manifest() {
    let fixture = tempdir().expect("fixture directory");
    let spec = ImageSpec::load(std::path::Path::new("profiles/alt-controller.toml"))
        .expect("load controller spec");
    let plan = BuildPlan::compile(spec).expect("compile build plan");
    let installer = FixtureInstaller::default();
    let mut executor = BuildExecutor::new(&installer, FixtureInitramfsBuilder);
    let workspace = fixture.path().join("work");
    let artifact = fixture.path().join("out/controller.tar");

    let result = executor
        .execute(&plan, &workspace, "profiles/apt.conf", &artifact)
        .expect("execute native build");

    assert_eq!(installer.requests.borrow().len(), 1);
    assert_eq!(result.artifact(), artifact);
    assert_eq!(
        fs::read_to_string(workspace.join("chroot/etc/initrd.mk.oem")).expect("read OEM recipe"),
        "FEATURES += add-modules cleanup compress qemu rdshell rootfs usb\nMODULES += ahci.ko ahci_platform.ko ext4 sd_mod.ko virtio_blk.ko virtio_net.ko virtio_pci.ko\n"
    );
    assert!(artifact.is_file());
    let manifest = ArtifactManifest::load(result.manifest()).expect("load companion manifest");
    let initrd = result.initrd().expect("initrd result");
    assert_eq!(
        manifest.initrd,
        Some(alt_controller_image::manifest::InitrdRecord::new(
            initrd.initrd_path().display().to_string(),
            initrd.sha256(),
        ))
    );
}

#[test]
fn refuses_to_reuse_an_existing_workspace() {
    let fixture = tempdir().expect("fixture directory");
    let spec = ImageSpec::load(std::path::Path::new("profiles/alt-controller.toml"))
        .expect("load controller spec");
    let plan = BuildPlan::compile(spec).expect("compile build plan");
    let installer = FixtureInstaller::default();
    let mut executor = BuildExecutor::new(&installer, FixtureInitramfsBuilder);
    let workspace = fixture.path().join("existing-work");
    fs::create_dir(&workspace).expect("create existing workspace");

    let error = executor
        .execute(&plan, &workspace, "profiles/apt.conf", fixture.path().join("image.tar"))
        .expect_err("existing workspace must be rejected");

    assert!(error.to_string().contains("workspace already exists"));
    assert!(installer.requests.borrow().is_empty());
}