Commit graph

836 commits

Author SHA1 Message Date
rcourtman
cd33c577f8 test: Add resolvePublicURL tests for API package
Add comprehensive tests for the resolvePublicURL function covering:
- Configured PublicURL (simple, trailing slashes, ports, whitespace)
- Request-derived URL (HTTP, HTTPS via TLS, X-Forwarded-Proto)
- No host fallback (with/without frontend port)
- Nil request handling

Coverage: resolvePublicURL 12.5% → 100%
Coverage: API package 30.3% → 30.5%
2025-12-02 12:45:04 +00:00
rcourtman
80739cce94 test: Add rescheduleTask tests for monitoring package
Add comprehensive tests for the rescheduleTask function covering:
- Nil taskQueue handling (early return)
- Successful task outcome (regular rescheduling)
- Transient failure with backoff
- Non-transient failure routing to dead letter queue
- Exceeded retry attempts routing to dead letter queue
- No outcome uses default interval
- PBS and PMG instance type intervals
- Adaptive polling max interval capping
- Existing interval preservation

Coverage: rescheduleTask 32.1% → 58.9%
Coverage: monitoring package 52.8% → 53.5%
2025-12-02 12:38:50 +00:00
rcourtman
2842dded28 test: Add getGuestThresholds tests for alerts package
Add comprehensive tests for the getGuestThresholds function covering:
- Default threshold application
- Guest-specific overrides
- Custom rule filter matching
- Override precedence over custom rules
- Priority-based rule selection
- Disabled rules handling
- Disabled override handling
- DisableConnectivity propagation from overrides and rules
- Legacy CPU threshold conversion
- Legacy ID migration (clustered and standalone VMs)
- Container type support
- All metric thresholds application

Coverage: getGuestThresholds 40.2% → 77.6%
2025-12-02 12:35:07 +00:00
rcourtman
a4e3fe65b8 test: Add preserveAlertState, checkPMGQuarantineBacklog, LoadActiveAlerts tests
Add comprehensive tests for three low-coverage functions:
- preserveAlertState: nil handling, state preservation from existing alerts,
  ackState fallback, new alert handling
- checkPMGQuarantineBacklog: nil quarantine handling, warning/critical
  thresholds, growth rate alerts, alert updates, virus quarantine
- LoadActiveAlerts: missing file, valid file loading, old alert filtering,
  old acknowledged alert filtering, ack state restoration, invalid JSON,
  duplicate alert handling

Coverage improvements:
- preserveAlertState: 63.6% → 100%
- checkPMGQuarantineBacklog: 12.9% → 100%
- checkQuarantineMetric: 0% → 93.1%
- LoadActiveAlerts: 26.2% → 80.0%
- Alerts package: 83.5% → 86.6%
2025-12-02 12:22:14 +00:00
rcourtman
2133b25bb7 test: Add performCleanup tests for notifications queue
Add 4 tests covering the performCleanup function:
- cleanup removes old completed entries (>7 days)
- cleanup removes old DLQ entries (>30 days)
- cleanup removes old audit logs (>30 days)
- cleanup with empty database (no panic)

performCleanup coverage: 0% → 87.0%
Notifications package: 57.3% → 58.3%
2025-12-02 12:16:55 +00:00
rcourtman
a6f4fc7bc0 test: Add GetQueue, addWebhookDelivery, GetWebhookHistory tests
Tests for NotificationManager accessor and helper functions.
Covers queue retrieval, webhook delivery tracking, history trimming
to max 100 entries, and copy-on-read semantics. Notifications 56.6%→57.3%.
2025-12-02 12:10:29 +00:00
rcourtman
f184174f2b test: Add HistoryManager tests for alerts package
New history_test.go with 24 tests covering GetStats, getFileSize,
AddAlert, GetHistory, GetAllHistory, RemoveAlert, ClearAllHistory,
cleanOldEntries, saveHistory, loadHistory. Alerts package 83.6%→84.0%.
2025-12-02 12:06:53 +00:00
rcourtman
fc96ba7b69 test: Add WaitNext and key() tests for TaskQueue
Tests cover context cancellation, immediately due tasks, waiting for
future tasks, empty queue timeout, and multiple task priority ordering.
WaitNext coverage 0%→92.3%, key() 0%→100%. Monitoring package 52.3%→52.9%.
2025-12-02 12:02:13 +00:00
rcourtman
e63c297ca3 test: Add BuildPlan, FilterDue, DispatchDue, LastScheduled tests
Comprehensive tests for AdaptiveScheduler methods covering empty inventory,
single/multiple instances, priority ordering, interval clamping, task caching,
nil receiver handling, and task filtering. Monitoring package 51.4%→52.3%.
2025-12-02 11:59:37 +00:00
rcourtman
ea120b78d7 test: Add RecordNodeResult, RecordQueueWait, SetQueueDepth tests
Improves metrics.go coverage to 100%. Added comprehensive tests for
node-level poll metrics, queue wait time recording, and queue depth
setting with edge cases (nil receiver, negative values, label normalization).
2025-12-02 11:57:05 +00:00
rcourtman
47d0fb5a44 test: Add dispatchAlert tests (55.6%→77.8%)
Add TestDispatchAlert with 8 test cases covering:
- Returns false when onAlert callback is nil
- Returns false when alert is nil
- Returns false when activation state is pending
- Returns false when activation state is snoozed
- Returns false for monitor-only alerts
- Dispatches synchronously when async is false
- Dispatches asynchronously when async is true
- Clones alert before dispatch

Alerts package coverage: 83.4%→83.5%
2025-12-02 11:47:24 +00:00
rcourtman
b3bf63d3c7 test: Add CheckStorage tests (52.4%→92.9%)
Add comprehensive TestCheckStorageComprehensive with 11 test cases covering:
- Returns early when alerts disabled
- DisableAllStorage clears existing usage and offline alerts
- Override with Disabled clears alerts
- Usage threshold checking
- Override threshold applied correctly
- Skips usage check when offline/unavailable/zero usage
- Offline status creates alert after confirmations
- Unavailable status creates alert
- Clears offline alert when back online

Alerts package coverage: 82.4%→83.4%
2025-12-02 11:43:56 +00:00
rcourtman
9127b27f4c test: Add CheckPMG tests (0%→100%)
Add comprehensive TestCheckPMGComprehensive with 9 test cases covering:
- Returns early when alerts disabled
- DisableAllPMG clears all PMG alert types (queue-total, queue-deferred,
  queue-hold, oldest-message, offline)
- Override with Disabled clears alerts
- DisableAllPMGOffline clears offline alert
- Offline status creates alert after confirmations
- Connection health error triggers offline alert
- Connection health unhealthy triggers offline alert
- Clears offline alert when back online
- Skips metrics when PMG is offline

Alerts package coverage: 81.5%→82.4%
2025-12-02 11:40:53 +00:00
rcourtman
073d5ffa55 fix: Use --ctid instead of --standalone --http-mode in quick-setup command
The quick-setup command for temperature monitoring was generating
--standalone --http-mode which is meant for Docker deployments. This
confused users trying to set up multi-server Proxmox monitoring.

Now uses --ctid which works for both local and remote Proxmox hosts.
The installer detects when the container doesn't exist locally and
installs in "host monitoring only" mode automatically.

If we can determine the actual CTID from the host proxy summary,
we use it; otherwise we show <PULSE_CTID> for the user to replace.

Related to #785
2025-12-02 11:38:47 +00:00
rcourtman
9f174be20b test: Add CheckPBS tests (0%→98.3%)
Add comprehensive TestCheckPBSComprehensive with 12 test cases covering:
- Returns early when alerts disabled
- DisableAllPBS clears existing CPU/memory/offline alerts
- Override with Disabled clears alerts
- DisableAllPBSOffline clears offline alert
- CPU threshold checking when online
- Memory threshold checking when online
- Skips metrics when PBS is offline
- Override thresholds applied correctly
- Offline status creates alert after confirmations
- Connection health error triggers offline alert
- Connection health unhealthy triggers offline alert
- Clears offline alert when back online

