Improve portable launch, forge persistence, and operator auth UX.
Persist build extra_files for Build Manager history, print dashboard login on every start, add libp2p for Mesh P2P forge, defer WebSocket until login, and split devrun.bat from LAUNCH.bat with USB deck auto-detection.
This commit is contained in:
74
agent/miner/pool_guard_test.go
Normal file
74
agent/miner/pool_guard_test.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package miner
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"crypto-miner-agent/config"
|
||||
"crypto-miner-agent/stats"
|
||||
)
|
||||
|
||||
func TestPoolResourcesOKBlocksHighMinFreeRAM(t *testing.T) {
|
||||
r := stats.NewReporter()
|
||||
free := r.FreeMemoryMB()
|
||||
if free == 0 {
|
||||
t.Skip("free memory unavailable on this platform")
|
||||
}
|
||||
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
|
||||
MiningMode: "always",
|
||||
MinFreeRAM: int(free + 1_000_000),
|
||||
MaxCPUUsage: 0,
|
||||
MaxMemoryPct: 0,
|
||||
}}
|
||||
p := NewPool(1, cfg, r, nil)
|
||||
if p.resourcesOK() {
|
||||
t.Fatal("MinFreeRAM above available free RAM should block mining")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoolResourcesOKBlocksLowMaxMemoryPct(t *testing.T) {
|
||||
r := stats.NewReporter()
|
||||
total := r.TotalMemoryMB()
|
||||
if total == 0 {
|
||||
t.Skip("total memory unavailable on this platform")
|
||||
}
|
||||
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
|
||||
MiningMode: "always",
|
||||
MaxMemoryPct: 1,
|
||||
MaxCPUUsage: 0,
|
||||
MinFreeRAM: 0,
|
||||
}}
|
||||
p := NewPool(1, cfg, r, nil)
|
||||
if p.resourcesOK() {
|
||||
t.Fatal("MaxMemoryPct=1 should block when system memory use exceeds 1%")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoolResourcesOKAllowsHighMaxCPU(t *testing.T) {
|
||||
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
|
||||
MiningMode: "always",
|
||||
MaxCPUUsage: 100,
|
||||
MinFreeRAM: 0,
|
||||
}}
|
||||
p := NewPool(1, cfg, stats.NewReporter(), nil)
|
||||
if !p.resourcesOK() {
|
||||
t.Fatal("MaxCPUUsage=100 should allow mining when CPU is at most 100%")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoolMiningAllowedRequiresResourcesAndSchedule(t *testing.T) {
|
||||
r := stats.NewReporter()
|
||||
free := r.FreeMemoryMB()
|
||||
if free == 0 {
|
||||
t.Skip("free memory unavailable on this platform")
|
||||
}
|
||||
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
|
||||
MiningMode: "always",
|
||||
MinFreeRAM: int(free + 1_000_000),
|
||||
MaxCPUUsage: 0,
|
||||
MaxMemoryPct: 0,
|
||||
}}
|
||||
p := NewPool(1, cfg, r, nil)
|
||||
if p.miningAllowed() {
|
||||
t.Fatal("miningAllowed should deny when resource guard fails even in always mode")
|
||||
}
|
||||
}
|
||||
@@ -147,3 +147,102 @@ func TestStratumMsgJobNotification(t *testing.T) {
|
||||
t.Fatalf("job notification: %+v", sj)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildStratumEndpointsMultipleBackups(t *testing.T) {
|
||||
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
|
||||
PoolHost: "primary.pool",
|
||||
PoolPort: 3333,
|
||||
BackupPools: []config.BackupPool{
|
||||
{Host: "backup1.pool", Port: 4444, Pass: "a"},
|
||||
{Host: "backup2.pool", Port: 5555, TLS: true},
|
||||
},
|
||||
}}
|
||||
eps := buildStratumEndpoints(cfg)
|
||||
if len(eps) != 3 {
|
||||
t.Fatalf("expected primary + 2 backups, got %d", len(eps))
|
||||
}
|
||||
if eps[2].Host != "backup2.pool" || eps[2].Port != 5555 || !eps[2].TLS {
|
||||
t.Fatalf("third endpoint mismatch: %+v", eps[2])
|
||||
}
|
||||
}
|
||||
|
||||
func TestStratumLoginErrorResponse(t *testing.T) {
|
||||
line := `{"id":1,"jsonrpc":"2.0","error":{"code":-1,"message":"invalid wallet"}}`
|
||||
var loginResp stratumMsg
|
||||
if err := json.Unmarshal([]byte(line), &loginResp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if loginResp.Error == nil {
|
||||
t.Fatal("expected login error field")
|
||||
}
|
||||
if loginResp.Result != nil {
|
||||
t.Fatal("error response should not carry a result")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStratumKeepaliveMsgRoundTrip(t *testing.T) {
|
||||
params := mustMarshal(map[string]string{"id": "sess-abc"})
|
||||
msg := stratumMsg{ID: 3, JSONRPC: "2.0", Method: "keepalived", Params: params}
|
||||
b, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var decoded stratumMsg
|
||||
if err := json.Unmarshal(b, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if decoded.Method != "keepalived" || decoded.JSONRPC != "2.0" {
|
||||
t.Fatalf("keepalive msg: %+v", decoded)
|
||||
}
|
||||
var p map[string]string
|
||||
if err := json.Unmarshal(decoded.Params, &p); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if p["id"] != "sess-abc" {
|
||||
t.Fatalf("keepalive params: %v", p)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStratumSubmitRequestRoundTrip(t *testing.T) {
|
||||
params, err := json.Marshal(submitParams{
|
||||
ID: "sess-1", JobID: "42", Nonce: "04030201", Hash: "deadbeef",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
msg := stratumMsg{ID: 4, JSONRPC: "2.0", Method: "submit", Params: params}
|
||||
b, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var decoded stratumMsg
|
||||
if err := json.Unmarshal(b, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if decoded.Method != "submit" {
|
||||
t.Fatalf("method=%q", decoded.Method)
|
||||
}
|
||||
var sp submitParams
|
||||
if err := json.Unmarshal(decoded.Params, &sp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if sp.ID != "sess-1" || sp.JobID != "42" || sp.Nonce != "04030201" || sp.Hash != "deadbeef" {
|
||||
t.Fatalf("submit params: %+v", sp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStratumJobParamsInvalidJSON(t *testing.T) {
|
||||
msg := stratumMsg{Method: "job", Params: json.RawMessage(`{"blob":`)}
|
||||
var sj stratumJob
|
||||
if err := json.Unmarshal(msg.Params, &sj); err == nil {
|
||||
t.Fatal("malformed job params should fail unmarshal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStratumLineInvalidJSONIgnored(t *testing.T) {
|
||||
line := "not-json\n"
|
||||
var msg stratumMsg
|
||||
if err := json.Unmarshal([]byte(line), &msg); err == nil {
|
||||
t.Fatal("invalid stratum line should not parse as msg")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user