257 lines
7.3 KiB
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
|