summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorNamilskyy <alive6863@gmail.com>2025-12-01 14:06:10 +0300
committerNamilskyy <alive6863@gmail.com>2025-12-01 14:06:10 +0300
commit068eea55e0612184151461e64633b3dc18e53490 (patch)
treed3e20aea860a88e2b50ad3d35ddbd8792a1e531e /tests
parent2029c2c09284d0228c0bce2977fdfa0ca8a8db06 (diff)
Implemented test suite, fixed some issues and added more modular structure into .woodpecker.yaml
Diffstat (limited to 'tests')
-rw-r--r--tests/http_funcs.rs199
-rw-r--r--tests/i2p_functions.rs101
-rw-r--r--tests/pkgtoolkit_funcs.rs193
-rw-r--r--tests/secondary_funcs.rs29
-rw-r--r--tests/shared.rs22
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