defmodule Microwaveprop.CacheTest do use ExUnit.Case, async: false alias Microwaveprop.Cache setup do Cache.clear() :ok end describe "fetch_or_store/3" do test "invokes the function and returns the value on a cold cache" do assert Cache.fetch_or_store(:the_key, 1_000, fn -> 42 end) == 42 end test "returns the cached value without invoking the function on a warm hit" do Cache.fetch_or_store(:the_key, 1_000, fn -> 42 end) assert Cache.fetch_or_store(:the_key, 1_000, fn -> raise "should not run" end) == 42 end test "re-invokes the function once the TTL expires" do Cache.put(:the_key, 1, -1) assert Cache.fetch_or_store(:the_key, 1_000, fn -> 2 end) == 2 end test "isolates values by key" do assert Cache.fetch_or_store(:a, 1_000, fn -> 1 end) == 1 assert Cache.fetch_or_store(:b, 1_000, fn -> 2 end) == 2 assert Cache.fetch_or_store(:a, 1_000, fn -> raise "no" end) == 1 assert Cache.fetch_or_store(:b, 1_000, fn -> raise "no" end) == 2 end end describe "put/3 and invalidate/1" do test "put/3 stores a value with the given TTL" do Cache.put(:k, "hello", 1_000) assert Cache.fetch_or_store(:k, 1_000, fn -> "other" end) == "hello" end test "invalidate/1 removes an entry, forcing the next fetch to recompute" do Cache.put(:k, "stale", 60_000) Cache.invalidate(:k) assert Cache.fetch_or_store(:k, 1_000, fn -> "fresh" end) == "fresh" end end describe "sweep/0" do test "removes expired entries" do Cache.put(:expired, "old", 1) Process.sleep(5) assert Cache.sweep() >= 1 assert :ets.lookup(:microwaveprop_cache, :expired) == [] end test "leaves unexpired entries in place" do Cache.put(:fresh, "new", 60_000) _ = Cache.sweep() assert [{:fresh, "new", _}] = :ets.lookup(:microwaveprop_cache, :fresh) end test "handles a mix of expired and unexpired entries" do Cache.put(:expired_a, 1, 1) Cache.put(:expired_b, 2, 1) Cache.put(:fresh, 3, 60_000) Process.sleep(5) deleted = Cache.sweep() assert deleted >= 2 assert :ets.lookup(:microwaveprop_cache, :expired_a) == [] assert :ets.lookup(:microwaveprop_cache, :expired_b) == [] assert [{:fresh, 3, _}] = :ets.lookup(:microwaveprop_cache, :fresh) end end end