11ad837a4SLoGin pub mod fstype; 2*c6f35e8aSLoGin pub mod partition; 3*c6f35e8aSLoGin 41ad837a4SLoGin mod utils; 5e2cc487bSLoGin 61ad837a4SLoGin use std::{fs, path::PathBuf}; 71ad837a4SLoGin 81ad837a4SLoGin use anyhow::Result; 91ad837a4SLoGin use fstype::FsType; 10*c6f35e8aSLoGin use partition::PartitionConfig; 111ad837a4SLoGin use serde::Deserialize; 121ad837a4SLoGin 131ad837a4SLoGin /// rootfs配置文件 14*c6f35e8aSLoGin #[derive(Debug, Clone, Deserialize)] 151ad837a4SLoGin pub struct RootFSConfigFile { 161ad837a4SLoGin pub metadata: RootFSMeta, 17*c6f35e8aSLoGin #[serde(default)] 18*c6f35e8aSLoGin pub partition: PartitionConfig, 191ad837a4SLoGin } 201ad837a4SLoGin 211ad837a4SLoGin impl RootFSConfigFile { 22*c6f35e8aSLoGin pub const LBA_SIZE: usize = 512; 231ad837a4SLoGin pub fn load(path: &PathBuf) -> Result<Self> { 241ad837a4SLoGin // 读取文件内容 251ad837a4SLoGin let content = fs::read_to_string(path)?; 261ad837a4SLoGin Self::load_from_str(&content) 271ad837a4SLoGin } 281ad837a4SLoGin 291ad837a4SLoGin pub fn load_from_str(content: &str) -> Result<Self> { 301ad837a4SLoGin let config: RootFSConfigFile = toml::from_str(content)?; 311ad837a4SLoGin 321ad837a4SLoGin Ok(config) 331ad837a4SLoGin } 341ad837a4SLoGin } 351ad837a4SLoGin 361ad837a4SLoGin #[derive(Debug, Clone, Copy, Deserialize)] 371ad837a4SLoGin pub struct RootFSMeta { 381ad837a4SLoGin /// rootfs文件系统类型 391ad837a4SLoGin pub fs_type: FsType, 401ad837a4SLoGin /// rootfs磁盘大小(至少要大于这个值) 41*c6f35e8aSLoGin /// 单位:字节 421ad837a4SLoGin #[serde(deserialize_with = "utils::size::deserialize_size")] 431ad837a4SLoGin pub size: usize, 441ad837a4SLoGin } 451ad837a4SLoGin 461ad837a4SLoGin #[cfg(test)] 471ad837a4SLoGin mod tests { 481ad837a4SLoGin use std::io::Write; 491ad837a4SLoGin 501ad837a4SLoGin use super::*; 511ad837a4SLoGin use tempfile::NamedTempFile; 521ad837a4SLoGin 531ad837a4SLoGin #[test] 541ad837a4SLoGin fn test_load_from_valid_file() { 551ad837a4SLoGin let config_content = r#" 561ad837a4SLoGin [metadata] 571ad837a4SLoGin fs_type = "fat32" 581ad837a4SLoGin size = "1024M" 591ad837a4SLoGin "#; 601ad837a4SLoGin 611ad837a4SLoGin let mut temp_file = NamedTempFile::new().expect("Failed to create temp file"); 621ad837a4SLoGin temp_file 631ad837a4SLoGin .write_all(config_content.as_bytes()) 641ad837a4SLoGin .expect("Failed to write to temp file"); 651ad837a4SLoGin 661ad837a4SLoGin let config_path = PathBuf::from(temp_file.path()); 671ad837a4SLoGin let config = RootFSConfigFile::load(&config_path).expect("Failed to load config"); 681ad837a4SLoGin 691ad837a4SLoGin assert_eq!(config.metadata.fs_type, FsType::Fat32); 701ad837a4SLoGin assert_eq!(config.metadata.size, 1024 * 1024 * 1024); // Assuming `deserialize_size` converts MB to Bytes 711ad837a4SLoGin } 721ad837a4SLoGin 731ad837a4SLoGin #[test] 741ad837a4SLoGin fn test_load_from_valid_str() { 751ad837a4SLoGin let config_content = r#" 761ad837a4SLoGin [metadata] 771ad837a4SLoGin fs_type = "fat32" 781ad837a4SLoGin size = "512M" 791ad837a4SLoGin "#; 801ad837a4SLoGin 811ad837a4SLoGin let config = RootFSConfigFile::load_from_str(config_content) 821ad837a4SLoGin .expect("Failed to load config from str"); 831ad837a4SLoGin 841ad837a4SLoGin assert_eq!(config.metadata.fs_type, FsType::Fat32); 851ad837a4SLoGin assert_eq!(config.metadata.size, 512 * 1024 * 1024); // Assuming `deserialize_size` converts MB to Bytes 861ad837a4SLoGin } 871ad837a4SLoGin #[test] 881ad837a4SLoGin fn test_load_from_invalid_fs_type() { 891ad837a4SLoGin let config_content = r#" 901ad837a4SLoGin [metadata] 911ad837a4SLoGin fs_type = "ABCDE" 921ad837a4SLoGin size = "512M" 931ad837a4SLoGin "#; 941ad837a4SLoGin assert!(RootFSConfigFile::load_from_str(config_content).is_err()); 951ad837a4SLoGin } 961ad837a4SLoGin 971ad837a4SLoGin /// 测试size为int类型的字节大小 981ad837a4SLoGin #[test] 991ad837a4SLoGin fn test_load_from_valid_str_size_integer() { 1001ad837a4SLoGin let config_content = r#" 1011ad837a4SLoGin [metadata] 1021ad837a4SLoGin fs_type = "fat32" 1031ad837a4SLoGin size = 1048576 1041ad837a4SLoGin "#; 1051ad837a4SLoGin 1061ad837a4SLoGin let config = RootFSConfigFile::load_from_str(config_content) 1071ad837a4SLoGin .expect("Failed to load config from str"); 1081ad837a4SLoGin 1091ad837a4SLoGin assert_eq!(config.metadata.fs_type, FsType::Fat32); 1101ad837a4SLoGin assert_eq!(config.metadata.size, 1048576); // Assuming `deserialize_size` converts MB to Bytes 1111ad837a4SLoGin } 1121ad837a4SLoGin #[test] 1131ad837a4SLoGin fn test_load_from_valid_str_size_bytes_str() { 1141ad837a4SLoGin let config_content = r#" 1151ad837a4SLoGin [metadata] 1161ad837a4SLoGin fs_type = "fat32" 1171ad837a4SLoGin size = "1048576" 1181ad837a4SLoGin "#; 1191ad837a4SLoGin 1201ad837a4SLoGin let config = RootFSConfigFile::load_from_str(config_content) 1211ad837a4SLoGin .expect("Failed to load config from str"); 1221ad837a4SLoGin 1231ad837a4SLoGin assert_eq!(config.metadata.fs_type, FsType::Fat32); 1241ad837a4SLoGin assert_eq!(config.metadata.size, 1048576); // Assuming `deserialize_size` converts MB to Bytes 1251ad837a4SLoGin } 1261ad837a4SLoGin 1271ad837a4SLoGin #[test] 1281ad837a4SLoGin fn test_load_from_invalid_file() { 1291ad837a4SLoGin let temp_file = NamedTempFile::new().expect("Failed to create temp file"); 1301ad837a4SLoGin let config_path = PathBuf::from(temp_file.path()); 1311ad837a4SLoGin 1321ad837a4SLoGin assert!(RootFSConfigFile::load(&config_path).is_err()); 1331ad837a4SLoGin } 1341ad837a4SLoGin 1351ad837a4SLoGin /// Parse from an incorrect size field (string) 1361ad837a4SLoGin #[test] 1371ad837a4SLoGin fn test_load_from_invalid_size_str() { 1381ad837a4SLoGin let invalid_config_content = r#" 1391ad837a4SLoGin [metadata] 1401ad837a4SLoGin fs_type = "fat32" 1411ad837a4SLoGin size = "not_a_size" 1421ad837a4SLoGin "#; 1431ad837a4SLoGin 1441ad837a4SLoGin assert!(RootFSConfigFile::load_from_str(invalid_config_content).is_err()); 1451ad837a4SLoGin } 1461ad837a4SLoGin 1471ad837a4SLoGin /// Parse from an incorrect size field (array) 1481ad837a4SLoGin #[test] 1491ad837a4SLoGin fn test_load_from_invalid_size_array() { 1501ad837a4SLoGin // The 'size' field should not be an array 1511ad837a4SLoGin let invalid_config_content = r#" 1521ad837a4SLoGin [metadata] 1531ad837a4SLoGin fs_type = "fat32" 1541ad837a4SLoGin size = ["not_a_size"] 1551ad837a4SLoGin "#; 1561ad837a4SLoGin 1571ad837a4SLoGin assert!(RootFSConfigFile::load_from_str(invalid_config_content).is_err()); 1581ad837a4SLoGin } 1591ad837a4SLoGin } 160