1798fc6804
Machine status probe on page load: - POST /api/machines/refresh probes all machines in parallel (max 20 concurrent, 1.5s timeout) - Updates DB status and broadcasts via SSE to all connected browser tabs - Server-side throttle: ignores refresh requests within 10s - Machines.tsx and Dashboard.tsx fire probe on mount - Visual "Checking machine status..." indicator in Machines table - MachineHandler now accepts *Engine for ProbeAllMachines access
67 lines
1.6 KiB
Go
67 lines
1.6 KiB
Go
package syncengine
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/syncserver/internal/wol"
|
|
)
|
|
|
|
func TestIsReachable(t *testing.T) {
|
|
ln, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 0})
|
|
if err != nil {
|
|
t.Skipf("skipping test (no TCP listener available): %v", err)
|
|
}
|
|
defer ln.Close()
|
|
addr := ln.Addr().(*net.TCPAddr)
|
|
|
|
ctx := context.Background()
|
|
|
|
if !wol.IsReachable(ctx, "127.0.0.1", addr.Port, 500*time.Millisecond) {
|
|
t.Error("expected reachable on listening port")
|
|
}
|
|
if wol.IsReachable(ctx, "127.0.0.1", addr.Port+1, 500*time.Millisecond) {
|
|
t.Error("expected unreachable on non-listening port")
|
|
}
|
|
}
|
|
|
|
func TestIsReachableTimeout(t *testing.T) {
|
|
ctx := context.Background()
|
|
start := time.Now()
|
|
if wol.IsReachable(ctx, "192.0.2.1", 12345, 500*time.Millisecond) {
|
|
t.Error("expected unreachable for non-routable IP")
|
|
}
|
|
if d := time.Since(start); d < 400*time.Millisecond {
|
|
t.Errorf("IsReachable returned too early: %v", d)
|
|
}
|
|
}
|
|
|
|
func TestProbeThrottle(t *testing.T) {
|
|
e := &Engine{lastProbeAt: atomic.Int64{}}
|
|
|
|
e.lastProbeAt.Store(time.Now().UnixNano())
|
|
|
|
now := time.Now().UnixNano()
|
|
last := e.lastProbeAt.Load()
|
|
if now-last < int64(probeThrottleSeconds*time.Second) {
|
|
return
|
|
}
|
|
t.Error("throttle check did not run as expected")
|
|
}
|
|
|
|
func TestProbeConstants(t *testing.T) {
|
|
if probeThrottleSeconds != 10 {
|
|
t.Errorf("probeThrottleSeconds = %d, want 10", probeThrottleSeconds)
|
|
}
|
|
if probeTimeout != 1500*time.Millisecond {
|
|
t.Errorf("probeTimeout = %v, want 1500ms", probeTimeout)
|
|
}
|
|
if probeMaxConcurrent != 20 {
|
|
t.Errorf("probeMaxConcurrent = %d, want 20", probeMaxConcurrent)
|
|
}
|
|
}
|
|
|