nip/tests/test_nix_adapter.nim

316 lines
8.7 KiB
Nim

## test_nix_adapter.nim
## Unit tests for NixAdapter
import std/[unittest, tables, os, strutils, options]
import ../src/nimpak/build/[types, nix_adapter]
suite "NixAdapter Tests":
test "NixAdapter initialization":
let adapter = newNixAdapter()
check adapter != nil
check adapter.name == "nix"
check adapter.nixpkgsPath == "<nixpkgs>"
check adapter.storeDir == "/nix/store"
check adapter.packageCount == 100000
test "NixAdapter availability check":
let adapter = newNixAdapter()
let available = adapter.isAvailable()
# Should match actual system state
check available == dirExists("/nix")
test "Package name validation - valid names":
let adapter = newNixAdapter()
let validNames = @[
"firefox",
"nixpkgs.firefox",
"my-package",
"package_name",
"package.with.dots",
"Package123"
]
for name in validNames:
let request = BuildRequest(
packageName: name,
version: "",
variantFlags: initTable[string, seq[string]](),
sourceFlags: @[],
cacheDir: getTempDir(),
verbose: false
)
# Should not raise ValidationError
try:
discard adapter.buildPackage(request)
except ValidationError:
fail()
test "Package name validation - invalid names":
let adapter = newNixAdapter()
let invalidNames = @[
"",
"../etc/passwd",
"/absolute/path",
"package;rm -rf /",
"package`whoami`",
"package$(whoami)",
"a" & "b".repeat(300) # Too long
]
for name in invalidNames:
let request = BuildRequest(
packageName: name,
version: "",
variantFlags: initTable[string, seq[string]](),
sourceFlags: @[],
cacheDir: getTempDir(),
verbose: false
)
let result = adapter.buildPackage(request)
check result.success == false
check result.errors.len > 0
test "Nix expression generation - no overrides":
let adapter = newNixAdapter()
# We can't directly test the private generateNixExpression,
# but we can test it through buildPackage
let request = BuildRequest(
packageName: "hello",
version: "",
variantFlags: initTable[string, seq[string]](),
sourceFlags: @[],
cacheDir: getTempDir() / "nip-test-cache",
verbose: false
)
# This will generate the expression file
discard adapter.buildPackage(request)
# Check that expression file was created
let exprFile = getTempDir() / "nip-test-cache" / "nix" / "build-hello.nix"
if fileExists(exprFile):
let content = readFile(exprFile)
check "with import <nixpkgs> {};" in content
check "hello" in content
test "Nix expression generation - with overrides":
let adapter = newNixAdapter()
let request = BuildRequest(
packageName: "firefox",
version: "",
variantFlags: initTable[string, seq[string]](),
sourceFlags: @["waylandSupport = true", "enableLTO = true"],
cacheDir: getTempDir() / "nip-test-cache",
verbose: false
)
discard adapter.buildPackage(request)
let exprFile = getTempDir() / "nip-test-cache" / "nix" / "build-firefox.nix"
if fileExists(exprFile):
let content = readFile(exprFile)
check "with import <nixpkgs> {};" in content
check "firefox" in content
check ".override" in content
check "waylandSupport = true" in content
check "enableLTO = true" in content
test "Override key validation - valid keys":
let adapter = newNixAdapter()
let validFlags = @[
"waylandSupport = true",
"enable-feature = false",
"with_option = true",
"flag123 = true"
]
let request = BuildRequest(
packageName: "test",
version: "",
variantFlags: initTable[string, seq[string]](),
sourceFlags: validFlags,
cacheDir: getTempDir() / "nip-test-cache",
verbose: false
)
# Should not raise ValidationError
let result = adapter.buildPackage(request)
# May fail at nix-build stage, but not at validation
if not result.success and result.errors.len > 0:
check "Invalid override key" notin result.errors[0]
test "Override key validation - invalid keys":
let adapter = newNixAdapter()
# Test with malicious override key
let request = BuildRequest(
packageName: "test",
version: "",
variantFlags: initTable[string, seq[string]](),
sourceFlags: @["bad;key = true"],
cacheDir: getTempDir() / "nip-test-cache",
verbose: false
)
let result = adapter.buildPackage(request)
check result.success == false
test "Build result structure":
let adapter = newNixAdapter()
let request = BuildRequest(
packageName: "test-package",
version: "",
variantFlags: initTable[string, seq[string]](),
sourceFlags: @[],
cacheDir: getTempDir() / "nip-test-cache",
verbose: false
)
let result = adapter.buildPackage(request)
# Check result structure
check result.source == "nix"
check result.packageName == "test-package"
# success may be false if nix-build fails, which is expected in test environment
test "Cache directory creation":
let cacheDir = getTempDir() / "nip-test-cache-new"
# Remove if exists
if dirExists(cacheDir):
removeDir(cacheDir)
let adapter = newNixAdapter()
let request = BuildRequest(
packageName: "test",
version: "",
variantFlags: initTable[string, seq[string]](),
sourceFlags: @[],
cacheDir: cacheDir,
verbose: false
)
discard adapter.buildPackage(request)
# Check that cache directory was created
check dirExists(cacheDir / "nix")
test "Package name sanitization for filenames":
let adapter = newNixAdapter()
# Package name with dots should be sanitized for filename
let request = BuildRequest(
packageName: "nixpkgs.firefox",
version: "",
variantFlags: initTable[string, seq[string]](),
sourceFlags: @[],
cacheDir: getTempDir() / "nip-test-cache",
verbose: false
)
discard adapter.buildPackage(request)
# Check that file was created with sanitized name
let exprFile = getTempDir() / "nip-test-cache" / "nix" / "build-nixpkgs_firefox.nix"
check fileExists(exprFile)
test "Variant flags in build result":
let adapter = newNixAdapter()
var variantFlags = initTable[string, seq[string]]()
variantFlags["graphics"] = @["wayland", "vulkan"]
variantFlags["audio"] = @["pipewire"]
let request = BuildRequest(
packageName: "test",
version: "",
variantFlags: variantFlags,
sourceFlags: @[],
cacheDir: getTempDir() / "nip-test-cache",
verbose: false
)
let result = adapter.buildPackage(request)
# Variant flags should be preserved in result
check result.variantDomains.hasKey("graphics")
check result.variantDomains.hasKey("audio")
test "Error handling - build failure":
let adapter = newNixAdapter()
# Use a package name that will definitely fail
let request = BuildRequest(
packageName: "this-package-definitely-does-not-exist-12345",
version: "",
variantFlags: initTable[string, seq[string]](),
sourceFlags: @[],
cacheDir: getTempDir() / "nip-test-cache",
verbose: false
)
let result = adapter.buildPackage(request)
# Should fail gracefully
check result.success == false
check result.errors.len > 0
test "Verbose mode":
let adapter = newNixAdapter()
let request = BuildRequest(
packageName: "test",
version: "",
variantFlags: initTable[string, seq[string]](),
sourceFlags: @[],
cacheDir: getTempDir() / "nip-test-cache",
verbose: true
)
# Should not crash with verbose mode
discard adapter.buildPackage(request)
# Only run search tests if Nix is actually available
if dirExists("/nix"):
suite "NixAdapter Search Tests (Nix Available)":
test "Search for existing package":
let adapter = newNixAdapter()
# Search for a package that should exist
let result = adapter.searchPackage("hello")
# May or may not find it depending on nixpkgs availability
if result.isSome:
let info = result.get()
check info.name == "hello"
check info.source == "nix"
check info.available == true
test "Search for non-existent package":
let adapter = newNixAdapter()
let result = adapter.searchPackage("this-package-does-not-exist-xyz123")
# Should return none
check result.isNone
test "Search with invalid package name":
let adapter = newNixAdapter()
let result = adapter.searchPackage("../etc/passwd")
# Should return none due to validation
check result.isNone