Alerts package coverage: 80.0%→81.5%
2025-12-02 11:38:36 +00:00
rcourtman
13f5ca4018 test: Add CheckHost tests (49.6%→98.3%)
Add comprehensive TestCheckHostComprehensive with 17 test cases covering:
- Empty host ID early return
- Alerts disabled early return
- DisableAllHosts clears existing alerts
- Override with Disabled clears alerts
- CPU/Memory/Disk threshold nil clears alerts
- RAID degraded/rebuilding/healthy states
- RAID with failed devices triggers critical alert
- RAID resync triggers rebuilding alert
- Existing RAID alert not duplicated (preserves start time)
- Override thresholds applied correctly
- Multiple disks handling
- Offline alert cleared when host comes online
- Tags included in metadata

Alerts package coverage: 78.6%→80.0%
2025-12-02 11:34:20 +00:00
rcourtman
f4e3f625e7 test: Add CheckGuest tests (41.4%→97.4%)
Cover all CheckGuest branches:
- Early return when alerts disabled
- Early return when all guests disabled
- VM and Container type handling
- Unsupported guest type returns early
- pulse-no-alerts tag suppresses alerts
- Stopped guest triggers powered-off check
- DisableAllGuestsOffline clears tracking
- Paused guest clears powered-off alert
- Non-running guest clears metric alerts
- Running guest clears powered-off alert
- Disabled thresholds clear existing alerts
- CPU, memory, disk metric checks
- Individual disk checks (mountpoint, device, index fallback)
- Skips disk with zero total or negative usage
- I/O metrics (diskRead, diskWrite, networkIn, networkOut)
- pulse-relaxed tag applies relaxed thresholds

Alerts package coverage: 76.0%→78.6%
2025-12-02 11:27:32 +00:00
rcourtman
4ceb4f9a35 test: Add CheckNode tests (31%→100%)
Cover all CheckNode branches:
- Early return when alerts disabled
- DisableAllNodes clears existing alerts
- DisableNodesOffline clears tracking
- Offline/connection error/failed triggers offline check
- Online node clears offline alert
- Online node triggers metric checks
- Offline node skips metric checks
- Override thresholds applied correctly
- Temperature with package temp and max fallback
- Temperature skipped when unavailable/nil/no threshold
- Memory and disk metric checks

Alerts package coverage: 75.2%→76.0%
2025-12-02 11:24:04 +00:00
rcourtman
9791fc07cb test: Add suppressGuestAlerts and guestHasMonitorOnlyAlerts tests
Coverage improvements:
- suppressGuestAlerts: 37% -> 96.3%
- guestHasMonitorOnlyAlerts: 40% -> 90%

Tests cover:
- No alerts returns false
- Exact ResourceID match clears
- Prefix match (e.g., "vm100/disk1") clears
- All auxiliary maps cleared (pending, recent, suppressed, rateLimit)
- Multiple alerts cleared
- Monitor-only detection via metadata (bool and string types)
2025-12-02 11:14:30 +00:00
rcourtman
f661c5a6a8 test: Add applyThresholdOverride tests
Coverage for applyThresholdOverride: 50% -> 93.2%

Tests cover:
- Empty override returns base unchanged
- Disabled/DisableConnectivity flag overrides
- Modern CPU threshold override
- Legacy CPU threshold conversion
- Modern takes precedence over legacy
- Multiple metrics override
- Note override, clearing, trimming
- All legacy metric types (Memory, Disk, etc.)
- Temperature and Usage override
- ensureHysteresisThreshold Clear value filling
2025-12-02 11:08:58 +00:00
rcourtman
ed118c973f test: Add ClearActiveAlerts test with existing alerts
Coverage for ClearActiveAlerts: 16% -> 92%

Tests verify all internal maps are properly cleared when alerts exist:
- activeAlerts, pendingAlerts, recentAlerts
- suppressedUntil, alertRateLimit
- nodeOfflineCount, offlineConfirmations
- dockerOfflineCount, dockerStateConfirm
- ackState, recentlyResolved
2025-12-02 11:01:54 +00:00
rcourtman
219c568649 test: Add CheckDiskHealth normal path tests
Coverage for CheckDiskHealth: 51% -> 98%

Tests cover:
- Healthy disk (PASSED/OK) creates no alert
- Failed non-Samsung disk creates critical alert
- Alert cleared when disk health recovers
- Low wearout (<10%) creates warning alert
- Wearout alert updates on subsequent checks
- Wearout alert cleared when wearout >= 10%
- Empty/UNKNOWN health creates no alert
2025-12-02 10:59:48 +00:00
rcourtman
c04d559700 test: Add Docker container restart loop alert tests
Coverage for checkDockerContainerRestartLoop: 53.5% -> 95.3%

Tests cover:
- First check initializes tracking without alert
- Stable restart count doesn't alert
- Restarts under threshold (<=3) don't alert
- Restart loop threshold (>3) triggers critical alert
- Recovery after window expires clears alert
- Incremental restart accumulation
- Alert StartTime preservation on updates
2025-12-02 10:54:51 +00:00
rcourtman
b6624e32cf test: Add Docker container health and OOM kill alert tests
Coverage improvements:
- checkDockerContainerHealth: 21.1% -> 94.7%
- checkDockerContainerOOMKill: 19.2% -> 96.2%

