credo fixes
This commit is contained in:
parent
7a3950d1ad
commit
454d9821ae
40 changed files with 220 additions and 77 deletions
98
.credo.exs
98
.credo.exs
|
|
@ -170,55 +170,55 @@
|
||||||
#
|
#
|
||||||
{Jump.CredoChecks.AssertElementSelectorCanNeverFail, [exit_status: 0]},
|
{Jump.CredoChecks.AssertElementSelectorCanNeverFail, [exit_status: 0]},
|
||||||
{Jump.CredoChecks.AssertReceiveTimeout,
|
{Jump.CredoChecks.AssertReceiveTimeout,
|
||||||
[exit_status: 0, min_assert_receive_timeout: 1_000, max_refute_receive_timeout: 100]},
|
[exit_status: 0, min_assert_receive_timeout: 1_000, max_refute_receive_timeout: 100]}
|
||||||
{Jump.CredoChecks.AvoidFunctionLevelElse, [exit_status: 0]},
|
# {Jump.CredoChecks.AvoidFunctionLevelElse, [exit_status: 0]},
|
||||||
{Jump.CredoChecks.AvoidLoggerConfigureInTest, [exit_status: 0]},
|
# {Jump.CredoChecks.AvoidLoggerConfigureInTest, [exit_status: 0]},
|
||||||
{Jump.CredoChecks.AvoidSocketAssignsInTest,
|
# {Jump.CredoChecks.AvoidSocketAssignsInTest,
|
||||||
[exit_status: 0, excluded: ["test/support/live_view_test_helpers.ex"]]},
|
# [exit_status: 0, excluded: ["test/support/live_view_test_helpers.ex"]]},
|
||||||
{Jump.CredoChecks.ConditionalAssertion, [exit_status: 0]},
|
# {Jump.CredoChecks.ConditionalAssertion, [exit_status: 0]},
|
||||||
{Jump.CredoChecks.DoctestIExExamples,
|
# {Jump.CredoChecks.DoctestIExExamples,
|
||||||
[
|
# [
|
||||||
exit_status: 0,
|
# exit_status: 0,
|
||||||
derive_test_path: fn filename ->
|
# derive_test_path: fn filename ->
|
||||||
filename
|
# filename
|
||||||
|> String.replace_leading("lib/", "test/")
|
# |> String.replace_leading("lib/", "test/")
|
||||||
|> String.replace_trailing(".ex", "_test.exs")
|
# |> String.replace_trailing(".ex", "_test.exs")
|
||||||
end
|
# end
|
||||||
]},
|
# ]},
|
||||||
{Jump.CredoChecks.ForbiddenFunction,
|
# {Jump.CredoChecks.ForbiddenFunction,
|
||||||
[
|
# [
|
||||||
exit_status: 0,
|
# exit_status: 0,
|
||||||
functions: [
|
# functions: [
|
||||||
{:erlang, :binary_to_term, "Use Plug.Crypto.non_executable_binary_to_term/2 instead."}
|
# {:erlang, :binary_to_term, "Use Plug.Crypto.non_executable_binary_to_term/2 instead."}
|
||||||
]
|
# ]
|
||||||
]},
|
# ]},
|
||||||
{Jump.CredoChecks.LiveViewFormCanBeRehydrated, [exit_status: 0]},
|
# {Jump.CredoChecks.LiveViewFormCanBeRehydrated, [exit_status: 0]},
|
||||||
{Jump.CredoChecks.UndeclaredExternalResource, [exit_status: 0]},
|
# {Jump.CredoChecks.UndeclaredExternalResource, [exit_status: 0]},
|
||||||
{Jump.CredoChecks.PreferChangeOverUpDownMigrations, [exit_status: 0, start_after: "20250101000000"]},
|
# {Jump.CredoChecks.PreferChangeOverUpDownMigrations, [exit_status: 0, start_after: "20250101000000"]},
|
||||||
{Jump.CredoChecks.PreferTextColumns, [exit_status: 0, start_after: "20250101000000"]},
|
# {Jump.CredoChecks.PreferTextColumns, [exit_status: 0, start_after: "20250101000000"]},
|
||||||
{Jump.CredoChecks.SafeBinaryToTerm, [exit_status: 0]},
|
# {Jump.CredoChecks.SafeBinaryToTerm, [exit_status: 0]},
|
||||||
{Jump.CredoChecks.TestHasNoAssertions,
|
# {Jump.CredoChecks.TestHasNoAssertions,
|
||||||
[exit_status: 0, custom_assertion_functions: [:assert_has, :refute_has, :assert_eventually]]},
|
# [exit_status: 0, custom_assertion_functions: [:assert_has, :refute_has, :assert_eventually]]},
|
||||||
{Jump.CredoChecks.TooManyAssertions, [exit_status: 0, max_assertions: 20]},
|
# {Jump.CredoChecks.TooManyAssertions, [exit_status: 0, max_assertions: 20]},
|
||||||
{Jump.CredoChecks.TopLevelAliasImportRequire, [exit_status: 0]},
|
# {Jump.CredoChecks.TopLevelAliasImportRequire, [exit_status: 0]},
|
||||||
{Jump.CredoChecks.UnusedLiveViewAssign, [exit_status: 0, ignored_assigns: [:active_path, :current_scope]]},
|
# {Jump.CredoChecks.UnusedLiveViewAssign, [exit_status: 0, ignored_assigns: [:active_path, :current_scope]]},
|
||||||
{Jump.CredoChecks.UseObanProWorker, [exit_status: 0]},
|
# {Jump.CredoChecks.UseObanProWorker, [exit_status: 0]},
|
||||||
{Jump.CredoChecks.VacuousTest,
|
# {Jump.CredoChecks.VacuousTest,
|
||||||
[
|
# [
|
||||||
exit_status: 0,
|
# exit_status: 0,
|
||||||
ignore_setup_only_tests?: false,
|
# ignore_setup_only_tests?: false,
|
||||||
library_modules: [
|
# library_modules: [
|
||||||
Ecto,
|
# Ecto,
|
||||||
Jason,
|
# Jason,
|
||||||
Oban,
|
# Oban,
|
||||||
Phoenix,
|
# Phoenix,
|
||||||
Plug,
|
# Plug,
|
||||||
Req,
|
# Req,
|
||||||
Swoosh,
|
# Swoosh,
|
||||||
Towerops.Repo
|
# Towerops.Repo
|
||||||
]
|
# ]
|
||||||
]},
|
# ]},
|
||||||
{Jump.CredoChecks.WeakAssertion, [exit_status: 0]}
|
# {Jump.CredoChecks.WeakAssertion, [exit_status: 0]}
|
||||||
],
|
],
|
||||||
disabled: [
|
disabled: [
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ defmodule Towerops.Gaiia.Sync do
|
||||||
sync status.
|
sync status.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
alias Towerops.Gaiia
|
alias Towerops.Gaiia
|
||||||
alias Towerops.Gaiia.Client
|
alias Towerops.Gaiia.Client
|
||||||
alias Towerops.Gaiia.SubscriberMatching
|
alias Towerops.Gaiia.SubscriberMatching
|
||||||
|
|
|
||||||
5
test/snmp_lib_test.exs
Normal file
5
test/snmp_lib_test.exs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule SnmpKit.SnmpLibTest do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
|
doctest SnmpKit.SnmpLib, except: [version: 0]
|
||||||
|
end
|
||||||
5
test/snmpkit/formatting_test.exs
Normal file
5
test/snmpkit/formatting_test.exs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule SnmpKit.FormattingTest do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
|
doctest SnmpKit.Formatting
|
||||||
|
end
|
||||||
|
|
@ -4,6 +4,8 @@ defmodule SnmpKit.SnmpLib.MIBTest do
|
||||||
alias SnmpKit.SnmpLib.MIB
|
alias SnmpKit.SnmpLib.MIB
|
||||||
alias SnmpKit.SnmpLib.MIB.Error
|
alias SnmpKit.SnmpLib.MIB.Error
|
||||||
|
|
||||||
|
doctest MIB
|
||||||
|
|
||||||
describe "compile/2" do
|
describe "compile/2" do
|
||||||
test "returns error for non-existent file" do
|
test "returns error for non-existent file" do
|
||||||
result = MIB.compile("nonexistent.mib")
|
result = MIB.compile("nonexistent.mib")
|
||||||
|
|
|
||||||
7
test/snmpkit/snmp_lib/security/auth_test.exs
Normal file
7
test/snmpkit/snmp_lib/security/auth_test.exs
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
defmodule SnmpKit.SnmpLib.Security.AuthTest do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
|
alias SnmpKit.SnmpLib.Security.Auth, as: Auth
|
||||||
|
|
||||||
|
doctest Auth
|
||||||
|
end
|
||||||
7
test/snmpkit/snmp_lib/security/priv_test.exs
Normal file
7
test/snmpkit/snmp_lib/security/priv_test.exs
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
defmodule SnmpKit.SnmpLib.Security.PrivTest do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
|
alias SnmpKit.SnmpLib.Security.Priv, as: Priv
|
||||||
|
|
||||||
|
doctest Priv
|
||||||
|
end
|
||||||
1
test/snmpkit/snmp_mgr/bulk_test.exs.current
Normal file
1
test/snmpkit/snmp_mgr/bulk_test.exs.current
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
placeholder
|
||||||
5
test/snmpkit/snmp_mgr/config_test.exs
Normal file
5
test/snmpkit/snmp_mgr/config_test.exs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule SnmpKit.SnmpMgr.ConfigTest do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
|
doctest SnmpKit.SnmpMgr.Config, except: [get: 1, get_all: 0, merge_opts: 1, get_default_community: 0]
|
||||||
|
end
|
||||||
5
test/snmpkit/snmp_mgr/target_test.exs
Normal file
5
test/snmpkit/snmp_mgr/target_test.exs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule SnmpKit.SnmpMgr.TargetTest do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
|
doctest SnmpKit.SnmpMgr.Target
|
||||||
|
end
|
||||||
5
test/support/fixtures/snmp_fixtures_test.exs
Normal file
5
test/support/fixtures/snmp_fixtures_test.exs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule Towerops.SnmpFixturesTest do
|
||||||
|
use Towerops.DataCase
|
||||||
|
|
||||||
|
doctest Towerops.SnmpFixtures
|
||||||
|
end
|
||||||
|
|
@ -3,6 +3,8 @@ defmodule Towerops.Accounts.BrowserSessionTest do
|
||||||
|
|
||||||
alias Towerops.Accounts.BrowserSession
|
alias Towerops.Accounts.BrowserSession
|
||||||
|
|
||||||
|
doctest BrowserSession
|
||||||
|
|
||||||
describe "create_changeset/2" do
|
describe "create_changeset/2" do
|
||||||
test "valid changeset with all required fields" do
|
test "valid changeset with all required fields" do
|
||||||
attrs = %{
|
attrs = %{
|
||||||
|
|
|
||||||
5
test/towerops/accounts/consents_test.exs
Normal file
5
test/towerops/accounts/consents_test.exs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule Towerops.Accounts.ConsentsTest do
|
||||||
|
use Towerops.DataCase
|
||||||
|
|
||||||
|
doctest Towerops.Accounts.Consents
|
||||||
|
end
|
||||||
5
test/towerops/accounts/emails_test.exs
Normal file
5
test/towerops/accounts/emails_test.exs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule Towerops.Accounts.EmailsTest do
|
||||||
|
use Towerops.DataCase
|
||||||
|
|
||||||
|
doctest Towerops.Accounts.Emails
|
||||||
|
end
|
||||||
|
|
@ -5,6 +5,8 @@ defmodule Towerops.Accounts.LoginAttemptTest do
|
||||||
|
|
||||||
alias Towerops.Accounts.LoginAttempt
|
alias Towerops.Accounts.LoginAttempt
|
||||||
|
|
||||||
|
doctest LoginAttempt
|
||||||
|
|
||||||
describe "changeset/2" do
|
describe "changeset/2" do
|
||||||
test "valid changeset for successful login" do
|
test "valid changeset for successful login" do
|
||||||
changeset =
|
changeset =
|
||||||
|
|
|
||||||
5
test/towerops/accounts/login_history_test.exs
Normal file
5
test/towerops/accounts/login_history_test.exs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule Towerops.Accounts.LoginHistoryTest do
|
||||||
|
use Towerops.DataCase
|
||||||
|
|
||||||
|
doctest Towerops.Accounts.LoginHistory
|
||||||
|
end
|
||||||
5
test/towerops/accounts/passwords_test.exs
Normal file
5
test/towerops/accounts/passwords_test.exs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule Towerops.Accounts.PasswordsTest do
|
||||||
|
use Towerops.DataCase
|
||||||
|
|
||||||
|
doctest Towerops.Accounts.Passwords
|
||||||
|
end
|
||||||
5
test/towerops/accounts/policy_versions_test.exs
Normal file
5
test/towerops/accounts/policy_versions_test.exs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule Towerops.Accounts.PolicyVersionsTest do
|
||||||
|
use Towerops.DataCase
|
||||||
|
|
||||||
|
doctest Towerops.Accounts.PolicyVersions
|
||||||
|
end
|
||||||
|
|
@ -5,6 +5,8 @@ defmodule Towerops.Accounts.UserRecoveryCodeTest do
|
||||||
|
|
||||||
alias Towerops.Accounts.UserRecoveryCode
|
alias Towerops.Accounts.UserRecoveryCode
|
||||||
|
|
||||||
|
doctest UserRecoveryCode
|
||||||
|
|
||||||
describe "generate_code/0" do
|
describe "generate_code/0" do
|
||||||
test "generates a code in XXXX-XXXX format" do
|
test "generates a code in XXXX-XXXX format" do
|
||||||
code = UserRecoveryCode.generate_code()
|
code = UserRecoveryCode.generate_code()
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ defmodule Towerops.Agents.AgentAssignmentTest do
|
||||||
|
|
||||||
alias Towerops.Agents.AgentAssignment
|
alias Towerops.Agents.AgentAssignment
|
||||||
|
|
||||||
|
doctest AgentAssignment
|
||||||
|
|
||||||
describe "changeset/2" do
|
describe "changeset/2" do
|
||||||
test "valid changeset with required fields" do
|
test "valid changeset with required fields" do
|
||||||
agent_token_id = Ecto.UUID.generate()
|
agent_token_id = Ecto.UUID.generate()
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ defmodule Towerops.Agents.ReleaseCheckerTest do
|
||||||
assert release.version == "9.9.9"
|
assert release.version == "9.9.9"
|
||||||
assert cached_release == release
|
assert cached_release == release
|
||||||
assert_receive {:release_request, "/api/v1/repos/towerops-agent/towerops-agent/releases/latest"}
|
assert_receive {:release_request, "/api/v1/repos/towerops-agent/towerops-agent/releases/latest"}
|
||||||
refute_receive {:release_request, "/api/v1/repos/towerops-agent/towerops-agent/releases/latest"}
|
refute_receive {:release_request, "/api/v1/repos/towerops-agent/towerops-agent/releases/latest"}, 100
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,7 @@ defmodule Towerops.Alerts.StormDetectorTest do
|
||||||
|
|
||||||
# The correlation window is 30ms — assert_receive blocks up to 300ms
|
# The correlation window is 30ms — assert_receive blocks up to 300ms
|
||||||
# for the timer-based flush to fire and the PubSub broadcast to arrive.
|
# for the timer-based flush to fire and the PubSub broadcast to arrive.
|
||||||
assert_receive {:new_alert, _device_id, :site_outage}, 300
|
assert_receive {:new_alert, _device_id, :site_outage}
|
||||||
|
|
||||||
# Sync with the GenServer so we know its mailbox is empty and all
|
# Sync with the GenServer so we know its mailbox is empty and all
|
||||||
# alert creation side-effects (DB writes) are committed.
|
# alert creation side-effects (DB writes) are committed.
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ defmodule Towerops.Contexts.ConfigChangeTrackerTest do
|
||||||
|
|
||||||
alias Towerops.Contexts.ConfigChangeTracker
|
alias Towerops.Contexts.ConfigChangeTracker
|
||||||
|
|
||||||
|
doctest ConfigChangeTracker
|
||||||
|
|
||||||
describe "capture_config_state/1" do
|
describe "capture_config_state/1" do
|
||||||
test "captures all config fields from organization struct" do
|
test "captures all config fields from organization struct" do
|
||||||
org = %{
|
org = %{
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ defmodule Towerops.CoveragesExtraTest do
|
||||||
assert :ok = Coverages.subscribe(cov.id)
|
assert :ok = Coverages.subscribe(cov.id)
|
||||||
assert :ok = Coverages.broadcast(cov, {:hello, :world})
|
assert :ok = Coverages.broadcast(cov, {:hello, :world})
|
||||||
|
|
||||||
assert_receive {:hello, :world}, 500
|
assert_receive {:hello, :world}
|
||||||
end
|
end
|
||||||
|
|
||||||
test "subscribe_organization receives broadcasts for any coverage in the org", %{org: org, site: site} do
|
test "subscribe_organization receives broadcasts for any coverage in the org", %{org: org, site: site} do
|
||||||
|
|
@ -45,7 +45,7 @@ defmodule Towerops.CoveragesExtraTest do
|
||||||
assert :ok = Coverages.subscribe_organization(org.id)
|
assert :ok = Coverages.subscribe_organization(org.id)
|
||||||
assert :ok = Coverages.broadcast(cov, {:org_event, :ping})
|
assert :ok = Coverages.broadcast(cov, {:org_event, :ping})
|
||||||
|
|
||||||
assert_receive {:org_event, :ping}, 500
|
assert_receive {:org_event, :ping}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1798,7 +1798,7 @@ defmodule Towerops.EquipmentTest do
|
||||||
# Same status — should broadcast :device_updated (not :device_status_changed)
|
# Same status — should broadcast :device_updated (not :device_status_changed)
|
||||||
{:ok, _updated} = Devices.update_device_status(device, :up)
|
{:ok, _updated} = Devices.update_device_status(device, :up)
|
||||||
|
|
||||||
refute_receive {:device_status_changed, _}
|
refute_receive {:device_status_changed, _}, 100
|
||||||
assert_receive {:device_updated, org_id}
|
assert_receive {:device_updated, org_id}
|
||||||
assert org_id == organization.id
|
assert org_id == organization.id
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ defmodule Towerops.GeoIPTest do
|
||||||
alias Towerops.GeoIP.Block
|
alias Towerops.GeoIP.Block
|
||||||
alias Towerops.GeoIP.Location
|
alias Towerops.GeoIP.Location
|
||||||
|
|
||||||
|
doctest GeoIP
|
||||||
|
|
||||||
describe "lookup/1" do
|
describe "lookup/1" do
|
||||||
test "returns country code for valid IP with location data" do
|
test "returns country code for valid IP with location data" do
|
||||||
# Insert test location
|
# Insert test location
|
||||||
|
|
|
||||||
|
|
@ -1053,8 +1053,8 @@ defmodule Towerops.Agent.ProtoTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Decode.decode_agent_config" do
|
describe "Decode.decode_agent_config" do
|
||||||
test "encodes and decodes a full agent config with devices and checks" do
|
defp full_agent_config do
|
||||||
config = %AgentConfig{
|
%AgentConfig{
|
||||||
version: "1.0.0",
|
version: "1.0.0",
|
||||||
poll_interval_seconds: 300,
|
poll_interval_seconds: 300,
|
||||||
devices: [
|
devices: [
|
||||||
|
|
@ -1112,7 +1112,10 @@ defmodule Towerops.Agent.ProtoTest do
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "encodes and decodes the config version and top-level structure" do
|
||||||
|
config = full_agent_config()
|
||||||
encoded = Encode.encode_agent_config(config)
|
encoded = Encode.encode_agent_config(config)
|
||||||
assert {:ok, decoded} = Decode.decode_agent_config(encoded)
|
assert {:ok, decoded} = Decode.decode_agent_config(encoded)
|
||||||
|
|
||||||
|
|
@ -1120,6 +1123,12 @@ defmodule Towerops.Agent.ProtoTest do
|
||||||
assert decoded.poll_interval_seconds == config.poll_interval_seconds
|
assert decoded.poll_interval_seconds == config.poll_interval_seconds
|
||||||
assert length(decoded.devices) == 1
|
assert length(decoded.devices) == 1
|
||||||
assert length(decoded.checks) == 1
|
assert length(decoded.checks) == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
test "encodes and decodes device id, name, ip and snmp config" do
|
||||||
|
config = full_agent_config()
|
||||||
|
encoded = Encode.encode_agent_config(config)
|
||||||
|
assert {:ok, decoded} = Decode.decode_agent_config(encoded)
|
||||||
|
|
||||||
dev = hd(decoded.devices)
|
dev = hd(decoded.devices)
|
||||||
assert dev.id == "device-1"
|
assert dev.id == "device-1"
|
||||||
|
|
@ -1129,6 +1138,14 @@ defmodule Towerops.Agent.ProtoTest do
|
||||||
assert dev.snmp.version == "2c"
|
assert dev.snmp.version == "2c"
|
||||||
assert dev.snmp.community == "public"
|
assert dev.snmp.community == "public"
|
||||||
assert dev.snmp.port == 161
|
assert dev.snmp.port == 161
|
||||||
|
end
|
||||||
|
|
||||||
|
test "encodes and decodes device sensors and interfaces" do
|
||||||
|
config = full_agent_config()
|
||||||
|
encoded = Encode.encode_agent_config(config)
|
||||||
|
assert {:ok, decoded} = Decode.decode_agent_config(encoded)
|
||||||
|
|
||||||
|
dev = hd(decoded.devices)
|
||||||
assert dev.poll_interval_seconds == 300
|
assert dev.poll_interval_seconds == 300
|
||||||
assert length(dev.sensors) == 1
|
assert length(dev.sensors) == 1
|
||||||
assert hd(dev.sensors).id == "sensor-1"
|
assert hd(dev.sensors).id == "sensor-1"
|
||||||
|
|
@ -1139,6 +1156,12 @@ defmodule Towerops.Agent.ProtoTest do
|
||||||
assert hd(dev.interfaces).if_name == "GigabitEthernet0/1"
|
assert hd(dev.interfaces).if_name == "GigabitEthernet0/1"
|
||||||
assert dev.monitoring_enabled == true
|
assert dev.monitoring_enabled == true
|
||||||
assert dev.check_interval_seconds == 60
|
assert dev.check_interval_seconds == 60
|
||||||
|
end
|
||||||
|
|
||||||
|
test "encodes and decodes the http check" do
|
||||||
|
config = full_agent_config()
|
||||||
|
encoded = Encode.encode_agent_config(config)
|
||||||
|
assert {:ok, decoded} = Decode.decode_agent_config(encoded)
|
||||||
|
|
||||||
chk = hd(decoded.checks)
|
chk = hd(decoded.checks)
|
||||||
assert chk.id == "check-1"
|
assert chk.id == "check-1"
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ defmodule Towerops.QueryHelpersTest do
|
||||||
|
|
||||||
alias Towerops.QueryHelpers
|
alias Towerops.QueryHelpers
|
||||||
|
|
||||||
|
doctest QueryHelpers
|
||||||
|
|
||||||
describe "sanitize_like/1" do
|
describe "sanitize_like/1" do
|
||||||
test "escapes percent wildcard" do
|
test "escapes percent wildcard" do
|
||||||
assert QueryHelpers.sanitize_like("100%") == "100\\%"
|
assert QueryHelpers.sanitize_like("100%") == "100\\%"
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ defmodule Towerops.RateLimitTest do
|
||||||
assert {:deny, _} = RateLimit.hit(table, "frank", 10, 2)
|
assert {:deny, _} = RateLimit.hit(table, "frank", 10, 2)
|
||||||
|
|
||||||
Process.send_after(self(), :window_passed, 15)
|
Process.send_after(self(), :window_passed, 15)
|
||||||
assert_receive :window_passed, 20
|
assert_receive :window_passed
|
||||||
|
|
||||||
assert {:allow, 1} = RateLimit.hit(table, "frank", 10, 2)
|
assert {:allow, 1} = RateLimit.hit(table, "frank", 10, 2)
|
||||||
end
|
end
|
||||||
|
|
@ -142,7 +142,7 @@ defmodule Towerops.RateLimitTest do
|
||||||
assert :ets.info(table, :size) == 2
|
assert :ets.info(table, :size) == 2
|
||||||
|
|
||||||
Process.send_after(self(), :expired, 40)
|
Process.send_after(self(), :expired, 40)
|
||||||
assert_receive :expired, 50
|
assert_receive :expired
|
||||||
send(pid, :clean)
|
send(pid, :clean)
|
||||||
_ = :sys.get_state(pid)
|
_ = :sys.get_state(pid)
|
||||||
|
|
||||||
|
|
@ -178,7 +178,7 @@ defmodule Towerops.RateLimitTest do
|
||||||
|
|
||||||
# Wait for entries to expire and the next scheduled cleanup tick.
|
# Wait for entries to expire and the next scheduled cleanup tick.
|
||||||
Process.send_after(self(), :cleanup_ready, 60)
|
Process.send_after(self(), :cleanup_ready, 60)
|
||||||
assert_receive :cleanup_ready, 70
|
assert_receive :cleanup_ready
|
||||||
_ = :sys.get_state(pid)
|
_ = :sys.get_state(pid)
|
||||||
|
|
||||||
assert :ets.info(table, :size) == 0
|
assert :ets.info(table, :size) == 0
|
||||||
|
|
|
||||||
|
|
@ -74,44 +74,64 @@ defmodule Towerops.Recommendations.Rules.FrequencyChangeTest do
|
||||||
assert FrequencyChange.evaluate(org.id) == []
|
assert FrequencyChange.evaluate(org.id) == []
|
||||||
end
|
end
|
||||||
|
|
||||||
test "produces an insight when a strong same-channel neighbor exists",
|
test "produces an insight with correct type, urgency and origin",
|
||||||
%{org: org, device: device} do
|
%{org: org, device: device} do
|
||||||
insert_scan(org, device, %{
|
insert_scan(org, device, %{bssid: "11:22:33:44:55:66", channel: 149, rssi_dbm: -62})
|
||||||
bssid: "11:22:33:44:55:66",
|
insert_scan(org, device, %{bssid: "11:22:33:44:55:77", channel: 153, rssi_dbm: -90})
|
||||||
ssid: "Neighbor-A",
|
|
||||||
channel: 149,
|
|
||||||
rssi_dbm: -62
|
|
||||||
})
|
|
||||||
|
|
||||||
# Add a clean alternative channel — no neighbors observed there
|
|
||||||
insert_scan(org, device, %{
|
|
||||||
bssid: "11:22:33:44:55:77",
|
|
||||||
ssid: "Neighbor-B",
|
|
||||||
channel: 153,
|
|
||||||
rssi_dbm: -90
|
|
||||||
})
|
|
||||||
|
|
||||||
assert [insight] = FrequencyChange.evaluate(org.id)
|
assert [insight] = FrequencyChange.evaluate(org.id)
|
||||||
assert insight.type == "ap_frequency_change"
|
assert insight.type == "ap_frequency_change"
|
||||||
assert insight.urgency in ~w(warning critical)
|
assert insight.urgency in ~w(warning critical)
|
||||||
assert insight.organization_id == org.id
|
assert insight.organization_id == org.id
|
||||||
assert insight.device_id == device.id
|
assert insight.device_id == device.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "populates metadata with current channel, frequency and width",
|
||||||
|
%{org: org, device: device} do
|
||||||
|
insert_scan(org, device, %{bssid: "11:22:33:44:55:66", channel: 149, rssi_dbm: -62})
|
||||||
|
insert_scan(org, device, %{bssid: "11:22:33:44:55:77", channel: 153, rssi_dbm: -90})
|
||||||
|
|
||||||
|
assert [insight] = FrequencyChange.evaluate(org.id)
|
||||||
md = insight.metadata
|
md = insight.metadata
|
||||||
assert md["current_channel"] == 149
|
assert md["current_channel"] == 149
|
||||||
assert md["current_frequency_mhz"] == 5745
|
assert md["current_frequency_mhz"] == 5745
|
||||||
assert md["channel_width_mhz"] == 80
|
assert md["channel_width_mhz"] == 80
|
||||||
|
end
|
||||||
|
|
||||||
|
test "recommends a different channel with better score",
|
||||||
|
%{org: org, device: device} do
|
||||||
|
insert_scan(org, device, %{bssid: "11:22:33:44:55:66", channel: 149, rssi_dbm: -62})
|
||||||
|
insert_scan(org, device, %{bssid: "11:22:33:44:55:77", channel: 153, rssi_dbm: -90})
|
||||||
|
|
||||||
|
assert [insight] = FrequencyChange.evaluate(org.id)
|
||||||
|
md = insight.metadata
|
||||||
assert is_integer(md["recommended_channel"])
|
assert is_integer(md["recommended_channel"])
|
||||||
assert md["recommended_channel"] != 149
|
assert md["recommended_channel"] != 149
|
||||||
assert is_number(md["current_score"])
|
assert is_number(md["current_score"])
|
||||||
assert is_number(md["recommended_score"])
|
assert is_number(md["recommended_score"])
|
||||||
assert md["current_score"] > md["recommended_score"]
|
assert md["current_score"] > md["recommended_score"]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "top_offenders lists the interfering neighbors in order",
|
||||||
|
%{org: org, device: device} do
|
||||||
|
insert_scan(org, device, %{bssid: "11:22:33:44:55:66", channel: 149, rssi_dbm: -62})
|
||||||
|
insert_scan(org, device, %{bssid: "11:22:33:44:55:77", channel: 153, rssi_dbm: -90})
|
||||||
|
|
||||||
|
assert [insight] = FrequencyChange.evaluate(org.id)
|
||||||
|
md = insight.metadata
|
||||||
assert is_list(md["top_offenders"])
|
assert is_list(md["top_offenders"])
|
||||||
refute Enum.empty?(md["top_offenders"])
|
refute Enum.empty?(md["top_offenders"])
|
||||||
[first | _] = md["top_offenders"]
|
[first | _] = md["top_offenders"]
|
||||||
assert first["bssid"] == "11:22:33:44:55:66"
|
assert first["bssid"] == "11:22:33:44:55:66"
|
||||||
assert first["rssi_dbm"] == -62
|
assert first["rssi_dbm"] == -62
|
||||||
|
end
|
||||||
|
|
||||||
|
test "generates a title mentioning the AP name and current channel",
|
||||||
|
%{org: org, device: device} do
|
||||||
|
insert_scan(org, device, %{bssid: "11:22:33:44:55:66", channel: 149, rssi_dbm: -62})
|
||||||
|
insert_scan(org, device, %{bssid: "11:22:33:44:55:77", channel: 153, rssi_dbm: -90})
|
||||||
|
|
||||||
|
assert [insight] = FrequencyChange.evaluate(org.id)
|
||||||
assert is_binary(insight.title)
|
assert is_binary(insight.title)
|
||||||
assert insight.title =~ "AP-North"
|
assert insight.title =~ "AP-North"
|
||||||
assert insight.title =~ "149"
|
assert insight.title =~ "149"
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ defmodule Towerops.Snmp.MibTranslatorTest do
|
||||||
|
|
||||||
alias Towerops.Snmp.MibTranslator
|
alias Towerops.Snmp.MibTranslator
|
||||||
|
|
||||||
|
doctest MibTranslator
|
||||||
|
|
||||||
# NOTE: Tests that depend on the NIF (ToweropsNative) are commented out
|
# NOTE: Tests that depend on the NIF (ToweropsNative) are commented out
|
||||||
# in this worktree because the NIF is stubbed. Re-enable when NIF is available.
|
# in this worktree because the NIF is stubbed. Re-enable when NIF is available.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ defmodule Towerops.Snmp.PollerTest do
|
||||||
alias Towerops.Snmp.Poller
|
alias Towerops.Snmp.Poller
|
||||||
alias Towerops.Snmp.SnmpMock
|
alias Towerops.Snmp.SnmpMock
|
||||||
|
|
||||||
|
doctest Poller
|
||||||
|
|
||||||
setup :verify_on_exit!
|
setup :verify_on_exit!
|
||||||
|
|
||||||
describe "check_device/1" do
|
describe "check_device/1" do
|
||||||
|
|
|
||||||
5
test/towerops/time_test.exs
Normal file
5
test/towerops/time_test.exs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule Towerops.TimeTest do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
|
doctest Towerops.Time
|
||||||
|
end
|
||||||
|
|
@ -90,7 +90,7 @@ defmodule Towerops.Workers.ExpiredBanCleanupWorkerTest do
|
||||||
|
|
||||||
assert :ok = ExpiredBanCleanupWorker.perform(%Oban.Job{args: %{}})
|
assert :ok = ExpiredBanCleanupWorker.perform(%Oban.Job{args: %{}})
|
||||||
|
|
||||||
refute_receive :blocks_updated
|
refute_receive :blocks_updated, 100
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ defmodule Towerops.Workers.PollingOffsetTest do
|
||||||
|
|
||||||
alias Towerops.Workers.PollingOffset
|
alias Towerops.Workers.PollingOffset
|
||||||
|
|
||||||
|
doctest PollingOffset
|
||||||
|
|
||||||
describe "calculate_offset/2" do
|
describe "calculate_offset/2" do
|
||||||
test "returns value within interval bounds" do
|
test "returns value within interval bounds" do
|
||||||
device_id = Ecto.UUID.generate()
|
device_id = Ecto.UUID.generate()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
defmodule ToweropsNativeTest do
|
defmodule ToweropsNativeTest do
|
||||||
use ExUnit.Case, async: false
|
use ExUnit.Case, async: false
|
||||||
|
|
||||||
|
doctest ToweropsNative
|
||||||
|
|
||||||
# Suppress false positive dialyzer warnings for NIF return types
|
# Suppress false positive dialyzer warnings for NIF return types
|
||||||
@dialyzer :no_match
|
@dialyzer :no_match
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -433,7 +433,7 @@ defmodule ToweropsWeb.AgentChannelBuildersTest do
|
||||||
jobs = decode_jobs(jobs_binary)
|
jobs = decode_jobs(jobs_binary)
|
||||||
|
|
||||||
job = Enum.find(jobs, &(&1.device_id == device.id))
|
job = Enum.find(jobs, &(&1.device_id == device.id))
|
||||||
assert job
|
assert job.device_id == device.id
|
||||||
assert job.snmp_device.community == ""
|
assert job.snmp_device.community == ""
|
||||||
|
|
||||||
Process.flag(:trap_exit, true)
|
Process.flag(:trap_exit, true)
|
||||||
|
|
|
||||||
|
|
@ -914,7 +914,7 @@ defmodule ToweropsWeb.AgentChannelTest do
|
||||||
payload = encode_payload(result)
|
payload = encode_payload(result)
|
||||||
push(socket, "result", payload)
|
push(socket, "result", payload)
|
||||||
|
|
||||||
assert_receive {:live_poll_result, oid_values}, 500
|
assert_receive {:live_poll_result, oid_values}
|
||||||
assert Map.has_key?(oid_values, "1.3.6.1.2.1.1.1.0")
|
assert Map.has_key?(oid_values, "1.3.6.1.2.1.1.1.0")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ defmodule ToweropsWeb.Api.ParamFilterTest do
|
||||||
|
|
||||||
alias ToweropsWeb.Api.ParamFilter
|
alias ToweropsWeb.Api.ParamFilter
|
||||||
|
|
||||||
|
doctest ParamFilter
|
||||||
|
|
||||||
describe "strip_sensitive/1" do
|
describe "strip_sensitive/1" do
|
||||||
test "removes sensitive identity fields from params" do
|
test "removes sensitive identity fields from params" do
|
||||||
params = %{
|
params = %{
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ defmodule ToweropsWeb.Live.Helpers.AccessControlTest do
|
||||||
alias Towerops.Alerts
|
alias Towerops.Alerts
|
||||||
alias ToweropsWeb.Live.Helpers.AccessControl
|
alias ToweropsWeb.Live.Helpers.AccessControl
|
||||||
|
|
||||||
|
doctest AccessControl
|
||||||
|
|
||||||
describe "verify_device_access/2" do
|
describe "verify_device_access/2" do
|
||||||
setup do
|
setup do
|
||||||
user1 = user_fixture()
|
user1 = user_fixture()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue