## test_variant_paths.nim ## Tests for variant path management ## Ensures proper path generation, validation, and parsing import std/[unittest, strutils] import ../src/nimpak/variant_paths import ../src/nimpak/variant_types suite "Path Generation Tests": test "Generate basic variant path": let path = generateVariantPath("nginx", "1.28.0", "blake2b-abc123def456") check path == "/Programs/nginx/1.28.0-blake2b-abc123def456" test "Generate path with different package": let path = generateVariantPath("firefox", "120.0", "blake2b-xyz789") check path == "/Programs/firefox/120.0-blake2b-xyz789" test "Generate path with complex version": let path = generateVariantPath("python", "3.11.5-rc1", "blake2b-aaa111") check path == "/Programs/python/3.11.5-rc1-blake2b-aaa111" test "Empty package name raises error": expect(ValueError): discard generateVariantPath("", "1.0.0", "blake2b-abc123") test "Empty version raises error": expect(ValueError): discard generateVariantPath("nginx", "", "blake2b-abc123") test "Empty fingerprint raises error": expect(ValueError): discard generateVariantPath("nginx", "1.0.0", "") suite "Path Validation Tests": test "Valid variant path passes validation": check validateVariantPath("/Programs/nginx/1.28.0-blake2b-abc123def456") == true test "Valid path with trailing slash": check validateVariantPath("/Programs/nginx/1.28.0-blake2b-abc123def456/") == true test "Invalid path without Programs": check validateVariantPath("/usr/local/nginx/1.28.0-blake2b-abc123") == false test "Invalid path without fingerprint": check validateVariantPath("/Programs/nginx/1.28.0") == false test "Invalid path with wrong fingerprint format": check validateVariantPath("/Programs/nginx/1.28.0-abc123") == false test "Empty path is invalid": check validateVariantPath("") == false test "Path with too few components is invalid": check validateVariantPath("/Programs/nginx") == false test "isValidVariantPath alias works": check isValidVariantPath("/Programs/nginx/1.28.0-blake2b-abc123") == true suite "Path Parsing Tests": test "Extract package name from path": let name = extractPackageNameFromPath("/Programs/nginx/1.28.0-blake2b-abc123/") check name == "nginx" test "Extract version from path": let version = extractVersionFromPath("/Programs/nginx/1.28.0-blake2b-abc123/") check version == "1.28.0" test "Extract fingerprint from path": let fp = extractFingerprintFromPath("/Programs/nginx/1.28.0-blake2b-abc123def456/") check fp == "blake2b-abc123def456" test "Extract from complex version": let version = extractVersionFromPath("/Programs/python/3.11.5-rc1-blake2b-xyz789/") check version == "3.11.5-rc1" test "Extract from path without trailing slash": let name = extractPackageNameFromPath("/Programs/firefox/120.0-blake2b-aaa111") check name == "firefox" test "Extract from invalid path raises error": expect(ValueError): discard extractPackageNameFromPath("/invalid/path") suite "Path Query Tests": test "Get variant base path": let basePath = getVariantBasePath("nginx") check basePath == "/Programs/nginx" test "Get variant bin path": let binPath = getVariantBinPath("/Programs/nginx/1.28.0-blake2b-abc123/") check binPath == "/Programs/nginx/1.28.0-blake2b-abc123/bin" test "Get variant lib path": let libPath = getVariantLibPath("/Programs/nginx/1.28.0-blake2b-abc123/") check libPath == "/Programs/nginx/1.28.0-blake2b-abc123/lib" test "Get variant include path": let incPath = getVariantIncludePath("/Programs/nginx/1.28.0-blake2b-abc123/") check incPath == "/Programs/nginx/1.28.0-blake2b-abc123/include" test "Get variant share path": let sharePath = getVariantSharePath("/Programs/nginx/1.28.0-blake2b-abc123/") check sharePath == "/Programs/nginx/1.28.0-blake2b-abc123/share" suite "Path Comparison Tests": test "Same variant paths are equal": let path1 = "/Programs/nginx/1.28.0-blake2b-abc123/" let path2 = "/Programs/nginx/1.28.0-blake2b-abc123/" check isSameVariant(path1, path2) == true test "Different fingerprints are not equal": let path1 = "/Programs/nginx/1.28.0-blake2b-abc123/" let path2 = "/Programs/nginx/1.28.0-blake2b-def456/" check isSameVariant(path1, path2) == false test "Compare variant paths by version": let path1 = "/Programs/nginx/1.27.0-blake2b-abc123/" let path2 = "/Programs/nginx/1.28.0-blake2b-abc123/" check compareVariantPaths(path1, path2) < 0 test "Compare variant paths by fingerprint": let path1 = "/Programs/nginx/1.28.0-blake2b-aaa111/" let path2 = "/Programs/nginx/1.28.0-blake2b-bbb222/" check compareVariantPaths(path1, path2) < 0 test "Compare identical paths": let path = "/Programs/nginx/1.28.0-blake2b-abc123/" check compareVariantPaths(path, path) == 0 suite "Path Utilities Tests": test "Normalize path adds trailing slash": let normalized = normalizeVariantPath("/Programs/nginx/1.28.0-blake2b-abc123") check normalized.endsWith("/") test "Normalize path adds leading slash": let normalized = normalizeVariantPath("Programs/nginx/1.28.0-blake2b-abc123") check normalized.startsWith("/") test "Normalize already normalized path": let path = "/Programs/nginx/1.28.0-blake2b-abc123/" let normalized = normalizeVariantPath(path) check normalized == path suite "VariantPathInfo Tests": test "Parse valid variant path": let info = parseVariantPath("/Programs/nginx/1.28.0-blake2b-abc123def456/") check info.isValid == true check info.packageName == "nginx" check info.version == "1.28.0" check info.fingerprint == "blake2b-abc123def456" test "Parse invalid variant path": let info = parseVariantPath("/invalid/path") check info.isValid == false test "String representation of valid path info": let info = parseVariantPath("/Programs/nginx/1.28.0-blake2b-abc123/") let str = $info check "nginx" in str check "1.28.0" in str test "String representation of invalid path info": let info = parseVariantPath("/invalid/path") let str = $info check "invalid" in str suite "Path Conflict Detection Tests": test "No conflicts in different packages": let paths = @[ "/Programs/nginx/1.28.0-blake2b-abc123/", "/Programs/firefox/120.0-blake2b-def456/" ] let conflicts = detectPathConflicts(paths) check conflicts.len == 0 test "No conflicts in different versions": let paths = @[ "/Programs/nginx/1.27.0-blake2b-abc123/", "/Programs/nginx/1.28.0-blake2b-abc123/" ] let conflicts = detectPathConflicts(paths) check conflicts.len == 0 test "Detect conflict in same package/version with different fingerprints": let paths = @[ "/Programs/nginx/1.28.0-blake2b-abc123/", "/Programs/nginx/1.28.0-blake2b-def456/" ] let conflicts = detectPathConflicts(paths) check conflicts.len == 1 test "No conflicts with same fingerprint": let paths = @[ "/Programs/nginx/1.28.0-blake2b-abc123/", "/Programs/nginx/1.28.0-blake2b-abc123/" ] let conflicts = detectPathConflicts(paths) check conflicts.len == 0 suite "Edge Cases Tests": test "Package name with hyphens": let path = generateVariantPath("my-package", "1.0.0", "blake2b-abc123") check path == "/Programs/my-package/1.0.0-blake2b-abc123" let name = extractPackageNameFromPath(path) check name == "my-package" test "Version with multiple hyphens": let path = generateVariantPath("pkg", "1.0.0-rc1-beta2", "blake2b-abc123") let version = extractVersionFromPath(path) check version == "1.0.0-rc1-beta2" test "Long fingerprint": let longFp = "blake2b-" & "a".repeat(60) let path = generateVariantPath("nginx", "1.0.0", longFp) let extracted = extractFingerprintFromPath(path) check extracted == longFp test "Package name with numbers": let path = generateVariantPath("python3", "3.11.5", "blake2b-abc123") check path == "/Programs/python3/3.11.5-blake2b-abc123" test "Version with dots and numbers": let path = generateVariantPath("pkg", "2.0.1.5", "blake2b-xyz789") let version = extractVersionFromPath(path) check version == "2.0.1.5" suite "Real-World Path Tests": test "Nginx variant path": let path = generateVariantPath("nginx", "1.28.0", "blake2b-89ab4c5d") check validateVariantPath(path) == true check extractPackageNameFromPath(path) == "nginx" check extractVersionFromPath(path) == "1.28.0" test "Firefox variant path": let path = generateVariantPath("firefox", "120.0", "blake2b-def67890") check validateVariantPath(path) == true check extractPackageNameFromPath(path) == "firefox" test "Python variant path": let path = generateVariantPath("python", "3.11.5", "blake2b-abc12345") check validateVariantPath(path) == true check extractVersionFromPath(path) == "3.11.5" test "Complex package with all features": let path = generateVariantPath("my-app", "2.1.0-rc1", "blake2b-fedcba98") check validateVariantPath(path) == true let info = parseVariantPath(path) check info.isValid == true check info.packageName == "my-app" check info.version == "2.1.0-rc1" check info.fingerprint == "blake2b-fedcba98" check getVariantBinPath(path) == "/Programs/my-app/2.1.0-rc1-blake2b-fedcba98/bin" when isMainModule: echo "Running variant paths tests..." suite "Hash Algorithm Compatibility Tests": test "Validate blake2b path": check validateVariantPath("/Programs/nginx/1.28.0-blake2b-abc123/") == true test "Validate blake3 path (future compatibility)": check validateVariantPath("/Programs/nginx/1.28.0-blake3-xyz789/") == true test "Detect blake2b algorithm": let algo = detectHashAlgorithm("/Programs/nginx/1.28.0-blake2b-abc123/") check algo == "blake2b" test "Detect blake3 algorithm": let algo = detectHashAlgorithm("/Programs/nginx/1.28.0-blake3-xyz789/") check algo == "blake3" test "Extract version from blake3 path": let version = extractVersionFromPath("/Programs/nginx/1.28.0-blake3-xyz789/") check version == "1.28.0" test "Extract fingerprint from blake3 path": let fp = extractFingerprintFromPath("/Programs/nginx/1.28.0-blake3-xyz789abc/") check fp == "blake3-xyz789abc" test "Parse blake3 variant path": let info = parseVariantPath("/Programs/firefox/120.0-blake3-fedcba98/") check info.isValid == true check info.packageName == "firefox" check info.version == "120.0" check info.fingerprint == "blake3-fedcba98" test "Blake2b and blake3 variants can coexist": let paths = @[ "/Programs/nginx/1.28.0-blake2b-abc123/", "/Programs/nginx/1.28.0-blake3-xyz789/" ] # These are different fingerprints (different algorithms), detected as different variants # The conflict detector will flag them as same version but different fingerprints # This is actually correct - they ARE different variants that can coexist let conflicts = detectPathConflicts(paths) check conflicts.len == 1 # Detected as "conflict" but both are valid test "Compare blake2b and blake3 paths": let path1 = "/Programs/nginx/1.28.0-blake2b-abc123/" let path2 = "/Programs/nginx/1.28.0-blake3-xyz789/" # Different fingerprints check isSameVariant(path1, path2) == false test "Invalid hash algorithm rejected": check validateVariantPath("/Programs/nginx/1.28.0-md5-abc123/") == false check validateVariantPath("/Programs/nginx/1.28.0-sha256-abc123/") == false suite "Migration Scenario Tests": test "Old blake2b packages remain valid after blake3 introduction": # Simulate existing blake2b packages let oldPath = "/Programs/nginx/1.27.0-blake2b-old123/" check validateVariantPath(oldPath) == true check detectHashAlgorithm(oldPath) == "blake2b" # New blake3 packages also valid let newPath = "/Programs/nginx/1.28.0-blake3-new456/" check validateVariantPath(newPath) == true check detectHashAlgorithm(newPath) == "blake3" test "Mixed hash algorithms in variant listing": # Both old and new packages can be listed let paths = @[ "/Programs/nginx/1.27.0-blake2b-abc123/", "/Programs/nginx/1.28.0-blake3-def456/", "/Programs/nginx/1.29.0-blake3-ghi789/" ] for path in paths: check validateVariantPath(path) == true test "Path operations work regardless of hash algorithm": let blake2Path = "/Programs/nginx/1.0.0-blake2b-aaa111/" let blake3Path = "/Programs/nginx/2.0.0-blake3-bbb222/" # All operations should work on both check extractPackageNameFromPath(blake2Path) == "nginx" check extractPackageNameFromPath(blake3Path) == "nginx" check getVariantBinPath(blake2Path) == "/Programs/nginx/1.0.0-blake2b-aaa111/bin" check getVariantBinPath(blake3Path) == "/Programs/nginx/2.0.0-blake3-bbb222/bin"