From ca04a88e354479d8ca24599192bf5096f7fdf61c Mon Sep 17 00:00:00 2001 From: Snider Date: Sun, 22 Feb 2026 21:00:16 +0000 Subject: [PATCH] refactor: apply go fix modernizers for Go 1.26 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Automated fixes: interface{} → any, range-over-int, t.Context(), wg.Go(), strings.SplitSeq, strings.Builder, slices.Contains, maps helpers, min/max builtins. Co-Authored-By: Virgil --- logging/logger.go | 23 +++++++++---------- node/bench_test.go | 6 ++--- node/bufpool.go | 4 ++-- node/bufpool_test.go | 10 ++++----- node/controller_test.go | 29 +++++++++++------------- node/dispatcher_test.go | 6 ++--- node/integration_test.go | 6 ++--- node/levin/storage.go | 10 ++++----- node/message.go | 14 +++++------- node/peer_test.go | 19 ++++++---------- node/protocol.go | 4 ++-- node/transport.go | 14 +++++------- node/transport_test.go | 20 ++++++++--------- node/worker.go | 18 +++++++-------- node/worker_test.go | 48 ++++++++++++++++++---------------------- 15 files changed, 104 insertions(+), 127 deletions(-) diff --git a/logging/logger.go b/logging/logger.go index f400dc9..669add2 100644 --- a/logging/logger.go +++ b/logging/logger.go @@ -4,6 +4,7 @@ package logging import ( "fmt" "io" + "maps" "os" "strings" "sync" @@ -100,7 +101,7 @@ func (l *Logger) GetLevel() Level { } // Fields represents key-value pairs for structured logging. -type Fields map[string]interface{} +type Fields map[string]any // log writes a log message at the specified level. func (l *Logger) log(level Level, msg string, fields Fields) { @@ -164,22 +165,22 @@ func (l *Logger) Error(msg string, fields ...Fields) { } // Debugf logs a formatted debug message. -func (l *Logger) Debugf(format string, args ...interface{}) { +func (l *Logger) Debugf(format string, args ...any) { l.log(LevelDebug, fmt.Sprintf(format, args...), nil) } // Infof logs a formatted informational message. -func (l *Logger) Infof(format string, args ...interface{}) { +func (l *Logger) Infof(format string, args ...any) { l.log(LevelInfo, fmt.Sprintf(format, args...), nil) } // Warnf logs a formatted warning message. -func (l *Logger) Warnf(format string, args ...interface{}) { +func (l *Logger) Warnf(format string, args ...any) { l.log(LevelWarn, fmt.Sprintf(format, args...), nil) } // Errorf logs a formatted error message. -func (l *Logger) Errorf(format string, args ...interface{}) { +func (l *Logger) Errorf(format string, args ...any) { l.log(LevelError, fmt.Sprintf(format, args...), nil) } @@ -190,9 +191,7 @@ func mergeFields(fields []Fields) Fields { } result := make(Fields) for _, f := range fields { - for k, v := range f { - result[k] = v - } + maps.Copy(result, f) } return result } @@ -248,22 +247,22 @@ func Error(msg string, fields ...Fields) { } // Debugf logs a formatted debug message using the global logger. -func Debugf(format string, args ...interface{}) { +func Debugf(format string, args ...any) { GetGlobal().Debugf(format, args...) } // Infof logs a formatted informational message using the global logger. -func Infof(format string, args ...interface{}) { +func Infof(format string, args ...any) { GetGlobal().Infof(format, args...) } // Warnf logs a formatted warning message using the global logger. -func Warnf(format string, args ...interface{}) { +func Warnf(format string, args ...any) { GetGlobal().Warnf(format, args...) } // Errorf logs a formatted error message using the global logger. -func Errorf(format string, args ...interface{}) { +func Errorf(format string, args ...any) { GetGlobal().Errorf(format, args...) } diff --git a/node/bench_test.go b/node/bench_test.go index a9f125a..7ded95b 100644 --- a/node/bench_test.go +++ b/node/bench_test.go @@ -111,13 +111,13 @@ func BenchmarkMessageCreateOnly(b *testing.B) { // BenchmarkMarshalJSON measures the pooled JSON encoder against stdlib. func BenchmarkMarshalJSON(b *testing.B) { - data := map[string]interface{}{ + data := map[string]any{ "id": "test-id-1234", "type": "stats", "from": "node-a", "to": "node-b", "timestamp": time.Now(), - "payload": map[string]interface{}{ + "payload": map[string]any{ "hashrate": 1234.56, "shares": 1000, }, @@ -209,7 +209,7 @@ func BenchmarkPeerScoring(b *testing.B) { defer reg.Close() // Add 50 peers with varied metrics - for i := 0; i < 50; i++ { + for i := range 50 { peer := &Peer{ ID: filepath.Join("peer", string(rune('A'+i%26)), string(rune('0'+i/26))), Name: "peer", diff --git a/node/bufpool.go b/node/bufpool.go index a4f0e68..7848214 100644 --- a/node/bufpool.go +++ b/node/bufpool.go @@ -9,7 +9,7 @@ import ( // bufferPool provides reusable byte buffers for JSON encoding. // This reduces allocation overhead in hot paths like message serialization. var bufferPool = sync.Pool{ - New: func() interface{} { + New: func() any { return bytes.NewBuffer(make([]byte, 0, 1024)) }, } @@ -31,7 +31,7 @@ func putBuffer(buf *bytes.Buffer) { // MarshalJSON encodes a value to JSON using a pooled buffer. // Returns a copy of the encoded bytes (safe to use after the function returns). -func MarshalJSON(v interface{}) ([]byte, error) { +func MarshalJSON(v any) ([]byte, error) { buf := getBuffer() defer putBuffer(buf) diff --git a/node/bufpool_test.go b/node/bufpool_test.go index 93235c1..cd0c786 100644 --- a/node/bufpool_test.go +++ b/node/bufpool_test.go @@ -80,7 +80,7 @@ func TestBufPool_BufferIndependence(t *testing.T) { func TestMarshalJSON_BasicTypes(t *testing.T) { tests := []struct { name string - input interface{} + input any }{ { name: "string value", @@ -108,7 +108,7 @@ func TestMarshalJSON_BasicTypes(t *testing.T) { }, { name: "map value", - input: map[string]interface{}{"key": "value", "num": 42}, + input: map[string]any{"key": "value", "num": 42}, }, { name: "slice value", @@ -188,10 +188,10 @@ func TestBufferPool_ConcurrentAccess(t *testing.T) { var wg sync.WaitGroup wg.Add(goroutines) - for g := 0; g < goroutines; g++ { + for range goroutines { go func() { defer wg.Done() - for i := 0; i < iterations; i++ { + for range iterations { buf := getBuffer() buf.WriteString("concurrent test data") @@ -214,7 +214,7 @@ func TestMarshalJSON_ConcurrentSafety(t *testing.T) { errs := make([]error, goroutines) - for g := 0; g < goroutines; g++ { + for g := range goroutines { go func(idx int) { defer wg.Done() payload := PingPayload{SentAt: int64(idx)} diff --git a/node/controller_test.go b/node/controller_test.go index ff1de51..ee9a383 100644 --- a/node/controller_test.go +++ b/node/controller_test.go @@ -159,7 +159,7 @@ func TestController_GetAllStats(t *testing.T) { const numWorkers = 2 workerIDs := make([]string, numWorkers) - for i := 0; i < numWorkers; i++ { + for i := range numWorkers { nm, addr, _ := makeWorkerServer(t) wID := nm.GetIdentity().ID workerIDs[i] = wID @@ -228,7 +228,7 @@ func TestController_ConcurrentRequests(t *testing.T) { const numPeers = 3 peerIDs := make([]string, numPeers) - for i := 0; i < numPeers; i++ { + for i := range numPeers { nm, addr, _ := makeWorkerServer(t) pID := nm.GetIdentity().ID peerIDs[i] = pID @@ -312,7 +312,7 @@ func TestController_MultipleSequentialPings(t *testing.T) { controller, _, tp := setupControllerPair(t) serverID := tp.ServerNode.GetIdentity().ID - for i := 0; i < 5; i++ { + for i := range 5 { rtt, err := controller.PingPeer(serverID) require.NoError(t, err, "iteration %d should succeed", i) assert.Greater(t, rtt, 0.0, "iteration %d RTT should be positive", i) @@ -329,15 +329,13 @@ func TestController_ConcurrentRequestsSamePeer(t *testing.T) { var wg sync.WaitGroup var successCount atomic.Int32 - for g := 0; g < goroutines; g++ { - wg.Add(1) - go func() { - defer wg.Done() + for range goroutines { + wg.Go(func() { rtt, err := controller.PingPeer(serverID) if err == nil && rtt > 0 { successCount.Add(1) } - }() + }) } wg.Wait() @@ -419,7 +417,7 @@ func setupControllerPairWithMiner(t *testing.T) (*Controller, *Worker, *testTran "running-miner": { name: "running-miner", minerType: "xmrig", - stats: map[string]interface{}{ + stats: map[string]any{ "hashrate": 1234.5, "shares": 42, "rejected": 2, @@ -454,7 +452,7 @@ type mockMinerManagerFull struct { miners map[string]*mockMinerFull } -func (m *mockMinerManagerFull) StartMiner(minerType string, config interface{}) (MinerInstance, error) { +func (m *mockMinerManagerFull) StartMiner(minerType string, config any) (MinerInstance, error) { m.mu.Lock() defer m.mu.Unlock() @@ -462,7 +460,7 @@ func (m *mockMinerManagerFull) StartMiner(minerType string, config interface{}) miner := &mockMinerFull{ name: name, minerType: minerType, - stats: map[string]interface{}{ + stats: map[string]any{ "hashrate": 0.0, "shares": 0, }, @@ -509,13 +507,13 @@ func (m *mockMinerManagerFull) GetMiner(name string) (MinerInstance, error) { type mockMinerFull struct { name string minerType string - stats interface{} + stats any consoleHistory []string } -func (m *mockMinerFull) GetName() string { return m.name } -func (m *mockMinerFull) GetType() string { return m.minerType } -func (m *mockMinerFull) GetStats() (interface{}, error) { return m.stats, nil } +func (m *mockMinerFull) GetName() string { return m.name } +func (m *mockMinerFull) GetType() string { return m.minerType } +func (m *mockMinerFull) GetStats() (any, error) { return m.stats, nil } func (m *mockMinerFull) GetConsoleHistory(lines int) []string { if lines >= len(m.consoleHistory) { return m.consoleHistory @@ -529,7 +527,6 @@ func TestController_StartRemoteMiner(t *testing.T) { configOverride := json.RawMessage(`{"pool":"pool.example.com:3333"}`) err := controller.StartRemoteMiner(serverID, "xmrig", "profile-1", configOverride) - require.NoError(t, err, "StartRemoteMiner should succeed") } diff --git a/node/dispatcher_test.go b/node/dispatcher_test.go index ddbab71..971d44d 100644 --- a/node/dispatcher_test.go +++ b/node/dispatcher_test.go @@ -248,7 +248,7 @@ func TestDispatcher_ConcurrentDispatchSafety(t *testing.T) { var wg sync.WaitGroup wg.Add(goroutines) - for i := 0; i < goroutines; i++ { + for range goroutines { go func() { defer wg.Done() pkt := makePacket(IntentCompute, 0, []byte("concurrent")) @@ -277,7 +277,7 @@ func TestDispatcher_ConcurrentRegisterAndDispatch(t *testing.T) { wg.Add(goroutines * 2) // Half the goroutines dispatch packets - for i := 0; i < goroutines; i++ { + for range goroutines { go func() { defer wg.Done() pkt := makePacket(IntentHandshake, 0, []byte("data")) @@ -286,7 +286,7 @@ func TestDispatcher_ConcurrentRegisterAndDispatch(t *testing.T) { } // Half the goroutines register/replace handlers concurrently - for i := 0; i < goroutines; i++ { + for i := range goroutines { go func(n int) { defer wg.Done() d.RegisterHandler(byte(n%4), func(pkt *ueps.ParsedPacket) error { diff --git a/node/integration_test.go b/node/integration_test.go index 0b698fa..30b8588 100644 --- a/node/integration_test.go +++ b/node/integration_test.go @@ -70,7 +70,7 @@ func TestIntegration_FullNodeLifecycle(t *testing.T) { "integration-miner": { name: "integration-miner", minerType: "xmrig", - stats: map[string]interface{}{ + stats: map[string]any{ "hashrate": 5000.0, "shares": 250, }, @@ -276,7 +276,7 @@ func TestIntegration_TwoNodeBidirectionalMessages(t *testing.T) { assert.NotEmpty(t, stats.NodeID) // Verify multiple sequential round-trips work. - for i := 0; i < 5; i++ { + for i := range 5 { rtt, err := controller.PingPeer(serverID) require.NoError(t, err, "sequential ping %d should succeed", i) assert.Greater(t, rtt, 0.0) @@ -294,7 +294,7 @@ func TestIntegration_MultiPeerTopology(t *testing.T) { const numWorkers = 3 workerIDs := make([]string, numWorkers) - for i := 0; i < numWorkers; i++ { + for i := range numWorkers { nm, addr, _ := makeWorkerServer(t) wID := nm.GetIdentity().ID workerIDs[i] = wID diff --git a/node/levin/storage.go b/node/levin/storage.go index 173ac0b..99ad80f 100644 --- a/node/levin/storage.go +++ b/node/levin/storage.go @@ -484,7 +484,7 @@ func decodeSection(buf []byte) (Section, int, error) { s := make(Section, int(count)) - for i := uint64(0); i < count; i++ { + for range count { // Name length (1 byte). if off >= len(buf) { return nil, 0, ErrStorageTruncated @@ -632,7 +632,7 @@ func decodeArray(buf []byte, tag uint8) (Value, int, error) { switch elemType { case TypeUint64: arr := make([]uint64, count) - for i := uint64(0); i < count; i++ { + for i := range count { if off+8 > len(buf) { return Value{}, 0, ErrStorageTruncated } @@ -643,7 +643,7 @@ func decodeArray(buf []byte, tag uint8) (Value, int, error) { case TypeUint32: arr := make([]uint32, count) - for i := uint64(0); i < count; i++ { + for i := range count { if off+4 > len(buf) { return Value{}, 0, ErrStorageTruncated } @@ -654,7 +654,7 @@ func decodeArray(buf []byte, tag uint8) (Value, int, error) { case TypeString: arr := make([][]byte, count) - for i := uint64(0); i < count; i++ { + for i := range count { strLen, sn, err := UnpackVarint(buf[off:]) if err != nil { return Value{}, 0, err @@ -672,7 +672,7 @@ func decodeArray(buf []byte, tag uint8) (Value, int, error) { case TypeObject: arr := make([]Section, count) - for i := uint64(0); i < count; i++ { + for i := range count { sec, consumed, err := decodeSection(buf[off:]) if err != nil { return Value{}, 0, err diff --git a/node/message.go b/node/message.go index 6f343df..d4b2b6e 100644 --- a/node/message.go +++ b/node/message.go @@ -2,6 +2,7 @@ package node import ( "encoding/json" + "slices" "time" "github.com/google/uuid" @@ -21,12 +22,7 @@ var SupportedProtocolVersions = []string{"1.0"} // IsProtocolVersionSupported checks if a given version is supported. func IsProtocolVersionSupported(version string) bool { - for _, v := range SupportedProtocolVersions { - if v == version { - return true - } - } - return false + return slices.Contains(SupportedProtocolVersions, version) } // MessageType defines the type of P2P message. @@ -71,7 +67,7 @@ type Message struct { } // NewMessage creates a new message with a generated ID and timestamp. -func NewMessage(msgType MessageType, from, to string, payload interface{}) (*Message, error) { +func NewMessage(msgType MessageType, from, to string, payload any) (*Message, error) { var payloadBytes json.RawMessage if payload != nil { data, err := MarshalJSON(payload) @@ -92,7 +88,7 @@ func NewMessage(msgType MessageType, from, to string, payload interface{}) (*Mes } // Reply creates a reply message to this message. -func (m *Message) Reply(msgType MessageType, payload interface{}) (*Message, error) { +func (m *Message) Reply(msgType MessageType, payload any) (*Message, error) { reply, err := NewMessage(msgType, m.To, m.From, payload) if err != nil { return nil, err @@ -102,7 +98,7 @@ func (m *Message) Reply(msgType MessageType, payload interface{}) (*Message, err } // ParsePayload unmarshals the payload into the given struct. -func (m *Message) ParsePayload(v interface{}) error { +func (m *Message) ParsePayload(v any) error { if m.Payload == nil { return nil } diff --git a/node/peer_test.go b/node/peer_test.go index a621d3b..9653cbe 100644 --- a/node/peer_test.go +++ b/node/peer_test.go @@ -3,6 +3,7 @@ package node import ( "os" "path/filepath" + "slices" "testing" "time" ) @@ -431,13 +432,7 @@ func TestPeerRegistry_PublicKeyAllowlist(t *testing.T) { // List should contain the key keys := pr.ListAllowedPublicKeys() - found := false - for _, k := range keys { - if k == testKey { - found = true - break - } - } + found := slices.Contains(keys, testKey) if !found { t.Error("ListAllowedPublicKeys should contain the added key") } @@ -562,7 +557,7 @@ func TestPeerRegistry_ScoreRecording(t *testing.T) { pr.AddPeer(peer) // Record successes - score should increase - for i := 0; i < 5; i++ { + for range 5 { pr.RecordSuccess("score-record-test") } updated := pr.GetPeer("score-record-test") @@ -572,7 +567,7 @@ func TestPeerRegistry_ScoreRecording(t *testing.T) { // Record failures - score should decrease initialScore := updated.Score - for i := 0; i < 3; i++ { + for range 3 { pr.RecordFailure("score-record-test") } updated = pr.GetPeer("score-record-test") @@ -589,7 +584,7 @@ func TestPeerRegistry_ScoreRecording(t *testing.T) { } // Score should be clamped to min/max - for i := 0; i < 100; i++ { + for range 100 { pr.RecordSuccess("score-record-test") } updated = pr.GetPeer("score-record-test") @@ -597,7 +592,7 @@ func TestPeerRegistry_ScoreRecording(t *testing.T) { t.Errorf("score should be clamped to max %f, got %f", ScoreMaximum, updated.Score) } - for i := 0; i < 100; i++ { + for range 100 { pr.RecordFailure("score-record-test") } updated = pr.GetPeer("score-record-test") @@ -861,7 +856,7 @@ func TestPeerRegistry_ScheduleSave_Debounce(t *testing.T) { } // Multiple rapid saves should be debounced - for i := 0; i < 10; i++ { + for range 10 { pr.scheduleSave() } diff --git a/node/protocol.go b/node/protocol.go index 197d5e4..c8f9d61 100644 --- a/node/protocol.go +++ b/node/protocol.go @@ -46,7 +46,7 @@ func (h *ResponseHandler) ValidateResponse(resp *Message, expectedType MessageTy // ParseResponse validates the response and parses the payload into the target. // This combines ValidateResponse and ParsePayload into a single call. -func (h *ResponseHandler) ParseResponse(resp *Message, expectedType MessageType, target interface{}) error { +func (h *ResponseHandler) ParseResponse(resp *Message, expectedType MessageType, target any) error { if err := h.ValidateResponse(resp, expectedType); err != nil { return err } @@ -69,7 +69,7 @@ func ValidateResponse(resp *Message, expectedType MessageType) error { } // ParseResponse is a convenience function using the default handler. -func ParseResponse(resp *Message, expectedType MessageType, target interface{}) error { +func ParseResponse(resp *Message, expectedType MessageType, target any) error { return DefaultResponseHandler.ParseResponse(resp, expectedType, target) } diff --git a/node/transport.go b/node/transport.go index 2982388..2591f89 100644 --- a/node/transport.go +++ b/node/transport.go @@ -12,8 +12,8 @@ import ( "sync/atomic" "time" - "github.com/Snider/Borg/pkg/smsg" "forge.lthn.ai/core/go-p2p/logging" + "github.com/Snider/Borg/pkg/smsg" "github.com/gorilla/websocket" ) @@ -237,9 +237,7 @@ func (t *Transport) Start() error { } } - t.wg.Add(1) - go func() { - defer t.wg.Done() + t.wg.Go(func() { var err error if t.config.TLSCertPath != "" && t.config.TLSKeyPath != "" { err = t.server.ListenAndServeTLS(t.config.TLSCertPath, t.config.TLSKeyPath) @@ -249,12 +247,10 @@ func (t *Transport) Start() error { if err != nil && err != http.ErrServerClosed { logging.Error("HTTP server error", logging.Fields{"error": err, "addr": t.config.ListenAddr}) } - }() + }) // Start message deduplication cleanup goroutine - t.wg.Add(1) - go func() { - defer t.wg.Done() + t.wg.Go(func() { ticker := time.NewTicker(time.Minute) defer ticker.Stop() for { @@ -265,7 +261,7 @@ func (t *Transport) Start() error { t.dedup.Cleanup() } } - }() + }) return nil } diff --git a/node/transport_test.go b/node/transport_test.go index 3239017..ffa6e5a 100644 --- a/node/transport_test.go +++ b/node/transport_test.go @@ -162,7 +162,7 @@ func TestMessageDeduplicator(t *testing.T) { t.Run("ConcurrentAccess", func(t *testing.T) { d := NewMessageDeduplicator(5 * time.Minute) var wg sync.WaitGroup - for i := 0; i < 100; i++ { + for i := range 100 { wg.Add(1) go func(id int) { defer wg.Done() @@ -179,7 +179,7 @@ func TestPeerRateLimiter(t *testing.T) { t.Run("AllowUpToBurst", func(t *testing.T) { rl := NewPeerRateLimiter(10, 5) - for i := 0; i < 10; i++ { + for i := range 10 { if !rl.Allow() { t.Errorf("should allow message %d (within burst)", i) } @@ -194,7 +194,7 @@ func TestPeerRateLimiter(t *testing.T) { rl := NewPeerRateLimiter(5, 10) // 5 burst, 10/sec refill // Exhaust all tokens - for i := 0; i < 5; i++ { + for range 5 { rl.Allow() } @@ -397,7 +397,7 @@ func TestTransport_RateLimiting(t *testing.T) { serverID := tp.ServerNode.GetIdentity().ID // Send 150 messages rapidly (rate limiter burst = 100) - for i := 0; i < 150; i++ { + for range 150 { msg, _ := NewMessage(MsgPing, clientID, serverID, PingPayload{SentAt: time.Now().UnixMilli()}) pc.Send(msg) } @@ -569,15 +569,13 @@ func TestTransport_ConcurrentSends(t *testing.T) { const msgsPerGoroutine = 5 var wg sync.WaitGroup - for g := 0; g < goroutines; g++ { - wg.Add(1) - go func() { - defer wg.Done() - for i := 0; i < msgsPerGoroutine; i++ { + for range goroutines { + wg.Go(func() { + for range msgsPerGoroutine { msg, _ := NewMessage(MsgPing, clientID, serverID, PingPayload{SentAt: time.Now().UnixMilli()}) pc.Send(msg) } - }() + }) } wg.Wait() @@ -603,7 +601,7 @@ func TestTransport_Broadcast(t *testing.T) { const numWorkers = 2 var receiveCounters [numWorkers]*atomic.Int32 - for i := 0; i < numWorkers; i++ { + for i := range numWorkers { receiveCounters[i] = &atomic.Int32{} counter := receiveCounters[i] diff --git a/node/worker.go b/node/worker.go index 72eb9ff..10b7ec6 100644 --- a/node/worker.go +++ b/node/worker.go @@ -14,7 +14,7 @@ import ( // MinerManager interface for the mining package integration. // This allows the node package to interact with mining.Manager without import cycles. type MinerManager interface { - StartMiner(minerType string, config interface{}) (MinerInstance, error) + StartMiner(minerType string, config any) (MinerInstance, error) StopMiner(name string) error ListMiners() []MinerInstance GetMiner(name string) (MinerInstance, error) @@ -24,14 +24,14 @@ type MinerManager interface { type MinerInstance interface { GetName() string GetType() string - GetStats() (interface{}, error) + GetStats() (any, error) GetConsoleHistory(lines int) []string } // ProfileManager interface for profile operations. type ProfileManager interface { - GetProfile(id string) (interface{}, error) - SaveProfile(profile interface{}) error + GetProfile(id string) (any, error) + SaveProfile(profile any) error } // Worker handles incoming messages on a worker node. @@ -159,14 +159,14 @@ func (w *Worker) handleGetStats(msg *Message) (*Message, error) { } // convertMinerStats converts miner stats to the protocol format. -func convertMinerStats(miner MinerInstance, rawStats interface{}) MinerStatsItem { +func convertMinerStats(miner MinerInstance, rawStats any) MinerStatsItem { item := MinerStatsItem{ Name: miner.GetName(), Type: miner.GetType(), } // Try to extract common fields from the stats - if statsMap, ok := rawStats.(map[string]interface{}); ok { + if statsMap, ok := rawStats.(map[string]any); ok { if hashrate, ok := statsMap["hashrate"].(float64); ok { item.Hashrate = hashrate } @@ -207,7 +207,7 @@ func (w *Worker) handleStartMiner(msg *Message) (*Message, error) { } // Get the config from the profile or use the override - var config interface{} + var config any if payload.Config != nil { config = payload.Config } else if w.profileManager != nil { @@ -327,7 +327,7 @@ func (w *Worker) handleDeploy(conn *PeerConnection, msg *Message) (*Message, err } // Unmarshal into interface{} to pass to ProfileManager - var profile interface{} + var profile any if err := json.Unmarshal(profileData, &profile); err != nil { return nil, fmt.Errorf("invalid profile data JSON: %w", err) } @@ -367,7 +367,7 @@ func (w *Worker) handleDeploy(conn *PeerConnection, msg *Message) (*Message, err // If the bundle contained a profile config, save it if len(profileData) > 0 && w.profileManager != nil { - var profile interface{} + var profile any if err := json.Unmarshal(profileData, &profile); err != nil { logging.Warn("failed to parse profile from miner bundle", logging.Fields{"error": err}) } else { diff --git a/node/worker_test.go b/node/worker_test.go index a3fa98a..3d4b128 100644 --- a/node/worker_test.go +++ b/node/worker_test.go @@ -425,12 +425,12 @@ func TestWorker_HandleDeploy_UnknownType(t *testing.T) { func TestConvertMinerStats(t *testing.T) { tests := []struct { name string - rawStats interface{} + rawStats any wantHash float64 }{ { name: "MapWithHashrate", - rawStats: map[string]interface{}{ + rawStats: map[string]any{ "hashrate": 100.5, "shares": 10, "rejected": 2, @@ -442,7 +442,7 @@ func TestConvertMinerStats(t *testing.T) { }, { name: "EmptyMap", - rawStats: map[string]interface{}{}, + rawStats: map[string]any{}, wantHash: 0, }, { @@ -473,7 +473,7 @@ type mockMinerManager struct { miners []MinerInstance } -func (m *mockMinerManager) StartMiner(minerType string, config interface{}) (MinerInstance, error) { +func (m *mockMinerManager) StartMiner(minerType string, config any) (MinerInstance, error) { return nil, nil } @@ -497,21 +497,21 @@ func (m *mockMinerManager) GetMiner(name string) (MinerInstance, error) { type mockMinerInstance struct { name string minerType string - stats interface{} + stats any } func (m *mockMinerInstance) GetName() string { return m.name } func (m *mockMinerInstance) GetType() string { return m.minerType } -func (m *mockMinerInstance) GetStats() (interface{}, error) { return m.stats, nil } +func (m *mockMinerInstance) GetStats() (any, error) { return m.stats, nil } func (m *mockMinerInstance) GetConsoleHistory(lines int) []string { return []string{} } type mockProfileManager struct{} -func (m *mockProfileManager) GetProfile(id string) (interface{}, error) { +func (m *mockProfileManager) GetProfile(id string) (any, error) { return nil, nil } -func (m *mockProfileManager) SaveProfile(profile interface{}) error { +func (m *mockProfileManager) SaveProfile(profile any) error { return nil } @@ -522,7 +522,7 @@ type mockMinerManagerFailing struct { mockMinerManager } -func (m *mockMinerManagerFailing) StartMiner(minerType string, config interface{}) (MinerInstance, error) { +func (m *mockMinerManagerFailing) StartMiner(minerType string, config any) (MinerInstance, error) { return nil, fmt.Errorf("mining hardware not available") } @@ -536,10 +536,10 @@ func (m *mockMinerManagerFailing) GetMiner(name string) (MinerInstance, error) { // mockProfileManagerFull implements ProfileManager that returns real data. type mockProfileManagerFull struct { - profiles map[string]interface{} + profiles map[string]any } -func (m *mockProfileManagerFull) GetProfile(id string) (interface{}, error) { +func (m *mockProfileManagerFull) GetProfile(id string) (any, error) { p, ok := m.profiles[id] if !ok { return nil, fmt.Errorf("profile %s not found", id) @@ -547,18 +547,18 @@ func (m *mockProfileManagerFull) GetProfile(id string) (interface{}, error) { return p, nil } -func (m *mockProfileManagerFull) SaveProfile(profile interface{}) error { +func (m *mockProfileManagerFull) SaveProfile(profile any) error { return nil } // mockProfileManagerFailing always returns errors. type mockProfileManagerFailing struct{} -func (m *mockProfileManagerFailing) GetProfile(id string) (interface{}, error) { +func (m *mockProfileManagerFailing) GetProfile(id string) (any, error) { return nil, fmt.Errorf("profile %s not found", id) } -func (m *mockProfileManagerFailing) SaveProfile(profile interface{}) error { +func (m *mockProfileManagerFailing) SaveProfile(profile any) error { return fmt.Errorf("save failed") } @@ -640,8 +640,8 @@ func TestWorker_HandleStartMiner_WithManager(t *testing.T) { t.Run("WithProfileManager", func(t *testing.T) { pm := &mockProfileManagerFull{ - profiles: map[string]interface{}{ - "test-profile": map[string]interface{}{"pool": "pool.test:3333"}, + profiles: map[string]any{ + "test-profile": map[string]any{"pool": "pool.test:3333"}, }, } worker.SetProfileManager(pm) @@ -723,7 +723,7 @@ type mockMinerManagerWithStart struct { counter int } -func (m *mockMinerManagerWithStart) StartMiner(minerType string, config interface{}) (MinerInstance, error) { +func (m *mockMinerManagerWithStart) StartMiner(minerType string, config any) (MinerInstance, error) { m.counter++ name := fmt.Sprintf("%s-%d", minerType, m.counter) return &mockMinerInstance{name: name, minerType: minerType}, nil @@ -845,9 +845,6 @@ func TestWorker_HandleGetLogs_WithManager(t *testing.T) { mm := &mockMinerManagerFailing{} worker.SetMinerManager(mm) - - - payload := GetLogsPayload{MinerName: "non-existent", Lines: 50} msg, _ := NewMessage(MsgGetLogs, "sender-id", identity.ID, payload) @@ -924,7 +921,7 @@ func TestWorker_HandleGetStats_WithMinerManager(t *testing.T) { &mockMinerInstance{ name: "miner-1", minerType: "xmrig", - stats: map[string]interface{}{ + stats: map[string]any{ "hashrate": 500.0, "shares": 25, "rejected": 1, @@ -936,7 +933,7 @@ func TestWorker_HandleGetStats_WithMinerManager(t *testing.T) { &mockMinerInstance{ name: "miner-2", minerType: "tt-miner", - stats: map[string]interface{}{ + stats: map[string]any{ "hashrate": 1200.0, }, }, @@ -983,7 +980,6 @@ func TestWorker_HandleMessage_UnknownType(t *testing.T) { worker.HandleMessage(nil, msg) } - func TestWorker_HandleDeploy_ProfileWithManager(t *testing.T) { cleanup := setupTestEnv(t) defer cleanup() @@ -1002,7 +998,7 @@ func TestWorker_HandleDeploy_ProfileWithManager(t *testing.T) { transport := NewTransport(nm, pr, DefaultTransportConfig()) worker := NewWorker(nm, transport) - pm := &mockProfileManagerFull{profiles: make(map[string]interface{})} + pm := &mockProfileManagerFull{profiles: make(map[string]any)} worker.SetProfileManager(pm) identity := nm.GetIdentity() @@ -1098,7 +1094,7 @@ func TestWorker_HandleDeploy_MinerBundle(t *testing.T) { } transport := NewTransport(nm, pr, DefaultTransportConfig()) worker := NewWorker(nm, transport) - pm := &mockProfileManagerFull{profiles: make(map[string]interface{})} + pm := &mockProfileManagerFull{profiles: make(map[string]any)} worker.SetProfileManager(pm) identity := nm.GetIdentity() @@ -1329,7 +1325,7 @@ func TestWorker_HandleMessage_GetStats_IntegrationViaWebSocket(t *testing.T) { &mockMinerInstance{ name: "test-miner", minerType: "xmrig", - stats: map[string]interface{}{ + stats: map[string]any{ "hashrate": 500.0, "shares": 25, "rejected": 1,