diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/http_funcs.rs | 199 | ||||
| -rw-r--r-- | tests/i2p_functions.rs | 101 | ||||
| -rw-r--r-- | tests/pkgtoolkit_funcs.rs | 193 | ||||
| -rw-r--r-- | tests/secondary_funcs.rs | 29 | ||||
| -rw-r--r-- | tests/shared.rs | 22 |
5 files changed, 544 insertions, 0 deletions
diff --git a/tests/http_funcs.rs b/tests/http_funcs.rs new file mode 100644 index 0000000..efbaa53 --- /dev/null +++ b/tests/http_funcs.rs @@ -0,0 +1,199 @@ +use mesk::pkgtoolkit::pkgtools::{Package, Archs}; +use mesk::net::http_package::HTTPPackage; +use std::fs; + +mod shared; +use shared::create_test_config; + +use std::collections::HashMap; +use tempfile::TempDir; +use tokio; + +// Add these imports for logging +use log::{info, debug, error}; + +#[cfg(test)] +mod http_package_tests { + use super::*; + + // Helper function to initialize the logger for each test. + // This uses `call_once` to ensure it's only initialized once, + // even if called multiple times, preventing panics. + fn init_logger() { + let _ = env_logger::builder() + .is_test(true) + .try_init(); + } + + #[tokio::test] + async fn test_http_fetch_index_success() -> Result<(), Box<dyn std::error::Error>> { + init_logger(); // Initialize logger + info!("Starting test_http_fetch_index_success"); + + let mut server = mockito::Server::new_async().await; + let index_toml_content = r#" +[[packages]] +name = "test-pkg" +version = "1.0.0" +arch = "X86_64" +url = "/repo/test-pkg.mesk" +descr = "A test package from index" +license = "MIT" +"#; + + let temp_dir = TempDir::new()?; + let index_toml_path = temp_dir.path().join("INDEX.toml"); + fs::write(&index_toml_path, index_toml_content)?; + let archive_path = temp_dir.path().join("INDEX.tar.gz"); + + // Создаём архив + let file = fs::File::create(&archive_path)?; + let gz_encoder = flate2::write::GzEncoder::new(file, flate2::Compression::default()); + let mut tar_builder = tar::Builder::new(gz_encoder); + tar_builder.append_path_with_name(&index_toml_path, "INDEX.toml")?; + tar_builder.into_inner()?.finish()?; + + let mock_body = fs::read(&archive_path)?; + let _mock = server + .mock("GET", "/INDEX.tar.gz") + .with_status(200) + .with_header("content-length", &mock_body.len().to_string()) + .with_body(mock_body) + .create_async() + .await; + + let temp_config_dir = TempDir::new()?; + let config = create_test_config(temp_config_dir.path().to_str().unwrap()); + + let mut config_with_mock_url = config.clone(); + config_with_mock_url.repo.repo_url = server.url(); + + let mut http_pkg = HTTPPackage::new(config_with_mock_url); + + debug!("Attempting to fetch index via HTTP"); + let result = http_pkg.fetch_index_http().await; + + info!("Checking if fetch_index_http result is OK"); + assert!(result.is_ok(), "fetch_index_http should return Ok"); + + info!("Checking if fetch_index_http returned true"); + assert_eq!(result.unwrap(), true, "fetch_index_http should indicate success"); + + + info!("Checking if index_packages is populated"); + assert!(http_pkg.index_packages.is_some(), "index_packages should not be None after successful fetch"); + + let packages = http_pkg.index_packages.as_ref().unwrap(); + info!("Checking number of packages in the index"); + assert_eq!(packages.len(), 1, "There should be exactly one package in the index"); + + info!("Checking if 'test-pkg' exists in the index"); + assert!(packages.contains_key("test-pkg"), "The package 'test-pkg' should be present in the index"); + + let pkg_info = packages.get("test-pkg").unwrap(); + + info!("Checking if package URL is correctly formed"); + assert!(pkg_info.url.starts_with(&server.url()), "Package URL should be prefixed with the server URL"); + + Ok(()) + } + + #[tokio::test] + async fn test_http_fetch_index_http_error() -> Result<(), Box<dyn std::error::Error>> { + init_logger(); + info!("Starting test_http_fetch_index_http_error"); + + let mut server = mockito::Server::new_async().await; + let _mock = server + .mock("GET", "/INDEX.tar.gz") + .with_status(404) // Ошибка HTTP + .create_async() + .await; + + let temp_config_dir = TempDir::new()?; + let config = create_test_config(temp_config_dir.path().to_str().unwrap()); + let mut config_with_mock_url = config.clone(); + config_with_mock_url.repo.repo_url = server.url(); + + let mut http_pkg = HTTPPackage::new(config_with_mock_url); + + debug!("Attempting to fetch index with expected 404 error"); + let result = http_pkg.fetch_index_http().await; + + info!("Checking if fetch_index_http resulted in an error as expected"); + assert!(result.is_err(), "fetch_index_http should return an Err for a 404 response"); + + let err_msg = result.unwrap_err().to_string(); + info!("Verifying error message contains 'HTTP Error: 404'"); + assert!(err_msg.contains("HTTP Error: 404"), "Error message should contain 'HTTP Error: 404', got: {}", err_msg); + + Ok(()) + } + + #[tokio::test] + async fn test_http_fetch_package_info_success() -> Result<(), Box<dyn std::error::Error>> { + init_logger(); + info!("Starting test_http_fetch_package_info_success"); + + let temp_config_dir = TempDir::new()?; + let config = create_test_config(temp_config_dir.path().to_str().unwrap()); + + let mut http_pkg = HTTPPackage::new(config); + let mut packages_map = HashMap::new(); + let pkg = Package { + name: "test-pkg".to_string(), + version: "1.0.0".to_string(), + arch: Archs::X86_64, + descr: Some("Test".to_string()), + license: Some("MIT".to_string()), + url: "http://example.com/repo/test-pkg.mesk".to_string(), + }; + packages_map.insert("test-pkg".to_string(), pkg); + http_pkg.index_packages = Some(packages_map); + + debug!("Fetching package info for 'test-pkg'"); + let pkg_info = http_pkg.fetch_package_info("test-pkg"); + + info!("Checking if fetch_package_info returned successfully"); + assert!(pkg_info.is_ok(), "fetch_package_info should return Ok for an existing package"); + + info!("Checking the retrieved package name"); + assert_eq!(pkg_info.unwrap().name, "test-pkg", "Retrieved package name should be 'test-pkg'"); + + Ok(()) + } + + #[tokio::test] + async fn test_http_fetch_package_info_not_found() -> Result<(), Box<dyn std::error::Error>> { + init_logger(); + info!("Starting test_http_fetch_package_info_not_found"); + + let temp_config_dir = TempDir::new()?; + let config = create_test_config(temp_config_dir.path().to_str().unwrap()); + + let http_pkg = HTTPPackage::new(config.clone()); + debug!("Attempting to fetch package info before index load"); + let result = http_pkg.fetch_package_info("nonexistent-pkg"); + + info!("Checking if fetch_package_info failed due to unloaded index"); + assert!(result.is_err(), "fetch_package_info should fail when index is not loaded"); + + let err_msg = result.unwrap_err().to_string(); + info!("Verifying error message contains 'Index not loaded'"); + assert!(err_msg.contains("Index not loaded"), "Error message should contain 'Index not loaded', got: {}", err_msg); + + let mut http_pkg_empty_index = HTTPPackage::new(config); + http_pkg_empty_index.index_packages = Some(HashMap::new()); + debug!("Attempting to fetch package info from an empty index"); + let result_empty = http_pkg_empty_index.fetch_package_info("nonexistent-pkg"); + + info!("Checking if fetch_package_info failed due to missing package in index"); + assert!(result_empty.is_err(), "fetch_package_info should fail for a package not in the index"); + + let err_msg_empty = result_empty.unwrap_err().to_string(); + info!("Verifying error message contains 'not found in index'"); + assert!(err_msg_empty.contains("not found in index"), "Error message should contain 'not found in index', got: {}", err_msg_empty); + + Ok(()) + } +}
\ No newline at end of file diff --git a/tests/i2p_functions.rs b/tests/i2p_functions.rs new file mode 100644 index 0000000..6b24d14 --- /dev/null +++ b/tests/i2p_functions.rs @@ -0,0 +1,101 @@ +use mesk::pkgtoolkit::pkgtools::{Package, Archs}; +use mesk::net::i2p_package::I2PPackage; + +mod shared; +use shared::create_test_config; + +use std::collections::HashMap; +use tempfile::TempDir; +use tokio; + +#[cfg(test)] +mod i2p_package_tests { + use super::*; + + // fn parse_http_response(response_bytes: &[u8]) -> Result<(u16, &[u8]), Box<dyn std::error::Error>> { ... } + // #[test] + // fn test_parse_http_response() { ... } + /* + #[tokio::test] + async fn test_i2p_fetch_index_success() -> Result<(), Box<dyn std::error::Error>> { + let temp_config_dir = TempDir::new()?; + let config = create_test_config(temp_config_dir.path().to_str().unwrap()); + let mut config_with_mock_url = config.clone(); + config_with_mock_url.repo.repo_url = "http://dummy.i2p/repo"; + + let mut mock_session = MockSession::new(); + mock_session + .expect_connect() + .with(eq("dummy.i2p")) + .returning(|_| { + // Возвращаем мок-поток, который возвращает байты архива + let index_toml_content = r#"[[packages]] name = "test-pkg" ... "#; + let mut archive_data = Vec::new(); + // ... заполняем archive_data как в test_http_fetch_index_success ... + let response_body = format!( + "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}", + archive_data.len(), + std::str::from_utf8(&archive_data).unwrap() + ).into_bytes(); + Ok(MockStream::new(response_body)) + }); + + + let mut i2p_pkg = I2PPackage::new_with_session(config_with_mock_url, Box::new(mock_session)); + + let result = i2p_pkg.fetch_index().await; + + assert!(result.is_ok()); + + Ok(()) + } + */ + #[tokio::test] + async fn test_i2p_fetch_package_info_success() -> Result<(), Box<dyn std::error::Error>> { + let temp_config_dir = TempDir::new()?; + let config = create_test_config(temp_config_dir.path().to_str().unwrap()); + + let mut i2p_pkg = I2PPackage::new(config); + let mut packages_map = HashMap::new(); + let pkg = Package { + name: "test-pkg".to_string(), + version: "1.0.0".to_string(), + arch: Archs::X86_64, + descr: Some("Test".to_string()), + license: Some("MIT".to_string()), + url: "http://example.i2p/repo/test-pkg.mesk".to_string(), + }; + packages_map.insert("test-pkg".to_string(), pkg); + i2p_pkg.index_packages = Some(packages_map); + + let pkg_info = i2p_pkg.fetch_package_info("test-pkg"); + + assert!(pkg_info.is_ok()); + assert_eq!(pkg_info.unwrap().name, "test-pkg"); + + Ok(()) + } + + #[tokio::test] + async fn test_i2p_fetch_package_info_not_found() -> Result<(), Box<dyn std::error::Error>> { + let temp_config_dir = TempDir::new()?; + let config = create_test_config(temp_config_dir.path().to_str().unwrap()); + + let i2p_pkg = I2PPackage::new(config.clone()); // index_packages = None + let result = i2p_pkg.fetch_package_info("nonexistent-pkg"); + + assert!(result.is_err()); + let err_msg = result.unwrap_err().to_string(); + assert!(err_msg.contains("Index not loaded")); + + let mut i2p_pkg_empty_index = I2PPackage::new(config); + i2p_pkg_empty_index.index_packages = Some(HashMap::new()); + let result_empty = i2p_pkg_empty_index.fetch_package_info("nonexistent-pkg"); + + assert!(result_empty.is_err()); + let err_msg_empty = result_empty.unwrap_err().to_string(); + assert!(err_msg_empty.contains("not found in index")); + + Ok(()) + } +} diff --git a/tests/pkgtoolkit_funcs.rs b/tests/pkgtoolkit_funcs.rs new file mode 100644 index 0000000..ae0c4d7 --- /dev/null +++ b/tests/pkgtoolkit_funcs.rs @@ -0,0 +1,193 @@ +use mesk::pkgtoolkit::pkgtools::{Package, Archs}; + + +mod shared; +use shared::create_test_config; + +use tempfile::TempDir; +use tokio; + + +// Pkg toolkit tests +#[cfg(test)] +mod package_tests { + use super::*; + use std::fs; + use std::io::Write; + + #[test] + fn test_archs_as_str() { + assert_eq!(Archs::X86_64.as_str(), "x86_64"); + assert_eq!(Archs::Aarch64.as_str(), "aarch64"); + assert_eq!(Archs::X86.as_str(), "x86"); + assert_eq!(Archs::ArmV7.as_str(), "armv7"); + assert_eq!(Archs::ArmV8.as_str(), "armv8"); + } + + #[tokio::test] + async fn test_extract_archive() -> Result<(), Box<dyn std::error::Error>> { + let temp_dir = TempDir::new()?; + let _config = create_test_config(temp_dir.path().to_str().unwrap()); + + + let test_file_content = "test content"; + let test_file_path = temp_dir.path().join("test_file.txt"); + fs::write(&test_file_path, test_file_content)?; + + let archive_path = temp_dir.path().join("test_archive.tar.gz"); + let file = fs::File::create(&archive_path)?; + let gz_encoder = flate2::write::GzEncoder::new(file, flate2::Compression::default()); + let mut tar_builder = tar::Builder::new(gz_encoder); + tar_builder.append_path_with_name(&test_file_path, "extracted_test_file.txt")?; + tar_builder.into_inner()?.finish()?; + + + Package::extract_archive(archive_path.to_str().unwrap())?; + + + let extracted_file_path = temp_dir.path().join("extracted_test_file.txt"); + assert!(extracted_file_path.exists()); + let content = fs::read_to_string(extracted_file_path)?; + assert_eq!(content, test_file_content); + + Ok(()) + } + + + #[tokio::test] + async fn test_package_check_valid() -> Result<(), Box<dyn std::error::Error>> { + let temp_dir = TempDir::new()?; + let _config = create_test_config(temp_dir.path().to_str().unwrap()); + + + let install_content = r#" +[package] +name = "test-pkg" +version = "1.0.0" +arch = "X86_64" # Используйте архитектуру хоста или измените для теста архитектуры +descr = "A test package" +license = "MIT" +url = "/repo/test-pkg.mesk" + +[install] +path = "/tmp/test_binary" +user = "root" +group = "root" +mode = "755" +"#; + let install_path = temp_dir.path().join("INSTALL"); + let mut install_file = fs::File::create(&install_path)?; + install_file.write_all(install_content.as_bytes())?; + + + let archive_path = temp_dir.path().join("test_pkg_with_install.tar.gz"); + let file = fs::File::create(&archive_path)?; + let gz_encoder = flate2::write::GzEncoder::new(file, flate2::Compression::default()); + let mut tar_builder = tar::Builder::new(gz_encoder); + tar_builder.append_path_with_name(&install_path, "INSTALL")?; + tar_builder.into_inner()?.finish()?; + + let result = Package::check(archive_path.to_str().unwrap().to_string()); + + assert!(result.is_ok()); + assert_eq!(result.unwrap(), true); + + Ok(()) + } + + + #[tokio::test] + async fn test_package_check_missing_install() -> Result<(), Box<dyn std::error::Error>> { + let temp_dir = TempDir::new()?; + + let archive_path = temp_dir.path().join("test_pkg_without_install.tar.gz"); + let file = fs::File::create(&archive_path)?; + let gz_encoder = flate2::write::GzEncoder::new(file, flate2::Compression::default()); + let mut tar_builder = tar::Builder::new(gz_encoder); + let dummy_path = temp_dir.path().join("dummy.txt"); + fs::write(&dummy_path, "dummy")?; + tar_builder.append_path_with_name(&dummy_path, "dummy.txt")?; + tar_builder.into_inner()?.finish()?; + + let result = Package::check(archive_path.to_str().unwrap().to_string()); + + assert!(result.is_err()); + let err = result.unwrap_err(); + assert_eq!(err.kind(), std::io::ErrorKind::NotFound); + assert!(err.to_string().contains("INSTALL file not found")); + + Ok(()) + } + + + #[tokio::test] + async fn test_package_check_empty_install() -> Result<(), Box<dyn std::error::Error>> { + let temp_dir = TempDir::new()?; + + let install_path = temp_dir.path().join("INSTALL"); + fs::write(&install_path, "")?; + let archive_path = temp_dir.path().join("test_pkg_with_empty_install.tar.gz"); + let file = fs::File::create(&archive_path)?; + let gz_encoder = flate2::write::GzEncoder::new(file, flate2::Compression::default()); + let mut tar_builder = tar::Builder::new(gz_encoder); + tar_builder.append_path_with_name(&install_path, "INSTALL")?; + tar_builder.into_inner()?.finish()?; + + + let result = Package::check(archive_path.to_str().unwrap().to_string()); + + assert!(result.is_err()); + let err = result.unwrap_err(); + assert_eq!(err.kind(), std::io::ErrorKind::InvalidData); + assert!(err.to_string().contains("INSTALL file is empty")); + + Ok(()) + } + + + #[tokio::test] + async fn test_package_check_arch_mismatch() -> Result<(), Box<dyn std::error::Error>> { + let temp_dir = TempDir::new()?; + let _config = create_test_config(temp_dir.path().to_str().unwrap()); + + let host_arch = std::env::consts::ARCH; + let wrong_arch = if host_arch == "x86" { "x86_64" } else { "x86" }; + let install_content = format!(r#" +[package] +name = "test-pkg" +version = "1.0.0" +arch = "{}" +descr = "A test package for arch mismatch" +license = "MIT" +url = "/repo/test-pkg.mesk" + +[install] +path = "/tmp/test_binary" +user = "root" +group = "root" +mode = "755" +"#, wrong_arch); + + let install_path = temp_dir.path().join("INSTALL"); + let mut install_file = fs::File::create(&install_path)?; + install_file.write_all(install_content.as_bytes())?; + + let archive_path = temp_dir.path().join("test_pkg_with_wrong_arch.tar.gz"); + let file = fs::File::create(&archive_path)?; + let gz_encoder = flate2::write::GzEncoder::new(file, flate2::Compression::default()); + let mut tar_builder = tar::Builder::new(gz_encoder); + tar_builder.append_path_with_name(&install_path, "INSTALL")?; + tar_builder.into_inner()?.finish()?; + + let result = Package::check(archive_path.to_str().unwrap().to_string()); + + + assert!(result.is_err()); + let err = result.unwrap_err(); + assert_eq!(err.kind(), std::io::ErrorKind::InvalidData); + assert!(err.to_string().contains("Arch mismatch")); + + Ok(()) + } + +}
\ No newline at end of file diff --git a/tests/secondary_funcs.rs b/tests/secondary_funcs.rs new file mode 100644 index 0000000..84034d8 --- /dev/null +++ b/tests/secondary_funcs.rs @@ -0,0 +1,29 @@ +// use mesk::cfg::config::Config; +// use toml; + +/* +fn create_test_config(temp_dir_path: &str) -> Config { + /* + #[derive(Deserialize, Debug, Clone)] + pub struct Config { + pub repo: RepoConfig, + pub paths: PathConfig, + ... + } + + #[derive(Deserialize, Debug, Clone)] + pub struct RepoConfig { + pub repo_url: String, + } + + #[derive(Deserialize, Debug, Clone)] + pub struct PathConfig { + pub cache_dir: String, + ... + } + */ + let cfg = Config::default().unwrap(); + assert!(toml::to_string(&cfg).is_ok()); + cfg +} +*/
\ No newline at end of file diff --git a/tests/shared.rs b/tests/shared.rs new file mode 100644 index 0000000..2ea0bf5 --- /dev/null +++ b/tests/shared.rs @@ -0,0 +1,22 @@ +use mesk::cfg::config::{Config, Repo, Log, Loglevel, Paths}; + +pub fn create_test_config(temp_dir_path: &str) -> Config { + let cfg: Config = Config { + repo: Repo { + repo_url: format!(r"http://mesk.anthrill.i2p/repo/{}", std::env::consts::ARCH), + auto_update: true, + destination: (String::from("mesk"), String::from("mesk")), + repo_http_url: None, + }, + log: Log { + log_file: String::from("/var/log/mesk.log"), + log_level: Loglevel::Info, + }, + paths: Paths { + cache_dir: String::from(temp_dir_path), + build_dir: String::from(format!("{}/build", String::from(temp_dir_path))) + }, + }; + + cfg +}
\ No newline at end of file |
