## 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")