From 00af878d1dd041a6e029f1bf15cfb505ccab8bc1 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Fri, 24 Apr 2026 08:05:27 -0500 Subject: [PATCH] test: Aprsme.Is init/1 connect success and failure paths --- test/aprsme/is_test.exs | 75 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/test/aprsme/is_test.exs b/test/aprsme/is_test.exs index 1b510c8..b6c7457 100644 --- a/test/aprsme/is_test.exs +++ b/test/aprsme/is_test.exs @@ -644,6 +644,81 @@ defmodule Aprsme.IsTest do end end + describe "init/1 with real TCP connection (not :test env)" do + test "connects and sets up timers on successful login" do + {:ok, listen} = :gen_tcp.listen(0, [:binary, active: false, reuseaddr: true]) + {:ok, port} = :inet.port(listen) + + spawn_link(fn -> + case :gen_tcp.accept(listen, 5_000) do + {:ok, srv} -> + _ = :gen_tcp.recv(srv, 0, 1_000) + _ = :gen_tcp.close(srv) + + _ -> + :ok + end + end) + + original_disabled = Application.get_env(:aprsme, :disable_aprs_connection, false) + original_env = Application.get_env(:aprsme, :env) + original_server = Application.get_env(:aprsme, :aprs_is_server) + original_port = Application.get_env(:aprsme, :aprs_is_port) + + Application.put_env(:aprsme, :disable_aprs_connection, false) + Application.put_env(:aprsme, :env, :dev) + Application.put_env(:aprsme, :aprs_is_server, ~c"127.0.0.1") + Application.put_env(:aprsme, :aprs_is_port, port) + + try do + capture_log(fn -> + assert {:ok, state} = Aprsme.Is.init([]) + # Socket should be set after successful connect. + assert state.socket + assert is_reference(state.timer) + assert is_reference(state.keepalive_timer) + + # Cleanup + if state.socket, do: :gen_tcp.close(state.socket) + if state.timer, do: Process.cancel_timer(state.timer) + if state.keepalive_timer, do: Process.cancel_timer(state.keepalive_timer) + end) + after + Application.put_env(:aprsme, :disable_aprs_connection, original_disabled) + Application.put_env(:aprsme, :env, original_env) + if original_server, do: Application.put_env(:aprsme, :aprs_is_server, original_server) + if original_port, do: Application.put_env(:aprsme, :aprs_is_port, original_port) + _ = :gen_tcp.close(listen) + end + end + + test "handles connect failure gracefully" do + original_disabled = Application.get_env(:aprsme, :disable_aprs_connection, false) + original_env = Application.get_env(:aprsme, :env) + original_server = Application.get_env(:aprsme, :aprs_is_server) + original_port = Application.get_env(:aprsme, :aprs_is_port) + + Application.put_env(:aprsme, :disable_aprs_connection, false) + Application.put_env(:aprsme, :env, :dev) + Application.put_env(:aprsme, :aprs_is_server, ~c"127.0.0.1") + # Port 1 → connection refused. + Application.put_env(:aprsme, :aprs_is_port, 1) + + try do + capture_log(fn -> + assert {:ok, state} = Aprsme.Is.init([]) + # Connection failed — socket stays nil but state is still returned. + assert is_nil(state.socket) + end) + after + Application.put_env(:aprsme, :disable_aprs_connection, original_disabled) + Application.put_env(:aprsme, :env, original_env) + if original_server, do: Application.put_env(:aprsme, :aprs_is_server, original_server) + if original_port, do: Application.put_env(:aprsme, :aprs_is_port, original_port) + end + end + end + describe "handle_info(:reconnect) when connect fails" do test "schedules another reconnect attempt on connection error" do # Port 1 should always refuse or fail — triggers the connect-error branch.