Tests cover:
- Health states (healthy, empty, none, starting, unhealthy, degraded)
- Health alert recovery when container becomes healthy
- OOM kill detection (exit code 137)
- OOM alert deduplication (repeated 137 doesn't re-alert)
- OOM alert clearing when container recovers or exits with different code
2025-12-02 10:49:42 +00:00
rcourtman
1ed8b18c12 fix: Deadlock in CancelByAlertIDs and add tests
Fixed deadlock where CancelByAlertIDs held nq.mu.Lock() and then called
UpdateStatus() which also tried to acquire the same lock. Now uses
direct SQL while holding the lock.

Tests added for CancelByAlertIDs:
- No matching notifications (notification stays pending)
- Matching notification cancelled
- Multiple alerts with partial match (any match cancels)

Coverage: CancelByAlertIDs 65.7% -> 81.1%
2025-12-02 10:40:07 +00:00
rcourtman
5ef4587767 test: Add queue IncrementAttempt and GetQueueStats tests
Coverage improvements:
- IncrementAttempt: 0% -> 85.7%
- GetQueueStats: 0% -> 87.5%

Tests verify attempt counter increments correctly and queue stats
aggregate notification counts by status.
2025-12-02 10:31:00 +00:00
rcourtman
e27717f1a2 test: Add secure webhook client tests for redirect handling
Tests SSRF protection in webhook client:
- Redirect limit enforcement (max 3)
- Blocking redirects to private networks (10.x, 192.168.x, 172.16.x)
- Blocking redirects to link-local addresses (169.254.x)
- Allowing valid redirects to allowlisted servers

Coverage: createSecureWebhookClient 18.2% -> 100%
2025-12-02 10:26:34 +00:00
rcourtman
9118344355 fix: Isolate alerts tests with temp directories to prevent flaky failures
Tests using NewManager() were sharing /etc/pulse/alerts, causing race
conditions when running in parallel. Added newTestManager(t) helper that
creates isolated temp directories for each test.
2025-12-02 10:21:03 +00:00
rcourtman
350d21c80d test: Add diagnostics function tests for error handling
Add comprehensive tests for untested diagnostics functions:

- fingerprintPublicKey: 14 test cases covering empty/whitespace input,
  invalid key formats, truncated/malformed keys, and valid ED25519 keys

- countLegacySSHKeys: 8 test cases covering non-existent directories,
  empty directories, files without id_ prefix, multiple key types,
  and directory filtering (subdirectories not counted)

- resolveUserName: 4 test cases covering UID 0 (root), current user,
  non-existent UID fallback, and max uint32 boundary

- resolveGroupName: 4 test cases covering GID 0 (root/wheel), current
  group, non-existent GID fallback, and max uint32 boundary

Coverage: fingerprintPublicKey 0% -> 100%, countLegacySSHKeys 0% -> 100%,
resolveUserName 0% -> 100%, resolveGroupName 0% -> 100%
2025-12-02 03:39:52 +00:00
rcourtman
b053a2848b fix: Update TestPublicURLDetectionUsesForwardedHeaders for proxy hardening
The test was failing after commit d6cbfc23 added security hardening
that requires authentication and trusted proxy configuration for
X-Forwarded-* headers to be read during public URL detection.

- Add API token authentication to the test request
- Configure 127.0.0.1 as trusted proxy for the test
- Add export_test.go with ResetTrustedProxyConfigForTests() to allow
  external tests to reset the trusted proxy configuration
2025-12-02 03:16:52 +00:00
rcourtman
201f613ac3 test: Add sendNotificationsDirect email and apprise tests
Test email enabled and apprise enabled code paths.
Coverage: 66.7% → 100.0%
2025-12-02 03:08:35 +00:00
rcourtman
37ec6c3a93 test: Add scanNotification DLQ timestamp test
Test scanNotification with CompletedAt and LastAttempt populated
via DLQ path. Coverage: 61.9% → 81.0%
2025-12-02 03:04:37 +00:00
rcourtman
ae54cfad8c test: Add processNotification tests for all code paths
Test cancelled notification, no processor, success, and failure paths.
Coverage: 50.0% → 80.0%
2025-12-02 03:01:17 +00:00
rcourtman
ca7da7c18f test: Add CancelByAlertIDs empty input and no-match tests
Test early return for empty alertIDs and happy path with empty queue.
Coverage: 62.9% → 65.7%
2025-12-02 02:58:10 +00:00
rcourtman
7a1c9ff53f test: Add SaveNodesConfigAllowEmpty test and document deadlock
Add test for SaveNodesConfigAllowEmpty which permits explicit
deletion of all nodes. Document deadlock bug in saveNodesConfig
where empty config protection tries to call LoadNodesConfig
while holding write lock.
2025-12-02 02:54:49 +00:00
rcourtman
d0fc62d45f test: Add LoadNodesConfig PBS/PMG migration tests
Test PBS and PMG token clearing and host normalization migrations.
Coverage: 61.4% → 76.3%
2025-12-02 02:46:47 +00:00
rcourtman
6d1eb44f7b test: Add LoadEmailConfig encrypted round-trip test
Test Save+Load with encryption enabled to cover success path
after decryption. Coverage: 58.8% → 88.2%
2025-12-02 02:43:49 +00:00
rcourtman
3c1ae26166 test: Add LoadWebhooks migration and error path tests
Cover unencrypted .enc file migration fallback and legacy file
with invalid JSON graceful handling.
Coverage: 67.9% → 75.0%
2025-12-02 02:39:04 +00:00
rcourtman
9eb7c59a4d test: Add SaveAlertConfig host defaults normalization tests
Cover nil HostDefaults initialization (CPU/Memory/Disk) and clear
threshold computation when clear=0 but trigger is set.
Coverage: 68.2% → 75.3%
2025-12-02 02:37:01 +00:00
rcourtman
9027ab359b test: Add StageFile transaction tests
Cover success path, already committed error, replacing existing staged
file, and empty basename edge case.
2025-12-02 02:34:20 +00:00
rcourtman
6cb12bd048 test: Add ImportConfig error path tests
Cover empty passphrase, invalid base64, wrong passphrase decryption
failure, and invalid JSON content error paths.
Coverage: 66.7% → 73.7%
2025-12-02 02:32:06 +00:00
rcourtman
0d482f9d63 test: Add DiscoveryConfig UnmarshalJSON tests
Cover invalid JSON error path, modern field parsing, legacy field
parsing, and empty object default handling.
Coverage: 60% → 88.9%
2025-12-02 02:29:38 +00:00
rcourtman
071ccc44ec test: Add ProcessQueuedNotification error path tests
Cover invalid config JSON for email, webhook, and apprise types,
plus unknown notification type handling.
Coverage: 63.3% → 83.3%
2025-12-02 02:26:25 +00:00
rcourtman
7a63cf3be9 test: Add sendNotificationsDirect tests
Cover disabled paths: all channels disabled, webhook disabled,
multiple webhooks with mixed enabled state.
Coverage: 44.4% → 66.7%
2025-12-02 02:21:46 +00:00
rcourtman
ea04e4faae test: Add sendHTMLEmailWithError tests
Cover email sending paths: empty To uses From as recipient,
nil email manager creates new one, existing manager config updates.
Coverage: 57.9% → 89.5%
2025-12-02 02:19:49 +00:00
rcourtman
9768316e07 test: Add sendGroupedApprise error path tests
Add 3 tests for Apprise notification error handling:
- No alerts returns error
- Not enabled returns error
- Empty payload (all nil alerts) returns error

Coverage: 56.2% → 75.0%
2025-12-02 02:14:13 +00:00
rcourtman
42e7359506 test: Add describeInstancesForScheduler tests
Add 6 tests for instance descriptor generation:
- No clients returns nil
- PVE only with sorted order
- PBS only
- PMG only
- All types combined
- Nil scheduler/stalenessTracker safety

Coverage: 60.7% → 62.5%
2025-12-02 02:11:14 +00:00
rcourtman
de90519b21 test: Add handleHealth method tests
Add 2 tests for health endpoint:
- POST/PUT/DELETE/PATCH return 405 Method Not Allowed
- HEAD is allowed (same as GET)

Coverage: 50% → 83.3%
2025-12-02 02:09:04 +00:00
rcourtman
2d09c28129 test: Add recordTaskResult tests
Add 6 tests for polling task result recording:
- Nil monitor safety check
- Success case resets counters
- Failure case increments counters
- Consecutive failures tracking
- Success resets failure state
- Nil internal maps don't panic

Coverage: 53.7% → 97.6%
2025-12-02 02:06:08 +00:00
rcourtman
67d322c456 test: Add ApplyHostReport error path tests
Add 4 tests for error and edge cases:
- Missing hostname returns error
- Whitespace-only hostname returns error
- Nil hostTokenBindings map is initialized
- Fallback identifier generation

Coverage: 63.7% → 70.8%
2025-12-02 02:03:03 +00:00
rcourtman
7c94f3001e test: Add ApplyDockerReport error path tests
Add 4 tests for error conditions:
- Missing identifier (no agent ID or hostname)
- Removed host rejection
- Token bound to different agent
- Missing hostname

Coverage: 63.0% → 69.5%
2025-12-02 02:00:06 +00:00
rcourtman
781f72c953 test: Add RemoveHostAgent error path tests
Add 4 tests for uncovered branches:
- Empty/whitespace hostID returns error
- Host not found returns synthetic host
- No token binding (token exists but not bound)
- Nil alertManager doesn't panic

Coverage: 64.3% → 78.6%
2025-12-02 01:56:50 +00:00
rcourtman
5ff69a7e35 test: Add adminBypassEnabled tests
Add 5 tests to cover all branches:
- Not requested (ALLOW_ADMIN_BYPASS != "1")
- Enabled with PULSE_DEV=true
- Enabled with NODE_ENV=development
- Case-insensitive NODE_ENV check
- Declined when outside dev mode

Coverage: 40% → 100%
2025-12-02 01:53:55 +00:00
rcourtman
7ed8ef2074 test: Add loadTrustedProxyCIDRs tests
Cover invalid CIDR, invalid IP, IPv6, and empty entry handling (48% to 100%)
2025-12-02 01:48:41 +00:00
rcourtman
24fbce1281 test: Add LogAuditEvent tests
Cover success and failure logging branches (66.7% to 100%)
2025-12-02 01:46:27 +00:00
rcourtman
8f42156781 test: Add SecurityHeadersWithConfig tests
Cover all CSP/X-Frame-Options embedding configurations (57.1% to 100%)
2025-12-02 01:44:22 +00:00
rcourtman
07997b3516 test: Add filesystem error tests for SessionStore
Cover saveUnsafe (57.9% to 89.5%) and load (55.6% to 74.1%) error paths
2025-12-02 01:40:54 +00:00
rcourtman
21b69607f0 test: Add filesystem error tests for CSRFTokenStore
Cover saveUnsafe (57.9% to 89.5%) and load (50.0% to 67.9%) error paths
2025-12-02 01:38:49 +00:00
rcourtman
999f19beed test: Add filesystem error tests for RecoveryTokenStore.saveUnsafe
Cover MkdirAll, WriteFile, and Rename error paths (46.7% to 86.7%)
2025-12-02 01:36:21 +00:00
rcourtman
b3f88d7a8c test: Add edge case tests for HandleSetupScript
Tests method not allowed, missing type parameter, and invalid host
parameter error paths (71.4% to 79.2% coverage).
2025-12-02 01:11:57 +00:00
rcourtman
c080a6beb6 test: Add DNS resolution failure test for ValidateWebhookURL
Tests the error path when webhook hostname cannot be resolved
(78.1% to 81.2% coverage).
2025-12-02 01:09:03 +00:00
rcourtman
7d3de1bbcc test: Add invalid PEM data test for newOIDCHTTPClient
Tests the error path when a CA bundle file contains non-PEM data
(81.8% to 86.4% coverage).
2025-12-02 01:00:06 +00:00
rcourtman
1a595b3b2e test: Add edge cases for UniversalRateLimitMiddleware
Cover nil config initialization and static asset bypass paths.
Coverage: UniversalRateLimitMiddleware 87.5% -> 100%
2025-12-02 00:54:37 +00:00
rcourtman
c57c07f827 test: Add edge case for initializeBootstrapToken error path
Cover loadOrCreateBootstrapToken failure path.
Coverage: initializeBootstrapToken 92% -> 100%
2025-12-02 00:51:44 +00:00
rcourtman
a5f0482d97 test: Add edge cases for HandleLookup error paths
Cover method-not-allowed and missing lookup parameter paths.
Coverage: HandleLookup 88.4% -> 97.7%
2025-12-02 00:49:16 +00:00
rcourtman
44b835ad15 test: Add critical-only grouped alert template case
Test multiple critical alerts without warnings to cover the
"critical > 0" only branch in subject line generation.

Coverage: 97.7% → 100%
2025-12-02 00:40:02 +00:00
rcourtman
96bf0b0ca6 test: Add edge cases for buildApprisePayload
- Test nil alerts in list are filtered out
- Test all-nil alert list returns empty
- Test multiple alerts changes title format

Coverage: 88.9% → 100%
2025-12-02 00:37:28 +00:00
rcourtman
296a520d81 test: Add edge case for extractTelegramChatID URL parse error
Test URL with control characters triggers url.Parse error path.

Coverage: 92.9% → 100%
2025-12-02 00:31:50 +00:00
rcourtman
890a2f792d test: Add edge case for NormalizeAppriseConfig low timeout
Test TimeoutSeconds value between 1-4 clamps to minimum of 5.

Coverage: 97.4% → 100%
2025-12-02 00:29:12 +00:00
rcourtman
6777257a7a test: Add edge cases for normalizeRequestedScopes
- Test blank scope identifier returns error
- Test wildcard-only input returns wildcard scope

Coverage: 89.7% → 96.6% (remaining 3.4% is defensive
unreachable code path)
2025-12-02 00:19:20 +00:00
rcourtman
e07bd834b6 Filter virtual/system filesystems from host disk display
Host disk bars were showing virtual filesystems like tmpfs, /dev, /run,
/sys, and Docker overlay mounts. These clutter the UI and don't represent
meaningful disk usage.

Changed from `shouldIgnoreReadOnlyFilesystem` (read-only only) to the
full `fsfilters.ShouldSkipFilesystem` which also excludes:
- Virtual FS types: tmpfs, devtmpfs, sysfs, proc, cgroup, etc.
- Special mountpoints: /dev, /proc, /sys, /run, /var/lib/docker, /snap
- Network filesystems: fuse, nfs, cifs, etc.

Related to #790
2025-12-02 00:16:39 +00:00
rcourtman
b5d42f6e2e test: Add edge case for ensureSettingsWriteScope valid scope
Tests the code path when an API token has the settings:write scope,
which allows the operation to proceed.
2025-12-02 00:13:32 +00:00
rcourtman
8597eca010 Fix backup indicator being reset when VMs/Containers are re-polled
UpdateVMsForInstance and UpdateContainersForInstance were replacing
guest data without preserving the LastBackup field that was populated
by SyncGuestBackupTimes. This caused backup indicators to always show
"no backup found" since the LastBackup would be wiped every time
guests were polled (which happens more frequently than backup polling).

Now both functions preserve LastBackup from existing data when the
incoming guest data has a zero value.

Related to #762
2025-12-02 00:12:31 +00:00
rcourtman
9baf99d32a test: Add edge cases for isTrustedProxyIP and GetClientIP
Tests empty string, invalid IP, and IP not matching CIDR for
isTrustedProxyIP. Also adds tests for GetClientIP empty RemoteAddr
and X-Real-IP fallback paths.
2025-12-02 00:09:23 +00:00
rcourtman
02419827b6 test: Add tests for hostAgentSearchCandidates parameter variants
Tests all code paths: strict mode (both params), platform only,
and no params (generic paths).
2025-12-02 00:03:19 +00:00
rcourtman
7407447bbf test: Add edge case for handleServerInfo method not allowed
Tests that POST requests to /api/server/info return 405.
2025-12-02 00:01:17 +00:00
rcourtman
4751f57187 test: Add edge case for capturePublicURLFromRequest nil inputs
Tests the early return paths when router, request, or config are nil.
2025-12-01 23:59:17 +00:00
rcourtman
b9f9077496 test: Add edge case for canCapturePublicURL nil inputs
Tests the early return paths when config or request are nil.
2025-12-01 23:56:59 +00:00
rcourtman
f0688db9af test: Add edge case for recovery token load read error
Tests the error logging path when os.ReadFile fails with an error
other than ErrNotExist. Uses a directory in place of the file.
2025-12-01 23:54:42 +00:00
rcourtman
347d6b1cbb test: Add edge case for writeErrorResponse encode failure
Tests the error logging path when json.Encode fails due to a
write error on the ResponseWriter.
2025-12-01 23:52:21 +00:00
rcourtman
90d81f2217 test: Add edge cases for markAutoRegistered empty inputs
Tests the early return paths when nodeType or nodeName are empty.
2025-12-01 23:50:10 +00:00
rcourtman
3280fad5ae test: Add edge case for clearBootstrapToken remove failure
Tests the warning log path when os.Remove fails with an error other
than ErrNotExist. Uses a directory with contents to trigger ENOTEMPTY.
2025-12-01 23:47:58 +00:00
rcourtman
678c5aac5f test: Add edge cases for initializeBootstrapToken
- Nil router and nil config handling (no panic)
- OIDC enabled clears bootstrap token
Coverage: 80% to 92%.
2025-12-01 23:40:22 +00:00
rcourtman
8c40c7faa3 test: Add panic recovery test for ErrorHandler
Tests that panics in handlers are recovered and return 500.
Coverage: 91.7% to 100%.
2025-12-01 23:37:50 +00:00
rcourtman
d0c2524353 test: Add edge case for handleValidateBootstrapToken invalid JSON
Tests invalid JSON body triggers json.Decode error and returns 400.
Coverage: 90.5% to 100%.
2025-12-01 23:35:40 +00:00
rcourtman
890178acb0 test: Add edge case for RequireScope empty scope
Empty scope should allow all requests through without checking token.
Coverage: 84.6% to 100%.
2025-12-01 23:33:11 +00:00
rcourtman
0fa717a78a test: Add edge case for normalizeNodeHost URL parse error
Control character (null byte) triggers url.Parse error, covering the
'invalid host format' error branch. Coverage: 96.3% to 100%.
2025-12-01 23:28:32 +00:00
rcourtman
08765c7b59 test: Add edge case for DemoModeMiddleware WebSocket POST upgrade
Tests WebSocket upgrade with POST method in demo mode, ensuring the
websocket check branch is exercised after the GET/HEAD/OPTIONS check.
Coverage: 90% to 100%.
2025-12-01 23:24:06 +00:00
rcourtman
a5369ba2cd test: Add test for ErrorHandler empty URL path normalization
Covers the fix for issue #334 where empty path is normalized to '/'.
Coverage: 87.5% to 91.7%.
2025-12-01 23:21:07 +00:00
rcourtman
1fdb15c779 test: Add edge case tests for auth helper functions
- respondMissingScope: nil writer handling (80% to 100%)
- attachAPITokenRecord: nil record handling (80% to 100%)
- getAPITokenRecordFromRequest: wrong type and missing value (87.5% to 100%)
2025-12-01 23:15:04 +00:00
rcourtman
c71fb694bb test: Add edge case test for addQueryParam URL parse error
Add test case for URL containing control character (null byte)
which triggers url.Parse error and returns path unchanged.

Coverage improved from 88.9% to 100%.
2025-12-01 23:08:36 +00:00
rcourtman
37cc97952f test: Add comprehensive test cases for isPrivateIP function
Expand test coverage from 5 cases to 26 cases:
- Public IPv4/IPv6 addresses
- All RFC1918 private ranges (10.x, 172.16-31.x, 192.168.x)
- Loopback addresses (127.x.x.x, ::1)
- Link-local addresses (169.254.x.x, fe80::)
- Link-local multicast (224.0.0.x, ff02::)
- Unique local IPv6 (fc00::/7, fd00::)
- Edge cases: empty string, invalid IP, invalid format
- Addresses with port numbers

Coverage unchanged at 93.8% (remaining 6.2% is defensive
error handling for hardcoded valid CIDRs).
2025-12-01 22:54:56 +00:00
rcourtman
ef380df362 test: Add edge case tests for normalizeNodeHost function
Add 6 new test cases covering previously untested branches:
- Empty host returns error
- Whitespace-only host returns error
- Unknown node type keeps host without port
- Docker node type keeps host without port
- IPv4 address gets default port
- IPv4 with custom port preserved

Coverage improved from 92.6% to 96.3%.
2025-12-01 22:49:29 +00:00
rcourtman
7c27a74c42 test: Add comprehensive tests for PBS snapshot conversion
Add 13 test cases for convertPBSSnapshots covering:
- Empty/nil input handling
- Basic snapshot field mapping
- Files as string array
- Files as object array with filename field
- Invalid file objects ignored gracefully
- Verification status as string ("ok" vs other)
- Verification status as object with state field
- Verification object without state field
- Multiple snapshots with unique IDs
- Empty namespace handling in ID generation
- Container (ct) backup type

Coverage: convertPBSSnapshots 0% -> 100%
2025-12-01 22:23:47 +00:00
rcourtman
4019b3006b test: Add tests for instance lookup and setup token validation
- Add TestFindInstanceNameByHost (12 test cases):
  - PVE instance lookup by host
  - PBS instance lookup by host
  - Unknown node types return empty
  - Empty config handling

- Add TestValidateSetupToken (8 test cases):
  - Empty token returns false
  - Valid/expired/used setup codes
  - Valid/expired recent setup tokens
  - Non-existent token handling
  - Precedence of setup codes over recent tokens

Both functions now have 100% coverage of their logic paths.
2025-12-01 22:19:30 +00:00
rcourtman
b403cdd7b7 test: Add comprehensive tests for convertDockerTasks function
- Test nil input returns nil
- Test empty slice returns nil
- Test single task with all fields populated
- Test task with error state (failed tasks)
- Test multiple tasks conversion
- Test nil time pointers preserved as nil
- Test zero time values converted to nil (defensive handling)
- Test all optional time fields (UpdatedAt, StartedAt, CompletedAt)

Improves monitoring package coverage for Docker Swarm task handling.
2025-12-01 22:13:43 +00:00
rcourtman
67a351fbd9 test: Add tests for webhook template generation and bootstrap token functions
- Add comprehensive tests for generatePayloadFromTemplateWithService covering:
  - Valid JSON template rendering
  - Invalid template syntax error handling
  - Template execution errors
  - ntfy service (plain text, skips JSON validation)
  - Various services (discord, telegram, pagerduty) JSON validation
  - Template function usage (upper, title)
  - Numeric and boolean values in templates
  - Special characters and empty template edge cases

- Add tests for bootstrapTokenValid covering:
  - Nil router handling
  - Empty hash and empty token cases
  - Valid token validation
  - Invalid token rejection
  - Whitespace trimming

- Add tests for clearBootstrapToken covering:
  - Nil router safety
  - Token file deletion
  - Missing file handling
  - Empty path handling
2025-12-01 22:07:40 +00:00
rcourtman
cb683597c6 test: Add tests for GPU temperature parsing functions
- parseGPUTemps: AMD GPU edge/junction/mem temperatures, sensor mapping
- parseNouveauGPUTemps: NVIDIA nouveau GPU core temperature parsing
- Case insensitive sensor name matching
- Invalid/zero/negative temperature handling
- Append behavior for multiple GPUs
2025-12-01 21:56:33 +00:00
rcourtman
3233c48986 test: Add tests for API helper functions
- isRecentlyAutoRegistered: expiry logic, cleanup behavior
- clearAutoRegistered: key deletion, empty input handling
- normalizeDockerAgentArch: all arch variants, case handling, trimming
2025-12-01 21:33:45 +00:00
rcourtman
80702a51bf test: Add tests for prepareWebhookData function
Covers webhook payload data preparation:
- publicURL handling with trailing slash trimming
- alert.Instance URL detection (http/https)
- Metadata extraction and copying
- Value/Threshold rounding to 1 decimal
- AckTime formatting
- CustomFields passthrough
2025-12-01 21:27:29 +00:00
rcourtman
833ec0933f test: Add tests for notification rate limiting and content building
- checkWebhookRateLimit: rate limit window, counter, per-URL isolation
- buildResolvedNotificationContent: single/multiple alerts, nil filtering,
  HTML escaping, timestamp handling, optional fields
2025-12-01 21:25:02 +00:00
rcourtman
334cffb1c7 test: Add tests for monitor helper and metrics functions
- clearGuestMetadataCache: nil safety, cache clearing, key isolation
- shouldRunBackupPoll: interval-based, cycle-based, config validation
- storeNodeLastSuccess/lastNodeSuccessFor: store/retrieve, overwrite, missing keys

Improves coverage for backup polling logic and node metrics tracking.
2025-12-01 21:18:33 +00:00
rcourtman
8198e1d839 test: Add comprehensive tests for guest metadata functions
Tests for rate limiting, retry, and slot management:
- retryGuestAgentCall: timeout retry, non-timeout break, context cancellation
- acquireGuestMetadataSlot: nil safety, slot acquisition, context cancellation
- releaseGuestMetadataSlot: nil safety, non-blocking release
- tryReserveGuestMetadataFetch: reservation logic, default hold duration
- scheduleNextGuestMetadataFetch: interval, jitter, RNG handling
- deferGuestMetadataRetry: backoff logic, defaults

Covers error handling and edge cases in guest agent metadata fetching.
2025-12-01 21:10:28 +00:00
rcourtman
a3eb81778f test: Add table-driven tests for parseSensorsJSON
Comprehensive coverage for temperature sensor JSON parsing:
- Empty/whitespace input handling
- Invalid JSON error handling
- Legacy and wrapper format support
- Multiple chip types: coretemp, k10temp, acpitz, nvme, amdgpu, nouveau, zenpower, nct6795, it87, rp1_adc
- Edge cases: non-map chip data, CPUMax calculation from cores
2025-12-01 21:00:46 +00:00
rcourtman
1af38e3f99 test: Add tests for parseContainerMountMetadata, convertContainerDiskInfo, StalenessScore
- parseContainerMountMetadata: parts without equals, mountpoint key variant,
  whitespace handling, single source value (96.4% -> 100%)
- convertContainerDiskInfo: nil metadata, device from metadata, negative free
  clamping, whitespace label handling (95.1% -> 97.6%, remaining is dead code)
- StalenessScore: negative maxStale default, metrics lookup failure, score
  clamping edge cases (95.7% - remaining is defensive dead code)
2025-12-01 20:44:00 +00:00
rcourtman
ed0644035f test: Add tests for sanitizeGuestAddressStrings, parseContainerConfigNetworks, mergeNVMeTempsIntoDisks
- sanitizeGuestAddressStrings: IPv6 loopback with CIDR (::1/128) edge case
  (96.2% -> 100%)
- parseContainerConfigNetworks: parts without equals, mac/ips/ip6addr/ip6prefix
  key variants, whitespace-only values, all-empty results (97.2% -> 100%)
- mergeNVMeTempsIntoDisks: NVMe disk with no legacy temps (continue branch),
  more disks than temps (break branch) (97% -> 100%)
2025-12-01 20:34:48 +00:00
rcourtman
4e33b396e0 test: Add tests for normalizeEndpointHost, SelectInterval, generateDockerHostIdentifier
- normalizeEndpointHost: port-only URL host (parsed.Host fallback),
  edge cases for URL parsing (94.4% -> 100%)
- SelectInterval: negative penalty, instance key derivation, clamping
  edge cases (96% - remaining is unreachable dead code guards)
- generateDockerHostIdentifier: empty base fallbacks, suffix candidates,
  hash suffix, numeric suffix increments (91.7% -> 100%)
2025-12-01 20:26:21 +00:00
rcourtman
4c91dce2f8 test: Add tests for allow, ensureContainerRootDiskEntry; remove dead code
- allow (circuitBreaker): all states including unknown/default branch,
  open→half-open transition, half-open window timing (93.8% -> 100%)
- ensureContainerRootDiskEntry: nil container, existing disks, used>total
  clamping, negative free clamping, usage calculation (92.3% -> 100%)
- convertPoolInfoToModel: removed unreachable nil check (dead code since
  ConvertToModelZFSPool only returns nil for nil receiver) (88.9% -> 100%)
2025-12-01 20:15:32 +00:00
rcourtman
0a9177f161 test: Add tests for lookupClusterEndpointLabel, GetNodeMetrics, stateDetails
- lookupClusterEndpointLabel: nil instance, no match, Host vs IP fallback,
  case-insensitive NodeName, whitespace handling (84.6% -> 100%)
- GetNodeMetrics: unknown metric types, empty nodeID, zero duration,
  empty metrics data, disk type (94.1% -> 100%)
- stateDetails: all breaker states including unknown/invalid state,
  retryAt calculations, timestamps (90% -> 100%)
2025-12-01 20:07:22 +00:00
rcourtman
2fdc051c11 fix: Make parseNVMeTemps deterministic by checking Composite before Sensor 1
Go map iteration order is non-deterministic, causing flaky test failures.
This fix ensures "Composite" sensor is always preferred over "Sensor 1"
by checking them in separate loops rather than relying on iteration order.
2025-12-01 20:03:05 +00:00
rcourtman
f79d20296b test: Add tests for GetGuestMetrics, mergeSnapshot, getDockerCommandPayload
- GetGuestMetrics: all metric types, duration filtering, guest not found,
  unknown metric type, empty data (81% -> 100%)
- mergeSnapshot: timestamp merging for LastSuccess/LastError/LastMutated,
  ChangeHash preservation (86.7% -> 100%)
- getDockerCommandPayload: empty hostID, whitespace normalization, host
  not found, expired command cleanup, queued->dispatched marking,
  already-dispatched preservation (91.3% -> 100%)
2025-12-01 19:58:43 +00:00
rcourtman
196389853e test: Add tests for StalenessScore, parseCPUTemps, queueDockerStopCommand
- StalenessScore: 78.3%→95.7% (4 cases for metrics, future timestamp, defaults)
- parseCPUTemps: 98.1%→100% (core temp exceeding package case)
- queueDockerStopCommand: 76.9%→100% (12 cases for validation, status checks)
2025-12-01 19:50:42 +00:00
rcourtman
2594a6c124 test: Add tests for handleProxyHostFailure, recordNodeSnapshot, evaluateHostAgents
- handleProxyHostFailure: 76.5%→100% (9 cases for per-host failure tracking)
- recordNodeSnapshot: 75%→100% (6 cases for diagnostic snapshot storage)
- evaluateHostAgents: 87%→100% (10 cases for host health evaluation)
2025-12-01 19:40:32 +00:00
rcourtman
c6a34c4412 test: Add tests for handleProxyFailure, parseRPiTemperature, RecordResult
- handleProxyFailure: 86.7%→100% (6 cases for proxy disable threshold logic)
- parseRPiTemperature: 77.8%→100% (7 cases for RPi temp parsing edge cases)
- RecordResult: 95.8%→100% (negative staleness clamping case)
2025-12-01 19:33:06 +00:00
rcourtman
1f380eaaf3 test: Add tests for isProxyEnabled, taskHeap.Pop, NewAdaptiveScheduler
- isProxyEnabled: 94.4%→100% (7 cases for proxy cooldown/restore logic)
- taskHeap.Pop: 87.5%→100% (3 cases for empty/single/multi-element heap)
- NewAdaptiveScheduler: 84.6%→100% (14 cases for default value handling)
2025-12-01 19:26:37 +00:00
rcourtman
0ed84f3179 test: Add tests for disableLegacySSHOnAuthFailure, parseNVMeTemps, updateDeadLetterMetrics
- disableLegacySSHOnAuthFailure: 87.5%→100% (13 cases for auth error detection)
- parseNVMeTemps: 88.9%→100% (16 cases for NVMe temp parsing)
- updateDeadLetterMetrics: 75%→100% (6 cases for nil handling, queue states)
2025-12-01 19:20:09 +00:00
rcourtman
7bab2f86af test: Add tests for AllowDockerHostReenroll, SelectInterval, ensureBreaker
- AllowDockerHostReenroll: 95%→100% (7 cases for empty/blocked/cleanup paths)
- ensureBreaker: 94.4%→100% (6 cases for nil map, existing, custom config)
- SelectInterval: 94%→96% (20+ cases for edge cases, remaining guards unreachable)
2025-12-01 19:13:40 +00:00
rcourtman
e7bc06033a test: Add tests for convertDockerSwarmInfo, namespacePathsForDatastore, preserveFailedStorageBackups
- convertDockerSwarmInfo: 66.7%→100% (4 cases for nil, empty, populated structs)
- namespacePathsForDatastore: 92.3%→100% (removed unreachable dead code)
- preserveFailedStorageBackups: 91.3%→100% (6 cases for filtering, deduplication)
2025-12-01 19:04:23 +00:00
rcourtman
0bfc9ed447 test: Add tests for storageNamesForNode, GetDockerHost, and SchedulerHealth edge cases
- storageNamesForNode: 83.3%→100% (8 cases for filtering logic)
- GetDockerHost: 75%→100% (5 cases for lookup and whitespace handling)
- SchedulerHealth: 85.3%→89.1% (13 cases for nil handling, breaker key parsing)
2025-12-01 18:57:09 +00:00
rcourtman
2d775e9409 test: Add tests for polling interval, proxy success handlers, and failed instance removal
- effectivePVEPollingInterval: 80%→100% (6 cases for nil/clamping)
- handleProxySuccess: 80%→100% (3 cases for nil client, reset)
- handleProxyHostSuccess: →100% (6 cases for empty/whitespace/removal)
- removeFailedPBSNode: 75%→100% (5 cases for removal, backups, health)
- removeFailedPMGInstance: 75%→100% (5 cases for removal, backups, health)
2025-12-01 18:49:09 +00:00
rcourtman
acb7f4cf3a test: Add tests for normalizeEndpointHost, taskExecutionTimeout, decrementPending
- normalizeEndpointHost: 89%→94.4% (19 cases covering schemes, ports, paths, edge cases)
- taskExecutionTimeout: 83%→100% (4 cases covering defaults and custom timeouts)
- decrementPending: 88%→100% (5 cases covering decrement logic and no-op scenarios)
2025-12-01 18:42:57 +00:00
rcourtman
6183727368 test: Add tests for getNodeDisplayName, lookupClusterEndpointLabel, extractSnapshotName
- getNodeDisplayName: 71%→100% (12 tests covering cluster/non-cluster fallbacks)
- lookupClusterEndpointLabel: 77%→85% (14 tests covering endpoint matching)
- extractSnapshotName: 78%→100% (8 tests covering volid parsing)

Monitoring package 46.2%→46.4%
2025-12-01 18:37:27 +00:00
rcourtman
330cec7829 test: Add tests for clampUint64ToInt64 and resetAuthFailures
- clampUint64ToInt64: 67%→100% (5 tests covering boundary conditions)
- resetAuthFailures: 67%→100% (6 tests covering map cleanup logic)

Note: cloneStringFloatMap and cloneStringMap tests already existed.
2025-12-01 18:31:34 +00:00
rcourtman
7672cad174 test: Add tests for SetBreakerState, RecordResult, ResetQueueDepth, IncInFlight, DecInFlight
- SetBreakerState: 67%→100% (8 tests covering state conversion, retryAt clamping)
- RecordResult: 75%→96% (11 tests covering success/failure paths, staleness)
- ResetQueueDepth: 75%→100% (4 tests covering negative clamping)
- IncInFlight/DecInFlight: 67%→100% (4 tests)

Monitoring package 45.9%→46.2%
2025-12-01 18:27:05 +00:00
rcourtman
44b6745741 test: Add tests for recordAuthFailure, shouldSkipProxyHost, recoverFromPanic
- recordAuthFailure: 53%→100% (8 tests covering failure counting, node removal)
- shouldSkipProxyHost: 44%→100% (9 tests covering cooldown logic, state cleanup)
- recoverFromPanic: 50%→100% (7 tests covering various panic value types)

Monitoring package 45.3%→45.9%
2025-12-01 18:20:12 +00:00
rcourtman
b4fb5d2a6a test: Add tests for mergeNVMeTempsIntoDisks, UpdateQueueSnapshot, UpdateDeadLetterCounts, templateFuncMap
- mergeNVMeTempsIntoDisks: 57%→97% (14 tests covering WWN/serial/path matching, NVMe fallback)
- UpdateQueueSnapshot: 57%→100% (5 tests covering nil, gauges, stale key cleanup)
- UpdateDeadLetterCounts: 52%→100% (7 tests covering aggregation, normalization)
- templateFuncMap: 20%→100% (8 tests covering all template helper functions)

Monitoring 44.6%→45.3%, notifications 45.7%→45.9%
2025-12-01 18:14:43 +00:00
rcourtman
0803951854 test: Add tests for getInstanceConfig, baseIntervalForInstanceType, LoadOIDCConfig
- getInstanceConfig: 33%→100% (nil handling, case-insensitive matching)
- baseIntervalForInstanceType: 50%→100% (all instance types, clamping)
- LoadOIDCConfig: 35%→94% (file not exist, read errors, decryption)
2025-12-01 18:06:15 +00:00
rcourtman
4defced1a6 test: Add monitoring tests for parseDurationEnv, parseIntEnv, markFailed, logNodeMemorySource
Add comprehensive test coverage for:
- parseDurationEnv: empty/unset env, valid durations, invalid inputs
- parseIntEnv: empty/unset env, valid integers, invalid inputs
- markFailed: status setting, timestamps, failure reason
- logNodeMemorySource: nil handling, source change detection, log levels

All four functions now at 100% coverage (up from 0-78%).
2025-12-01 17:59:20 +00:00
rcourtman
7314510280 test: Add tests for SSH knownhosts error and path methods
- HostKeyChangeError.Error(): message formatting
- HostKeyChangeError.Unwrap(): error chain verification
- manager.Path(): path retrieval
- HostFieldMatches(): host matching patterns

ssh/knownhosts coverage: 72.2% → 75.0%
2025-12-01 17:50:13 +00:00
rcourtman
5d592bf4e6 test: Add tests for diagnostic snapshot recording and retrieval
- recordGuestSnapshot: nil handling, field setting, map initialization
- GetDiagnosticSnapshots: nil/empty handling, sorting verification

Both functions now at 100% coverage.
2025-12-01 17:48:36 +00:00
rcourtman
3de1eafd65 test: Add error path tests for config persistence functions
- LoadAPITokens: invalid JSON, empty file, file not exist
- LoadEmailConfig: invalid JSON, file not exist
- LoadWebhooks: invalid JSON, legacy migration
- LoadNodesConfig: empty arrays, missing fields, corruption recovery
- cleanupOldBackups: non-existent dir, multiple files cleanup
- Bonus: LoadAppriseConfig, LoadAlertConfig, LoadSystemSettings error paths

config package coverage: 46.3% → 48.2%
2025-12-01 17:45:50 +00:00
rcourtman
2158c14cce test: Add comprehensive tests for API token management
- Clone: deep copy verification for pointers and slices
- NewAPITokenRecord/NewHashedAPITokenRecord: creation and validation
- Config methods: HasAPITokens, APITokenCount, ActiveAPITokenHashes
- Config methods: HasAPITokenHash, PrimaryAPITokenHash, PrimaryAPITokenHint
- Config methods: ValidateAPIToken, UpsertAPIToken, RemoveAPIToken, SortAPITokens

config package coverage: 43.5% → 46.3%
2025-12-01 17:37:27 +00:00
rcourtman
d6359276ed test: Add tests for monitoring and notifications functions
- buildCephClusterModel: 0% → 100% (11 test cases)
- collectContainerRootUsage: 0% → 100% (18 test cases)
- NotificationManager getters/setters: 8 functions now tested

Overall coverage: 45.5% → 45.8%
2025-12-01 17:33:36 +00:00
rcourtman
caa33b3140 test: Add tests for checkPMGNodeQueues
- 12 test cases covering per-node queue monitoring
- Tests total/deferred/hold queue thresholds at warning/critical levels
- Tests oldest message age per node
- Tests outlier detection, threshold clearing, existing alert updates
- Tests empty nodes and nil QueueStatus handling

Coverage: checkPMGNodeQueues 0%→85.1%
Package coverage: 70.3%→72.3%
2025-12-01 17:16:32 +00:00
rcourtman
5f85f4e5ac test: Add tests for checkZFSPoolHealth
- 14 test cases covering pool state alerts (ONLINE, DEGRADED, FAULTED,
  UNAVAIL), pool error tracking, device-level alerts, state transitions
- Tests pool state clearing on recovery, error count updates,
  SPARE device handling, FAULTED device critical alerts

Coverage: checkZFSPoolHealth 0%→100%
Package coverage: 68.6%→70.3%
2025-12-01 17:14:12 +00:00
rcourtman
e3b8a00fe4 test: Add tests for checkEscalations and CleanupAlertsForNodes
- checkEscalations: 6 test cases covering disabled/enabled states,
  acknowledged alerts, threshold timing, multi-level escalation
- CleanupAlertsForNodes: 7 test cases covering node removal,
  Docker/PBS alert preservation, empty node handling, nil safety

Coverage: checkEscalations 0%→100%, CleanupAlertsForNodes 0%→92%
Package coverage: 67.6%→68.6%
2025-12-01 17:11:47 +00:00
rcourtman
1aa5eeb0cb test: Add tests for Cleanup and convertLegacyThreshold
- Cleanup: 16 test cases covering auto-acknowledge, TTL cleanup,
  rate limit entries, suppressions, pending alerts, flapping history,
  Docker restart tracking, PMG anomaly trackers, quarantine history
- convertLegacyThreshold: 5 test cases covering nil/zero/negative input,
  default margin, custom margin

Coverage: Cleanup 0%→97.6%, convertLegacyThreshold 0%→83.3%
Package coverage: 65.4%→67.6%
2025-12-01 17:08:45 +00:00
rcourtman
24c44c8e5a test: Add tests for checkStorageOffline and checkGuestPoweredOff
- checkStorageOffline: 5 test cases covering confirmation polling,
  alert creation, LastSeen updates, disabled storage handling
- checkGuestPoweredOff: 9 test cases covering confirmation polling,
  alert creation, severity overrides, disabled guests, monitorOnly flag

Coverage: checkStorageOffline 0%→100%, checkGuestPoweredOff 0%→100%
Package coverage: 63.4%→65.4%

Note: Pre-existing test failure in suite related to /etc/pulse file
access - not caused by these changes.
2025-12-01 17:05:15 +00:00
rcourtman
6806512ef1 test: Add tests for checkPMGQueueDepths and checkPMGOldestMessage
- checkPMGQueueDepths: 10 test cases covering total/deferred/hold queues
  at warning/critical levels, existing alert updates, threshold clearing
- checkPMGOldestMessage: 8 test cases covering threshold logic,
  multi-node oldest detection, alert creation/updates/clearing

Coverage: checkPMGQueueDepths 0%→88.1%, checkPMGOldestMessage 0%→100%
Package coverage: 61.3%→63.4%
2025-12-01 16:59:59 +00:00
rcourtman
b7c08ca6e1 test: Add tests for calculateTrimmedBaseline and createOrUpdateNodeAlert
- calculateTrimmedBaseline: 8 test cases covering sample count thresholds,
  trimmed mean calculation, median fallback logic, odd-length arrays
- createOrUpdateNodeAlert: 2 test cases for new alert creation and
  existing alert updates

Coverage: calculateTrimmedBaseline 0%→96.9%, createOrUpdateNodeAlert 0%→100%
Package coverage: 59.6%→61.3%
2025-12-01 16:56:14 +00:00
rcourtman
34b4a0d50c test: Add tests for checkPBSOffline and checkPMGOffline functions
checkPBSOffline (0%→100%):
- Override Disabled clears alert and returns
- Override DisableConnectivity clears alert and returns
- Insufficient confirmations waits
- Creates alert after 3 confirmations
- Existing alert updates LastSeen

checkPMGOffline (0%→100%):
- Override Disabled clears alert and returns
- Override DisableConnectivity clears alert and returns
- Insufficient confirmations waits
- Creates alert after 3 confirmations
- Existing alert updates LastSeen

Coverage: 58.6% → 59.6%
2025-12-01 16:50:18 +00:00
rcourtman
42ded0dd23 test: Add tests for checkNodeOffline function
checkNodeOffline (0%→100%):
- Override DisableConnectivity clears alert and returns
- Existing alert updates StartTime
- Insufficient confirmations waits (1, 2 confirmations)
- Creates alert after 3 confirmations with correct metadata
- Alert added to history

Coverage: 58.5% → 58.6%
2025-12-01 16:48:13 +00:00
rcourtman
785a03ea77 test: Add tests for offline alert clearing functions
clearNodeOfflineAlert (0%→100%):
- No alert and no count is no-op
- Resets offline count when node comes online
- Clears existing alert and adds to resolved

clearPBSOfflineAlert (0%→100%):
- No alert and no count is no-op
- Resets offline confirmation count
- Clears existing alert and adds to resolved

clearPMGOfflineAlert (0%→100%):
- No alert and no count is no-op
- Resets offline confirmation count
- Clears existing alert and adds to resolved

Coverage: 57.4% → 58.5%
2025-12-01 16:45:51 +00:00
rcourtman
b9e49a26c4 test: Add tests for alert utility functions
SetMetricHooks (0%→100%):
- Sets all four hooks correctly
- Nil hooks are safely handled
- Properly saves/restores state to avoid test pollution

NotifyExistingAlert (0%→100%):
- Non-existent alert is no-op
- Existing alert dispatches async notification

GetResolvedAlert (0%→100%):
- Returns nil for non-existent alert
- Returns nil for nil resolved entry
- Returns nil when Alert is nil
- Returns cloned alert with resolved time

GetAlertHistory/GetAlertHistorySince (0%→100%):
- Returns history from history manager
- Respects limit parameter
- Zero time returns all history
- Filters by time correctly

ClearAlertHistory (0%→100%):
- Clears all history entries

Coverage: 56.9% → 57.4%
2025-12-01 16:43:04 +00:00
rcourtman
5c584b9eee test: Add comprehensive tests for HandleDockerHostOffline
HandleDockerHostOffline (0%→100%):
- Empty host ID is no-op
- Disabled alerts is no-op
- DisableAllDockerHostsOffline clears tracking and alert
- Override DisableConnectivity clears tracking and alert
- Existing alert updates LastSeen
- Requires 3 confirmations before alert
- Alert has correct metadata (resourceType, hostId, agentId)

Coverage: 55.6% → 56.9%
2025-12-01 16:39:10 +00:00
rcourtman
7bac96d60b test: Add comprehensive tests for HandleHostRemoved, ReevaluateGuestAlert
HandleHostRemoved (0%→100%):
- Empty host ID is no-op
- Clears host offline alert and confirmations
- Clears host metric alerts (CPU, memory)
- Clears host disk alerts
- Clears all alert types together

ReevaluateGuestAlert (0%→100%):
- No active alerts is no-op
- Clears alert when threshold disabled (nil)
- Clears alert when trigger is zero
- Clears alert when value below clear threshold
- Clears alert when value below trigger threshold
- Keeps alert when value above both thresholds
- Processes all metric types (7 types)
- Clears pending alert when threshold disabled
- Uses clear equals trigger when clear is zero
- Ignores alerts for different guests

NormalizeMetricTimeThresholds (0%→100%):
- Updated existing test to call public wrapper instead of internal function

Coverage: 54.6% → 55.6%
2025-12-01 16:36:48 +00:00
rcourtman
65e5eb84ae test: Add comprehensive tests for reevaluateActiveAlertsLocked
Tests major branches for alert re-evaluation on config change:
- Empty alerts map (no-op)
- Alert ID with insufficient parts (skipped)
- DisableAllPMG resolves PMG queue alerts
- DisableAllHosts resolves Host alerts via resourceType metadata
- Docker host offline alerts are skipped (not threshold-based)
- DisableAllDockerHosts resolves dockerhost metric alerts
- DisableAllNodes resolves Node alerts via Instance field
- DisableAllStorage resolves Storage alerts
- DisableAllPBS resolves PBS alerts
- DisableAllGuests resolves Guest alerts
- Disabled override resolves alert
- Alert below clear threshold is resolved
- Alert between clear and trigger is resolved on config change

Coverage improvement:
- reevaluateActiveAlertsLocked: 59.8% → 81.2%
- alerts package: 54.0% → 54.6%
2025-12-01 16:31:05 +00:00
rcourtman
46eccd561a test: Add comprehensive tests for HandleHostOffline function
Tests all branches:
- Empty host ID returns early
- Alerts disabled returns early
- DisableAllHostsOffline clears alert and confirmation tracking
- Override DisableConnectivity clears alert and returns
- Override Disabled clears alert and returns
- Existing alert updates LastSeen only
- Insufficient confirmations waits for more
- Sufficient confirmations (3) creates alert with metadata

Coverage improvement:
- HandleHostOffline: 64.0% → 100%
- alerts package: 53.5% → 54.0%
2025-12-01 16:26:56 +00:00
rcourtman
1647b232db test: Add comprehensive tests for applyGlobalOfflineSettingsLocked
Tests all 7 disable settings branches:
- DisableAllNodesOffline: clears node-offline-* alerts and nodeOfflineCount
- DisableAllPBSOffline: clears pbs-offline-* alerts and offlineConfirmations
- DisableAllGuestsOffline: clears guest-powered-off-* alerts and offlineConfirmations
- DisableAllDockerHostsOffline: clears docker-host-offline-* alerts and dockerOfflineCount
- DisableAllDockerContainers: clears docker-container-* alerts and tracking state
- DisableAllDockerServices: clears docker-service-* alerts
- No settings enabled: verifies no-op behavior

Coverage improvement:
- applyGlobalOfflineSettingsLocked: 57.1% → 100%
- alerts package: 53.0% → 53.5%
2025-12-01 16:23:45 +00:00
rcourtman
a4008f914f test: Add comprehensive tests for alert clearing functions
- TestClearBackupAlertsLocked: tests backup-age alert clearing with nil handling
- TestClearBackupAlerts: tests public wrapper function
- TestClearSnapshotAlertsForInstanceLocked: tests instance-specific snapshot clearing
- TestClearSnapshotAlertsForInstance: tests public wrapper function

Coverage improvement:
- clearBackupAlertsLocked: 75% → 100%
- clearBackupAlerts: 0% → 100%
- clearSnapshotAlertsForInstanceLocked: 50% → 100%
- clearSnapshotAlertsForInstance: 0% → 100%
- alerts package: 52.8% → 53.0%
2025-12-01 16:20:49 +00:00