use dtb_file::*;
use fdt_edit::*;
#[test]
fn test_encode_empty_fdt() {
let fdt = Fdt::new();
let encoded = fdt.encode();
assert!(!encoded.is_empty());
assert!(encoded.len() >= 40);
let parsed = Fdt::from_bytes(&encoded);
assert!(parsed.is_ok());
}
#[test]
fn test_encode_with_properties() {
let mut fdt = Fdt::new();
let root_id = fdt.root_id();
let node = fdt.node_mut(root_id).unwrap();
node.set_property(crate::Property::new(
"#address-cells",
vec![0x00, 0x00, 0x00, 0x02],
));
node.set_property(crate::Property::new(
"#size-cells",
vec![0x00, 0x00, 0x00, 0x01],
));
node.set_property(crate::Property::new("model", {
let mut v = b"Test Device".to_vec();
v.push(0);
v
}));
let encoded = fdt.encode();
let parsed = Fdt::from_bytes(&encoded).unwrap();
let root = parsed.get_by_path("/").unwrap();
let node_ref = root.as_node();
assert_eq!(node_ref.address_cells(), Some(2));
assert_eq!(node_ref.size_cells(), Some(1));
assert_eq!(
node_ref.get_property("model").unwrap().as_str(),
Some("Test Device")
);
}
#[test]
fn test_encode_with_children() {
let mut fdt = Fdt::new();
let root_id = fdt.root_id();
let mut soc = crate::Node::new("soc");
soc.set_property(crate::Property::new(
"#address-cells",
vec![0x00, 0x00, 0x00, 0x02],
));
soc.set_property(crate::Property::new(
"#size-cells",
vec![0x00, 0x00, 0x00, 0x02],
));
let soc_id = fdt.add_node(root_id, soc);
let mut uart = crate::Node::new("uart@1000");
uart.set_property(crate::Property::new("reg", {
let v = vec![0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00];
v
}));
uart.set_property(crate::Property::new("compatible", {
let mut v = b"test,uart".to_vec();
v.push(0);
v
}));
fdt.add_node(soc_id, uart);
let encoded = fdt.encode();
let parsed = Fdt::from_bytes(&encoded).unwrap();
let soc = parsed.get_by_path("/soc").unwrap();
assert_eq!(soc.name(), "soc");
let uart = parsed.get_by_path("/soc/uart@1000").unwrap();
assert_eq!(uart.name(), "uart@1000");
}
#[test]
fn test_parse_and_encode() {
let raw_data = fdt_phytium();
let original = Fdt::from_bytes(&raw_data).unwrap();
let encoded = original.encode();
let reparsed = Fdt::from_bytes(&encoded).unwrap();
assert_eq!(original.boot_cpuid_phys, reparsed.boot_cpuid_phys);
assert_eq!(original.node_count(), reparsed.node_count());
assert_eq!(
original.memory_reservations.len(),
reparsed.memory_reservations.len()
);
for (orig, rep) in original
.memory_reservations
.iter()
.zip(reparsed.memory_reservations.iter())
{
assert_eq!(orig.address, rep.address);
assert_eq!(orig.size, rep.size);
}
for id in original.iter_node_ids() {
let path = original.path_of(id);
let reparsed_id = reparsed.get_by_path_id(&path);
assert!(
reparsed_id.is_some(),
"path {} not found in reparsed FDT",
path
);
}
}
#[test]
fn test_parse_and_encode_rpi() {
let raw_data = fdt_rpi_4b();
let original = Fdt::from_bytes(&raw_data).unwrap();
let encoded = original.encode();
let reparsed = Fdt::from_bytes(&encoded).unwrap();
assert_eq!(original.boot_cpuid_phys, reparsed.boot_cpuid_phys);
assert_eq!(original.node_count(), reparsed.node_count());
}
#[test]
fn test_encode_with_memory_reservations() {
let mut fdt = Fdt::new();
fdt.memory_reservations.push(fdt_raw::MemoryReservation {
address: 0x8000_0000,
size: 0x1000,
});
fdt.memory_reservations.push(fdt_raw::MemoryReservation {
address: 0x9000_0000,
size: 0x2000,
});
let encoded = fdt.encode();
let reparsed = Fdt::from_bytes(&encoded).unwrap();
assert_eq!(reparsed.memory_reservations.len(), 2);
assert_eq!(reparsed.memory_reservations[0].address, 0x8000_0000);
assert_eq!(reparsed.memory_reservations[0].size, 0x1000);
assert_eq!(reparsed.memory_reservations[1].address, 0x9000_0000);
assert_eq!(reparsed.memory_reservations[1].size, 0x2000);
}
#[test]
fn test_encode_with_reserve_dtb() {
let raw_data = fdt_reserve();
let original = Fdt::from_bytes(&raw_data).unwrap();
let encoded = original.encode();
let reparsed = Fdt::from_bytes(&encoded).unwrap();
assert_eq!(
original.memory_reservations.len(),
reparsed.memory_reservations.len()
);
}
#[test]
fn test_encode_properties_integrity() {
let mut fdt = Fdt::new();
let root_id = fdt.root_id();
let node = fdt.node_mut(root_id).unwrap();
node.set_property(crate::Property::new(
"prop-u32",
0x12345678u32.to_be_bytes().to_vec(),
));
node.set_property(crate::Property::new(
"prop-u64",
0x1234567890ABCDEFu64.to_be_bytes().to_vec(),
));
node.set_property(crate::Property::new("prop-string", {
let mut v = b"test string".to_vec();
v.push(0);
v
}));
{
let v = b"first\0second\0third\0".to_vec();
node.set_property(crate::Property::new("prop-string-list", v));
}
{
let v = vec![
0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x40,
0x00, 0x00,
];
node.set_property(crate::Property::new("reg", v));
}
let encoded = fdt.encode();
let reparsed = Fdt::from_bytes(&encoded).unwrap();
let root = reparsed.get_by_path("/").unwrap();
let node_ref = root.as_node();
let prop_u32 = node_ref.get_property("prop-u32").unwrap();
assert_eq!(prop_u32.get_u32(), Some(0x12345678));
let prop_u64 = node_ref.get_property("prop-u64").unwrap();
assert_eq!(prop_u64.get_u64(), Some(0x1234567890ABCDEF));
let prop_string = node_ref.get_property("prop-string").unwrap();
assert_eq!(prop_string.as_str(), Some("test string"));
let prop_list = node_ref.get_property("prop-string-list").unwrap();
let strings: Vec<&str> = prop_list.as_str_iter().collect();
assert_eq!(strings, vec!["first", "second", "third"]);
}