platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
211
selective-vpn-api/app/transport_policy_apply_health_test.go
Normal file
211
selective-vpn-api/app/transport_policy_apply_health_test.go
Normal file
@@ -0,0 +1,211 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRunTransportPolicyHealthCheckSkipsInactiveDraftClient(t *testing.T) {
|
||||
now := time.Date(2026, time.March, 15, 12, 0, 0, 0, time.UTC)
|
||||
clients := []TransportClient{
|
||||
{
|
||||
ID: "draft-a",
|
||||
Kind: TransportClientSingBox,
|
||||
Enabled: false,
|
||||
Status: TransportClientDown,
|
||||
},
|
||||
}
|
||||
plan := TransportPolicyCompilePlan{
|
||||
Interfaces: []TransportPolicyCompileInterface{
|
||||
{IfaceID: "edge-a", ClientIDs: []string{"draft-a"}},
|
||||
},
|
||||
}
|
||||
|
||||
res, updated, changed := runTransportPolicyHealthCheck(clients, plan, now)
|
||||
if !res.OK {
|
||||
t.Fatalf("expected skipped draft client to keep health-check green: %#v", res)
|
||||
}
|
||||
if res.CheckedCount != 0 || res.FailedCount != 0 {
|
||||
t.Fatalf("unexpected counts: %#v", res)
|
||||
}
|
||||
if len(res.Items) != 1 || res.Items[0].Required {
|
||||
t.Fatalf("expected one skipped item: %#v", res.Items)
|
||||
}
|
||||
if res.InterfaceCount != 1 || len(res.Interfaces) != 1 {
|
||||
t.Fatalf("expected one interface summary: %#v", res)
|
||||
}
|
||||
if !res.Interfaces[0].OK || res.Interfaces[0].CheckedCount != 0 || res.Interfaces[0].SkippedCount != 1 {
|
||||
t.Fatalf("unexpected interface summary: %#v", res.Interfaces[0])
|
||||
}
|
||||
if changed {
|
||||
t.Fatalf("inactive draft client should not mutate health snapshot")
|
||||
}
|
||||
if updated[0].Health.LastCheck != "" {
|
||||
t.Fatalf("unexpected health update for skipped client: %#v", updated[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunTransportPolicyHealthCheckFailsEnabledDownClient(t *testing.T) {
|
||||
now := time.Date(2026, time.March, 15, 12, 0, 0, 0, time.UTC)
|
||||
clients := []TransportClient{
|
||||
{
|
||||
ID: "edge-a-main",
|
||||
Kind: TransportClientSingBox,
|
||||
Enabled: true,
|
||||
Status: TransportClientDown,
|
||||
Config: map[string]any{
|
||||
"runner": "mock",
|
||||
},
|
||||
},
|
||||
}
|
||||
plan := TransportPolicyCompilePlan{
|
||||
Interfaces: []TransportPolicyCompileInterface{
|
||||
{IfaceID: "edge-a", ClientIDs: []string{"edge-a-main"}},
|
||||
},
|
||||
}
|
||||
|
||||
res, updated, changed := runTransportPolicyHealthCheck(clients, plan, now)
|
||||
if res.OK {
|
||||
t.Fatalf("expected enabled down client to fail health-check: %#v", res)
|
||||
}
|
||||
if res.CheckedCount != 1 || res.FailedCount != 1 {
|
||||
t.Fatalf("unexpected counts: %#v", res)
|
||||
}
|
||||
if len(res.Items) != 1 || res.Items[0].Code != "TRANSPORT_POLICY_HEALTH_DOWN" {
|
||||
t.Fatalf("unexpected health-check item: %#v", res.Items)
|
||||
}
|
||||
if res.InterfaceCount != 1 || len(res.Interfaces) != 1 {
|
||||
t.Fatalf("expected one interface summary: %#v", res)
|
||||
}
|
||||
if res.Interfaces[0].OK || res.Interfaces[0].CheckedCount != 1 || res.Interfaces[0].FailedCount != 1 {
|
||||
t.Fatalf("unexpected interface summary: %#v", res.Interfaces[0])
|
||||
}
|
||||
if !changed {
|
||||
t.Fatalf("expected health snapshot to be updated")
|
||||
}
|
||||
if updated[0].Health.LastCheck != now.Format(time.RFC3339) {
|
||||
t.Fatalf("missing health timestamp update: %#v", updated[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunTransportPolicyHealthCheckFailsUnsupportedRuntime(t *testing.T) {
|
||||
now := time.Date(2026, time.March, 15, 12, 0, 0, 0, time.UTC)
|
||||
clients := []TransportClient{
|
||||
{
|
||||
ID: "edge-b-embedded",
|
||||
Kind: TransportClientPhoenix,
|
||||
Enabled: true,
|
||||
Status: TransportClientUp,
|
||||
Config: map[string]any{
|
||||
"runtime_mode": "embedded",
|
||||
},
|
||||
},
|
||||
}
|
||||
plan := TransportPolicyCompilePlan{
|
||||
Interfaces: []TransportPolicyCompileInterface{
|
||||
{IfaceID: "edge-b", ClientIDs: []string{"edge-b-embedded"}},
|
||||
},
|
||||
}
|
||||
|
||||
res, updated, changed := runTransportPolicyHealthCheck(clients, plan, now)
|
||||
if res.OK {
|
||||
t.Fatalf("expected unsupported runtime to fail health-check: %#v", res)
|
||||
}
|
||||
if len(res.Items) != 1 || res.Items[0].Code != "TRANSPORT_BACKEND_RUNTIME_MODE_UNSUPPORTED" {
|
||||
t.Fatalf("unexpected health-check item: %#v", res.Items)
|
||||
}
|
||||
if res.InterfaceCount != 1 || len(res.Interfaces) != 1 {
|
||||
t.Fatalf("expected one interface summary: %#v", res)
|
||||
}
|
||||
if res.Interfaces[0].OK || res.Interfaces[0].CheckedCount != 1 || res.Interfaces[0].FailedCount != 1 {
|
||||
t.Fatalf("unexpected interface summary: %#v", res.Interfaces[0])
|
||||
}
|
||||
if !changed {
|
||||
t.Fatalf("expected unsupported runtime probe to update snapshot")
|
||||
}
|
||||
if updated[0].Status != TransportClientDegraded {
|
||||
t.Fatalf("unexpected degraded status after failed probe: %#v", updated[0])
|
||||
}
|
||||
if updated[0].Health.LastError == "" {
|
||||
t.Fatalf("expected last_error to be persisted after failed probe")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunTransportPolicyHealthCheckBuildsPerInterfaceSummary(t *testing.T) {
|
||||
now := time.Date(2026, time.March, 15, 12, 0, 0, 0, time.UTC)
|
||||
clients := []TransportClient{
|
||||
{
|
||||
ID: "edge-a-main",
|
||||
Kind: TransportClientSingBox,
|
||||
Enabled: true,
|
||||
Status: TransportClientUp,
|
||||
Config: map[string]any{
|
||||
"runner": "mock",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "edge-a-draft",
|
||||
Kind: TransportClientSingBox,
|
||||
Enabled: false,
|
||||
Status: TransportClientDown,
|
||||
},
|
||||
{
|
||||
ID: "edge-b-main",
|
||||
Kind: TransportClientPhoenix,
|
||||
Enabled: true,
|
||||
Status: TransportClientUp,
|
||||
Config: map[string]any{
|
||||
"runtime_mode": "embedded",
|
||||
},
|
||||
},
|
||||
}
|
||||
plan := TransportPolicyCompilePlan{
|
||||
Interfaces: []TransportPolicyCompileInterface{
|
||||
{
|
||||
IfaceID: "edge-a",
|
||||
Mode: "dedicated",
|
||||
RuntimeIface: "tun-a",
|
||||
NetnsName: "svpn-edge-a",
|
||||
RoutingTable: "agvpn_if_edge_a",
|
||||
ClientIDs: []string{"edge-a-main", "edge-a-draft"},
|
||||
},
|
||||
{
|
||||
IfaceID: "edge-b",
|
||||
Mode: "dedicated",
|
||||
RuntimeIface: "tun-b",
|
||||
RoutingTable: "agvpn_if_edge_b",
|
||||
ClientIDs: []string{"edge-b-main"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
res, _, _ := runTransportPolicyHealthCheck(clients, plan, now)
|
||||
if res.InterfaceCount != 2 || len(res.Interfaces) != 2 {
|
||||
t.Fatalf("expected two interface summaries: %#v", res)
|
||||
}
|
||||
|
||||
ifaceA := res.Interfaces[0]
|
||||
if ifaceA.IfaceID != "edge-a" || !ifaceA.OK || ifaceA.ClientCount != 2 || ifaceA.CheckedCount != 1 || ifaceA.SkippedCount != 1 {
|
||||
t.Fatalf("unexpected edge-a summary: %#v", ifaceA)
|
||||
}
|
||||
if ifaceA.RuntimeIface != "tun-a" || ifaceA.NetnsName != "svpn-edge-a" || ifaceA.RoutingTable != "agvpn_if_edge_a" {
|
||||
t.Fatalf("edge-a runtime metadata missing: %#v", ifaceA)
|
||||
}
|
||||
if ifaceA.ActiveClientID != "edge-a-main" || ifaceA.Status != string(TransportClientUp) {
|
||||
t.Fatalf("edge-a runtime status fields mismatch: %#v", ifaceA)
|
||||
}
|
||||
|
||||
ifaceB := res.Interfaces[1]
|
||||
if ifaceB.IfaceID != "edge-b" || ifaceB.OK || ifaceB.ClientCount != 1 || ifaceB.CheckedCount != 1 || ifaceB.FailedCount != 1 {
|
||||
t.Fatalf("unexpected edge-b summary: %#v", ifaceB)
|
||||
}
|
||||
if ifaceB.RuntimeIface != "tun-b" || ifaceB.RoutingTable != "agvpn_if_edge_b" {
|
||||
t.Fatalf("edge-b runtime metadata missing: %#v", ifaceB)
|
||||
}
|
||||
if ifaceB.ActiveClientID != "edge-b-main" || ifaceB.Status != string(TransportClientDegraded) {
|
||||
t.Fatalf("edge-b runtime status fields mismatch: %#v", ifaceB)
|
||||
}
|
||||
if ifaceB.LastError == "" {
|
||||
t.Fatalf("edge-b expected last_error from degraded probe: %#v", ifaceB)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user