From f351ee1aeae2d29bf76d72a847f699a5c19a6537 Mon Sep 17 00:00:00 2001 From: ChristianVisintin Date: Thu, 3 Dec 2020 17:10:48 +0100 Subject: [PATCH] Ftptransfer tests --- Cargo.lock | 74 +++++----- src/filetransfer/ftp_transfer.rs | 238 ++++++++++++++++++++++++++++--- src/filetransfer/mod.rs | 3 +- 3 files changed, 255 insertions(+), 60 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6790c59..c51833f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,9 +41,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" [[package]] name = "cc" -version = "1.0.62" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1770ced377336a88a67c473594ccc14eca6f4559217c34f64aac8f83d641b40" +checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15" [[package]] name = "cfg-if" @@ -99,7 +99,7 @@ dependencies = [ "lazy_static", "libc", "mio", - "parking_lot 0.11.0", + "parking_lot 0.11.1", "signal-hook", "winapi", ] @@ -131,7 +131,7 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "ftp" version = "3.0.1" -source = "git+https://github.com/ChristianVisintin/rust-ftp#daf6274f196ad264f2bf17c561f7954593130438" +source = "git+https://github.com/ChristianVisintin/rust-ftp#08108bfb728b031d5d6ad5cd0a9ef4b0904fb500" dependencies = [ "chrono", "lazy_static", @@ -161,18 +161,18 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb1fc4429a33e1f80d41dc9fea4d108a88bec1de8053878898ae448a0b52f613" +checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "js-sys" -version = "0.3.45" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" +checksum = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175" dependencies = [ "wasm-bindgen", ] @@ -226,9 +226,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" +checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" dependencies = [ "scopeguard", ] @@ -250,9 +250,9 @@ checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "mio" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8962c171f57fcfffa53f4df1bb15ec4c8cf26a7569459c9ceb62d94aab0d9584" +checksum = "f33bc887064ef1fd66020c9adfc45bb9f33d75a42096c81e7c56c65b75dd1a8b" dependencies = [ "libc", "log", @@ -263,9 +263,9 @@ dependencies = [ [[package]] name = "miow" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e" +checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" dependencies = [ "socket2", "winapi", @@ -338,12 +338,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" dependencies = [ "instant", - "lock_api 0.4.1", + "lock_api 0.4.2", "parking_lot_core 0.8.0", ] @@ -518,17 +518,17 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" +checksum = "7acad6f34eb9e8a259d3283d1e8c1d34d7415943d4895f65cc73813c7396fc85" [[package]] name = "socket2" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44" +checksum = "2c29947abdee2a218277abeca306f25789c938e500ea5a9d4b12a5a504466902" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", "redox_syscall", "winapi", @@ -636,9 +636,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" [[package]] name = "unicode-width" @@ -682,19 +682,19 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" +checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" +checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62" dependencies = [ "bumpalo", "lazy_static", @@ -707,9 +707,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" +checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -717,9 +717,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" +checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549" dependencies = [ "proc-macro2", "quote", @@ -730,15 +730,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" +checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158" [[package]] name = "web-sys" -version = "0.3.45" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" +checksum = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/src/filetransfer/ftp_transfer.rs b/src/filetransfer/ftp_transfer.rs index 8a669aa..fb03acf 100644 --- a/src/filetransfer/ftp_transfer.rs +++ b/src/filetransfer/ftp_transfer.rs @@ -250,18 +250,20 @@ impl FileTransfer for FtpFileTransfer { } }; } - // If username / password... - if let Some(username) = username { - let password: String = match password { - Some(pwd) => String::from(pwd), - None => String::new(), - }; - if let Err(err) = stream.login(username.as_str(), password.as_str()) { - return Err(FileTransferError::new_ex( - FileTransferErrorType::AuthenticationFailed, - format!("{}", err), - )); - } + // Login (use anonymous if credentials are unspecified) + let username: String = match username { + Some(u) => u.clone(), + None => String::from("anonymous"), + }; + let password: String = match password { + Some(pwd) => String::from(pwd), + None => String::new(), + }; + if let Err(err) = stream.login(username.as_str(), password.as_str()) { + return Err(FileTransferError::new_ex( + FileTransferErrorType::AuthenticationFailed, + format!("{}", err), + )); } // Set stream self.stream = Some(stream); @@ -529,6 +531,7 @@ impl FileTransfer for FtpFileTransfer { mod tests { use super::*; + use std::time::Duration; #[test] fn test_filetransfer_ftp_new() { @@ -560,9 +563,27 @@ mod tests { assert_eq!(file.user, None); assert_eq!(file.group, None); assert_eq!(file.unix_pex.unwrap(), (6, 6, 4)); - assert_eq!(file.last_access_time, 1541376000); - assert_eq!(file.last_change_time, 1541376000); - assert_eq!(file.creation_time, 1541376000); + assert_eq!( + file.last_access_time + .duration_since(SystemTime::UNIX_EPOCH) + .ok() + .unwrap(), + Duration::from_secs(1541376000) + ); + assert_eq!( + file.last_change_time + .duration_since(SystemTime::UNIX_EPOCH) + .ok() + .unwrap(), + Duration::from_secs(1541376000) + ); + assert_eq!( + file.creation_time + .duration_since(SystemTime::UNIX_EPOCH) + .ok() + .unwrap(), + Duration::from_secs(1541376000) + ); } else { panic!("Expected file, got directory"); } @@ -577,14 +598,32 @@ mod tests { if let FsEntry::File(file) = fs_entry { assert_eq!(file.abs_path, PathBuf::from("/tmp/omar.txt")); assert_eq!(file.name, String::from("omar.txt")); - assert_eq!(file.size, 8192); + assert_eq!(file.size, 4096); assert_eq!(file.symlink, None); assert_eq!(file.user, Some(0)); assert_eq!(file.group, Some(9)); assert_eq!(file.unix_pex.unwrap(), (7, 5, 5)); - assert_eq!(file.last_access_time, 1604593920); - assert_eq!(file.last_change_time, 1604593920); - assert_eq!(file.creation_time, 1604593920); + assert_eq!( + file.last_access_time + .duration_since(SystemTime::UNIX_EPOCH) + .ok() + .unwrap(), + Duration::from_secs(1604593920) + ); + assert_eq!( + file.last_change_time + .duration_since(SystemTime::UNIX_EPOCH) + .ok() + .unwrap(), + Duration::from_secs(1604593920) + ); + assert_eq!( + file.creation_time + .duration_since(SystemTime::UNIX_EPOCH) + .ok() + .unwrap(), + Duration::from_secs(1604593920) + ); } else { panic!("Expected file, got directory"); } @@ -603,9 +642,27 @@ mod tests { assert_eq!(dir.user, Some(0)); assert_eq!(dir.group, Some(9)); assert_eq!(dir.unix_pex.unwrap(), (7, 7, 5)); - assert_eq!(dir.last_access_time, 1541376000); - assert_eq!(dir.last_change_time, 1541376000); - assert_eq!(dir.creation_time, 1541376000); + assert_eq!( + dir.last_access_time + .duration_since(SystemTime::UNIX_EPOCH) + .ok() + .unwrap(), + Duration::from_secs(1541376000) + ); + assert_eq!( + dir.last_change_time + .duration_since(SystemTime::UNIX_EPOCH) + .ok() + .unwrap(), + Duration::from_secs(1541376000) + ); + assert_eq!( + dir.creation_time + .duration_since(SystemTime::UNIX_EPOCH) + .ok() + .unwrap(), + Duration::from_secs(1541376000) + ); assert_eq!(dir.readonly, false); } else { panic!("Expected directory, got directory"); @@ -618,4 +675,141 @@ mod tests { ) .is_err()); } + + #[test] + fn test_filetransfer_ftp_connect_unsecure_anonymous() { + let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false); + // Connect + assert!(ftp + .connect(String::from("speedtest.tele2.net"), 21, None, None) + .is_ok()); + // Pwd + assert_eq!(ftp.pwd().ok().unwrap(), PathBuf::from("/")); + // Disconnect + assert!(ftp.disconnect().is_ok()); + } + + #[test] + fn test_filetransfer_ftp_connect_unsecure_username() { + let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false); + // Connect + assert!(ftp + .connect( + String::from("test.rebex.net"), + 21, + Some(String::from("demo")), + Some(String::from("password")) + ) + .is_ok()); + // Pwd + assert_eq!(ftp.pwd().ok().unwrap(), PathBuf::from("/")); + // Disconnect + assert!(ftp.disconnect().is_ok()); + } + + #[test] + fn test_filetransfer_ftp_connect_secure() { + let mut ftp: FtpFileTransfer = FtpFileTransfer::new(true); + // Connect + assert!(ftp + .connect( + String::from("test.rebex.net"), + 21, + Some(String::from("demo")), + Some(String::from("password")) + ) + .is_ok()); + // Pwd + assert_eq!(ftp.pwd().ok().unwrap(), PathBuf::from("/")); + // Disconnect + assert!(ftp.disconnect().is_ok()); + } + + #[test] + fn test_filetransfer_ftp_change_dir() { + let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false); + // Connect + assert!(ftp + .connect(String::from("speedtest.tele2.net"), 21, None, None) + .is_ok()); + // Pwd + assert_eq!(ftp.pwd().ok().unwrap(), PathBuf::from("/")); + // Cwd + assert!(ftp.change_dir(PathBuf::from("upload/").as_path()).is_ok()); + // Pwd + assert_eq!(ftp.pwd().ok().unwrap(), PathBuf::from("/upload")); + // Disconnect + assert!(ftp.disconnect().is_ok()); + } + + /* NOTE: they don't work + #[test] + fn test_filetransfer_ftp_list_dir() { + let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false); + // Connect + assert!(ftp.connect(String::from("speedtest.tele2.net"), 21, None, None).is_ok()); + // Pwd + assert_eq!(ftp.pwd().ok().unwrap(), PathBuf::from("/")); + // List dir + println!("{:?}", ftp.list_dir(PathBuf::from("/").as_path())); + let files: Vec = ftp.list_dir(PathBuf::from("/").as_path()).ok().unwrap(); + // There should be 19 files + assert_eq!(files.len(), 19); + // Verify first entry (1000GB.zip) + let first: &FsEntry = files.get(0).unwrap(); + if let FsEntry::File(f) = first { + assert_eq!(f.name, String::from("1000GB.zip")); + assert_eq!(f.abs_path, PathBuf::from("/1000GB.zip")); + assert_eq!(f.size, 1073741824000); + assert_eq!(*f.ftype.as_ref().unwrap(), String::from("zip")); + assert_eq!(f.unix_pex.unwrap(), (6, 4, 4)); + assert_eq!(f.creation_time.duration_since(SystemTime::UNIX_EPOCH).unwrap(), Duration::from_secs(1455840000)); + assert_eq!(f.last_access_time.duration_since(SystemTime::UNIX_EPOCH).unwrap(), Duration::from_secs(1455840000)); + assert_eq!(f.last_change_time.duration_since(SystemTime::UNIX_EPOCH).unwrap(), Duration::from_secs(1455840000)); + } else { + panic!("First should be a file, but it a directory"); + } + // Verify last entry (directory upload) + let last: &FsEntry = files.get(18).unwrap(); + if let FsEntry::Directory(d) = last { + assert_eq!(d.name, String::from("upload")); + assert_eq!(d.abs_path, PathBuf::from("/upload")); + assert_eq!(d.readonly, false); + assert_eq!(d.unix_pex.unwrap(), (7, 5, 5)); + } else { + panic!("Last should be a directory, but is a file"); + } + // Disconnect + assert!(ftp.disconnect().is_ok()); + } + + #[test] + fn test_filetransfer_ftp_recv() { + let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false); + // Connect + assert!(ftp.connect(String::from("test.rebex.net"), 21, Some(String::from("demo")), Some(String::from("password"))).is_ok()); + // Pwd + assert_eq!(ftp.pwd().ok().unwrap(), PathBuf::from("/")); + // Recv 100KB + assert!(ftp.recv_file(PathBuf::from("readme.txt").as_path()).is_ok()); + // Disconnect + assert!(ftp.disconnect().is_ok()); + } + + #[test] + fn test_filetransfer_ftp_send() { + let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false); + // Connect + assert!(ftp.connect(String::from("speedtest.tele2.net"), 21, None, None).is_ok()); + // Pwd + assert_eq!(ftp.pwd().ok().unwrap(), PathBuf::from("/")); + // Cwd + assert!(ftp.change_dir(PathBuf::from("upload/").as_path()).is_ok()); + // Pwd + assert_eq!(ftp.pwd().ok().unwrap(), PathBuf::from("/upload")); + // Send a sample file 100KB + assert!(ftp.send_file(PathBuf::from("test.txt").as_path()).is_ok()); + // Disconnect + assert!(ftp.disconnect().is_ok()); + }*/ } diff --git a/src/filetransfer/mod.rs b/src/filetransfer/mod.rs index e123342..49619f2 100644 --- a/src/filetransfer/mod.rs +++ b/src/filetransfer/mod.rs @@ -45,7 +45,7 @@ pub enum FileTransferProtocol { /// ## FileTransferError /// /// FileTransferError defines the possible errors available for a file transfer - +#[derive(std::fmt::Debug)] pub struct FileTransferError { code: FileTransferErrorType, msg: Option, @@ -55,6 +55,7 @@ pub struct FileTransferError { /// /// FileTransferErrorType defines the possible errors available for a file transfer #[allow(dead_code)] +#[derive(std::fmt::Debug)] pub enum FileTransferErrorType { AuthenticationFailed, BadAddress,