## 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