From 79f83b71de5f55c660ef98a7f8526c629ad79293 Mon Sep 17 00:00:00 2001 From: lol Date: Wed, 21 Feb 2024 16:55:56 +0100 Subject: [PATCH] test: create first real test --- .gitignore | 15 ++-- tests/tests.rs | 216 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+), 6 deletions(-) create mode 100644 tests/tests.rs diff --git a/.gitignore b/.gitignore index 635f34d..4f6f3ce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ +* +!/**/ +!*.rs +!.gitignore +!README.md +!LICENSE + target -*.test -.env -todo -.nextsync -.nextsyncignore -test +tests/nextcloud-docker-dev +tests/data diff --git a/tests/tests.rs b/tests/tests.rs new file mode 100644 index 0000000..a6369df --- /dev/null +++ b/tests/tests.rs @@ -0,0 +1,216 @@ +use std::process::{Command, Output}; +use std::os::unix::fs::PermissionsExt; +use rand::{distributions::Alphanumeric, Rng}; // 0.8 +use std::fs::{self, File, Permissions}; +use std::io::{Write, BufReader, BufRead}; +use std::env; +use std::path::PathBuf; + +struct ServerTest { + user: String, + volume: PathBuf, + test_id: String +} + +impl ServerTest { + fn new(id: String) -> Self { + let mut volume = env::current_dir().unwrap(); + volume = volume.join("tests/data/admin/files"); + + ServerTest { + user: String::from("admin"), + volume, + test_id: id + } + } + + fn init(mut self) -> Self { + self.add_dir(self.test_id.clone()); + self.volume = self.volume.join(self.test_id.clone()); + self.sync_test() + } + + fn clean(mut self) -> Self { + self.remove_dir(self.test_id.clone()); + self.sync_root() + } + + fn add_dir(&mut self, path: String) -> &mut ServerTest { + let mut full_path = self.volume.clone(); + full_path.push(path); + + match fs::create_dir(&full_path) { + Ok(_) => { + // Set permissions to 777 to allow nextcloud to access it (workaround avoiding to + // set group and owner to www-data) + if let Err(e) = fs::set_permissions(&full_path, Permissions::from_mode(0o777)) { + eprintln!("Error setting permissions: {}", e); + } + }, + Err(e) => eprintln!("Error creating directory: {}", e), + } + + self + } + + fn remove_dir(&mut self, path: String) -> &mut ServerTest { + let mut full_path = self.volume.clone(); + full_path.push(path); + + let _ = fs::remove_dir_all(&full_path); + self + } + + fn sync_root(self) -> Self { + self.sync("") + } + + fn sync_test(self) -> Self { + let test_id = self.test_id.clone(); + self.sync(&test_id) + } + + fn sync(self, path: &str) -> Self { + // perform the occ files:scan command inside the nextcloud docker container + + let nextcloud_docker = "master-nextcloud-1"; + let mut args = String::from("exec -ti --user www-data"); + args.push_str(nextcloud_docker); + args.push_str("/var/www/html/occ files:scan --path=/"); + args.push_str(&self.user); + args.push_str("files/"); + args.push_str(path); + + let _output = Command::new("docker") + .args(args.split(" ")) + .output() + .expect("Could not execute nextsync command"); + self + } + + fn has_file(&mut self, file: &str, content: &str) -> bool { + let full_path = self.volume.clone().join(file); + + if !full_path.exists() { + eprintln!("File '{}' does't exists", file); + return false; + } + + let file = File::open(full_path).unwrap(); + for line in BufReader::new(file).lines(){ + if let Ok(line) = line { + return line == content; + } + } + return false; + } +} + +struct ClientTest { + user: String, + volume: String, + test_id: String, + exe_path: PathBuf, +} + +impl ClientTest { + 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"); + + let _ = env::set_current_dir(vol.clone()); + + // build the client + ClientTest { + user: String::from("admin"), + volume: vol, + test_id: id, + exe_path + } + } + + 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 + } + + fn clean(self) -> Self { + let _ = fs::remove_dir_all(&self.volume); + self + } + + fn run_cmd_ok(&mut self, args: &str) -> Output { + let output = self.run_cmd(args); + if !output.status.success() { + 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 + } + + fn run_cmd(&mut self, args: &str) -> Output { + let output = Command::new(self.exe_path.to_str().unwrap()) + .args(args.split(" ")) + .output() + .expect("Could not execute nextsync command"); + return output; + } + + 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(()) + } +} + +fn get_random_test_id() -> String { + let mut id: String = rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(7) + .map(char::from) + .collect(); + id.push_str("_nextsync"); + id.to_owned() +} + +#[test] +fn test1() { + let id = get_random_test_id(); + dbg!(id.clone()); + let mut server = ServerTest::new(id.clone()).init(); + let mut client = ClientTest::new(id).init(); + + let _ = client.add_file("file1", "foo"); + client.run_cmd_ok("add file1"); + client.run_cmd_ok("push"); + + // tests + assert!(server.has_file("file1", "foo")); + + client.clean(); + server.clean(); +}