nip/tests/test_orchestrator.nim

456 lines
12 KiB
Nim

## Tests for Resolution Orchestrator
##
## This test suite verifies the orchestrator's ability to coordinate
## all resolver components and provide a unified resolution interface.
import unittest
import tables
import ../src/nip/resolver/orchestrator
import ../src/nip/resolver/types
import ../src/nip/cas/storage
suite "Orchestrator Construction":
test "Create with default config":
let cas = newCASStorage("/tmp/test-orch-1")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
check orch.getConfig().enableCache == true
check orch.getConfig().enableParallel == false
check orch.getConfig().maxRetries == 3
check orch.getConfig().l1CacheCapacity == 100
test "Create with custom config":
let cas = newCASStorage("/tmp/test-orch-2")
let repos: seq[Repository] = @[]
let config = ResolverConfig(
enableCache: false,
enableParallel: true,
maxRetries: 5,
timeout: initDuration(seconds = 600),
l1CacheCapacity: 200
)
let orch = newResolutionOrchestrator(cas, repos, config)
check orch.getConfig().enableCache == false
check orch.getConfig().enableParallel == true
check orch.getConfig().maxRetries == 5
check orch.getConfig().l1CacheCapacity == 200
suite "Basic Resolution":
test "Resolve simple package":
let cas = newCASStorage("/tmp/test-orch-3")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
let result = orch.resolve(
"test-pkg",
"*",
VariantDemand(
useFlags: @[],
libc: "musl",
allocator: "jemalloc",
targetArch: "x86_64",
buildFlags: @[]
)
)
check result.isOk
check result.get.cacheHit == false
check result.get.resolutionTime >= 0.0
test "Resolve with version constraint":
let cas = newCASStorage("/tmp/test-orch-4")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
let result = orch.resolve(
"nginx",
">=1.24.0",
VariantDemand(
useFlags: @["ssl", "http2"],
libc: "musl",
allocator: "jemalloc",
targetArch: "x86_64",
buildFlags: @[]
)
)
check result.isOk
test "Resolve with USE flags":
let cas = newCASStorage("/tmp/test-orch-5")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
let result = orch.resolve(
"firefox",
"*",
VariantDemand(
useFlags: @["wayland", "pulseaudio", "alsa"],
libc: "glibc",
allocator: "default",
targetArch: "x86_64",
buildFlags: @["-O3", "-march=native"]
)
)
check result.isOk
suite "Caching Behavior":
test "Cache miss on first resolution":
let cas = newCASStorage("/tmp/test-orch-6")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
let result = orch.resolve(
"test-pkg",
"*",
VariantDemand(
useFlags: @[],
libc: "musl",
allocator: "jemalloc",
targetArch: "x86_64",
buildFlags: @[]
)
)
check result.isOk
check result.get.cacheHit == false
let metrics = orch.getMetrics()
check metrics.cacheMisses == 1
check metrics.cacheHits == 0
test "Cache hit on second resolution":
let cas = newCASStorage("/tmp/test-orch-7")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
let demand = VariantDemand(
useFlags: @[],
libc: "musl",
allocator: "jemalloc",
targetArch: "x86_64",
buildFlags: @[]
)
# First resolution
let result1 = orch.resolve("test-pkg", "*", demand)
check result1.isOk
check result1.get.cacheHit == false
# Second resolution (should hit cache)
let result2 = orch.resolve("test-pkg", "*", demand)
check result2.isOk
check result2.get.cacheHit == true
let metrics = orch.getMetrics()
check metrics.cacheHits == 1
check metrics.cacheMisses == 1
test "Different variants produce different cache keys":
let cas = newCASStorage("/tmp/test-orch-8")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
let demand1 = VariantDemand(
useFlags: @["ssl"],
libc: "musl",
allocator: "jemalloc",
targetArch: "x86_64",
buildFlags: @[]
)
let demand2 = VariantDemand(
useFlags: @["ssl", "http2"], # Different USE flags
libc: "musl",
allocator: "jemalloc",
targetArch: "x86_64",
buildFlags: @[]
)
# Resolve with first variant
let result1 = orch.resolve("nginx", "*", demand1)
check result1.isOk
check result1.get.cacheHit == false
# Resolve with second variant (different cache key)
let result2 = orch.resolve("nginx", "*", demand2)
check result2.isOk
check result2.get.cacheHit == false
let metrics = orch.getMetrics()
check metrics.cacheMisses == 2
check metrics.cacheHits == 0
test "Disabled cache always misses":
let cas = newCASStorage("/tmp/test-orch-9")
let repos: seq[Repository] = @[]
let config = ResolverConfig(
enableCache: false,
enableParallel: false,
maxRetries: 3,
timeout: initDuration(seconds = 300),
l1CacheCapacity: 100
)
let orch = newResolutionOrchestrator(cas, repos, config)
let demand = VariantDemand(
useFlags: @[],
libc: "musl",
allocator: "jemalloc",
targetArch: "x86_64",
buildFlags: @[]
)
# First resolution
let result1 = orch.resolve("test-pkg", "*", demand)
check result1.isOk
check result1.get.cacheHit == false
# Second resolution (cache disabled, should still miss)
let result2 = orch.resolve("test-pkg", "*", demand)
check result2.isOk
check result2.get.cacheHit == false
suite "Metrics Tracking":
test "Track total resolutions":
let cas = newCASStorage("/tmp/test-orch-10")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
let demand = VariantDemand(
useFlags: @[],
libc: "musl",
allocator: "jemalloc",
targetArch: "x86_64",
buildFlags: @[]
)
for i in 0..<5:
discard orch.resolve(fmt"pkg-{i}", "*", demand)
let metrics = orch.getMetrics()
check metrics.totalResolutions == 5
check metrics.successfulResolutions == 5
test "Track cache hit rate":
let cas = newCASStorage("/tmp/test-orch-11")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
let demand = VariantDemand(
useFlags: @[],
libc: "musl",
allocator: "jemalloc",
targetArch: "x86_64",
buildFlags: @[]
)
# First resolution (miss)
discard orch.resolve("test-pkg", "*", demand)
# Three more resolutions (hits)
for i in 0..<3:
discard orch.resolve("test-pkg", "*", demand)
let metrics = orch.getMetrics()
check metrics.totalResolutions == 4
check metrics.cacheHits == 3
check metrics.cacheMisses == 1
test "Reset metrics":
let cas = newCASStorage("/tmp/test-orch-12")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
let demand = VariantDemand(
useFlags: @[],
libc: "musl",
allocator: "jemalloc",
targetArch: "x86_64",
buildFlags: @[]
)
# Do some resolutions
for i in 0..<3:
discard orch.resolve(fmt"pkg-{i}", "*", demand)
check orch.getMetrics().totalResolutions == 3
# Reset metrics
orch.resetMetrics()
check orch.getMetrics().totalResolutions == 0
check orch.getMetrics().cacheHits == 0
check orch.getMetrics().cacheMisses == 0
suite "Configuration Management":
test "Update configuration":
let cas = newCASStorage("/tmp/test-orch-13")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
check orch.getConfig().enableCache == true
var newConfig = config
newConfig.enableCache = false
orch.updateConfig(newConfig)
check orch.getConfig().enableCache == false
test "Configuration affects behavior":
let cas = newCASStorage("/tmp/test-orch-14")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
let demand = VariantDemand(
useFlags: @[],
libc: "musl",
allocator: "jemalloc",
targetArch: "x86_64",
buildFlags: @[]
)
# Resolve with cache enabled
let result1 = orch.resolve("test-pkg", "*", demand)
check result1.isOk
let result2 = orch.resolve("test-pkg", "*", demand)
check result2.get.cacheHit == true
# Disable cache
var newConfig = orch.getConfig()
newConfig.enableCache = false
orch.updateConfig(newConfig)
# Resolve with cache disabled
let result3 = orch.resolve("test-pkg", "*", demand)
check result3.get.cacheHit == false
suite "Cache Management":
test "Clear cache":
let cas = newCASStorage("/tmp/test-orch-15")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
let demand = VariantDemand(
useFlags: @[],
libc: "musl",
allocator: "jemalloc",
targetArch: "x86_64",
buildFlags: @[]
)
# Populate cache
discard orch.resolve("test-pkg", "*", demand)
# Verify cache hit
let result1 = orch.resolve("test-pkg", "*", demand)
check result1.get.cacheHit == true
# Clear cache
orch.clearCache()
# Verify cache miss
let result2 = orch.resolve("test-pkg", "*", demand)
check result2.get.cacheHit == false
test "Get cache metrics":
let cas = newCASStorage("/tmp/test-orch-16")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
let cacheMetrics = orch.getCacheMetrics()
check cacheMetrics.l1Size == 0
check cacheMetrics.l1Capacity == 100
suite "Repository Management":
test "Update repositories":
let cas = newCASStorage("/tmp/test-orch-17")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
check orch.getRepositories().len == 0
let newRepos = @[
Repository(
name: "main",
packages: @[]
)
]
orch.updateRepositories(newRepos)
check orch.getRepositories().len == 1
check orch.getRepositories()[0].name == "main"
test "Repository update invalidates cache":
let cas = newCASStorage("/tmp/test-orch-18")
let repos: seq[Repository] = @[]
let config = defaultConfig()
let orch = newResolutionOrchestrator(cas, repos, config)
let demand = VariantDemand(
useFlags: @[],
libc: "musl",
allocator: "jemalloc",
targetArch: "x86_64",
buildFlags: @[]
)
# Populate cache
discard orch.resolve("test-pkg", "*", demand)
# Verify cache hit
let result1 = orch.resolve("test-pkg", "*", demand)
check result1.get.cacheHit == true
# Update repositories (should invalidate cache)
let newRepos = @[
Repository(
name: "main",
packages: @[]
)
]
orch.updateRepositories(newRepos)
# Verify cache miss (invalidated)
let result2 = orch.resolve("test-pkg", "*", demand)
check result2.get.cacheHit == false