mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Improved test coverage
This commit is contained in:
@@ -64,7 +64,7 @@ pub struct SerializerError {
|
|||||||
/// ## SerializerErrorKind
|
/// ## SerializerErrorKind
|
||||||
///
|
///
|
||||||
/// Describes the kind of error for the serializer/deserializer
|
/// Describes the kind of error for the serializer/deserializer
|
||||||
#[derive(std::fmt::Debug)]
|
#[derive(std::fmt::Debug, PartialEq)]
|
||||||
pub enum SerializerErrorKind {
|
pub enum SerializerErrorKind {
|
||||||
IoError,
|
IoError,
|
||||||
SerializationError,
|
SerializationError,
|
||||||
@@ -101,7 +101,7 @@ impl SerializerError {
|
|||||||
impl std::fmt::Display for SerializerError {
|
impl std::fmt::Display for SerializerError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
let err: String = match &self.kind {
|
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::SerializationError => String::from("Serialization error"),
|
||||||
SerializerErrorKind::SyntaxError => String::from("Syntax 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<String, Bookmark> = HashMap::with_capacity(1);
|
||||||
|
bookmarks.insert(String::from("test"), bookmark);
|
||||||
|
let mut recents: HashMap<String, Bookmark> = 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")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -866,4 +866,31 @@ mod tests {
|
|||||||
// Disconnect
|
// Disconnect
|
||||||
assert!(ftp.disconnect().is_ok());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ pub mod sftp_transfer;
|
|||||||
///
|
///
|
||||||
/// This enum defines the different transfer protocol available in TermSCP
|
/// 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 {
|
pub enum FileTransferProtocol {
|
||||||
Sftp,
|
Sftp,
|
||||||
Scp,
|
Scp,
|
||||||
@@ -78,10 +78,7 @@ impl FileTransferError {
|
|||||||
///
|
///
|
||||||
/// Instantiates a new FileTransferError
|
/// Instantiates a new FileTransferError
|
||||||
pub fn new(code: FileTransferErrorType) -> FileTransferError {
|
pub fn new(code: FileTransferErrorType) -> FileTransferError {
|
||||||
FileTransferError {
|
FileTransferError { code, msg: None }
|
||||||
code,
|
|
||||||
msg: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ### new_ex
|
/// ### new_ex
|
||||||
@@ -102,7 +99,7 @@ impl std::fmt::Display for FileTransferError {
|
|||||||
FileTransferErrorType::ConnectionError => String::from("Connection error"),
|
FileTransferErrorType::ConnectionError => String::from("Connection error"),
|
||||||
FileTransferErrorType::DirStatFailed => String::from("Could not stat directory"),
|
FileTransferErrorType::DirStatFailed => String::from("Could not stat directory"),
|
||||||
FileTransferErrorType::FileCreateDenied => String::from("Failed to create file"),
|
FileTransferErrorType::FileCreateDenied => String::from("Failed to create file"),
|
||||||
FileTransferErrorType::IoErr(err) => format!("IO Error: {}", err),
|
FileTransferErrorType::IoErr(err) => format!("IO error: {}", err),
|
||||||
FileTransferErrorType::NoSuchFileOrDirectory => {
|
FileTransferErrorType::NoSuchFileOrDirectory => {
|
||||||
String::from("No such file or directory")
|
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
|
/// File name is referred to the name of the file as it will be saved
|
||||||
/// Data contains the file data
|
/// Data contains the file data
|
||||||
/// Returns file and its size
|
/// Returns file and its size
|
||||||
fn send_file(&mut self, local: &FsFile, file_name: &Path) -> Result<Box<dyn Write>, FileTransferError>;
|
fn send_file(
|
||||||
|
&mut self,
|
||||||
|
local: &FsFile,
|
||||||
|
file_name: &Path,
|
||||||
|
) -> Result<Box<dyn Write>, FileTransferError>;
|
||||||
|
|
||||||
/// ### recv_file
|
/// ### 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.
|
/// You must call this method each time you want to finalize the read of the remote file.
|
||||||
fn on_recv(&mut self, readable: Box<dyn Read>) -> Result<(), FileTransferError>;
|
fn on_recv(&mut self, readable: Box<dyn Read>) -> 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")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ impl ScpFileTransfer {
|
|||||||
Some(p) => match self.stat(p.as_path()) {
|
Some(p) => match self.stat(p.as_path()) {
|
||||||
Ok(e) => Some(Box::new(e)),
|
Ok(e) => Some(Box::new(e)),
|
||||||
Err(_) => None, // Ignore errors
|
Err(_) => None, // Ignore errors
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
// Check if file_name is '.' or '..'
|
// Check if file_name is '.' or '..'
|
||||||
if file_name.as_str() == "." || file_name.as_str() == ".." {
|
if file_name.as_str() == "." || file_name.as_str() == ".." {
|
||||||
@@ -1029,4 +1029,31 @@ mod tests {
|
|||||||
assert!(client.disconnect().is_ok());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -859,4 +859,31 @@ mod tests {
|
|||||||
assert!(client.disconnect().is_ok());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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::path::{Path, PathBuf};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
// Metadata ext
|
// Metadata ext
|
||||||
@@ -74,7 +74,7 @@ impl std::fmt::Display for HostError {
|
|||||||
HostErrorType::NoSuchFileOrDirectory => "No such file or directory",
|
HostErrorType::NoSuchFileOrDirectory => "No such file or directory",
|
||||||
HostErrorType::ReadonlyFile => "File is readonly",
|
HostErrorType::ReadonlyFile => "File is readonly",
|
||||||
HostErrorType::DirNotAccessible => "Could not access directory",
|
HostErrorType::DirNotAccessible => "Could not access directory",
|
||||||
HostErrorType::FileNotAccessible => "Could not access directory",
|
HostErrorType::FileNotAccessible => "Could not access file",
|
||||||
HostErrorType::FileAlreadyExists => "File already exists",
|
HostErrorType::FileAlreadyExists => "File already exists",
|
||||||
HostErrorType::CouldNotCreateFile => "Could not create file",
|
HostErrorType::CouldNotCreateFile => "Could not create file",
|
||||||
HostErrorType::DeleteFailed => "Could not delete file",
|
HostErrorType::DeleteFailed => "Could not delete file",
|
||||||
@@ -766,6 +766,45 @@ mod tests {
|
|||||||
.is_err());
|
.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_sample_file
|
||||||
///
|
///
|
||||||
/// Create a sample file
|
/// Create a sample file
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ pub struct BookmarksClient {
|
|||||||
hosts: UserHosts,
|
hosts: UserHosts,
|
||||||
bookmarks_file: PathBuf,
|
bookmarks_file: PathBuf,
|
||||||
key: String,
|
key: String,
|
||||||
|
recents_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BookmarksClient {
|
impl BookmarksClient {
|
||||||
@@ -55,7 +56,11 @@ impl BookmarksClient {
|
|||||||
/// Instantiates a new BookmarksClient
|
/// Instantiates a new BookmarksClient
|
||||||
/// Bookmarks file path must be provided
|
/// Bookmarks file path must be provided
|
||||||
/// Key file must be provided
|
/// Key file must be provided
|
||||||
pub fn new(bookmarks_file: &Path, key_file: &Path) -> Result<BookmarksClient, SerializerError> {
|
pub fn new(
|
||||||
|
bookmarks_file: &Path,
|
||||||
|
key_file: &Path,
|
||||||
|
recents_size: usize,
|
||||||
|
) -> Result<BookmarksClient, SerializerError> {
|
||||||
// Create default hosts
|
// Create default hosts
|
||||||
let default_hosts: UserHosts = Default::default();
|
let default_hosts: UserHosts = Default::default();
|
||||||
// If key file doesn't exist, create key, otherwise read it
|
// If key file doesn't exist, create key, otherwise read it
|
||||||
@@ -73,6 +78,7 @@ impl BookmarksClient {
|
|||||||
hosts: default_hosts,
|
hosts: default_hosts,
|
||||||
bookmarks_file: PathBuf::from(bookmarks_file),
|
bookmarks_file: PathBuf::from(bookmarks_file),
|
||||||
key,
|
key,
|
||||||
|
recents_size,
|
||||||
};
|
};
|
||||||
// If bookmark file doesn't exist, initialize it
|
// If bookmark file doesn't exist, initialize it
|
||||||
if !bookmarks_file.exists() {
|
if !bookmarks_file.exists() {
|
||||||
@@ -196,8 +202,9 @@ impl BookmarksClient {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If hosts size is bigger than 16; pop last
|
// If hosts size is bigger than self.recents_size; pop last
|
||||||
if self.hosts.recents.len() >= 16 {
|
if self.hosts.recents.len() >= self.recents_size {
|
||||||
|
// Get keys
|
||||||
let mut keys: Vec<String> = Vec::with_capacity(self.hosts.recents.len());
|
let mut keys: Vec<String> = Vec::with_capacity(self.hosts.recents.len());
|
||||||
for key in self.hosts.recents.keys() {
|
for key in self.hosts.recents.keys() {
|
||||||
keys.push(key.clone());
|
keys.push(key.clone());
|
||||||
@@ -207,8 +214,8 @@ impl BookmarksClient {
|
|||||||
// Delete keys starting from the last one
|
// Delete keys starting from the last one
|
||||||
for key in keys.iter() {
|
for key in keys.iter() {
|
||||||
let _ = self.hosts.recents.remove(key);
|
let _ = self.hosts.recents.remove(key);
|
||||||
// If length is < 16; break
|
// If length is < self.recents_size; break
|
||||||
if self.hosts.recents.len() < 16 {
|
if self.hosts.recents.len() < self.recents_size {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -389,6 +396,8 @@ impl BookmarksClient {
|
|||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::thread::sleep;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_system_bookmarks_new() {
|
fn test_system_bookmarks_new() {
|
||||||
@@ -396,19 +405,28 @@ mod tests {
|
|||||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||||
// Initialize a new bookmarks client
|
// Initialize a new bookmarks client
|
||||||
let client: BookmarksClient =
|
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
|
// Verify client
|
||||||
assert_eq!(client.hosts.bookmarks.len(), 0);
|
assert_eq!(client.hosts.bookmarks.len(), 0);
|
||||||
assert_eq!(client.hosts.recents.len(), 0);
|
assert_eq!(client.hosts.recents.len(), 0);
|
||||||
assert!(client.key.len() > 0);
|
assert!(client.key.len() > 0);
|
||||||
assert_eq!(client.bookmarks_file, cfg_path);
|
assert_eq!(client.bookmarks_file, cfg_path);
|
||||||
|
assert_eq!(client.recents_size, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_system_bookmarks_new_err() {
|
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!(
|
assert!(
|
||||||
BookmarksClient::new(Path::new("/tmp/oifoif/omar"), Path::new("/tmp/efnnu/omar"))
|
BookmarksClient::new(cfg_path.as_path(), Path::new("/tmp/efnnu/omar"), 16).is_err()
|
||||||
.is_err()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,7 +436,7 @@ mod tests {
|
|||||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||||
// Initialize a new bookmarks client
|
// Initialize a new bookmarks client
|
||||||
let mut client: BookmarksClient =
|
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
|
// Add some bookmarks
|
||||||
client.add_bookmark(
|
client.add_bookmark(
|
||||||
String::from("raspberry"),
|
String::from("raspberry"),
|
||||||
@@ -439,7 +457,7 @@ mod tests {
|
|||||||
let key: String = client.key.clone();
|
let key: String = client.key.clone();
|
||||||
// Re-initialize a client
|
// Re-initialize a client
|
||||||
let client: BookmarksClient =
|
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
|
// Verify it loaded parameters correctly
|
||||||
assert_eq!(client.key, key);
|
assert_eq!(client.key, key);
|
||||||
let bookmark: (String, u16, FileTransferProtocol, String, Option<String>) =
|
let bookmark: (String, u16, FileTransferProtocol, String, Option<String>) =
|
||||||
@@ -463,7 +481,7 @@ mod tests {
|
|||||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||||
// Initialize a new bookmarks client
|
// Initialize a new bookmarks client
|
||||||
let mut client: BookmarksClient =
|
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
|
// Add bookmark
|
||||||
client.add_bookmark(
|
client.add_bookmark(
|
||||||
String::from("raspberry"),
|
String::from("raspberry"),
|
||||||
@@ -473,6 +491,16 @@ mod tests {
|
|||||||
String::from("pi"),
|
String::from("pi"),
|
||||||
Some(String::from("mypassword")),
|
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
|
// Get bookmark
|
||||||
let bookmark: (String, u16, FileTransferProtocol, String, Option<String>) =
|
let bookmark: (String, u16, FileTransferProtocol, String, Option<String>) =
|
||||||
client.get_bookmark(&String::from("raspberry")).unwrap();
|
client.get_bookmark(&String::from("raspberry")).unwrap();
|
||||||
@@ -491,13 +519,32 @@ mod tests {
|
|||||||
assert!(client.write_bookmarks().is_ok());
|
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]
|
#[test]
|
||||||
fn test_system_bookmarks_manipulate_recents() {
|
fn test_system_bookmarks_manipulate_recents() {
|
||||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||||
// Initialize a new bookmarks client
|
// Initialize a new bookmarks client
|
||||||
let mut client: BookmarksClient =
|
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
|
// Add bookmark
|
||||||
client.add_recent(
|
client.add_recent(
|
||||||
String::from("192.168.1.31"),
|
String::from("192.168.1.31"),
|
||||||
@@ -505,6 +552,8 @@ mod tests {
|
|||||||
FileTransferProtocol::Sftp,
|
FileTransferProtocol::Sftp,
|
||||||
String::from("pi"),
|
String::from("pi"),
|
||||||
);
|
);
|
||||||
|
// Iter
|
||||||
|
assert_eq!(client.iter_recents().count(), 1);
|
||||||
let key: String = String::from(client.iter_recents().next().unwrap());
|
let key: String = String::from(client.iter_recents().next().unwrap());
|
||||||
// Get bookmark
|
// Get bookmark
|
||||||
let bookmark: (String, u16, FileTransferProtocol, String) =
|
let bookmark: (String, u16, FileTransferProtocol, String) =
|
||||||
@@ -523,6 +572,76 @@ mod tests {
|
|||||||
assert!(client.write_bookmarks().is_ok());
|
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]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn test_system_bookmarks_add_bookmark_empty() {
|
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());
|
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||||
// Initialize a new bookmarks client
|
// Initialize a new bookmarks client
|
||||||
let mut client: BookmarksClient =
|
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
|
// Add bookmark
|
||||||
client.add_bookmark(
|
client.add_bookmark(
|
||||||
String::from(""),
|
String::from(""),
|
||||||
|
|||||||
@@ -61,8 +61,35 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
use std::fs::{File, OpenOptions};
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_system_environment_get_config_dir() {
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ impl AuthActivity {
|
|||||||
let mut key_file: PathBuf = path;
|
let mut key_file: PathBuf = path;
|
||||||
key_file.push(".bookmarks.key"); // key file is hidden
|
key_file.push(".bookmarks.key"); // key file is hidden
|
||||||
// Initialize client
|
// 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),
|
Ok(cli) => self.bookmarks_client = Some(cli),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.input_mode = InputMode::Popup(PopupType::Alert(
|
self.input_mode = InputMode::Popup(PopupType::Alert(
|
||||||
|
|||||||
Reference in New Issue
Block a user