276 lines
8.3 KiB
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..."
|