Skip to content

Commit 1b55337

Browse files
parser/bls: Add tests for bls parser
Signed-off-by: Johan-Liebert1 <[email protected]>
1 parent 63a3d3e commit 1b55337

File tree

6 files changed

+204
-90
lines changed

6 files changed

+204
-90
lines changed

crates/lib/src/bls_config.rs

Lines changed: 0 additions & 87 deletions
This file was deleted.

crates/lib/src/deploy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ use ostree_ext::sysroot::SysrootLock;
2525
use ostree_ext::tokio_util::spawn_blocking_cancellable_flatten;
2626
use rustix::fs::{fsync, renameat_with, AtFlags, RenameFlags};
2727

28-
use crate::bls_config::{parse_bls_config, BLSConfig};
2928
use crate::composefs_consts::{
3029
BOOT_LOADER_ENTRIES, ROLLBACK_BOOT_LOADER_ENTRIES, USER_CFG, USER_CFG_ROLLBACK,
3130
};
3231
use crate::install::{get_efi_uuid_source, BootType};
32+
use crate::parsers::bls_config::{parse_bls_config, BLSConfig};
3333
use crate::parsers::grub_menuconfig::{parse_grub_menuentry_file, MenuEntry};
3434
use crate::progress_jsonl::{Event, ProgressWriter, SubTaskBytes, SubTaskStep};
3535
use crate::spec::ImageReference;

crates/lib/src/install.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ use serde::{Deserialize, Serialize};
7474

