From 8775947341b680d7c822a4e9799214f6dde61c88 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Apr 2026 13:23:22 +0100 Subject: [PATCH] ax(node): complete HandleGetStats test triple with Bad and Ugly cases TestWorker_HandleGetStats_Bad and TestWorker_HandleGetStats_Ugly were missing; AX requires all three categories mandatory per function. Bad covers uninitialised identity, Ugly covers failed miner stat collection. Co-Authored-By: Charon --- pkg/node/worker_test.go | 96 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/pkg/node/worker_test.go b/pkg/node/worker_test.go index fdb8ac4..34b0adc 100644 --- a/pkg/node/worker_test.go +++ b/pkg/node/worker_test.go @@ -308,6 +308,90 @@ func TestWorker_HandleGetStats_Good(t *testing.T) { } } +func TestWorker_HandleGetStats_Bad(t *testing.T) { + tmpDir := t.TempDir() + // Identity deliberately not generated — worker must return error + nodeManager, err := NewNodeManagerWithPaths( + tmpDir+"/private.key", + tmpDir+"/node.json", + ) + if err != nil { + t.Fatalf("failed to create node manager: %v", err) + } + + peerRegistry, err := NewPeerRegistryWithPath(t.TempDir() + "/peers.json") + if err != nil { + t.Fatalf("failed to create peer registry: %v", err) + } + + transport := NewTransport(nodeManager, peerRegistry, DefaultTransportConfig()) + worker := NewWorker(nodeManager, transport) + + msg, err := NewMessage(MsgGetStats, "sender-id", "uninitialised-id", nil) + if err != nil { + t.Fatalf("failed to create get_stats message: %v", err) + } + + _, err = worker.handleGetStats(msg) + if err == nil { + t.Error("expected error when node identity is not initialised") + } +} + +func TestWorker_HandleGetStats_Ugly(t *testing.T) { + tmpDir := t.TempDir() + nodeManager, err := NewNodeManagerWithPaths( + tmpDir+"/private.key", + tmpDir+"/node.json", + ) + if err != nil { + t.Fatalf("failed to create node manager: %v", err) + } + if err := nodeManager.GenerateIdentity("test-worker", RoleWorker); err != nil { + t.Fatalf("failed to generate identity: %v", err) + } + + peerRegistry, err := NewPeerRegistryWithPath(t.TempDir() + "/peers.json") + if err != nil { + t.Fatalf("failed to create peer registry: %v", err) + } + + transport := NewTransport(nodeManager, peerRegistry, DefaultTransportConfig()) + worker := NewWorker(nodeManager, transport) + + // Miner manager returns stats errors — handleGetStats must skip failed miners and still succeed + failingManager := &mockMinerManager{ + miners: []MinerInstance{&mockFailingMinerInstance{name: "broken", minerType: "xmrig"}}, + } + worker.SetMinerManager(failingManager) + + identity := nodeManager.GetIdentity() + if identity == nil { + t.Fatal("expected identity to be generated") + } + msg, err := NewMessage(MsgGetStats, "sender-id", identity.ID, nil) + if err != nil { + t.Fatalf("failed to create get_stats message: %v", err) + } + + response, err := worker.handleGetStats(msg) + if err != nil { + t.Fatalf("handleGetStats should not fail when a miner stat fetch fails: %v", err) + } + if response == nil { + t.Fatal("expected a response even when miner stats fail") + } + + var stats StatsPayload + if err := response.ParsePayload(&stats); err != nil { + t.Fatalf("failed to parse stats payload: %v", err) + } + // Broken miner is skipped — miners list is empty + if len(stats.Miners) != 0 { + t.Errorf("expected 0 miners (failed stat skipped), got %d", len(stats.Miners)) + } +} + func TestWorker_HandleStartMiner_Bad(t *testing.T) { cleanup := setupTestEnv(t) defer cleanup() @@ -588,6 +672,18 @@ func (m *mockMinerInstance) GetType() string { return m.min func (m *mockMinerInstance) GetStats() (interface{}, error) { return m.stats, nil } func (m *mockMinerInstance) GetConsoleHistory(lines int) []string { return []string{} } +type mockFailingMinerInstance struct { + name string + minerType string +} + +func (m *mockFailingMinerInstance) GetName() string { return m.name } +func (m *mockFailingMinerInstance) GetType() string { return m.minerType } +func (m *mockFailingMinerInstance) GetStats() (interface{}, error) { + return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "stats unavailable"} +} +func (m *mockFailingMinerInstance) GetConsoleHistory(lines int) []string { return []string{} } + type mockProfileManager struct{} func (m *mockProfileManager) GetProfile(id string) (interface{}, error) {