defmodule VavPipeline.SugyaTest do @moduledoc "The case behind each threshold (specs/sugya.md §IV, step 1): the facts are whole, and the Doorpost refuses a rule without them." use ExUnit.Case, async: false alias VavPipeline.{Anchors, Doorpost, Sugya} test "the sugya file is a Doorpost file, beside the anchors" do assert "talmudic_engine/src/halt/sugya.pl" in Doorpost.files() assert "talmudic_engine/src/halt/anchors.pl" in Doorpost.files() end test "every anchored rule has a kind, a precedent and a dissent; every verse is in L1" do assert :ok = Sugya.verify() {:ok, anchors} = Anchors.declared() {:ok, s} = Sugya.declared() for a <- anchors do assert Enum.any?(s.kinds, &(&1.rule == a.rule)), "#{a.rule} has no kind" assert Enum.any?(s.precedents, &(&1.rule == a.rule)), "#{a.rule} has no precedent" assert Enum.any?(s.dissents, &(&1.rule == a.rule)), "#{a.rule} has no dissent" end end test "the kinds follow sugya.md §II: marks seen once, the forms as deeds, the grounding rules as words" do {:ok, s} = Sugya.declared() kind = fn r -> Enum.find_value(s.kinds, &(&1.rule == r && &1.kind)) end assert kind.("lo_taaseh_lekha") == "deed" assert kind.("golden_calf") == "word" assert kind.("self_grounding") == "word" assert kind.("even_vaaven") == "measure" for r <- ~w(avodah_zarah shfichut_damim gilui_arayot parah_adumah carrier_centered chelbenah), do: assert(kind.(r) == "mark", r) end test "the exception the reader asked to see cited: forged_fringe stands on one witness because it is a mark on the offering" do {:ok, s} = Sugya.declared() e = Enum.find(s.exceptions, &(&1.rule == "lo_taaseh_lekha" and &1.condition =~ "forged_fringe")) assert e, "no single-witness exception for forged_fringe" assert Sugya.cite(e.verse) == "Vayikra 22:20" # and the two-witness dissent is recorded for every form assert Enum.any?(s.dissents, &(&1.rule == "lo_taaseh_lekha" and &1.reading == "single_witness_noted")) end test "for_rule/1 renders a rule's sugya for a verdict to carry" do r = Sugya.for_rule("golden_calf") assert r.kind == "word" and r.verse == "Devarim 18:22" assert r.precedent == "tablet(49)" assert Enum.any?(r.dissent, &(&1.reading == "hedged")) assert Enum.any?(r.exception, &(&1.condition == "no_ground_given")) assert Sugya.for_rule("no_such_rule") == nil end describe "drift (synthetic spec root)" do setup do temp = Path.join(System.tmp_dir!(), "sugya_test_#{System.unique_integer([:positive])}") for rel <- Doorpost.files() do src = Path.join(Doorpost.repo_root(), rel) dst = Path.join(temp, rel) File.mkdir_p!(Path.dirname(dst)) if File.exists?(src), do: File.cp!(src, dst) end on_exit(fn -> File.rm_rf!(temp) end) %{temp: temp, path: Path.join(temp, "talmudic_engine/src/halt/sugya.pl")} end test "a mirror verifies", %{temp: temp} do assert :ok = Sugya.verify(temp) end test "a rule without a dissent fails: the minority must be recorded", %{temp: temp, path: path} do text = File.read!(path) |> String.replace(~r/^dissent\(even_vaaven,.*\n/m, "") File.write!(path, text) assert {:error, "SUGYA_MISSING: rule even_vaaven has no dissent" <> _} = Sugya.verify(temp) end test "a rule without a kind fails", %{temp: temp, path: path} do File.write!(path, String.replace(File.read!(path), "kind(chelbenah, mark, verse(vayikra, 13, 3)).", "")) assert {:error, "SUGYA_MISSING: rule chelbenah has no kind" <> _} = Sugya.verify(temp) end test "a kind that is not one of the four fails", %{temp: temp, path: path} do File.write!(path, String.replace(File.read!(path), "kind(chelbenah, mark,", "kind(chelbenah, rumour,")) assert {:error, "SUGYA_INVALID: rule chelbenah has kind rumour" <> _} = Sugya.verify(temp) end test "a verse that is not in L1 fails", %{temp: temp, path: path} do File.write!(path, String.replace(File.read!(path), "verse(vayikra, 22, 20)", "verse(vayikra, 22, 99)")) assert {:error, "SUGYA_NOT_IN_L1: Vayikra 22:99" <> _} = Sugya.verify(temp) end test "a sugya for a rule that has no anchor fails: nothing added", %{temp: temp, path: path} do File.write!(path, File.read!(path) <> "\nexception(new_rule, whatever, verse(bereishit, 1, 1)).\n") assert {:error, "SUGYA_INVALID: " <> _ = msg} = Sugya.verify(temp) assert msg =~ "new_rule" end test "a fact in a comment is not a fact", %{temp: temp, path: path} do File.write!(path, File.read!(path) <> "\n%% kind(imaginary, mark, verse(bereishit, 1, 1)).\n") assert :ok = Sugya.verify(temp) end test "a missing sugya file fails", %{temp: temp, path: path} do File.rm!(path) assert {:error, "SUGYA_UNREADABLE: " <> _} = Sugya.verify(temp) end end end