432 lines
11 KiB
Nim
432 lines
11 KiB
Nim
## 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..."
|