prop/test/microwaveprop/cache_test.exs
Graham McIntire cc3dc41a6b
Fix all medium findings and split contact_live_test.exs
- Fix N+1 queries in radio.ex (preload :user)
- Add encryption_salt to session options
- Consolidate token deletion to single query
- Wrap gunzip in try/rescue for corrupt files
- Add Cache.match_delete/1 to encapsulate ETS access
- Precompute sec_i_factor_ref as module attribute
- Guard EXLA.Backend config to dev/test only
- Split 3505-line contact_live_test.exs into 4 files
- Replace Process.sleep with :sys.get_state synchronization
- Replace Process.alive? with DOM output assertions
- Clarify router.ex comment for non-live_session routes
- Update findings.md to reflect fixes
2026-05-29 15:53:04 -05:00

74 lines
2.3 KiB
Elixir

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)
Cache.sweep()
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)
Cache.sweep()
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