aprs.me/test/aprsme/archiver_test.exs

238 lines
6 KiB
Elixir

defmodule Aprsme.ArchiverTest do
use ExUnit.Case, async: true
alias Aprsme.Archiver
describe "start_link/1" do
test "starts the archiver GenServer with default args" do
assert {:ok, pid} = Archiver.start_link()
assert is_pid(pid)
assert Process.alive?(pid)
# Clean up
GenServer.stop(pid)
end
test "starts the archiver GenServer with custom args" do
args = [some: :option]
assert {:ok, pid} = Archiver.start_link(args)
assert is_pid(pid)
assert Process.alive?(pid)
# Clean up
GenServer.stop(pid)
end
test "registers the process with name :archiver" do
# Ensure no previous archiver is running
if Process.whereis(:archiver) do
GenServer.stop(:archiver)
Process.sleep(10)
end
assert {:ok, pid} = Archiver.start_link()
assert Process.whereis(:archiver) == pid
# Clean up
GenServer.stop(:archiver)
end
test "returns error if archiver is already running" do
# Ensure no previous archiver is running
if Process.whereis(:archiver) do
GenServer.stop(:archiver)
Process.sleep(10)
end
assert {:ok, _pid1} = Archiver.start_link()
assert {:error, {:already_started, _pid}} = Archiver.start_link()
# Clean up
GenServer.stop(:archiver)
end
end
describe "init/1" do
test "initializes with default empty state" do
assert {:ok, []} = Archiver.init()
end
test "initializes with provided state" do
state = [some: :data]
assert {:ok, ^state} = Archiver.init(state)
end
test "schedules connect message after 5 seconds" do
# Start the GenServer to test init behavior
{:ok, pid} = Archiver.start_link()
# We can't easily test the exact timing without making the test slow,
# but we can verify the GenServer started successfully
assert Process.alive?(pid)
# Clean up
GenServer.stop(pid)
end
test "subscribes to the 'call' topic" do
# Mock the Endpoint.subscribe call
# Since we can't easily mock in this context, we'll just verify
# the GenServer starts without errors
{:ok, pid} = Archiver.start_link()
assert Process.alive?(pid)
# Clean up
GenServer.stop(pid)
end
end
describe "handle_info/2" do
setup do
{:ok, pid} = Archiver.start_link()
%{pid: pid}
end
test "handles :connect message", %{pid: pid} do
state = [some: :state]
# Send the connect message directly to test the handler
result = Archiver.handle_info(:connect, state)
assert {:noreply, ^state} = result
# Clean up
GenServer.stop(pid)
end
test "handles unknown messages", %{pid: pid} do
state = [some: :state]
# Send an unknown message
result = Archiver.handle_info(:unknown_message, state)
assert {:noreply, ^state} = result
# Clean up
GenServer.stop(pid)
end
test "handles various message types", %{pid: pid} do
state = [test: :data]
# Test different message types
messages = [
{:some, :tuple},
"string_message",
123,
%{map: "message"},
[:list, :message]
]
for message <- messages do
result = Archiver.handle_info(message, state)
assert {:noreply, ^state} = result
end
# Clean up
GenServer.stop(pid)
end
test "preserves state across different messages", %{pid: pid} do
initial_state = [counter: 0]
# Test that state is preserved
result1 = Archiver.handle_info(:connect, initial_state)
assert {:noreply, ^initial_state} = result1
result2 = Archiver.handle_info(:other_message, initial_state)
assert {:noreply, ^initial_state} = result2
# Clean up
GenServer.stop(pid)
end
end
describe "GenServer behavior" do
test "can send messages to running archiver" do
{:ok, pid} = Archiver.start_link()
# Send a message and verify the process handles it
send(pid, :test_message)
# Give it a moment to process
Process.sleep(10)
# Verify the process is still alive (didn't crash)
assert Process.alive?(pid)
# Clean up
GenServer.stop(pid)
end
test "can be stopped gracefully" do
{:ok, pid} = Archiver.start_link()
assert Process.alive?(pid)
# Stop the GenServer
:ok = GenServer.stop(pid)
# Give it a moment to stop
Process.sleep(10)
# Verify it's no longer alive
refute Process.alive?(pid)
end
test "handles multiple concurrent operations" do
{:ok, pid} = Archiver.start_link()
# Send multiple messages concurrently
tasks =
for i <- 1..10 do
Task.async(fn ->
send(pid, {:message, i})
:ok
end)
end
# Wait for all tasks to complete
Enum.each(tasks, &Task.await/1)
# Verify the process is still alive
assert Process.alive?(pid)
# Clean up
GenServer.stop(pid)
end
end
describe "module constants and specs" do
test "has correct topic constant" do
# This tests that the module compiles correctly with the @topic attribute
# The actual value is tested indirectly through the init function
assert Code.ensure_loaded?(Archiver)
end
test "has correct typespec for start_link" do
# This ensures the module compiles with correct typespecs
# We can't directly test typespecs, but we can ensure the function
# behaves according to its spec
result = Archiver.start_link([])
assert match?({:ok, _pid}, result) or match?({:error, _reason}, result)
if match?({:ok, _pid}, result) do
GenServer.stop(elem(result, 1))
end
end
test "has correct typespec for init" do
# Test that init returns the expected format
result = Archiver.init([])
assert {:ok, []} = result
result2 = Archiver.init(some: :data)
assert {:ok, [some: :data]} = result2
end
end
end