defmodule VavPipeline.Tablet50SocketLineTest do @moduledoc """ Tablet 50 (2026-10-06) — one reply is one line, however long. Both socket clients read a reply with a single `:gen_tcp.recv/3`, which returns at most one receive buffer (1460 bytes). A bedikah of forty claims answered in 18 KB; the client decoded the first 1460 bytes, failed, reconnected, failed again, and left the retry's socket open — the single-threaded Korban Processor then waited on that dead conversation and every later bedikah timed out. Live, for everyone. This test stands up a one-line server that answers with a long line and a short one, and asks both clients for them. """ use ExUnit.Case, async: false alias VavPipeline.{KorbanProcessorSocket, TalmudicEngineSocket} @long_pad String.duplicate("x", 60_000) setup do path = Path.join(System.tmp_dir!(), "tablet50_#{System.unique_integer([:positive])}.sock") File.rm(path) {:ok, listen} = :gen_tcp.listen(0, [:binary, active: false, packet: :raw, ifaddr: {:local, String.to_charlist(path)}]) parent = self() server = spawn_link(fn -> loop = fn loop -> {:ok, conn} = :gen_tcp.accept(listen) serve = fn serve -> case read_line(conn) do {:ok, line} -> send(parent, {:server_got, byte_size(line)}) reply = Jason.encode!(%{"status" => "ok", "examination" => %{"pad" => @long_pad, "claims" => []}, "violations" => [], "action" => "t"}) :ok = :gen_tcp.send(conn, reply <> "\n") serve.(serve) _ -> :gen_tcp.close(conn) end end serve.(serve) loop.(loop) end loop.(loop) end) on_exit(fn -> Process.exit(server, :kill); File.rm(path) end) %{path: path} end test "the Korban client reads a 60 KB reply whole, and the next call still works", %{path: path} do {:ok, pid} = GenServer.start_link(KorbanProcessorSocket, [socket_path: path], name: :tablet50_korban) on_exit(fn -> if Process.alive?(pid), do: GenServer.stop(pid) end) for _ <- 1..3 do assert {:ok, %{"status" => "ok", "examination" => %{"pad" => pad}}} = GenServer.call(:tablet50_korban, {:request, Jason.encode!(%{"action" => "examine", "output" => String.duplicate("y", 20_000)})}, 15_000) assert byte_size(pad) == 60_000 assert_receive {:server_got, got}, 5_000 assert got > 20_000 end end test "the Talmudic client reads a 60 KB reply whole", %{path: path} do {:ok, pid} = GenServer.start_link(TalmudicEngineSocket, [socket_path: path], name: :tablet50_talmudic) on_exit(fn -> if Process.alive?(pid), do: GenServer.stop(pid) end) assert {:ok, %{"status" => "ok"} = reply} = GenServer.call(:tablet50_talmudic, {:request, Jason.encode!(%{"action" => "halt_check"})}, 15_000) assert byte_size(reply["examination"]["pad"]) == 60_000 end defp read_line(conn, acc \\ "") do case :gen_tcp.recv(conn, 0, 5_000) do {:ok, chunk} -> acc = acc <> chunk if String.ends_with?(acc, "\n"), do: {:ok, acc}, else: read_line(conn, acc) err -> err end end end