# Configure MIB directories BEFORE any NIF loading # This must happen before ExUnit.start() to ensure ToweropsNative NIF # can find vendor MIBs when it initializes mib_dir = Application.app_dir(:towerops, "priv/mibs") if File.dir?(mib_dir) do # Get main directory plus all subdirectories for vendor MIBs subdirs = mib_dir |> File.ls!() |> Enum.map(&Path.join(mib_dir, &1)) |> Enum.filter(&File.dir?/1) mib_dirs = [mib_dir | subdirs] mibdirs_env = Enum.join(mib_dirs, ":") # Set environment variables BEFORE initializing the NIF System.put_env("MIBDIRS", mibdirs_env) System.put_env("MIBS", "ALL") # Add each directory to net-snmp's search path (NIF may not be loaded) try do Enum.each(mib_dirs, fn dir -> case ToweropsNative.load_mib_directory(dir) do :ok -> :ok # Ignore errors in test environment {:error, _reason} -> :ok end end) # Explicitly initialize the MIB library with correct environment variables case ToweropsNative.init_mib_library() do result when result in ["initialized", "already_initialized"] -> IO.puts("Test MIB library initialized: #{result}") other -> IO.puts("Warning: Unexpected MIB library init result: #{inspect(other)}") end rescue _e in ErlangError -> IO.puts("ToweropsNative NIF not available — MIB resolution disabled in tests") end end # Load antenna pattern registry for tests that exercise the Coverages # context (the schema validates antenna_slug against this in-memory registry). Towerops.Coverages.Antenna.load_registry() ExUnit.start() # Skip the coverage-compute integration test when the GDAL CLI tools # aren't installed (e.g. CI test gate runs in a lean image without # gdal-bin). Locally we install GDAL via `brew install gdal` per # CLAUDE.md, so the test runs there. extra_excludes = if System.find_executable("gdal_translate") && System.find_executable("gdaldem") do [] else [:requires_gdal] end # Exclude tests by default # Run specific tests with: mix test --only ExUnit.configure( exclude: [ :integration, # Tests making real network calls (ping, DNS, SSL) :network, # SnmpKit-specific exclusions :performance, :snmpv3, :memory, :shell_integration, :optional, :needs_simulator, :manual, :real_device, :yecc_required ] ++ extra_excludes ) # Define mocks for testing Mox.defmock(Towerops.Monitoring.PingMock, for: Towerops.Monitoring.PingBehaviour) Mox.defmock(Towerops.Snmp.PollerMock, for: Towerops.Snmp.PollerBehaviour) Mox.defmock(Towerops.Snmp.SnmpMock, for: Towerops.Snmp.SnmpBehaviour) Mox.defmock(Towerops.RateLimit.RedisClientMock, for: Towerops.RateLimit.RedisClient) # Tests assert on the bare ":no_tile" return path of the LIDAR catalog # without needing to mock the synthetic USGS NED runner. Real prod use # enables this fallback for nationwide CONUS coverage. Application.put_env(:towerops, :lidar_ned_fallback, false) # Same idea for the LANDFIRE tree-canopy COG: tests disable it so the # worker doesn't try to stream LANDFIRE bytes during compute. Tests # that exercise the canopy code path opt back in explicitly. Application.put_env(:towerops, :tree_canopy_enabled, false) # Define stub module for SNMP mock (returns errors for all calls) defmodule Towerops.Snmp.SnmpMockStub do @moduledoc false @behaviour Towerops.Snmp.SnmpBehaviour def get(_target, _oid, _opts), do: {:error, :timeout} def get_next(_target, _oid, _opts), do: {:error, :timeout} def walk(_target, _oid, _opts), do: {:error, :timeout} def get_bulk(_target, _oid, _opts), do: {:error, :timeout} def get_multiple(_target, _oids, _opts), do: {:error, :timeout} end Ecto.Adapters.SQL.Sandbox.mode(Towerops.Repo, :manual)