|
@@ -8,15 +8,15 @@ use crate::common::target_arch::TargetArch;
|
|
|
use std::fs;
|
|
|
use toml;
|
|
|
|
|
|
-#[derive(Debug, Clone, Deserialize)]
|
|
|
-pub struct Metadata {
|
|
|
- /// Target processor architecture
|
|
|
- pub arch: TargetArch,
|
|
|
-}
|
|
|
-
|
|
|
+/// The main configuration file for DADK
|
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
|
pub struct DadkManifest {
|
|
|
pub metadata: Metadata,
|
|
|
+
|
|
|
+ /// A flag variable used to indicate whether
|
|
|
+ /// the default value function was called during deserialization.
|
|
|
+ #[serde(skip)]
|
|
|
+ pub used_default: bool,
|
|
|
}
|
|
|
|
|
|
impl DadkManifest {
|
|
@@ -27,24 +27,83 @@ impl DadkManifest {
|
|
|
}
|
|
|
|
|
|
fn do_load(content: &str) -> Result<Self> {
|
|
|
- // 解析TOML内容
|
|
|
- let manifest_toml: DadkManifest = toml::from_str(&content)?;
|
|
|
+ // Parse TOML content
|
|
|
+ let mut manifest_toml: DadkManifest = toml::from_str(content)?;
|
|
|
+
|
|
|
+ manifest_toml.used_default = check_used_default();
|
|
|
|
|
|
Ok(manifest_toml)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+thread_local! {
|
|
|
+ /// Global variable to track if default values were used during deserialization.
|
|
|
+ static USED_DEFAULT: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
|
|
|
+}
|
|
|
+
|
|
|
+/// Call this function to set a flag when
|
|
|
+/// default values are used during DADK manifest parsing
|
|
|
+fn set_used_default() {
|
|
|
+ USED_DEFAULT.with(|used_default| {
|
|
|
+ used_default.set(true);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/// Check if default values were used during deserialization.
|
|
|
+fn check_used_default() -> bool {
|
|
|
+ USED_DEFAULT.with(|used_default| used_default.get())
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Debug, Clone, Deserialize)]
|
|
|
+pub struct Metadata {
|
|
|
+ /// Target processor architecture
|
|
|
+ pub arch: TargetArch,
|
|
|
+ /// Rootfs configuration file path
|
|
|
+ #[serde(default = "default_rootfs_config_path")]
|
|
|
+ pub rootfs_config: PathBuf,
|
|
|
+
|
|
|
+ /// Hypervisor configuration file path
|
|
|
+ #[serde(default = "default_hypervisor_config_path")]
|
|
|
+ pub hypervisor_config: PathBuf,
|
|
|
+
|
|
|
+ /// Boot configuration file path
|
|
|
+ #[serde(default = "default_boot_config_path")]
|
|
|
+ pub boot_config: PathBuf,
|
|
|
+}
|
|
|
+
|
|
|
+/// Returns the default path for the rootfs configuration file.
|
|
|
+fn default_rootfs_config_path() -> PathBuf {
|
|
|
+ set_used_default();
|
|
|
+ "config/rootfs.toml".into()
|
|
|
+}
|
|
|
+
|
|
|
+/// Returns the default path for the hypervisor configuration file.
|
|
|
+fn default_hypervisor_config_path() -> PathBuf {
|
|
|
+ set_used_default();
|
|
|
+ "config/hypervisor.toml".into()
|
|
|
+}
|
|
|
+
|
|
|
+/// Returns the default path for the boot configuration file.
|
|
|
+fn default_boot_config_path() -> PathBuf {
|
|
|
+ set_used_default();
|
|
|
+ "config/boot.toml".into()
|
|
|
+}
|
|
|
+
|
|
|
#[cfg(test)]
|
|
|
mod tests {
|
|
|
use super::*;
|
|
|
use std::io::Write;
|
|
|
use tempfile::NamedTempFile;
|
|
|
|
|
|
+ /// Test loading a complete configuration file
|
|
|
#[test]
|
|
|
- fn test_load_success() -> Result<()> {
|
|
|
+ fn test_full_load_success() -> Result<()> {
|
|
|
let toml_content = r#"
|
|
|
[metadata]
|
|
|
arch = "x86_64"
|
|
|
+ rootfs_config = "config/rootfs-x86_64.toml"
|
|
|
+ hypervisor_config = "config/hypervisor-x86_64.toml"
|
|
|
+ boot_config = "config/boot-x86_64.toml"
|
|
|
"#;
|
|
|
|
|
|
let mut temp_file = NamedTempFile::new()?;
|
|
@@ -54,10 +113,24 @@ mod tests {
|
|
|
let manifest = DadkManifest::load(&path)?;
|
|
|
|
|
|
assert_eq!(manifest.metadata.arch, TargetArch::X86_64);
|
|
|
+ assert_eq!(
|
|
|
+ manifest.metadata.rootfs_config,
|
|
|
+ PathBuf::from("config/rootfs-x86_64.toml")
|
|
|
+ );
|
|
|
+ assert_eq!(
|
|
|
+ manifest.metadata.hypervisor_config,
|
|
|
+ PathBuf::from("config/hypervisor-x86_64.toml")
|
|
|
+ );
|
|
|
+ assert_eq!(
|
|
|
+ manifest.metadata.boot_config,
|
|
|
+ PathBuf::from("config/boot-x86_64.toml")
|
|
|
+ );
|
|
|
+ assert!(!manifest.used_default);
|
|
|
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
+ /// Test whether an error is reported when the file does not exist.
|
|
|
#[test]
|
|
|
fn test_load_file_not_found() {
|
|
|
let path = PathBuf::from("non_existent_file.toml");
|
|
@@ -66,6 +139,7 @@ mod tests {
|
|
|
assert!(result.is_err());
|
|
|
}
|
|
|
|
|
|
+ /// Test whether an error is reported when the TOML content is invalid
|
|
|
#[test]
|
|
|
fn test_load_invalid_toml() -> Result<()> {
|
|
|
let invalid_toml_content = r#"
|
|
@@ -84,6 +158,7 @@ mod tests {
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
+ /// Test whether an error is reported when the arch field is invalid
|
|
|
#[test]
|
|
|
fn test_load_invalid_arch_toml() -> Result<()> {
|
|
|
// Invalid arch value
|
|
@@ -103,6 +178,7 @@ mod tests {
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
+ /// Test whether an error is reported when a required field is missing
|
|
|
#[test]
|
|
|
fn test_load_missing_required_fields() -> Result<()> {
|
|
|
let toml_content = r#"
|
|
@@ -120,4 +196,32 @@ mod tests {
|
|
|
|
|
|
Ok(())
|
|
|
}
|
|
|
+
|
|
|
+ /// Test whether default values are used
|
|
|
+ /// when the rootfs_config and other configuration file path fields are not set
|
|
|
+ #[test]
|
|
|
+ fn test_load_default_config_path_value() -> Result<()> {
|
|
|
+ let toml_content = r#"
|
|
|
+ [metadata]
|
|
|
+ arch = "x86_64"
|
|
|
+ "#;
|
|
|
+ let mut temp_file = NamedTempFile::new()?;
|
|
|
+ temp_file.write_all(toml_content.as_bytes())?;
|
|
|
+ let path = temp_file.path().to_path_buf();
|
|
|
+ let manifest = DadkManifest::load(&path)?;
|
|
|
+ assert_eq!(manifest.used_default, true);
|
|
|
+ assert_eq!(
|
|
|
+ manifest.metadata.rootfs_config,
|
|
|
+ PathBuf::from("config/rootfs.toml")
|
|
|
+ );
|
|
|
+ assert_eq!(
|
|
|
+ manifest.metadata.hypervisor_config,
|
|
|
+ PathBuf::from("config/hypervisor.toml")
|
|
|
+ );
|
|
|
+ assert_eq!(
|
|
|
+ manifest.metadata.boot_config,
|
|
|
+ PathBuf::from("config/boot.toml")
|
|
|
+ );
|
|
|
+ Ok(())
|
|
|
+ }
|
|
|
}
|