nip/tests/test_install_manager.nim

469 lines
14 KiB
Nim

# tests/test_install_manager.nim
# Unit tests for install_manager module
import unittest, os, times, json, tables, strutils, sequtils
import ../src/nimpak/install_manager
import ../src/nimpak/cas
suite "InstallManager Tests":
var testRoot: string
var manager: InstallManager
var config: InstallConfig
setup:
# Create temporary test directory
testRoot = getTempDir() / "nip_test_" & $epochTime().int
createDir(testRoot)
# Configure test environment
config = InstallConfig(
programsDir: testRoot / "Programs",
linksDir: testRoot / "System" / "Links",
cacheDir: testRoot / "cache",
dbFile: testRoot / "db" / "packages.json",
autoSymlink: true,
checkConflicts: true,
verbose: false
)
# Create manager
manager = newInstallManager(config)
teardown:
# Clean up test directory
if dirExists(testRoot):
removeDir(testRoot)
test "Create install manager with default config":
let defaultMgr = newInstallManager(defaultConfig())
check defaultMgr != nil
check defaultMgr.config.programsDir == "/Programs"
check defaultMgr.config.linksDir == "/System/Links"
check defaultMgr.config.autoSymlink == true
check defaultMgr.config.checkConflicts == true
test "Install package to temporary directory":
# Create a mock package source directory
let sourcePath = testRoot / "source" / "testpkg"
createDir(sourcePath / "bin")
createDir(sourcePath / "lib")
# Create test files
writeFile(sourcePath / "bin" / "testcmd", "#!/bin/sh\necho test")
writeFile(sourcePath / "lib" / "libtest.so.1", "mock library")
# Install the package
let metadata = %*{"description": "Test package"}
let result = manager.installPackage(
packageName = "testpkg",
version = "1.0.0",
source = "test",
sourcePath = sourcePath,
graftHash = "blake2b-abc123",
metadata = metadata
)
# Verify installation succeeded
check result.success == true
check result.packageName == "testpkg"
check result.version == "1.0.0"
check result.errors.len == 0
# Verify package directory was created
check dirExists(result.installPath)
check fileExists(result.installPath / "bin" / "testcmd")
check fileExists(result.installPath / "lib" / "libtest.so.1")
# Verify package is in database
check manager.isInstalled("testpkg")
let pkg = manager.getInstalledPackage("testpkg")
check pkg.name == "testpkg"
check pkg.version == "1.0.0"
check pkg.source == "test"
test "Install package with variant descriptor":
let sourcePath = testRoot / "source" / "varpkg"
createDir(sourcePath / "bin")
writeFile(sourcePath / "bin" / "varcmd", "#!/bin/sh\necho variant")
# Install with custom variant
let result = manager.installPackage(
packageName = "varpkg",
version = "2.0.0",
source = "test",
sourcePath = sourcePath,
graftHash = "blake2b-def456",
metadata = newJObject(),
variantDescriptor = "optimized"
)
check result.success == true
check "optimized" in result.installPath
test "Symlink creation for executables":
let sourcePath = testRoot / "source" / "binpkg"
createDir(sourcePath / "bin")
writeFile(sourcePath / "bin" / "cmd1", "#!/bin/sh\necho cmd1")
writeFile(sourcePath / "bin" / "cmd2", "#!/bin/sh\necho cmd2")
let result = manager.installPackage(
packageName = "binpkg",
version = "1.0.0",
source = "test",
sourcePath = sourcePath,
graftHash = "blake2b-bin123"
)
check result.success == true
check result.symlinksCreated.len == 2
# Verify symlinks were created
let execDir = config.linksDir / "Executables"
check symlinkExists(execDir / "cmd1")
check symlinkExists(execDir / "cmd2")
test "Symlink creation for libraries":
let sourcePath = testRoot / "source" / "libpkg"
createDir(sourcePath / "lib")
writeFile(sourcePath / "lib" / "libfoo.so.1", "library")
writeFile(sourcePath / "lib" / "libbar.so.2.0", "library")
let result = manager.installPackage(
packageName = "libpkg",
version = "1.0.0",
source = "test",
sourcePath = sourcePath,
graftHash = "blake2b-lib123"
)
check result.success == true
check result.symlinksCreated.len == 2
# Verify library symlinks
let libDir = config.linksDir / "Libraries"
check symlinkExists(libDir / "libfoo.so.1")
check symlinkExists(libDir / "libbar.so.2.0")
test "Package removal and cleanup":
# First install a package
let sourcePath = testRoot / "source" / "rmpkg"
createDir(sourcePath / "bin")
writeFile(sourcePath / "bin" / "rmcmd", "#!/bin/sh\necho remove")
let installResult = manager.installPackage(
packageName = "rmpkg",
version = "1.0.0",
source = "test",
sourcePath = sourcePath,
graftHash = "blake2b-rm123"
)
check installResult.success == true
check manager.isInstalled("rmpkg")
# Now remove it
let removeResult = manager.removePackage("rmpkg")
check removeResult.success == true
check removeResult.packageName == "rmpkg"
check removeResult.errors.len == 0
# Verify package was removed
check not manager.isInstalled("rmpkg")
check not dirExists(installResult.installPath)
# Verify symlinks were removed
let execDir = config.linksDir / "Executables"
check not symlinkExists(execDir / "rmcmd")
test "Remove non-existent package":
let result = manager.removePackage("nonexistent")
check result.success == false
check result.errors.len > 0
check "not installed" in result.errors[0]
test "Conflict detection - executable":
# Install first package
let source1 = testRoot / "source" / "pkg1"
createDir(source1 / "bin")
writeFile(source1 / "bin" / "conflict", "#!/bin/sh\necho pkg1")
let result1 = manager.installPackage(
packageName = "pkg1",
version = "1.0.0",
source = "test",
sourcePath = source1,
graftHash = "blake2b-pkg1"
)
check result1.success == true
# Try to install second package with same executable
let source2 = testRoot / "source" / "pkg2"
createDir(source2 / "bin")
writeFile(source2 / "bin" / "conflict", "#!/bin/sh\necho pkg2")
let result2 = manager.installPackage(
packageName = "pkg2",
version = "1.0.0",
source = "test",
sourcePath = source2,
graftHash = "blake2b-pkg2"
)
# Installation should succeed but with warnings
check result2.success == true
check result2.warnings.len > 0
check "conflict" in result2.warnings[0].toLowerAscii()
test "Conflict detection - library":
# Install first package with library
let source1 = testRoot / "source" / "libpkg1"
createDir(source1 / "lib")
writeFile(source1 / "lib" / "libconflict.so.1", "lib1")
let result1 = manager.installPackage(
packageName = "libpkg1",
version = "1.0.0",
source = "test",
sourcePath = source1,
graftHash = "blake2b-libpkg1"
)
check result1.success == true
# Try to install second package with same library
let source2 = testRoot / "source" / "libpkg2"
createDir(source2 / "lib")
writeFile(source2 / "lib" / "libconflict.so.1", "lib2")
let result2 = manager.installPackage(
packageName = "libpkg2",
version = "1.0.0",
source = "test",
sourcePath = source2,
graftHash = "blake2b-libpkg2"
)
check result2.success == true
check result2.warnings.len > 0
test "List installed packages":
# Install multiple packages
for i in 1..3:
let sourcePath = testRoot / "source" / "pkg" & $i
createDir(sourcePath / "bin")
writeFile(sourcePath / "bin" / "cmd" & $i, "test")
let result = manager.installPackage(
packageName = "pkg" & $i,
version = "1.0.0",
source = "test",
sourcePath = sourcePath,
graftHash = "blake2b-pkg" & $i
)
check result.success == true
# List packages
let installed = manager.listInstalled()
check installed.len == 3
# Verify package names
let names = installed.mapIt(it.name)
check "pkg1" in names
check "pkg2" in names
check "pkg3" in names
test "Get system status":
# Install a package
let sourcePath = testRoot / "source" / "statuspkg"
createDir(sourcePath / "bin")
writeFile(sourcePath / "bin" / "statuscmd", "test")
discard manager.installPackage(
packageName = "statuspkg",
version = "1.0.0",
source = "test",
sourcePath = sourcePath,
graftHash = "blake2b-status"
)
# Get status
let status = manager.getStatus()
check status.hasKey("total_packages")
check status["total_packages"].getInt() == 1
check status.hasKey("by_source")
check status.hasKey("total_size_mb")
check status.hasKey("programs_dir")
check status.hasKey("links_dir")
test "Database persistence":
# Install a package
let sourcePath = testRoot / "source" / "dbpkg"
createDir(sourcePath / "bin")
writeFile(sourcePath / "bin" / "dbcmd", "test")
let result = manager.installPackage(
packageName = "dbpkg",
version = "1.0.0",
source = "test",
sourcePath = sourcePath,
graftHash = "blake2b-db123"
)
check result.success == true
# Create new manager to test database loading
let manager2 = newInstallManager(config)
# Verify package was loaded from database
check manager2.isInstalled("dbpkg")
let pkg = manager2.getInstalledPackage("dbpkg")
check pkg.name == "dbpkg"
check pkg.version == "1.0.0"
test "Database backup creation":
# Install first package
let source1 = testRoot / "source" / "backup1"
createDir(source1 / "bin")
writeFile(source1 / "bin" / "cmd1", "test")
discard manager.installPackage(
packageName = "backup1",
version = "1.0.0",
source = "test",
sourcePath = source1,
graftHash = "blake2b-backup1"
)
# Install second package (should create backup)
let source2 = testRoot / "source" / "backup2"
createDir(source2 / "bin")
writeFile(source2 / "bin" / "cmd2", "test")
discard manager.installPackage(
packageName = "backup2",
version = "1.0.0",
source = "test",
sourcePath = source2,
graftHash = "blake2b-backup2"
)
# Check for backup files
let dbDir = parentDir(config.dbFile)
var backupFound = false
for file in walkDir(dbDir):
if ".backup." in extractFilename(file.path):
backupFound = true
break
check backupFound == true
test "Install with missing source directory":
let result = manager.installPackage(
packageName = "missing",
version = "1.0.0",
source = "test",
sourcePath = testRoot / "nonexistent",
graftHash = "blake2b-missing"
)
check result.success == false
check result.errors.len > 0
check "does not exist" in result.errors[0]
test "Install duplicate package":
# Install package first time
let sourcePath = testRoot / "source" / "duppkg"
createDir(sourcePath / "bin")
writeFile(sourcePath / "bin" / "dupcmd", "test")
let result1 = manager.installPackage(
packageName = "duppkg",
version = "1.0.0",
source = "test",
sourcePath = sourcePath,
graftHash = "blake2b-dup123"
)
check result1.success == true
# Try to install again
let result2 = manager.installPackage(
packageName = "duppkg",
version = "1.0.0",
source = "test",
sourcePath = sourcePath,
graftHash = "blake2b-dup123"
)
check result2.success == false
check result2.errors.len > 0
check "already installed" in result2.errors[0]
test "Symlink creation with auto-symlink disabled":
# Create manager with auto-symlink disabled
var noSymlinkConfig = config
noSymlinkConfig.autoSymlink = false
let noSymlinkMgr = newInstallManager(noSymlinkConfig)
let sourcePath = testRoot / "source" / "nosympkg"
createDir(sourcePath / "bin")
writeFile(sourcePath / "bin" / "nosymcmd", "test")
let result = noSymlinkMgr.installPackage(
packageName = "nosympkg",
version = "1.0.0",
source = "test",
sourcePath = sourcePath,
graftHash = "blake2b-nosym"
)
check result.success == true
check result.symlinksCreated.len == 0
test "Current symlink creation and switching":
# Install first variant
let source1 = testRoot / "source" / "varpkg1"
createDir(source1 / "bin")
writeFile(source1 / "bin" / "varcmd", "variant1")
let result1 = manager.installPackage(
packageName = "varpkg",
version = "1.0.0",
source = "test",
sourcePath = source1,
graftHash = "blake2b-var1",
variantDescriptor = "default"
)
check result1.success == true
# Verify Current symlink exists
let versionDir = config.programsDir / "varpkg" / "1.0.0"
let currentLink = versionDir / "Current"
check symlinkExists(currentLink)
# Install second variant (should switch Current)
let source2 = testRoot / "source" / "varpkg2"
createDir(source2 / "bin")
writeFile(source2 / "bin" / "varcmd", "variant2")
let result2 = manager.installPackage(
packageName = "varpkg",
version = "1.0.0",
source = "test",
sourcePath = source2,
graftHash = "blake2b-var2",
variantDescriptor = "optimized"
)
check result2.success == true
check symlinkExists(currentLink)
# Current should now point to optimized variant
let target = expandSymlink(currentLink)
check "optimized" in target