From 9ba86685c3c0d122bc02ec585bf1cae21ea2007b Mon Sep 17 00:00:00 2001 From: Abdul Munif Hanafi Date: Wed, 25 Dec 2024 23:28:37 +0700 Subject: [PATCH] Add more tests --- http-client/tests/integration_test.rs | 180 ++++++++++++++++++++++++++ src/defaults.rs | 142 ++++++++++++++++++++ 2 files changed, 322 insertions(+) create mode 100644 http-client/tests/integration_test.rs diff --git a/http-client/tests/integration_test.rs b/http-client/tests/integration_test.rs new file mode 100644 index 0000000..ee69146 --- /dev/null +++ b/http-client/tests/integration_test.rs @@ -0,0 +1,180 @@ +use http_client::{HttpClient, HttpMethod}; +use std::time::Duration; + +const TEST_SERVER: &str = "https://httpbin.org"; +const HTTP_TEST_SERVER: &str = "http://httpbin.org"; + +#[test] +fn test_get_request() { + let client = HttpClient::new(TEST_SERVER); + let response = client.get("/get").unwrap(); + assert!(response.is_success()); + assert_eq!(response.status_code, 200); +} + +#[test] +fn test_post_request() { + let client = HttpClient::new(TEST_SERVER); + let body = b"test data"; + let response = client.post("/post", body).unwrap(); + assert!(response.is_success()); + assert_eq!(response.status_code, 200); +} + +#[test] +fn test_headers() { + let mut client = HttpClient::new(TEST_SERVER); + client.set_header("X-Custom-Header", "test-value"); + let response = client.get("/headers").unwrap(); + assert!(response.is_success()); + + // Convert response body to string and verify it contains our header + let body_str = String::from_utf8_lossy(&response.body); + assert!(body_str.contains("X-Custom-Header")); + assert!(body_str.contains("test-value")); +} + +#[test] +fn test_timeout() { + let mut client = HttpClient::new(TEST_SERVER); + client.set_timeout(Duration::from_secs(1)); + let result = client.get("/delay/2"); + assert!(result.is_err()); +} + +#[test] +fn test_basic_auth() { + let mut client = HttpClient::new(TEST_SERVER); + client.set_auth("testuser", "testpass"); + let response = client.get("/basic-auth/testuser/testpass").unwrap(); + assert!(response.is_success()); + assert_eq!(response.status_code, 200); +} + +#[test] +fn test_redirect() { + let client = HttpClient::new(TEST_SERVER); + let response = client.get("/redirect/1").unwrap(); + assert!(response.is_success()); + assert_eq!(response.status_code, 200); +} + +#[test] +fn test_different_http_methods() { + let client = HttpClient::new(TEST_SERVER); + + // Test PUT + let put_response = client.put("/put", b"test data").unwrap(); + assert!(put_response.is_success()); + + // Test DELETE + let delete_response = client.delete("/delete").unwrap(); + assert!(delete_response.is_success()); + + // Test custom method (PATCH) + let patch_response = client + .request(HttpMethod::PATCH, "/patch", Some(b"test data")) + .unwrap(); + assert!(patch_response.is_success()); +} + +#[test] +fn test_error_responses() { + let client = HttpClient::new(TEST_SERVER); + + // Test 404 + let not_found = client.get("/status/404"); + assert!(not_found.unwrap().is_client_error()); + + // Test 500 + let server_error = client.get("/status/500"); + assert!(server_error.unwrap().is_server_error()); +} + +// Plain HTTP specific tests + +#[test] +fn test_plain_http_get() { + let client = HttpClient::new(HTTP_TEST_SERVER); + let response = client.get("/get").unwrap(); + assert!(response.is_success()); + assert_eq!(response.status_code, 200); + + // Verify we're using plain HTTP + let body_str = String::from_utf8_lossy(&response.body); + assert!(body_str.contains("\"url\": \"http://")); +} + +#[test] +fn test_plain_http_content_length() { + let client = HttpClient::new(HTTP_TEST_SERVER); + let response = client.get("/html").unwrap(); + assert!(response.is_success()); + assert_eq!(response.status_code, 200); + + // Verify we got HTML content + let body_str = String::from_utf8_lossy(&response.body); + assert!(body_str.contains("")); +} + +#[test] +fn test_plain_http_streaming() { + let client = HttpClient::new(HTTP_TEST_SERVER); + // Test with chunked transfer encoding + let response = client.get("/stream/5").unwrap(); + assert!(response.is_success()); + assert_eq!(response.status_code, 200); + + let body_str = String::from_utf8_lossy(&response.body); + // Verify we received all 5 chunks + assert_eq!(body_str.matches("\"id\": ").count(), 5); +} + +#[test] +fn test_plain_http_gzip() { + let mut client = HttpClient::new(HTTP_TEST_SERVER); + client.set_header("Accept-Encoding", "gzip"); + let response = client.get("/json").unwrap(); // Using /json instead of /gzip to avoid binary response + assert!(response.is_success()); + assert_eq!(response.status_code, 200); + + // Check if we got a valid JSON response + let body_str = String::from_utf8_lossy(&response.body); + assert!(body_str.contains("{")); // Simple check for JSON content +} + +#[test] +fn test_plain_http_with_query_params() { + let client = HttpClient::new(HTTP_TEST_SERVER); + let response = client.get("/get?param1=value1¶m2=value2").unwrap(); + assert!(response.is_success()); + + let body_str = String::from_utf8_lossy(&response.body); + assert!(body_str.contains("\"param1\": \"value1\"")); + assert!(body_str.contains("\"param2\": \"value2\"")); +} + +#[test] +fn test_plain_http_post_form() { + let mut client = HttpClient::new(HTTP_TEST_SERVER); + client.set_header("Content-Type", "application/x-www-form-urlencoded"); + let form_data = b"field1=value1&field2=value2"; + let response = client.post("/post", form_data).unwrap(); + assert!(response.is_success()); + + let body_str = String::from_utf8_lossy(&response.body); + assert!(body_str.contains("\"field1\": \"value1\"")); + assert!(body_str.contains("\"field2\": \"value2\"")); +} + +#[test] +fn test_plain_http_connection_reuse() { + let client = HttpClient::new(HTTP_TEST_SERVER); + + // Make multiple requests using the same client + for _ in 0..3 { + let response = client.get("/get").unwrap(); + assert!(response.is_success()); + assert_eq!(response.status_code, 200); + } +} diff --git a/src/defaults.rs b/src/defaults.rs index 1fbdda6..28f986c 100644 --- a/src/defaults.rs +++ b/src/defaults.rs @@ -423,3 +423,145 @@ impl UserData for Defaults { }); } } + +// Tests +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_defaults_new() { + let defaults = Defaults::new(); + + // Test default values + assert_eq!(*defaults.port.lock().unwrap(), 22); + assert_eq!(*defaults.user.lock().unwrap(), None); + assert_eq!(*defaults.private_key_file.lock().unwrap(), None); + assert_eq!(*defaults.private_key_pass.lock().unwrap(), None); + assert_eq!(*defaults.password.lock().unwrap(), None); + assert_eq!(*defaults.ignore_exit_code.lock().unwrap(), false); + assert_eq!(*defaults.elevate.lock().unwrap(), false); + assert_eq!(*defaults.elevation_method.lock().unwrap(), "sudo"); + assert_eq!(*defaults.as_user.lock().unwrap(), None); + assert_eq!(*defaults.host_key_check.lock().unwrap(), true); + + // Test default environment variables + let env = defaults.env.lock().unwrap(); + assert_eq!( + env.get("DEBIAN_FRONTEND"), + Some(&"noninteractive".to_string()) + ); + } + + #[test] + fn test_global_singleton() { + let defaults1 = Defaults::global(); + let defaults2 = Defaults::global(); + + // Modify a value using the first instance + *defaults1.port.lock().unwrap() = 2222; + + // Check if the change is reflected in the second instance + assert_eq!(*defaults2.port.lock().unwrap(), 2222); + } + + #[test] + fn test_lua_interface() -> mlua::Result<()> { + let lua = mlua::Lua::new(); + let defaults = Defaults::new(); + + // Register the defaults instance with Lua + lua.globals().set("defaults", defaults.clone())?; + + // Test port + lua.load("assert(defaults:get_port() == 22)").exec()?; + lua.load("defaults:set_port(2222)").exec()?; + lua.load("assert(defaults:get_port() == 2222)").exec()?; + + // Test user + lua.load("assert(defaults:get_user() == nil)").exec()?; + lua.load("defaults:set_user('testuser')").exec()?; + lua.load("assert(defaults:get_user() == 'testuser')") + .exec()?; + lua.load("defaults:set_user(nil)").exec()?; + lua.load("assert(defaults:get_user() == nil)").exec()?; + + // Test private key file + lua.load("assert(defaults:get_private_key_file() == nil)") + .exec()?; + lua.load("defaults:set_private_key_file('/path/to/key')") + .exec()?; + lua.load("assert(defaults:get_private_key_file() == '/path/to/key')") + .exec()?; + + // Test private key password + lua.load("assert(defaults:get_private_key_pass() == nil)") + .exec()?; + lua.load("defaults:set_private_key_pass('password123')") + .exec()?; + lua.load("assert(defaults:get_private_key_pass() == 'password123')") + .exec()?; + + // Test password + lua.load("assert(defaults:get_password() == nil)").exec()?; + lua.load("defaults:set_password('secret123')").exec()?; + lua.load("assert(defaults:get_password() == 'secret123')") + .exec()?; + + // Test ignore exit code + lua.load("assert(defaults:get_ignore_exit_code() == false)") + .exec()?; + lua.load("defaults:set_ignore_exit_code(true)").exec()?; + lua.load("assert(defaults:get_ignore_exit_code() == true)") + .exec()?; + + // Test elevate + lua.load("assert(defaults:get_elevate() == false)").exec()?; + lua.load("defaults:set_elevate(true)").exec()?; + lua.load("assert(defaults:get_elevate() == true)").exec()?; + + // Test elevation method + lua.load("assert(defaults:get_elevation_method() == 'sudo')") + .exec()?; + lua.load("defaults:set_elevation_method('doas')").exec()?; + lua.load("assert(defaults:get_elevation_method() == 'doas')") + .exec()?; + + // Test as user + lua.load("assert(defaults:get_as_user() == nil)").exec()?; + lua.load("defaults:set_as_user('root')").exec()?; + lua.load("assert(defaults:get_as_user() == 'root')") + .exec()?; + + // Test host key check + lua.load("assert(defaults:get_host_key_check() == true)") + .exec()?; + lua.load("defaults:set_host_key_check(false)").exec()?; + lua.load("assert(defaults:get_host_key_check() == false)") + .exec()?; + + // Test known hosts file + lua.load( + r#" + local known_hosts = defaults:get_known_hosts_file() + assert(known_hosts:match('/.ssh/known_hosts$') ~= nil) + defaults:set_known_hosts_file('/custom/known_hosts') + assert(defaults:get_known_hosts_file() == '/custom/known_hosts') + "#, + ) + .exec()?; + + // Test environment variables + lua.load("assert(defaults:get_env('TEST_ENV') == '')") + .exec()?; + lua.load("defaults:set_env('TEST_ENV', 'test_value')") + .exec()?; + lua.load("assert(defaults:get_env('TEST_ENV') == 'test_value')") + .exec()?; + lua.load("defaults:remove_env('TEST_ENV')").exec()?; + lua.load("assert(defaults:get_env('TEST_ENV') == '')") + .exec()?; + + Ok(()) + } +}