mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Merge pull request #46 from veeso/github-actions-containers
GitHub actions containers
This commit is contained in:
17
.github/workflows/coverage.yml
vendored
17
.github/workflows/coverage.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: coverage
|
||||
name: Coverage
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
@@ -6,22 +6,23 @@ env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
coverage:
|
||||
name: Generate coverage
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup rust toolchain
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup containers
|
||||
run: docker-compose -f "tests/docker-compose.yml" up -d --build
|
||||
- name: Setup nightly toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
override: true
|
||||
- name: Run tests
|
||||
- name: Run tests (nightly)
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --all-features --no-fail-fast
|
||||
args: --all-features --lib --no-fail-fast
|
||||
env:
|
||||
CARGO_INCREMENTAL: "0"
|
||||
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests"
|
||||
|
||||
7
.github/workflows/linux.yml
vendored
7
.github/workflows/linux.yml
vendored
@@ -11,15 +11,18 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup containers
|
||||
run: docker-compose -f "tests/docker-compose.yml" up -d --build
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
- uses: actions-rs/cargo@v1
|
||||
- name: Run tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --all-features --no-fail-fast
|
||||
args: --all-features --lib --no-fail-fast
|
||||
- name: Format
|
||||
run: cargo fmt --all -- --check
|
||||
- name: Clippy
|
||||
|
||||
2
.github/workflows/macos.yml
vendored
2
.github/workflows/macos.yml
vendored
@@ -14,6 +14,6 @@ jobs:
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
||||
run: cargo test --verbose --features githubActions -- --test-threads 1
|
||||
run: cargo test --verbose --lib --features github-actions -- --test-threads 1
|
||||
- name: Clippy
|
||||
run: cargo clippy
|
||||
|
||||
2
.github/workflows/windows.yml
vendored
2
.github/workflows/windows.yml
vendored
@@ -14,6 +14,6 @@ jobs:
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
||||
run: cargo test --verbose --features githubActions -- --test-threads 1
|
||||
run: cargo test --verbose --lib --features github-actions -- --test-threads 1
|
||||
- name: Clippy
|
||||
run: cargo clippy
|
||||
|
||||
@@ -22,6 +22,12 @@
|
||||
|
||||
Released on FIXME: ??
|
||||
|
||||
- Enhancements:
|
||||
- **CI now uses containers to test file transfers (SSH/FTP)**
|
||||
- Improved coverage
|
||||
- Found many bugs which has now been fixed
|
||||
- Build in CI won't fail due to test servers not responding
|
||||
- We're now able to test all the functionalities of the file transfers
|
||||
- Bugfix:
|
||||
- Fixed broken input cursor when typing UTF8 characters (tui-realm 0.3.2)
|
||||
- Fixed [Issue 44](https://github.com/veeso/termscp/issues/44): Could not move files to other paths in FTP
|
||||
|
||||
@@ -59,7 +59,8 @@ wildmatch = "2.0.0"
|
||||
pretty_assertions = "0.7.2"
|
||||
|
||||
[features]
|
||||
githubActions = []
|
||||
github-actions = []
|
||||
with-containers = []
|
||||
|
||||
[target."cfg(any(target_os = \"unix\", target_os = \"macos\", target_os = \"linux\"))"]
|
||||
[target."cfg(any(target_os = \"unix\", target_os = \"macos\", target_os = \"linux\"))".dependencies]
|
||||
|
||||
@@ -3,15 +3,26 @@
|
||||
Document audience: developers
|
||||
|
||||
- [Developer Manual](#developer-manual)
|
||||
- [How to test](#how-to-test)
|
||||
- [How termscp works](#how-termscp-works)
|
||||
- [Activities](#activities)
|
||||
- [The Context](#the-context)
|
||||
- [Tests fails due to receivers](#tests-fails-due-to-receivers)
|
||||
- [Implementing File Transfers](#implementing-file-transfers)
|
||||
|
||||
Welcome to the developer manual for termscp. This chapter DOESN'T contain the documentation for termscp modules, which can instead be found on Rust Docs at <https://docs.rs/termscp>
|
||||
This chapter describes how termscp works and the guide lines to implement stuff such as file transfers and add features to the user interface.
|
||||
|
||||
## How to test
|
||||
|
||||
First an introduction to tests.
|
||||
|
||||
Usually it's enough to run `cargo test`, but please note that whenever you're working on file transfer you'll need one more step.
|
||||
In order to run tests with file transfers, you need to start the file transfer server containers, which can be started via `docker`.
|
||||
|
||||
To run all tests with file transfers just run: `./tests/test.sh`
|
||||
|
||||
---
|
||||
|
||||
## How termscp works
|
||||
|
||||
termscp is basically made up of 4 components:
|
||||
@@ -62,12 +73,6 @@ The context basically holds the following data:
|
||||
|
||||
---
|
||||
|
||||
## Tests fails due to receivers
|
||||
|
||||
Yes. This happens quite often and is related to the fact that I'm using public SSH/SFTP/FTP server to test file receivers and sometimes this server go down for even a day or more. If your tests don't pass due to this, don't worry, submit the pull request and I'll take care of testing them by myself.
|
||||
|
||||
---
|
||||
|
||||
## Implementing File Transfers
|
||||
|
||||
This chapter describes how to implement a file transfer in termscp. A file transfer is a module which implements the `FileTransfer` trait. The file transfer provides different modules to interact with a remote server, which in addition to the most obvious methods, used to download and upload files, provides also methods to list files, delete files, create directories etc.
|
||||
|
||||
@@ -183,6 +183,12 @@ mod tests {
|
||||
file_fmt: Some(String::from("{NAME}")),
|
||||
remote_file_fmt: Some(String::from("{USER}")),
|
||||
};
|
||||
assert_eq!(ui.default_protocol, String::from("SFTP"));
|
||||
assert_eq!(ui.text_editor, PathBuf::from("nano"));
|
||||
assert_eq!(ui.show_hidden_files, true);
|
||||
assert_eq!(ui.check_for_updates, Some(true));
|
||||
assert_eq!(ui.group_dirs, Some(String::from("first")));
|
||||
assert_eq!(ui.file_fmt, Some(String::from("{NAME}")));
|
||||
let cfg: UserConfig = UserConfig {
|
||||
user_interface: ui,
|
||||
remote: remote,
|
||||
|
||||
@@ -208,6 +208,25 @@ mod tests {
|
||||
assert!(serializer.deserialize(Box::new(toml_file)).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_serializer_fail_write() {
|
||||
let toml_file: tempfile::NamedTempFile = tempfile::NamedTempFile::new().ok().unwrap();
|
||||
let writer: Box<dyn Write> = Box::new(std::fs::File::open(toml_file.path()).unwrap());
|
||||
// Try to write unexisting file
|
||||
let serializer: ConfigSerializer = ConfigSerializer {};
|
||||
let cfg: UserConfig = UserConfig::default();
|
||||
assert!(serializer.serialize(writer, &cfg).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_serializer_fail_read() {
|
||||
let toml_file: tempfile::NamedTempFile = tempfile::NamedTempFile::new().ok().unwrap();
|
||||
let reader: Box<dyn Read> = Box::new(std::fs::File::open(toml_file.path()).unwrap());
|
||||
// Try to write unexisting file
|
||||
let serializer: ConfigSerializer = ConfigSerializer {};
|
||||
assert!(serializer.deserialize(reader).is_err());
|
||||
}
|
||||
|
||||
fn create_good_toml() -> tempfile::NamedTempFile {
|
||||
// Write
|
||||
let mut tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap();
|
||||
|
||||
@@ -491,7 +491,10 @@ impl FileTransfer for FtpFileTransfer {
|
||||
info!("Disconnecting from FTP server...");
|
||||
match &mut self.stream {
|
||||
Some(stream) => match stream.quit() {
|
||||
Ok(_) => Ok(()),
|
||||
Ok(_) => {
|
||||
self.stream = None;
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => Err(FileTransferError::new_ex(
|
||||
FileTransferErrorType::ConnectionError,
|
||||
err.to_string(),
|
||||
@@ -859,9 +862,14 @@ impl FileTransfer for FtpFileTransfer {
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
use crate::utils::file::open_file;
|
||||
use crate::utils::fmt::fmt_time;
|
||||
#[cfg(feature = "with-containers")]
|
||||
use crate::utils::test_helpers::write_file;
|
||||
use crate::utils::test_helpers::{create_sample_file_entry, make_fsentry};
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::io::{Read, Write};
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
@@ -875,120 +883,281 @@ mod tests {
|
||||
assert!(ftp.stream.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-containers")]
|
||||
fn test_filetransfer_ftp_server() {
|
||||
let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||
// Sample file
|
||||
let (entry, file): (FsFile, tempfile::NamedTempFile) = create_sample_file_entry();
|
||||
// Connect
|
||||
#[cfg(not(feature = "github-actions"))]
|
||||
let hostname: String = String::from("127.0.0.1");
|
||||
#[cfg(feature = "github-actions")]
|
||||
let hostname: String = String::from("127.0.0.1");
|
||||
assert!(ftp
|
||||
.connect(
|
||||
hostname,
|
||||
10021,
|
||||
Some(String::from("test")),
|
||||
Some(String::from("test")),
|
||||
)
|
||||
.is_ok());
|
||||
assert_eq!(ftp.is_connected(), true);
|
||||
// Get pwd
|
||||
assert_eq!(ftp.pwd().unwrap(), PathBuf::from("/"));
|
||||
// List dir (dir is empty)
|
||||
assert_eq!(ftp.list_dir(&Path::new("/")).unwrap().len(), 0);
|
||||
// Make directory
|
||||
assert!(ftp.mkdir(PathBuf::from("/home").as_path()).is_ok());
|
||||
// Make directory (err)
|
||||
assert!(ftp.mkdir(PathBuf::from("/root/pommlar").as_path()).is_err());
|
||||
// Change directory
|
||||
assert!(ftp.change_dir(PathBuf::from("/home").as_path()).is_ok());
|
||||
// Change directory (err)
|
||||
assert!(ftp
|
||||
.change_dir(PathBuf::from("/tmp/oooo/aaaa/eee").as_path())
|
||||
.is_err());
|
||||
// Copy (not supported)
|
||||
assert!(ftp
|
||||
.copy(&FsEntry::File(entry.clone()), PathBuf::from("/").as_path())
|
||||
.is_err());
|
||||
// Exec (not supported)
|
||||
assert!(ftp.exec("echo 1;").is_err());
|
||||
// Upload 2 files
|
||||
let mut writable = ftp
|
||||
.send_file(&entry, PathBuf::from("omar.txt").as_path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
write_file(&file, &mut writable);
|
||||
assert!(ftp.on_sent(writable).is_ok());
|
||||
let mut writable = ftp
|
||||
.send_file(&entry, PathBuf::from("README.md").as_path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
write_file(&file, &mut writable);
|
||||
assert!(ftp.on_sent(writable).is_ok());
|
||||
// Upload file (err)
|
||||
assert!(ftp
|
||||
.send_file(&entry, PathBuf::from("/ommlar/omarone").as_path())
|
||||
.is_err());
|
||||
// List dir
|
||||
let list: Vec<FsEntry> = ftp.list_dir(PathBuf::from("/home").as_path()).ok().unwrap();
|
||||
assert_eq!(list.len(), 2);
|
||||
// Find
|
||||
assert!(ftp.change_dir(PathBuf::from("/").as_path()).is_ok());
|
||||
assert_eq!(ftp.find("*.txt").ok().unwrap().len(), 1);
|
||||
assert_eq!(ftp.find("*.md").ok().unwrap().len(), 1);
|
||||
assert_eq!(ftp.find("*.jpeg").ok().unwrap().len(), 0);
|
||||
assert!(ftp.change_dir(PathBuf::from("/home").as_path()).is_ok());
|
||||
// Rename
|
||||
assert!(ftp.mkdir(PathBuf::from("/uploads").as_path()).is_ok());
|
||||
assert!(ftp
|
||||
.rename(
|
||||
list.get(0).unwrap(),
|
||||
PathBuf::from("/uploads/README.txt").as_path()
|
||||
)
|
||||
.is_ok());
|
||||
// Rename (err)
|
||||
assert!(ftp
|
||||
.rename(list.get(0).unwrap(), PathBuf::from("OMARONE").as_path())
|
||||
.is_err());
|
||||
let dummy: FsEntry = FsEntry::File(FsFile {
|
||||
name: String::from("cucumber.txt"),
|
||||
abs_path: PathBuf::from("/cucumber.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
|
||||
});
|
||||
assert!(ftp
|
||||
.rename(&dummy, PathBuf::from("/a/b/c").as_path())
|
||||
.is_err());
|
||||
// Remove
|
||||
assert!(ftp.remove(list.get(1).unwrap()).is_ok());
|
||||
assert!(ftp.remove(list.get(1).unwrap()).is_err());
|
||||
// Receive file
|
||||
let mut writable = ftp
|
||||
.send_file(&entry, PathBuf::from("/uploads/README.txt").as_path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
write_file(&file, &mut writable);
|
||||
assert!(ftp.on_sent(writable).is_ok());
|
||||
let file: FsFile = ftp
|
||||
.list_dir(PathBuf::from("/uploads").as_path())
|
||||
.ok()
|
||||
.unwrap()
|
||||
.get(0)
|
||||
.unwrap()
|
||||
.clone()
|
||||
.unwrap_file();
|
||||
let mut readable = ftp.recv_file(&file).ok().unwrap();
|
||||
let mut data: Vec<u8> = vec![0; 1024];
|
||||
assert!(readable.read(&mut data).is_ok());
|
||||
assert!(ftp.on_recv(readable).is_ok());
|
||||
// Receive file (err)
|
||||
assert!(ftp.recv_file(&entry).is_err());
|
||||
// Cleanup
|
||||
assert!(ftp.change_dir(PathBuf::from("/").as_path()).is_ok());
|
||||
assert!(ftp
|
||||
.remove(&make_fsentry(PathBuf::from("/home"), true))
|
||||
.is_ok());
|
||||
assert!(ftp
|
||||
.remove(&make_fsentry(PathBuf::from("/uploads"), true))
|
||||
.is_ok());
|
||||
// Disconnect
|
||||
assert!(ftp.disconnect().is_ok());
|
||||
assert_eq!(ftp.is_connected(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-containers")]
|
||||
fn test_filetransfer_ftp_server_bad_auth() {
|
||||
let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||
// Connect
|
||||
assert!(ftp
|
||||
.connect(
|
||||
String::from("127.0.0.1"),
|
||||
10021,
|
||||
Some(String::from("omar")),
|
||||
Some(String::from("ommlar")),
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-containers")]
|
||||
fn test_filetransfer_ftp_no_credentials() {
|
||||
let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||
assert!(ftp
|
||||
.connect(String::from("127.0.0.1"), 10021, None, None)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_ftp_server_bad_server() {
|
||||
let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||
// Connect
|
||||
assert!(ftp
|
||||
.connect(
|
||||
String::from("mybadserver.veryverybad.awful"),
|
||||
21,
|
||||
Some(String::from("omar")),
|
||||
Some(String::from("ommlar")),
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_ftp_parse_list_line_unix() {
|
||||
let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||
// Simple file
|
||||
let fs_entry: FsEntry = ftp
|
||||
let file: FsFile = ftp
|
||||
.parse_list_line(
|
||||
PathBuf::from("/tmp").as_path(),
|
||||
"-rw-rw-r-- 1 root dialout 8192 Nov 5 2018 omar.txt",
|
||||
)
|
||||
.ok()
|
||||
.unwrap();
|
||||
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!(file.symlink.is_none());
|
||||
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
|
||||
.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");
|
||||
}
|
||||
.unwrap()
|
||||
.unwrap_file();
|
||||
assert_eq!(file.abs_path, PathBuf::from("/tmp/omar.txt"));
|
||||
assert_eq!(file.name, String::from("omar.txt"));
|
||||
assert_eq!(file.size, 8192);
|
||||
assert!(file.symlink.is_none());
|
||||
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
|
||||
.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)
|
||||
);
|
||||
// Simple file with number as gid, uid
|
||||
let fs_entry: FsEntry = ftp
|
||||
let file: FsFile = ftp
|
||||
.parse_list_line(
|
||||
PathBuf::from("/tmp").as_path(),
|
||||
"-rwxr-xr-x 1 0 9 4096 Nov 5 16:32 omar.txt",
|
||||
)
|
||||
.ok()
|
||||
.unwrap();
|
||||
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, 4096);
|
||||
assert!(file.symlink.is_none());
|
||||
assert_eq!(file.user, Some(0));
|
||||
assert_eq!(file.group, Some(9));
|
||||
assert_eq!(file.unix_pex.unwrap(), (7, 5, 5));
|
||||
assert_eq!(
|
||||
fmt_time(file.last_access_time, "%m %d %M").as_str(),
|
||||
"11 05 32"
|
||||
);
|
||||
assert_eq!(
|
||||
fmt_time(file.last_change_time, "%m %d %M").as_str(),
|
||||
"11 05 32"
|
||||
);
|
||||
assert_eq!(
|
||||
fmt_time(file.creation_time, "%m %d %M").as_str(),
|
||||
"11 05 32"
|
||||
);
|
||||
} else {
|
||||
panic!("Expected file, got directory");
|
||||
}
|
||||
.unwrap()
|
||||
.unwrap_file();
|
||||
assert_eq!(file.abs_path, PathBuf::from("/tmp/omar.txt"));
|
||||
assert_eq!(file.name, String::from("omar.txt"));
|
||||
assert_eq!(file.size, 4096);
|
||||
assert!(file.symlink.is_none());
|
||||
assert_eq!(file.user, Some(0));
|
||||
assert_eq!(file.group, Some(9));
|
||||
assert_eq!(file.unix_pex.unwrap(), (7, 5, 5));
|
||||
assert_eq!(
|
||||
fmt_time(file.last_access_time, "%m %d %M").as_str(),
|
||||
"11 05 32"
|
||||
);
|
||||
assert_eq!(
|
||||
fmt_time(file.last_change_time, "%m %d %M").as_str(),
|
||||
"11 05 32"
|
||||
);
|
||||
assert_eq!(
|
||||
fmt_time(file.creation_time, "%m %d %M").as_str(),
|
||||
"11 05 32"
|
||||
);
|
||||
// Directory
|
||||
let fs_entry: FsEntry = ftp
|
||||
let dir: FsDirectory = ftp
|
||||
.parse_list_line(
|
||||
PathBuf::from("/tmp").as_path(),
|
||||
"drwxrwxr-x 1 0 9 4096 Nov 5 2018 docs",
|
||||
)
|
||||
.ok()
|
||||
.unwrap();
|
||||
if let FsEntry::Directory(dir) = fs_entry {
|
||||
assert_eq!(dir.abs_path, PathBuf::from("/tmp/docs"));
|
||||
assert_eq!(dir.name, String::from("docs"));
|
||||
assert!(dir.symlink.is_none());
|
||||
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
|
||||
.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");
|
||||
}
|
||||
.unwrap()
|
||||
.unwrap_dir();
|
||||
assert_eq!(dir.abs_path, PathBuf::from("/tmp/docs"));
|
||||
assert_eq!(dir.name, String::from("docs"));
|
||||
assert!(dir.symlink.is_none());
|
||||
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
|
||||
.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);
|
||||
// Error
|
||||
assert!(ftp
|
||||
.parse_list_line(
|
||||
@@ -1002,186 +1171,85 @@ mod tests {
|
||||
fn test_filetransfer_ftp_parse_list_line_dos() {
|
||||
let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||
// Simple file
|
||||
let fs_entry: FsEntry = ftp
|
||||
let file: FsFile = ftp
|
||||
.parse_list_line(
|
||||
PathBuf::from("/tmp").as_path(),
|
||||
"04-08-14 03:09PM 8192 omar.txt",
|
||||
)
|
||||
.ok()
|
||||
.unwrap();
|
||||
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!(file.symlink.is_none());
|
||||
assert_eq!(file.user, None);
|
||||
assert_eq!(file.group, None);
|
||||
assert_eq!(file.unix_pex, None);
|
||||
assert_eq!(
|
||||
file.last_access_time
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.ok()
|
||||
.unwrap(),
|
||||
Duration::from_secs(1407164940)
|
||||
);
|
||||
assert_eq!(
|
||||
file.last_change_time
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.ok()
|
||||
.unwrap(),
|
||||
Duration::from_secs(1407164940)
|
||||
);
|
||||
assert_eq!(
|
||||
file.creation_time
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.ok()
|
||||
.unwrap(),
|
||||
Duration::from_secs(1407164940)
|
||||
);
|
||||
} else {
|
||||
panic!("Expected file, got directory");
|
||||
}
|
||||
.unwrap()
|
||||
.unwrap_file();
|
||||
assert_eq!(file.abs_path, PathBuf::from("/tmp/omar.txt"));
|
||||
assert_eq!(file.name, String::from("omar.txt"));
|
||||
assert_eq!(file.size, 8192);
|
||||
assert!(file.symlink.is_none());
|
||||
assert_eq!(file.user, None);
|
||||
assert_eq!(file.group, None);
|
||||
assert_eq!(file.unix_pex, None);
|
||||
assert_eq!(
|
||||
file.last_access_time
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.ok()
|
||||
.unwrap(),
|
||||
Duration::from_secs(1407164940)
|
||||
);
|
||||
assert_eq!(
|
||||
file.last_change_time
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.ok()
|
||||
.unwrap(),
|
||||
Duration::from_secs(1407164940)
|
||||
);
|
||||
assert_eq!(
|
||||
file.creation_time
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.ok()
|
||||
.unwrap(),
|
||||
Duration::from_secs(1407164940)
|
||||
);
|
||||
// Directory
|
||||
let fs_entry: FsEntry = ftp
|
||||
let dir: FsDirectory = ftp
|
||||
.parse_list_line(
|
||||
PathBuf::from("/tmp").as_path(),
|
||||
"04-08-14 03:09PM <DIR> docs",
|
||||
)
|
||||
.ok()
|
||||
.unwrap();
|
||||
if let FsEntry::Directory(dir) = fs_entry {
|
||||
assert_eq!(dir.abs_path, PathBuf::from("/tmp/docs"));
|
||||
assert_eq!(dir.name, String::from("docs"));
|
||||
assert!(dir.symlink.is_none());
|
||||
assert_eq!(dir.user, None);
|
||||
assert_eq!(dir.group, None);
|
||||
assert_eq!(dir.unix_pex, None);
|
||||
assert_eq!(
|
||||
dir.last_access_time
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.ok()
|
||||
.unwrap(),
|
||||
Duration::from_secs(1407164940)
|
||||
);
|
||||
assert_eq!(
|
||||
dir.last_change_time
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.ok()
|
||||
.unwrap(),
|
||||
Duration::from_secs(1407164940)
|
||||
);
|
||||
assert_eq!(
|
||||
dir.creation_time
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.ok()
|
||||
.unwrap(),
|
||||
Duration::from_secs(1407164940)
|
||||
);
|
||||
assert_eq!(dir.readonly, false);
|
||||
} else {
|
||||
panic!("Expected directory, got directory");
|
||||
}
|
||||
.unwrap()
|
||||
.unwrap_dir();
|
||||
assert_eq!(dir.abs_path, PathBuf::from("/tmp/docs"));
|
||||
assert_eq!(dir.name, String::from("docs"));
|
||||
assert!(dir.symlink.is_none());
|
||||
assert_eq!(dir.user, None);
|
||||
assert_eq!(dir.group, None);
|
||||
assert_eq!(dir.unix_pex, None);
|
||||
assert_eq!(
|
||||
dir.last_access_time
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.ok()
|
||||
.unwrap(),
|
||||
Duration::from_secs(1407164940)
|
||||
);
|
||||
assert_eq!(
|
||||
dir.last_change_time
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.ok()
|
||||
.unwrap(),
|
||||
Duration::from_secs(1407164940)
|
||||
);
|
||||
assert_eq!(
|
||||
dir.creation_time
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.ok()
|
||||
.unwrap(),
|
||||
Duration::from_secs(1407164940)
|
||||
);
|
||||
assert_eq!(dir.readonly, false);
|
||||
// Error
|
||||
assert!(ftp
|
||||
.parse_list_line(PathBuf::from("/").as_path(), "04-08-14 omar.txt")
|
||||
.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());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_ftp_copy() {
|
||||
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("/"));
|
||||
// Copy
|
||||
let file: FsFile = FsFile {
|
||||
name: String::from("readme.txt"),
|
||||
abs_path: PathBuf::from("/readme.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
|
||||
};
|
||||
assert!(ftp
|
||||
.copy(&FsEntry::File(file), &Path::new("/tmp/dest.txt"))
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_ftp_list_dir_dos_syntax() {
|
||||
let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||
@@ -1205,94 +1273,16 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
fn test_filetransfer_ftp_list_dir_unix_syntax() {
|
||||
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
|
||||
let files: Vec<FsEntry> = ftp.list_dir(PathBuf::from("/").as_path()).ok().unwrap();
|
||||
// There should be at least 1 file
|
||||
assert!(files.len() > 0);
|
||||
// Disconnect
|
||||
assert!(ftp.disconnect().is_ok());
|
||||
}
|
||||
|
||||
/* NOTE: they don't work
|
||||
#[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());
|
||||
}*/
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_ftp_exec() {
|
||||
let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||
// Connect
|
||||
assert!(ftp
|
||||
.connect(String::from("speedtest.tele2.net"), 21, None, None)
|
||||
.is_ok());
|
||||
// Pwd
|
||||
assert!(ftp.exec("echo 1;").is_err());
|
||||
// Disconnect
|
||||
assert!(ftp.disconnect().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_ftp_find() {
|
||||
let mut client: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||
// Connect
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
21,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Pwd
|
||||
assert_eq!(client.pwd().ok().unwrap(), PathBuf::from("/"));
|
||||
// Search for file (let's search for pop3-*.png); there should be 2
|
||||
let search_res: Vec<FsEntry> = client.find("pop3-*.png").ok().unwrap();
|
||||
assert_eq!(search_res.len(), 2);
|
||||
// verify names
|
||||
assert_eq!(search_res[0].get_name(), "pop3-browser.png");
|
||||
assert_eq!(search_res[1].get_name(), "pop3-console-client.png");
|
||||
// Search directory
|
||||
let search_res: Vec<FsEntry> = client.find("pub").ok().unwrap();
|
||||
assert_eq!(search_res.len(), 1);
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
// Verify err
|
||||
assert!(client.find("pippo").is_err());
|
||||
fn test_filetransfer_ftp_get_name_and_link() {
|
||||
let client: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||
assert_eq!(
|
||||
client.get_name_and_link("Cargo.toml"),
|
||||
(String::from("Cargo.toml"), None)
|
||||
);
|
||||
assert_eq!(
|
||||
client.get_name_and_link("Cargo -> Cargo.toml"),
|
||||
(String::from("Cargo"), Some(PathBuf::from("Cargo.toml")))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1316,9 +1306,25 @@ mod tests {
|
||||
assert!(ftp.disconnect().is_err());
|
||||
assert!(ftp.list_dir(Path::new("/tmp")).is_err());
|
||||
assert!(ftp.mkdir(Path::new("/tmp")).is_err());
|
||||
assert!(ftp
|
||||
.remove(&make_fsentry(PathBuf::from("/nowhere"), false))
|
||||
.is_err());
|
||||
assert!(ftp
|
||||
.rename(
|
||||
&make_fsentry(PathBuf::from("/nowhere"), false),
|
||||
PathBuf::from("/culonia").as_path()
|
||||
)
|
||||
.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());
|
||||
let (_, temp): (FsFile, tempfile::NamedTempFile) = create_sample_file_entry();
|
||||
let readable: Box<dyn Read> = Box::new(std::fs::File::open(temp.path()).unwrap());
|
||||
assert!(ftp.on_recv(readable).is_err());
|
||||
let (_, temp): (FsFile, tempfile::NamedTempFile) = create_sample_file_entry();
|
||||
let writable: Box<dyn Write> =
|
||||
Box::new(open_file(temp.path(), true, true, true).ok().unwrap());
|
||||
assert!(ftp.on_sent(writable).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,10 +284,7 @@ pub trait FileTransfer {
|
||||
if filter.matches(dir.name.as_str()) {
|
||||
drained.push(FsEntry::Directory(dir.clone()));
|
||||
}
|
||||
match self.iter_search(dir.abs_path.as_path(), filter) {
|
||||
Ok(mut filtered) => drained.append(&mut filtered),
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
drained.append(&mut self.iter_search(dir.abs_path.as_path(), filter)?);
|
||||
}
|
||||
FsEntry::File(file) => {
|
||||
if filter.matches(file.name.as_str()) {
|
||||
|
||||
@@ -445,10 +445,9 @@ impl FileTransfer for ScpFileTransfer {
|
||||
self.session = Some(session);
|
||||
// Get working directory
|
||||
debug!("Getting working directory...");
|
||||
match self.perform_shell_cmd("pwd") {
|
||||
Ok(output) => self.wrkdir = PathBuf::from(output.as_str().trim()),
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
self.wrkdir = self
|
||||
.perform_shell_cmd("pwd")
|
||||
.map(|x| PathBuf::from(x.as_str().trim()))?;
|
||||
info!(
|
||||
"Connection established; working directory: {}",
|
||||
self.wrkdir.display()
|
||||
@@ -486,7 +485,7 @@ impl FileTransfer for ScpFileTransfer {
|
||||
///
|
||||
/// Indicates whether the client is connected to remote
|
||||
fn is_connected(&self) -> bool {
|
||||
self.session.as_ref().is_some()
|
||||
self.session.is_some()
|
||||
}
|
||||
|
||||
/// ### pwd
|
||||
@@ -853,7 +852,15 @@ impl FileTransfer for ScpFileTransfer {
|
||||
) -> Result<Box<dyn Write>, FileTransferError> {
|
||||
match self.session.as_ref() {
|
||||
Some(session) => {
|
||||
let file_name: PathBuf = Self::resolve(file_name);
|
||||
let file_name: PathBuf = match file_name.is_absolute() {
|
||||
true => PathBuf::from(file_name),
|
||||
false => {
|
||||
let mut p: PathBuf = self.wrkdir.clone();
|
||||
p.push(file_name);
|
||||
Self::resolve(p.as_path())
|
||||
}
|
||||
};
|
||||
let file_name: PathBuf = Self::resolve(file_name.as_path());
|
||||
info!(
|
||||
"Sending file {} to {}",
|
||||
local.abs_path.display(),
|
||||
@@ -963,8 +970,12 @@ impl FileTransfer for ScpFileTransfer {
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
use crate::utils::test_helpers::make_fsentry;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[cfg(feature = "with-containers")]
|
||||
use crate::utils::test_helpers::{create_sample_file_entry, write_file, write_ssh_key};
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_scp_new() {
|
||||
let client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
@@ -973,31 +984,210 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_scp_connect() {
|
||||
#[cfg(feature = "with-containers")]
|
||||
fn test_filetransfer_scp_server() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert_eq!(client.is_connected(), false);
|
||||
// Sample file
|
||||
let (entry, file): (FsFile, tempfile::NamedTempFile) = create_sample_file_entry();
|
||||
// Connect
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
String::from("127.0.0.1"),
|
||||
10222,
|
||||
Some(String::from("sftp")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and scp
|
||||
// Check session and sftp
|
||||
assert!(client.session.is_some());
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/config"));
|
||||
assert_eq!(client.is_connected(), true);
|
||||
// Pwd
|
||||
assert_eq!(client.wrkdir.clone(), client.pwd().ok().unwrap());
|
||||
// Stat
|
||||
let stat: FsFile = client
|
||||
.stat(PathBuf::from("sshd.pid").as_path())
|
||||
.ok()
|
||||
.unwrap()
|
||||
.unwrap_file();
|
||||
assert_eq!(stat.abs_path, PathBuf::from("/config/sshd.pid"));
|
||||
let stat: FsDirectory = client
|
||||
.stat(PathBuf::from("/config/").as_path())
|
||||
.ok()
|
||||
.unwrap()
|
||||
.unwrap_dir();
|
||||
assert_eq!(stat.abs_path, PathBuf::from("/config/"));
|
||||
// Stat (err)
|
||||
assert!(client
|
||||
.stat(PathBuf::from("/config/5t0ca220.log").as_path())
|
||||
.is_err());
|
||||
// List dir (dir has 4 (one is hidden :D) entries)
|
||||
assert_eq!(client.list_dir(&Path::new("/config")).unwrap().len(), 4);
|
||||
// Make directory
|
||||
assert!(client.mkdir(PathBuf::from("/tmp/omar").as_path()).is_ok());
|
||||
// Make directory (err)
|
||||
assert!(client
|
||||
.mkdir(PathBuf::from("/root/aaaaa/pommlar").as_path())
|
||||
.is_err());
|
||||
// Change directory
|
||||
assert!(client
|
||||
.change_dir(PathBuf::from("/tmp/omar").as_path())
|
||||
.is_ok());
|
||||
// Change directory (err)
|
||||
assert!(client
|
||||
.change_dir(PathBuf::from("/tmp/oooo/aaaa/eee").as_path())
|
||||
.is_err());
|
||||
// Copy file
|
||||
assert!(client
|
||||
.copy(
|
||||
&make_fsentry(PathBuf::from("/config/sshd.pid"), false),
|
||||
PathBuf::from("/tmp/sshd.pid").as_path()
|
||||
)
|
||||
.is_ok());
|
||||
// Copy dir
|
||||
assert!(client
|
||||
.copy(
|
||||
&make_fsentry(PathBuf::from("/tmp/omar"), true),
|
||||
PathBuf::from("/tmp/ommlar").as_path()
|
||||
)
|
||||
.is_ok());
|
||||
// Copy (err)
|
||||
assert!(client
|
||||
.copy(
|
||||
&make_fsentry(PathBuf::from("/tmp/zattera"), false),
|
||||
PathBuf::from("/").as_path()
|
||||
)
|
||||
.is_err());
|
||||
// Exec
|
||||
assert_eq!(client.exec("echo 5").ok().unwrap().as_str(), "5\n");
|
||||
// Change dir to ommlar
|
||||
assert!(client
|
||||
.change_dir(PathBuf::from("/tmp/ommlar/").as_path())
|
||||
.is_ok());
|
||||
// Upload 2 files
|
||||
let mut writable = client
|
||||
.send_file(&entry, PathBuf::from("omar.txt").as_path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
write_file(&file, &mut writable);
|
||||
assert!(client.on_sent(writable).is_ok());
|
||||
let mut writable = client
|
||||
.send_file(&entry, PathBuf::from("README.md").as_path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
write_file(&file, &mut writable);
|
||||
assert!(client.on_sent(writable).is_ok());
|
||||
// Upload file (err)
|
||||
assert!(client
|
||||
.send_file(&entry, PathBuf::from("/ommlar/omarone").as_path())
|
||||
.is_err());
|
||||
// List dir
|
||||
let list: Vec<FsEntry> = client
|
||||
.list_dir(PathBuf::from("/tmp/ommlar").as_path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
assert_eq!(list.len(), 2);
|
||||
// Find
|
||||
assert_eq!(client.find("*.txt").ok().unwrap().len(), 1);
|
||||
assert_eq!(client.find("*.md").ok().unwrap().len(), 1);
|
||||
assert_eq!(client.find("*.jpeg").ok().unwrap().len(), 0);
|
||||
// Rename
|
||||
assert!(client
|
||||
.mkdir(PathBuf::from("/tmp/uploads").as_path())
|
||||
.is_ok());
|
||||
assert!(client
|
||||
.rename(
|
||||
list.get(0).unwrap(),
|
||||
PathBuf::from("/tmp/uploads/README.txt").as_path()
|
||||
)
|
||||
.is_ok());
|
||||
// Rename (err)
|
||||
assert!(client
|
||||
.rename(list.get(0).unwrap(), PathBuf::from("OMARONE").as_path())
|
||||
.is_err());
|
||||
let dummy: FsEntry = FsEntry::File(FsFile {
|
||||
name: String::from("cucumber.txt"),
|
||||
abs_path: PathBuf::from("/cucumber.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
|
||||
});
|
||||
assert!(client
|
||||
.rename(&dummy, PathBuf::from("/a/b/c").as_path())
|
||||
.is_err());
|
||||
// Remove
|
||||
assert!(client.remove(list.get(1).unwrap()).is_ok());
|
||||
// Receive file
|
||||
let mut writable = client
|
||||
.send_file(&entry, PathBuf::from("/tmp/uploads/README.txt").as_path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
write_file(&file, &mut writable);
|
||||
assert!(client.on_sent(writable).is_ok());
|
||||
let file: FsFile = client
|
||||
.list_dir(PathBuf::from("/tmp/uploads").as_path())
|
||||
.ok()
|
||||
.unwrap()
|
||||
.get(0)
|
||||
.unwrap()
|
||||
.clone()
|
||||
.unwrap_file();
|
||||
let mut readable = client.recv_file(&file).ok().unwrap();
|
||||
let mut data: Vec<u8> = vec![0; 1024];
|
||||
assert!(readable.read(&mut data).is_ok());
|
||||
assert!(client.on_recv(readable).is_ok());
|
||||
// Receive file (err)
|
||||
assert!(client.recv_file(&entry).is_err());
|
||||
// Cleanup
|
||||
assert!(client.change_dir(PathBuf::from("/").as_path()).is_ok());
|
||||
assert!(client
|
||||
.remove(&make_fsentry(PathBuf::from("/tmp/ommlar"), true))
|
||||
.is_ok());
|
||||
assert!(client
|
||||
.remove(&make_fsentry(PathBuf::from("/tmp/omar"), true))
|
||||
.is_ok());
|
||||
assert!(client
|
||||
.remove(&make_fsentry(PathBuf::from("/tmp/uploads"), true))
|
||||
.is_ok());
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
assert_eq!(client.is_connected(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-containers")]
|
||||
fn test_filetransfer_scp_ssh_storage() {
|
||||
let mut storage: SshKeyStorage = SshKeyStorage::empty();
|
||||
let key_file: tempfile::NamedTempFile = write_ssh_key();
|
||||
storage.add_key("127.0.0.1", "sftp", key_file.path().to_path_buf());
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(storage);
|
||||
// Connect
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("127.0.0.1"),
|
||||
10222,
|
||||
Some(String::from("sftp")),
|
||||
None,
|
||||
)
|
||||
.is_ok());
|
||||
assert_eq!(client.is_connected(), true);
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_scp_bad_auth() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
String::from("127.0.0.1"),
|
||||
10222,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("badpassword"))
|
||||
)
|
||||
@@ -1005,10 +1195,11 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-containers")]
|
||||
fn test_filetransfer_scp_no_credentials() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(String::from("test.rebex.net"), 22, None, None)
|
||||
.connect(String::from("127.0.0.1"), 10222, None, None)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
@@ -1024,245 +1215,92 @@ mod tests {
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
#[test]
|
||||
fn test_filetransfer_scp_pwd() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and scp
|
||||
assert!(client.session.is_some());
|
||||
// Pwd
|
||||
assert_eq!(client.pwd().ok().unwrap(), PathBuf::from("/"));
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
fn test_filetransfer_scp_cwd() {
|
||||
fn test_filetransfer_scp_parse_ls() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
// File
|
||||
let entry: FsFile = client
|
||||
.parse_ls_output(
|
||||
PathBuf::from("/tmp").as_path(),
|
||||
"-rw-r--r-- 1 root root 2056 giu 13 21:11 Cargo.toml",
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and scp
|
||||
assert!(client.session.is_some());
|
||||
// Cwd (relative)
|
||||
assert!(client.change_dir(PathBuf::from("pub/").as_path()).is_ok());
|
||||
// Cwd (absolute)
|
||||
assert!(client.change_dir(PathBuf::from("/pub").as_path()).is_ok());
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_scp_cwd_error() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Cwd (abs)
|
||||
assert!(client
|
||||
.change_dir(PathBuf::from("/omar/gabber").as_path())
|
||||
.is_err());
|
||||
// Cwd (rel)
|
||||
assert!(client
|
||||
.change_dir(PathBuf::from("gomar/pett").as_path())
|
||||
.is_err());
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_scp_ls() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and scp
|
||||
assert!(client.session.is_some());
|
||||
// List dir
|
||||
let pwd: PathBuf = client.pwd().ok().unwrap();
|
||||
let files: Vec<FsEntry> = client.list_dir(pwd.as_path()).ok().unwrap();
|
||||
assert_eq!(files.len(), 3); // There are 3 files
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_scp_stat() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and scp
|
||||
assert!(client.session.is_some());
|
||||
let file: FsEntry = client
|
||||
.stat(PathBuf::from("readme.txt").as_path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
if let FsEntry::File(file) = file {
|
||||
assert_eq!(file.abs_path, PathBuf::from("/readme.txt"));
|
||||
} else {
|
||||
panic!("Expected readme.txt to be a file");
|
||||
}
|
||||
.unwrap()
|
||||
.unwrap_file();
|
||||
assert_eq!(entry.name.as_str(), "Cargo.toml");
|
||||
assert_eq!(entry.abs_path, PathBuf::from("/tmp/Cargo.toml"));
|
||||
assert_eq!(entry.unix_pex.unwrap(), (6, 4, 4));
|
||||
assert_eq!(entry.size, 2056);
|
||||
assert_eq!(entry.readonly, false);
|
||||
assert_eq!(entry.ftype.unwrap().as_str(), "toml");
|
||||
assert!(entry.symlink.is_none());
|
||||
// File (year)
|
||||
let entry: FsFile = client
|
||||
.parse_ls_output(
|
||||
PathBuf::from("/tmp").as_path(),
|
||||
"-rw-rw-rw- 1 root root 3368 nov 7 2020 CODE_OF_CONDUCT.md",
|
||||
)
|
||||
.ok()
|
||||
.unwrap()
|
||||
.unwrap_file();
|
||||
assert_eq!(entry.name.as_str(), "CODE_OF_CONDUCT.md");
|
||||
assert_eq!(entry.abs_path, PathBuf::from("/tmp/CODE_OF_CONDUCT.md"));
|
||||
assert_eq!(entry.unix_pex.unwrap(), (6, 6, 6));
|
||||
assert_eq!(entry.size, 3368);
|
||||
assert_eq!(entry.readonly, false);
|
||||
assert_eq!(entry.ftype.unwrap().as_str(), "md");
|
||||
assert!(entry.symlink.is_none());
|
||||
// Directory
|
||||
let entry: FsDirectory = client
|
||||
.parse_ls_output(
|
||||
PathBuf::from("/tmp").as_path(),
|
||||
"drwxr-xr-x 1 root root 512 giu 13 21:11 docs",
|
||||
)
|
||||
.ok()
|
||||
.unwrap()
|
||||
.unwrap_dir();
|
||||
assert_eq!(entry.name.as_str(), "docs");
|
||||
assert_eq!(entry.abs_path, PathBuf::from("/tmp/docs"));
|
||||
assert_eq!(entry.unix_pex.unwrap(), (7, 5, 5));
|
||||
assert_eq!(entry.readonly, false);
|
||||
assert!(entry.symlink.is_none());
|
||||
// Short metadata
|
||||
assert!(client
|
||||
.parse_ls_output(
|
||||
PathBuf::from("/tmp").as_path(),
|
||||
"drwxr-xr-x 1 root root 512 giu 13 21:11",
|
||||
)
|
||||
.is_err());
|
||||
// Special file
|
||||
assert!(client
|
||||
.parse_ls_output(
|
||||
PathBuf::from("/tmp").as_path(),
|
||||
"crwxr-xr-x 1 root root 512 giu 13 21:11 ttyS1",
|
||||
)
|
||||
.is_err());
|
||||
// Bad pex
|
||||
assert!(client
|
||||
.parse_ls_output(
|
||||
PathBuf::from("/tmp").as_path(),
|
||||
"-rwxr-xr 1 root root 512 giu 13 21:11 ttyS1",
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_scp_exec() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and scp
|
||||
assert!(client.session.is_some());
|
||||
// Exec
|
||||
assert_eq!(client.exec("echo 5").ok().unwrap().as_str(), "5\n");
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
fn test_filetransfer_scp_get_name_and_link() {
|
||||
let client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert_eq!(
|
||||
client.get_name_and_link("Cargo.toml"),
|
||||
(String::from("Cargo.toml"), None)
|
||||
);
|
||||
assert_eq!(
|
||||
client.get_name_and_link("Cargo -> Cargo.toml"),
|
||||
(String::from("Cargo"), Some(PathBuf::from("Cargo.toml")))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
//#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
fn test_filetransfer_scp_find() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and scp
|
||||
assert!(client.session.is_some());
|
||||
// Search for file (let's search for pop3-*.png); there should be 2
|
||||
let search_res: Vec<FsEntry> = client.find("pop3-*.png").ok().unwrap();
|
||||
assert_eq!(search_res.len(), 2);
|
||||
// verify names
|
||||
assert_eq!(search_res[0].get_name(), "pop3-browser.png");
|
||||
assert_eq!(search_res[1].get_name(), "pop3-console-client.png");
|
||||
// Search directory
|
||||
let search_res: Vec<FsEntry> = client.find("pub").ok().unwrap();
|
||||
assert_eq!(search_res.len(), 1);
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
// Verify err
|
||||
assert!(client.find("pippo").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_scp_recv() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and scp
|
||||
assert!(client.session.is_some());
|
||||
let file: FsFile = FsFile {
|
||||
name: String::from("readme.txt"),
|
||||
abs_path: PathBuf::from("/readme.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
|
||||
};
|
||||
// Receive file
|
||||
assert!(client.recv_file(&file).is_ok());
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
#[test]
|
||||
fn test_filetransfer_scp_recv_failed_nosuchfile() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and scp
|
||||
assert!(client.session.is_some());
|
||||
// Receive file
|
||||
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
|
||||
};
|
||||
assert!(client.recv_file(&file).is_err());
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
// NOTE: other functions doesn't work with this test scp server
|
||||
|
||||
/* NOTE: the server doesn't allow you to create directories
|
||||
#[test]
|
||||
fn test_filetransfer_scp_mkdir() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client.connect(String::from("test.rebex.net"), 22, Some(String::from("demo")), Some(String::from("password"))).is_ok());
|
||||
let dir: String = String::from("foo");
|
||||
// Mkdir
|
||||
assert!(client.mkdir(dir).is_ok());
|
||||
// cwd
|
||||
assert!(client.change_dir(PathBuf::from("foo/").as_path()).is_ok());
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/foo"));
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
*/
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_scp_uninitialized() {
|
||||
let file: FsFile = FsFile {
|
||||
@@ -1282,9 +1320,19 @@ mod tests {
|
||||
let mut scp: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(scp.change_dir(Path::new("/tmp")).is_err());
|
||||
assert!(scp.disconnect().is_err());
|
||||
assert!(scp.exec("echo 5").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
|
||||
.remove(&make_fsentry(PathBuf::from("/nowhere"), false))
|
||||
.is_err());
|
||||
assert!(scp
|
||||
.rename(
|
||||
&make_fsentry(PathBuf::from("/nowhere"), false),
|
||||
PathBuf::from("/culonia").as_path()
|
||||
)
|
||||
.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());
|
||||
|
||||
@@ -466,10 +466,7 @@ impl FileTransfer for SftpFileTransfer {
|
||||
match self.sftp.as_ref() {
|
||||
Some(_) => {
|
||||
// Change working directory
|
||||
self.wrkdir = match self.get_remote_path(dir) {
|
||||
Ok(p) => p,
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
self.wrkdir = self.get_remote_path(dir)?;
|
||||
info!("Changed working directory to {}", self.wrkdir.display());
|
||||
Ok(self.wrkdir.clone())
|
||||
}
|
||||
@@ -532,10 +529,7 @@ impl FileTransfer for SftpFileTransfer {
|
||||
match self.sftp.as_ref() {
|
||||
Some(sftp) => {
|
||||
// Get path
|
||||
let dir: PathBuf = match self.get_remote_path(path) {
|
||||
Ok(p) => p,
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
let dir: PathBuf = self.get_remote_path(path)?;
|
||||
info!("Getting file entries in {}", path.display());
|
||||
// Get files
|
||||
match sftp.readdir(dir.as_path()) {
|
||||
@@ -609,10 +603,7 @@ impl FileTransfer for SftpFileTransfer {
|
||||
// Remove recursively
|
||||
debug!("{} is a directory; removing all directory entries", d.name);
|
||||
// Get directory files
|
||||
let directory_content: Vec<FsEntry> = match self.list_dir(d.abs_path.as_path()) {
|
||||
Ok(entries) => entries,
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
let directory_content: Vec<FsEntry> = self.list_dir(d.abs_path.as_path())?;
|
||||
for entry in directory_content.iter() {
|
||||
if let Err(err) = self.remove(&entry) {
|
||||
return Err(err);
|
||||
@@ -666,10 +657,7 @@ impl FileTransfer for SftpFileTransfer {
|
||||
match self.sftp.as_ref() {
|
||||
Some(sftp) => {
|
||||
// Get path
|
||||
let dir: PathBuf = match self.get_remote_path(path) {
|
||||
Ok(p) => p,
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
let dir: PathBuf = self.get_remote_path(path)?;
|
||||
info!("Stat file {}", dir.display());
|
||||
// Get file
|
||||
match sftp.stat(dir.as_path()) {
|
||||
@@ -758,10 +746,7 @@ impl FileTransfer for SftpFileTransfer {
|
||||
)),
|
||||
Some(sftp) => {
|
||||
// Get remote file name
|
||||
let remote_path: PathBuf = match self.get_remote_path(file.abs_path.as_path()) {
|
||||
Ok(p) => p,
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
let remote_path: PathBuf = self.get_remote_path(file.abs_path.as_path())?;
|
||||
info!("Receiving file {}", remote_path.display());
|
||||
// Open remote file
|
||||
match sftp.open(remote_path.as_path()) {
|
||||
@@ -800,7 +785,9 @@ impl FileTransfer for SftpFileTransfer {
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
use crate::utils::test_helpers::make_fsentry;
|
||||
#[cfg(feature = "with-containers")]
|
||||
use crate::utils::test_helpers::{create_sample_file_entry, write_file, write_ssh_key};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
@@ -813,34 +800,188 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_connect() {
|
||||
#[cfg(feature = "with-containers")]
|
||||
fn test_filetransfer_sftp_server() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert_eq!(client.is_connected(), false);
|
||||
// Sample file
|
||||
let (entry, file): (FsFile, tempfile::NamedTempFile) = create_sample_file_entry();
|
||||
// Connect
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
String::from("127.0.0.1"),
|
||||
10022,
|
||||
Some(String::from("sftp")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and sftp
|
||||
assert!(client.session.is_some());
|
||||
assert!(client.sftp.is_some());
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/"));
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/config"));
|
||||
assert_eq!(client.is_connected(), true);
|
||||
// Pwd
|
||||
assert_eq!(client.wrkdir.clone(), client.pwd().ok().unwrap());
|
||||
// Stat
|
||||
let stat: FsFile = client
|
||||
.stat(PathBuf::from("/config/sshd.pid").as_path())
|
||||
.ok()
|
||||
.unwrap()
|
||||
.unwrap_file();
|
||||
assert_eq!(stat.name.as_str(), "sshd.pid");
|
||||
let stat: FsDirectory = client
|
||||
.stat(PathBuf::from("/config").as_path())
|
||||
.ok()
|
||||
.unwrap()
|
||||
.unwrap_dir();
|
||||
assert_eq!(stat.name.as_str(), "config");
|
||||
// Stat (err)
|
||||
assert!(client
|
||||
.stat(PathBuf::from("/config/5t0ca220.log").as_path())
|
||||
.is_err());
|
||||
// List dir (dir has 4 (one is hidden :D) entries)
|
||||
assert_eq!(client.list_dir(&Path::new("/config")).unwrap().len(), 4);
|
||||
// Make directory
|
||||
assert!(client.mkdir(PathBuf::from("/tmp/omar").as_path()).is_ok());
|
||||
// Make directory (err)
|
||||
assert!(client
|
||||
.mkdir(PathBuf::from("/root/aaaaa/pommlar").as_path())
|
||||
.is_err());
|
||||
// Change directory
|
||||
assert!(client
|
||||
.change_dir(PathBuf::from("/tmp/omar").as_path())
|
||||
.is_ok());
|
||||
// Change directory (err)
|
||||
assert!(client
|
||||
.change_dir(PathBuf::from("/tmp/oooo/aaaa/eee").as_path())
|
||||
.is_err());
|
||||
// Copy (not supported)
|
||||
assert!(client
|
||||
.copy(&FsEntry::File(entry.clone()), PathBuf::from("/").as_path())
|
||||
.is_err());
|
||||
// Exec
|
||||
assert_eq!(client.exec("echo 5").ok().unwrap().as_str(), "5\n");
|
||||
// Upload 2 files
|
||||
let mut writable = client
|
||||
.send_file(&entry, PathBuf::from("omar.txt").as_path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
write_file(&file, &mut writable);
|
||||
assert!(client.on_sent(writable).is_ok());
|
||||
let mut writable = client
|
||||
.send_file(&entry, PathBuf::from("README.md").as_path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
write_file(&file, &mut writable);
|
||||
assert!(client.on_sent(writable).is_ok());
|
||||
// Upload file (err)
|
||||
assert!(client
|
||||
.send_file(&entry, PathBuf::from("/ommlar/omarone").as_path())
|
||||
.is_err());
|
||||
// List dir
|
||||
let list: Vec<FsEntry> = client
|
||||
.list_dir(PathBuf::from("/tmp/omar").as_path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
assert_eq!(list.len(), 2);
|
||||
// Find
|
||||
assert_eq!(client.find("*.txt").ok().unwrap().len(), 1);
|
||||
assert_eq!(client.find("*.md").ok().unwrap().len(), 1);
|
||||
assert_eq!(client.find("*.jpeg").ok().unwrap().len(), 0);
|
||||
// Rename
|
||||
assert!(client
|
||||
.mkdir(PathBuf::from("/tmp/uploads").as_path())
|
||||
.is_ok());
|
||||
assert!(client
|
||||
.rename(
|
||||
list.get(0).unwrap(),
|
||||
PathBuf::from("/tmp/uploads/README.txt").as_path()
|
||||
)
|
||||
.is_ok());
|
||||
// Rename (err)
|
||||
assert!(client
|
||||
.rename(list.get(0).unwrap(), PathBuf::from("OMARONE").as_path())
|
||||
.is_err());
|
||||
let dummy: FsEntry = FsEntry::File(FsFile {
|
||||
name: String::from("cucumber.txt"),
|
||||
abs_path: PathBuf::from("/cucumber.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
|
||||
});
|
||||
assert!(client
|
||||
.rename(&dummy, PathBuf::from("/a/b/c").as_path())
|
||||
.is_err());
|
||||
// Remove
|
||||
assert!(client.remove(list.get(1).unwrap()).is_ok());
|
||||
assert!(client.remove(list.get(1).unwrap()).is_err());
|
||||
// Receive file
|
||||
let mut writable = client
|
||||
.send_file(&entry, PathBuf::from("/tmp/uploads/README.txt").as_path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
write_file(&file, &mut writable);
|
||||
assert!(client.on_sent(writable).is_ok());
|
||||
let file: FsFile = client
|
||||
.list_dir(PathBuf::from("/tmp/uploads").as_path())
|
||||
.ok()
|
||||
.unwrap()
|
||||
.get(0)
|
||||
.unwrap()
|
||||
.clone()
|
||||
.unwrap_file();
|
||||
let mut readable = client.recv_file(&file).ok().unwrap();
|
||||
let mut data: Vec<u8> = vec![0; 1024];
|
||||
assert!(readable.read(&mut data).is_ok());
|
||||
assert!(client.on_recv(readable).is_ok());
|
||||
// Receive file (err)
|
||||
assert!(client.recv_file(&entry).is_err());
|
||||
// Cleanup
|
||||
assert!(client.change_dir(PathBuf::from("/").as_path()).is_ok());
|
||||
assert!(client
|
||||
.remove(&make_fsentry(PathBuf::from("/tmp/omar"), true))
|
||||
.is_ok());
|
||||
assert!(client
|
||||
.remove(&make_fsentry(PathBuf::from("/tmp/uploads"), true))
|
||||
.is_ok());
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
assert_eq!(client.is_connected(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-containers")]
|
||||
fn test_filetransfer_sftp_ssh_storage() {
|
||||
let mut storage: SshKeyStorage = SshKeyStorage::empty();
|
||||
let key_file: tempfile::NamedTempFile = write_ssh_key();
|
||||
storage.add_key("127.0.0.1", "sftp", key_file.path().to_path_buf());
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(storage);
|
||||
// Connect
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("127.0.0.1"),
|
||||
10022,
|
||||
Some(String::from("sftp")),
|
||||
None,
|
||||
)
|
||||
.is_ok());
|
||||
assert_eq!(client.is_connected(), true);
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_bad_auth() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
String::from("127.0.0.1"),
|
||||
10022,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("badpassword"))
|
||||
)
|
||||
@@ -848,13 +989,52 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-containers")]
|
||||
fn test_filetransfer_sftp_no_credentials() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(String::from("test.rebex.net"), 22, None, None)
|
||||
.connect(String::from("127.0.0.1"), 10022, None, None)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-containers")]
|
||||
fn test_filetransfer_sftp_get_remote_path() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
// Connect
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("127.0.0.1"),
|
||||
10022,
|
||||
Some(String::from("sftp")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// get realpath
|
||||
assert!(client
|
||||
.change_dir(PathBuf::from("/config").as_path())
|
||||
.is_ok());
|
||||
assert_eq!(
|
||||
client
|
||||
.get_remote_path(PathBuf::from("sshd.pid").as_path())
|
||||
.ok()
|
||||
.unwrap(),
|
||||
PathBuf::from("/config/sshd.pid")
|
||||
);
|
||||
// No such file
|
||||
assert!(client
|
||||
.get_remote_path(PathBuf::from("omarone.txt").as_path())
|
||||
.is_err());
|
||||
// Ok abs path
|
||||
assert_eq!(
|
||||
client
|
||||
.get_remote_path(PathBuf::from("/config/sshd.pid").as_path())
|
||||
.ok()
|
||||
.unwrap(),
|
||||
PathBuf::from("/config/sshd.pid")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_bad_server() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
@@ -868,302 +1048,6 @@ mod tests {
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_pwd() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and sftp
|
||||
assert!(client.session.is_some());
|
||||
assert!(client.sftp.is_some());
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/"));
|
||||
// Pwd
|
||||
assert_eq!(client.wrkdir.clone(), client.pwd().ok().unwrap());
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_cwd() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and sftp
|
||||
assert!(client.session.is_some());
|
||||
assert!(client.sftp.is_some());
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/"));
|
||||
// Pwd
|
||||
assert_eq!(client.wrkdir.clone(), client.pwd().ok().unwrap());
|
||||
// Cwd (relative)
|
||||
assert!(client.change_dir(PathBuf::from("pub/").as_path()).is_ok());
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/pub"));
|
||||
// Cwd (absolute)
|
||||
assert!(client.change_dir(PathBuf::from("/").as_path()).is_ok());
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/"));
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_copy() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and sftp
|
||||
assert!(client.session.is_some());
|
||||
assert!(client.sftp.is_some());
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/"));
|
||||
// Copy
|
||||
let file: FsFile = FsFile {
|
||||
name: String::from("readme.txt"),
|
||||
abs_path: PathBuf::from("/readme.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
|
||||
};
|
||||
assert!(client
|
||||
.copy(&FsEntry::File(file), &Path::new("/tmp/dest.txt"))
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_cwd_error() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Cwd (abs)
|
||||
assert!(client
|
||||
.change_dir(PathBuf::from("/omar/gabber").as_path())
|
||||
.is_err());
|
||||
// Cwd (rel)
|
||||
assert!(client
|
||||
.change_dir(PathBuf::from("gomar/pett").as_path())
|
||||
.is_err());
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
assert!(client
|
||||
.change_dir(PathBuf::from("gomar/pett").as_path())
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_ls() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and sftp
|
||||
assert!(client.session.is_some());
|
||||
assert!(client.sftp.is_some());
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/"));
|
||||
// List dir
|
||||
let pwd: PathBuf = client.pwd().ok().unwrap();
|
||||
let files: Vec<FsEntry> = client.list_dir(pwd.as_path()).ok().unwrap();
|
||||
assert_eq!(files.len(), 3); // There are 3 files
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
// Verify err
|
||||
assert!(client.list_dir(pwd.as_path()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_stat() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and sftp
|
||||
assert!(client.session.is_some());
|
||||
assert!(client.sftp.is_some());
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/"));
|
||||
let file: FsEntry = client
|
||||
.stat(PathBuf::from("readme.txt").as_path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
if let FsEntry::File(file) = file {
|
||||
assert_eq!(file.abs_path, PathBuf::from("/readme.txt"));
|
||||
} else {
|
||||
panic!("Expected readme.txt to be a file");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_exec() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and scp
|
||||
assert!(client.session.is_some());
|
||||
// Exec
|
||||
assert_eq!(client.exec("echo 5").ok().unwrap().as_str(), "5\n");
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
// Verify err
|
||||
assert!(client.exec("echo 1").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_find() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and scp
|
||||
assert!(client.session.is_some());
|
||||
// Search for file (let's search for pop3-*.png); there should be 2
|
||||
let search_res: Vec<FsEntry> = client.find("pop3-*.png").ok().unwrap();
|
||||
assert_eq!(search_res.len(), 2);
|
||||
// verify names
|
||||
assert_eq!(search_res[0].get_name(), "pop3-browser.png");
|
||||
assert_eq!(search_res[1].get_name(), "pop3-console-client.png");
|
||||
// Search directory
|
||||
let search_res: Vec<FsEntry> = client.find("pub").ok().unwrap();
|
||||
assert_eq!(search_res.len(), 1);
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
// Verify err
|
||||
assert!(client.find("pippo").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_recv() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and sftp
|
||||
assert!(client.session.is_some());
|
||||
assert!(client.sftp.is_some());
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/"));
|
||||
let file: FsFile = FsFile {
|
||||
name: String::from("readme.txt"),
|
||||
abs_path: PathBuf::from("/readme.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
|
||||
};
|
||||
// Receive file
|
||||
assert!(client.recv_file(&file).is_ok());
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_recv_failed_nosuchfile() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and sftp
|
||||
assert!(client.session.is_some());
|
||||
assert!(client.sftp.is_some());
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/"));
|
||||
// Receive file
|
||||
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
|
||||
};
|
||||
assert!(client.recv_file(&file).is_err());
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
|
||||
// NOTE: other functions doesn't work with this test SFTP server
|
||||
|
||||
/* NOTE: the server doesn't allow you to create directories
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_mkdir() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client.connect(String::from("test.rebex.net"), 22, Some(String::from("demo")), Some(String::from("password"))).is_ok());
|
||||
let dir: String = String::from("foo");
|
||||
// Mkdir
|
||||
assert!(client.mkdir(dir).is_ok());
|
||||
// cwd
|
||||
assert!(client.change_dir(PathBuf::from("foo/").as_path()).is_ok());
|
||||
assert_eq!(client.wrkdir, PathBuf::from("/foo"));
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
*/
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_uninitialized() {
|
||||
let file: FsFile = FsFile {
|
||||
@@ -1182,10 +1066,26 @@ mod tests {
|
||||
};
|
||||
let mut sftp: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(sftp.change_dir(Path::new("/tmp")).is_err());
|
||||
assert!(sftp
|
||||
.copy(
|
||||
&make_fsentry(PathBuf::from("/nowhere"), false),
|
||||
PathBuf::from("/culonia").as_path()
|
||||
)
|
||||
.is_err());
|
||||
assert!(sftp.exec("echo 5").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
|
||||
.remove(&make_fsentry(PathBuf::from("/nowhere"), false))
|
||||
.is_err());
|
||||
assert!(sftp
|
||||
.rename(
|
||||
&make_fsentry(PathBuf::from("/nowhere"), false),
|
||||
PathBuf::from("/culonia").as_path()
|
||||
)
|
||||
.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());
|
||||
|
||||
@@ -226,6 +226,28 @@ impl FsEntry {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// ### unwrap_file
|
||||
///
|
||||
/// Unwrap FsEntry as FsFile
|
||||
pub fn unwrap_file(self) -> FsFile {
|
||||
match self {
|
||||
FsEntry::File(file) => file,
|
||||
_ => panic!("unwrap_file: not a file"),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// ### unwrap_dir
|
||||
///
|
||||
/// Unwrap FsEntry as FsDirectory
|
||||
pub fn unwrap_dir(self) -> FsDirectory {
|
||||
match self {
|
||||
FsEntry::Directory(dir) => dir,
|
||||
_ => panic!("unwrap_dir: not a directory"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -262,6 +284,7 @@ mod tests {
|
||||
assert_eq!(entry.is_dir(), true);
|
||||
assert_eq!(entry.is_file(), false);
|
||||
assert_eq!(entry.get_unix_pex(), Some((7, 5, 5)));
|
||||
assert_eq!(entry.unwrap_dir().abs_path, PathBuf::from("/foo"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -294,6 +317,47 @@ mod tests {
|
||||
assert_eq!(entry.is_symlink(), false);
|
||||
assert_eq!(entry.is_dir(), false);
|
||||
assert_eq!(entry.is_file(), true);
|
||||
assert_eq!(entry.unwrap_file().abs_path, PathBuf::from("/bar.txt"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_fs_fsentry_file_unwrap_bad() {
|
||||
let t_now: SystemTime = SystemTime::now();
|
||||
let entry: FsEntry = FsEntry::File(FsFile {
|
||||
name: String::from("bar.txt"),
|
||||
abs_path: PathBuf::from("/bar.txt"),
|
||||
last_change_time: t_now,
|
||||
last_access_time: t_now,
|
||||
creation_time: t_now,
|
||||
size: 8192,
|
||||
readonly: false,
|
||||
ftype: Some(String::from("txt")),
|
||||
symlink: None, // UNIX only
|
||||
user: Some(0), // UNIX only
|
||||
group: Some(0), // UNIX only
|
||||
unix_pex: Some((6, 4, 4)), // UNIX only
|
||||
});
|
||||
entry.unwrap_dir();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_fs_fsentry_dir_unwrap_bad() {
|
||||
let t_now: SystemTime = SystemTime::now();
|
||||
let entry: FsEntry = FsEntry::Directory(FsDirectory {
|
||||
name: String::from("foo"),
|
||||
abs_path: PathBuf::from("/foo"),
|
||||
last_change_time: t_now,
|
||||
last_access_time: t_now,
|
||||
creation_time: t_now,
|
||||
readonly: false,
|
||||
symlink: None, // UNIX only
|
||||
user: Some(0), // UNIX only
|
||||
group: Some(0), // UNIX only
|
||||
unix_pex: Some((7, 5, 5)), // UNIX only
|
||||
});
|
||||
entry.unwrap_file();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -773,10 +773,7 @@ impl Localhost {
|
||||
if filter.matches(dir.name.as_str()) {
|
||||
drained.push(FsEntry::Directory(dir.clone()));
|
||||
}
|
||||
match self.iter_search(dir.abs_path.as_path(), filter) {
|
||||
Ok(mut filtered) => drained.append(&mut filtered),
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
drained.append(&mut self.iter_search(dir.abs_path.as_path(), filter)?);
|
||||
}
|
||||
FsEntry::File(file) => {
|
||||
if filter.matches(file.name.as_str()) {
|
||||
@@ -829,6 +826,9 @@ impl Localhost {
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
use crate::utils::test_helpers::{create_sample_file, make_fsentry};
|
||||
use crate::utils::test_helpers::{make_dir_at, make_file_at};
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::fs::File;
|
||||
@@ -975,6 +975,7 @@ mod tests {
|
||||
//fs::set_permissions(file.path(), perms)?;
|
||||
assert!(host.open_file_write(file.path()).is_err());
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
#[test]
|
||||
fn test_host_localhost_symlinks() {
|
||||
@@ -1038,6 +1039,13 @@ mod tests {
|
||||
assert!(host
|
||||
.mkdir_ex(PathBuf::from("/tmp/test_dir_123456789").as_path(), true)
|
||||
.is_ok());
|
||||
// Fail
|
||||
assert!(host
|
||||
.mkdir_ex(
|
||||
PathBuf::from("/aaaa/oooooo/tmp/test_dir_123456789").as_path(),
|
||||
true
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1060,6 +1068,13 @@ mod tests {
|
||||
let files: Vec<FsEntry> = host.list_dir();
|
||||
assert_eq!(files.len(), 1); // There should be 1 file now
|
||||
assert!(host.remove(files.get(0).unwrap()).is_ok());
|
||||
// Remove unexisting directory
|
||||
assert!(host
|
||||
.remove(&make_fsentry(PathBuf::from("/a/b/c/d"), true))
|
||||
.is_err());
|
||||
assert!(host
|
||||
.remove(&make_fsentry(PathBuf::from("/aaaaaaa"), false))
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1073,7 +1088,7 @@ mod tests {
|
||||
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
||||
let files: Vec<FsEntry> = host.list_dir();
|
||||
assert_eq!(files.len(), 1); // There should be 1 file now
|
||||
assert_eq!(get_filename(files.get(0).unwrap()), String::from("foo.txt"));
|
||||
assert_eq!(files.get(0).unwrap().get_name(), "foo.txt");
|
||||
// Rename file
|
||||
let dst_path: PathBuf =
|
||||
PathBuf::from(format!("{}/bar.txt", tmpdir.path().display()).as_str());
|
||||
@@ -1083,7 +1098,7 @@ mod tests {
|
||||
// There should be still 1 file now, but named bar.txt
|
||||
let files: Vec<FsEntry> = host.list_dir();
|
||||
assert_eq!(files.len(), 1); // There should be 0 files now
|
||||
assert_eq!(get_filename(files.get(0).unwrap()), String::from("bar.txt"));
|
||||
assert_eq!(files.get(0).unwrap().get_name(), "bar.txt");
|
||||
// Fail
|
||||
let bad_path: PathBuf = PathBuf::from("/asdailsjoidoewojdijow/ashdiuahu");
|
||||
assert!(host
|
||||
@@ -1131,6 +1146,13 @@ mod tests {
|
||||
assert!(host.copy(&file1_entry, file2_path.as_path()).is_ok());
|
||||
// Verify host has two files
|
||||
assert_eq!(host.files.len(), 2);
|
||||
// Fail copy
|
||||
assert!(host
|
||||
.copy(
|
||||
&make_fsentry(PathBuf::from("/a/a7/a/a7a"), false),
|
||||
PathBuf::from("571k422i").as_path()
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
@@ -1232,16 +1254,16 @@ mod tests {
|
||||
let tmpdir: tempfile::TempDir = tempfile::TempDir::new().unwrap();
|
||||
let dir_path: &Path = tmpdir.path();
|
||||
// Make files
|
||||
assert!(make_sample_file(dir_path, "pippo.txt").is_ok());
|
||||
assert!(make_sample_file(dir_path, "foo.jpg").is_ok());
|
||||
assert!(make_file_at(dir_path, "pippo.txt").is_ok());
|
||||
assert!(make_file_at(dir_path, "foo.jpg").is_ok());
|
||||
// Make nested struct
|
||||
assert!(make_dir(dir_path, "examples").is_ok());
|
||||
assert!(make_dir_at(dir_path, "examples").is_ok());
|
||||
let mut subdir: PathBuf = PathBuf::from(dir_path);
|
||||
subdir.push("examples/");
|
||||
assert!(make_sample_file(subdir.as_path(), "omar.txt").is_ok());
|
||||
assert!(make_sample_file(subdir.as_path(), "errors.txt").is_ok());
|
||||
assert!(make_sample_file(subdir.as_path(), "screenshot.png").is_ok());
|
||||
assert!(make_sample_file(subdir.as_path(), "examples.csv").is_ok());
|
||||
assert!(make_file_at(subdir.as_path(), "omar.txt").is_ok());
|
||||
assert!(make_file_at(subdir.as_path(), "errors.txt").is_ok());
|
||||
assert!(make_file_at(subdir.as_path(), "screenshot.png").is_ok());
|
||||
assert!(make_file_at(subdir.as_path(), "examples.csv").is_ok());
|
||||
let host: Localhost = Localhost::new(PathBuf::from(dir_path)).ok().unwrap();
|
||||
// Find txt files
|
||||
let mut result: Vec<FsEntry> = host.find("*.txt").ok().unwrap();
|
||||
@@ -1300,50 +1322,4 @@ mod tests {
|
||||
String::from("File already exists")
|
||||
);
|
||||
}
|
||||
|
||||
/// ### make_sample_file
|
||||
///
|
||||
/// Make a file with `name` in the current directory
|
||||
fn make_sample_file(dir: &Path, filename: &str) -> std::io::Result<()> {
|
||||
let mut p: PathBuf = PathBuf::from(dir);
|
||||
p.push(filename);
|
||||
let mut file: File = File::create(p.as_path())?;
|
||||
write!(
|
||||
file,
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.\nMauris ultricies consequat eros,\nnec scelerisque magna imperdiet metus.\n"
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// ### make_dir
|
||||
///
|
||||
/// Make a directory in `dir`
|
||||
fn make_dir(dir: &Path, dirname: &str) -> std::io::Result<()> {
|
||||
let mut p: PathBuf = PathBuf::from(dir);
|
||||
p.push(dirname);
|
||||
std::fs::create_dir(p.as_path())
|
||||
}
|
||||
|
||||
/// ### create_sample_file
|
||||
///
|
||||
/// Create a sample file
|
||||
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
fn create_sample_file() -> tempfile::NamedTempFile {
|
||||
// Write
|
||||
let mut tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap();
|
||||
write!(
|
||||
tmpfile,
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.\nMauris ultricies consequat eros,\nnec scelerisque magna imperdiet metus.\n"
|
||||
)
|
||||
.unwrap();
|
||||
tmpfile
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
fn get_filename(entry: &FsEntry) -> String {
|
||||
match entry {
|
||||
FsEntry::Directory(d) => d.name.clone(),
|
||||
FsEntry::File(f) => f.name.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,11 +427,12 @@ mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[test]
|
||||
|
||||
fn test_system_bookmarks_new() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: tempfile::TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
// Initialize a new bookmarks client
|
||||
let client: BookmarksClient =
|
||||
@@ -454,7 +455,7 @@ mod tests {
|
||||
)
|
||||
.is_err());
|
||||
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: tempfile::TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, _): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
assert!(
|
||||
BookmarksClient::new(cfg_path.as_path(), Path::new("/tmp/efnnu/omar"), 16).is_err()
|
||||
@@ -464,7 +465,7 @@ mod tests {
|
||||
#[test]
|
||||
|
||||
fn test_system_bookmarks_new_from_existing() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: tempfile::TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
// Initialize a new bookmarks client
|
||||
let mut client: BookmarksClient =
|
||||
@@ -510,7 +511,7 @@ mod tests {
|
||||
#[test]
|
||||
|
||||
fn test_system_bookmarks_manipulate_bookmarks() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: tempfile::TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
// Initialize a new bookmarks client
|
||||
let mut client: BookmarksClient =
|
||||
@@ -556,7 +557,7 @@ mod tests {
|
||||
#[should_panic]
|
||||
|
||||
fn test_system_bookmarks_bad_bookmark_name() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: tempfile::TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
// Initialize a new bookmarks client
|
||||
let mut client: BookmarksClient =
|
||||
@@ -575,7 +576,7 @@ mod tests {
|
||||
#[test]
|
||||
|
||||
fn test_system_bookmarks_manipulate_recents() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: tempfile::TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
// Initialize a new bookmarks client
|
||||
let mut client: BookmarksClient =
|
||||
@@ -610,7 +611,7 @@ mod tests {
|
||||
#[test]
|
||||
|
||||
fn test_system_bookmarks_dup_recent() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: tempfile::TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
// Initialize a new bookmarks client
|
||||
let mut client: BookmarksClient =
|
||||
@@ -635,7 +636,7 @@ mod tests {
|
||||
#[test]
|
||||
|
||||
fn test_system_bookmarks_recents_more_than_limit() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: tempfile::TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
// Initialize a new bookmarks client
|
||||
let mut client: BookmarksClient =
|
||||
@@ -681,9 +682,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
|
||||
fn test_system_bookmarks_add_bookmark_empty() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: tempfile::TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
// Initialize a new bookmarks client
|
||||
let mut client: BookmarksClient =
|
||||
@@ -702,19 +702,10 @@ mod tests {
|
||||
/// ### get_paths
|
||||
///
|
||||
/// Get paths for configuration and key for bookmarks
|
||||
|
||||
fn get_paths(dir: &Path) -> (PathBuf, PathBuf) {
|
||||
let k: PathBuf = PathBuf::from(dir);
|
||||
let mut c: PathBuf = k.clone();
|
||||
c.push("bookmarks.toml");
|
||||
(c, k)
|
||||
}
|
||||
|
||||
/// ### create_tmp_dir
|
||||
///
|
||||
/// Create temporary directory
|
||||
|
||||
fn create_tmp_dir() -> tempfile::TempDir {
|
||||
tempfile::TempDir::new().ok().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,10 +408,11 @@ mod tests {
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::io::Read;
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[test]
|
||||
fn test_system_config_new() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, ssh_keys_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
let client: ConfigClient = ConfigClient::new(cfg_path.as_path(), ssh_keys_path.as_path())
|
||||
.ok()
|
||||
@@ -437,14 +438,14 @@ mod tests {
|
||||
ConfigClient::new(Path::new("/tmp/oifoif/omar"), Path::new("/tmp/efnnu/omar"),)
|
||||
.is_err()
|
||||
);
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, _): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
assert!(ConfigClient::new(cfg_path.as_path(), Path::new("/tmp/efnnu/omar")).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_system_config_from_existing() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
let mut client: ConfigClient = ConfigClient::new(cfg_path.as_path(), key_path.as_path())
|
||||
.ok()
|
||||
@@ -477,7 +478,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_system_config_text_editor() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
let mut client: ConfigClient = ConfigClient::new(cfg_path.as_path(), key_path.as_path())
|
||||
.ok()
|
||||
@@ -488,7 +489,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_system_config_default_protocol() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
let mut client: ConfigClient = ConfigClient::new(cfg_path.as_path(), key_path.as_path())
|
||||
.ok()
|
||||
@@ -502,7 +503,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_system_config_show_hidden_files() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
let mut client: ConfigClient = ConfigClient::new(cfg_path.as_path(), key_path.as_path())
|
||||
.ok()
|
||||
@@ -513,7 +514,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_system_config_check_for_updates() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
let mut client: ConfigClient = ConfigClient::new(cfg_path.as_path(), key_path.as_path())
|
||||
.ok()
|
||||
@@ -527,7 +528,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_system_config_group_dirs() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
let mut client: ConfigClient = ConfigClient::new(cfg_path.as_path(), key_path.as_path())
|
||||
.ok()
|
||||
@@ -540,7 +541,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_system_config_local_file_fmt() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
let mut client: ConfigClient = ConfigClient::new(cfg_path.as_path(), key_path.as_path())
|
||||
.ok()
|
||||
@@ -555,7 +556,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_system_config_remote_file_fmt() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
let mut client: ConfigClient = ConfigClient::new(cfg_path.as_path(), key_path.as_path())
|
||||
.ok()
|
||||
@@ -573,7 +574,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_system_config_ssh_keys() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
let mut client: ConfigClient = ConfigClient::new(cfg_path.as_path(), key_path.as_path())
|
||||
.ok()
|
||||
@@ -637,13 +638,6 @@ mod tests {
|
||||
(c, k)
|
||||
}
|
||||
|
||||
/// ### create_tmp_dir
|
||||
///
|
||||
/// Create temporary directory
|
||||
fn create_tmp_dir() -> tempfile::TempDir {
|
||||
tempfile::TempDir::new().ok().unwrap()
|
||||
}
|
||||
|
||||
fn get_sample_rsa_key() -> String {
|
||||
format!(
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n{}\n-----END OPENSSH PRIVATE KEY-----",
|
||||
|
||||
@@ -87,6 +87,16 @@ impl SshKeyStorage {
|
||||
fn make_mapkey(host: &str, username: &str) -> String {
|
||||
format!("{}@{}", username, host)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// ### add_key
|
||||
///
|
||||
/// Add a key to storage
|
||||
/// NOTE: available only for tests
|
||||
pub fn add_key(&mut self, host: &str, username: &str, p: PathBuf) {
|
||||
let key: String = Self::make_mapkey(host, username);
|
||||
self.hosts.insert(key, p);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -100,7 +110,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_system_sshkey_storage_new() {
|
||||
let tmp_dir: tempfile::TempDir = create_tmp_dir();
|
||||
let tmp_dir: tempfile::TempDir = tempfile::TempDir::new().ok().unwrap();
|
||||
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||
let mut client: ConfigClient = ConfigClient::new(cfg_path.as_path(), key_path.as_path())
|
||||
.ok()
|
||||
@@ -128,6 +138,16 @@ mod tests {
|
||||
assert_eq!(storage.hosts.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_system_sshkey_storage_add() {
|
||||
let mut storage: SshKeyStorage = SshKeyStorage::empty();
|
||||
storage.add_key("deskichup", "veeso", PathBuf::from("/tmp/omar"));
|
||||
assert_eq!(
|
||||
*storage.resolve("deskichup", "veeso").unwrap(),
|
||||
PathBuf::from("/tmp/omar")
|
||||
);
|
||||
}
|
||||
|
||||
/// ### get_paths
|
||||
///
|
||||
/// Get paths for configuration and keys directory
|
||||
@@ -138,11 +158,4 @@ mod tests {
|
||||
c.push("config.toml");
|
||||
(c, k)
|
||||
}
|
||||
|
||||
/// ### create_tmp_dir
|
||||
///
|
||||
/// Create temporary directory
|
||||
fn create_tmp_dir() -> tempfile::TempDir {
|
||||
tempfile::TempDir::new().ok().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "githubActions"))]
|
||||
#[cfg(not(feature = "github-actions"))]
|
||||
fn test_ui_context() {
|
||||
// Prepare stuff
|
||||
let mut ctx: Context = Context::new(None, Some(String::from("alles kaput")));
|
||||
|
||||
@@ -80,7 +80,7 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[cfg(not(all(target_os = "macos", feature = "githubActions")))]
|
||||
#[cfg(not(all(target_os = "macos", feature = "github-actions")))]
|
||||
fn test_utils_git_check_for_updates() {
|
||||
assert!(check_for_updates("100.0.0").ok().unwrap().is_none());
|
||||
assert!(check_for_updates("0.0.1").ok().unwrap().is_some());
|
||||
|
||||
@@ -33,3 +33,7 @@ pub mod git;
|
||||
pub mod parser;
|
||||
pub mod random;
|
||||
pub mod ui;
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code)]
|
||||
pub mod test_helpers;
|
||||
|
||||
@@ -186,13 +186,10 @@ pub fn parse_lstime(tm: &str, fmt_year: &str, fmt_hours: &str) -> Result<SystemT
|
||||
let this_year: i32 = Utc::now().year();
|
||||
let date_time_str: String = format!("{} {}", tm, this_year);
|
||||
// Now parse
|
||||
match NaiveDateTime::parse_from_str(
|
||||
NaiveDateTime::parse_from_str(
|
||||
date_time_str.as_ref(),
|
||||
format!("{} %Y", fmt_hours).as_ref(),
|
||||
) {
|
||||
Ok(dt) => dt,
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
)?
|
||||
}
|
||||
};
|
||||
// Convert datetime to system time
|
||||
|
||||
248
src/utils/test_helpers.rs
Normal file
248
src/utils/test_helpers.rs
Normal file
@@ -0,0 +1,248 @@
|
||||
//! ## TestHelpers
|
||||
//!
|
||||
//! contains helper functions for tests
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* termscp - Copyright (c) 2021 Christian Visintin
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
use crate::fs::{FsDirectory, FsEntry, FsFile};
|
||||
// ext
|
||||
use std::fs::File;
|
||||
#[cfg(feature = "with-containers")]
|
||||
use std::fs::OpenOptions;
|
||||
#[cfg(feature = "with-containers")]
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::SystemTime;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
pub fn create_sample_file_entry() -> (FsFile, NamedTempFile) {
|
||||
// Write
|
||||
let tmpfile = create_sample_file();
|
||||
(
|
||||
FsFile {
|
||||
name: tmpfile
|
||||
.path()
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
abs_path: tmpfile.path().to_path_buf(),
|
||||
last_change_time: SystemTime::UNIX_EPOCH,
|
||||
last_access_time: SystemTime::UNIX_EPOCH,
|
||||
creation_time: SystemTime::UNIX_EPOCH,
|
||||
size: 127,
|
||||
ftype: None, // File type
|
||||
readonly: false,
|
||||
symlink: None, // UNIX only
|
||||
user: Some(0), // UNIX only
|
||||
group: Some(0), // UNIX only
|
||||
unix_pex: Some((6, 4, 4)), // UNIX only
|
||||
},
|
||||
tmpfile,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn create_sample_file() -> NamedTempFile {
|
||||
// Write
|
||||
let mut tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap();
|
||||
writeln!(
|
||||
tmpfile,
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.Mauris ultricies consequat eros,nec scelerisque magna imperdiet metus."
|
||||
)
|
||||
.unwrap();
|
||||
tmpfile
|
||||
}
|
||||
|
||||
/// ### make_file_at
|
||||
///
|
||||
/// Make a file with `name` at specified path
|
||||
pub fn make_file_at(dir: &Path, filename: &str) -> std::io::Result<()> {
|
||||
let mut p: PathBuf = PathBuf::from(dir);
|
||||
p.push(filename);
|
||||
let mut file: File = File::create(p.as_path())?;
|
||||
writeln!(
|
||||
file,
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.Mauris ultricies consequat eros,nec scelerisque magna imperdiet metus."
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// ### make_dir_at
|
||||
///
|
||||
/// Make a directory in `dir`
|
||||
pub fn make_dir_at(dir: &Path, dirname: &str) -> std::io::Result<()> {
|
||||
let mut p: PathBuf = PathBuf::from(dir);
|
||||
p.push(dirname);
|
||||
std::fs::create_dir(p.as_path())
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-containers")]
|
||||
pub fn write_file(file: &NamedTempFile, writable: &mut Box<dyn Write>) {
|
||||
let mut fhnd = OpenOptions::new()
|
||||
.create(false)
|
||||
.read(true)
|
||||
.write(false)
|
||||
.open(file.path())
|
||||
.ok()
|
||||
.unwrap();
|
||||
// Read file
|
||||
let mut buffer: [u8; 65536] = [0; 65536];
|
||||
assert!(fhnd.read(&mut buffer).is_ok());
|
||||
// Write file
|
||||
assert!(writable.write(&buffer).is_ok());
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-containers")]
|
||||
pub fn write_ssh_key() -> NamedTempFile {
|
||||
let mut tmpfile: NamedTempFile = NamedTempFile::new().unwrap();
|
||||
writeln!(
|
||||
tmpfile,
|
||||
r"-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
|
||||
NhAAAAAwEAAQAAAQEAxKyYUMRCNPlb4ZV1VMofrzApu2l3wgP4Ot9wBvHsw/+RMpcHIbQK
|
||||
9iQqAVp8Z+M1fJyPXTKjoJtIzuCLF6Sjo0KI7/tFTh+yPnA5QYNLZOIRZb8skumL4gwHww
|
||||
5Z942FDPuUDQ30C2mZR9lr3Cd5pA8S1ZSPTAV9QQHkpgoS8cAL8QC6dp3CJjUC8wzvXh3I
|
||||
oN3bTKxCpM10KMEVuWO3lM4Nvr71auB9gzo1sFJ3bwebCZIRH01FROyA/GXRiaOtJFG/9N
|
||||
nWWI/iG5AJzArKpLZNHIP+FxV/NoRH0WBXm9Wq5MrBYrD1NQzm+kInpS/2sXk3m1aZWqLm
|
||||
HF2NKRXSbQAAA8iI+KSniPikpwAAAAdzc2gtcnNhAAABAQDErJhQxEI0+VvhlXVUyh+vMC
|
||||
m7aXfCA/g633AG8ezD/5EylwchtAr2JCoBWnxn4zV8nI9dMqOgm0jO4IsXpKOjQojv+0VO
|
||||
H7I+cDlBg0tk4hFlvyyS6YviDAfDDln3jYUM+5QNDfQLaZlH2WvcJ3mkDxLVlI9MBX1BAe
|
||||
SmChLxwAvxALp2ncImNQLzDO9eHcig3dtMrEKkzXQowRW5Y7eUzg2+vvVq4H2DOjWwUndv
|
||||
B5sJkhEfTUVE7ID8ZdGJo60kUb/02dZYj+IbkAnMCsqktk0cg/4XFX82hEfRYFeb1arkys
|
||||
FisPU1DOb6QielL/axeTebVplaouYcXY0pFdJtAAAAAwEAAQAAAP8u3PFuTVV5SfGazwIm
|
||||
MgNaux82iOsAT/HWFWecQAkqqrruUw5f+YajH/riV61NE9aq2qNOkcJrgpTWtqpt980GGd
|
||||
SHWlgpRWQzfIooEiDk6Pk8RVFZsEykkDlJQSIu2onZjhi5A5ojHgZoGGabDsztSqoyOjPq
|
||||
6WPvGYRiDAR3leBMyp1WufBCJqAsC4L8CjPJSmnZhc5a0zXkC9Syz74Fa08tdM7bGhtvP1
|
||||
GmzuYxkgxHH2IFeoumUSBHRiTZayGuRUDel6jgEiUMxenaDKXe7FpYzMm9tQZA10Mm4LhK
|
||||
5rP9nd2/KRTFRnfZMnKvtIRC9vtlSLBe14qw+4ZCl60AAACAf1kghlO3+HIWplOmk/lCL0
|
||||
w75Zz+RdvueL9UuoyNN1QrUEY420LsixgWSeRPby+Rb/hW+XSAZJQHowQ8acFJhU85So7f
|
||||
4O4wcDuE4f6hpsW9tTfkCEUdLCQJ7EKLCrod6jIV7hvI6rvXiVucRpeAzdOaq4uzj2cwDd
|
||||
tOdYVsnmQAAACBAOVxBsvO/Sr3rZUbNtA6KewZh/09HNGoKNaCeiD7vaSn2UJbbPRByF/o
|
||||
Oo5zv8ee8r3882NnmG808XfSn7pPZAzbbTmOaJt0fmyZhivCghSNzV6njW3o0PdnC0fGZQ
|
||||
ruVXgkd7RJFbsIiD4dDcF4VCjwWHfTK21EOgJUA5pN6TNvAAAAgQDbcJWRx8Uyhkj2+srb
|
||||
3n2Rt6CR7kEl9cw17ItFjMn+pO81/5U2aGw0iLlX7E06TAMQC+dyW/WaxQRey8RRdtbJ1e
|
||||
TNKCN34QCWkyuYRHGhcNc0quEDayPw5QWGXlP4BzjfRUcPxY9cCXLe5wDLYsX33HwOAc59
|
||||
RorU9FCmS/654wAAABFyb290QDhjNTBmZDRjMzQ1YQECAw==
|
||||
-----END OPENSSH PRIVATE KEY-----"
|
||||
)
|
||||
.unwrap();
|
||||
tmpfile
|
||||
}
|
||||
|
||||
/// ### make_fsentry
|
||||
///
|
||||
/// Create a FsEntry at specified path
|
||||
pub fn make_fsentry(path: PathBuf, is_dir: bool) -> FsEntry {
|
||||
match is_dir {
|
||||
true => FsEntry::Directory(FsDirectory {
|
||||
name: path.file_name().unwrap().to_string_lossy().to_string(),
|
||||
abs_path: path,
|
||||
last_change_time: SystemTime::UNIX_EPOCH,
|
||||
last_access_time: SystemTime::UNIX_EPOCH,
|
||||
creation_time: SystemTime::UNIX_EPOCH,
|
||||
readonly: false,
|
||||
symlink: None, // UNIX only
|
||||
user: Some(0), // UNIX only
|
||||
group: Some(0), // UNIX only
|
||||
unix_pex: Some((6, 4, 4)), // UNIX only
|
||||
}),
|
||||
false => FsEntry::File(FsFile {
|
||||
name: path.file_name().unwrap().to_string_lossy().to_string(),
|
||||
abs_path: path,
|
||||
last_change_time: SystemTime::UNIX_EPOCH,
|
||||
last_access_time: SystemTime::UNIX_EPOCH,
|
||||
creation_time: SystemTime::UNIX_EPOCH,
|
||||
size: 127,
|
||||
ftype: None, // File type
|
||||
readonly: false,
|
||||
symlink: None, // UNIX only
|
||||
user: Some(0), // UNIX only
|
||||
group: Some(0), // UNIX only
|
||||
unix_pex: Some((6, 4, 4)), // UNIX only
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn test_utils_test_helpers_sample_file() {
|
||||
let (file, _) = create_sample_file_entry();
|
||||
assert_eq!(file.readonly, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-containers")]
|
||||
fn test_utils_test_helpers_write_file() {
|
||||
let (_, temp) = create_sample_file_entry();
|
||||
let tempdest = NamedTempFile::new().unwrap();
|
||||
let mut dest: Box<dyn Write> = Box::new(
|
||||
OpenOptions::new()
|
||||
.create(true)
|
||||
.read(false)
|
||||
.write(true)
|
||||
.open(tempdest.path())
|
||||
.ok()
|
||||
.unwrap(),
|
||||
);
|
||||
write_file(&temp, &mut dest);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-containers")]
|
||||
fn test_utils_test_helpers_write_ssh_key() {
|
||||
let _ = write_ssh_key();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_utils_test_helpers_make_fsentry() {
|
||||
assert_eq!(
|
||||
make_fsentry(PathBuf::from("/tmp/omar.txt"), false)
|
||||
.unwrap_file()
|
||||
.name
|
||||
.as_str(),
|
||||
"omar.txt"
|
||||
);
|
||||
assert_eq!(
|
||||
make_fsentry(PathBuf::from("/tmp/cards"), true)
|
||||
.unwrap_dir()
|
||||
.name
|
||||
.as_str(),
|
||||
"cards"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_utils_test_helpers_make_samples() {
|
||||
let tmpdir: tempfile::TempDir = tempfile::TempDir::new().unwrap();
|
||||
assert!(make_file_at(tmpdir.path(), "omaroni.txt").is_ok());
|
||||
assert!(make_file_at(PathBuf::from("/aaaaa/bbbbb/cccc").as_path(), "readme.txt").is_err());
|
||||
assert!(make_dir_at(tmpdir.path(), "docs").is_ok());
|
||||
assert!(make_dir_at(PathBuf::from("/aaaaa/bbbbb/cccc").as_path(), "docs").is_err());
|
||||
}
|
||||
}
|
||||
35
tests/docker-compose.yml
Normal file
35
tests/docker-compose.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
version: "3"
|
||||
services:
|
||||
openssh-server:
|
||||
image: ghcr.io/linuxserver/openssh-server
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=Europe/London
|
||||
- SUDO_ACCESS=false
|
||||
- PUBLIC_KEY=ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDErJhQxEI0+VvhlXVUyh+vMCm7aXfCA/g633AG8ezD/5EylwchtAr2JCoBWnxn4zV8nI9dMqOgm0jO4IsXpKOjQojv+0VOH7I+cDlBg0tk4hFlvyyS6YviDAfDDln3jYUM+5QNDfQLaZlH2WvcJ3mkDxLVlI9MBX1BAeSmChLxwAvxALp2ncImNQLzDO9eHcig3dtMrEKkzXQowRW5Y7eUzg2+vvVq4H2DOjWwUndvB5sJkhEfTUVE7ID8ZdGJo60kUb/02dZYj+IbkAnMCsqktk0cg/4XFX82hEfRYFeb1arkysFisPU1DOb6QielL/axeTebVplaouYcXY0pFdJt root@8c50fd4c345a
|
||||
- PASSWORD_ACCESS=true
|
||||
- USER_PASSWORD=password
|
||||
- USER_NAME=sftp
|
||||
ports:
|
||||
- "10022:2222"
|
||||
openssh-server-scp:
|
||||
image: ghcr.io/linuxserver/openssh-server
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=Europe/London
|
||||
- SUDO_ACCESS=false
|
||||
- PASSWORD_ACCESS=true
|
||||
- PUBLIC_KEY=ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDErJhQxEI0+VvhlXVUyh+vMCm7aXfCA/g633AG8ezD/5EylwchtAr2JCoBWnxn4zV8nI9dMqOgm0jO4IsXpKOjQojv+0VOH7I+cDlBg0tk4hFlvyyS6YviDAfDDln3jYUM+5QNDfQLaZlH2WvcJ3mkDxLVlI9MBX1BAeSmChLxwAvxALp2ncImNQLzDO9eHcig3dtMrEKkzXQowRW5Y7eUzg2+vvVq4H2DOjWwUndvB5sJkhEfTUVE7ID8ZdGJo60kUb/02dZYj+IbkAnMCsqktk0cg/4XFX82hEfRYFeb1arkysFisPU1DOb6QielL/axeTebVplaouYcXY0pFdJt root@8c50fd4c345a
|
||||
- USER_PASSWORD=password
|
||||
- USER_NAME=sftp
|
||||
ports:
|
||||
- "10222:2222"
|
||||
ftp-server:
|
||||
image: afharo/pure-ftp
|
||||
ports:
|
||||
- "10021:21"
|
||||
- "30000-30009:30000-30009"
|
||||
environment:
|
||||
- PUBLICHOST=localhost
|
||||
29
tests/test.sh
Executable file
29
tests/test.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
if [ ! -f docker-compose.yml ]; then
|
||||
set -e
|
||||
cd tests/
|
||||
set +e
|
||||
fi
|
||||
|
||||
echo "Prepare volume..."
|
||||
rm -rf /tmp/termscp-test-ftp
|
||||
mkdir -p /tmp/termscp-test-ftp
|
||||
echo "Building docker image..."
|
||||
docker compose build
|
||||
set -e
|
||||
docker compose up -d
|
||||
set +e
|
||||
|
||||
# Go back to src root
|
||||
cd ..
|
||||
# Run tests
|
||||
echo "Running tests"
|
||||
cargo test --features with-containers -- --test-threads 1
|
||||
TEST_RESULT=$?
|
||||
# Stop container
|
||||
cd tests/
|
||||
echo "Stopping container..."
|
||||
docker compose stop
|
||||
|
||||
exit $TEST_RESULT
|
||||
Reference in New Issue
Block a user