340 lines
9.4 KiB
Nim
340 lines
9.4 KiB
Nim
## Unit Tests for Flexible Adapter
|
|
##
|
|
## Tests for the flexible adapter implementation which handles
|
|
## source-based builds like Gentoo and NPK.
|
|
|
|
import std/[unittest, options, tables, strutils]
|
|
import ../src/nip/resolver/flexible_adapter
|
|
import ../src/nip/resolver/source_adapter
|
|
import ../src/nip/resolver/variant_types
|
|
|
|
suite "Flexible Adapter Tests":
|
|
|
|
test "Create flexible adapter":
|
|
## Test basic adapter creation
|
|
|
|
let adapter = newFlexibleAdapter("test-flexible", priority = 30)
|
|
|
|
check adapter.name == "test-flexible"
|
|
check adapter.class == Flexible
|
|
check adapter.priority == 30
|
|
|
|
test "Add package to flexible adapter":
|
|
## Test adding buildable packages
|
|
|
|
let adapter = newFlexibleAdapter("test-flexible")
|
|
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "https://nginx.org/download/nginx-1.24.0.tar.gz",
|
|
buildTime: 300 # 5 minutes
|
|
)
|
|
|
|
adapter.addPackage(metadata)
|
|
|
|
check adapter.availablePackages.hasKey("nginx")
|
|
check adapter.availablePackages["nginx"].name == "nginx"
|
|
check adapter.availablePackages["nginx"].buildTime == 300
|
|
|
|
test "canSatisfy: Package available":
|
|
## Test that available packages are detected
|
|
|
|
let adapter = newFlexibleAdapter("test-flexible")
|
|
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "https://nginx.org/download/nginx-1.24.0.tar.gz",
|
|
buildTime: 300
|
|
)
|
|
|
|
adapter.addPackage(metadata)
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
let availability = adapter.canSatisfy(demand)
|
|
|
|
check availability == Available
|
|
|
|
test "canSatisfy: Package unavailable":
|
|
## Test that unavailable packages are detected
|
|
|
|
let adapter = newFlexibleAdapter("test-flexible")
|
|
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nonexistent",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
let availability = adapter.canSatisfy(demand)
|
|
|
|
check availability == Unavailable
|
|
|
|
test "canSatisfy: Any variant is acceptable":
|
|
## Test that flexible sources accept any variant
|
|
## (they can build with any configuration)
|
|
|
|
let adapter = newFlexibleAdapter("test-flexible")
|
|
|
|
var availableProfile = newVariantProfile()
|
|
availableProfile.addFlag("optimization", "lto")
|
|
availableProfile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[availableProfile],
|
|
sourceHash: "https://nginx.org/download/nginx-1.24.0.tar.gz",
|
|
buildTime: 300
|
|
)
|
|
|
|
adapter.addPackage(metadata)
|
|
|
|
# Request different variant
|
|
var demandProfile = newVariantProfile()
|
|
demandProfile.addFlag("optimization", "pgo")
|
|
demandProfile.addFlag("graphics", "wayland")
|
|
demandProfile.calculateHash()
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: demandProfile,
|
|
optional: false
|
|
)
|
|
|
|
let availability = adapter.canSatisfy(demand)
|
|
|
|
# Flexible sources can build any variant
|
|
check availability == Available
|
|
|
|
test "getVariant: Returns metadata with requested variant":
|
|
## Test that getVariant returns metadata for any variant
|
|
|
|
let adapter = newFlexibleAdapter("test-flexible")
|
|
|
|
var baseProfile = newVariantProfile()
|
|
baseProfile.addFlag("optimization", "lto")
|
|
baseProfile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[baseProfile],
|
|
sourceHash: "https://nginx.org/download/nginx-1.24.0.tar.gz",
|
|
buildTime: 300
|
|
)
|
|
|
|
adapter.addPackage(metadata)
|
|
|
|
# Request different variant
|
|
var demandProfile = newVariantProfile()
|
|
demandProfile.addFlag("optimization", "pgo")
|
|
demandProfile.calculateHash()
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: demandProfile,
|
|
optional: false
|
|
)
|
|
|
|
let result = adapter.getVariant(demand)
|
|
|
|
check result.isSome
|
|
check result.get.name == "nginx"
|
|
check result.get.availableVariants[0] == demandProfile
|
|
|
|
test "getVariant: Returns none for unavailable package":
|
|
## Test that getVariant returns none for missing packages
|
|
|
|
let adapter = newFlexibleAdapter("test-flexible")
|
|
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nonexistent",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
let result = adapter.getVariant(demand)
|
|
|
|
check result.isNone
|
|
|
|
test "synthesize: Successful build with mock function":
|
|
## Test successful package synthesis
|
|
|
|
let mockBuild = mockBuildSuccess("nginx", "cas-nginx-abc123")
|
|
let adapter = newFlexibleAdapter("test-flexible", buildFunc = mockBuild)
|
|
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "https://nginx.org/download/nginx-1.24.0.tar.gz",
|
|
buildTime: 300
|
|
)
|
|
|
|
adapter.addPackage(metadata)
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
let result = adapter.synthesize(demand)
|
|
|
|
check result.isOk
|
|
check $result.value == "cas-nginx-abc123"
|
|
|
|
test "synthesize: Build failure with mock function":
|
|
## Test build failure handling
|
|
|
|
let mockBuild = mockBuildFailure("Compilation failed", exitCode = 2)
|
|
let adapter = newFlexibleAdapter("test-flexible", buildFunc = mockBuild)
|
|
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "https://nginx.org/download/nginx-1.24.0.tar.gz",
|
|
buildTime: 300
|
|
)
|
|
|
|
adapter.addPackage(metadata)
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
let result = adapter.synthesize(demand)
|
|
|
|
check not result.isOk
|
|
check result.error.exitCode == 2
|
|
check "Compilation failed" in result.error.message
|
|
|
|
test "synthesize: Package not found":
|
|
## Test synthesis of non-existent package
|
|
|
|
let adapter = newFlexibleAdapter("test-flexible")
|
|
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nonexistent",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
let result = adapter.synthesize(demand)
|
|
|
|
check not result.isOk
|
|
check "not found" in result.error.message.toLowerAscii()
|
|
|
|
test "synthesize: Default implementation generates CAS ID":
|
|
## Test that default synthesis generates valid CAS ID
|
|
|
|
let adapter = newFlexibleAdapter("test-flexible")
|
|
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "https://nginx.org/download/nginx-1.24.0.tar.gz",
|
|
buildTime: 300
|
|
)
|
|
|
|
adapter.addPackage(metadata)
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
let result = adapter.synthesize(demand)
|
|
|
|
check result.isOk
|
|
# CAS ID should contain package name and variant hash
|
|
let casIdStr = $result.value
|
|
check "nginx" in casIdStr
|
|
check profile.hash in casIdStr
|
|
|
|
test "synthesize: Variant profile is passed correctly":
|
|
## Test that the requested variant profile is used in synthesis
|
|
|
|
var capturedProfile: VariantProfile
|
|
|
|
let mockBuild = proc(demand: VariantDemand): Result[CasId, BuildError] =
|
|
capturedProfile = demand.variantProfile
|
|
return ok[CasId, BuildError](newCasId("test-cas-id"))
|
|
|
|
let adapter = newFlexibleAdapter("test-flexible", buildFunc = mockBuild)
|
|
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.addFlag("graphics", "wayland")
|
|
profile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "firefox",
|
|
version: "120.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "https://mozilla.org/firefox-120.0.tar.gz",
|
|
buildTime: 600
|
|
)
|
|
|
|
adapter.addPackage(metadata)
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "firefox",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
let result = adapter.synthesize(demand)
|
|
|
|
check result.isOk
|
|
check capturedProfile == profile
|
|
check capturedProfile.hasDomain("optimization")
|
|
check capturedProfile.hasDomain("graphics")
|
|
|