## Manifest Parser Tests ## Comprehensive test suite for format-agnostic manifest parsing import std/[unittest, options, strutils] import nip/manifest_parser import nip/platform suite "Semantic Versioning": test "Parse valid semver": let v = parseSemanticVersion("1.2.3") check v.major == 1 check v.minor == 2 check v.patch == 3 check v.prerelease == "" check v.build == "" test "Parse semver with prerelease": let v = parseSemanticVersion("1.0.0-alpha.1") check v.major == 1 check v.minor == 0 check v.patch == 0 check v.prerelease == "alpha.1" test "Parse semver with build metadata": let v = parseSemanticVersion("1.0.0+20130313144700") check v.major == 1 check v.build == "20130313144700" test "Parse semver with both": let v = parseSemanticVersion("1.0.0-beta+exp.sha.5114f85") check v.prerelease == "beta" check v.build == "exp.sha.5114f85" test "Reject invalid semver": expect ManifestError: discard parseSemanticVersion("1.0") expect ManifestError: discard parseSemanticVersion("v1.2.3") expect ManifestError: discard parseSemanticVersion("1.2.x") test "Version comparison": let v1 = parseSemanticVersion("1.0.0") let v2 = parseSemanticVersion("1.0.1") let v3 = parseSemanticVersion("1.1.0") let v4 = parseSemanticVersion("2.0.0") check v1 < v2 check v2 < v3 check v3 < v4 check v1 == v1 check v4 > v1 test "Prerelease comparison": let release = parseSemanticVersion("1.0.0") let prerelease = parseSemanticVersion("1.0.0-alpha") check prerelease < release # Prerelease < release suite "Version Constraints": test "Parse exact constraint": let c = parseVersionConstraint("1.2.3") check c.operator == OpExact check c.version.major == 1 test "Parse >= constraint": let c = parseVersionConstraint(">=1.0.0") check c.operator == OpGreaterEq test "Parse ~ constraint": let c = parseVersionConstraint("~1.2.3") check c.operator == OpTilde test "Parse ^ constraint": let c = parseVersionConstraint("^2.0.0") check c.operator == OpCaret test "Parse * constraint": let c = parseVersionConstraint("*") check c.operator == OpAny test "Satisfy exact constraint": let v = parseSemanticVersion("1.2.3") let c = parseVersionConstraint("=1.2.3") check satisfiesConstraint(v, c) let v2 = parseSemanticVersion("1.2.4") check not satisfiesConstraint(v2, c) test "Satisfy >= constraint": let v1 = parseSemanticVersion("1.2.3") let v2 = parseSemanticVersion("1.2.4") let c = parseVersionConstraint(">=1.2.3") check satisfiesConstraint(v1, c) check satisfiesConstraint(v2, c) test "Satisfy ~ constraint": let c = parseVersionConstraint("~1.2.3") check satisfiesConstraint(parseSemanticVersion("1.2.3"), c) check satisfiesConstraint(parseSemanticVersion("1.2.4"), c) check not satisfiesConstraint(parseSemanticVersion("1.3.0"), c) check not satisfiesConstraint(parseSemanticVersion("2.0.0"), c) test "Satisfy ^ constraint": let c = parseVersionConstraint("^1.2.3") check satisfiesConstraint(parseSemanticVersion("1.2.3"), c) check satisfiesConstraint(parseSemanticVersion("1.3.0"), c) check satisfiesConstraint(parseSemanticVersion("1.9.9"), c) check not satisfiesConstraint(parseSemanticVersion("2.0.0"), c) suite "Format Detection": test "Detect JSON format": let jsonContent = """{"name": "test"}""" check detectFormat(jsonContent) == FormatJSON test "Detect KDL format": let kdlContent = """package "test" { }""" check detectFormat(kdlContent) == FormatKDL test "Detect JSON array": let jsonArray = """[{"name": "test"}]""" check detectFormat(jsonArray) == FormatJSON suite "JSON Manifest Parsing": test "Parse minimal valid manifest": let jsonContent = """ { "name": "test-package", "version": "1.0.0", "license": "MIT" } """ let manifest = parseManifest(jsonContent, NPK, FormatJSON, ValidationStrict) check manifest.name == "test-package" check manifest.version.major == 1 check manifest.license == "MIT" test "Parse manifest with dependencies": let jsonContent = """ { "name": "test-package", "version": "1.0.0", "license": "MIT", "dependencies": [ {"name": "dep1", "version": ">=1.0.0"}, {"name": "dep2", "version": "~2.0.0", "optional": true} ] } """ let manifest = parseManifest(jsonContent, NPK, FormatJSON, ValidationStrict) check manifest.dependencies.len == 2 check manifest.dependencies[0].name == "dep1" check manifest.dependencies[1].optional == true test "Parse manifest with platform constraints": let jsonContent = """ { "name": "test-package", "version": "1.0.0", "license": "MIT", "supported_os": ["linux", "freebsd"], "supported_architectures": ["x86_64", "aarch64"] } """ let manifest = parseManifest(jsonContent, NPK, FormatJSON, ValidationStrict) check manifest.supportedOS.len == 2 check "linux" in manifest.supportedOS check manifest.supportedArchitectures.len == 2 check "x86_64" in manifest.supportedArchitectures test "Reject missing required field": let jsonContent = """ { "name": "test-package", "license": "MIT" } """ expect ManifestError: discard parseManifest(jsonContent, NPK, FormatJSON, ValidationStrict) test "Reject invalid semver": let jsonContent = """ { "name": "test-package", "version": "1.0", "license": "MIT" } """ expect ManifestError: discard parseManifest(jsonContent, NPK, FormatJSON, ValidationStrict) test "Reject unknown field in strict mode": let jsonContent = """ { "name": "test-package", "version": "1.0.0", "license": "MIT", "unknown_field": "contamination" } """ expect ManifestError: discard parseManifest(jsonContent, NPK, FormatJSON, ValidationStrict) test "Accept unknown field in lenient mode": let jsonContent = """ { "name": "test-package", "version": "1.0.0", "license": "MIT", "unknown_field": "allowed" } """ # Should not raise in lenient mode let manifest = parseManifest(jsonContent, NPK, FormatJSON, ValidationLenient) check manifest.name == "test-package" suite "KDL Manifest Parsing": test "Parse minimal KDL manifest": let kdlContent = """ package "test-package" { version "1.0.0" license "MIT" } """ let manifest = parseManifest(kdlContent, NPK, FormatKDL, ValidationStrict) check manifest.name == "test-package" check manifest.version.major == 1 check manifest.license == "MIT" test "Parse KDL manifest with dependencies": let kdlContent = """ package "test-package" { version "1.0.0" license "MIT" dependencies { "dep1" version=">=1.0.0" "dep2" version="~2.0.0" optional=true } } """ let manifest = parseManifest(kdlContent, NPK, FormatKDL, ValidationStrict) check manifest.dependencies.len == 2 check manifest.dependencies[0].name == "dep1" check manifest.dependencies[1].optional == true suite "Platform Validation": test "Validate valid OS": let jsonContent = """ { "name": "test-package", "version": "1.0.0", "license": "MIT", "supported_os": ["linux", "freebsd"] } """ let manifest = parseManifest(jsonContent, NPK, FormatJSON, ValidationStrict) check manifest.supportedOS.len == 2 test "Reject invalid OS in strict mode": let jsonContent = """ { "name": "test-package", "version": "1.0.0", "license": "MIT", "supported_os": ["invalid_os"] } """ expect ManifestError: discard parseManifest(jsonContent, NPK, FormatJSON, ValidationStrict) test "Reject invalid architecture in strict mode": let jsonContent = """ { "name": "test-package", "version": "1.0.0", "license": "MIT", "supported_architectures": ["invalid_arch"] } """ expect ManifestError: discard parseManifest(jsonContent, NPK, FormatJSON, ValidationStrict) test "Check platform compatibility": let jsonContent = """ { "name": "test-package", "version": "1.0.0", "license": "MIT", "supported_os": ["linux"], "supported_architectures": ["x86_64"] } """ let manifest = parseManifest(jsonContent, NPK, FormatJSON, ValidationStrict) # Create mock platform capabilities var caps = PlatformCapabilities( osType: Linux, hasUserNamespaces: true, hasJails: false, hasUnveil: false, isRoot: false, kernelVersion: "6.1.0", isEmbedded: false, memoryTotal: 8589934592, cpuCount: 8 ) check checkPlatformCompatibility(manifest, caps) # Change to incompatible platform caps.osType = FreeBSD check not checkPlatformCompatibility(manifest, caps) suite "Serialization": test "Serialize to JSON": let manifest = PackageManifest( format: NPK, name: "test-package", version: parseSemanticVersion("1.0.0"), license: "MIT", description: some("A test package"), supportedOS: @["linux", "freebsd"], supportedArchitectures: @["x86_64"] ) let jsonStr = serializeManifestToJSON(manifest) check jsonStr.contains("test-package") check jsonStr.contains("1.0.0") check jsonStr.contains("MIT") test "Serialize to KDL": let manifest = PackageManifest( format: NPK, name: "test-package", version: parseSemanticVersion("1.0.0"), license: "MIT", description: some("A test package") ) let kdlStr = serializeManifestToKDL(manifest) check kdlStr.contains("package \"test-package\"") check kdlStr.contains("version \"1.0.0\"") check kdlStr.contains("license \"MIT\"") test "Round-trip JSON": let original = """ { "name": "test-package", "version": "1.0.0", "license": "MIT", "description": "A test package" } """ let manifest = parseManifest(original, NPK, FormatJSON, ValidationStrict) let serialized = serializeManifestToJSON(manifest) let reparsed = parseManifest(serialized, NPK, FormatJSON, ValidationStrict) check reparsed.name == manifest.name check reparsed.version == manifest.version check reparsed.license == manifest.license suite "Validation Rules": test "Required fields rule": let jsonContent = """ { "version": "1.0.0", "license": "MIT" } """ expect ManifestError: discard parseManifest(jsonContent, NPK, FormatJSON, ValidationStrict) test "Dependency validation": let jsonContent = """ { "name": "test-package", "version": "1.0.0", "license": "MIT", "dependencies": [ {"name": "dep1", "version": "invalid"} ] } """ expect ManifestError: discard parseManifest(jsonContent, NPK, FormatJSON, ValidationStrict) suite "Format-Specific Fields": test "NPK-specific fields allowed": let jsonContent = """ { "name": "test-package", "version": "1.0.0", "license": "MIT", "files": ["file1", "file2"] } """ let manifest = parseManifest(jsonContent, NPK, FormatJSON, ValidationStrict) check manifest.name == "test-package" test "NIP-specific fields allowed": let jsonContent = """ { "name": "test-package", "version": "1.0.0", "license": "MIT", "desktop": "test.desktop" } """ let manifest = parseManifest(jsonContent, NIP, FormatJSON, ValidationStrict) check manifest.name == "test-package" test "NEXTER-specific fields allowed": let jsonContent = """ { "name": "test-package", "version": "1.0.0", "license": "MIT", "container": "test-container" } """ let manifest = parseManifest(jsonContent, NEXTER, FormatJSON, ValidationStrict) check manifest.name == "test-package" when isMainModule: echo "Running manifest parser tests..."