Changes: - Updated MonitorWorker to use configured ping_module adapter instead of System.cmd - Removed direct ping command execution and regex parsing - Simplified ping_device/1 to use adapter.ping/2 (mockable in tests) - Added PingMock expectations to all MonitorWorker tests - Removed @tag :integration from unreachable host test (now mocked) - All ping calls now use mocked responses in tests Benefits: - MonitorWorker tests now run in 0.2s instead of 5+ seconds - No real ICMP network traffic during test runs - Tests are deterministic and don't depend on network conditions - Follows same adapter pattern as SNMP (testable, configurable) All 1041 tests passing with no real network operations.
154 lines
4.3 KiB
Elixir
154 lines
4.3 KiB
Elixir
defmodule Towerops.Workers.MonitorWorkerTest do
|
|
use Towerops.DataCase, async: true
|
|
|
|
import Mox
|
|
import Towerops.AccountsFixtures
|
|
|
|
alias Towerops.Monitoring
|
|
alias Towerops.Monitoring.PingMock
|
|
alias Towerops.Workers.MonitorWorker
|
|
|
|
setup :verify_on_exit!
|
|
|
|
setup do
|
|
user = user_fixture()
|
|
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)
|
|
|
|
{:ok, site} =
|
|
Towerops.Sites.create_site(%{
|
|
name: "Test Site",
|
|
organization_id: organization.id
|
|
})
|
|
|
|
{:ok, device} =
|
|
Towerops.Devices.create_device(%{
|
|
name: "Test Device",
|
|
# Use localhost for reliable testing
|
|
ip_address: "127.0.0.1",
|
|
monitoring_enabled: true,
|
|
site_id: site.id
|
|
})
|
|
|
|
{:ok, device: device, org: organization}
|
|
end
|
|
|
|
describe "perform/1" do
|
|
test "creates a check when monitoring is enabled", %{device: device} do
|
|
# Mock successful ping
|
|
expect(PingMock, :ping, fn _ip, _timeout ->
|
|
{:ok, 10.5}
|
|
end)
|
|
|
|
result = MonitorWorker.perform(device.id)
|
|
|
|
# Should return :ok
|
|
assert result == :ok
|
|
|
|
# Verify a successful check was created
|
|
checks = Monitoring.list_devices_checks(device.id, 10)
|
|
assert length(checks) == 1
|
|
|
|
check = hd(checks)
|
|
assert check.device_id == device.id
|
|
assert check.status == :success
|
|
assert check.checked_at
|
|
assert check.response_time_ms == 10.5
|
|
end
|
|
|
|
test "skips check when monitoring is disabled", %{device: device} do
|
|
# Disable monitoring
|
|
{:ok, device} = Towerops.Devices.update_device(device, %{monitoring_enabled: false})
|
|
|
|
assert :ok = MonitorWorker.perform(device.id)
|
|
|
|
# Verify no check was created
|
|
checks = Monitoring.list_devices_checks(device.id, 10)
|
|
assert length(checks) == 0
|
|
end
|
|
|
|
test "returns error when device not found" do
|
|
non_existent_id = Ecto.UUID.generate()
|
|
|
|
assert {:error, :device_not_found} = MonitorWorker.perform(non_existent_id)
|
|
end
|
|
|
|
test "broadcasts update after check", %{device: device} do
|
|
# Mock successful ping
|
|
expect(PingMock, :ping, fn _ip, _timeout ->
|
|
{:ok, 10.5}
|
|
end)
|
|
|
|
# Subscribe to device topic
|
|
Phoenix.PubSub.subscribe(Towerops.PubSub, "device:#{device.id}")
|
|
|
|
MonitorWorker.perform(device.id)
|
|
|
|
# Verify broadcast was sent
|
|
assert_receive {:monitoring_check_updated, device_id}, 1000
|
|
assert device_id == device.id
|
|
end
|
|
|
|
test "creates failed check for unreachable host" do
|
|
user = user_fixture()
|
|
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)
|
|
|
|
{:ok, site} =
|
|
Towerops.Sites.create_site(%{
|
|
name: "Test Site",
|
|
organization_id: organization.id
|
|
})
|
|
|
|
{:ok, device} =
|
|
Towerops.Devices.create_device(%{
|
|
name: "Unreachable Device",
|
|
ip_address: "192.0.2.1",
|
|
monitoring_enabled: true,
|
|
site_id: site.id
|
|
})
|
|
|
|
# Mock failed ping
|
|
expect(PingMock, :ping, fn _ip, _timeout ->
|
|
{:error, :timeout}
|
|
end)
|
|
|
|
assert :ok = MonitorWorker.perform(device.id)
|
|
|
|
# Verify check was created as failure
|
|
checks = Monitoring.list_devices_checks(device.id, 10)
|
|
assert length(checks) == 1
|
|
|
|
check = hd(checks)
|
|
assert check.status == :failure
|
|
assert check.response_time_ms == nil
|
|
end
|
|
|
|
test "successfully completes monitoring check", %{device: device} do
|
|
# Mock successful ping
|
|
expect(PingMock, :ping, fn _ip, _timeout ->
|
|
{:ok, 15.0}
|
|
end)
|
|
|
|
assert :ok = MonitorWorker.perform(device.id)
|
|
|
|
# Verify a successful check was created
|
|
checks = Monitoring.list_devices_checks(device.id, 10)
|
|
assert length(checks) >= 1
|
|
|
|
check = hd(checks)
|
|
assert check.device_id == device.id
|
|
assert check.status == :success
|
|
assert check.checked_at
|
|
assert check.response_time_ms == 15.0
|
|
end
|
|
|
|
test "correctly skips monitoring when disabled", %{device: device} do
|
|
{:ok, device} = Towerops.Devices.update_device(device, %{monitoring_enabled: false})
|
|
|
|
assert :ok = MonitorWorker.perform(device.id)
|
|
|
|
# Verify no check was created
|
|
checks = Monitoring.list_devices_checks(device.id, 10)
|
|
assert length(checks) == 0
|
|
end
|
|
end
|
|
end
|