KubeOS/0008-test-rust-os-agent-add-os-agent-unit-tests.patch

818 lines
33 KiB
Diff
Raw Normal View History

From e30fcb3c11ba4290b892e7307976b2c2a64c8fee Mon Sep 17 00:00:00 2001
From: Yuhang Wei <weiyuhang3@huawei.com>
Date: Tue, 16 Jan 2024 20:05:26 +0800
Subject: [PATCH 08/13] test(rust os-agent): add os-agent unit tests
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
---
KubeOS-Rust/agent/src/rpc/agent_impl.rs | 28 +++++----
KubeOS-Rust/cli/src/client.rs | 23 ++-----
KubeOS-Rust/cli/src/method/callable_method.rs | 28 +++++++++
KubeOS-Rust/cli/src/method/configure.rs | 31 ++++++++++
KubeOS-Rust/cli/src/method/prepare_upgrade.rs | 37 +++++++++++
KubeOS-Rust/cli/src/method/request.rs | 37 +++++++++++
KubeOS-Rust/cli/src/method/rollback.rs | 13 ++++
KubeOS-Rust/cli/src/method/upgrade.rs | 13 ++++
KubeOS-Rust/manager/src/api/types.rs | 58 +++++++++++++++++
KubeOS-Rust/manager/src/sys_mgmt/config.rs | 62 +++++++++----------
.../manager/src/sys_mgmt/containerd_image.rs | 22 +------
.../manager/src/sys_mgmt/disk_image.rs | 7 ++-
.../manager/src/sys_mgmt/docker_image.rs | 4 +-
KubeOS-Rust/manager/src/utils/common.rs | 43 ++++++++++---
.../manager/src/utils/container_image.rs | 46 ++++++++++++--
KubeOS-Rust/manager/src/utils/partition.rs | 15 +++++
16 files changed, 366 insertions(+), 101 deletions(-)
diff --git a/KubeOS-Rust/agent/src/rpc/agent_impl.rs b/KubeOS-Rust/agent/src/rpc/agent_impl.rs
index bc1eabd..8aef414 100644
--- a/KubeOS-Rust/agent/src/rpc/agent_impl.rs
+++ b/KubeOS-Rust/agent/src/rpc/agent_impl.rs
@@ -13,7 +13,7 @@
use std::{sync::Mutex, thread, time::Duration};
use anyhow::{bail, Result};
-use log::{debug, error, info};
+use log::{debug, info};
use manager::{
api::{AgentStatus, ConfigureRequest, ImageType, Response, UpgradeRequest},
sys_mgmt::{CtrImageHandler, DiskImageHandler, DockerImageHandler, CONFIG_TEMPLATE, DEFAULT_GRUBENV_PATH},
@@ -101,7 +101,6 @@ impl AgentImpl {
debug!("Found configuration type: \"{}\"", config_type);
configuration.set_config(config)?;
} else {
- error!("Unknown configuration type: \"{}\"", config_type);
bail!("Unknown configuration type: \"{}\"", config_type);
}
}
@@ -123,7 +122,7 @@ impl AgentImpl {
Ok(Response { status: AgentStatus::Rollbacked })
}
- pub fn reboot(&self) -> Result<()> {
+ fn reboot(&self) -> Result<()> {
info!("Wait to reboot");
thread::sleep(Duration::from_secs(1));
sync();
@@ -144,7 +143,15 @@ mod test {
use super::*;
#[test]
- fn configure_impl_tests() {
+ fn test_reboot() {
+ let mut agent = AgentImpl::default();
+ agent.disable_reboot = true;
+ let res = agent.reboot();
+ assert!(res.is_ok());
+ }
+
+ #[test]
+ fn test_configure() {
let agent = AgentImpl::default();
let req = ConfigureRequest {
configs: vec![Sysconfig {
@@ -153,7 +160,7 @@ mod test {
contents: HashMap::new(),
}],
};
- let res = agent.configure_impl(req).unwrap();
+ let res = agent.configure(req).unwrap();
assert_eq!(res, Response { status: AgentStatus::Configured });
let req = ConfigureRequest {
@@ -163,17 +170,12 @@ mod test {
contents: HashMap::new(),
}],
};
- let res = agent.configure_impl(req);
+ let res = agent.configure(req);
assert!(res.is_err());
}
#[test]
- fn upgrade_impl_tests() {
- let _ = env_logger::builder()
- .target(env_logger::Target::Stdout)
- .filter_level(log::LevelFilter::Trace)
- .is_test(true)
- .try_init();
+ fn test_prepare_upgrade() {
let agent = AgentImpl::default();
let req = UpgradeRequest {
version: "v2".into(),
@@ -185,7 +187,7 @@ mod test {
mtls: false,
certs: CertsInfo { ca_cert: "".to_string(), client_cert: "".to_string(), client_key: "".to_string() },
};
- let res = agent.prepare_upgrade_impl(req);
+ let res = agent.prepare_upgrade(req);
assert!(res.is_err());
}
}
diff --git a/KubeOS-Rust/cli/src/client.rs b/KubeOS-Rust/cli/src/client.rs
index ce45cdd..9765a42 100644
--- a/KubeOS-Rust/cli/src/client.rs
+++ b/KubeOS-Rust/cli/src/client.rs
@@ -43,27 +43,14 @@ impl Client {
#[cfg(test)]
mod test {
- use kubeos_manager::api;
-
use super::*;
- use crate::method::{callable_method::RpcMethod, configure::ConfigureMethod};
-
#[test]
- #[ignore]
fn test_client() {
- let socket_path = "/home/yuhang/os-agent-rust.sock";
+ let socket_path = "/tmp/KubeOS-test.sock";
let cli = Client::new(socket_path);
-
- let configured = api::AgentStatus::Configured;
- let resp = api::Response { status: configured };
- let config_request = api::ConfigureRequest {
- configs: vec![api::Sysconfig {
- model: "kernel.sysctl".into(),
- config_path: "".into(),
- contents: std::collections::hash_map::HashMap::new(),
- }],
- };
- let config_resp = ConfigureMethod::new(config_request).call(&cli).unwrap();
- assert_eq!(resp, config_resp);
+ let command = "example_command";
+ let params = vec![];
+ let request = cli.send_request(cli.build_request(command, &params));
+ assert!(request.is_err());
}
}
diff --git a/KubeOS-Rust/cli/src/method/callable_method.rs b/KubeOS-Rust/cli/src/method/callable_method.rs
index c46614b..a174b5b 100644
--- a/KubeOS-Rust/cli/src/method/callable_method.rs
+++ b/KubeOS-Rust/cli/src/method/callable_method.rs
@@ -24,3 +24,31 @@ pub trait RpcMethod {
response.result().map_err(parse_error)
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::client;
+
+ #[derive(Default)]
+ struct DummyMethod;
+
+ impl RpcMethod for DummyMethod {
+ type Response = String;
+
+ fn command_name(&self) -> &'static str {
+ "dummy_command"
+ }
+
+ fn command_params(&self) -> Vec<Box<RawValue>> {
+ vec![]
+ }
+ }
+
+ #[test]
+ fn test_call() {
+ let client = client::Client::new("/tmp/KubeOS-test.sock");
+ let result = DummyMethod::default().call(&client);
+ assert!(result.is_err());
+ }
+}
diff --git a/KubeOS-Rust/cli/src/method/configure.rs b/KubeOS-Rust/cli/src/method/configure.rs
index d137106..cca752d 100644
--- a/KubeOS-Rust/cli/src/method/configure.rs
+++ b/KubeOS-Rust/cli/src/method/configure.rs
@@ -39,3 +39,34 @@ impl RpcMethod for ConfigureMethod {
vec![to_raw_value(&self.req).unwrap()]
}
}
+#[cfg(test)]
+mod tests {
+ use kubeos_manager::api::{ConfigureRequest, Sysconfig};
+
+ use super::*;
+
+ #[test]
+ fn test_configure_method() {
+ let req = ConfigureRequest { configs: vec![] };
+ let mut method = ConfigureMethod::new(req);
+
+ // Test set_configure_request method
+ let new_req = ConfigureRequest {
+ configs: vec![Sysconfig {
+ model: "model".to_string(),
+ config_path: "config_path".to_string(),
+ contents: Default::default(),
+ }],
+ };
+ method.set_configure_request(new_req);
+
+ // Test command_name method
+ assert_eq!(method.command_name(), "configure");
+
+ // Test command_params method
+ let expected_params =
+ "RawValue({\"configs\":[{\"model\":\"model\",\"config_path\":\"config_path\",\"contents\":{}}]})";
+ let actual_params = format!("{:?}", method.command_params()[0]);
+ assert_eq!(actual_params, expected_params);
+ }
+}
diff --git a/KubeOS-Rust/cli/src/method/prepare_upgrade.rs b/KubeOS-Rust/cli/src/method/prepare_upgrade.rs
index 91dae79..f2034f6 100644
--- a/KubeOS-Rust/cli/src/method/prepare_upgrade.rs
+++ b/KubeOS-Rust/cli/src/method/prepare_upgrade.rs
@@ -39,3 +39,40 @@ impl RpcMethod for PrepareUpgradeMethod {
vec![to_raw_value(&self.req).unwrap()]
}
}
+#[cfg(test)]
+mod tests {
+ use kubeos_manager::api::{CertsInfo, UpgradeRequest};
+
+ use super::*;
+
+ #[test]
+ fn test_prepare_upgrade_method() {
+ let req = UpgradeRequest {
+ version: "v1".into(),
+ check_sum: "".into(),
+ image_type: "".into(),
+ container_image: "".into(),
+ image_url: "".to_string(),
+ flag_safe: false,
+ mtls: false,
+ certs: CertsInfo { ca_cert: "".to_string(), client_cert: "".to_string(), client_key: "".to_string() },
+ };
+ let mut method = PrepareUpgradeMethod::new(req);
+ let new_req = UpgradeRequest {
+ version: "v2".into(),
+ check_sum: "xxx".into(),
+ image_type: "xxx".into(),
+ container_image: "xxx".into(),
+ image_url: "".to_string(),
+ flag_safe: false,
+ mtls: false,
+ certs: CertsInfo { ca_cert: "".to_string(), client_cert: "".to_string(), client_key: "".to_string() },
+ };
+ method.set_prepare_upgrade_request(new_req);
+ assert_eq!(method.command_name(), "prepare_upgrade");
+
+ let expected_params = "RawValue({\"version\":\"v2\",\"check_sum\":\"xxx\",\"image_type\":\"xxx\",\"container_image\":\"xxx\",\"image_url\":\"\",\"flag_safe\":false,\"mtls\":false,\"certs\":{\"ca_cert\":\"\",\"client_cert\":\"\",\"client_key\":\"\"}})";
+ let actual_params = format!("{:?}", method.command_params()[0]);
+ assert_eq!(actual_params, expected_params);
+ }
+}
diff --git a/KubeOS-Rust/cli/src/method/request.rs b/KubeOS-Rust/cli/src/method/request.rs
index 2dc1ffb..ff75afd 100644
--- a/KubeOS-Rust/cli/src/method/request.rs
+++ b/KubeOS-Rust/cli/src/method/request.rs
@@ -50,3 +50,40 @@ pub fn parse_error(error: Error) -> anyhow::Error {
},
}
}
+
+#[cfg(test)]
+mod tests {
+ use jsonrpc::error::RpcError;
+ use serde::de::Error as DeError;
+
+ use super::*;
+
+ #[test]
+ fn test_parse_error() {
+ // Test Error::Transport
+ let transport_error =
+ Error::Transport(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "Connection timeout")));
+ let result = parse_error(transport_error);
+ assert_eq!(result.to_string(), "Cannot connect to KubeOS os-agent unix socket, Connection timeout");
+
+ // Test Error::Json
+ let json_error = Error::Json(serde_json::Error::custom("Failed to parse response"));
+ let result = parse_error(json_error);
+ assert_eq!(result.to_string(), "Failed to parse response");
+
+ // Test Error::Rpc with "Method not found" message
+ let rpc_error = Error::Rpc(RpcError { code: -32601, message: "Method not found".to_string(), data: None });
+ let result = parse_error(rpc_error);
+ assert_eq!(result.to_string(), "Method is unimplemented");
+
+ // Test Error::Rpc with other message
+ let rpc_error = Error::Rpc(RpcError { code: -32603, message: "Internal server error".to_string(), data: None });
+ let result = parse_error(rpc_error);
+ assert_eq!(result.to_string(), "Internal server error");
+
+ // Test other Error variant
+ let other_error = Error::VersionMismatch;
+ let result = parse_error(other_error);
+ assert_eq!(result.to_string(), "Response is invalid");
+ }
+}
diff --git a/KubeOS-Rust/cli/src/method/rollback.rs b/KubeOS-Rust/cli/src/method/rollback.rs
index 55aa751..7945f4b 100644
--- a/KubeOS-Rust/cli/src/method/rollback.rs
+++ b/KubeOS-Rust/cli/src/method/rollback.rs
@@ -27,3 +27,16 @@ impl RpcMethod for RollbackMethod {
vec![]
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ #[test]
+ fn test_rollback_method() {
+ let method = RollbackMethod::default();
+ assert_eq!(method.command_name(), "rollback");
+ let expected_params = "[]";
+ let actual_params = format!("{:?}", method.command_params());
+ assert_eq!(actual_params, expected_params);
+ }
+}
diff --git a/KubeOS-Rust/cli/src/method/upgrade.rs b/KubeOS-Rust/cli/src/method/upgrade.rs
index a9692ca..f2f94cd 100644
--- a/KubeOS-Rust/cli/src/method/upgrade.rs
+++ b/KubeOS-Rust/cli/src/method/upgrade.rs
@@ -27,3 +27,16 @@ impl RpcMethod for UpgradeMethod {
vec![]
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ #[test]
+ fn test_upgrade_method() {
+ let method = UpgradeMethod::default();
+ assert_eq!(method.command_name(), "upgrade");
+ let expected_params = "[]";
+ let actual_params = format!("{:?}", method.command_params());
+ assert_eq!(actual_params, expected_params);
+ }
+}
diff --git a/KubeOS-Rust/manager/src/api/types.rs b/KubeOS-Rust/manager/src/api/types.rs
index 28ee97d..98aeaa3 100644
--- a/KubeOS-Rust/manager/src/api/types.rs
+++ b/KubeOS-Rust/manager/src/api/types.rs
@@ -80,3 +80,61 @@ impl<T: CommandExecutor> ImageType<T> {
pub trait ImageHandler<T: CommandExecutor> {
fn download_image(&self, req: &UpgradeRequest) -> anyhow::Result<UpgradeImageManager<T>>;
}
+
+#[cfg(test)]
+mod tests {
+ use anyhow::Result;
+ use mockall::mock;
+
+ use super::*;
+ use crate::utils::PreparePath;
+
+ mock! {
+ pub CommandExec{}
+ impl CommandExecutor for CommandExec {
+ fn run_command<'a>(&self, name: &'a str, args: &[&'a str]) -> Result<()>;
+ fn run_command_with_output<'a>(&self, name: &'a str, args: &[&'a str]) -> Result<String>;
+ }
+ impl Clone for CommandExec {
+ fn clone(&self) -> Self;
+ }
+ }
+
+ #[test]
+ fn test_download_image() {
+ let req = UpgradeRequest {
+ version: "KubeOS v2".to_string(),
+ image_type: "containerd".to_string(),
+ container_image: "kubeos-temp".to_string(),
+ check_sum: "22222".to_string(),
+ image_url: "".to_string(),
+ flag_safe: false,
+ mtls: false,
+ certs: CertsInfo { ca_cert: "".to_string(), client_cert: "".to_string(), client_key: "".to_string() },
+ };
+
+ let mut mock_executor1 = MockCommandExec::new();
+ mock_executor1.expect_run_command().returning(|_, _| Ok(()));
+ mock_executor1.expect_run_command_with_output().returning(|_, _| Ok(String::new()));
+ let c_handler = CtrImageHandler::new(PreparePath::default(), mock_executor1);
+ let image_type = ImageType::Containerd(c_handler);
+ let result = image_type.download_image(&req);
+ assert!(result.is_err());
+
+ let mut mock_executor2 = MockCommandExec::new();
+ mock_executor2.expect_run_command().returning(|_, _| Ok(()));
+ mock_executor2.expect_run_command_with_output().returning(|_, _| Ok(String::new()));
+ let docker_handler = DockerImageHandler::new(PreparePath::default(), "test".into(), mock_executor2);
+ let image_type = ImageType::Docker(docker_handler);
+ let result = image_type.download_image(&req);
+ assert!(result.is_err());
+
+ let mut mock_executor3 = MockCommandExec::new();
+ mock_executor3.expect_run_command().returning(|_, _| Ok(()));
+ mock_executor3.expect_run_command_with_output().returning(|_, _| Ok(String::new()));
+ let disk_handler = DiskImageHandler::new(PreparePath::default(), mock_executor3, "test".into());
+ let image_type = ImageType::Disk(disk_handler);
+ let result = image_type.download_image(&req);
+ assert!(result.is_err());
+ }
+}
diff --git a/KubeOS-Rust/manager/src/sys_mgmt/config.rs b/KubeOS-Rust/manager/src/sys_mgmt/config.rs
index cb5fad1..48517b4 100644
--- a/KubeOS-Rust/manager/src/sys_mgmt/config.rs
+++ b/KubeOS-Rust/manager/src/sys_mgmt/config.rs
@@ -186,7 +186,7 @@ fn handle_delete_key(config_kv: &Vec<&str>, new_config_info: &KeyInfo) -> String
return config_kv.join("=");
}
info!("Delete configuration {}={}", key, old_value);
- String::from("")
+ String::new()
}
fn handle_update_key(config_kv: &Vec<&str>, new_config_info: &KeyInfo) -> String {
@@ -413,11 +413,20 @@ mod tests {
let mut tmp_file = tempfile::NamedTempFile::new().unwrap();
writeln!(tmp_file, "{}", comment).unwrap();
writeln!(tmp_file, "a=0").unwrap();
+ writeln!(tmp_file, "d=4").unwrap();
+ writeln!(tmp_file, "e=5").unwrap();
+ writeln!(tmp_file, "g=7").unwrap();
let kernel_sysctl_persist = KernelSysctlPersist {};
let config_detail = HashMap::from([
("a".to_string(), KeyInfo { value: "1".to_string(), operation: "".to_string() }),
("b".to_string(), KeyInfo { value: "2".to_string(), operation: "delete".to_string() }),
("c".to_string(), KeyInfo { value: "3".to_string(), operation: "add".to_string() }),
+ ("d".to_string(), KeyInfo { value: "".to_string(), operation: "".to_string() }),
+ ("e".to_string(), KeyInfo { value: "".to_string(), operation: "delete".to_string() }),
+ ("f".to_string(), KeyInfo { value: "".to_string(), operation: "add".to_string() }),
+ ("g".to_string(), KeyInfo { value: "7".to_string(), operation: "delete".to_string() }),
+ ("".to_string(), KeyInfo { value: "8".to_string(), operation: "".to_string() }),
+ ("s=x".to_string(), KeyInfo { value: "8".to_string(), operation: "".to_string() }),
]);
let mut config = Sysconfig {
model: KERNEL_SYSCTL_PERSIST.to_string(),
@@ -426,33 +435,16 @@ mod tests {
};
kernel_sysctl_persist.set_config(&mut config).unwrap();
let result = fs::read_to_string(tmp_file.path().to_str().unwrap()).unwrap();
- let expected_res = format!("{}\n{}\n{}\n", comment, "a=1", "c=3");
+ let expected_res = format!("{}\n{}\n{}\n{}\n{}\n", comment, "a=1", "d=4", "e=5", "c=3");
assert_eq!(result, expected_res);
-
- // test config_path is empty
- // remember modify DEFAULT_KERNEL_CONFIG_PATH first
- // let config_detail = HashMap::from([
- // (
- // "aaa".to_string(),
- // KeyInfo {
- // value: "3".to_string(),
- // operation: "add".to_string(),
- // },
- // ),
- // (
- // "bbb".to_string(),
- // KeyInfo {
- // value: "1".to_string(),
- // operation: "delete".to_string(),
- // },
- // ),
- // ]);
- // config.config_path = "".to_string();
- // config.contents = config_detail;
- // kernel_sysctl_persist.set_config(&mut config).unwrap();
- // let result = fs::read_to_string(crate::sys_mgmt::DEFAULT_KERNEL_CONFIG_PATH).unwrap();
- // let expected_res = format!("{}\n", "aaa=3",);
- // assert_eq!(result, expected_res);
+ let mut config = Sysconfig {
+ model: KERNEL_SYSCTL_PERSIST.to_string(),
+ config_path: String::from("/tmp/kubeos-test-kernel-sysctl-persist.txt"),
+ contents: HashMap::new(),
+ };
+ kernel_sysctl_persist.set_config(&mut config).unwrap();
+ assert!(is_file_exist(&config.config_path));
+ delete_file_or_dir(&config.config_path).unwrap();
}
#[test]
@@ -492,7 +484,7 @@ menuentry 'B' --class KubeOS --class gnu-linux --class gnu --class os --unrestri
initrd /boot/initramfs.img
}";
writeln!(tmp_file, "{}", grub_cfg).unwrap();
- let config_first_part = HashMap::from([
+ let config_second_part = HashMap::from([
("debug".to_string(), KeyInfo { value: "".to_string(), operation: "".to_string() }),
("quiet".to_string(), KeyInfo { value: "".to_string(), operation: "delete".to_string() }),
("panic".to_string(), KeyInfo { value: "5".to_string(), operation: "".to_string() }),
@@ -506,15 +498,16 @@ menuentry 'B' --class KubeOS --class gnu-linux --class gnu --class os --unrestri
let mut config = Sysconfig {
model: GRUB_CMDLINE_CURRENT.to_string(),
config_path: String::new(),
- contents: config_first_part,
+ contents: config_second_part,
};
grub_cmdline.set_config(&mut config).unwrap();
grub_cmdline.is_cur_partition = false;
- let config_second = HashMap::from([
+ let config_first_part = HashMap::from([
("pci".to_string(), KeyInfo { value: "nomis".to_string(), operation: "".to_string() }),
- ("panic".to_string(), KeyInfo { value: "5".to_string(), operation: "".to_string() }),
+ ("quiet".to_string(), KeyInfo { value: "11".to_string(), operation: "delete".to_string() }),
+ ("panic".to_string(), KeyInfo { value: "5".to_string(), operation: "update".to_string() }),
]);
- config.contents = config_second;
+ config.contents = config_first_part;
config.model = GRUB_CMDLINE_NEXT.to_string();
grub_cmdline.set_config(&mut config).unwrap();
let result = fs::read_to_string(tmp_file.path().to_str().unwrap()).unwrap();
@@ -540,6 +533,11 @@ menuentry 'B' --class KubeOS --class gnu-linux --class gnu --class os --unrestri
}
";
assert_eq!(result, expected_res);
+
+ // test grub.cfg not exist
+ grub_cmdline.grub_path = "/tmp/grub-KubeOS-test.cfg".to_string();
+ let res = grub_cmdline.set_config(&mut config);
+ assert!(res.is_err());
}
#[test]
diff --git a/KubeOS-Rust/manager/src/sys_mgmt/containerd_image.rs b/KubeOS-Rust/manager/src/sys_mgmt/containerd_image.rs
index 0b50ad6..dd7036f 100644
--- a/KubeOS-Rust/manager/src/sys_mgmt/containerd_image.rs
+++ b/KubeOS-Rust/manager/src/sys_mgmt/containerd_image.rs
@@ -48,7 +48,7 @@ impl Default for CtrImageHandler<RealCommandExecutor> {
impl<T: CommandExecutor> CtrImageHandler<T> {
#[cfg(test)]
- fn new(paths: PreparePath, executor: T) -> Self {
+ pub fn new(paths: PreparePath, executor: T) -> Self {
Self { paths, executor }
}
@@ -301,24 +301,4 @@ mod tests {
assert!(result.is_ok());
}
-
- #[test]
- #[ignore]
- fn test_download_image() {
- init();
- let ctr = CtrImageHandler { paths: PreparePath::default(), executor: RealCommandExecutor {} };
- let update_req = UpgradeRequest {
- version: "KubeOS v2".to_string(),
- image_type: "containerd".to_string(),
- container_image: "docker.io/library/busybox:latest".to_string(),
- check_sum: "".to_string(),
- image_url: "".to_string(),
- flag_safe: false,
- mtls: false,
- certs: CertsInfo { ca_cert: "".to_string(), client_cert: "".to_string(), client_key: "".to_string() },
- };
- ctr.download_image(&update_req).unwrap();
- let tar_path = "/persist/KubeOS-Update/os.tar";
- assert_eq!(true, Path::new(tar_path).exists());
- }
}
diff --git a/KubeOS-Rust/manager/src/sys_mgmt/disk_image.rs b/KubeOS-Rust/manager/src/sys_mgmt/disk_image.rs
index 4ccb603..a120db8 100644
--- a/KubeOS-Rust/manager/src/sys_mgmt/disk_image.rs
+++ b/KubeOS-Rust/manager/src/sys_mgmt/disk_image.rs
@@ -41,7 +41,7 @@ impl Default for DiskImageHandler<RealCommandExecutor> {
impl<T: CommandExecutor> DiskImageHandler<T> {
#[cfg(test)]
- fn new(paths: PreparePath, executor: T, certs_path: String) -> Self {
+ pub fn new(paths: PreparePath, executor: T, certs_path: String) -> Self {
Self { paths, executor, certs_path }
}
@@ -392,11 +392,14 @@ mod tests {
.with_body("This is a test txt file for KubeOS test.\n")
.create();
handler.download_image(&upgrade_request).unwrap();
-
assert_eq!(true, handler.paths.image_path.exists());
assert_eq!(
fs::read(handler.paths.image_path.to_str().unwrap()).unwrap(),
"This is a test txt file for KubeOS test.\n".as_bytes()
);
+
+ let _m = mockito::mock("GET", "/test.txt").with_status(404).with_body("Not found").create();
+ let res = handler.download_image(&upgrade_request);
+ assert!(res.is_err())
}
}
diff --git a/KubeOS-Rust/manager/src/sys_mgmt/docker_image.rs b/KubeOS-Rust/manager/src/sys_mgmt/docker_image.rs
index 121e257..177dfeb 100644
--- a/KubeOS-Rust/manager/src/sys_mgmt/docker_image.rs
+++ b/KubeOS-Rust/manager/src/sys_mgmt/docker_image.rs
@@ -33,7 +33,7 @@ impl Default for DockerImageHandler<RealCommandExecutor> {
impl<T: CommandExecutor> DockerImageHandler<T> {
#[cfg(test)]
- fn new(paths: PreparePath, container_name: String, executor: T) -> Self {
+ pub fn new(paths: PreparePath, container_name: String, executor: T) -> Self {
Self { paths, container_name, executor }
}
@@ -129,6 +129,8 @@ mod tests {
let result =
DockerImageHandler::new(PreparePath::default(), "test".into(), mock_executor).check_and_rm_container();
assert!(result.is_ok());
+
+ assert_eq!(DockerImageHandler::default().container_name, "kubeos-temp");
}
#[test]
diff --git a/KubeOS-Rust/manager/src/utils/common.rs b/KubeOS-Rust/manager/src/utils/common.rs
index 301a8c8..da8c8c3 100644
--- a/KubeOS-Rust/manager/src/utils/common.rs
+++ b/KubeOS-Rust/manager/src/utils/common.rs
@@ -23,14 +23,25 @@ use nix::{mount, mount::MntFlags};
use super::executor::CommandExecutor;
use crate::sys_mgmt::{MOUNT_DIR, OS_IMAGE_NAME, PERSIST_DIR, ROOTFS_ARCHIVE, UPDATE_DIR};
+/// * persist_path: /persist
+///
+/// * update_path: /persist/KubeOS-Update
+///
+/// * mount_path: /persist/KubeOS-Update/kubeos-update
+///
+/// * tar_path: /persist/KubeOS-Update/os.tar
+///
+/// * image_path: /persist/update.img
+///
+/// * rootfs_file: os.tar
#[derive(Clone)]
pub struct PreparePath {
- pub persist_path: PathBuf, // persist_path: /persist
- pub update_path: PathBuf, // update_path: /persist/KubeOS-Update
- pub mount_path: PathBuf, // mount_path: /persist/KubeOS-Update/kubeos-update
- pub tar_path: PathBuf, // tar_path: /persist/KubeOS-Update/os.tar
- pub image_path: PathBuf, // image_path: /persist/update.img
- pub rootfs_file: String, // rootfs_file: os.tar
+ pub persist_path: PathBuf,
+ pub update_path: PathBuf,
+ pub mount_path: PathBuf,
+ pub tar_path: PathBuf,
+ pub image_path: PathBuf,
+ pub rootfs_file: String,
}
impl Default for PreparePath {
@@ -72,7 +83,7 @@ pub fn check_disk_size<P: AsRef<Path>>(need_bytes: i64, path: P) -> Result<()> {
Ok(())
}
-// clean_env will umount the mount path and delete directory /persist/KubeOS-Update and /persist/update.img
+/// clean_env will umount the mount path and delete directory /persist/KubeOS-Update and /persist/update.img
pub fn clean_env<P>(update_path: P, mount_path: P, image_path: P) -> Result<()>
where
P: AsRef<Path>,
@@ -160,6 +171,7 @@ mod tests {
use tempfile::{NamedTempFile, TempDir};
use super::*;
+ use crate::utils::RealCommandExecutor;
// Mock the CommandExecutor trait
mock! {
@@ -278,10 +290,23 @@ mod tests {
}
#[test]
- #[ignore]
fn test_get_boot_mode() {
init();
let boot_mode = get_boot_mode();
- assert!(boot_mode == "uefi");
+ let executor = RealCommandExecutor {};
+ let res = executor.run_command("ls", &["/sys/firmware/efi"]);
+ if res.is_ok() {
+ assert!(boot_mode == "uefi");
+ } else {
+ assert!(boot_mode == "bios");
+ }
+ }
+
+ #[test]
+ fn test_is_command_available() {
+ init();
+ let executor = RealCommandExecutor {};
+ assert_eq!(is_command_available("ls", &executor), true);
+ assert_eq!(is_command_available("aaaabb", &executor), false);
}
}
diff --git a/KubeOS-Rust/manager/src/utils/container_image.rs b/KubeOS-Rust/manager/src/utils/container_image.rs
index a54fc19..7c3aa02 100644
--- a/KubeOS-Rust/manager/src/utils/container_image.rs
+++ b/KubeOS-Rust/manager/src/utils/container_image.rs
@@ -197,12 +197,24 @@ mod tests {
let out1 = get_oci_image_digest(container_runtime, image_name, &mock).unwrap();
let expect_output = "1111";
assert_eq!(out1, expect_output);
+ mock.expect_run_command_with_output().times(1).returning(|_, _| Ok("invalid output".to_string()));
+ let out2 = get_oci_image_digest(container_runtime, image_name, &mock);
+ assert!(out2.is_err());
let container_runtime = "crictl";
let command_output2 = "[docker.io/nginx@sha256:1111]";
mock.expect_run_command_with_output().times(1).returning(|_, _| Ok(command_output2.to_string()));
- let out2 = get_oci_image_digest(container_runtime, image_name, &mock).unwrap();
- assert_eq!(out2, expect_output);
+ let out3 = get_oci_image_digest(container_runtime, image_name, &mock).unwrap();
+ assert_eq!(out3, expect_output);
+
+ let out4 = get_oci_image_digest("invalid", image_name, &mock);
+ assert!(out4.is_err());
+
+ let container_runtime = "crictl";
+ let command_output3 = "[docker.io/nginx:sha256:1111]";
+ mock.expect_run_command_with_output().times(1).returning(|_, _| Ok(command_output3.to_string()));
+ let out5 = get_oci_image_digest(container_runtime, image_name, &mock);
+ assert!(out5.is_err());
}
#[test]
@@ -211,11 +223,13 @@ mod tests {
let mut mock = MockCommandExec::new();
let image_name = "docker.io/nginx:latest";
let container_runtime = "crictl";
- let command_output = "[docker.io/nginx@sha256:1111]";
- let check_sum = "1111";
- mock.expect_run_command_with_output().times(1).returning(|_, _| Ok(command_output.to_string()));
+ let command_output = "[docker.io/nginx@sha256:1a2b]";
+ let check_sum = "1A2B";
+ mock.expect_run_command_with_output().times(2).returning(|_, _| Ok(command_output.to_string()));
let result = check_oci_image_digest(container_runtime, image_name, check_sum, &mock);
assert!(result.is_ok());
+ let result = check_oci_image_digest(container_runtime, image_name, "1111", &mock);
+ assert!(result.is_err());
}
#[test]
@@ -251,4 +265,26 @@ mod tests {
let result = pull_image("aaa", image_name, &mock_executor);
assert!(result.is_err());
}
+
+ #[test]
+ fn test_remove_image_if_exist() {
+ init();
+ let mut mock_executor = MockCommandExec::new();
+ mock_executor
+ .expect_run_command_with_output()
+ .withf(|cmd, args| cmd == "ctr" && args.contains(&"check")) // simplified with a closure
+ .times(1)
+ .returning(|_, _| Ok(String::from("something")));
+ mock_executor
+ .expect_run_command()
+ .withf(|cmd, args| cmd == "ctr" && args.contains(&"rm")) // simplified with a closure
+ .times(1)
+ .returning(|_, _| Ok(()));
+ let image_name = "docker.io/nginx:latest";
+ let res = remove_image_if_exist("ctr", image_name, &mock_executor);
+ assert!(res.is_ok());
+
+ let res = remove_image_if_exist("invalid", image_name, &mock_executor);
+ assert!(res.is_err());
+ }
}
diff --git a/KubeOS-Rust/manager/src/utils/partition.rs b/KubeOS-Rust/manager/src/utils/partition.rs
index 0419159..fcfa2d8 100644
--- a/KubeOS-Rust/manager/src/utils/partition.rs
+++ b/KubeOS-Rust/manager/src/utils/partition.rs
@@ -22,6 +22,7 @@ pub struct PartitionInfo {
pub fs_type: String,
}
+/// get_partition_info returns the current partition info and the next partition info.
pub fn get_partition_info<T: CommandExecutor>(executor: &T) -> Result<(PartitionInfo, PartitionInfo), anyhow::Error> {
let lsblk = executor.run_command_with_output("lsblk", &["-lno", "NAME,MOUNTPOINTS,FSTYPE"])?;
// After split whitespace, the root directory line should have 3 elements, which are "sda2 / ext4".
@@ -93,5 +94,19 @@ mod tests {
PartitionInfo { device: "/dev/sda3".to_string(), menuentry: "B".to_string(), fs_type: "ext4".to_string() },
);
assert_eq!(res, expect_res);
+
+ let command_output2 = "sda\nsda1 /boot/efi vfat\nsda2 ext4\nsda3 / ext4\nsda4 /persist ext4\nsr0 iso9660\n";
+ mock.expect_run_command_with_output().times(1).returning(|_, _| Ok(command_output2.to_string()));
+ let res = get_partition_info(&mock).unwrap();
+ let expect_res = (
+ PartitionInfo { device: "/dev/sda3".to_string(), menuentry: "B".to_string(), fs_type: "ext4".to_string() },
+ PartitionInfo { device: "/dev/sda2".to_string(), menuentry: "A".to_string(), fs_type: "ext4".to_string() },
+ );
+ assert_eq!(res, expect_res);
+
+ let command_output3 = "";
+ mock.expect_run_command_with_output().times(1).returning(|_, _| Ok(command_output3.to_string()));
+ let res = get_partition_info(&mock);
+ assert!(res.is_err());
}
}
--
2.34.1