nip/tests/test_build_coordinator.nim

288 lines
9.0 KiB
Nim

## test_build_coordinator.nim
## Unit tests for BuildCoordinator
import std/[unittest, tables, times, os, options]
import ../src/nimpak/build/[types, coordinator, adapter]
import ../src/nimpak/graft_coordinator
import ../src/nimpak/install_manager
import ../src/nimpak/variants
# Mock adapter for testing
type
MockAdapter = ref object of BuildAdapter
shouldFail: bool
searchResult: bool
proc newMockAdapter(name: string, available: bool = true): MockAdapter =
result = MockAdapter(
name: name,
available: available,
packageCount: 100,
shouldFail: false,
searchResult: true
)
method isAvailable*(adapter: MockAdapter): bool =
adapter.available
method searchPackage*(
adapter: MockAdapter,
packageName: string
): Option[PackageInfo] =
if adapter.searchResult:
return some(PackageInfo(
name: packageName,
version: "1.0.0",
description: "Mock package",
source: adapter.name,
category: "",
available: true
))
return none(PackageInfo)
method buildPackage*(
adapter: MockAdapter,
request: BuildRequest
): BuildResult =
result = BuildResult(
success: not adapter.shouldFail,
source: adapter.name,
packageName: request.packageName,
version: "1.0.0",
artifactPath: if not adapter.shouldFail: "/mock/path" else: "",
buildLog: "Mock build log",
variantFingerprint: "mock-fingerprint",
variantDomains: request.variantFlags,
errors: if adapter.shouldFail: @["Mock build error"] else: @[],
warnings: @[],
buildTime: initDuration(seconds = 1)
)
suite "BuildCoordinator Tests":
setup:
let buildConfig = BuildConfig(
cacheDir: getTempDir() / "nip-test-cache",
buildLogsDir: getTempDir() / "nip-test-cache" / "logs",
keepWork: false,
rebuild: false,
noInstall: false,
timeout: initDuration(hours = 2),
jobs: 4,
verbose: false
)
# Create a minimal graft coordinator for testing
let installConfig = InstallConfig(
programsDir: getTempDir() / "Programs",
linksDir: getTempDir() / "System" / "Links",
cacheDir: getTempDir() / "nip-test-cache",
dbFile: getTempDir() / "nip-test.db",
autoSymlink: true,
checkConflicts: true,
verbose: false
)
let graftCoordinator = newGraftCoordinator(installConfig, false)
let coordinator = newBuildCoordinator(buildConfig, graftCoordinator)
test "BuildCoordinator initialization":
check coordinator != nil
check coordinator.config.cacheDir == getTempDir() / "nip-test-cache"
check coordinator.adapters.len == 0
check coordinator.verbose == false
test "Adapter registration":
let mockAdapter = newMockAdapter("mock")
coordinator.registerAdapter(mockAdapter)
check coordinator.adapters.len == 1
check coordinator.adapters.hasKey("mock")
test "Get adapter by name":
let mockAdapter = newMockAdapter("test-adapter")
coordinator.registerAdapter(mockAdapter)
let retrieved = coordinator.getAdapter("test-adapter")
check retrieved.isSome
check retrieved.get().name == "test-adapter"
test "Get non-existent adapter":
let retrieved = coordinator.getAdapter("non-existent")
check retrieved.isNone
test "Adapter name case insensitivity":
let mockAdapter = newMockAdapter("TestAdapter")
coordinator.registerAdapter(mockAdapter)
let retrieved1 = coordinator.getAdapter("testadapter")
let retrieved2 = coordinator.getAdapter("TESTADAPTER")
let retrieved3 = coordinator.getAdapter("TestAdapter")
check retrieved1.isSome
check retrieved2.isSome
check retrieved3.isSome
test "Source detection - Nix available":
if dirExists("/nix"):
let sources = coordinator.detectSources()
check "nix" in sources
test "Source detection - PKGSRC available":
if dirExists("/usr/pkgsrc"):
let sources = coordinator.detectSources()
check "pkgsrc" in sources
test "Source detection - Gentoo available":
if fileExists("/usr/bin/emerge"):
let sources = coordinator.detectSources()
check "gentoo" in sources
test "Source selection - auto with priority":
let nixAdapter = newMockAdapter("nix", available = true)
let pkgsrcAdapter = newMockAdapter("pkgsrc", available = true)
let gentooAdapter = newMockAdapter("gentoo", available = true)
coordinator.registerAdapter(nixAdapter)
coordinator.registerAdapter(pkgsrcAdapter)
coordinator.registerAdapter(gentooAdapter)
# Mock the detection to return all sources
if dirExists("/nix"):
let selected = coordinator.selectSource("auto")
check selected.isSome
check selected.get() == "nix" # Nix has highest priority
test "Source selection - specific source":
let mockAdapter = newMockAdapter("mock", available = true)
coordinator.registerAdapter(mockAdapter)
let selected = coordinator.selectSource("mock")
check selected.isSome
check selected.get() == "mock"
test "Source selection - unavailable source":
let mockAdapter = newMockAdapter("mock", available = false)
coordinator.registerAdapter(mockAdapter)
let selected = coordinator.selectSource("mock")
check selected.isNone
test "Source selection - no sources available":
# Don't register any adapters
let selected = coordinator.selectSource("auto")
# Result depends on actual system state
discard selected
test "Build package - successful build":
let mockAdapter = newMockAdapter("mock", available = true)
coordinator.registerAdapter(mockAdapter)
let variantFlags = @[
VariantFlag(domain: "graphics", value: "wayland"),
VariantFlag(domain: "optimization", value: "lto")
]
let result = coordinator.buildPackage("test-package", variantFlags, "mock")
check result.success == true
check result.packageName == "test-package"
check result.source == "mock"
check result.artifactPath == "/mock/path"
check result.errors.len == 0
test "Build package - failed build":
let mockAdapter = newMockAdapter("mock", available = true)
mockAdapter.shouldFail = true
coordinator.registerAdapter(mockAdapter)
let variantFlags: seq[VariantFlag] = @[]
let result = coordinator.buildPackage("test-package", variantFlags, "mock")
check result.success == false
check result.errors.len > 0
check "Mock build error" in result.errors
test "Build package - no suitable source":
let variantFlags: seq[VariantFlag] = @[]
let result = coordinator.buildPackage("test-package", variantFlags, "non-existent")
check result.success == false
check result.errors.len > 0
test "Build package - variant flags conversion":
let mockAdapter = newMockAdapter("mock", available = true)
coordinator.registerAdapter(mockAdapter)
let variantFlags = @[
VariantFlag(domain: "graphics", value: "wayland"),
VariantFlag(domain: "graphics", value: "vulkan"),
VariantFlag(domain: "audio", value: "pipewire")
]
let result = coordinator.buildPackage("test-package", variantFlags, "mock")
check result.success == true
check result.variantDomains.hasKey("graphics")
check result.variantDomains["graphics"].len == 2
check result.variantDomains.hasKey("audio")
check result.variantDomains["audio"].len == 1
test "Install build artifact - successful":
let mockResult = BuildResult(
success: true,
source: "mock",
packageName: "test-package",
version: "1.0.0",
artifactPath: "/mock/path",
buildLog: "",
variantFingerprint: "test-fingerprint",
variantDomains: initTable[string, seq[string]](),
errors: @[],
warnings: @[],
buildTime: initDuration(seconds = 1)
)
let installed = coordinator.installBuildArtifact(mockResult)
# Will fail because mock path doesn't exist, but that's expected
# The important thing is it returns a tuple with the right structure
check installed.errors.len >= 0 # Just check structure is correct
test "Install build artifact - failed build":
let mockResult = BuildResult(
success: false,
source: "mock",
packageName: "test-package",
version: "1.0.0",
artifactPath: "",
buildLog: "",
variantFingerprint: "",
variantDomains: initTable[string, seq[string]](),
errors: @["Build failed"],
warnings: @[],
buildTime: initDuration(seconds = 1)
)
let installed = coordinator.installBuildArtifact(mockResult)
check installed.success == false
test "Install build artifact - no install flag":
coordinator.config.noInstall = true
let mockResult = BuildResult(
success: true,
source: "mock",
packageName: "test-package",
version: "1.0.0",
artifactPath: "/mock/path",
buildLog: "",
variantFingerprint: "test-fingerprint",
variantDomains: initTable[string, seq[string]](),
errors: @[],
warnings: @[],
buildTime: initDuration(seconds = 1)
)
let installed = coordinator.installBuildArtifact(mockResult)
check installed.success == true # Returns true but skips installation