LightNest / experiments /tests /test_native_recursive.py
LIghtJUNction's picture
Integrate latest architecture breakthrough, harder tasks, and evaluation suite
e64c5d2 verified
Raw History Blame Contribute Delete
3.52 kB
"""Fast contract checks; long learned lineage experiments are saved separately."""
import hashlib
import json
from pathlib import Path
import subprocess
import pytest
import torch
from lightnest.learned_patch import PatchNetwork, encode
from lightnest.pack_recursive import build
@pytest.fixture(scope="module")
def native(tmp_path_factory):
directory = tmp_path_factory.mktemp("recursive")
torch.set_num_threads(2)
torch.manual_seed(716031)
model = PatchNetwork().eval()
checkpoint = directory / "model.pt"
torch.save({"state_dict": model.state_dict(), "threshold": .55}, checkpoint)
executable = build(checkpoint, directory / "parent")
return executable, checkpoint, model
def run(executable, *args):
return subprocess.run([str(executable), *map(str, args)], capture_output=True, timeout=20)
def test_proposals_match_python(native, tmp_path):
executable, _, model = native
raw = bytes([3, 7, 10, 19, 31])
path = tmp_path / "window"
path.write_bytes(raw)
result = run(executable, "--propose", "change add to sub", path)
assert result.returncode == 0, result.stderr
actual = json.loads(result.stdout)
command, binary = encode("change add to sub", raw)
with torch.no_grad():
scores, bits = model(torch.tensor([command]), torch.tensor([binary]))
position = int(scores[0].argmax())
byte = 0 if position == 256 else sum(int(bits[0, position, k] >= 0) << k for k in range(8))
assert (actual["position"], actual["byte"]) == (position, byte)
assert actual["pointer_confidence"] == pytest.approx(float(scores[0].softmax(0)[position]), abs=2e-6)
@pytest.mark.parametrize("generations,updates,reason", [(0, 256, "generation_budget"), (3, 0, "zero_updates")])
def test_budget_stops_without_child_or_parent_change(native, tmp_path, generations, updates, reason):
executable, _, _ = native
before = hashlib.sha256(executable.read_bytes()).digest()
directory = tmp_path / "children"
result = run(executable, "--evolve", directory, generations, updates)
assert result.returncode == 0, result.stderr
events = [json.loads(line) for line in result.stdout.splitlines()]
assert events[-1]["reason"] == reason
assert not list(directory.iterdir())
assert hashlib.sha256(executable.read_bytes()).digest() == before
def test_uninitialized_continuation_and_invalid_limits_reject(native, tmp_path):
executable, _, _ = native
assert run(executable, "--continue", tmp_path / "child").returncode != 0
for generations, updates in [(9, 1), (3, 2049), (-1, 4), (2.5, 4), (3, "nan")]:
result = run(executable, "--evolve", tmp_path / "child", generations, updates)
assert result.returncode != 0
assert not (tmp_path / "child").exists()
def test_checkpoint_semantics_and_output_publication(native, tmp_path):
executable, checkpoint, model = native
before = executable.read_bytes()
with pytest.raises(FileExistsError):
build(checkpoint, executable)
link = tmp_path / "link"
link.symlink_to(executable)
with pytest.raises(FileExistsError):
build(checkpoint, link)
unsupported = tmp_path / "xor.pt"
torch.save({"state_dict": model.state_dict(), "threshold": .55,
"architecture": "xor-mask"}, unsupported)
with pytest.raises(ValueError, match="architecture"):
build(unsupported, tmp_path / "wrong-model")
assert not (tmp_path / "wrong-model").exists()
assert executable.read_bytes() == before