128 lines
3.6 KiB
Go
128 lines
3.6 KiB
Go
//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{
|
|
"<?xml version=\"1.0\"",
|
|
"com.aetherforge.",
|
|
binPath,
|
|
"<key>KeepAlive</key>",
|
|
"<key>RunAtLoad</key>",
|
|
"<true/>",
|
|
"<key>ProcessType</key>",
|
|
"Background",
|
|
}
|
|
for _, s := range requiredStrings {
|
|
if !strings.Contains(content, s) {
|
|
t.Errorf("plist missing %q\ncontent:\n%s", s, content)
|
|
}
|
|
}
|
|
}
|