defmodule Aprsme.RegexCacheTest do # async: false — the cache is a singleton GenServer owning a named ETS table # shared across the whole application. Parallel tests would see each other. use ExUnit.Case, async: false alias Aprsme.RegexCache # Each test gets a unique pattern to avoid cross-test pollution of the # shared cache (we can't safely clear it without racing other callers). defp unique_pattern(tag) do suffix = System.unique_integer([:positive, :monotonic]) "#{tag}_#{suffix}" end describe "get_or_compile/1" do test "compiles and returns a Regex on first call" do pattern = unique_pattern("hello") assert {:ok, regex} = RegexCache.get_or_compile(pattern) assert %Regex{} = regex assert Regex.match?(regex, pattern) end test "returns the same compiled regex on subsequent calls" do pattern = unique_pattern("same") assert {:ok, r1} = RegexCache.get_or_compile(pattern) assert {:ok, r2} = RegexCache.get_or_compile(pattern) assert r1 == r2 end test "returns {:error, _} for invalid patterns" do assert {:error, _reason} = RegexCache.get_or_compile("[") assert {:error, _reason} = RegexCache.get_or_compile("(unbalanced") end test "does not cache failed compilations" do assert {:error, _} = RegexCache.get_or_compile("[bad") # Still an error on retry — error path didn't poison the cache with nil. assert {:error, _} = RegexCache.get_or_compile("[bad") end test "distinct patterns produce distinct regexes" do p1 = unique_pattern("a") p2 = unique_pattern("b") assert {:ok, r1} = RegexCache.get_or_compile(p1) assert {:ok, r2} = RegexCache.get_or_compile(p2) refute r1 == r2 end test "compiled regex actually matches as expected" do pattern = unique_pattern("match") <> "\\d+" assert {:ok, regex} = RegexCache.get_or_compile(pattern) base = String.trim_trailing(pattern, "\\d+") assert Regex.match?(regex, "#{base}123") refute Regex.match?(regex, "nope") end end end