test: add ping/escalation tests; coverage 84.99% → 85.13%

This commit is contained in:
Graham McIntire 2026-05-08 11:23:08 -05:00
parent fd75837ae9
commit c7c9f893a5
2 changed files with 113 additions and 1 deletions

View file

@ -133,7 +133,6 @@ defmodule Towerops.Monitoring.PingTest do
# correctly handles various response formats by testing with valid IPs
# that return quickly (localhost)
@tag :integration
test "localhost ping returns valid response format" do
result = Ping.ping("127.0.0.1", 2000)
@ -149,6 +148,24 @@ defmodule Towerops.Monitoring.PingTest do
end
end
test "default-arity ping/1 dispatches to ping/2" do
# ping/1 calls ping(ip, 5000); we mostly want to exercise the arity
# without slowing the suite down for a real timeout.
result = Ping.ping("127.0.0.1")
case result do
{:ok, response_time} -> assert is_float(response_time)
{:error, reason} -> assert reason in [:timeout, :command_not_found, :parse_error]
end
end
test "unreachable IP returns :timeout error" do
# 192.0.2.0/24 is reserved for documentation per RFC 5737 — never routed.
result = Ping.ping("192.0.2.1", 1000)
# Either the OS resolves immediately (timeout) or the binary is missing.
assert match?({:error, :timeout}, result) or match?({:error, _}, result)
end
@tag :integration
test "IPv6 localhost ping returns valid response format" do
result = Ping.ping("::1", 2000)

View file

@ -9,6 +9,7 @@ defmodule Towerops.OnCall.EscalationTest do
alias Towerops.Alerts
alias Towerops.OnCall.Escalation
alias Towerops.OnCall.Incident
setup do
user = user_fixture()
@ -146,4 +147,98 @@ defmodule Towerops.OnCall.EscalationTest do
assert Escalation.find_incident_for_alert(Ecto.UUID.generate()) == nil
end
end
describe "check_and_escalate/1" do
test "is a no-op when the incident no longer exists" do
assert :ok = Escalation.check_and_escalate(Ecto.UUID.generate())
end
test "is a no-op for acknowledged incidents", ctx do
policy = escalation_policy_fixture(ctx.organization.id)
rule = escalation_rule_fixture(policy.id, %{position: 0, timeout_minutes: 5})
escalation_target_fixture(rule.id, %{target_type: "user", user_id: ctx.user.id})
{:ok, alert} =
Alerts.create_alert(%{
alert_type: "device_down",
device_id: ctx.device.id,
triggered_at: DateTime.utc_now(),
message: "Device is down"
})
{:ok, incident} = Escalation.start_escalation(alert, policy.id)
{:ok, _} = Escalation.acknowledge_incident(incident.id, ctx.user.id)
assert :ok = Escalation.check_and_escalate(incident.id)
end
test "advances to the next rule when current is not the last", ctx do
policy = escalation_policy_fixture(ctx.organization.id)
rule0 = escalation_rule_fixture(policy.id, %{position: 0, timeout_minutes: 1})
_rule1 = escalation_rule_fixture(policy.id, %{position: 1, timeout_minutes: 1})
escalation_target_fixture(rule0.id, %{target_type: "user", user_id: ctx.user.id})
{:ok, alert} =
Alerts.create_alert(%{
alert_type: "device_down",
device_id: ctx.device.id,
triggered_at: DateTime.utc_now(),
message: "Device is down"
})
{:ok, incident} = Escalation.start_escalation(alert, policy.id)
assert :ok = Escalation.check_and_escalate(incident.id)
reloaded = Towerops.Repo.get!(Incident, incident.id)
assert reloaded.current_rule_position == 1
end
test "loops back to first rule when current is last and repeat_count not exhausted",
ctx do
policy =
escalation_policy_fixture(ctx.organization.id, %{repeat_count: 2})
rule0 = escalation_rule_fixture(policy.id, %{position: 0, timeout_minutes: 1})
escalation_target_fixture(rule0.id, %{target_type: "user", user_id: ctx.user.id})
{:ok, alert} =
Alerts.create_alert(%{
alert_type: "device_down",
device_id: ctx.device.id,
triggered_at: DateTime.utc_now(),
message: "Device is down"
})
{:ok, incident} = Escalation.start_escalation(alert, policy.id)
assert :ok = Escalation.check_and_escalate(incident.id)
reloaded = Towerops.Repo.get!(Incident, incident.id)
assert reloaded.current_loop == 2
assert reloaded.current_rule_position == 0
end
test "exhausts when current is last rule and loop count met", ctx do
policy =
escalation_policy_fixture(ctx.organization.id, %{repeat_count: 1})
rule0 = escalation_rule_fixture(policy.id, %{position: 0, timeout_minutes: 1})
escalation_target_fixture(rule0.id, %{target_type: "user", user_id: ctx.user.id})
{:ok, alert} =
Alerts.create_alert(%{
alert_type: "device_down",
device_id: ctx.device.id,
triggered_at: DateTime.utc_now(),
message: "Device is down"
})
{:ok, incident} = Escalation.start_escalation(alert, policy.id)
# current_loop is already 1 == repeat_count, so further escalation is exhausted
assert :ok = Escalation.check_and_escalate(incident.id)
end
end
end