437 lines
13 KiB
Nim
437 lines
13 KiB
Nim
## Tests for NPK Package Format Handler
|
|
##
|
|
## This module tests the NPK package format creation, validation, and conversion
|
|
## capabilities with CAS integration and digital signature support.
|
|
|
|
import unittest, os, times, json, options
|
|
import ../src/nimpak/[types, packages, cas]
|
|
|
|
suite "NPK Package Format Handler":
|
|
setup:
|
|
let testDir = getTempDir() / "nimpak_test_npk"
|
|
let casDir = testDir / "cas"
|
|
let sourceDir = testDir / "source"
|
|
let outputDir = testDir / "output"
|
|
|
|
# Clean up and create test directories
|
|
if dirExists(testDir):
|
|
removeDir(testDir)
|
|
createDir(testDir)
|
|
createDir(casDir)
|
|
createDir(sourceDir)
|
|
createDir(outputDir)
|
|
|
|
# Initialize CAS manager
|
|
let cas = initCasManager(casDir, casDir)
|
|
|
|
# Create test files in source directory
|
|
writeFile(sourceDir / "test.txt", "Hello, NimPak!")
|
|
writeFile(sourceDir / "config.conf", "setting=value\nother=123")
|
|
createDir(sourceDir / "subdir")
|
|
writeFile(sourceDir / "subdir" / "nested.dat", "nested file content")
|
|
|
|
teardown:
|
|
let testDir = getTempDir() / "nimpak_test_npk"
|
|
if dirExists(testDir):
|
|
removeDir(testDir)
|
|
|
|
test "create NPK package from Fragment and source directory":
|
|
leagment = Fragment(
|
|
id: PackageId(name: "test-package", version: "1.0.0", stream: Stable),
|
|
source: Source(
|
|
url: "https://example.com/test-package-1.0.0.tar.gz",
|
|
hash: "blake2b-test123",
|
|
hashAlgorithm: "blake2b",
|
|
sourceMethod: Http,
|
|
timestamp: now()
|
|
),
|
|
dependencies: @[],
|
|
buildSystem: Custom,
|
|
metadata: PackageMetadata(
|
|
description: "Test package for NPK format",
|
|
license: "MIT",
|
|
maintainer: "test@example.com",
|
|
tags: @["test"],
|
|
runtime: RuntimeProfile(
|
|
libc: Musl,
|
|
allocator: Jemalloc,
|
|
systemdAware: false,
|
|
reproducible: true,
|
|
tags: @["cli"]
|
|
)
|
|
),
|
|
acul: AculCompliance(
|
|
required: false,
|
|
membership: "",
|
|
attribution: "",
|
|
buildLog: ""
|
|
)
|
|
)
|
|
|
|
let result = createNpkPackage(fragment, sourceDir, cas)
|
|
check result.isOk
|
|
|
|
let npk = result.get()
|
|
check npk.metadata.id.name == "test-package"
|
|
check npk.metadata.id.version == "1.0.0"
|
|
check npk.files.len == 3 # test.txt, config.conf, subdir/nested.dat
|
|
check npk.manifest.totalSize > 0
|
|
check npk.manifest.merkleRoot.len > 0
|
|
check npk.manifest.merkleRoot.startsWith("blake2b-")
|
|
|
|
test "validate NPK package metadata and structure":
|
|
let fragment = Fragment(
|
|
id: PackageId(name: "valid-package", version: "2.0.0", stream: Testing),
|
|
source: Source(
|
|
url: "https://example.com/valid-package.tar.gz",
|
|
hash: "blake2b-valid123",
|
|
hashAlgorithm: "blake2b",
|
|
sourceMethod: Git,
|
|
timestamp: now()
|
|
),
|
|
dependencies: @[PackageId(name: "dep1", version: "1.0", stream: Stable)],
|
|
buildSystem: CMake,
|
|
metadata: PackageMetadata(
|
|
description: "Valid test package",
|
|
license: "ACUL",
|
|
maintainer: "maintainer@example.com",
|
|
tags: @["valid", "test"],
|
|
runtime: RuntimeProfile(
|
|
libc: Glibc,
|
|
allocator: System,
|
|
systemdAware: true,
|
|
reproducible: true,
|
|
tags: @["system"]
|
|
)
|
|
),
|
|
acul: AculCompliance(
|
|
required: true,
|
|
membership: "NexusOS-Community",
|
|
attribution: "Original work",
|
|
buildLog: "Build completed successfully"
|
|
)
|
|
)
|
|
|
|
let createResult = createNpkPackage(fragment, sourceDir, cas)
|
|
check createResult.isOk
|
|
|
|
let npk = createResult.get()
|
|
let validation = validateNpkPackage(npk)
|
|
|
|
check validation.valid == true
|
|
check validation.errors.len == 0
|
|
# May have warnings about non-standard hash algorithms, but should be valid
|
|
|
|
test "serialize NPK package to KDL format":
|
|
let fragment = Fragment(
|
|
id: PackageId(name: "kdl-test", version: "1.5.0", stream: Stable),
|
|
source: Source(
|
|
url: "https://example.com/kdl-test.tar.gz",
|
|
hash: "blake2b-kdltest123",
|
|
hashAlgorithm: "blake2b",
|
|
sourceMethod: Http,
|
|
timestamp: now()
|
|
),
|
|
dependencies: @[],
|
|
buildSystem: Meson,
|
|
metadata: PackageMetadata(
|
|
description: "KDL serialization test",
|
|
license: "MIT",
|
|
maintainer: "test@kdl.com",
|
|
tags: @["kdl"],
|
|
runtime: RuntimeProfile(
|
|
libc: Musl,
|
|
allocator: Jemalloc,
|
|
systemdAware: false,
|
|
reproducible: true,
|
|
tags: @["serialization"]
|
|
)
|
|
),
|
|
acul: AculCompliance(
|
|
required: false,
|
|
membership: "",
|
|
attribution: "",
|
|
buildLog: ""
|
|
)
|
|
)
|
|
|
|
let createResult = createNpkPackage(fragment, sourceDir, cas)
|
|
check createResult.isOk
|
|
|
|
let npk = createResult.get()
|
|
let kdlContent = serializeToKdl(npk)
|
|
|
|
# Check that KDL content contains expected sections
|
|
check kdlContent.contains("package \"kdl-test\"")
|
|
check kdlContent.contains("version \"1.5.0\"")
|
|
check kdlContent.contains("stream \"Stable\"")
|
|
check kdlContent.contains("source {")
|
|
check kdlContent.contains("integrity {")
|
|
check kdlContent.contains("runtime {")
|
|
check kdlContent.contains("acul {")
|
|
check kdlContent.contains("manifest {")
|
|
check kdlContent.contains("files {")
|
|
check kdlContent.contains("algorithm \"BLAKE2b\"")
|
|
|
|
test "create and validate .npk.zst archive":
|
|
let fragment = Fragment(
|
|
id: PackageId(name: "archive-test", version: "3.0.0", stream: Dev),
|
|
source: Source(
|
|
url: "https://example.com/archive-test.tar.gz",
|
|
hash: "blake2b-archive123",
|
|
hashAlgorithm: "blake2b",
|
|
sourceMethod: Local,
|
|
timestamp: now()
|
|
),
|
|
dependencies: @[],
|
|
buildSystem: Autotools,
|
|
metadata: PackageMetadata(
|
|
description: "Archive format test",
|
|
license: "EUPL-1.2",
|
|
maintainer: "archive@test.com",
|
|
tags: @["archive"],
|
|
runtime: RuntimeProfile(
|
|
libc: Musl,
|
|
allocator: Internal,
|
|
systemdAware: false,
|
|
reproducible: true,
|
|
tags: @["compression"]
|
|
)
|
|
),
|
|
acul: AculCompliance(
|
|
required: true,
|
|
membership: "NexusOS",
|
|
attribution: "Test archive",
|
|
buildLog: "Archive test build"
|
|
)
|
|
)
|
|
|
|
let createResult = createNpkPackage(fragment, sourceDir, cas)
|
|
check createResult.isOk
|
|
|
|
let npk = createResult.get()
|
|
let archivePath = outputDir / "test-archive"
|
|
|
|
# Test .npk.zst format (default)
|
|
let archiveResult = createNpkArchive(npk, archivePath, NpkZst)
|
|
check archiveResult.isOk
|
|
|
|
let finalPath = archivePath & ".npk.zst"
|
|
check fileExists(finalPath)
|
|
|
|
# Verify archive is not empty
|
|
let archiveInfo = getFileInfo(finalPath)
|
|
check archiveInfo.size > 0
|
|
|
|
test "create uncompressed .npk.tar archive for debugging":
|
|
let fragment = Fragment(
|
|
id: PackageId(name: "debug-test", version: "1.0.0", stream: Dev),
|
|
source: Source(
|
|
url: "file:///tmp/debug-test",
|
|
hash: "blake2b-debug123",
|
|
hashAlgorithm: "blake2b",
|
|
sourceMethod: Local,
|
|
timestamp: now()
|
|
),
|
|
dependencies: @[],
|
|
buildSystem: Custom,
|
|
metadata: PackageMetadata(
|
|
description: "Debug archive test",
|
|
license: "MIT",
|
|
maintainer: "debug@test.com",
|
|
tags: @["debug"],
|
|
runtime: RuntimeProfile(
|
|
libc: None,
|
|
allocator: System,
|
|
systemdAware: false,
|
|
reproducible: true,
|
|
tags: @["debug"]
|
|
)
|
|
),
|
|
acul: AculCompliance(
|
|
required: false,
|
|
membership: "",
|
|
attribution: "",
|
|
buildLog: ""
|
|
)
|
|
)
|
|
|
|
let createResult = createNpkPackage(fragment, sourceDir, cas)
|
|
check createResult.isOk
|
|
|
|
let npk = createResult.get()
|
|
let archivePath = outputDir / "debug-archive"
|
|
|
|
# Test .npk.tar format (uncompressed)
|
|
let archiveResult = createNpkArchive(npk, archivePath, NpkTar)
|
|
check archiveResult.isOk
|
|
|
|
let finalPath = archivePath & ".npk.tar"
|
|
check fileExists(finalPath)
|
|
|
|
test "extract NPK package using CAS":
|
|
let fragment = Fragment(
|
|
id: PackageId(name: "extract-test", version: "2.5.0", stream: Stable),
|
|
source: Source(
|
|
url: "https://example.com/extract-test.tar.gz",
|
|
hash: "blake2b-extract123",
|
|
hashAlgorithm: "blake2b",
|
|
sourceMethod: Http,
|
|
timestamp: now()
|
|
),
|
|
dependencies: @[],
|
|
buildSystem: Nim,
|
|
metadata: PackageMetadata(
|
|
description: "Extraction test package",
|
|
license: "MIT",
|
|
maintainer: "extract@test.com",
|
|
tags: @["extract"],
|
|
runtime: RuntimeProfile(
|
|
libc: Musl,
|
|
allocator: Jemalloc,
|
|
systemdAware: false,
|
|
reproducible: true,
|
|
tags: @["extraction"]
|
|
)
|
|
),
|
|
acul: AculCompliance(
|
|
required: false,
|
|
membership: "",
|
|
attribution: "",
|
|
buildLog: ""
|
|
)
|
|
)
|
|
|
|
let createResult = createNpkPackage(fragment, sourceDir, cas)
|
|
check createResult.isOk
|
|
|
|
let npk = createResult.get()
|
|
let extractDir = outputDir / "extracted"
|
|
|
|
let extractResult = extractNpkPackage(npk, extractDir, cas)
|
|
check extractResult.isOk
|
|
|
|
# Verify extracted files exist
|
|
check fileExists(extractDir / "test.txt")
|
|
check fileExists(extractDir / "config.conf")
|
|
check fileExists(extractDir / "subdir" / "nested.dat")
|
|
|
|
# Verify file contents
|
|
check readFile(extractDir / "test.txt") == "Hello, NimPak!"
|
|
check readFile(extractDir / "config.conf") == "setting=value\nother=123"
|
|
check readFile(extractDir / "subdir" / "nested.dat") == "nested file content"
|
|
|
|
test "validate NPK package with missing required fields":
|
|
# Create an invalid fragment with missing required fields
|
|
let invalidFragment = Fragment(
|
|
id: PackageId(name: "", version: "", stream: Stable), # Empty name and version
|
|
source: Source(
|
|
url: "", # Empty URL
|
|
hash: "", # Empty hash
|
|
hashAlgorithm: "blake2b",
|
|
sourceMethod: Http,
|
|
timestamp: now()
|
|
),
|
|
dependencies: @[],
|
|
buildSystem: Custom,
|
|
metadata: PackageMetadata(
|
|
description: "Invalid test package",
|
|
license: "MIT",
|
|
maintainer: "invalid@test.com",
|
|
tags: @[],
|
|
runtime: RuntimeProfile(
|
|
libc: Musl,
|
|
allocator: System,
|
|
systemdAware: false,
|
|
reproducible: false,
|
|
tags: @[]
|
|
)
|
|
),
|
|
acul: AculCompliance(
|
|
required: false,
|
|
membership: "",
|
|
attribution: "",
|
|
buildLog: ""
|
|
)
|
|
)
|
|
|
|
let createResult = createNpkPackage(invalidFragment, sourceDir, cas)
|
|
check createResult.isOk # Creation should succeed even with invalid metadata
|
|
|
|
let npk = createResult.get()
|
|
let validation = validateNpkPackage(npk)
|
|
|
|
check validation.valid == false
|
|
check validation.errors.len > 0
|
|
|
|
# Check for specific validation errors
|
|
var hasNameError = false
|
|
var hasVersionError = false
|
|
var hasUrlError = false
|
|
var hasHashError = false
|
|
|
|
for error in validation.errors:
|
|
if error.field == "metadata.id.name":
|
|
hasNameError = true
|
|
elif error.field == "metadata.id.version":
|
|
hasVersionError = true
|
|
elif error.field == "metadata.source.url":
|
|
hasUrlError = true
|
|
elif error.field == "metadata.source.hash":
|
|
hasHashError = true
|
|
|
|
check hasNameError
|
|
check hasVersionError
|
|
check hasUrlError
|
|
check hasHashError
|
|
|
|
test "get human-readable NPK package information":
|
|
let fragment = Fragment(
|
|
id: PackageId(name: "info-test", version: "4.2.1", stream: LTS),
|
|
source: Source(
|
|
url: "https://example.com/info-test.tar.gz",
|
|
hash: "blake2b-info123",
|
|
hashAlgorithm: "blake2b",
|
|
sourceMethod: Git,
|
|
timestamp: now()
|
|
),
|
|
dependencies: @[],
|
|
buildSystem: Cargo,
|
|
metadata: PackageMetadata(
|
|
description: "Package info test",
|
|
license: "Apache-2.0",
|
|
maintainer: "info@test.com",
|
|
tags: @["info"],
|
|
runtime: RuntimeProfile(
|
|
libc: Glibc,
|
|
allocator: Jemalloc,
|
|
systemdAware: true,
|
|
reproducible: true,
|
|
tags: @["information"]
|
|
)
|
|
),
|
|
acul: AculCompliance(
|
|
required: true,
|
|
membership: "NexusOS-Pro",
|
|
attribution: "Info test package",
|
|
buildLog: "Info build completed"
|
|
)
|
|
)
|
|
|
|
let createResult = createNpkPackage(fragment, sourceDir, cas)
|
|
check createResult.isOk
|
|
|
|
let npk = createResult.get()
|
|
let info = getNpkInfo(npk)
|
|
|
|
check info.contains("NPK Package: info-test v4.2.1")
|
|
check info.contains("Stream: LTS")
|
|
check info.contains("Files: 3")
|
|
check info.contains("Total Size:")
|
|
check info.contains("Created:")
|
|
check info.contains("Merkle Root: blake2b-")
|
|
check info.contains("Signed: No")
|
|
|
|
when isMainModule:
|
|
# Run the tests
|
|
echo "Running NPK Package Format Handler tests..." |