nip/tests/test_variant_compiler.nim

276 lines
8.3 KiB
Nim

## test_variant_compiler.nim
## Tests for compiler flag resolution system
## Ensures proper flag resolution with priority ordering
import std/[unittest, tables, strutils, sequtils]
import ../src/nimpak/variant_compiler
import ../src/nimpak/variant_types
import ../src/nimpak/config
suite "Compiler Flag Resolution Tests":
let baseFlags = CompilerFlags(
cflags: "-O2 -pipe",
cxxflags: "-O2 -pipe",
ldflags: "-Wl,-O1",
makeflags: "-j4"
)
test "Empty domains return base flags":
var domains = initTable[string, seq[string]]()
let resolved = resolveCompilerFlags(domains, baseFlags)
check resolved.cflags == baseFlags.cflags
check resolved.ldflags == baseFlags.ldflags
test "Optimization LTO flag adds compiler flags":
var domains = initTable[string, seq[string]]()
domains["optimization"] = @["lto"]
let resolved = resolveCompilerFlags(domains, baseFlags)
check "-flto=full" in resolved.cflags
check "-flto" in resolved.ldflags
check "-fuse-ld=mold" in resolved.ldflags
test "Optimization march-native flag":
var domains = initTable[string, seq[string]]()
domains["optimization"] = @["march-native"]
let resolved = resolveCompilerFlags(domains, baseFlags)
check "-march=native" in resolved.cflags
test "Security PIE flag":
var domains = initTable[string, seq[string]]()
domains["security"] = @["pie"]
let resolved = resolveCompilerFlags(domains, baseFlags)
check "-fPIE" in resolved.cflags
check "-pie" in resolved.ldflags
test "Security RELRO flag":
var domains = initTable[string, seq[string]]()
domains["security"] = @["relro"]
let resolved = resolveCompilerFlags(domains, baseFlags)
check "-Wl,-z,relro,-z,now" in resolved.ldflags
test "Security hardened flag":
var domains = initTable[string, seq[string]]()
domains["security"] = @["hardened"]
let resolved = resolveCompilerFlags(domains, baseFlags)
check "-D_FORTIFY_SOURCE=2" in resolved.cflags
check "-fstack-protector-strong" in resolved.cflags
test "Multiple flags in same domain":
var domains = initTable[string, seq[string]]()
domains["security"] = @["pie", "relro", "hardened"]
let resolved = resolveCompilerFlags(domains, baseFlags)
check "-fPIE" in resolved.cflags
check "-D_FORTIFY_SOURCE=2" in resolved.cflags
check "-pie" in resolved.ldflags
check "-Wl,-z,relro,-z,now" in resolved.ldflags
suite "Priority Ordering Tests":
let baseFlags = CompilerFlags(
cflags: "-O2",
ldflags: "-Wl,-O1"
)
test "Security flags applied before optimization":
var domains = initTable[string, seq[string]]()
domains["security"] = @["pie"]
domains["optimization"] = @["lto"]
let resolved = resolveCompilerFlags(domains, baseFlags)
# Security flags should appear before optimization flags
let cflagsStr = resolved.cflags
let piePos = cflagsStr.find("-fPIE")
let ltoPos = cflagsStr.find("-flto")
check piePos >= 0
check ltoPos >= 0
check piePos < ltoPos # PIE should come before LTO
test "Multiple domains with priority ordering":
var domains = initTable[string, seq[string]]()
domains["optimization"] = @["lto", "march-native"]
domains["security"] = @["pie", "relro"]
let resolved = resolveCompilerFlags(domains, baseFlags)
# All flags should be present
check "-fPIE" in resolved.cflags
check "-flto=full" in resolved.cflags
check "-march=native" in resolved.cflags
check "-pie" in resolved.ldflags
check "-Wl,-z,relro,-z,now" in resolved.ldflags
suite "Flag Rule Query Tests":
test "hasCompilerFlagRule detects existing rules":
check hasCompilerFlagRule("optimization", "lto") == true
check hasCompilerFlagRule("security", "pie") == true
test "hasCompilerFlagRule returns false for non-existent rules":
check hasCompilerFlagRule("optimization", "nonexistent") == false
check hasCompilerFlagRule("nonexistent", "lto") == false
test "getCompilerFlagRule returns correct rule":
let rule = getCompilerFlagRule("optimization", "lto")
check rule.condition == "lto"
check rule.cflags == "-flto=full"
check rule.ldflags == "-flto -fuse-ld=mold"
test "getDomainRules returns all rules for domain":
let rules = getDomainRules("optimization")
check rules.hasKey("lto")
check rules.hasKey("march-native")
check rules.hasKey("pgo")
test "getDomainRules returns empty for unknown domain":
let rules = getDomainRules("unknown_domain")
check rules.len == 0
suite "Flag Analysis Tests":
test "analyzeCompilerFlags lists applied flags":
var domains = initTable[string, seq[string]]()
domains["optimization"] = @["lto"]
domains["security"] = @["pie"]
let analysis = analyzeCompilerFlags(domains)
check analysis.len == 2
check any(analysis, proc(s: string): bool = "optimization.lto" in s)
check any(analysis, proc(s: string): bool = "security.pie" in s)
test "explainFlag provides detailed information":
let explanation = explainFlag("optimization", "lto")
check "lto" in explanation
check "CFLAGS" in explanation
check "LDFLAGS" in explanation
check "-flto=full" in explanation
test "explainFlag handles non-existent flag":
let explanation = explainFlag("optimization", "nonexistent")
check "No compiler flag rule" in explanation
suite "Conflict Detection Tests":
test "No conflicts in normal configuration":
var domains = initTable[string, seq[string]]()
domains["optimization"] = @["lto", "march-native"]
domains["security"] = @["pie", "relro"]
let conflicts = detectFlagConflicts(domains)
check conflicts.len == 0
check hasConflicts(domains) == false
test "Detect debug + strip conflict":
var domains = initTable[string, seq[string]]()
domains["optimization"] = @["debug", "strip"]
let conflicts = detectFlagConflicts(domains)
check conflicts.len > 0
check hasConflicts(domains) == true
check any(conflicts, proc(s: string): bool = "debug" in s and "strip" in s)
test "Detect debug + lto warning":
var domains = initTable[string, seq[string]]()
domains["optimization"] = @["debug", "lto"]
let conflicts = detectFlagConflicts(domains)
check conflicts.len > 0
check any(conflicts, proc(s: string): bool = "debug" in s and "lto" in s)
suite "Helper Function Tests":
test "mergeCompilerFlags combines flags":
let base = CompilerFlags(
cflags: "-O2",
ldflags: "-Wl,-O1"
)
let additional = CompilerFlags(
cflags: "-march=native",
ldflags: "-flto"
)
let merged = mergeCompilerFlags(base, additional)
check "-O2" in merged.cflags
check "-march=native" in merged.cflags
check "-Wl,-O1" in merged.ldflags
check "-flto" in merged.ldflags
test "cleanCompilerFlags removes extra spaces":
let dirty = CompilerFlags(
cflags: "-O2 -pipe -march=native",
ldflags: "-Wl,-O1 -flto"
)
let clean = cleanCompilerFlags(dirty)
check clean.cflags == "-O2 -pipe -march=native"
check clean.ldflags == "-Wl,-O1 -flto"
suite "Real-World Configuration Tests":
let baseFlags = CompilerFlags(
cflags: "-O2 -pipe",
ldflags: "-Wl,-O1"
)
test "Fleet node configuration":
var domains = initTable[string, seq[string]]()
domains["security"] = @["pie", "relro", "hardened"]
domains["optimization"] = @["lto", "march-native"]
let resolved = resolveCompilerFlags(domains, baseFlags)
# Security flags
check "-fPIE" in resolved.cflags
check "-D_FORTIFY_SOURCE=2" in resolved.cflags
check "-pie" in resolved.ldflags
check "-Wl,-z,relro,-z,now" in resolved.ldflags
# Optimization flags
check "-flto=full" in resolved.cflags
check "-march=native" in resolved.cflags
test "Debug build configuration":
var domains = initTable[string, seq[string]]()
domains["optimization"] = @["debug"]
let resolved = resolveCompilerFlags(domains, baseFlags)
check "-g" in resolved.cflags
check "-O0" in resolved.cflags
test "Minimal configuration":
var domains = initTable[string, seq[string]]()
domains["security"] = @["pie"]
let resolved = resolveCompilerFlags(domains, baseFlags)
check "-fPIE" in resolved.cflags
check "-pie" in resolved.ldflags
# Base flags should still be present
check "-O2" in resolved.cflags
when isMainModule:
echo "Running variant compiler tests..."