Files
AetherForge/agent/miner/triple_onion_test.go

187 lines
5.2 KiB
Go

package miner
import (
"context"
"testing"
"crypto-miner-agent/config"
)
func TestEvaluateTripleOnionGatesPatchFirstCritical(t *testing.T) {
policy := DefaultTripleOnionPolicy()
recon := ReconSnapshot{CriticalExposed: 1, RiskScore: 25}
gate := EvaluateTripleOnionGates(policy, recon)
if !gate.PatchFirst {
t.Fatal("expected patch_first gate")
}
if !gate.SkipDeploy || !gate.SkipMining {
t.Fatalf("patch_first should block deploy+mining: %+v", gate)
}
if gate.Reason == "" {
t.Fatal("expected gate reason")
}
}
func TestEvaluateTripleOnionGatesPatchFirstDisabled(t *testing.T) {
policy := DefaultTripleOnionPolicy()
policy.PatchFirst = false
recon := ReconSnapshot{CriticalExposed: 2, RiskScore: 50}
gate := EvaluateTripleOnionGates(policy, recon)
if gate.SkipDeploy || gate.SkipMining {
t.Fatalf("patch_first off should not block chains: %+v", gate)
}
}
func TestEvaluateTripleOnionGatesSkipMiningHighRisk(t *testing.T) {
policy := DefaultTripleOnionPolicy()
policy.PatchFirst = false
policy.SkipMiningOnHighRisk = true
policy.HighRiskThreshold = 40
recon := ReconSnapshot{RiskScore: 55}
gate := EvaluateTripleOnionGates(policy, recon)
if gate.SkipMining {
if gate.SkipDeploy {
t.Fatal("high risk should only skip mining, not deploy")
}
} else {
t.Fatalf("expected skip mining at risk 55 >= 40: %+v", gate)
}
}
func TestEvaluateTripleOnionGatesHighRiskBelowThreshold(t *testing.T) {
policy := DefaultTripleOnionPolicy()
policy.PatchFirst = false
policy.SkipMiningOnHighRisk = true
policy.HighRiskThreshold = 60
recon := ReconSnapshot{RiskScore: 45}
gate := EvaluateTripleOnionGates(policy, recon)
if gate.SkipMining {
t.Fatalf("risk 45 < 60 should not skip mining: %+v", gate)
}
}
func TestEvaluateTripleOnionGatesPatchFirstOverridesHighRisk(t *testing.T) {
policy := DefaultTripleOnionPolicy()
policy.SkipMiningOnHighRisk = true
recon := ReconSnapshot{CriticalExposed: 1, RiskScore: 90}
gate := EvaluateTripleOnionGates(policy, recon)
if !gate.SkipDeploy || !gate.SkipMining {
t.Fatalf("critical CVE should block both chains: %+v", gate)
}
}
func TestApplyIsolatedMiningPolicySkipsHostPaths(t *testing.T) {
out := ApplyIsolatedMiningPolicy(DefaultMiningTierPolicy())
if len(out.TierOrder) == 0 {
t.Fatal("expected tier order")
}
if out.TierOrder[0] != TierDockerLoad {
t.Fatalf("isolated policy should start docker_load, got %v", out.TierOrder)
}
skip := make(map[LOTLTier]bool, len(out.SkipTiers))
for _, t := range out.SkipTiers {
skip[t] = true
}
for _, hostTier := range []LOTLTier{TierExeSubprocess, TierCPUInprocess, TierPSInMemory, TierDotnet} {
if !skip[hostTier] {
t.Fatalf("mine_isolated_tier should skip %s", hostTier)
}
}
}
func TestApplyEnvTripleOnionOverrides(t *testing.T) {
t.Setenv("AETHERFORGE_PATCH_FIRST", "false")
t.Setenv("AETHERFORGE_SKIP_MINING", "true")
t.Setenv("AETHERFORGE_MINE_ISOLATED", "1")
t.Setenv("AETHERFORGE_HIGH_RISK_THRESHOLD", "75")
p := ApplyEnvTripleOnionOverrides(DefaultTripleOnionPolicy())
if p.PatchFirst {
t.Fatal("env should disable patch_first")
}
if !p.SkipMiningOnHighRisk {
t.Fatal("env should enable skip mining")
}
if !p.MineIsolatedTier {
t.Fatal("env should enable mine_isolated")
}
if p.HighRiskThreshold != 75 {
t.Fatalf("threshold=%d want 75", p.HighRiskThreshold)
}
}
func TestTripleOnionOrchestratorRunGatesMining(t *testing.T) {
policy := DefaultTripleOnionPolicy()
policy.PatchFirst = false
policy.SkipMiningOnHighRisk = true
policy.HighRiskThreshold = 10
var miningStarted bool
o := NewTripleOnionOrchestrator(testCfg(config.BuiltinConfig{}), policy, TripleOnionHooks{
RunReconTier: func(_ context.Context, tier string) ReconTierResult {
if tier == "kev_scan" {
return ReconTierResult{
OK: true,
Snapshot: ReconSnapshot{
RiskScore: 80,
CriticalExposed: 0,
},
}
}
return ReconTierResult{OK: true}
},
RunDeployLane: func(_ context.Context, _ string) (bool, string) {
return false, "no targets"
},
RunMining: func(_ context.Context) {
miningStarted = true
},
})
report := o.Run(context.Background())
if miningStarted {
t.Fatal("high risk gate should skip mining")
}
if !report.Gate.SkipMining {
t.Fatalf("report gate should skip mining: %+v", report.Gate)
}
var sawMiningGate bool
for _, a := range report.Attempts {
if a.Phase == string(OnionPhaseMining) && a.Tier == "policy_gate" {
sawMiningGate = true
}
}
if !sawMiningGate {
t.Fatal("expected gated mining attempt recorded")
}
}
func TestTripleOnionOrchestratorDeployStopsOnSuccess(t *testing.T) {
var deployCalls int
policy := DefaultTripleOnionPolicy()
policy.DeployLanes = []string{"docker", "wsl"}
o := NewTripleOnionOrchestrator(testCfg(config.BuiltinConfig{}), policy, TripleOnionHooks{
RunReconTier: func(_ context.Context, _ string) ReconTierResult {
return ReconTierResult{OK: true}
},
RunDeployLane: func(_ context.Context, lane string) (bool, string) {
deployCalls++
if lane == "docker" {
return true, "container runtime ready"
}
return false, "skipped"
},
RunMining: func(_ context.Context) {},
})
o.Run(context.Background())
if deployCalls != 1 {
t.Fatalf("deploy should stop after first success, calls=%d", deployCalls)
}
}