towerops/test/mix/tasks/gen_vendor_tests_test.exs
2026-02-03 10:19:56 -06:00

335 lines
10 KiB
Elixir

defmodule Mix.Tasks.GenVendorTestsTest do
use ExUnit.Case, async: false
import ExUnit.CaptureIO
alias Mix.Tasks.GenVendorTests
@moduletag :mix_task
setup do
# Save original directory
original_dir = File.cwd!()
# Create temporary directories for vendor modules and tests
temp_dir = Path.join(System.tmp_dir!(), "vendor_tests_#{System.unique_integer([:positive])}")
vendors_dir = Path.join(temp_dir, "lib/towerops/snmp/profiles/vendors")
tests_dir = Path.join(temp_dir, "test/towerops/snmp/profiles/vendors")
File.mkdir_p!(vendors_dir)
File.mkdir_p!(tests_dir)
on_exit(fn ->
File.cd!(original_dir)
File.rm_rf!(temp_dir)
end)
{:ok, temp_dir: temp_dir, vendors_dir: vendors_dir, tests_dir: tests_dir}
end
describe "run/1 with dry-run" do
test "reports vendors without tests in dry-run mode", %{
vendors_dir: vendors_dir,
tests_dir: _tests_dir,
temp_dir: temp_dir
} do
# Create vendor module
File.write!(Path.join(vendors_dir, "mikrotik.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.Mikrotik do
@behaviour Towerops.Snmp.Profiles.Vendors.Vendor
@impl true
def profile_names, do: ["mikrotik"]
end
""")
# Change to temp directory to run task
File.cd!(temp_dir, fn ->
output =
capture_io(fn ->
GenVendorTests.run(["--dry-run"])
end)
assert output =~ "Found 1 vendor modules"
assert output =~ "Found 0 existing tests"
assert output =~ "1 vendors need tests"
assert output =~ "Would generate: test/towerops/snmp/profiles/vendors/mikrotik_test.exs"
end)
end
test "reports no work needed when all vendors have tests", %{
vendors_dir: vendors_dir,
tests_dir: tests_dir,
temp_dir: temp_dir
} do
# Create vendor module
File.write!(Path.join(vendors_dir, "mikrotik.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.Mikrotik do
def profile_names, do: ["mikrotik"]
end
""")
# Create corresponding test
File.write!(Path.join(tests_dir, "mikrotik_test.exs"), """
defmodule Towerops.Snmp.Profiles.Vendors.MikrotikTest do
use ExUnit.Case
end
""")
File.cd!(temp_dir, fn ->
output =
capture_io(fn ->
GenVendorTests.run(["--dry-run"])
end)
assert output =~ "All vendor modules have tests!"
end)
end
end
describe "run/1 without dry-run" do
test "generates test file for vendor without test", %{
vendors_dir: vendors_dir,
tests_dir: tests_dir,
temp_dir: temp_dir
} do
# Create vendor module with profile_names
File.write!(Path.join(vendors_dir, "cisco.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.Cisco do
@behaviour Towerops.Snmp.Profiles.Vendors.Vendor
@impl true
def profile_names, do: ["cisco-ios", "cisco-nxos"]
end
""")
File.cd!(temp_dir, fn ->
output =
capture_io(fn ->
GenVendorTests.run([])
end)
assert output =~ "Generated: test/towerops/snmp/profiles/vendors/cisco_test.exs"
assert output =~ "Generated 1 test files"
# Verify test file was created
test_file = Path.join(tests_dir, "cisco_test.exs")
assert File.exists?(test_file)
content = File.read!(test_file)
assert content =~ "defmodule Towerops.Snmp.Profiles.Vendors.CiscoTest do"
assert content =~ "use Towerops.DataCase, async: true"
assert content =~ "alias Towerops.Snmp.Profiles.Vendors.Cisco"
assert content =~ ~s{profile_names() == ["cisco-ios", "cisco-nxos"]}
assert content =~ "describe \"profile_names/0\" do"
assert content =~ "describe \"detect_hardware/1\" do"
assert content =~ "describe \"wireless_oid_defs/0\" do"
assert content =~ "describe \"discover_wireless_sensors/1\" do"
end)
end
test "generates tests for multiple vendors", %{vendors_dir: vendors_dir, tests_dir: tests_dir, temp_dir: temp_dir} do
# Create multiple vendor modules
File.write!(Path.join(vendors_dir, "mikrotik.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.Mikrotik do
def profile_names, do: ["mikrotik"]
end
""")
File.write!(Path.join(vendors_dir, "ubiquiti.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.Ubiquiti do
def profile_names, do: ["ubnt"]
end
""")
File.write!(Path.join(vendors_dir, "cisco.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.Cisco do
def profile_names, do: ["cisco"]
end
""")
File.cd!(temp_dir, fn ->
output =
capture_io(fn ->
GenVendorTests.run([])
end)
assert output =~ "Generated 3 test files"
assert File.exists?(Path.join(tests_dir, "mikrotik_test.exs"))
assert File.exists?(Path.join(tests_dir, "ubiquiti_test.exs"))
assert File.exists?(Path.join(tests_dir, "cisco_test.exs"))
end)
end
test "skips vendors that already have tests", %{vendors_dir: vendors_dir, tests_dir: tests_dir, temp_dir: temp_dir} do
# Create vendor modules
File.write!(Path.join(vendors_dir, "mikrotik.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.Mikrotik do
def profile_names, do: ["mikrotik"]
end
""")
File.write!(Path.join(vendors_dir, "cisco.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.Cisco do
def profile_names, do: ["cisco"]
end
""")
# Create test for mikrotik (but not cisco)
File.write!(Path.join(tests_dir, "mikrotik_test.exs"), """
defmodule Towerops.Snmp.Profiles.Vendors.MikrotikTest do
use ExUnit.Case
end
""")
File.cd!(temp_dir, fn ->
output =
capture_io(fn ->
GenVendorTests.run([])
end)
assert output =~ "Found 2 vendor modules"
assert output =~ "Found 1 existing tests"
assert output =~ "1 vendors need tests"
assert output =~ "Generated 1 test files"
# Only cisco test should be generated
assert File.exists?(Path.join(tests_dir, "cisco_test.exs"))
# Mikrotik test should be the old one (not regenerated)
mikrotik_test = File.read!(Path.join(tests_dir, "mikrotik_test.exs"))
assert mikrotik_test =~ "use ExUnit.Case"
refute mikrotik_test =~ "use Towerops.DataCase"
end)
end
test "excludes registry and vendor files from generation", %{
vendors_dir: vendors_dir,
tests_dir: tests_dir,
temp_dir: temp_dir
} do
# Create vendor modules
File.write!(Path.join(vendors_dir, "registry.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.Registry do
end
""")
File.write!(Path.join(vendors_dir, "vendor.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.Vendor do
end
""")
File.write!(Path.join(vendors_dir, "mikrotik.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.Mikrotik do
def profile_names, do: ["mikrotik"]
end
""")
File.cd!(temp_dir, fn ->
output =
capture_io(fn ->
GenVendorTests.run([])
end)
# Should only count mikrotik as vendor module
assert output =~ "Found 1 vendor modules"
assert output =~ "Generated 1 test files"
# Only mikrotik test should be generated
assert File.exists?(Path.join(tests_dir, "mikrotik_test.exs"))
refute File.exists?(Path.join(tests_dir, "registry_test.exs"))
refute File.exists?(Path.join(tests_dir, "vendor_test.exs"))
end)
end
test "handles vendor module without profile_names function", %{
vendors_dir: vendors_dir,
tests_dir: tests_dir,
temp_dir: temp_dir
} do
# Create vendor module without profile_names
File.write!(Path.join(vendors_dir, "custom.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.Custom do
# No profile_names function
end
""")
File.cd!(temp_dir, fn ->
output =
capture_io(fn ->
GenVendorTests.run([])
end)
assert output =~ "Generated 1 test files"
# Test should be generated with empty profile list
test_file = Path.join(tests_dir, "custom_test.exs")
assert File.exists?(test_file)
content = File.read!(test_file)
assert content =~ "assert Custom.profile_names() == []"
end)
end
test "generates proper module name for snake_case files", %{
vendors_dir: vendors_dir,
tests_dir: tests_dir,
temp_dir: temp_dir
} do
# Create vendor module with snake_case filename
File.write!(Path.join(vendors_dir, "palo_alto.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.PaloAlto do
def profile_names, do: ["panos"]
end
""")
File.cd!(temp_dir, fn ->
_output =
capture_io(fn ->
GenVendorTests.run([])
end)
# Test file should be palo_alto_test.exs
test_file = Path.join(tests_dir, "palo_alto_test.exs")
assert File.exists?(test_file)
# Module should be PaloAltoTest
content = File.read!(test_file)
assert content =~ "defmodule Towerops.Snmp.Profiles.Vendors.PaloAltoTest do"
assert content =~ "alias Towerops.Snmp.Profiles.Vendors.PaloAlto"
end)
end
test "generates tests with proper expect counts for wireless_oid_defs", %{
vendors_dir: vendors_dir,
tests_dir: tests_dir,
temp_dir: temp_dir
} do
# Create vendor module with multiple OID defs
File.write!(Path.join(vendors_dir, "test_vendor.ex"), """
defmodule Towerops.Snmp.Profiles.Vendors.TestVendor do
def profile_names, do: ["test"]
def wireless_oid_defs do
[
%{oid: "1.2.3.4.0", sensor_descr: "Temp", sensor_type: "temperature", sensor_unit: "C", sensor_divisor: 1},
%{oid: "1.2.3.5.0", sensor_descr: "Voltage", sensor_type: "voltage", sensor_unit: "V", sensor_divisor: 1},
%{oid: "1.2.3.6.0", sensor_descr: "Power", sensor_type: "power", sensor_unit: "W", sensor_divisor: 1}
]
end
end
""")
File.cd!(temp_dir, fn ->
capture_io(fn ->
GenVendorTests.run([])
end)
test_file = Path.join(tests_dir, "test_vendor_test.exs")
content = File.read!(test_file)
# Should verify list has >= 1 items (not hardcoded count)
assert content =~ "assert length(defs) >= 1"
end)
end
end
end