From 5dea83355ea8974d61179be53c5f7d72e25b9196 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 18 Mar 2023 01:45:44 +0100 Subject: [PATCH] test(backend): re-add tests to new backend src location Signed-off-by: MichaIng --- Cargo.toml | 3 + src/socket_handlers.rs | 46 +++++++++++++ src/systemdata.rs | 144 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 193 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 95afdba8..4b615309 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,9 @@ hex = "0.4.3" vite-embed = { git = "https://github.com/ravenclaw900/vite-embed", version = "0.1.0", features = ["prod"], optional = true } mime_guess = { version = "2.0.4", default-features = false } +[dev-dependencies] +tempfile = "3.3.0" + [features] default = ["frontend"] frontend = ["dep:vite-embed"] diff --git a/src/socket_handlers.rs b/src/socket_handlers.rs index 290f2402..a8d9cf46 100644 --- a/src/socket_handlers.rs +++ b/src/socket_handlers.rs @@ -488,3 +488,49 @@ pub async fn file_handler( } } } + +#[cfg(test)] +mod tests { + use super::*; + use nanoserde::SerJson; + use shared::FileRequest; + use std::io::Write; + use tempfile::NamedTempFile; + use warp::Filter; + + #[tokio::test] + async fn file_socket_test() { + let file_route = warp::ws().map(|ws: warp::ws::Ws| ws.on_upgrade(file_handler)); + + let (mut file, path) = NamedTempFile::new().unwrap().into_parts(); + let path = path.to_str().unwrap().to_string(); + file.write_all(b"dietpi dashboard, hello file!").unwrap(); + let mut socket = warp::test::ws().handshake(file_route).await.unwrap(); + socket + .send_text(SerJson::serialize_json(&FileRequest { + cmd: "open".to_string(), + path: path.clone(), + token: String::new(), + arg: String::new(), + })) + .await; + assert_eq!( + socket.recv().await.unwrap().to_str().unwrap(), + "dietpi dashboard, hello file!" + ); + socket + .send_text(SerJson::serialize_json(&FileRequest { + cmd: "save".to_string(), + path: path.clone(), + token: String::new(), + arg: "dietpi dashboard, writing test".to_string(), + })) + .await; + // Wait for writing to complete + tokio::time::sleep(std::time::Duration::from_millis(500)).await; + + // Yes, .read_to_string() on the file should work, but it doesn't for some reason + let contents = std::fs::read_to_string(path).unwrap(); + assert_eq!(contents, "dietpi dashboard, writing test"); + } +} diff --git a/src/systemdata.rs b/src/systemdata.rs index 2be1e830..a51d0a3f 100644 --- a/src/systemdata.rs +++ b/src/systemdata.rs @@ -603,3 +603,147 @@ mod tests { } } } + +#[allow(clippy::float_cmp)] // All it's doing is rounding, so there shouldn't be any floating point errors +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn check_round() { + assert_eq!(round_percent(56.7396), 56.74); + assert_eq!(round_percent(99.989), 99.99); + assert_eq!(round_percent(99.999), 100.00); + assert_eq!(round_percent(31.25), 31.25); + assert_eq!(round_percent(20.323), 20.32); + assert_eq!(round_percent(0.105), 0.11); + assert_eq!(round_percent(0.001), 0.0); + } + + #[tokio::test] + async fn validate_cpu() { + let output = cpu().await; + assert!((0.0..=100.0).contains(&output)); + } + + #[allow(clippy::cast_precision_loss)] + fn usage_test(used: u64, total: u64, percent_test: f32) { + assert!(used <= total); + if total != 0 { + assert_eq!( + round_percent((used as f32 / total as f32) * 100.0), + percent_test + ); + } + } + + #[test] + fn validate_ram() { + let output = ram(); + assert!(output.total > 0); + usage_test(output.used, output.total, output.percent); + } + + #[test] + fn validate_swap() { + let output = swap(); + usage_test(output.used, output.total, output.percent); + } + + // Disk percent is actually a measure of user space used, so we can't validate here + #[tokio::test] + async fn validate_disk() { + let output = disk(); + assert!(output.used <= output.total); + assert!(output.used < output.total); + } + + #[tokio::test] + async fn validate_network() { + let mut output = network(); + assert_eq!(output.sent, 0); + assert_eq!(output.received, 0); + // Just make sure that it works + for _ in 0..20 { + sleep(Duration::from_millis(100)).await; + let old_sent = BYTES_SENT.load(Relaxed); + let old_recv = BYTES_RECV.load(Relaxed); + output = network(); + assert_eq!(BYTES_SENT.load(Relaxed), output.sent + old_sent); + assert_eq!(BYTES_RECV.load(Relaxed), output.received + old_recv); + } + } + + // Very little to actually validate here, just make sure that there are no errors + #[tokio::test] + async fn validate_processes() { + for _ in 0..30 { + processes().await; + } + } + + #[test] + fn validate_software() { + let output = dpsoftware(); + let cmd = Command::new("/boot/dietpi/dietpi-software") + .arg("list") + .output() + .unwrap() + .stdout; + let mut install_counter = 0; + let mut uninstall_counter = 0; + for i in from_utf8(&cmd).unwrap().lines().skip(4) { + if i.contains("DISABLED") { + continue; + } + if i.split_once('|') + .unwrap() + .1 + .trim() + .trim_start_matches('=') + .starts_with('0') + { + uninstall_counter += 1; + } else { + install_counter += 1; + } + } + assert_eq!(uninstall_counter, output.0.len()); + assert_eq!(install_counter, output.1.len()); + } + + #[test] + fn validate_host() { + let output = host(); + + assert_eq!( + output.kernel, + from_utf8(&Command::new("uname").arg("-r").output().unwrap().stdout) + .unwrap() + .trim_end_matches('\n') + ); + + // The IP address shouldn't be the loopback + assert_ne!(output.nic, "127.0.0.1"); + + assert_eq!( + output.hostname, + from_utf8(&Command::new("hostname").output().unwrap().stdout) + .unwrap() + .trim_end_matches('\n') + ); + } + + #[test] + fn validate_services() { + let output = services(); + for i in output { + if i.status == "running" || i.status == "exited" { + assert_ne!(i.start, ""); + assert_eq!(i.log, ""); + } else if i.status == "failed" { + assert_ne!(i.log, ""); + } + } + } +}