Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(backend): add Rust tests #104

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4ceb70a
test(backend): add basic CPU validation test
ravenclaw900 Dec 31, 2021
95e3984
fix(backend): fix clippy lint
ravenclaw900 Dec 31, 2021
1c7d08e
test(dashboard): add tests for statistics page
ravenclaw900 Dec 31, 2021
874b604
fix(backend): fix clippy lints
ravenclaw900 Dec 31, 2021
74d4fee
test(backend): add network test
ravenclaw900 Jan 1, 2022
afc4e06
style: fix spelling of received
ravenclaw900 Jan 1, 2022
6c819b0
test(backend): add all systemdata tests
ravenclaw900 Jan 2, 2022
5913908
test(software): add missing assertations
ravenclaw900 Jan 2, 2022
b5fc77c
test(backend): fix clippy lints
ravenclaw900 Jan 2, 2022
6300d83
Merge branch 'main' into tests
ravenclaw900 Feb 21, 2022
f91d960
Merge branch 'main' into tests
ravenclaw900 Mar 20, 2022
a76a9fb
fix(tests): remove unnecessary `await`s
ravenclaw900 Mar 20, 2022
47ed11a
fix(tests): remove unnecessary `async`s
ravenclaw900 Mar 20, 2022
061ce91
fix(tests): do some more fixing of the tests to work with psutil
ravenclaw900 Mar 22, 2022
edb35ba
test(filebrowser): begin to add tests for file browser
ravenclaw900 Mar 27, 2022
c710356
Merge branch 'main' into tests
ravenclaw900 Mar 29, 2022
ee01fd9
Merge branch 'main' into tests
ravenclaw900 May 1, 2022
13b5c85
Merge branch 'main' into tests
ravenclaw900 May 1, 2022
fc04c03
build(backend): fix clippy lints
ravenclaw900 May 1, 2022
b3acd79
Merge branch 'main' into tests
ravenclaw900 Jun 30, 2022
8dc58a1
Merge branch 'main' into tests
MichaIng Mar 18, 2023
a67d40c
test(backend): re-add tests to new backend src location
MichaIng Mar 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 51 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
46 changes: 46 additions & 0 deletions src/socket_handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}
144 changes: 144 additions & 0 deletions src/systemdata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,3 +459,147 @@ pub fn temp() -> shared::CPUTemp {
},
}
}

#[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, "");
}
}
}
}