244 lines
6.6 KiB
Elixir
244 lines
6.6 KiB
Elixir
defmodule Towerops.Snmp.EntityPhysicalReadingTest do
|
|
use Towerops.DataCase, async: true
|
|
|
|
import Towerops.SnmpFixtures
|
|
|
|
alias Towerops.Repo
|
|
alias Towerops.Snmp.EntityPhysical
|
|
alias Towerops.Snmp.EntityPhysicalReading
|
|
|
|
describe "changeset/2" do
|
|
test "validates required fields" do
|
|
changeset = EntityPhysicalReading.changeset(%EntityPhysicalReading{}, %{})
|
|
|
|
refute changeset.valid?
|
|
assert "can't be blank" in errors_on(changeset).entity_physical_id
|
|
assert "can't be blank" in errors_on(changeset).measured_at
|
|
end
|
|
|
|
test "accepts valid attributes" do
|
|
snmp_device = snmp_device_fixture()
|
|
|
|
{:ok, entity} =
|
|
%EntityPhysical{}
|
|
|> EntityPhysical.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
entity_index: "1",
|
|
entity_class: "powerSupply",
|
|
name: "PS1"
|
|
})
|
|
|> Repo.insert()
|
|
|
|
attrs = %{
|
|
entity_physical_id: entity.id,
|
|
operational_status: "up",
|
|
admin_status: "unlocked",
|
|
measured_at: DateTime.utc_now()
|
|
}
|
|
|
|
changeset = EntityPhysicalReading.changeset(%EntityPhysicalReading{}, attrs)
|
|
assert changeset.valid?
|
|
end
|
|
|
|
test "validates operational_status is a known value" do
|
|
snmp_device = snmp_device_fixture()
|
|
|
|
{:ok, entity} =
|
|
%EntityPhysical{}
|
|
|> EntityPhysical.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
entity_index: "1",
|
|
entity_class: "fan",
|
|
name: "Fan1"
|
|
})
|
|
|> Repo.insert()
|
|
|
|
# Valid statuses: up, down, testing, unknown, dormant, notPresent, lowerLayerDown
|
|
valid_statuses = [
|
|
"up",
|
|
"down",
|
|
"testing",
|
|
"unknown",
|
|
"dormant",
|
|
"notPresent",
|
|
"lowerLayerDown"
|
|
]
|
|
|
|
for status <- valid_statuses do
|
|
changeset =
|
|
EntityPhysicalReading.changeset(%EntityPhysicalReading{}, %{
|
|
entity_physical_id: entity.id,
|
|
operational_status: status,
|
|
measured_at: DateTime.utc_now()
|
|
})
|
|
|
|
assert changeset.valid?, "Status #{status} should be valid"
|
|
end
|
|
end
|
|
|
|
test "validates admin_status is a known value" do
|
|
snmp_device = snmp_device_fixture()
|
|
|
|
{:ok, entity} =
|
|
%EntityPhysical{}
|
|
|> EntityPhysical.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
entity_index: "1",
|
|
entity_class: "module",
|
|
name: "Module1"
|
|
})
|
|
|> Repo.insert()
|
|
|
|
# Valid statuses: locked, unlocked, shuttingDown, unknown
|
|
valid_statuses = ["locked", "unlocked", "shuttingDown", "unknown"]
|
|
|
|
for status <- valid_statuses do
|
|
changeset =
|
|
EntityPhysicalReading.changeset(%EntityPhysicalReading{}, %{
|
|
entity_physical_id: entity.id,
|
|
admin_status: status,
|
|
measured_at: DateTime.utc_now()
|
|
})
|
|
|
|
assert changeset.valid?, "Status #{status} should be valid"
|
|
end
|
|
end
|
|
|
|
test "allows nil for optional status fields" do
|
|
snmp_device = snmp_device_fixture()
|
|
|
|
{:ok, entity} =
|
|
%EntityPhysical{}
|
|
|> EntityPhysical.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
entity_index: "1",
|
|
entity_class: "chassis",
|
|
name: "Chassis1"
|
|
})
|
|
|> Repo.insert()
|
|
|
|
attrs = %{
|
|
entity_physical_id: entity.id,
|
|
measured_at: DateTime.utc_now()
|
|
}
|
|
|
|
changeset = EntityPhysicalReading.changeset(%EntityPhysicalReading{}, attrs)
|
|
assert changeset.valid?
|
|
end
|
|
|
|
test "casts measured_at to DateTime" do
|
|
snmp_device = snmp_device_fixture()
|
|
|
|
{:ok, entity} =
|
|
%EntityPhysical{}
|
|
|> EntityPhysical.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
entity_index: "1",
|
|
entity_class: "sensor",
|
|
name: "Temp1"
|
|
})
|
|
|> Repo.insert()
|
|
|
|
now = Towerops.Time.now()
|
|
|
|
attrs = %{
|
|
entity_physical_id: entity.id,
|
|
operational_status: "up",
|
|
measured_at: now
|
|
}
|
|
|
|
changeset = EntityPhysicalReading.changeset(%EntityPhysicalReading{}, attrs)
|
|
assert changeset.valid?
|
|
assert Ecto.Changeset.get_field(changeset, :measured_at) == now
|
|
end
|
|
end
|
|
|
|
describe "database constraints" do
|
|
test "requires entity_physical_id foreign key to exist" do
|
|
attrs = %{
|
|
entity_physical_id: Ecto.UUID.generate(),
|
|
operational_status: "up",
|
|
measured_at: DateTime.utc_now()
|
|
}
|
|
|
|
assert {:error, changeset} =
|
|
%EntityPhysicalReading{}
|
|
|> EntityPhysicalReading.changeset(attrs)
|
|
|> Repo.insert()
|
|
|
|
assert "does not exist" in errors_on(changeset).entity_physical_id
|
|
end
|
|
|
|
test "cascades delete when entity_physical is deleted" do
|
|
snmp_device = snmp_device_fixture()
|
|
|
|
{:ok, entity} =
|
|
%EntityPhysical{}
|
|
|> EntityPhysical.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
entity_index: "1",
|
|
entity_class: "powerSupply",
|
|
name: "PS1"
|
|
})
|
|
|> Repo.insert()
|
|
|
|
{:ok, reading} =
|
|
%EntityPhysicalReading{}
|
|
|> EntityPhysicalReading.changeset(%{
|
|
entity_physical_id: entity.id,
|
|
operational_status: "up",
|
|
measured_at: DateTime.utc_now()
|
|
})
|
|
|> Repo.insert()
|
|
|
|
# Delete entity
|
|
Repo.delete!(entity)
|
|
|
|
# Reading should be deleted
|
|
assert is_nil(Repo.get(EntityPhysicalReading, reading.id))
|
|
end
|
|
end
|
|
|
|
describe "querying" do
|
|
test "can query readings by entity_physical_id" do
|
|
snmp_device = snmp_device_fixture()
|
|
|
|
{:ok, entity} =
|
|
%EntityPhysical{}
|
|
|> EntityPhysical.changeset(%{
|
|
snmp_device_id: snmp_device.id,
|
|
entity_index: "1",
|
|
entity_class: "fan",
|
|
name: "Fan1"
|
|
})
|
|
|> Repo.insert()
|
|
|
|
{:ok, _reading1} =
|
|
%EntityPhysicalReading{}
|
|
|> EntityPhysicalReading.changeset(%{
|
|
entity_physical_id: entity.id,
|
|
operational_status: "up",
|
|
measured_at: DateTime.add(DateTime.utc_now(), -3600, :second)
|
|
})
|
|
|> Repo.insert()
|
|
|
|
{:ok, reading2} =
|
|
%EntityPhysicalReading{}
|
|
|> EntityPhysicalReading.changeset(%{
|
|
entity_physical_id: entity.id,
|
|
operational_status: "down",
|
|
measured_at: DateTime.utc_now()
|
|
})
|
|
|> Repo.insert()
|
|
|
|
readings =
|
|
EntityPhysicalReading
|
|
|> where([r], r.entity_physical_id == ^entity.id)
|
|
|> order_by([r], desc: r.measured_at)
|
|
|> Repo.all()
|
|
|
|
assert length(readings) == 2
|
|
assert hd(readings).id == reading2.id
|
|
end
|
|
end
|
|
end
|