From 014ad45371aaa67c4321cd05d6bbed1f80c22df4 Mon Sep 17 00:00:00 2001 From: Adilson Neto Date: Fri, 12 Jul 2024 23:23:44 -0300 Subject: [PATCH] fix: update project to not use external sources --- README.md | 5 +-- res/pub/example/data | 1 + res/pub/example/file1 | 1 + res/pub/example/file2 | 1 + res/pub/example/file3 | 1 + res/pub/sample.txt | 0 sample-server/Dockerfile | 6 +-- sample-server/server.py | 2 +- src/client.rs | 20 +++++++-- src/lib.rs | 3 +- src/sync.rs | 12 +++-- tests/client.rs | 97 ++++++++++++++++------------------------ 12 files changed, 74 insertions(+), 75 deletions(-) create mode 100644 res/pub/example/data create mode 100644 res/pub/example/file1 create mode 100644 res/pub/example/file2 create mode 100644 res/pub/example/file3 create mode 100644 res/pub/sample.txt diff --git a/README.md b/README.md index cee63c2..4437c09 100644 --- a/README.md +++ b/README.md @@ -31,14 +31,13 @@ To run all tests a few dependencies are needed, you need to run the docker image ### Building the image ```bash -cd sample-server -docker build . -t ftp-server +docker build . -t ftp-server -f sample-server/Dockerfile ``` ### Running the image on the background ```bash -docker run -d -p 20:20 -p 21:21 -p 2558:2558 -p 2559:2559 ftp-server +docker run -p 20:20 -p 21:21 -p 2558:2558 -p 2559:2559 ftp-server ``` After that, you can run ```cargo test``` as you normally would. diff --git a/res/pub/example/data b/res/pub/example/data new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/res/pub/example/data @@ -0,0 +1 @@ +1 diff --git a/res/pub/example/file1 b/res/pub/example/file1 new file mode 100644 index 0000000..7898192 --- /dev/null +++ b/res/pub/example/file1 @@ -0,0 +1 @@ +a diff --git a/res/pub/example/file2 b/res/pub/example/file2 new file mode 100644 index 0000000..6178079 --- /dev/null +++ b/res/pub/example/file2 @@ -0,0 +1 @@ +b diff --git a/res/pub/example/file3 b/res/pub/example/file3 new file mode 100644 index 0000000..f2ad6c7 --- /dev/null +++ b/res/pub/example/file3 @@ -0,0 +1 @@ +c diff --git a/res/pub/sample.txt b/res/pub/sample.txt new file mode 100644 index 0000000..e69de29 diff --git a/sample-server/Dockerfile b/sample-server/Dockerfile index e670ba9..7242f3d 100644 --- a/sample-server/Dockerfile +++ b/sample-server/Dockerfile @@ -3,8 +3,8 @@ FROM python:3.8 WORKDIR /app RUN mkdir res -COPY cat.png res/cat.png -COPY . . +COPY ./res res/ +COPY ./sample-server . RUN pip install --no-cache-dir -r requirements.txt @@ -13,4 +13,4 @@ EXPOSE 2558 2559 EXPOSE 20 21 -CMD [ "python", "server.py" ] \ No newline at end of file +CMD [ "python", "server.py" ] diff --git a/sample-server/server.py b/sample-server/server.py index 520e60e..a2b56bd 100644 --- a/sample-server/server.py +++ b/sample-server/server.py @@ -11,4 +11,4 @@ handler.passive_ports = range(2558, 2560) server = FTPServer(("0.0.0.0", 21), handler) -server.serve_forever() \ No newline at end of file +server.serve_forever() diff --git a/src/client.rs b/src/client.rs index 18cffc9..78fc2a4 100644 --- a/src/client.rs +++ b/src/client.rs @@ -177,9 +177,14 @@ impl Client { /// /// The help command can also be used with an argument to see detailed /// information about a single command, this behaviour is not implemented. - pub async fn help(&mut self) -> Result<(), crate::error::Error> { + pub async fn help(&mut self, command: Option) -> Result<(), crate::error::Error> { + let command = match command { + Some(command_string) => format!(" {command_string}"), + None => "".to_string(), + }; + self.write_command_expecting( - "HELP", + &format!("HELP{command}"), vec![StatusCodeKind::SystemStatus, StatusCodeKind::HelpMessage], ) .await?; @@ -430,10 +435,17 @@ impl Client { /// the HELP SITE command. /// /// Extracted from RFC959. - pub async fn site_parameters(&mut self) -> Result { + pub async fn site_parameters( + &mut self, + argument: Option, + ) -> Result { + let argument = match argument { + Some(argument_string) => format!(" {argument_string}"), + None => "".to_string(), + }; let response = self .write_command_expecting( - "SITE", + &format!("SITE{argument}"), vec![StatusCodeKind::Ok, StatusCodeKind::FeatureNotImplemented], ) .await?; diff --git a/src/lib.rs b/src/lib.rs index 05ba860..865b8c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,8 @@ //! use ftp_client::{error::Error, sync::Client}; //! //! fn main() -> Result<(), Error> { -//! let mut client = Client::connect("test.rebex.net", "demo", "password")?; +//! let server_name = std::env::var("SERVER_HOSTNAME").expect("SERVER_HOSTNAME is not set."); +//! let mut client = Client::connect(&server_name, "user", "user")?; //! let names = client.list_names("/")?; //! println!("Listing names: "); //! for name in names { diff --git a/src/sync.rs b/src/sync.rs index b037798..cf1f501 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -64,8 +64,8 @@ impl Client { /// /// The help command can also be used with an argument to see detailed /// information about a single command, this behaviour is not implemented. - pub fn help(&mut self) -> Result<(), crate::error::Error> { - self.runtime.block_on(self.inner_client.help()) + pub fn help(&mut self, command: Option) -> Result<(), crate::error::Error> { + self.runtime.block_on(self.inner_client.help(command)) } /// This command should not do anything other than receiving @@ -181,8 +181,12 @@ impl Client { /// the HELP SITE command. /// /// Extracted from RFC959. - pub fn site_parameters(&mut self) -> Result { - self.runtime.block_on(self.inner_client.site_parameters()) + pub fn site_parameters( + &mut self, + argument: Option, + ) -> Result { + self.runtime + .block_on(self.inner_client.site_parameters(argument)) } /// Get the type of operating system on the server. diff --git a/tests/client.rs b/tests/client.rs index 6829901..3fa1173 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -1,7 +1,7 @@ //! Tests for the FTP client crate, all the tests //! are made with real sample FTP servers. //! -//! Tests that start with external_ are run with +//! Tests that start with test_ are run with //! external FTP servers, the others are run //! with a local dockerize server that you should start. use ftp_client::error::Error as FtpError; @@ -11,19 +11,18 @@ use std::io::Read; use std::sync::Mutex; #[test] -fn external_name_listing() -> Result<(), FtpError> { - let mut client = SyncClient::connect("test.rebex.net", "demo", "password")?; - +fn test_name_listing() -> Result<(), FtpError> { + let mut client = SyncClient::connect(&get_local_server_hostname(), "user", "user")?; assert_eq!( - vec!["/pub".to_string(), "/readme.txt".to_string()], - client.list_names("/")? + vec!["example".to_string(), "sample.txt".to_string(),], + client.list_names("/pub/")? ); Ok(()) } #[test] -fn external_pwd() -> Result<(), FtpError> { - let mut client = SyncClient::connect("test.rebex.net", "demo", "password")?; +fn test_pwd() -> Result<(), FtpError> { + let mut client = SyncClient::connect(&get_local_server_hostname(), "user", "user")?; client.cwd("/pub")?; let dir = client.pwd()?; assert!(dir.contains("/pub")); @@ -32,39 +31,40 @@ fn external_pwd() -> Result<(), FtpError> { } #[test] -fn external_site() -> Result<(), FtpError> { - let mut client = SyncClient::connect("test.rebex.net", "demo", "password")?; - client.site_parameters()?; +fn test_site() -> Result<(), FtpError> { + let mut client = SyncClient::connect(&get_local_server_hostname(), "user", "user")?; + client.site_parameters(Some("HELP".to_string()))?; Ok(()) } #[test] -fn external_file_retrieval() -> Result<(), FtpError> { - let mut client = SyncClient::connect("test.rebex.net", "demo", "password")?; - let readme_file = client.retrieve_file("/readme.txt")?; +fn test_file_retrieval() -> Result<(), FtpError> { + let mut client = SyncClient::connect(&get_local_server_hostname(), "user", "user")?; + let cat_file = client.retrieve_file("/cat.png")?; // Taken previously and unlikely to change - let file_size = 403; + let file_size = 29712; - assert_eq!(readme_file.len(), file_size); + assert_eq!(cat_file.len(), file_size); Ok(()) } #[test] -fn external_cwd() -> Result<(), FtpError> { - let mut client = SyncClient::connect("test.rebex.net", "demo", "password")?; +fn test_cwd() -> Result<(), FtpError> { + let mut client = SyncClient::connect(&get_local_server_hostname(), "user", "user")?; client.cwd("/pub/example")?; // The /pub/example dir has many files let names = client.list_names("")?; + dbg!(names.clone()); assert!(names.len() > 3); Ok(()) } #[test] -fn external_cdup() -> Result<(), FtpError> { - let mut client = SyncClient::connect("test.rebex.net", "demo", "password")?; +fn test_cdup() -> Result<(), FtpError> { + let mut client = SyncClient::connect(&get_local_server_hostname(), "user", "user")?; let initial_names = client.list_names("")?; client.cwd("/pub/example")?; @@ -79,44 +79,37 @@ fn external_cdup() -> Result<(), FtpError> { } #[test] -fn external_logout() -> Result<(), FtpError> { - let mut client = SyncClient::connect("test.rebex.net", "demo", "password")?; +fn test_logout() -> Result<(), FtpError> { + let mut client = SyncClient::connect(&get_local_server_hostname(), "user", "user")?; client.logout() } #[test] -fn external_noop() -> Result<(), FtpError> { - let mut client = SyncClient::connect("test.rebex.net", "demo", "password")?; +fn test_noop() -> Result<(), FtpError> { + let mut client = SyncClient::connect(&get_local_server_hostname(), "user", "user")?; client.noop() } #[test] -fn external_help() -> Result<(), FtpError> { - let mut client = SyncClient::connect("test.rebex.net", "demo", "password")?; - client.help() +fn test_help() -> Result<(), FtpError> { + let mut client = SyncClient::connect(&get_local_server_hostname(), "user", "user")?; + client.help(Some("LIST".to_string())) } #[test] -fn external_store() -> Result<(), FtpError> { - let mut client = SyncClient::connect( - "speedtest4.tele2.net", - "anonymous", - "anonymous@anonymous.com", - )?; +fn test_store() -> Result<(), FtpError> { + let mut client = SyncClient::connect(&get_local_server_hostname(), "user", "user")?; let file_data = b"Some data for you"; - let file_name = "/upload/readyou.txt"; + let file_name = "/pub/example/readyou.txt"; client.store(file_name, file_data) } #[test] -fn external_store_unique() -> Result<(), FtpError> { - let mut client = SyncClient::connect( - "speedtest4.tele2.net", - "anonymous", - "anonymous@anonymous.com", - )?; - client.cwd("/upload/")?; +fn test_store_unique() -> Result<(), FtpError> { + let mut client = SyncClient::connect(&get_local_server_hostname(), "user", "user")?; + + client.cwd("/pub/example/")?; let file_data = b"Some data for you"; client.store_unique(file_data)?; @@ -124,8 +117,8 @@ fn external_store_unique() -> Result<(), FtpError> { } #[test] -fn external_system() -> Result<(), FtpError> { - let mut client = SyncClient::connect("test.rebex.net", "demo", "password")?; +fn test_system() -> Result<(), FtpError> { + let mut client = SyncClient::connect(&get_local_server_hostname(), "user", "user")?; // Should be Windows_NT but we don't need to check that.. // since we don't want to break tests if the server changes OS let _system_name = client.system()?; @@ -133,20 +126,6 @@ fn external_system() -> Result<(), FtpError> { Ok(()) } -#[test] -#[ignore] -fn external_ipv6() -> Result<(), FtpError> { - let mut client = SyncClient::connect( - "speedtest6.tele2.net", - "anonymous", - "anonymous@anonymous.com", - )?; - - let data = b"DATA"; - let file_path = "/upload/readyou.txt"; - client.store(file_path, data) -} - #[test] fn append() -> Result<(), FtpError> { lock_server(); @@ -163,9 +142,9 @@ fn rename_file() -> Result<(), FtpError> { lock_server(); let mut client = SyncClient::connect(&get_local_server_hostname(), "user", "user")?; if !client.list_names("/")?.contains(&"testfile".to_string()) { - client.store("testfile", b"DATA")?; + client.store("/testfile", b"DATA")?; } - client.rename_file("testfile", "testfile.txt")?; + client.rename_file("/testfile", "/testfile.txt")?; Ok(()) }