391 lines
11 KiB
Nim
391 lines
11 KiB
Nim
## Integration Tests for CAS Integration
|
|
##
|
|
## Tests for the CAS integration module which bridges build synthesis
|
|
## with the existing Content-Addressable Storage system.
|
|
|
|
import std/[unittest, os, tempfiles, times, tables, options]
|
|
import ../src/nip/resolver/build_synthesis
|
|
import ../src/nip/resolver/variant_types
|
|
import ../src/nip/resolver/cas_integration
|
|
|
|
# Helper to count table entries
|
|
proc tableLen[K, V](t: Table[K, V]): int =
|
|
result = 0
|
|
for _ in t.keys:
|
|
result += 1
|
|
|
|
suite "CAS Integration Tests":
|
|
|
|
test "Create CAS integration manager":
|
|
## Test creating a CAS integration manager
|
|
|
|
let casRoot = getTempDir() / "test_cas_" & $getTime().toUnix()
|
|
createDir(casRoot)
|
|
|
|
try:
|
|
let manager = newCASIntegrationManager(casRoot)
|
|
|
|
check manager.casRoot == casRoot
|
|
check tableLen(manager.references) == 0
|
|
check tableLen(manager.artifacts) == 0
|
|
|
|
finally:
|
|
removeDir(casRoot)
|
|
|
|
test "Store build in CAS":
|
|
## Test storing a synthesized build in the CAS
|
|
|
|
let casRoot = getTempDir() / "test_cas_" & $getTime().toUnix()
|
|
createDir(casRoot)
|
|
|
|
try:
|
|
var manager = newCASIntegrationManager(casRoot)
|
|
|
|
# Create variant profile
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
# Synthesize build
|
|
let buildResult = synthesizeBuild(
|
|
packageName = "nginx",
|
|
packageVersion = "1.24.0",
|
|
variantProfile = profile,
|
|
sourceHash = "blake3-abc123"
|
|
)
|
|
|
|
# Store in CAS
|
|
let storeResult = manager.storeBuildInCAS(buildResult)
|
|
|
|
check storeResult.isOk
|
|
check tableLen(manager.references) == 1
|
|
check tableLen(manager.artifacts) == 1
|
|
|
|
finally:
|
|
removeDir(casRoot)
|
|
|
|
test "Retrieve build from CAS":
|
|
## Test retrieving a stored build from the CAS
|
|
|
|
let casRoot = getTempDir() / "test_cas_" & $getTime().toUnix()
|
|
createDir(casRoot)
|
|
|
|
try:
|
|
var manager = newCASIntegrationManager(casRoot)
|
|
|
|
# Create and store build
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let buildResult = synthesizeBuild(
|
|
packageName = "nginx",
|
|
packageVersion = "1.24.0",
|
|
variantProfile = profile,
|
|
sourceHash = "blake3-abc123"
|
|
)
|
|
|
|
let storeResult = manager.storeBuildInCAS(buildResult)
|
|
check storeResult.isOk
|
|
|
|
let casHash = storeResult.get()
|
|
|
|
# Retrieve from CAS
|
|
let retrieveResult = manager.retrieveBuildFromCAS(casHash)
|
|
|
|
check retrieveResult.isOk
|
|
let retrieved = retrieveResult.get()
|
|
check retrieved.buildHash == buildResult.buildHash
|
|
check retrieved.buildConfig.packageName == "nginx"
|
|
check retrieved.buildConfig.packageVersion == "1.24.0"
|
|
|
|
finally:
|
|
removeDir(casRoot)
|
|
|
|
test "Verify build in CAS":
|
|
## Test verifying that a build exists in the CAS
|
|
|
|
let casRoot = getTempDir() / "test_cas_" & $getTime().toUnix()
|
|
createDir(casRoot)
|
|
|
|
try:
|
|
var manager = newCASIntegrationManager(casRoot)
|
|
|
|
# Create and store build
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let buildResult = synthesizeBuild(
|
|
packageName = "nginx",
|
|
packageVersion = "1.24.0",
|
|
variantProfile = profile,
|
|
sourceHash = "blake3-abc123"
|
|
)
|
|
|
|
let storeResult = manager.storeBuildInCAS(buildResult)
|
|
check storeResult.isOk
|
|
|
|
# Verify build exists
|
|
check manager.verifyBuildInCAS(buildResult.buildHash) == true
|
|
|
|
# Verify non-existent build
|
|
check manager.verifyBuildInCAS("xxh3-nonexistent") == false
|
|
|
|
finally:
|
|
removeDir(casRoot)
|
|
|
|
test "Reference counting":
|
|
## Test reference counting for builds
|
|
|
|
let casRoot = getTempDir() / "test_cas_" & $getTime().toUnix()
|
|
createDir(casRoot)
|
|
|
|
try:
|
|
var manager = newCASIntegrationManager(casRoot)
|
|
|
|
# Create and store build
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let buildResult = synthesizeBuild(
|
|
packageName = "nginx",
|
|
packageVersion = "1.24.0",
|
|
variantProfile = profile,
|
|
sourceHash = "blake3-abc123"
|
|
)
|
|
|
|
let storeResult = manager.storeBuildInCAS(buildResult)
|
|
check storeResult.isOk
|
|
|
|
# Check initial reference count
|
|
let initialCount = manager.getReferenceCount(buildResult.buildHash)
|
|
var hasInitial = false
|
|
if initialCount.isSome:
|
|
hasInitial = true
|
|
check hasInitial
|
|
check initialCount.get() == 1
|
|
|
|
# Increment reference
|
|
let incResult = manager.incrementReference(buildResult.buildHash)
|
|
check incResult.isOk
|
|
|
|
let newCount = manager.getReferenceCount(buildResult.buildHash)
|
|
var hasNew = false
|
|
if newCount.isSome:
|
|
hasNew = true
|
|
check hasNew
|
|
check newCount.get() == 2
|
|
|
|
# Decrement reference
|
|
let decResult = manager.decrementReference(buildResult.buildHash)
|
|
check decResult.isOk
|
|
check decResult.get() == 1
|
|
|
|
finally:
|
|
removeDir(casRoot)
|
|
|
|
test "List tracked builds":
|
|
## Test listing all tracked builds
|
|
|
|
let casRoot = getTempDir() / "test_cas_" & $getTime().toUnix()
|
|
createDir(casRoot)
|
|
|
|
try:
|
|
var manager = newCASIntegrationManager(casRoot)
|
|
|
|
# Create and store multiple builds
|
|
for i in 0..<3:
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let buildResult = synthesizeBuild(
|
|
packageName = "package" & $i,
|
|
packageVersion = "1.0.0",
|
|
variantProfile = profile,
|
|
sourceHash = "blake3-" & $i
|
|
)
|
|
|
|
discard manager.storeBuildInCAS(buildResult)
|
|
|
|
# List tracked builds
|
|
let tracked = manager.listTrackedBuilds()
|
|
check tracked.len() == 3
|
|
|
|
finally:
|
|
removeDir(casRoot)
|
|
|
|
test "Get artifact metadata":
|
|
## Test retrieving artifact metadata
|
|
|
|
let casRoot = getTempDir() / "test_cas_" & $getTime().toUnix()
|
|
createDir(casRoot)
|
|
|
|
try:
|
|
var manager = newCASIntegrationManager(casRoot)
|
|
|
|
# Create and store build
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let buildResult = synthesizeBuild(
|
|
packageName = "nginx",
|
|
packageVersion = "1.24.0",
|
|
variantProfile = profile,
|
|
sourceHash = "blake3-abc123"
|
|
)
|
|
|
|
let storeResult = manager.storeBuildInCAS(buildResult)
|
|
check storeResult.isOk
|
|
|
|
# Get artifact metadata
|
|
let metadata = manager.getArtifactMetadata(buildResult.buildHash)
|
|
var hasMetadata = false
|
|
if metadata.isSome:
|
|
hasMetadata = true
|
|
check hasMetadata
|
|
|
|
let artifact = metadata.get()
|
|
check artifact.buildHash == buildResult.buildHash
|
|
check artifact.compressed == true
|
|
check artifact.size > 0
|
|
|
|
finally:
|
|
removeDir(casRoot)
|
|
|
|
test "Calculate total tracked size":
|
|
## Test calculating total size of tracked builds
|
|
|
|
let casRoot = getTempDir() / "test_cas_" & $getTime().toUnix()
|
|
createDir(casRoot)
|
|
|
|
try:
|
|
var manager = newCASIntegrationManager(casRoot)
|
|
|
|
# Create and store multiple builds
|
|
for i in 0..<3:
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let buildResult = synthesizeBuild(
|
|
packageName = "package" & $i,
|
|
packageVersion = "1.0.0",
|
|
variantProfile = profile,
|
|
sourceHash = "blake3-" & $i
|
|
)
|
|
|
|
discard manager.storeBuildInCAS(buildResult)
|
|
|
|
# Calculate total size
|
|
let totalSize = manager.getTotalTrackedSize()
|
|
check totalSize > 0
|
|
|
|
finally:
|
|
removeDir(casRoot)
|
|
|
|
test "Multiple builds with same package":
|
|
## Test storing multiple builds of the same package with different variants
|
|
|
|
let casRoot = getTempDir() / "test_cas_" & $getTime().toUnix()
|
|
createDir(casRoot)
|
|
|
|
try:
|
|
var manager = newCASIntegrationManager(casRoot)
|
|
|
|
# Create two builds with different variants
|
|
var profile1 = newVariantProfile()
|
|
profile1.addFlag("optimization", "lto")
|
|
profile1.calculateHash()
|
|
|
|
var profile2 = newVariantProfile()
|
|
profile2.addFlag("optimization", "o3")
|
|
profile2.calculateHash()
|
|
|
|
let build1 = synthesizeBuild(
|
|
packageName = "nginx",
|
|
packageVersion = "1.24.0",
|
|
variantProfile = profile1,
|
|
sourceHash = "blake3-abc123"
|
|
)
|
|
|
|
let build2 = synthesizeBuild(
|
|
packageName = "nginx",
|
|
packageVersion = "1.24.0",
|
|
variantProfile = profile2,
|
|
sourceHash = "blake3-abc123"
|
|
)
|
|
|
|
# Store both builds
|
|
let store1 = manager.storeBuildInCAS(build1)
|
|
let store2 = manager.storeBuildInCAS(build2)
|
|
|
|
check store1.isOk
|
|
check store2.isOk
|
|
|
|
# Verify both are tracked
|
|
check tableLen(manager.references) == 2
|
|
check tableLen(manager.artifacts) == 2
|
|
|
|
# Verify they have different hashes
|
|
check build1.buildHash != build2.buildHash
|
|
|
|
finally:
|
|
removeDir(casRoot)
|
|
|
|
test "Round-trip: store and retrieve":
|
|
## Test complete round-trip: store build, retrieve it, verify it matches
|
|
|
|
let casRoot = getTempDir() / "test_cas_" & $getTime().toUnix()
|
|
createDir(casRoot)
|
|
|
|
try:
|
|
var manager = newCASIntegrationManager(casRoot)
|
|
|
|
# Create build with specific configuration
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.addFlag("security", "hardened")
|
|
profile.calculateHash()
|
|
|
|
let original = synthesizeBuild(
|
|
packageName = "nginx",
|
|
packageVersion = "1.24.0",
|
|
variantProfile = profile,
|
|
sourceHash = "blake3-abc123",
|
|
compilerVersion = "gcc-13.2.0",
|
|
compilerFlags = @["-O2", "-march=native"],
|
|
configureFlags = @["--with-ssl", "--with-http2"],
|
|
targetArchitecture = "x86_64",
|
|
libc = "musl",
|
|
allocator = "jemalloc"
|
|
)
|
|
|
|
# Store in CAS
|
|
let storeResult = manager.storeBuildInCAS(original)
|
|
check storeResult.isOk
|
|
|
|
let casHash = storeResult.get()
|
|
|
|
# Retrieve from CAS
|
|
let retrieveResult = manager.retrieveBuildFromCAS(casHash)
|
|
check retrieveResult.isOk
|
|
|
|
let retrieved = retrieveResult.get()
|
|
|
|
# Verify all fields match
|
|
check retrieved.buildHash == original.buildHash
|
|
check retrieved.buildConfig.packageName == original.buildConfig.packageName
|
|
check retrieved.buildConfig.packageVersion == original.buildConfig.packageVersion
|
|
check retrieved.buildConfig.sourceHash == original.buildConfig.sourceHash
|
|
check retrieved.buildConfig.compilerVersion == original.buildConfig.compilerVersion
|
|
check retrieved.buildConfig.targetArchitecture == original.buildConfig.targetArchitecture
|
|
check retrieved.buildConfig.libc == original.buildConfig.libc
|
|
check retrieved.buildConfig.allocator == original.buildConfig.allocator
|
|
|
|
finally:
|
|
removeDir(casRoot)
|