# tests/test_npk_conversion.nim # Unit tests for NPK conversion with build hash integration import unittest, os, times, tables import ../src/nimpak/npk_conversion import ../src/nimpak/grafting import ../src/nip/types suite "NPK Conversion Tests": setup: let tempDir = getTempDir() / "nimpak_test_npk" if dirExists(tempDir): removeDir(tempDir) createDir(tempDir) teardown: let tempDir = getTempDir() / "nimpak_test_npk" if dirExists(tempDir): removeDir(tempDir) test "NPK converter creation": let conv = newNPKConverter() check conv.compressionLevel == 6 check conv.includeProvenance == true check conv.calculateBuildHash == true check conv.signPackages == false test "NPK converter with custom settings": var conv = newNPKConverter("/custom/output") conv.compressionLevel = 9 conv.signPackages = true conv.keyPath = "/path/to/key" check conv.outputDir == "/custom/output" check conv.compressionLevel == 9 check conv.signPackages == true check conv.keyPath == "/path/to/key" test "Build configuration creation": let metadata = GraftedPackageMetadata( packageName: "test-package", version: "1.0.0", source: "test", graftedAt: now(), originalHash: "test-hash", graftHash: "graft-hash", buildLog: "test build log", provenance: ProvenanceInfo() ) let buildConfig = extractBuildConfiguration(metadata) check buildConfig.sourceHash == "test-hash" check buildConfig.targetArchitecture == "x86_64" check buildConfig.libc == "musl" test "Build hash calculation": let config = BuildConfiguration( sourceHash: "source-123", sourceTimestamp: now(), configureFlags: @["--enable-feature"], compilerFlags: @["-O2"], linkerFlags: @[], compilerVersion: "gcc-11.0", nimVersion: "2.0.0", nimFlags: @[], targetArchitecture: "x86_64", libc: "musl", libcVersion: "1.2.4", allocator: "default", allocatorVersion: "system", environmentVars: initTable[string, string](), dependencies: @[] ) let hashResult = calculateBuildHash(config) check hashResult.isOk let buildHash = hashResult.get() check buildHash.algorithm == "blake3" check buildHash.hash.startsWith("blake3-") check buildHash.components.len > 0 test "File scanning": let testDir = getTempDir() / "test_scan" createDir(testDir) # Create test files writeFile(testDir / "test1.txt", "content1") writeFile(testDir / "test2.txt", "content2") createDir(testDir / "subdir") writeFile(testDir / "subdir" / "test3.txt", "content3") let filesResult = scanPackageFiles(testDir) check filesResult.isOk let files = filesResult.get() check files.len == 3 # Check file paths are normalized let paths = files.mapIt(it.path) check "/test1.txt" in paths check "/test2.txt" in paths check "/subdir/test3.txt" in paths # Cleanup removeDir(testDir) test "Manifest generation": let tempDir = getTempDir() / "test_manifest" createDir(tempDir) writeFile(tempDir / "test.txt", "test content") let metadata = GraftedPackageMetadata( packageName: "test-package", version: "1.0.0", source: "test", graftedAt: now(), originalHash: "original-hash", graftHash: "graft-hash", buildLog: "test build log", provenance: ProvenanceInfo( originalSource: "test-source", downloadUrl: "https://example.com/package", archivePath: "/path/to/archive", extractedPath: tempDir, conversionLog: "test conversion" ) ) let conv = newNPKConverter() let manifestResult = generateNPKManifest(conv, metadata, tempDir) check manifestResult.isOk let manifest = manifestResult.get() check manifest.name == "test-package" check manifest.version == "1.0.0" check manifest.sourceHash == "original-hash" check manifest.files.len == 1 check manifest.files[0].path == "/test.txt" removeDir(tempDir) test "KDL manifest writing": let manifest = NPKManifest( name: "test-package", version: "1.0.0", description: "Test package", homepage: "https://example.com", license: @["MIT"], maintainer: "Test Maintainer", buildHash: "build-hash-123", sourceHash: "source-hash-123", artifactHash: "artifact-hash-123", buildConfig: BuildConfiguration(), dependencies: @[], acul: AculCompliance( required: false, membership: "Test", attribution: "Test attribution", buildLog: "test log" ), files: @[ NPKFile( path: "/test.txt", hash: "file-hash-123", permissions: "644", size: 100 ) ], provenance: ProvenanceInfo( originalSource: "test", downloadUrl: "https://example.com", archivePath: "/path", extractedPath: "/extracted", conversionLog: "test" ), created: now(), converterName: "nimpak-test" ) let outputPath = getTempDir() / "test-manifest.kdl" let writeResult = writeManifestKDL(manifest, outputPath) check writeResult.isOk check fileExists(outputPath) let content = readFile(outputPath) check "package \"test-package\"" in content check "version \"1.0.0\"" in content check "build_hash \"build-hash-123\"" in content removeFile(outputPath) test "String array formatting": check formatStringArray(@[]) == "\"\"" check formatStringArray(@["single"]) == "\"single\"" check formatStringArray(@["first", "second"]) == "\"first\" \"second\"" check formatStringArray(@["a", "b", "c"]) == "\"a\" \"b\" \"c\"" suite "NPK Integration Tests": test "Full conversion workflow": let tempDir = getTempDir() / "test_conversion" createDir(tempDir) # Create test package structure let extractedDir = tempDir / "extracted" createDir(extractedDir) writeFile(extractedDir / "binary", "#!/bin/bash\necho hello") writeFile(extractedDir / "config.txt", "setting=value") let metadata = GraftedPackageMetadata( packageName: "test-conversion", version: "2.0.0", source: "test", graftedAt: now(), originalHash: "original-123", graftHash: "graft-123", buildLog: "successful build", provenance: ProvenanceInfo( originalSource: "test-conversion", downloadUrl: "https://example.com/test", archivePath: "/archive/path", extractedPath: extractedDir, conversionLog: "extracted successfully" ) ) let conv = newNPKConverter(tempDir / "output") let conversionResult = convertToNPK(conv, metadata, extractedDir) check conversionResult.isOk let result = conversionResult.get() check result.success == true check result.npkPath.endsWith(".npk") check result.buildHash.algorithm == "blake3" check result.manifest.name == "test-conversion" # Verify NPK file was created check fileExists(result.npkPath) removeDir(tempDir)