from src.cpg.context_extractor import DEFAULT_TOKEN_BUDGET, build_context, render_context def test_no_context_available_returns_has_context_false(): ctx = build_context({}, {}, []) assert ctx.has_context is False assert render_context(ctx) == "" def test_context_fits_under_budget_keeps_everything(): ctx = build_context( callee_bodies={"foo": "int foo() { return 1; }"}, callee_signatures={"bar": "int bar(int);"}, global_decls=["#define MAX 10"], ) assert ctx.has_context is True assert ctx.truncated is False assert "foo" in ctx.callee_bodies assert "bar" in ctx.callee_signatures assert ctx.global_decls == ["#define MAX 10"] def test_truncates_callee_bodies_before_dropping_whole_function(): big_body = "x " * 10_000 # ~10000 tokens, way over budget small_body = "int small() { return 0; }" ctx = build_context( callee_bodies={"big": big_body, "small": small_body}, callee_signatures={}, global_decls=[], token_budget=100, ) assert ctx.truncated is True assert "big" not in ctx.callee_bodies # dropped entirely, not mid-body assert "small" in ctx.callee_bodies def test_drops_2hop_signatures_after_bodies_exhaust_budget(): body = "x " * 90 # exactly 90 whitespace-split tokens sig = "int sig(int);" # 2 tokens ctx = build_context( callee_bodies={"body_fn": body}, callee_signatures={"sig_fn": sig}, global_decls=[], token_budget=90, # leaves 0 remaining after the body, so sig must drop ) assert "body_fn" in ctx.callee_bodies assert "sig_fn" not in ctx.callee_signatures assert ctx.truncated is True def test_global_decls_prioritized_over_callee_bodies(): decl = "typedef struct { int x; } Point;" body = "y " * 10_000 ctx = build_context( callee_bodies={"big": body}, callee_signatures={}, global_decls=[decl], token_budget=50, ) assert ctx.global_decls == [decl] assert "big" not in ctx.callee_bodies def test_default_budget_is_4096(): assert DEFAULT_TOKEN_BUDGET == 4096 def test_render_context_includes_all_kept_parts(): ctx = build_context( callee_bodies={"foo": "int foo() {}"}, callee_signatures={"bar": "int bar(int);"}, global_decls=["#define X 1"], ) rendered = render_context(ctx) assert "#define X 1" in rendered assert "foo" in rendered assert "bar" in rendered