Adds hundreds of unit/integration/e2e tests, fixes WS bcrypt auth, config merge, fleet analytics, agent schedule/log tail, and documents stale PROBLEMS items. Updates PROBLEMS.md, README, and test scripts; ignores local spread-kits and coverage dirs.
130 lines
3.4 KiB
Go
130 lines
3.4 KiB
Go
package client
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"crypto-miner-agent/config"
|
|
)
|
|
|
|
func TestBuildServerURLListDedupes(t *testing.T) {
|
|
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
|
|
ServerURL: "https://primary.example",
|
|
BackupServerURLs: []string{"https://backup.example", "https://primary.example", " "},
|
|
}}
|
|
urls := buildServerURLList(cfg)
|
|
if len(urls) != 2 {
|
|
t.Fatalf("expected 2 urls, got %v", urls)
|
|
}
|
|
if urls[0] != "https://primary.example" || urls[1] != "https://backup.example" {
|
|
t.Fatalf("unexpected order: %v", urls)
|
|
}
|
|
}
|
|
|
|
func TestBuildServerURLListEmptyFallback(t *testing.T) {
|
|
cfg := config.RuntimeConfig{}
|
|
urls := buildServerURLList(cfg)
|
|
if len(urls) != 1 || urls[0] != "" {
|
|
t.Fatalf("expected single empty fallback, got %v", urls)
|
|
}
|
|
}
|
|
|
|
func TestBuildWSURL(t *testing.T) {
|
|
cases := []struct {
|
|
in, want string
|
|
err bool
|
|
}{
|
|
{"https://hub.example/", "wss://hub.example/ws/agent", false},
|
|
{"http://hub.example:8080", "ws://hub.example:8080/ws/agent", false},
|
|
{"hub.example", "ws://hub.example/ws/agent", false},
|
|
{"wss://hub.example/extra/", "wss://hub.example/extra/ws/agent", false},
|
|
{"ftp://hub.example", "", true},
|
|
}
|
|
for _, tc := range cases {
|
|
got, err := buildWSURL(tc.in)
|
|
if tc.err {
|
|
if err == nil {
|
|
t.Fatalf("%q: expected error", tc.in)
|
|
}
|
|
continue
|
|
}
|
|
if err != nil {
|
|
t.Fatalf("%q: %v", tc.in, err)
|
|
}
|
|
if got != tc.want {
|
|
t.Fatalf("%q: got %q want %q", tc.in, got, tc.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFormatCmdErr(t *testing.T) {
|
|
got := formatCmdErr(os.ErrPermission, []byte("denied"))
|
|
if !strings.Contains(got, "permission denied") || !strings.Contains(got, "denied") {
|
|
t.Fatalf("unexpected: %q", got)
|
|
}
|
|
}
|
|
|
|
func TestReadLogTailDisabled(t *testing.T) {
|
|
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
|
|
FileLogging: false,
|
|
StealthMode: true,
|
|
}}
|
|
_, err := readLogTail(cfg, 50)
|
|
if err == nil || !strings.Contains(err.Error(), "logging disabled") {
|
|
t.Fatalf("expected disabled error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestReadLogTailFromInstallDir(t *testing.T) {
|
|
dir := t.TempDir()
|
|
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
|
|
FileLogging: true,
|
|
StealthMode: false,
|
|
InstallBase: "custom",
|
|
InstallCustomBase: dir,
|
|
InstallRelativePath: ".",
|
|
}}
|
|
logPath := filepath.Join(dir, "miner.log")
|
|
content := "line1\nline2\nline3\nline4\n"
|
|
if err := os.WriteFile(logPath, []byte(content), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
got, err := readLogTail(cfg, 2)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(got, "line3") || !strings.Contains(got, "line4") {
|
|
t.Fatalf("expected tail lines, got %q", got)
|
|
}
|
|
if strings.Contains(got, "line1") {
|
|
t.Fatal("should not include older lines beyond tail")
|
|
}
|
|
}
|
|
|
|
func TestReadLogTailMissingFile(t *testing.T) {
|
|
dir := t.TempDir()
|
|
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
|
|
FileLogging: true,
|
|
InstallBase: "custom",
|
|
InstallCustomBase: dir,
|
|
InstallRelativePath: ".",
|
|
}}
|
|
_, err := readLogTail(cfg, 10)
|
|
if err == nil || !strings.Contains(err.Error(), "miner.log not found") {
|
|
t.Fatalf("expected not found, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestNewAgentClientDefaults(t *testing.T) {
|
|
cfg := config.RuntimeConfig{AgentID: "agent-1"}
|
|
c := NewAgentClient(cfg)
|
|
if c.agentID != "agent-1" {
|
|
t.Fatalf("agent id %q", c.agentID)
|
|
}
|
|
if c.mesh == nil {
|
|
t.Fatal("mesh node should be initialized")
|
|
}
|
|
}
|