238 lines
6 KiB
Elixir
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
|