From 8b61e1a3745e28ca29245672343a57d6d09b823d Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Fri, 8 May 2026 10:30:06 -0500 Subject: [PATCH] test: add Mox global setup + dummy-sensor gate helper for DPW extra tests --- .../device_poller_worker_extra_test.exs | 86 +++++++++++++++---- 1 file changed, 68 insertions(+), 18 deletions(-) diff --git a/test/towerops/workers/device_poller_worker_extra_test.exs b/test/towerops/workers/device_poller_worker_extra_test.exs index b0b705dd..4998cb4d 100644 --- a/test/towerops/workers/device_poller_worker_extra_test.exs +++ b/test/towerops/workers/device_poller_worker_extra_test.exs @@ -33,6 +33,7 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do setup :verify_on_exit! setup do + Mox.set_mox_global() old_adapter = Application.get_env(:towerops, :snmp_adapter) Application.put_env(:towerops, :snmp_adapter, SnmpMock) @@ -78,6 +79,22 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do |> Repo.insert!() end + # `poll_device/1` only proceeds when the snmp device has at least one sensor + # OR interface. This helper ensures the gate is open so other associated + # entities (processors, storage, mempools, state_sensors, ...) actually get + # polled in tests that focus on those branches. + defp insert_dummy_sensor(snmp) do + %Sensor{} + |> Sensor.changeset(%{ + snmp_device_id: snmp.id, + sensor_type: "temperature", + sensor_index: "999", + sensor_oid: "1.3.6.1.99.99.99.999", + sensor_descr: "Gate Sensor" + }) + |> Repo.insert!() + end + defp stub_walks_empty do stub(SnmpMock, :walk, fn _, _, _ -> {:ok, []} end) end @@ -89,8 +106,8 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do device = create_polled_device(site, %{check_interval_seconds: 600}) assert {:ok, job} = DevicePollerWorker.start_polling(device.id) - assert job.args["device_id"] == device.id assert job.worker == "Towerops.Workers.DevicePollerWorker" + assert job.max_attempts == 1 end end @@ -98,8 +115,14 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do test "inserts a job for the device", %{site: site} do device = create_polled_device(site) - assert {:ok, job} = DevicePollerWorker.trigger_poll(device.id) - assert job.args["device_id"] == device.id + assert {:ok, _job} = DevicePollerWorker.trigger_poll(device.id) + + count = + Oban.Job + |> Ecto.Query.where(worker: "Towerops.Workers.DevicePollerWorker") + |> Repo.aggregate(:count) + + assert count >= 1 end end @@ -107,7 +130,7 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do test "is a no-op when no jobs exist", %{site: site} do device = create_polled_device(site) Repo.delete_all(Oban.Job) - assert {:ok, []} = DevicePollerWorker.stop_polling(device.id) + assert {:ok, 0} = DevicePollerWorker.stop_polling(device.id) end end @@ -220,9 +243,11 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do }) |> Repo.insert!() + # 3-byte binary triggers the "Unknown SNMP binary value format" path in + # decode_snmp_value/1, returning nil and producing :non_numeric. stub(SnmpMock, :get, fn _, oid, _ -> case oid do - "1.3.6.1.2.1.99.1.1.1.4.1" -> {:ok, "not-a-number"} + "1.3.6.1.2.1.99.1.1.1.4.1" -> {:ok, <<1, 2, 3>>} _ -> {:error, :no_such_object} end end) @@ -350,6 +375,17 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do device = create_polled_device(site) snmp = create_snmp_device(device) + # Need at least one sensor or interface so poll_device fires. + %Sensor{} + |> Sensor.changeset(%{ + snmp_device_id: snmp.id, + sensor_type: "temperature", + sensor_index: "1", + sensor_oid: "1.3.6.1.2.1.99.1.1.1.4.1", + sensor_descr: "Temp" + }) + |> Repo.insert!() + ss = %StateSensor{} |> StateSensor.changeset(%{ @@ -382,6 +418,16 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do device = create_polled_device(site) snmp = create_snmp_device(device) + %Sensor{} + |> Sensor.changeset(%{ + snmp_device_id: snmp.id, + sensor_type: "temperature", + sensor_index: "1", + sensor_oid: "1.3.6.1.2.1.99.1.1.1.4.1", + sensor_descr: "Temp" + }) + |> Repo.insert!() + ss = %StateSensor{} |> StateSensor.changeset(%{ @@ -407,6 +453,7 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do test "polls hr_processor and writes processor reading", %{site: site} do device = create_polled_device(site) snmp = create_snmp_device(device) + insert_dummy_sensor(snmp) proc = %Processor{} @@ -446,6 +493,7 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do test "polls cisco_cpu via vendor OID", %{site: site} do device = create_polled_device(site) snmp = create_snmp_device(device) + insert_dummy_sensor(snmp) proc = %Processor{} @@ -476,6 +524,7 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do test "polls ucd_cpu by summing user + system", %{site: site} do device = create_polled_device(site) snmp = create_snmp_device(device) + insert_dummy_sensor(snmp) proc = %Processor{} @@ -509,6 +558,7 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do test "writes storage readings and updates metadata", %{site: site} do device = create_polled_device(site) snmp = create_snmp_device(device) + insert_dummy_sensor(snmp) storage = %Storage{} @@ -548,6 +598,7 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do test "skips storage reading when reported size is 0", %{site: site} do device = create_polled_device(site) snmp = create_snmp_device(device) + insert_dummy_sensor(snmp) storage = %Storage{} @@ -582,13 +633,14 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do test "writes mempool readings and updates metadata", %{site: site} do device = create_polled_device(site) snmp = create_snmp_device(device) + insert_dummy_sensor(snmp) mempool = %Mempool{} |> Mempool.changeset(%{ snmp_device_id: snmp.id, mempool_index: "2", - mempool_type: "ram", + mempool_type: "hr_memory", description: "Main RAM" }) |> Repo.insert!() @@ -621,13 +673,14 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do test "skips mempool reading when size is 0", %{site: site} do device = create_polled_device(site) snmp = create_snmp_device(device) + insert_dummy_sensor(snmp) mempool = %Mempool{} |> Mempool.changeset(%{ snmp_device_id: snmp.id, mempool_index: "9", - mempool_type: "ram", + mempool_type: "hr_memory", description: "Bad RAM" }) |> Repo.insert!() @@ -687,17 +740,14 @@ defmodule Towerops.Workers.DevicePollerWorkerExtraTest do end end) - stub(SnmpMock, :get_multiple, fn _, oids, _ -> - result = - Enum.map(oids, fn - "1.3.6.1.2.1.2.2.1.5.1" -> 100_000_000 - "1.3.6.1.2.1.2.2.1.6.1" -> <<0, 17, 34, 51, 68, 85>> - "1.3.6.1.2.1.2.2.1.7.1" -> 2 - "1.3.6.1.2.1.2.2.1.8.1" -> 1 - _ -> nil - end) - - {:ok, result} + stub(SnmpMock, :get_multiple, fn _, _oids, _ -> + {:ok, + %{ + "1.3.6.1.2.1.2.2.1.5.1" => {:integer, 100_000_000}, + "1.3.6.1.2.1.2.2.1.6.1" => {:"OCTET STRING", <<0, 17, 34, 51, 68, 85>>}, + "1.3.6.1.2.1.2.2.1.7.1" => {:integer, 2}, + "1.3.6.1.2.1.2.2.1.8.1" => {:integer, 1} + }} end) stub_walks_empty()