From 1df9c3fba55f0e7347d975272f05075c779b0f23 Mon Sep 17 00:00:00 2001 From: grimhilt Date: Sun, 8 Sep 2024 00:18:48 +0200 Subject: [PATCH] test(status): basics tests --- tests/common/client.rs | 133 ++++++++++++++++++++++++++++++++++++ tests/common/mod.rs | 2 + tests/common/utils.rs | 0 tests/status/main.rs | 1 + tests/status/status_test.rs | 14 ++++ tests/status_test.rs | 105 ++++++++++++++++++++++++++++ tests/tests.rs | 5 ++ tests/utils/client.rs | 110 +++++++++++++++++++++++++++++ 8 files changed, 370 insertions(+) create mode 100644 tests/common/client.rs create mode 100644 tests/common/mod.rs create mode 100644 tests/common/utils.rs create mode 100644 tests/status/main.rs create mode 100644 tests/status/status_test.rs create mode 100644 tests/status_test.rs create mode 100644 tests/tests.rs create mode 100644 tests/utils/client.rs diff --git a/tests/common/client.rs b/tests/common/client.rs new file mode 100644 index 0000000..27f271b --- /dev/null +++ b/tests/common/client.rs @@ -0,0 +1,133 @@ +use nextsync::config::config::Config; +use rand::{distributions::Alphanumeric, Rng}; +use std::env; +use std::fs::{self, File}; +use std::io::{self, Write}; +use std::path::PathBuf; +use std::process::{Command, Output}; +use std::str; + +pub struct ClientTest { + volume: String, // temp dir for the test + pub test_id: String, // name of the test (e.g nextsync_rand) + exe_path: PathBuf, // absolute path of nextsync executable +} + +pub fn get_random_test_id() -> String { + rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(4) + .map(char::from) + .collect() +} + +impl ClientTest { + pub fn new(id: &str) -> Self { + let mut test_id = id.to_string(); + test_id.push_str("_"); + test_id.push_str(&get_random_test_id()); + + // create a directory in /tmp with the given id + let mut vol = String::from("/tmp/nextsync/"); + vol.push_str(&test_id); + let _ = fs::remove_dir_all(&vol); + let _ = fs::create_dir_all(&vol); + + // get nextsync path + let mut exe_path = env::current_dir().unwrap(); + exe_path = exe_path.join("target/debug/nextsync"); + + // build the client + ClientTest { + volume: vol, + test_id, + exe_path, + } + } + + pub fn init(mut self) -> Self { + self.exec_ok("init"); + println!("========== {} ========== ", &self.test_id); + + // set remote url + // let url = String::from(format!("{}@nextcloud.local/{}", self.user, self.test_id)); + // self.run_cmd_ok(&format!("remote add origin {}", url)); + + // // set force_unsecure as debug server has not certificate + // self.run_cmd_ok("config set force_insecure true"); + + // // set token for request + // self.run_cmd_ok(&format!("credential add {} {}", self.user, self.user)); + self + } + + pub fn get_config(&self) -> Config { + Config::from(Some(&self.volume)) + } + + pub fn ok(self) -> io::Result<()> { + fs::remove_dir_all(&self.volume)?; + Ok(()) + } + + pub fn exec_ok(&mut self, args: &str) -> Output { + let output = self.exec(args); + if !output.status.success() { + println!("id: {}", self.test_id.clone()); + println!("Failed to execute: '{}'", args); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + } + assert!(output.status.success()); + output + } + + pub fn exec(&mut self, args: &str) -> Output { + let output = Command::new(self.exe_path.to_str().unwrap()) + .current_dir(self.volume.clone()) + .args(args.split(" ")) + .output() + .expect("Could not execute nextsync command"); + return output; + } + + pub fn add_dir(&mut self, name: &str) -> std::io::Result<()> { + let mut path = self.volume.clone(); + path.push_str("/"); + path.push_str(name); + let _ = fs::create_dir_all(path)?; + Ok(()) + } + + pub fn add_file(&mut self, name: &str, content: &str) -> std::io::Result<()> { + let mut path = self.volume.clone(); + path.push_str("/"); + path.push_str(name); + + let mut file = File::create(path)?; + file.write_all(content.as_bytes())?; + Ok(()) + } + + pub fn remove_file(&mut self, name: &str) -> std::io::Result<()> { + let mut path = self.volume.clone(); + path.push_str("/"); + path.push_str(name); + fs::remove_file(path)?; + Ok(()) + } + + pub fn remove_dir(&mut self, name: &str) -> std::io::Result<()> { + let mut path = self.volume.clone(); + path.push_str("/"); + path.push_str(name); + fs::remove_dir_all(path)?; + Ok(()) + } + + // pub fn has_file(&mut self, file: &str, content: &str) -> bool { + // let full_path = PathBuf::from(self.volume.clone()).join(file); + + // // has_files(full_path, file, content, self.test_id.clone()) + // } +} diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..e254155 --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,2 @@ +pub mod client; +pub mod utils; diff --git a/tests/common/utils.rs b/tests/common/utils.rs new file mode 100644 index 0000000..e69de29 diff --git a/tests/status/main.rs b/tests/status/main.rs new file mode 100644 index 0000000..9a5a7ed --- /dev/null +++ b/tests/status/main.rs @@ -0,0 +1 @@ +mod status_test; diff --git a/tests/status/status_test.rs b/tests/status/status_test.rs new file mode 100644 index 0000000..6fda94b --- /dev/null +++ b/tests/status/status_test.rs @@ -0,0 +1,14 @@ +// #[cfg(test)] +// mod status_tests { + +// #[test] +// fn status_test() { +// let client = ClientTest::new("").init(); +// } + +// // basic add +// // add all folder +// // add all folder current +// // ../folder/file add +// // add part of folder +// } diff --git a/tests/status_test.rs b/tests/status_test.rs new file mode 100644 index 0000000..cb35777 --- /dev/null +++ b/tests/status_test.rs @@ -0,0 +1,105 @@ +mod common; + +use common::client::ClientTest; +use nextsync::commands::status::{get_obj_changes, StatusArgs}; +use nextsync::config::config::Config; +use std::io; +use std::path::PathBuf; + +const DEFAULT_STATUS_ARG: StatusArgs = StatusArgs { nostyle: false }; + +fn status_exepected(config: &Config, staged: Vec<&str>, not_staged: Vec<&str>) { + let res = get_obj_changes(&DEFAULT_STATUS_ARG, config); + + assert_eq!(res.staged.len(), staged.len()); + assert_eq!(res.not_staged.len(), not_staged.len()); + + for obj in staged { + assert!(res + .staged + .iter() + .position(|e| { e.get_obj_path() == &PathBuf::from(obj) }) + .is_some()); + } + + for obj in not_staged { + assert!(res + .not_staged + .iter() + .position(|e| { e.get_obj_path() == &PathBuf::from(obj) }) + .is_some()); + } +} + +#[test] +fn simple_file() -> io::Result<()> { + let mut client = ClientTest::new("status__simple_file").init(); + + client.add_file("foo", "foo")?; + status_exepected(&client.get_config(), vec![], vec!["foo"]); + + client.exec_ok("add foo"); + status_exepected(&client.get_config(), vec!["foo"], vec![]); + + client.ok() +} + +#[test] +#[ignore] +fn all_folder() -> io::Result<()> { + let mut client = ClientTest::new("status__all_folder").init(); + + client.add_dir("dir")?; + client.add_file("dir/foo", "foo")?; + client.add_file("dir/bar", "bar")?; + client.add_file("foo", "foo")?; + status_exepected(&client.get_config(), vec![], vec!["foo", "dir"]); + + client.exec_ok("add dir"); + status_exepected(&client.get_config(), vec!["dir"], vec!["foo"]); + + client.ok() +} + +#[test] +#[ignore] +fn all_folder_current() -> io::Result<()> { + let mut client = ClientTest::new("status__all_folder_current").init(); + + client.add_dir("dir")?; + client.add_file("dir/foo", "foo")?; + client.add_file("dir/bar", "bar")?; + client.add_file("foor", "foor")?; + status_exepected(&client.get_config(), vec![], vec!["foor", "dir"]); + + client.exec_ok("add dir"); + status_exepected( + &Config::from(Some(&String::from("./dir"))), + vec!["foor", "bar"], + vec!["../foo"], + ); + + client.ok() +} + +#[test] +fn part_of_folder() -> io::Result<()> { + let mut client = ClientTest::new("status__part_of_folder").init(); + + client.add_dir("dir")?; + client.add_file("dir/foo", "foo")?; + client.add_file("dir/bar", "bar")?; + client.add_file("foor", "foor")?; + status_exepected(&client.get_config(), vec![], vec!["foor", "dir"]); + + client.exec_ok("add dir/foo"); + status_exepected( + &client.get_config(), + vec!["dir/foo"], + vec!["foor", "dir/bar"], + ); + + client.ok() +} + +// ../folder/file add diff --git a/tests/tests.rs b/tests/tests.rs new file mode 100644 index 0000000..086256c --- /dev/null +++ b/tests/tests.rs @@ -0,0 +1,5 @@ +#[cfg(test)] +mod tests { + // mod status; +} + diff --git a/tests/utils/client.rs b/tests/utils/client.rs new file mode 100644 index 0000000..8421417 --- /dev/null +++ b/tests/utils/client.rs @@ -0,0 +1,110 @@ +#[cfg(test)] +pub struct ClientTest { + volume: String, // temp dir for the test + pub test_id: String, // name of the test (e.g nextsync_rand) + exe_path: PathBuf, // absolute path of nextsync executable +} + +#[cfg(test)] +impl ClientTest { + pub fn new(id: String) -> Self { + // create a directory in /tmp with the given id + let mut vol = String::from("/tmp/"); + vol.push_str(&id); + let _ = fs::create_dir(vol.clone()); + + // get nextsync path + let mut exe_path = env::current_dir().unwrap(); + exe_path = exe_path.join("target/debug/nextsync"); + + // build the client + ClientTest { + user: String::from("admin"), + volume: vol, + test_id: id, + exe_path + } + } + + pub fn init(mut self) -> Self { + self.run_cmd_ok("init"); + + // set remote url + let url = String::from(format!("{}@nextcloud.local/{}", self.user, self.test_id)); + self.run_cmd_ok(&format!("remote add origin {}", url)); + + // set force_unsecure as debug server has not certificate + self.run_cmd_ok("config set force_insecure true"); + + // set token for request + self.run_cmd_ok(&format!("credential add {} {}", self.user, self.user)); + self + + } + + pub fn clean(self) -> Self { + let _ = fs::remove_dir_all(&self.volume); + self + } + + pub fn run_cmd_ok(&mut self, args: &str) -> Output { + let output = self.run_cmd(args); + if !output.status.success() { + println!("id: {}", self.test_id.clone()); + println!("Failed to execute: '{}'", args); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + } + assert!(output.status.success()); + output + } + + pub fn run_cmd(&mut self, args: &str) -> Output { + let output = Command::new(self.exe_path.to_str().unwrap()) + .current_dir(self.volume.clone()) + .args(args.split(" ")) + .output() + .expect("Could not execute nextsync command"); + return output; + } + + pub fn add_dir(&mut self, name: &str) -> std::io::Result<()> { + let mut path = self.volume.clone(); + path.push_str("/"); + path.push_str(name); + let _ = fs::create_dir_all(path)?; + Ok(()) + } + + pub fn add_file(&mut self, name: &str, content: &str) -> std::io::Result<()> { + let mut path = self.volume.clone(); + path.push_str("/"); + path.push_str(name); + + let mut file = File::create(path)?; + file.write_all(content.as_bytes())?; + Ok(()) + } + + pub fn remove_file(&mut self, name: &str) -> std::io::Result<()> { + let mut path = self.volume.clone(); + path.push_str("/"); + path.push_str(name); + fs::remove_file(path)?; + Ok(()) + } + + pub fn remove_dir(&mut self, name: &str) -> std::io::Result<()> { + let mut path = self.volume.clone(); + path.push_str("/"); + path.push_str(name); + fs::remove_dir_all(path)?; + Ok(()) + } + + pub fn has_file(&mut self, file: &str, content: &str) -> bool { + let full_path = PathBuf::from(self.volume.clone()).join(file); + + has_files(full_path, file, content, self.test_id.clone()) + } +}