ips/libips/src/repository/tests.rs

537 lines
19 KiB
Rust
Raw Normal View History

// This Source Code Form is subject to the terms of
// the Mozilla Public License, v. 2.0. If a copy of the
// MPL was not distributed with this file, You can
// obtain one at https://mozilla.org/MPL/2.0/.
#[cfg(test)]
mod tests {
use crate::actions::Manifest;
use crate::fmri::Fmri;
use crate::repository::{
CatalogManager, FileBackend, ReadableRepository, RepositoryError, RepositoryVersion,
Result, WritableRepository, REPOSITORY_CONFIG_FILENAME,
};
use std::fs;
use std::path::PathBuf;
use std::process::Command;
// The base directory for all test repositories
const TEST_REPO_BASE_DIR: &str = "/tmp/libips_repo_test";
// Helper function to create a unique test directory
fn create_test_dir(test_name: &str) -> PathBuf {
let test_dir = PathBuf::from(format!("{}/{}", TEST_REPO_BASE_DIR, test_name));
// Clean up any existing directory
if test_dir.exists() {
fs::remove_dir_all(&test_dir).unwrap();
}
// Create the directory
fs::create_dir_all(&test_dir).unwrap();
test_dir
}
// Helper function to clean up test directory
fn cleanup_test_dir(test_dir: &PathBuf) {
if test_dir.exists() {
fs::remove_dir_all(test_dir).unwrap();
}
}
// Helper function to run the setup script
fn run_setup_script() -> (PathBuf, PathBuf) {
// Run the xtask setup-test-env command
let output = Command::new("cargo")
.args(["run", "-p", "xtask", "--", "setup-test-env"])
.output()
.expect("Failed to run xtask setup-test-env");
if !output.status.success() {
panic!(
"Failed to set up test environment: {}",
String::from_utf8_lossy(&output.stderr)
);
}
// Return the paths to the prototype and manifest directories
(
PathBuf::from("/tmp/pkg6_test/prototype"),
PathBuf::from("/tmp/pkg6_test/manifests"),
)
}
2025-07-26 12:54:01 +02:00
// Helper function to publish a package to a repository
fn publish_package(
repo: &mut FileBackend,
manifest_path: &PathBuf,
prototype_dir: &PathBuf,
publisher: &str,
) -> Result<()> {
2025-07-26 12:54:01 +02:00
println!(
"Publishing package from manifest: {}",
manifest_path.display()
);
println!("Prototype directory: {}", prototype_dir.display());
println!("Publisher: {}", publisher);
// Check if the manifest file exists
if !manifest_path.exists() {
println!("Error: Manifest file does not exist");
return Err(RepositoryError::FileReadError(format!(
"Manifest file does not exist: {}",
manifest_path.display()
)));
}
// Check if the prototype directory exists
if !prototype_dir.exists() {
println!("Error: Prototype directory does not exist");
return Err(RepositoryError::NotFound(format!(
"Prototype directory does not exist: {}",
prototype_dir.display()
)));
}
// Parse the manifest file
println!("Parsing manifest file...");
let manifest = Manifest::parse_file(manifest_path)?;
2025-07-26 12:54:01 +02:00
println!(
"Manifest parsed successfully. Files: {}",
manifest.files.len()
);
// Begin a transaction
println!("Beginning transaction...");
let mut transaction = repo.begin_transaction()?;
// Add files from the prototype directory to the transaction
println!("Adding files to transaction...");
for file_action in manifest.files.iter() {
// Construct the full path to the file in the prototype directory
let file_path = prototype_dir.join(&file_action.path);
2025-07-26 12:54:01 +02:00
// Check if the file exists
if !file_path.exists() {
2025-07-26 12:54:01 +02:00
println!(
"Warning: File does not exist in prototype directory: {}",
file_path.display()
);
continue;
}
2025-07-26 12:54:01 +02:00
// Add the file to the transaction
println!("Adding file: {}", file_action.path);
transaction.add_file(file_action.clone(), &file_path)?;
}
// Update the manifest in the transaction
println!("Updating manifest in transaction...");
transaction.update_manifest(manifest);
// Set the publisher for the transaction
println!("Setting publisher: {}", publisher);
transaction.set_publisher(publisher);
// Commit the transaction
println!("Committing transaction...");
transaction.commit()?;
println!("Transaction committed successfully");
2025-07-26 12:54:01 +02:00
// Debug: Check if the package manifest was stored in the correct location
let publisher_pkg_dir = FileBackend::construct_package_dir(&repo.path, publisher, "");
2025-07-26 12:54:01 +02:00
println!(
"Publisher package directory: {}",
publisher_pkg_dir.display()
);
if publisher_pkg_dir.exists() {
println!("Publisher directory exists");
2025-07-26 12:54:01 +02:00
// List files in the publisher directory
if let Ok(entries) = std::fs::read_dir(&publisher_pkg_dir) {
println!("Files in publisher directory:");
for entry in entries.flatten() {
println!(" {}", entry.path().display());
}
} else {
println!("Failed to read publisher directory");
}
} else {
println!("Publisher directory does not exist");
}
// Rebuild the catalog
println!("Rebuilding catalog...");
repo.rebuild(Some(publisher), false, false)?;
println!("Catalog rebuilt successfully");
Ok(())
}
#[test]
fn test_create_repository() {
// Create a test directory
let test_dir = create_test_dir("create_repository");
let repo_path = test_dir.join("repo");
// Create a repository
let _repo = FileBackend::create(&repo_path, RepositoryVersion::V4).unwrap();
// Check that the repository was created
assert!(repo_path.exists());
assert!(repo_path.join("publisher").exists());
assert!(repo_path.join("index").exists());
assert!(repo_path.join("trans").exists());
assert!(repo_path.join(REPOSITORY_CONFIG_FILENAME).exists());
// Clean up
cleanup_test_dir(&test_dir);
}
#[test]
fn test_add_publisher() {
// Create a test directory
let test_dir = create_test_dir("add_publisher");
let repo_path = test_dir.join("repo");
// Create a repository
let mut repo = FileBackend::create(&repo_path, RepositoryVersion::V4).unwrap();
// Add a publisher
repo.add_publisher("example.com").unwrap();
// Check that the publisher was added
assert!(repo.config.publishers.contains(&"example.com".to_string()));
assert!(FileBackend::construct_catalog_path(&repo_path, "example.com").exists());
assert!(FileBackend::construct_package_dir(&repo_path, "example.com", "").exists());
// Check that the pub.p5i file was created for backward compatibility
let pub_p5i_path = repo_path.join("publisher").join("example.com").join("pub.p5i");
assert!(pub_p5i_path.exists(), "pub.p5i file should be created for backward compatibility");
// Verify the content of the pub.p5i file
let pub_p5i_content = fs::read_to_string(&pub_p5i_path).unwrap();
let pub_p5i_json: serde_json::Value = serde_json::from_str(&pub_p5i_content).unwrap();
// Check the structure of the pub.p5i file
assert_eq!(pub_p5i_json["version"], 1);
assert!(pub_p5i_json["packages"].is_array());
assert!(pub_p5i_json["publishers"].is_array());
assert_eq!(pub_p5i_json["publishers"][0]["name"], "example.com");
// Clean up
cleanup_test_dir(&test_dir);
}
#[test]
fn test_catalog_manager() {
// Create a test directory
let test_dir = create_test_dir("catalog_manager");
let publisher_dir = test_dir.join("publisher");
let publisher_name = "test";
let catalog_dir = publisher_dir.join(publisher_name).join("catalog");
// Create the catalog directory
fs::create_dir_all(&catalog_dir).unwrap();
// Create a catalog manager with the publisher parameter
let mut catalog_manager = CatalogManager::new(&publisher_dir, publisher_name).unwrap();
// Create a catalog part
catalog_manager.create_part("test_part");
// Add a package to the part using the stored publisher
let fmri = Fmri::parse("pkg://test/example@1.0.0").unwrap();
catalog_manager.add_package_to_part("test_part", &fmri, None, None).unwrap();
// Save the part
catalog_manager.save_part("test_part").unwrap();
// Check that the part was saved
assert!(catalog_dir.join("test_part").exists());
// Create a new catalog manager and load the part
let mut new_catalog_manager = CatalogManager::new(&publisher_dir, publisher_name).unwrap();
new_catalog_manager.load_part("test_part").unwrap();
// Check that the part was loaded
let loaded_part = new_catalog_manager.get_part("test_part").unwrap();
assert_eq!(loaded_part.packages.len(), 1);
// Clean up
cleanup_test_dir(&test_dir);
}
#[test]
fn test_publish_files() {
// Run the setup script to prepare the test environment
let (prototype_dir, manifest_dir) = run_setup_script();
// Create a test directory
let test_dir = create_test_dir("publish_files");
let repo_path = test_dir.join("repo");
// Create a repository
let mut repo = FileBackend::create(&repo_path, RepositoryVersion::V4).unwrap();
// Add a publisher
repo.add_publisher("test").unwrap();
// Publish a package using the manifest
let manifest_path = manifest_dir.join("example.p5m");
publish_package(&mut repo, &manifest_path, &prototype_dir, "test").unwrap();
// Check that the files were published in the publisher-specific directory
assert!(repo_path.join("publisher").join("test").join("file").exists());
2025-07-26 12:54:01 +02:00
// Get repository information
let repo_info = repo.get_info().unwrap();
2025-07-26 12:54:01 +02:00
// Check that the publisher information is correct
assert_eq!(repo_info.publishers.len(), 1);
let publisher_info = &repo_info.publishers[0];
assert_eq!(publisher_info.name, "test");
2025-07-26 12:54:01 +02:00
// Clean up
cleanup_test_dir(&test_dir);
}
#[test]
fn test_list_packages() {
// Run the setup script to prepare the test environment
let (prototype_dir, manifest_dir) = run_setup_script();
// Create a test directory
let test_dir = create_test_dir("list_packages");
let repo_path = test_dir.join("repo");
// Create a repository
let mut repo = FileBackend::create(&repo_path, RepositoryVersion::V4).unwrap();
// Add a publisher
repo.add_publisher("test").unwrap();
// Publish a package using the manifest
let manifest_path = manifest_dir.join("example.p5m");
publish_package(&mut repo, &manifest_path, &prototype_dir, "test").unwrap();
// List packages
let packages = repo.list_packages(Some("test"), None).unwrap();
2025-07-26 12:54:01 +02:00
// Check that packages were listed
assert!(!packages.is_empty());
2025-07-26 12:54:01 +02:00
// Check that the package name is correct
assert_eq!(packages[0].fmri.name, "example");
2025-07-26 12:54:01 +02:00
// Clean up
cleanup_test_dir(&test_dir);
}
#[test]
fn test_show_contents() {
// Run the setup script to prepare the test environment
let (prototype_dir, manifest_dir) = run_setup_script();
// Create a test directory
let test_dir = create_test_dir("show_contents");
let repo_path = test_dir.join("repo");
// Create a repository
let mut repo = FileBackend::create(&repo_path, RepositoryVersion::V4).unwrap();
// Add a publisher
repo.add_publisher("test").unwrap();
// Publish a package using the manifest
let manifest_path = manifest_dir.join("example.p5m");
publish_package(&mut repo, &manifest_path, &prototype_dir, "test").unwrap();
// Show contents
let contents = repo.show_contents(Some("test"), None, None).unwrap();
2025-07-26 12:54:01 +02:00
// Check that contents were shown
assert!(!contents.is_empty());
2025-07-26 12:54:01 +02:00
// Check that the contents include the expected files
let package_contents = &contents[0];
assert!(package_contents.files.is_some());
let files = package_contents.files.as_ref().unwrap();
2025-07-26 12:54:01 +02:00
// Check for specific files
assert!(files.iter().any(|f| f.contains("usr/bin/hello")));
2025-07-26 12:54:01 +02:00
assert!(files
.iter()
.any(|f| f.contains("usr/share/doc/example/README.txt")));
assert!(files.iter().any(|f| f.contains("etc/config/example.conf")));
2025-07-26 12:54:01 +02:00
// Clean up
cleanup_test_dir(&test_dir);
}
#[test]
fn test_search() {
// Run the setup script to prepare the test environment
let (prototype_dir, manifest_dir) = run_setup_script();
// Create a test directory
let test_dir = create_test_dir("search");
let repo_path = test_dir.join("repo");
// Create a repository
let mut repo = FileBackend::create(&repo_path, RepositoryVersion::V4).unwrap();
// Add a publisher
repo.add_publisher("test").unwrap();
// Publish a package using the manifest
let manifest_path = manifest_dir.join("example.p5m");
publish_package(&mut repo, &manifest_path, &prototype_dir, "test").unwrap();
// Build the search index
repo.rebuild(Some("test"), false, false).unwrap();
// Search for packages
let results = repo.search("example", Some("test"), None).unwrap();
2025-07-26 12:54:01 +02:00
// Check that search results were returned
assert!(!results.is_empty());
2025-07-26 12:54:01 +02:00
// Check that the package name is correct
assert_eq!(results[0].fmri.name, "example");
2025-07-26 12:54:01 +02:00
// Clean up
cleanup_test_dir(&test_dir);
}
#[test]
fn test_file_structure() {
// Create a test directory
let test_dir = create_test_dir("file_structure");
let repo_path = test_dir.join("repo");
// Create a repository
let mut repo = FileBackend::create(&repo_path, RepositoryVersion::V4).unwrap();
// Add a publisher
repo.add_publisher("test").unwrap();
// Create a test file
let test_file_path = test_dir.join("test_file.txt");
fs::write(&test_file_path, "This is a test file").unwrap();
// Store the file in the repository
let hash = repo.store_file(&test_file_path, "test").unwrap();
// Check if the file was stored in the correct directory structure
let expected_path = FileBackend::construct_file_path_with_publisher(&repo_path, "test", &hash);
// Verify that the file exists at the expected path
assert!(
expected_path.exists(),
"File was not stored at the expected path: {}",
expected_path.display()
);
// Verify that the file does NOT exist at the old path (with no directory prefixing)
let old_path = repo_path.join("file").join(&hash);
assert!(
!old_path.exists(),
"File was stored at the old path: {}",
old_path.display()
);
// Clean up
cleanup_test_dir(&test_dir);
}
#[test]
fn test_transaction_pub_p5i_creation() {
// Run the setup script to prepare the test environment
let (prototype_dir, manifest_dir) = run_setup_script();
// Create a test directory
let test_dir = create_test_dir("transaction_pub_p5i");
let repo_path = test_dir.join("repo");
// Create a repository
let mut repo = FileBackend::create(&repo_path, RepositoryVersion::V4).unwrap();
// Create a new publisher through a transaction
let publisher = "transaction_test";
// Start a transaction
let mut transaction = repo.begin_transaction().unwrap();
// Set the publisher for the transaction
transaction.set_publisher(publisher);
// Add a simple manifest to the transaction
let manifest_path = manifest_dir.join("example.p5m");
let manifest = Manifest::parse_file(&manifest_path).unwrap();
transaction.update_manifest(manifest);
// Commit the transaction
transaction.commit().unwrap();
// Check that the pub.p5i file was created for the new publisher
let pub_p5i_path = repo_path.join("publisher").join(publisher).join("pub.p5i");
assert!(pub_p5i_path.exists(), "pub.p5i file should be created for new publisher in transaction");
// Verify the content of the pub.p5i file
let pub_p5i_content = fs::read_to_string(&pub_p5i_path).unwrap();
let pub_p5i_json: serde_json::Value = serde_json::from_str(&pub_p5i_content).unwrap();
// Check the structure of the pub.p5i file
assert_eq!(pub_p5i_json["version"], 1);
assert!(pub_p5i_json["packages"].is_array());
assert!(pub_p5i_json["publishers"].is_array());
assert_eq!(pub_p5i_json["publishers"][0]["name"], publisher);
// Clean up
cleanup_test_dir(&test_dir);
}
#[test]
fn test_legacy_pkg5_repository_creation() {
// Create a test directory
let test_dir = create_test_dir("legacy_pkg5_repository");
let repo_path = test_dir.join("repo");
// Create a repository
let mut repo = FileBackend::create(&repo_path, RepositoryVersion::V4).unwrap();
// Add a publisher
let publisher = "openindiana.org";
repo.add_publisher(publisher).unwrap();
// Set as default publisher
repo.set_default_publisher(publisher).unwrap();
// Check that the pkg5.repository file was created
let pkg5_repo_path = repo_path.join("pkg5.repository");
assert!(pkg5_repo_path.exists(), "pkg5.repository file should be created for backward compatibility");
// Verify the content of the pkg5.repository file
let pkg5_content = fs::read_to_string(&pkg5_repo_path).unwrap();
// Print the content for debugging
println!("pkg5.repository content:\n{}", pkg5_content);
// Check that the file contains the expected sections and values
assert!(pkg5_content.contains("[publisher]"));
assert!(pkg5_content.contains("prefix=openindiana.org"));
assert!(pkg5_content.contains("[repository]"));
assert!(pkg5_content.contains("version=4"));
assert!(pkg5_content.contains("trust-anchor-directory=/etc/certs/CA/"));
assert!(pkg5_content.contains("signature-required-names=[]"));
assert!(pkg5_content.contains("check-certificate-revocation=False"));
assert!(pkg5_content.contains("[CONFIGURATION]"));
// Clean up
cleanup_test_dir(&test_dir);
}
2025-07-26 12:54:01 +02:00
}