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
107
108
109
110
111
|
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());
}
#[test]
fn rejects_a_missing_apt_configuration_before_creating_the_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("work");
let missing_apt_config = fixture.path().join("missing-apt.conf");
let error = executor
.execute(&plan, &workspace, &missing_apt_config, fixture.path().join("image.tar"))
.expect_err("missing APT configuration must be rejected");
assert!(error.to_string().contains("APT configuration does not exist"));
assert!(!workspace.exists());
assert!(installer.requests.borrow().is_empty());
}
|