## test_variant_profiles.nim ## Tests for variant profile system import std/[unittest, tables, options, os, strutils] import ../src/nimpak/variant_profiles import ../src/nimpak/variant_types import ../src/nimpak/config suite "Variant Profile System": test "Load fleet-node profile from KDL": let profilePath = ".kiro/nip/profiles/fleet-node.kdl" if not fileExists(profilePath): skip() let profile = loadProfile(profilePath) check profile.name == "fleet-node" check profile.description.len > 0 check profile.domains.len > 0 # Check specific domains check profile.hasDomain("init") check profile.getDomainValues("init") == @["dinit"] check profile.hasDomain("security") let securityFlags = profile.getDomainValues("security") check "pie" in securityFlags check "relro" in securityFlags # Check compiler flags check profile.compilerFlags.cflags.len > 0 check "-Os" in profile.compilerFlags.cflags test "Load gaming-rig profile from KDL": let profilePath = ".kiro/nip/profiles/gaming-rig.kdl" if not fileExists(profilePath): skip() let profile = loadProfile(profilePath) check profile.name == "gaming-rig" check profile.hasDomain("graphics") let graphicsFlags = profile.getDomainValues("graphics") check "vulkan" in graphicsFlags check "wayland" in graphicsFlags # Check optimization check profile.hasDomain("optimization") let optFlags = profile.getDomainValues("optimization") check "lto" in optFlags check "march-native" in optFlags test "Load ml-workstation profile from KDL": let profilePath = ".kiro/nip/profiles/ml-workstation.kdl" if not fileExists(profilePath): skip() let profile = loadProfile(profilePath) check profile.name == "ml-workstation" check profile.hasDomain("runtime") let runtimeFlags = profile.getDomainValues("runtime") check "python" in runtimeFlags check profile.hasDomain("developer") let devFlags = profile.getDomainValues("developer") check "debugger" in devFlags check "lsp" in devFlags test "Merge profile with domain overrides": var baseProfile = newVariantProfile("base", "Base profile") baseProfile.domains["init"] = @["systemd"] baseProfile.domains["graphics"] = @["X"] baseProfile.compilerFlags.cflags = "-O2" var overrides = initTable[string, seq[string]]() overrides["init"] = @["dinit"] # Override init overrides["audio"] = @["pipewire"] # Add new domain let merged = mergeProfileWithOverrides(baseProfile, overrides) check merged.getDomainValues("init") == @["dinit"] # Overridden check merged.getDomainValues("graphics") == @["X"] # Preserved check merged.getDomainValues("audio") == @["pipewire"] # Added check merged.compilerFlags.cflags == "-O2" # Preserved test "Merge profile with compiler flag overrides": var baseProfile = newVariantProfile("base", "Base profile") baseProfile.compilerFlags.cflags = "-O2" baseProfile.compilerFlags.ldflags = "-Wl,-O1" var overrideFlags = CompilerFlags( cflags: "-O3 -march=native", ldflags: "", # Empty, should not override makeflags: "-j16" # New flag ) let merged = mergeProfileWithOverrides( baseProfile, initTable[string, seq[string]](), some(overrideFlags) ) check merged.compilerFlags.cflags == "-O3 -march=native" # Overridden check merged.compilerFlags.ldflags == "-Wl,-O1" # Preserved (empty override) check merged.compilerFlags.makeflags == "-j16" # Added test "Merge two profiles": var baseProfile = newVariantProfile("base", "Base profile") baseProfile.domains["init"] = @["systemd"] baseProfile.domains["graphics"] = @["X"] baseProfile.compilerFlags.cflags = "-O2" var overlayProfile = newVariantProfile("overlay", "Overlay profile") overlayProfile.domains["init"] = @["dinit"] # Override overlayProfile.domains["audio"] = @["pipewire"] # Add overlayProfile.compilerFlags.cflags = "-O3" # Override overlayProfile.compilerFlags.ldflags = "-Wl,-O1" # Add let merged = mergeProfiles(baseProfile, overlayProfile) check merged.name == "overlay" # Takes overlay name check merged.getDomainValues("init") == @["dinit"] # Overridden check merged.getDomainValues("graphics") == @["X"] # Preserved from base check merged.getDomainValues("audio") == @["pipewire"] # Added from overlay check merged.compilerFlags.cflags == "-O3" # Overridden check merged.compilerFlags.ldflags == "-Wl,-O1" # Added test "Profile string representation": var profile = newVariantProfile("test", "Test profile") profile.domains["init"] = @["dinit"] profile.domains["graphics"] = @["wayland", "vulkan"] profile.compilerFlags.cflags = "-O3" profile.compilerFlags.makeflags = "-j8" let str = $profile check "test" in str check "Test profile" in str check "init" in str check "dinit" in str check "graphics" in str check "wayland" in str check "CFLAGS" in str check "-O3" in str test "List domains in profile": var profile = newVariantProfile("test", "Test profile") profile.domains["init"] = @["dinit"] profile.domains["graphics"] = @["wayland"] profile.domains["audio"] = @["pipewire"] let domains = profile.listDomains() check domains.len == 3 check "init" in domains check "graphics" in domains check "audio" in domains test "Profile error handling - missing file": expect ProfileParseError: discard loadProfile("nonexistent.kdl") test "Profile error handling - invalid KDL": # Create a temporary invalid KDL file let tempPath = "/tmp/test_invalid_profile.kdl" writeFile(tempPath, "invalid { kdl syntax") try: expect CatchableError: # KDL parse errors are caught as ProfileParseError discard loadProfile(tempPath) finally: removeFile(tempPath) test "Profile error handling - missing profile node": # Create a KDL file without a profile node let tempPath = "/tmp/test_no_profile.kdl" writeFile(tempPath, """ config { value "test" } """) try: expect ProfileParseError: discard loadProfile(tempPath) finally: removeFile(tempPath) when isMainModule: echo "Running variant profile tests..."