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(); }