"""Tests for lambdagent primitives: Compose, If, Loop, Pair, Fst, Snd, Tool.""" import pytest from lambdagent.core import Context from lambdagent.primitives import Compose, If, Loop, Pair, Fst, Snd, Tool def make_tool(name, fn): return Tool(name, fn) def test_tool_apply(): t = make_tool("double", lambda x: int(x) * 2) assert t("3") == 6 def test_tool_trace(): ctx = Context() t = make_tool("inc", lambda x: int(x) + 1) t.apply("5", ctx) assert len(ctx.trace) == 1 assert ctx.trace[0].output == 6 def test_compose(): a = make_tool("add1", lambda x: int(x) + 1) b = make_tool("mul2", lambda x: int(x) * 2) pipe = Compose(a, b) assert pipe("3") == 8 # (3+1)*2 def test_compose_operator(): a = make_tool("a", lambda x: x + "A") b = make_tool("b", lambda x: x + "B") c = make_tool("c", lambda x: x + "C") pipe = a >> b >> c assert pipe("") == "ABC" def test_if_truthy(): t = make_tool("yes", lambda x: "YES") f = make_tool("no", lambda x: "NO") cond = If(lambda x: x == "go", t, f) assert cond("go") == "YES" assert cond("stop") == "NO" def test_if_term_cond(): cond_term = make_tool("check", lambda x: "TRUE" if len(x) > 3 else "FALSE") t = make_tool("long", lambda x: "long") f = make_tool("short", lambda x: "short") branch = If(cond_term, t, f) assert branch("hello") == "long" assert branch("hi") == "short" def test_loop(): counter = {"n": 0} def step(x): counter["n"] += 1 return int(x) + 1 body = make_tool("inc", step) loop = Loop(body, condition=lambda r, s: int(r) >= 5, max_steps=20) result = loop("0") assert result == 5 assert counter["n"] == 5 def test_loop_max_steps(): body = make_tool("noop", lambda x: x) loop = Loop(body, condition=lambda r, s: False, max_steps=3) loop("x") # Should not infinite loop def test_pair(): a = make_tool("upper", lambda x: x.upper()) b = make_tool("lower", lambda x: x.lower()) p = Pair(a, b) assert p("Hello") == ("HELLO", "hello") def test_fst_snd(): assert Fst()(("a", "b")) == "a" assert Snd()(("a", "b")) == "b"