353 lines
11 KiB
Nim
353 lines
11 KiB
Nim
## Unit Tests for Source Selection Strategy
|
|
##
|
|
## Tests for the source selection logic that chooses the best
|
|
## source adapter based on strategy (PreferBinary, PreferSource, Balanced).
|
|
|
|
import std/[unittest, options, strutils]
|
|
import ../src/nip/resolver/source_adapter
|
|
import ../src/nip/resolver/frozen_adapter
|
|
import ../src/nip/resolver/flexible_adapter
|
|
import ../src/nip/resolver/variant_types
|
|
|
|
suite "Source Selection Strategy Tests":
|
|
|
|
test "PreferBinary: Chooses frozen when available":
|
|
## Test that PreferBinary strategy prefers frozen sources
|
|
|
|
# Create frozen adapter with package
|
|
let frozenAdapter = newFrozenAdapter("nix", priority = 50)
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let frozenMetadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "nix-store-hash",
|
|
buildTime: 0
|
|
)
|
|
frozenAdapter.addPackage(frozenMetadata)
|
|
|
|
# Create flexible adapter with same package
|
|
let flexibleAdapter = newFlexibleAdapter("gentoo", priority = 30)
|
|
let flexibleMetadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "https://nginx.org/nginx-1.24.0.tar.gz",
|
|
buildTime: 300
|
|
)
|
|
flexibleAdapter.addPackage(flexibleMetadata)
|
|
|
|
# Create demand
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
# Select source with PreferBinary strategy
|
|
let adapters = @[SourceAdapter(frozenAdapter), SourceAdapter(flexibleAdapter)]
|
|
let selection = selectSource(adapters, demand, PreferBinary)
|
|
|
|
check selection.isSome
|
|
check selection.get.adapter.name == "nix"
|
|
check selection.get.adapter.class == Frozen
|
|
check selection.get.estimatedTime == 0
|
|
check "binary" in selection.get.reason.toLowerAscii()
|
|
|
|
test "PreferBinary: Falls back to flexible when no frozen available":
|
|
## Test that PreferBinary falls back to flexible sources
|
|
|
|
# Create only flexible adapter
|
|
let flexibleAdapter = newFlexibleAdapter("gentoo", priority = 30)
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "https://nginx.org/nginx-1.24.0.tar.gz",
|
|
buildTime: 300
|
|
)
|
|
flexibleAdapter.addPackage(metadata)
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
let adapters = @[SourceAdapter(flexibleAdapter)]
|
|
let selection = selectSource(adapters, demand, PreferBinary)
|
|
|
|
check selection.isSome
|
|
check selection.get.adapter.name == "gentoo"
|
|
check selection.get.adapter.class == Flexible
|
|
check selection.get.estimatedTime == 300
|
|
check "source" in selection.get.reason.toLowerAscii()
|
|
|
|
test "PreferSource: Always chooses flexible when available":
|
|
## Test that PreferSource strategy prefers flexible sources
|
|
|
|
# Create both frozen and flexible adapters
|
|
let frozenAdapter = newFrozenAdapter("nix", priority = 50)
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let frozenMetadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "nix-store-hash",
|
|
buildTime: 0
|
|
)
|
|
frozenAdapter.addPackage(frozenMetadata)
|
|
|
|
let flexibleAdapter = newFlexibleAdapter("gentoo", priority = 30)
|
|
let flexibleMetadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "https://nginx.org/nginx-1.24.0.tar.gz",
|
|
buildTime: 300
|
|
)
|
|
flexibleAdapter.addPackage(flexibleMetadata)
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
# Select with PreferSource strategy
|
|
let adapters = @[SourceAdapter(frozenAdapter), SourceAdapter(flexibleAdapter)]
|
|
let selection = selectSource(adapters, demand, PreferSource)
|
|
|
|
check selection.isSome
|
|
check selection.get.adapter.name == "gentoo"
|
|
check selection.get.adapter.class == Flexible
|
|
check selection.get.estimatedTime == 300
|
|
check "source" in selection.get.reason.toLowerAscii()
|
|
|
|
test "PreferSource: Falls back to frozen when no flexible available":
|
|
## Test that PreferSource falls back to frozen sources
|
|
|
|
# Create only frozen adapter
|
|
let frozenAdapter = newFrozenAdapter("nix", priority = 50)
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "nix-store-hash",
|
|
buildTime: 0
|
|
)
|
|
frozenAdapter.addPackage(metadata)
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
let adapters = @[SourceAdapter(frozenAdapter)]
|
|
let selection = selectSource(adapters, demand, PreferSource)
|
|
|
|
check selection.isSome
|
|
check selection.get.adapter.name == "nix"
|
|
check selection.get.adapter.class == Frozen
|
|
check selection.get.estimatedTime == 0
|
|
|
|
test "Balanced: Considers priority":
|
|
## Test that Balanced strategy respects adapter priority
|
|
|
|
# Create two frozen adapters with different priorities
|
|
let highPriorityAdapter = newFrozenAdapter("nix", priority = 100)
|
|
let lowPriorityAdapter = newFrozenAdapter("arch", priority = 50)
|
|
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "hash",
|
|
buildTime: 0
|
|
)
|
|
|
|
highPriorityAdapter.addPackage(metadata)
|
|
lowPriorityAdapter.addPackage(metadata)
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
# Select with Balanced strategy
|
|
let adapters = @[SourceAdapter(lowPriorityAdapter), SourceAdapter(highPriorityAdapter)]
|
|
let selection = selectSource(adapters, demand, Balanced)
|
|
|
|
check selection.isSome
|
|
check selection.get.adapter.name == "nix"
|
|
check selection.get.adapter.priority == 100
|
|
|
|
test "No source available returns None":
|
|
## Test that selectSource returns None when no source can satisfy
|
|
|
|
let frozenAdapter = newFrozenAdapter("nix", priority = 50)
|
|
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
# Don't add any packages to adapter
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nonexistent",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
let adapters = @[SourceAdapter(frozenAdapter)]
|
|
let selection = selectSource(adapters, demand, PreferBinary)
|
|
|
|
check selection.isNone
|
|
|
|
test "Empty adapter list returns None":
|
|
## Test that selectSource handles empty adapter list
|
|
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
let adapters: seq[SourceAdapter] = @[]
|
|
let selection = selectSource(adapters, demand, PreferBinary)
|
|
|
|
check selection.isNone
|
|
|
|
test "Multiple adapters with same priority":
|
|
## Test behavior when multiple adapters have same priority
|
|
|
|
let adapter1 = newFrozenAdapter("nix", priority = 50)
|
|
let adapter2 = newFrozenAdapter("arch", priority = 50)
|
|
|
|
var profile = newVariantProfile()
|
|
profile.addFlag("optimization", "lto")
|
|
profile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[profile],
|
|
sourceHash: "hash",
|
|
buildTime: 0
|
|
)
|
|
|
|
adapter1.addPackage(metadata)
|
|
adapter2.addPackage(metadata)
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: profile,
|
|
optional: false
|
|
)
|
|
|
|
# With Balanced strategy, should pick one deterministically
|
|
let adapters = @[SourceAdapter(adapter1), SourceAdapter(adapter2)]
|
|
let selection = selectSource(adapters, demand, Balanced)
|
|
|
|
check selection.isSome
|
|
# Should pick one of them (deterministic based on order)
|
|
check selection.get.adapter.name in ["nix", "arch"]
|
|
|
|
test "Frozen adapter with wrong variant is skipped":
|
|
## Test that frozen adapters with wrong variants are not selected
|
|
|
|
let frozenAdapter = newFrozenAdapter("nix", priority = 50)
|
|
|
|
var availableProfile = newVariantProfile()
|
|
availableProfile.addFlag("optimization", "lto")
|
|
availableProfile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[availableProfile],
|
|
sourceHash: "hash",
|
|
buildTime: 0
|
|
)
|
|
frozenAdapter.addPackage(metadata)
|
|
|
|
# Request different variant
|
|
var demandProfile = newVariantProfile()
|
|
demandProfile.addFlag("optimization", "pgo")
|
|
demandProfile.calculateHash()
|
|
|
|
let demand = VariantDemand(
|
|
packageName: "nginx",
|
|
variantProfile: demandProfile,
|
|
optional: false
|
|
)
|
|
|
|
let adapters = @[SourceAdapter(frozenAdapter)]
|
|
let selection = selectSource(adapters, demand, PreferBinary)
|
|
|
|
# Frozen adapter can't satisfy wrong variant
|
|
check selection.isNone
|
|
|
|
test "Flexible adapter accepts any variant":
|
|
## Test that flexible adapters can satisfy any variant
|
|
|
|
let flexibleAdapter = newFlexibleAdapter("gentoo", priority = 30)
|
|
|
|
var availableProfile = newVariantProfile()
|
|
availableProfile.addFlag("optimization", "lto")
|
|
availableProfile.calculateHash()
|
|
|
|
let metadata = PackageMetadata(
|
|
name: "nginx",
|
|
version: "1.24.0",
|
|
availableVariants: @[availableProfile],
|
|
sourceHash: "https://nginx.org/nginx-1.24.0.tar.gz",
|
|
buildTime: 300
|
|
)
|
|
flexibleAdapter.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 adapters = @[SourceAdapter(flexibleAdapter)]
|
|
let selection = selectSource(adapters, demand, PreferBinary)
|
|
|
|
# Flexible adapter can satisfy any variant
|
|
check selection.isSome
|
|
check selection.get.adapter.name == "gentoo"
|
|
check selection.get.estimatedTime == 300
|
|
|