symbiont_ex/test/symbiont/queue_test.exs

115 lines
3.2 KiB
Elixir

defmodule Symbiont.QueueTest do
use ExUnit.Case, async: false
@moduletag :capture_log
setup do
tmp_dir = Path.join(System.tmp_dir!(), "symbiont_queue_test_#{:rand.uniform(999_999)}")
File.mkdir_p!(tmp_dir)
if Process.whereis(Symbiont.Queue), do: GenServer.stop(Symbiont.Queue)
{:ok, _pid} = Symbiont.Queue.start_link(data_dir: tmp_dir)
on_exit(fn ->
if Process.whereis(Symbiont.Queue), do: GenServer.stop(Symbiont.Queue)
File.rm_rf!(tmp_dir)
end)
%{tmp_dir: tmp_dir}
end
test "starts with empty queue" do
assert Symbiont.Queue.size() == 0
assert Symbiont.Queue.list() == []
end
test "enqueue adds tasks and returns IDs" do
{:ok, id1} = Symbiont.Queue.enqueue("Task one")
{:ok, id2} = Symbiont.Queue.enqueue("Task two", "high")
assert is_binary(id1)
assert is_binary(id2)
assert id1 != id2
assert Symbiont.Queue.size() == 2
end
test "take returns pending tasks and marks them as processing" do
{:ok, _} = Symbiont.Queue.enqueue("Task A")
{:ok, _} = Symbiont.Queue.enqueue("Task B")
{:ok, _} = Symbiont.Queue.enqueue("Task C")
taken = Symbiont.Queue.take(2)
assert length(taken) == 2
assert Enum.all?(taken, &(&1["status"] == "processing"))
# Only 1 pending remains
assert Symbiont.Queue.size() == 1
end
test "complete marks a task as done" do
{:ok, id} = Symbiont.Queue.enqueue("Complete me")
[task] = Symbiont.Queue.take(1)
assert task["id"] == id
Symbiont.Queue.complete(id, "All done!")
Process.sleep(50)
tasks = Symbiont.Queue.list()
done = Enum.find(tasks, &(&1["id"] == id))
assert done["status"] == "done"
assert done["result"] == "All done!"
end
test "fail marks a task as failed" do
{:ok, id} = Symbiont.Queue.enqueue("Fail me")
_taken = Symbiont.Queue.take(1)
Symbiont.Queue.fail(id, "something broke")
Process.sleep(50)
tasks = Symbiont.Queue.list()
failed = Enum.find(tasks, &(&1["id"] == id))
assert failed["status"] == "failed"
assert failed["result"] == "something broke"
end
test "list filters by status" do
{:ok, _} = Symbiont.Queue.enqueue("Pending 1")
{:ok, _} = Symbiont.Queue.enqueue("To complete")
# Take one task (first pending)
[taken] = Symbiont.Queue.take(1)
# Complete the taken task
Symbiont.Queue.complete(taken["id"], "done")
Process.sleep(50)
pending = Symbiont.Queue.list("pending")
assert length(pending) == 1
done = Symbiont.Queue.list("done")
assert length(done) == 1
end
test "queue persists to JSONL file", %{tmp_dir: tmp_dir} do
{:ok, _} = Symbiont.Queue.enqueue("Persistent task")
path = Path.join(tmp_dir, "queue.jsonl")
content = File.read!(path)
assert String.contains?(content, "Persistent task")
assert String.contains?(content, "pending")
end
test "queue loads tasks from file on restart", %{tmp_dir: tmp_dir} do
{:ok, _} = Symbiont.Queue.enqueue("Survivor task")
assert Symbiont.Queue.size() == 1
# Stop and restart
GenServer.stop(Symbiont.Queue)
{:ok, _} = Symbiont.Queue.start_link(data_dir: tmp_dir)
assert Symbiont.Queue.size() == 1
[task] = Symbiont.Queue.list("pending")
assert task["task"] == "Survivor task"
end
end