5e32ec16df
Remove guns/bitbrain_net.nim (+README), test_bitbrain_net.nim,
measure_bitbrain_scaling.nim, rack id 17 and all of its plumbing in
selector.nim / ModularBot.nim / env_report.nim, the TR_BITBRAIN_NET switch
and the NEW-NETWORK TR_BITBRAIN_* knobs, and the BitBrainNet arm of
run_prediction_quality.nim.
With id 17 gone there is nothing to disambiguate, so the legacy namespace
becomes the ONLY one: TR_RACK_BITBRAIN always selects id 16 LEADGAIN and
every TR_BITBRAIN_<X> in the frozen 14-suffix alias set always means
TR_LEADGAIN_<X>. The alias layer and its [depr] line stay.
KEPT: the common_libs/bitbrain/ SBC library (learned_surfer imports
bitbrain/sbc), lead_gain at id 16 with env TR_LEADGAIN_* and log tag [lg],
and the c9b6753 crash fix (NumRackGuns widths + test_rack_stat_width).
Tombstone: docs/bitbrain_campaign.md ## RETIRED and one cross-reference line
in docs/gun_campaign.md. Shipped defaults unchanged: clean env -> rack
active 1v1 = PATTERN, movement default strafe.
162 lines
6.8 KiB
Nim
162 lines
6.8 KiB
Nim
## Guard test for the boot-time env report's Part 2 (the warnings).
|
|
##
|
|
## NO battle, NO Java, NO server. Run with:
|
|
## nim c -r common_libs/tests/test_env_report.nim
|
|
##
|
|
## It pins the two tables that must not drift:
|
|
## 1. the KNOWN TR_*/GUN_* name set covers every env read in the tree, so a
|
|
## new knob cannot silently start producing a false "unknown variable"
|
|
## warning (and, conversely, the set cannot rot);
|
|
## 2. the compile-time define map covers every `{.intdefine.}`/`{.strdefine.}`
|
|
## /`{.booldefine.}` symbol in the tree, and classifies the ONE real env
|
|
## twin (`TMH_NSTATES` -> `TR_TMHORIZON_NSTATES`) correctly.
|
|
|
|
import std/[os, strutils, sets, sequtils]
|
|
import gun_harness/selector
|
|
import "../../ModularBot_garage/src/env_report"
|
|
|
|
var failures = 0
|
|
proc check(name: string, ok: bool) =
|
|
if ok: echo "PASS: ", name
|
|
else: echo "FAIL: ", name; inc failures
|
|
|
|
const repoRoot = currentSourcePath().parentDir.parentDir.parentDir
|
|
|
|
# ── the source surface the scan walks (the bot's real modules) ───────────────
|
|
|
|
proc scannedFiles(): seq[string] =
|
|
## .nim files under common_libs (excluding common_libs/tests, which are
|
|
## probes/measurement scripts, not bot code) and ModularBot_garage/src.
|
|
## env_report.nim is excluded: it DEFINES the known set, so scanning it is
|
|
## circular (it also names "suggested but nonexistent" env vars on purpose).
|
|
for dir in [repoRoot / "common_libs", repoRoot / "ModularBot_garage" / "src"]:
|
|
for path in walkDirRec(dir):
|
|
if not path.endsWith(".nim"): continue
|
|
if "/tests/" in path: continue
|
|
if path.endsWith("/env_report.nim"): continue
|
|
result.add path
|
|
|
|
proc literalsOn(line: string): seq[string] =
|
|
## Double-quoted string literals on one line (env names have no escapes).
|
|
var i = 0
|
|
while i < line.len:
|
|
if line[i] == '"':
|
|
var j = i + 1
|
|
while j < line.len and line[j] != '"': inc j
|
|
if j >= line.len: break
|
|
result.add line[i + 1 ..< j]
|
|
i = j + 1
|
|
else:
|
|
inc i
|
|
|
|
proc isKnownOrPrefix(name: string, known: HashSet[string]): bool =
|
|
## A literal counts as covered when it is a known name OR a prefix of one
|
|
## (`TR_RACK_` is the rack prefix; `TR_`/`GUN_` are the filter prefixes).
|
|
if name in known: return true
|
|
for k in known:
|
|
if k.startsWith(name): return true
|
|
|
|
proc defineSymbolsOn(line: string): seq[string] =
|
|
## ` TMH_NCLAUSES* {.intdefine.} = 40` -> "TMH_NCLAUSES"
|
|
for pragma in ["{.intdefine.}", "{.strdefine.}", "{.booldefine.}"]:
|
|
if pragma in line:
|
|
var sym = line.split('{')[0].strip()
|
|
if sym.endsWith("*"): sym.setLen(sym.len - 1)
|
|
let parts = sym.splitWhitespace()
|
|
if parts.len > 0: result.add parts[^1]
|
|
|
|
# ── 1. the known-name set ────────────────────────────────────────────────────
|
|
|
|
proc testKnownNames() =
|
|
let known = knownEnvNames()
|
|
let s = known.toHashSet()
|
|
check "known set has no duplicates", known.len == s.len
|
|
check "known set only holds TR_*/GUN_* names",
|
|
known.allIt(it.startsWith("TR_") or it.startsWith("GUN_"))
|
|
check "known set covers all 17 rack names",
|
|
RackGunNames.allIt((RackEnvPrefix & it) in s)
|
|
for name in ["TR_MOVEMENT", "TR_POWER_ENERGY_MIN", "TR_TMHORIZON_NSTATES",
|
|
"GUN_VBULLET_METRIC", "TR_ENV_REPORT", "GUN_SELECTOR_SEED",
|
|
"TR_RACK_TMHORIZON", "TR_TMHORIZON_NSTATES"]:
|
|
check "known set contains " & name, name in s
|
|
|
|
# ── 2. the pure warning helpers ──────────────────────────────────────────────
|
|
|
|
proc testUnknownEnvNames() =
|
|
let unknown = unknownEnvNames(@[
|
|
("TR_POWER_LOG", "1"), ("GUN_STATS_PATH", "/tmp/x"),
|
|
("TR_TMHORIZON_NSTATE", "5"), ("PATH", "/bin"),
|
|
("TMH_NSTATES", "2"), ("JAVA_HOME", "/jdk")])
|
|
check "unknownEnvNames finds the misspelled TR_* only",
|
|
unknown == @["TR_TMHORIZON_NSTATE"]
|
|
check "unknownEnvNames ignores non TR_*/GUN_* names",
|
|
unknownEnvNames(@[("PATH", "/bin")]) == @[]
|
|
|
|
proc testDefineMap() =
|
|
check "isCompileTimeDefine(TMH_NSTATES)", isCompileTimeDefine("TMH_NSTATES")
|
|
check "isCompileTimeDefine(TM_S_DEF)", isCompileTimeDefine("TM_S_DEF")
|
|
check "isCompileTimeDefine(TR_TMHORIZON_NSTATES) is false",
|
|
not isCompileTimeDefine("TR_TMHORIZON_NSTATES")
|
|
check "defineWarningMessage is empty for a non-define",
|
|
defineWarningMessage("TR_MOVEMENT", "x") == ""
|
|
|
|
let m1 = defineWarningMessage("TMH_NSTATES", "2")
|
|
check "TMH_NSTATES warns it is compile-time and names TR_TMHORIZON_NSTATES",
|
|
"COMPILE-TIME define (-d:TMH_NSTATES=2)" in m1 and
|
|
"TR_TMHORIZON_NSTATES=2" in m1
|
|
let m2 = defineWarningMessage("TMH_NCLAUSES", "40")
|
|
check "TMH_NCLAUSES says TR_TMHORIZON_NCLAUSES does not exist",
|
|
"TR_TMHORIZON_NCLAUSES does not exist" in m2
|
|
let m3 = defineWarningMessage("TM_S_DEF", "1.5")
|
|
check "TM_S_DEF says this knob is compile-time only",
|
|
"compile-time only" in m3
|
|
|
|
let defs = setCompileTimeDefines(@[
|
|
("TMH_NSTATES", "2"), ("TR_MOVEMENT", "tfil"), ("TM_S_DEF", "1.5")])
|
|
check "setCompileTimeDefines finds both -d symbols",
|
|
defs == @["TMH_NSTATES", "TM_S_DEF"]
|
|
|
|
# ── 3. the tree scans (the anti-drift guard) ─────────────────────────────────
|
|
|
|
proc testTreeScan() =
|
|
let known = knownEnvNames().toHashSet()
|
|
var literals = 0
|
|
var missing: seq[string]
|
|
for path in scannedFiles():
|
|
for line in lines(path):
|
|
for lit in literalsOn(line):
|
|
if lit.startsWith("TR_") or lit.startsWith("GUN_"):
|
|
inc literals
|
|
if not isKnownOrPrefix(lit, known):
|
|
missing.add path.extractFilename & ":" & lit
|
|
check "tree scan is alive (>= 50 TR_*/GUN_* literals)", literals >= 50
|
|
check "every TR_*/GUN_* literal in the tree is in the known set: " &
|
|
$missing, missing.len == 0
|
|
|
|
proc testDefineScan() =
|
|
let mapped = CompileTimeDefineMap.mapIt(it.defineName).toHashSet()
|
|
var found: seq[string]
|
|
for path in scannedFiles():
|
|
for line in lines(path):
|
|
for sym in defineSymbolsOn(line):
|
|
found.add sym
|
|
var missing: seq[string]
|
|
for sym in found:
|
|
if sym notin mapped: missing.add sym
|
|
check "tree define scan is alive (>= 20 symbols)", found.len >= 20
|
|
check "every intdefine/strdefine/booldefine is in the map: " &
|
|
$missing, missing.len == 0
|
|
|
|
# ── driver ───────────────────────────────────────────────────────────────────
|
|
|
|
testKnownNames()
|
|
testUnknownEnvNames()
|
|
testDefineMap()
|
|
testTreeScan()
|
|
testDefineScan()
|
|
|
|
if failures > 0:
|
|
echo "\n", failures, " check(s) FAILED"
|
|
quit(1)
|
|
echo "\nAll env-report checks passed."
|