7575
#[cfg(feature = "install-to-disk")]
7676
use self::baseline::InstallBlockDeviceOpts;
77-
use crate::bls_config::{parse_bls_config, BLSConfig};
7877
use crate::boundimage::{BoundImage, ResolvedBoundImage};
7978
use crate::composefs_consts::{
8079
BOOT_LOADER_ENTRIES, COMPOSEFS_CMDLINE, COMPOSEFS_INSECURE_CMDLINE,
@@ -88,6 +87,7 @@ use crate::deploy::{
8887
PreparedPullResult,
8988
};
9089
use crate::lsm;
90+
use crate::parsers::bls_config::{parse_bls_config, BLSConfig};
9191
use crate::parsers::grub_menuconfig::MenuEntry;
9292
use crate::progress_jsonl::ProgressWriter;
9393
use crate::spec::ImageReference;

crates/lib/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
//! to provide a fully "container native" tool for using
55
//! bootable container images.
66
7-
mod bls_config;
87
mod boundimage;
98
pub mod cli;
109
mod composefs_consts;

crates/lib/src/parsers/bls_config.rs

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
use anyhow::Result;
2+
use serde::de::Error;
3+
use serde::{Deserialize, Deserializer};
4+
use std::collections::HashMap;
5+
use std::fmt::Display;
6+
7+
#[derive(Debug, Deserialize, Eq)]
8+
pub(crate) struct BLSConfig {
9+
pub(crate) title: Option<String>,
10+
#[serde(deserialize_with = "deserialize_version")]
11+
pub(crate) version: u32,
12+
pub(crate) linux: String,
13+
pub(crate) initrd: String,
14+
pub(crate) options: String,
15+
16+
#[serde(flatten)]
17+
pub(crate) extra: HashMap<String, String>,
18+
}
19+
20+
impl PartialEq for BLSConfig {
21+
fn eq(&self, other: &Self) -> bool {
22+
self.version == other.version
23+
}
24+
}
25+
26+
impl PartialOrd for BLSConfig {
27+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
28+
self.version.partial_cmp(&other.version)
29+
}
30+
}
31+
32+
impl Ord for BLSConfig {
33+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
34+
self.version.cmp(&other.version)
35+
}
36+
}
37+
38+
impl Display for BLSConfig {
39+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40+
if let Some(title) = &self.title {
41+
writeln!(f, "title {}", title)?;
42+
}
43+
44+
writeln!(f, "version {}", self.version)?;
45+
writeln!(f, "linux {}", self.linux)?;
46+
writeln!(f, "initrd {}", self.initrd)?;
47+
writeln!(f, "options {}", self.options)?;
48+
49+
for (key, value) in &self.extra {
50+
writeln!(f, "{} {}", key, value)?;
51+
}
52+
53+
Ok(())
54+
}
55+
}
56+
57+
fn deserialize_version<'de, D>(deserializer: D) -> Result<u32, D::Error>
58+
where
59+
D: Deserializer<'de>,
60+
{
61+
let s: Option<String> = Option::deserialize(deserializer)?;
62+
63+
match s {
64+
Some(s) => Ok(s.parse::<u32>().map_err(D::Error::custom)?),
65+
None => Err(D::Error::custom("Version not found")),
66+
}
67+
}
68+
69+
pub(crate) fn parse_bls_config(input: &str) -> Result<BLSConfig> {
70+
let mut map = HashMap::new();
71+
72+
for line in input.lines() {
73+
let line = line.trim();
74+
if line.is_empty() || line.starts_with('#') {
75+
continue;
76+
}
77+
78+
if let Some((key, value)) = line.split_once(' ') {
79+
map.insert(key.to_string(), value.trim().to_string());
80+
}
81+
}
82+
83+
let value = serde_json::to_value(map)?;
84+
let parsed: BLSConfig = serde_json::from_value(value)?;
85+
86+
Ok(parsed)
87+
}
88+
89+
#[cfg(test)]
90+
mod tests {
91+
use super::*;
92+
93+
#[test]
94+
fn test_parse_valid_bls_config() -> Result<()> {
95+
let input = r#"
96+
title Fedora 42.20250623.3.1 (CoreOS)
97+
version 2
98+
linux /boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/vmlinuz-5.14.10
99+
initrd /boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/initramfs-5.14.10.img
100+
options root=UUID=abc123 rw composefs=7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6
101+
custom1 value1
102+
custom2 value2
103+
"#;
104+
105+
let config = parse_bls_config(input)?;
106+
107+
assert_eq!(
108+
config.title,
109+
Some("Fedora 42.20250623.3.1 (CoreOS)".to_string())
110+
);
111+
assert_eq!(config.version, 2);
112+
assert_eq!(config.linux, "/boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/vmlinuz-5.14.10");
113+
assert_eq!(config.initrd, "/boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/initramfs-5.14.10.img");
114+
assert_eq!(config.options, "root=UUID=abc123 rw composefs=7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6");
115+
assert_eq!(config.extra.get("custom1"), Some(&"value1".to_string()));
116+
assert_eq!(config.extra.get("custom2"), Some(&"value2".to_string()));
117+
118+
Ok(())
119+
}
120+
121+
#[test]
122+
fn test_parse_missing_version() {
123+
let input = r#"
124+
title Fedora
125+
linux /vmlinuz
126+
initrd /initramfs.img
127+
options root=UUID=xyz ro quiet
128+
"#;
129+
130+
let parsed = parse_bls_config(input);
131+
assert!(parsed.is_err());
132+
}
133+
134+
#[test]
135+
fn test_parse_invalid_version_format() {
136+
let input = r#"
137+
title Fedora
138+
version not_an_int
139+
linux /vmlinuz
140+
initrd /initramfs.img
141+
options root=UUID=abc composefs=some-uuid
142+
"#;
143+
144+
let parsed = parse_bls_config(input);
145+
assert!(parsed.is_err());
146+
}
147+
148+
#[test]
149+
fn test_display_output() -> Result<()> {
150+
let input = r#"
151+
title Test OS
152+
version 10
153+
linux /boot/vmlinuz
154+
initrd /boot/initrd.img
155+
options root=UUID=abc composefs=some-uuid
156+
foo bar
157+
"#;
158+
159+
let config = parse_bls_config(input)?;
160+
let output = format!("{}", config);
161+
let mut output_lines = output.lines();
162+
163+
assert_eq!(output_lines.next().unwrap(), "title Test OS");
164+
assert_eq!(output_lines.next().unwrap(), "version 10");
165+
assert_eq!(output_lines.next().unwrap(), "linux /boot/vmlinuz");
166+
assert_eq!(output_lines.next().unwrap(), "initrd /boot/initrd.img");
167+
assert_eq!(
168+
output_lines.next().unwrap(),
169+
"options root=UUID=abc composefs=some-uuid"
170+
);
171+
assert_eq!(output_lines.next().unwrap(), "foo bar");
172+
173+
Ok(())
174+
}
175+
176+
#[test]
177+
fn test_ordering() -> Result<()> {
178+
let config1 = parse_bls_config(
179+
r#"
180+
title Entry 1
181+
version 3
182+
linux /vmlinuz-3
183+
initrd /initrd-3
184+
options opt1
185+
"#,
186+
)?;
187+
188+
let config2 = parse_bls_config(
189+
r#"
190+
title Entry 2
191+
version 5
192+
linux /vmlinuz-5
193+
initrd /initrd-5
194+
options opt2
195+
"#,
196+
)?;
197+
198+
assert!(config1 < config2);
199+
Ok(())
200+
}
201+
}

crates/lib/src/parsers/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
pub(crate) mod bls_config;
12
pub(crate) mod grub_menuconfig;

0 commit comments

Comments
 (0)