use std::path::PathBuf; use assert_fs::prelude::*; use rstest::*; use serde_json::json; use test_log::test; use crate::common::fixtures::*; /// Creates a directory in the form /// /// $TEMP/ /// $TEMP/dir1/ /// $TEMP/dir1/dira/ /// $TEMP/dir1/dirb/ /// $TEMP/dir1/dirb/file1 /// $TEMP/dir1/file1 /// $TEMP/dir1/file2 /// $TEMP/dir2/ /// $TEMP/dir2/dira/ /// $TEMP/dir2/dirb/ /// $TEMP/dir2/dirb/file1 /// $TEMP/dir2/file1 /// $TEMP/dir2/file2 /// $TEMP/file1 /// $TEMP/file2 fn make_directory() -> assert_fs::TempDir { let temp = assert_fs::TempDir::new().unwrap(); // $TEMP/file1 // $TEMP/file2 temp.child("file1").touch().unwrap(); temp.child("file2").touch().unwrap(); // $TEMP/dir1/ // $TEMP/dir1/file1 // $TEMP/dir1/file2 let dir1 = temp.child("dir1"); dir1.create_dir_all().unwrap(); dir1.child("file1").touch().unwrap(); dir1.child("file2").touch().unwrap(); // $TEMP/dir1/dira/ let dir1_dira = dir1.child("dira"); dir1_dira.create_dir_all().unwrap(); // $TEMP/dir1/dirb/ // $TEMP/dir1/dirb/file1 let dir1_dirb = dir1.child("dirb"); dir1_dirb.create_dir_all().unwrap(); dir1_dirb.child("file1").touch().unwrap(); // $TEMP/dir2/ // $TEMP/dir2/file1 // $TEMP/dir2/file2 let dir2 = temp.child("dir2"); dir2.create_dir_all().unwrap(); dir2.child("file1").touch().unwrap(); dir2.child("file2").touch().unwrap(); // $TEMP/dir2/dira/ let dir2_dira = dir2.child("dira"); dir2_dira.create_dir_all().unwrap(); // $TEMP/dir2/dirb/ // $TEMP/dir2/dirb/file1 let dir2_dirb = dir2.child("dirb"); dir2_dirb.create_dir_all().unwrap(); dir2_dirb.child("file1").touch().unwrap(); temp } #[rstest] #[test(tokio::test)] async fn should_support_json_output(mut api_process: CtxCommand) { validate_authentication(&mut api_process).await; let temp = make_directory(); let id = rand::random::().to_string(); let req = json!({ "id": id, "payload": { "type": "dir_read", "path": temp.to_path_buf(), "depth": 1, "absolute": false, "canonicalize": false, "include_root": false, }, }); let res = api_process.write_and_read_json(req).await.unwrap().unwrap(); assert_eq!(res["origin_id"], id, "JSON: {res}"); assert_eq!( res["payload"], json!({ "type": "dir_entries", "entries": [ {"path": PathBuf::from("dir1"), "file_type": "dir", "depth": 1}, {"path": PathBuf::from("dir2"), "file_type": "dir", "depth": 1}, {"path": PathBuf::from("file1"), "file_type": "file", "depth": 1}, {"path": PathBuf::from("file2"), "file_type": "file", "depth": 1}, ], "errors": [], }), "JSON: {res}" ); } #[rstest] #[test(tokio::test)] async fn should_support_json_returning_absolute_paths_if_specified( mut api_process: CtxCommand, ) { validate_authentication(&mut api_process).await; let temp = make_directory(); // NOTE: Our root path is always canonicalized, so the absolute path // provided is our canonicalized root path prepended let root_path = temp.to_path_buf().canonicalize().unwrap(); let id = rand::random::().to_string(); let req = json!({ "id": id, "payload": { "type": "dir_read", "path": temp.to_path_buf(), "depth": 1, "absolute": true, "canonicalize": false, "include_root": false, }, }); let res = api_process.write_and_read_json(req).await.unwrap().unwrap(); assert_eq!(res["origin_id"], id, "JSON: {res}"); assert_eq!( res["payload"], json!({ "type": "dir_entries", "entries": [ {"path": root_path.join("dir1"), "file_type": "dir", "depth": 1}, {"path": root_path.join("dir2"), "file_type": "dir", "depth": 1}, {"path": root_path.join("file1"), "file_type": "file", "depth": 1}, {"path": root_path.join("file2"), "file_type": "file", "depth": 1}, ], "errors": [], }), "JSON: {res}" ); } #[rstest] #[test(tokio::test)] async fn should_support_json_returning_all_files_and_directories_if_depth_is_0( mut api_process: CtxCommand, ) { validate_authentication(&mut api_process).await; let temp = make_directory(); let id = rand::random::().to_string(); let req = json!({ "id": id, "payload": { "type": "dir_read", "path": temp.to_path_buf(), "depth": 0, "absolute": false, "canonicalize": false, "include_root": false, }, }); let res = api_process.write_and_read_json(req).await.unwrap().unwrap(); assert_eq!(res["origin_id"], id, "JSON: {res}"); assert_eq!( res["payload"], json!({ "type": "dir_entries", "entries": [ {"path": PathBuf::from("dir1"), "file_type": "dir", "depth": 1}, {"path": PathBuf::from("dir1").join("dira"), "file_type": "dir", "depth": 2}, {"path": PathBuf::from("dir1").join("dirb"), "file_type": "dir", "depth": 2}, {"path": PathBuf::from("dir1").join("dirb").join("file1"), "file_type": "file", "depth": 3}, {"path": PathBuf::from("dir1").join("file1"), "file_type": "file", "depth": 2}, {"path": PathBuf::from("dir1").join("file2"), "file_type": "file", "depth": 2}, {"path": PathBuf::from("dir2"), "file_type": "dir", "depth": 1}, {"path": PathBuf::from("dir2").join("dira"), "file_type": "dir", "depth": 2}, {"path": PathBuf::from("dir2").join("dirb"), "file_type": "dir", "depth": 2}, {"path": PathBuf::from("dir2").join("dirb").join("file1"), "file_type": "file", "depth": 3}, {"path": PathBuf::from("dir2").join("file1"), "file_type": "file", "depth": 2}, {"path": PathBuf::from("dir2").join("file2"), "file_type": "file", "depth": 2}, {"path": PathBuf::from("file1"), "file_type": "file", "depth": 1}, {"path": PathBuf::from("file2"), "file_type": "file", "depth": 1}, ], "errors": [], }), "JSON: {res}" ); } #[rstest] #[test(tokio::test)] async fn should_support_json_including_root_directory_if_specified( mut api_process: CtxCommand, ) { validate_authentication(&mut api_process).await; let temp = make_directory(); // NOTE: Our root path is always canonicalized, so yielded entry // is the canonicalized version let root_path = temp.to_path_buf().canonicalize().unwrap(); let id = rand::random::().to_string(); let req = json!({ "id": id, "payload": { "type": "dir_read", "path": temp.to_path_buf(), "depth": 1, "absolute": false, "canonicalize": false, "include_root": true, }, }); let res = api_process.write_and_read_json(req).await.unwrap().unwrap(); assert_eq!(res["origin_id"], id, "JSON: {res}"); assert_eq!( res["payload"], json!({ "type": "dir_entries", "entries": [ {"path": root_path, "file_type": "dir", "depth": 0}, {"path": PathBuf::from("dir1"), "file_type": "dir", "depth": 1}, {"path": PathBuf::from("dir2"), "file_type": "dir", "depth": 1}, {"path": PathBuf::from("file1"), "file_type": "file", "depth": 1}, {"path": PathBuf::from("file2"), "file_type": "file", "depth": 1}, ], "errors": [], }), "JSON: {res}" ); } #[rstest] #[test(tokio::test)] async fn should_support_json_output_for_error(mut api_process: CtxCommand) { validate_authentication(&mut api_process).await; let temp = make_directory(); let dir = temp.child("missing-dir"); let id = rand::random::().to_string(); let req = json!({ "id": id, "payload": { "type": "dir_read", "path": dir.to_path_buf(), "depth": 1, "absolute": false, "canonicalize": false, "include_root": false, }, }); let res = api_process.write_and_read_json(req).await.unwrap().unwrap(); assert_eq!(res["origin_id"], id, "JSON: {res}"); assert_eq!(res["payload"]["type"], "error", "JSON: {res}"); assert_eq!(res["payload"]["kind"], "not_found", "JSON: {res}"); }