{
    "sourceFile": "crates/ggen-marketplace/tests/common/mod.rs",
    "activeCommit": 0,
    "commits": [
        {
            "activePatchIndex": 0,
            "patches": [
                {
                    "date": 1762979113849,
                    "content": "Index: \n===================================================================\n--- \n+++ \n"
                }
            ],
            "date": 1762979113849,
            "name": "Commit-0",
            "content": "//! Common Test Utilities\n//!\n//! Shared helper functions and test fixtures for ggen-marketplace tests.\n//! Follows the 80/20 principle: provide high-value helpers that eliminate boilerplate.\n\nuse ggen_marketplace::prelude::*;\nuse std::path::PathBuf;\nuse tempfile::TempDir;\n\n// ============================================================================\n// Registry Helpers\n// ============================================================================\n\n/// Create a local registry with temporary storage.\n/// Returns the registry and the temp directory (keep it alive for test duration).\npub async fn setup_local_registry() -> (LocalRegistry, TempDir) {\n    let temp_dir = tempfile::tempdir().expect(\"failed to create temp dir\");\n    let db_path = temp_dir.path().join(\"registry\");\n    let registry = LocalRegistry::new(db_path)\n        .await\n        .expect(\"failed to create registry\");\n    (registry, temp_dir)\n}\n\n/// Create a centralized registry pointing to a test URL.\n/// Note: This doesn't start a real server - use for testing error paths.\npub fn setup_centralized_registry(url: &str) -> CentralizedRegistry {\n    CentralizedRegistry::new(url).expect(\"failed to create centralized registry\")\n}\n\n// ============================================================================\n// Storage Helpers\n// ============================================================================\n\n/// Create a filesystem store with temporary storage.\n/// Returns the store and the temp directory (keep it alive for test duration).\npub async fn setup_filesystem_store() -> (FilesystemStore, TempDir) {\n    let temp_dir = tempfile::tempdir().expect(\"failed to create temp dir\");\n    let storage_path = temp_dir.path().join(\"storage\");\n    let store = FilesystemStore::new(storage_path)\n        .await\n        .expect(\"failed to create storage\");\n    (store, temp_dir)\n}\n\n/// Create an in-memory store for fast testing.\npub fn setup_memory_store() -> MemoryStore {\n    MemoryStore::new()\n}\n\n// ============================================================================\n// Package Builders\n// ============================================================================\n\n/// Create a test package with sensible defaults.\n///\n/// # Arguments\n/// * `name` - Package name (namespace will be \"test\")\n/// * `version` - Version string (e.g., \"1.0.0\")\n///\n/// # Example\n/// ```\n/// let pkg = create_test_package(\"my-package\", \"1.0.0\")?;\n/// ```\n/// Create a validated test package for use in tests.\n///\n/// **Root Cause Fix**: Returns validated Package instead of UnvalidatedPackage.\n/// This prevents tests from accessing fields directly without validation.\n///\n/// # Example\n/// ```\n/// let pkg = create_test_package(\"my-package\", \"1.0.0\")?;\n/// ```\npub fn create_test_package(name: &str, version: &str) -> Result<Package> {\n    let version_parts: Vec<&str> = version.split('.').collect();\n    let major = version_parts[0].parse().unwrap_or(1);\n    let minor = version_parts.get(1).and_then(|v| v.parse().ok()).unwrap_or(0);\n    let patch = version_parts.get(2).and_then(|v| v.parse().ok()).unwrap_or(0);\n\n    let unvalidated = Package::builder(\n        PackageId::new(\"test\", name),\n        Version::new(major, minor, patch),\n    )\n    .title(format!(\"Test Package {}\", name))\n    .description(format!(\"Test description for {}\", name))\n    .license(\"MIT\")\n    .tag(\"test\")\n    .content_id(ContentId::new(\n        format!(\"hash_{}\", name),\n        HashAlgorithm::Sha256,\n    ))\n    .build()?;\n    \n    // Validate package before returning (Poka-yoke: ensures package meets requirements)\n    let validated = unvalidated.validate()?;\n    Ok(validated.package().clone())\n}\n\n/// Create a test package with custom metadata.\n///\n/// # Example\n/// ```\n/// let pkg = create_custom_package(\n///     \"my-package\",\n///     \"1.0.0\",\n///     \"Custom Title\",\n///     \"Custom description\",\n///     \"Apache-2.0\",\n/// )?;\n/// ```\npub fn create_custom_package(\n    name: &str,\n    version: &str,\n    title: &str,\n    description: &str,\n    license: &str,\n) -> Result<Package> {\n    let version_parts: Vec<&str> = version.split('.').collect();\n    let major = version_parts[0].parse().unwrap_or(1);\n    let minor = version_parts.get(1).and_then(|v| v.parse().ok()).unwrap_or(0);\n    let patch = version_parts.get(2).and_then(|v| v.parse().ok()).unwrap_or(0);\n\n    Package::builder(\n        PackageId::new(\"test\", name),\n        Version::new(major, minor, patch),\n    )\n    .title(title)\n    .description(description)\n    .license(license)\n    .content_id(ContentId::new(\n        format!(\"hash_{}_{}\", name, version),\n        HashAlgorithm::Sha256,\n    ))\n    .build()\n}\n\n/// Create multiple test packages at once.\n///\n/// # Example\n/// ```\n/// let packages = create_test_packages(&[\n///     (\"web-framework\", \"1.0.0\"),\n///     (\"cli-tool\", \"2.0.0\"),\n///     (\"database\", \"1.5.0\"),\n/// ])?;\n/// ```\npub fn create_test_packages(specs: &[(&str, &str)]) -> Result<Vec<Package>> {\n    specs\n        .iter()\n        .map(|(name, version)| create_test_package(name, version))\n        .collect()\n}\n\n// ============================================================================\n// Content Helpers\n// ============================================================================\n\n/// Generate test content of specified size.\npub fn generate_test_content(size: usize) -> Vec<u8> {\n    vec![0u8; size]\n}\n\n/// Generate test content with pattern (useful for detecting corruption).\npub fn generate_patterned_content(size: usize) -> Vec<u8> {\n    (0..size).map(|i| (i % 256) as u8).collect()\n}\n\n// ============================================================================\n// Assertion Helpers\n// ============================================================================\n\n/// Assert that two packages are equal (compares all fields).\npub fn assert_package_eq(actual: &Package, expected: &Package, context: &str) {\n    assert_eq!(actual.id, expected.id, \"{}: ID mismatch\", context);\n    assert_eq!(actual.version, expected.version, \"{}: Version mismatch\", context);\n    assert_eq!(\n        actual.metadata.title, expected.metadata.title,\n        \"{}: Title mismatch\", context\n    );\n    assert_eq!(\n        actual.metadata.description, expected.metadata.description,\n        \"{}: Description mismatch\", context\n    );\n    assert_eq!(\n        actual.metadata.license, expected.metadata.license,\n        \"{}: License mismatch\", context\n    );\n}\n\n/// Assert that a package matches expected values.\npub fn assert_package_has(\n    package: &Package,\n    expected_name: &str,\n    expected_version: &str,\n    context: &str,\n) {\n    assert_eq!(\n        package.id.name, expected_name,\n        \"{}: Name mismatch\", context\n    );\n\n    let expected_ver = parse_version(expected_version);\n    assert_eq!(\n        package.version, expected_ver,\n        \"{}: Version mismatch\", context\n    );\n}\n\n/// Parse version string into Version struct.\nfn parse_version(version_str: &str) -> Version {\n    let parts: Vec<&str> = version_str.split('.').collect();\n    let major = parts[0].parse().unwrap_or(0);\n    let minor = parts.get(1).and_then(|v| v.parse().ok()).unwrap_or(0);\n    let patch = parts.get(2).and_then(|v| v.parse().ok()).unwrap_or(0);\n    Version::new(major, minor, patch)\n}\n\n// ============================================================================\n// Test Fixtures\n// ============================================================================\n\n/// Standard test packages for use across tests.\npub struct TestFixtures {\n    pub packages: Vec<Package>,\n}\n\nimpl TestFixtures {\n    /// Create standard test fixtures with common packages.\n    pub fn new() -> Result<Self> {\n        let packages = create_test_packages(&[\n            (\"web-framework\", \"1.0.0\"),\n            (\"web-server\", \"1.5.0\"),\n            (\"cli-tool\", \"2.0.0\"),\n            (\"database\", \"1.0.0\"),\n            (\"logging\", \"0.5.0\"),\n        ])?;\n\n        Ok(Self { packages })\n    }\n\n    /// Get a package by name.\n    pub fn get(&self, name: &str) -> Option<&Package> {\n        self.packages.iter().find(|p| p.id.name == name)\n    }\n}\n\nimpl Default for TestFixtures {\n    fn default() -> Self {\n        Self::new().expect(\"failed to create test fixtures\")\n    }\n}\n\n// ============================================================================\n// Async Test Helpers\n// ============================================================================\n\n/// Publish multiple packages to a registry.\npub async fn publish_packages<R: Registry>(\n    registry: &R,\n    packages: &[Package],\n) -> Result<()> {\n    for package in packages {\n        registry.publish(package.clone()).await?;\n    }\n    Ok(())\n}\n\n/// Store multiple contents in a store, return their IDs.\npub async fn store_contents<S: PackageStore>(\n    store: &S,\n    contents: &[&[u8]],\n) -> Result<Vec<ContentId>> {\n    let mut ids = Vec::new();\n    for content in contents {\n        let id = store.store(content).await?;\n        ids.push(id);\n    }\n    Ok(ids)\n}\n\n// ============================================================================\n// Performance Helpers\n// ============================================================================\n\nuse std::time::{Duration, Instant};\n\n/// Measure execution time of an async operation.\n///\n/// # Example\n/// ```\n/// let elapsed = measure_async(|| async {\n///     registry.search(&Query::new(\"test\")).await\n/// }).await;\n///\n/// assert!(elapsed < Duration::from_millis(100), \"Too slow\");\n/// ```\npub async fn measure_async<F, Fut, T>(f: F) -> Duration\nwhere\n    F: FnOnce() -> Fut,\n    Fut: std::future::Future<Output = T>,\n{\n    let start = Instant::now();\n    let _ = f().await;\n    start.elapsed()\n}\n\n/// Assert that an async operation completes within a time limit.\npub async fn assert_fast_async<F, Fut, T>(\n    f: F,\n    max_duration: Duration,\n    operation: &str,\n) -> T\nwhere\n    F: FnOnce() -> Fut,\n    Fut: std::future::Future<Output = T>,\n{\n    let start = Instant::now();\n    let result = f().await;\n    let elapsed = start.elapsed();\n\n    assert!(\n        elapsed <= max_duration,\n        \"{} took {:?}, expected <= {:?}\",\n        operation,\n        elapsed,\n        max_duration\n    );\n\n    result\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[tokio::test]\n    async fn test_helper_setup_local_registry() {\n        let (registry, _temp) = setup_local_registry().await;\n        // Should be able to search immediately\n        let result = registry.search(&Query::new(\"test\")).await;\n        assert!(result.is_ok());\n    }\n\n    #[tokio::test]\n    async fn test_helper_create_package() {\n        let pkg = create_test_package(\"example\", \"1.2.3\").unwrap();\n        assert_eq!(pkg.id.name, \"example\");\n        assert_eq!(pkg.version, Version::new(1, 2, 3));\n    }\n\n    #[test]\n    fn test_helper_fixtures() {\n        let fixtures = TestFixtures::new().unwrap();\n        assert_eq!(fixtures.packages.len(), 5);\n        assert!(fixtures.get(\"web-framework\").is_some());\n    }\n}\n"
        }
    ]
}