nip/tests/test_grafting_integration.nim

257 lines
7.3 KiB
Nim

## test_grafting_integration.nim
## Integration tests for build artifact grafting
import std/[unittest, tables, os, strutils]
import ../src/nimpak/build/[types, grafting]
import ../src/nimpak/graft_coordinator
import ../src/nimpak/install_manager
suite "Grafting Integration Tests":
setup:
let testCacheDir = getTempDir() / "nip-graft-test"
let testProgramsDir = getTempDir() / "Programs-test"
let testLinksDir = getTempDir() / "System-test" / "Links"
# Clean up from previous runs
if dirExists(testCacheDir):
removeDir(testCacheDir)
if dirExists(testProgramsDir):
removeDir(testProgramsDir)
if dirExists(testLinksDir):
removeDir(testLinksDir)
# Create test directories
createDir(testCacheDir)
createDir(testProgramsDir)
createDir(testLinksDir / "Executables")
createDir(testLinksDir / "Libraries")
let installConfig = InstallConfig(
programsDir: testProgramsDir,
linksDir: testLinksDir,
cacheDir: testCacheDir,
dbFile: testCacheDir / "test.db",
autoSymlink: true,
checkConflicts: false,
verbose: false
)
let coordinator = newGraftCoordinator(installConfig, false)
test "Validate artifact - valid directory":
# Create a mock artifact
let artifactPath = testCacheDir / "mock-artifact"
createDir(artifactPath / "bin")
writeFile(artifactPath / "bin" / "test-exe", "#!/bin/sh\necho test")
let (valid, errors) = validateArtifact(artifactPath)
check valid == true
check errors.len == 0
test "Validate artifact - missing directory":
let (valid, errors) = validateArtifact("/nonexistent/path")
check valid == false
check errors.len > 0
check "does not exist" in errors[0]
test "Validate artifact - empty directory":
let emptyPath = testCacheDir / "empty-artifact"
createDir(emptyPath)
let (valid, errors) = validateArtifact(emptyPath)
# Should be valid but with warnings
check valid == true
check errors.len > 0 # Has warning about being empty
test "Calculate directory hash":
# Create a test directory with content
let testDir = testCacheDir / "hash-test"
createDir(testDir)
writeFile(testDir / "file1.txt", "content1")
writeFile(testDir / "file2.txt", "content2")
let hash1 = calculateDirectoryHash(testDir)
# Hash should be consistent
let hash2 = calculateDirectoryHash(testDir)
check hash1 == hash2
# Hash should start with blake2b-
check hash1.startsWith("blake2b-")
test "Calculate directory hash - different content":
let testDir1 = testCacheDir / "hash-test-1"
let testDir2 = testCacheDir / "hash-test-2"
createDir(testDir1)
createDir(testDir2)
writeFile(testDir1 / "file.txt", "content1")
writeFile(testDir2 / "file.txt", "content2")
let hash1 = calculateDirectoryHash(testDir1)
let hash2 = calculateDirectoryHash(testDir2)
# Different content should produce different hashes
check hash1 != hash2
test "Build variant fingerprint":
var domains = initTable[string, seq[string]]()
domains["graphics"] = @["wayland"]
domains["audio"] = @["pipewire"]
let fingerprint = buildVariantFingerprint(
"test-package",
"1.0.0",
domains,
"nix"
)
# Should produce a hash
check fingerprint.len > 0
check fingerprint.startsWith("blake2b-")
test "Build variant fingerprint - consistency":
var domains = initTable[string, seq[string]]()
domains["graphics"] = @["wayland"]
let fp1 = buildVariantFingerprint("pkg", "1.0", domains, "nix")
let fp2 = buildVariantFingerprint("pkg", "1.0", domains, "nix")
# Same input should produce same fingerprint
check fp1 == fp2
test "Build variant fingerprint - different sources":
var domains = initTable[string, seq[string]]()
domains["graphics"] = @["wayland"]
let fpNix = buildVariantFingerprint("pkg", "1.0", domains, "nix")
let fpPkgsrc = buildVariantFingerprint("pkg", "1.0", domains, "pkgsrc")
# Different sources should produce different fingerprints
check fpNix != fpPkgsrc
test "Graft build artifact - basic flow":
# Create a mock build result
let artifactPath = testCacheDir / "mock-build"
createDir(artifactPath / "bin")
writeFile(artifactPath / "bin" / "test-app", "#!/bin/sh\necho test")
var domains = initTable[string, seq[string]]()
domains["test"] = @["value"]
let buildResult = BuildResult(
success: true,
source: "nix",
packageName: "test-package",
version: "1.0.0",
artifactPath: artifactPath,
buildLog: "",
variantFingerprint: "test-fp",
variantDomains: domains,
errors: @[],
warnings: @[]
)
let (success, installPath, errors) = graftBuildArtifact(
coordinator,
buildResult,
verbose = false
)
check success == true
check errors.len == 0
check installPath != ""
check dirExists(installPath)
# Check that files were copied
check fileExists(installPath / "bin" / "test-app")
# Check that Current symlink was created
let currentLink = testProgramsDir / "test-package" / "Current"
check symlinkExists(currentLink) or dirExists(currentLink)
test "Graft build artifact - with symlinks":
# Create a mock build result with executable
let artifactPath = testCacheDir / "mock-build-symlinks"
createDir(artifactPath / "bin")
let exePath = artifactPath / "bin" / "my-app"
writeFile(exePath, "#!/bin/sh\necho test")
# Make it executable
try:
setFilePermissions(exePath, {fpUserExec, fpUserRead, fpUserWrite})
except:
discard # Permissions might not work in all test environments
var domains = initTable[string, seq[string]]()
let buildResult = BuildResult(
success: true,
source: "nix",
packageName: "symlink-test",
version: "1.0.0",
artifactPath: artifactPath,
buildLog: "",
variantFingerprint: "test-fp-2",
variantDomains: domains,
errors: @[],
warnings: @[]
)
let (success, installPath, errors) = graftBuildArtifact(
coordinator,
buildResult,
verbose = false
)
check success == true
# Check that symlink was created (if autoSymlink is enabled)
let symlinkPath = testLinksDir / "Executables" / "my-app"
# Symlink might exist depending on system
if fileExists(symlinkPath) or symlinkExists(symlinkPath):
check true # Symlink was created
else:
check true # Symlink creation might have been skipped
test "Graft build artifact - failed build":
let buildResult = BuildResult(
success: false,
source: "nix",
packageName: "failed-package",
version: "1.0.0",
artifactPath: "",
buildLog: "",
variantFingerprint: "",
variantDomains: initTable[string, seq[string]](),
errors: @["Build failed"],
warnings: @[]
)
let (success, installPath, errors) = graftBuildArtifact(
coordinator,
buildResult,
verbose = false
)
# Should not graft failed builds
check success == false
check errors.len > 0
teardown:
# Clean up test directories
try:
if dirExists(testCacheDir):
removeDir(testCacheDir)
if dirExists(testProgramsDir):
removeDir(testProgramsDir)
if dirExists(testLinksDir):
removeDir(testLinksDir)
except:
discard # Cleanup failures are not critical