nip/tests/test_packages.nim

370 lines
11 KiB
Nim

## Tests for NPK Package Format Handler
##
## This module tests the NPK package creation, validation, and conversion
## functionality to ensure proper package format handling.
import unittest, os, times, options
import ../src/nimpak/types
import ../src/nimpak/packages
import ../src/nimpak/cas
suite "NPK Package Format Handler":
setup:
let testDir = getTempDir() / "nimpak_test_packages"
let sourceDir = testDir / "source"
let casDir = testDir / "cas"
# Clean up any existing test directory
if dirExists(testDir):
removeDir(testDir)
# Create test directory structure
createDir(sourceDir)
createDir(sourceDir / "bin")
createDir(sourceDir / "share" / "man")
# Create test files
writeFile(sourceDir / "bin" / "testapp", "#!/bin/bash\necho 'Hello World'\n")
writeFile(sourceDir / "share" / "man" / "testapp.1", ".TH TESTAPP 1\n.SH NAME\ntestapp - test application\n")
writeFile(sourceDir / "README.md", "# Test Application\nThis is a test application.\n")
# Initialize CAS manager
let casManager = initCasManager(casDir, casDir / "system")
teardown:
let testDir = getTempDir() / "nimpak_test_packages"
if dirExists(testDir):
removeDir(testDir)
test "create NPK package from Fragment":
let fragment = Fragment(
id: PackageId(
name: "testapp",
version: "1.0.0",
stream: Stable
),
source: Source(
url: "https://example.com/testapp-1.0.0.tar.gz",
hash: "blake2b-abc123def456",
hashAlgorithm: "blake2b",
sourceMethod: Http,
timestamp: now()
),
dependencies: @[],
buildSystem: Custom,
metadata: PackageMetadata(
description: "Test application for NPK testing",
license: "MIT",
maintainer: "test@example.com",
tags: @["test", "cli"],
runtime: RuntimeProfile(
libc: Musl,
allocator: System,
systemdAware: false,
reproducible: true,
tags: @["test"]
)
),
acul: AculCompliance(
required: false,
membership: "",
attribution: "",
buildLog: ""
)
)
let sourceDir = getTempDir() / "nimpak_test_packages" / "source"
let result = createNpkPackage(fragment, sourceDir)
check result.isOk
let npk = result.get()
check npk.metadata.id.name == "testapp"
check npk.metadata.id.version == "1.0.0"
check npk.files.len == 3 # bin/testapp, share/man/testapp.1, README.md
check npk.manifest.totalSize > 0
check npk.manifest.merkleRoot.len > 0
check npk.signature.isNone # No signature by default
test "validate NPK package":
let fragment = Fragment(
id: PackageId(name: "testapp", version: "1.0.0", stream: Stable),
source: Source(
url: "https://example.com/testapp-1.0.0.tar.gz",
hash: "blake2b-abc123def456",
hashAlgorithm: "blake2b",
sourceMethod: Http,
timestamp: now()
),
dependencies: @[],
buildSystem: Custom,
metadata: PackageMetadata(
description: "Test application",
license: "MIT",
maintainer: "test@example.com",
tags: @[],
runtime: RuntimeProfile(
libc: Musl,
allocator: System,
systemdAware: false,
reproducible: true,
tags: @[]
)
),
acul: AculCompliance(required: false, membership: "", attribution:, buildLog: "")
)
let sourceDir = getTempDir() / "nimpak_test_packages" / "source"
let createResult = createNpkPackage(fragment, sourceDir)
check createResult.isOk
let npk = createResult.get()
let validation = validateNpkPackage(npk)
check validation.valid == true
check validation.errors.len == 0
test "validate invalid NPK package":
# Create invalid package with empty name
let invalidFragment = Fragment(
id: PackageId(name: "", version: "", stream: Stable), # Invalid: empty name and version
source: Source(
url: "", # Invalid: empty URL
hash: "", # Invalid: empty hash
hashAlgorithm: "blake2b",
sourceMethod: Http,
timestamp: now()
),
dependencies: @[],
buildSystem: Custom,
metadata: PackageMetadata(
description: "Invalid test package",
license: "MIT",
maintainer: "test@example.com",
tags: @[],
runtime: RuntimeProfile(
libc: Musl,
allocator: System,
systemdAware: false,
reproducible: true,
tags: @[]
)
),
acul: AculCompliance(required: false, membership: "", attribution: "", buildLog: "")
)
let npk = NpkPackage(
metadata: invalidFragment,
files: @[], # No files
manifest: PackageManifest(
files: @[],
totalSize: 0,
created: now(),
merkleRoot: "" # Invalid: empty merkle root
),
signature: none(Signature)
)
let validation = validateNpkPackage(npk)
check validation.valid == false
check validation.errors.len > 0
# Check specific validation errors
let errorFields = validation.errors.mapIt(it.field)
check "metadata.id.name" in errorFields
check "metadata.id.version" in errorFields
check "metadata.source.url" in errorFields
check "metadata.source.hash" in errorFields
check "manifest.merkleRoot" in errorFields
test "serialize NPK to KDL format":
let fragment = Fragment(
id: PackageId(name: "testapp", version: "1.0.0", stream: Stable),
source: Source(
url: "https://example.com/testapp-1.0.0.tar.gz",
hash: "blake2b-abc123def456",
hashAlgorithm: "blake2b",
sourceMethod: Http,
timestamp: now()
),
dependencies: @[
PackageId(name: "libtest", version: "2.0.0", stream: Stable)
],
buildSystem: Custom,
metadata: PackageMetadata(
description: "Test application",
license: "MIT",
maintainer: "test@example.com",
tags: @["test", "cli"],
runtime: RuntimeProfile(
libc: Musl,
allocator: System,
systemdAware: false,
reproducible: true,
tags: @["test"]
)
),
acul: AculCompliance(
required: true,
membership: "NexusOS-Community",
attribution: "Original: testapp, Packaged: NexusOS",
buildLog: ""
)
)
let sourceDir = getTempDir() / "nimpak_test_packages" / "source"
let createResult = createNpkPackage(fragment, sourceDir)
check createResult.isOk
let npk = createResult.get()
let kdlContent = serializeToKdl(npk)
# Check KDL content contains expected elements
check "package \"testapp\"" in kdlContent
check "version \"1.0.0\"" in kdlContent
check "stream \"Stable\"" in kdlContent
check "method \"Http\"" in kdlContent
check "libc \"Musl\"" in kdlContent
check "libtest \"2.0.0\"" in kdlContent
check "required true" in kdlContent
check "membership \"NexusOS-Community\"" in kdlContent
test "sign and verify NPK package":
let fragment = Fragment(
id: PackageId(name: "testapp", version: "1.0.0", stream: Stable),
source: Source(
url: "https://example.com/testapp-1.0.0.tar.gz",
hash: "blake2b-abc123def456",
hashAlgorithm: "blake2b",
sourceMethod: Http,
timestamp: now()
),
dependencies: @[],
buildSystem: Custom,
metadata: PackageMetadata(
description: "Test application",
license: "MIT",
maintainer: "test@example.com",
tags: @[],
runtime: RuntimeProfile(
libc: Musl,
allocator: System,
systemdAware: false,
reproducible: true,
tags: @[]
)
),
acul: AculCompliance(required: false, membership: "", attribution: "", buildLog: "")
)
let sourceDir = getTempDir() / "nimpak_test_packages" / "source"
let createResult = createNpkPackage(fragment, sourceDir)
check createResult.isOk
var npk = createResult.get()
check npk.signature.isNone
# Sign the package
let privateKey = @[0x01'u8, 0x02'u8, 0x03'u8] # Placeholder key
let signResult = signNpkPackage(npk, "test-key-id", privateKey)
check signResult.isOk
check npk.signature.isSome
let signature = npk.signature.get()
check signature.keyId == "test-key-id"
check signature.algorithm == "ed25519"
# Verify the signature
let publicKey = @[0x04'u8, 0x05'u8, 0x06'u8] # Placeholder key
let verifyResult = verifyNpkSignature(npk, publicKey)
check verifyResult.isOk
# Note: This will be true with placeholder implementation
test "create and load NPK archive":
let fragment = Fragment(
id: PackageId(name: "testapp", version: "1.0.0", stream: Stable),
source: Source(
url: "https://example.com/testapp-1.0.0.tar.gz",
hash: "blake2b-abc123def456",
hashAlgorithm: "blake2b",
sourceMethod: Http,
timestamp: now()
),
dependencies: @[],
buildSystem: Custom,
metadata: PackageMetadata(
description: "Test application",
license: "MIT",
maintainer: "test@example.com",
tags: @[],
runtime: RuntimeProfile(
libc: Musl,
allocator: System,
systemdAware: false,
reproducible: true,
tags: @[]
)
),
acul: AculCompliance(required: false, membership: "", attribution: "", buildLog: "")
)
let sourceDir = getTempDir() / "nimpak_test_packages" / "source"
let createResult = createNpkPackage(fragment, sourceDir)
check createResult.isOk
let npk = createResult.get()
let archivePath = getTempDir() / "nimpak_test_packages" / "testapp-1.0.0.npk"
# Create archive
let archiveResult = createNpkArchive(npk, archivePath)
check archiveResult.isOk
check dirExists(archivePath) # Currently creates directory, will be tar.gz later
check fileExists(archivePath / "package.kdl")
check fileExists(archivePath / "manifest.json")
# Load archive (will fail with current placeholder implementation)
let loadResult = loadNpkArchive(archivePath)
check loadResult.isErr # Expected to fail until KDL parsing is implemented
test "get NPK package info":
let fragment = Fragment(
id: PackageId(name: "testapp", version: "1.0.0", stream: Stable),
source: Source(
url: "https://example.com/testapp-1.0.0.tar.gz",
hash: "blake2b-abc123def456",
hashAlgorithm: "blake2b",
sourceMethod: Http,
timestamp: now()
),
dependencies: @[],
buildSystem: Custom,
metadata: PackageMetadata(
description: "Test application",
license: "MIT",
maintainer: "test@example.com",
tags: @[],
runtime: RuntimeProfile(
libc: Musl,
allocator: System,
systemdAware: false,
reproducible: true,
tags: @[]
)
),
acul: AculCompliance(required: false, membership: "", attribution: "", buildLog: "")
)
let sourceDir = getTempDir() / "nimpak_test_packages" / "source"
let createResult = createNpkPackage(fragment, sourceDir)
check createResult.isOk
let npk = createResult.get()
let info = getNpkInfo(npk)
check "NPK Package: testapp v1.0.0" in info
check "Stream: Stable" in info
check "Files: 3" in info
check "Signed: No" in info