From 898b57943bec8923c4f7848b4d181b76c7c5de09 Mon Sep 17 00:00:00 2001 From: ChristianVisintin Date: Fri, 18 Dec 2020 14:40:37 +0100 Subject: [PATCH] Improved test coverage --- src/bookmarks/mod.rs | 88 ++++++++++- src/filetransfer/ftp_transfer.rs | 27 ++++ src/filetransfer/mod.rs | 125 +++++++++++++++- src/filetransfer/scp_transfer.rs | 29 +++- src/filetransfer/sftp_transfer.rs | 27 ++++ src/host/mod.rs | 43 +++++- src/system/bookmarks_client.rs | 145 +++++++++++++++++-- src/system/environment.rs | 29 +++- src/ui/activities/auth_activity/bookmarks.rs | 2 +- 9 files changed, 488 insertions(+), 27 deletions(-) diff --git a/src/bookmarks/mod.rs b/src/bookmarks/mod.rs index 2cd0cd0..7015322 100644 --- a/src/bookmarks/mod.rs +++ b/src/bookmarks/mod.rs @@ -64,7 +64,7 @@ pub struct SerializerError { /// ## SerializerErrorKind /// /// Describes the kind of error for the serializer/deserializer -#[derive(std::fmt::Debug)] +#[derive(std::fmt::Debug, PartialEq)] pub enum SerializerErrorKind { IoError, SerializationError, @@ -101,7 +101,7 @@ impl SerializerError { impl std::fmt::Display for SerializerError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let err: String = match &self.kind { - SerializerErrorKind::IoError => String::from("IO Error"), + SerializerErrorKind::IoError => String::from("IO error"), SerializerErrorKind::SerializationError => String::from("Serialization error"), SerializerErrorKind::SyntaxError => String::from("Syntax error"), }; @@ -111,3 +111,87 @@ impl std::fmt::Display for SerializerError { } } } + +// Tests + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn test_bookmarks_bookmark_new() { + let bookmark: Bookmark = Bookmark { + address: String::from("192.168.1.1"), + port: 22, + protocol: String::from("SFTP"), + username: String::from("root"), + password: Some(String::from("password")), + }; + let recent: Bookmark = Bookmark { + address: String::from("192.168.1.2"), + port: 22, + protocol: String::from("SCP"), + username: String::from("admin"), + password: Some(String::from("password")), + }; + let mut bookmarks: HashMap = HashMap::with_capacity(1); + bookmarks.insert(String::from("test"), bookmark); + let mut recents: HashMap = HashMap::with_capacity(1); + recents.insert(String::from("ISO20201218T181432"), recent); + let hosts: UserHosts = UserHosts { + bookmarks: bookmarks, + recents: recents, + }; + // Verify + let bookmark: &Bookmark = hosts.bookmarks.get(&String::from("test")).unwrap(); + assert_eq!(bookmark.address, String::from("192.168.1.1")); + assert_eq!(bookmark.port, 22); + assert_eq!(bookmark.protocol, String::from("SFTP")); + assert_eq!(bookmark.username, String::from("root")); + assert_eq!( + *bookmark.password.as_ref().unwrap(), + String::from("password") + ); + let bookmark: &Bookmark = hosts + .recents + .get(&String::from("ISO20201218T181432")) + .unwrap(); + assert_eq!(bookmark.address, String::from("192.168.1.2")); + assert_eq!(bookmark.port, 22); + assert_eq!(bookmark.protocol, String::from("SCP")); + assert_eq!(bookmark.username, String::from("admin")); + assert_eq!( + *bookmark.password.as_ref().unwrap(), + String::from("password") + ); + } + + #[test] + fn test_bookmarks_bookmark_errors() { + let error: SerializerError = SerializerError::new(SerializerErrorKind::SyntaxError); + assert_eq!(error.kind, SerializerErrorKind::SyntaxError); + assert!(error.msg.is_none()); + assert_eq!(format!("{}", error), String::from("Syntax error")); + let error: SerializerError = + SerializerError::new_ex(SerializerErrorKind::SyntaxError, String::from("bad syntax")); + assert_eq!(error.kind, SerializerErrorKind::SyntaxError); + assert!(error.msg.is_some()); + assert_eq!( + format!("{}", error), + String::from("Syntax error (bad syntax)") + ); + // Fmt + assert_eq!( + format!("{}", SerializerError::new(SerializerErrorKind::IoError)), + String::from("IO error") + ); + assert_eq!( + format!( + "{}", + SerializerError::new(SerializerErrorKind::SerializationError) + ), + String::from("Serialization error") + ); + } +} diff --git a/src/filetransfer/ftp_transfer.rs b/src/filetransfer/ftp_transfer.rs index 6141110..4c3bddd 100644 --- a/src/filetransfer/ftp_transfer.rs +++ b/src/filetransfer/ftp_transfer.rs @@ -866,4 +866,31 @@ mod tests { // Disconnect assert!(ftp.disconnect().is_ok()); }*/ + + #[test] + fn test_filetransfer_ftp_uninitialized() { + let file: FsFile = FsFile { + name: String::from("omar.txt"), + abs_path: PathBuf::from("/omar.txt"), + last_change_time: SystemTime::UNIX_EPOCH, + last_access_time: SystemTime::UNIX_EPOCH, + creation_time: SystemTime::UNIX_EPOCH, + size: 0, + ftype: Some(String::from("txt")), // File type + readonly: true, + symlink: None, // UNIX only + user: Some(0), // UNIX only + group: Some(0), // UNIX only + unix_pex: Some((6, 4, 4)), // UNIX only + }; + let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false); + assert!(ftp.change_dir(Path::new("/tmp")).is_err()); + assert!(ftp.disconnect().is_err()); + assert!(ftp.list_dir(Path::new("/tmp")).is_err()); + assert!(ftp.mkdir(Path::new("/tmp")).is_err()); + assert!(ftp.pwd().is_err()); + assert!(ftp.stat(Path::new("/tmp")).is_err()); + assert!(ftp.recv_file(&file).is_err()); + assert!(ftp.send_file(&file, Path::new("/tmp/omar.txt")).is_err()); + } } diff --git a/src/filetransfer/mod.rs b/src/filetransfer/mod.rs index a53f40f..90325b2 100644 --- a/src/filetransfer/mod.rs +++ b/src/filetransfer/mod.rs @@ -37,7 +37,7 @@ pub mod sftp_transfer; /// /// This enum defines the different transfer protocol available in TermSCP -#[derive(std::cmp::PartialEq, std::fmt::Debug, std::clone::Clone, Copy)] +#[derive(PartialEq, std::fmt::Debug, std::clone::Clone, Copy)] pub enum FileTransferProtocol { Sftp, Scp, @@ -78,10 +78,7 @@ impl FileTransferError { /// /// Instantiates a new FileTransferError pub fn new(code: FileTransferErrorType) -> FileTransferError { - FileTransferError { - code, - msg: None, - } + FileTransferError { code, msg: None } } /// ### new_ex @@ -102,7 +99,7 @@ impl std::fmt::Display for FileTransferError { FileTransferErrorType::ConnectionError => String::from("Connection error"), FileTransferErrorType::DirStatFailed => String::from("Could not stat directory"), FileTransferErrorType::FileCreateDenied => String::from("Failed to create file"), - FileTransferErrorType::IoErr(err) => format!("IO Error: {}", err), + FileTransferErrorType::IoErr(err) => format!("IO error: {}", err), FileTransferErrorType::NoSuchFileOrDirectory => { String::from("No such file or directory") } @@ -193,7 +190,11 @@ pub trait FileTransfer { /// File name is referred to the name of the file as it will be saved /// Data contains the file data /// Returns file and its size - fn send_file(&mut self, local: &FsFile, file_name: &Path) -> Result, FileTransferError>; + fn send_file( + &mut self, + local: &FsFile, + file_name: &Path, + ) -> Result, FileTransferError>; /// ### recv_file /// @@ -219,3 +220,113 @@ pub trait FileTransfer { /// You must call this method each time you want to finalize the read of the remote file. fn on_recv(&mut self, readable: Box) -> Result<(), FileTransferError>; } + +// Tests + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn test_filetransfer_mod_protocol() { + assert_eq!( + FileTransferProtocol::Ftp(true), + FileTransferProtocol::Ftp(true) + ); + assert_eq!( + FileTransferProtocol::Ftp(false), + FileTransferProtocol::Ftp(false) + ); + } + + #[test] + fn test_filetransfer_mod_error() { + let err: FileTransferError = FileTransferError::new_ex( + FileTransferErrorType::IoErr(std::io::Error::from(std::io::ErrorKind::AddrInUse)), + String::from("non va una mazza"), + ); + assert_eq!(*err.msg.as_ref().unwrap(), String::from("non va una mazza")); + assert_eq!( + format!("{}", err), + String::from("IO error: address in use (non va una mazza)") + ); + assert_eq!( + format!( + "{}", + FileTransferError::new(FileTransferErrorType::AuthenticationFailed) + ), + String::from("Authentication failed") + ); + assert_eq!( + format!( + "{}", + FileTransferError::new(FileTransferErrorType::BadAddress) + ), + String::from("Bad address syntax") + ); + assert_eq!( + format!( + "{}", + FileTransferError::new(FileTransferErrorType::ConnectionError) + ), + String::from("Connection error") + ); + assert_eq!( + format!( + "{}", + FileTransferError::new(FileTransferErrorType::DirStatFailed) + ), + String::from("Could not stat directory") + ); + assert_eq!( + format!( + "{}", + FileTransferError::new(FileTransferErrorType::FileCreateDenied) + ), + String::from("Failed to create file") + ); + assert_eq!( + format!( + "{}", + FileTransferError::new(FileTransferErrorType::NoSuchFileOrDirectory) + ), + String::from("No such file or directory") + ); + assert_eq!( + format!( + "{}", + FileTransferError::new(FileTransferErrorType::PexError) + ), + String::from("Not enough permissions") + ); + assert_eq!( + format!( + "{}", + FileTransferError::new(FileTransferErrorType::ProtocolError) + ), + String::from("Protocol error") + ); + assert_eq!( + format!( + "{}", + FileTransferError::new(FileTransferErrorType::SslError) + ), + String::from("SSL error") + ); + assert_eq!( + format!( + "{}", + FileTransferError::new(FileTransferErrorType::UninitializedSession) + ), + String::from("Uninitialized session") + ); + assert_eq!( + format!( + "{}", + FileTransferError::new(FileTransferErrorType::UnsupportedFeature) + ), + String::from("Unsupported feature") + ); + } +} diff --git a/src/filetransfer/scp_transfer.rs b/src/filetransfer/scp_transfer.rs index a4edeb3..08fbe2a 100644 --- a/src/filetransfer/scp_transfer.rs +++ b/src/filetransfer/scp_transfer.rs @@ -185,7 +185,7 @@ impl ScpFileTransfer { Some(p) => match self.stat(p.as_path()) { Ok(e) => Some(Box::new(e)), Err(_) => None, // Ignore errors - } + }, }; // Check if file_name is '.' or '..' if file_name.as_str() == "." || file_name.as_str() == ".." { @@ -1029,4 +1029,31 @@ mod tests { assert!(client.disconnect().is_ok()); } */ + + #[test] + fn test_filetransfer_scp_uninitialized() { + let file: FsFile = FsFile { + name: String::from("omar.txt"), + abs_path: PathBuf::from("/omar.txt"), + last_change_time: SystemTime::UNIX_EPOCH, + last_access_time: SystemTime::UNIX_EPOCH, + creation_time: SystemTime::UNIX_EPOCH, + size: 0, + ftype: Some(String::from("txt")), // File type + readonly: true, + symlink: None, // UNIX only + user: Some(0), // UNIX only + group: Some(0), // UNIX only + unix_pex: Some((6, 4, 4)), // UNIX only + }; + let mut scp: ScpFileTransfer = ScpFileTransfer::new(); + assert!(scp.change_dir(Path::new("/tmp")).is_err()); + assert!(scp.disconnect().is_err()); + assert!(scp.list_dir(Path::new("/tmp")).is_err()); + assert!(scp.mkdir(Path::new("/tmp")).is_err()); + assert!(scp.pwd().is_err()); + assert!(scp.stat(Path::new("/tmp")).is_err()); + assert!(scp.recv_file(&file).is_err()); + assert!(scp.send_file(&file, Path::new("/tmp/omar.txt")).is_err()); + } } diff --git a/src/filetransfer/sftp_transfer.rs b/src/filetransfer/sftp_transfer.rs index 5ec5d7d..1d199d3 100644 --- a/src/filetransfer/sftp_transfer.rs +++ b/src/filetransfer/sftp_transfer.rs @@ -859,4 +859,31 @@ mod tests { assert!(client.disconnect().is_ok()); } */ + + #[test] + fn test_filetransfer_sftp_uninitialized() { + let file: FsFile = FsFile { + name: String::from("omar.txt"), + abs_path: PathBuf::from("/omar.txt"), + last_change_time: SystemTime::UNIX_EPOCH, + last_access_time: SystemTime::UNIX_EPOCH, + creation_time: SystemTime::UNIX_EPOCH, + size: 0, + ftype: Some(String::from("txt")), // File type + readonly: true, + symlink: None, // UNIX only + user: Some(0), // UNIX only + group: Some(0), // UNIX only + unix_pex: Some((6, 4, 4)), // UNIX only + }; + let mut sftp: SftpFileTransfer = SftpFileTransfer::new(); + assert!(sftp.change_dir(Path::new("/tmp")).is_err()); + assert!(sftp.disconnect().is_err()); + assert!(sftp.list_dir(Path::new("/tmp")).is_err()); + assert!(sftp.mkdir(Path::new("/tmp")).is_err()); + assert!(sftp.pwd().is_err()); + assert!(sftp.stat(Path::new("/tmp")).is_err()); + assert!(sftp.recv_file(&file).is_err()); + assert!(sftp.send_file(&file, Path::new("/tmp/omar.txt")).is_err()); + } } diff --git a/src/host/mod.rs b/src/host/mod.rs index 4dc0f59..5a20073 100644 --- a/src/host/mod.rs +++ b/src/host/mod.rs @@ -23,7 +23,7 @@ * */ -use std::fs::{self, File, Metadata, OpenOptions, set_permissions}; +use std::fs::{self, set_permissions, File, Metadata, OpenOptions}; use std::path::{Path, PathBuf}; use std::time::SystemTime; // Metadata ext @@ -74,7 +74,7 @@ impl std::fmt::Display for HostError { HostErrorType::NoSuchFileOrDirectory => "No such file or directory", HostErrorType::ReadonlyFile => "File is readonly", HostErrorType::DirNotAccessible => "Could not access directory", - HostErrorType::FileNotAccessible => "Could not access directory", + HostErrorType::FileNotAccessible => "Could not access file", HostErrorType::FileAlreadyExists => "File already exists", HostErrorType::CouldNotCreateFile => "Could not create file", HostErrorType::DeleteFailed => "Could not delete file", @@ -766,6 +766,45 @@ mod tests { .is_err()); } + #[test] + fn test_host_fmt_error() { + let err: HostError = HostError::new( + HostErrorType::CouldNotCreateFile, + Some(std::io::Error::from(std::io::ErrorKind::AddrInUse)), + ); + assert_eq!( + format!("{}", err), + String::from("Could not create file: address in use") + ); + assert_eq!( + format!("{}", HostError::new(HostErrorType::DeleteFailed, None)), + String::from("Could not delete file") + ); + assert_eq!( + format!("{}", HostError::new(HostErrorType::DirNotAccessible, None)), + String::from("Could not access directory") + ); + assert_eq!( + format!( + "{}", + HostError::new(HostErrorType::NoSuchFileOrDirectory, None) + ), + String::from("No such file or directory") + ); + assert_eq!( + format!("{}", HostError::new(HostErrorType::ReadonlyFile, None)), + String::from("File is readonly") + ); + assert_eq!( + format!("{}", HostError::new(HostErrorType::FileNotAccessible, None)), + String::from("Could not access file") + ); + assert_eq!( + format!("{}", HostError::new(HostErrorType::FileAlreadyExists, None)), + String::from("File already exists") + ); + } + /// ### create_sample_file /// /// Create a sample file diff --git a/src/system/bookmarks_client.rs b/src/system/bookmarks_client.rs index cd3a66b..e8c4bba 100644 --- a/src/system/bookmarks_client.rs +++ b/src/system/bookmarks_client.rs @@ -47,6 +47,7 @@ pub struct BookmarksClient { hosts: UserHosts, bookmarks_file: PathBuf, key: String, + recents_size: usize, } impl BookmarksClient { @@ -55,7 +56,11 @@ impl BookmarksClient { /// Instantiates a new BookmarksClient /// Bookmarks file path must be provided /// Key file must be provided - pub fn new(bookmarks_file: &Path, key_file: &Path) -> Result { + pub fn new( + bookmarks_file: &Path, + key_file: &Path, + recents_size: usize, + ) -> Result { // Create default hosts let default_hosts: UserHosts = Default::default(); // If key file doesn't exist, create key, otherwise read it @@ -73,6 +78,7 @@ impl BookmarksClient { hosts: default_hosts, bookmarks_file: PathBuf::from(bookmarks_file), key, + recents_size, }; // If bookmark file doesn't exist, initialize it if !bookmarks_file.exists() { @@ -196,8 +202,9 @@ impl BookmarksClient { return; } } - // If hosts size is bigger than 16; pop last - if self.hosts.recents.len() >= 16 { + // If hosts size is bigger than self.recents_size; pop last + if self.hosts.recents.len() >= self.recents_size { + // Get keys let mut keys: Vec = Vec::with_capacity(self.hosts.recents.len()); for key in self.hosts.recents.keys() { keys.push(key.clone()); @@ -207,8 +214,8 @@ impl BookmarksClient { // Delete keys starting from the last one for key in keys.iter() { let _ = self.hosts.recents.remove(key); - // If length is < 16; break - if self.hosts.recents.len() < 16 { + // If length is < self.recents_size; break + if self.hosts.recents.len() < self.recents_size { break; } } @@ -389,6 +396,8 @@ impl BookmarksClient { mod tests { use super::*; + use std::thread::sleep; + use std::time::Duration; #[test] fn test_system_bookmarks_new() { @@ -396,19 +405,28 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path()).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); // Verify client assert_eq!(client.hosts.bookmarks.len(), 0); assert_eq!(client.hosts.recents.len(), 0); assert!(client.key.len() > 0); assert_eq!(client.bookmarks_file, cfg_path); + assert_eq!(client.recents_size, 16); } #[test] fn test_system_bookmarks_new_err() { + assert!(BookmarksClient::new( + Path::new("/tmp/oifoif/omar"), + Path::new("/tmp/efnnu/omar"), + 16 + ) + .is_err()); + + let tmp_dir: tempfile::TempDir = create_tmp_dir(); + let (cfg_path, _): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); assert!( - BookmarksClient::new(Path::new("/tmp/oifoif/omar"), Path::new("/tmp/efnnu/omar")) - .is_err() + BookmarksClient::new(cfg_path.as_path(), Path::new("/tmp/efnnu/omar"), 16).is_err() ); } @@ -418,7 +436,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path()).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); // Add some bookmarks client.add_bookmark( String::from("raspberry"), @@ -439,7 +457,7 @@ mod tests { let key: String = client.key.clone(); // Re-initialize a client let client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path()).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); // Verify it loaded parameters correctly assert_eq!(client.key, key); let bookmark: (String, u16, FileTransferProtocol, String, Option) = @@ -463,7 +481,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path()).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); // Add bookmark client.add_bookmark( String::from("raspberry"), @@ -473,6 +491,16 @@ mod tests { String::from("pi"), Some(String::from("mypassword")), ); + client.add_bookmark( + String::from("raspberry2"), + String::from("192.168.1.32"), + 22, + FileTransferProtocol::Sftp, + String::from("pi"), + Some(String::from("mypassword2")), + ); + // Iter + assert_eq!(client.iter_bookmarks().count(), 2); // Get bookmark let bookmark: (String, u16, FileTransferProtocol, String, Option) = client.get_bookmark(&String::from("raspberry")).unwrap(); @@ -491,13 +519,32 @@ mod tests { assert!(client.write_bookmarks().is_ok()); } + #[test] + #[should_panic] + fn test_system_bookmarks_bad_bookmark_name() { + let tmp_dir: tempfile::TempDir = create_tmp_dir(); + let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); + // Initialize a new bookmarks client + let mut client: BookmarksClient = + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + // Add bookmark + client.add_bookmark( + String::from(""), + String::from("192.168.1.31"), + 22, + FileTransferProtocol::Sftp, + String::from("pi"), + Some(String::from("mypassword")), + ); + } + #[test] fn test_system_bookmarks_manipulate_recents() { let tmp_dir: tempfile::TempDir = create_tmp_dir(); let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path()).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); // Add bookmark client.add_recent( String::from("192.168.1.31"), @@ -505,6 +552,8 @@ mod tests { FileTransferProtocol::Sftp, String::from("pi"), ); + // Iter + assert_eq!(client.iter_recents().count(), 1); let key: String = String::from(client.iter_recents().next().unwrap()); // Get bookmark let bookmark: (String, u16, FileTransferProtocol, String) = @@ -523,6 +572,76 @@ mod tests { assert!(client.write_bookmarks().is_ok()); } + #[test] + fn test_system_bookmarks_dup_recent() { + let tmp_dir: tempfile::TempDir = create_tmp_dir(); + let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); + // Initialize a new bookmarks client + let mut client: BookmarksClient = + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + // Add bookmark + client.add_recent( + String::from("192.168.1.31"), + 22, + FileTransferProtocol::Sftp, + String::from("pi"), + ); + client.add_recent( + String::from("192.168.1.31"), + 22, + FileTransferProtocol::Sftp, + String::from("pi"), + ); + // There should be only one recent + assert_eq!(client.iter_recents().count(), 1); + } + + #[test] + fn test_system_bookmarks_recents_more_than_limit() { + let tmp_dir: tempfile::TempDir = create_tmp_dir(); + let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); + // Initialize a new bookmarks client + let mut client: BookmarksClient = + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 2).unwrap(); + // Add recent, wait 1 second for each one (cause the name depends on time) + // 1 + client.add_recent( + String::from("192.168.1.1"), + 22, + FileTransferProtocol::Sftp, + String::from("pi"), + ); + sleep(Duration::from_secs(1)); + // 2 + client.add_recent( + String::from("192.168.1.2"), + 22, + FileTransferProtocol::Sftp, + String::from("pi"), + ); + sleep(Duration::from_secs(1)); + // 3 + client.add_recent( + String::from("192.168.1.3"), + 22, + FileTransferProtocol::Sftp, + String::from("pi"), + ); + // Limit is 2 + assert_eq!(client.iter_recents().count(), 2); + // Check that 192.168.1.1 has been removed + let key: String = client.iter_recents().nth(0).unwrap().to_string(); + assert!(matches!( + client.hosts.recents.get(&key).unwrap().address.as_str(), + "192.168.1.2" | "192.168.1.3" + )); + let key: String = client.iter_recents().nth(1).unwrap().to_string(); + assert!(matches!( + client.hosts.recents.get(&key).unwrap().address.as_str(), + "192.168.1.2" | "192.168.1.3" + )); + } + #[test] #[should_panic] fn test_system_bookmarks_add_bookmark_empty() { @@ -530,7 +649,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path()).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); // Add bookmark client.add_bookmark( String::from(""), diff --git a/src/system/environment.rs b/src/system/environment.rs index c4af3fe..b569f64 100644 --- a/src/system/environment.rs +++ b/src/system/environment.rs @@ -61,8 +61,35 @@ mod tests { use super::*; + use std::fs::{File, OpenOptions}; + use std::io::Write; + #[test] fn test_system_environment_get_config_dir() { - assert!(init_config_dir().ok().unwrap().is_some()); + // Create and get conf_dir + let conf_dir: PathBuf = init_config_dir().ok().unwrap().unwrap(); + // Remove dir + assert!(std::fs::remove_dir_all(conf_dir.as_path()).is_ok()); + } + + #[test] + fn test_system_environment_get_config_dir_err() { + let mut conf_dir: PathBuf = dirs::config_dir().unwrap(); + conf_dir.push("termscp"); + // Create file + let mut f: File = OpenOptions::new() + .create(true) + .write(true) + .open(conf_dir.as_path()) + .ok() + .unwrap(); + // Write + assert!(writeln!(f, "Hello world!").is_ok()); + // Drop file + drop(f); + // Get config dir (will fail) + assert!(init_config_dir().is_err()); + // Remove file + assert!(std::fs::remove_file(conf_dir.as_path()).is_ok()); } } diff --git a/src/ui/activities/auth_activity/bookmarks.rs b/src/ui/activities/auth_activity/bookmarks.rs index e473c81..ac10aeb 100644 --- a/src/ui/activities/auth_activity/bookmarks.rs +++ b/src/ui/activities/auth_activity/bookmarks.rs @@ -231,7 +231,7 @@ impl AuthActivity { let mut key_file: PathBuf = path; key_file.push(".bookmarks.key"); // key file is hidden // Initialize client - match BookmarksClient::new(bookmarks_file.as_path(), key_file.as_path()) { + match BookmarksClient::new(bookmarks_file.as_path(), key_file.as_path(), 16) { Ok(cli) => self.bookmarks_client = Some(cli), Err(err) => { self.input_mode = InputMode::Popup(PopupType::Alert(