ax(batch): add missing test files and fix pre-existing test compilation errors
Some checks are pending
Security Scan / security (push) Waiting to run
Test / test (push) Waiting to run

Adds test files for 6 source files that had no corresponding test:
bufpool_test.go (mining + node), metrics_test.go, version_test.go,
supervisor_test.go, mining_profile_test.go. Each follows
TestFilename_Function_{Good,Bad,Ugly} convention.

Also fixes 2 pre-existing compilation errors:
- ratelimiter_test.go: rl -> rateLimiter (leftover from AX rename)
- worker_test.go: worker.node -> worker.nodeManager (field was renamed)

Co-Authored-By: Charon <charon@lethean.io>
This commit is contained in:
Claude 2026-04-02 18:30:42 +01:00
parent 50f4310ba8
commit 63a9107f9c
No known key found for this signature in database
GPG key ID: AF404715446AEB41
8 changed files with 348 additions and 4 deletions

View file

@ -0,0 +1,69 @@
package mining
import (
"testing"
)
func TestBufpool_MarshalJSON_Good(t *testing.T) {
data := map[string]string{"key": "value"}
result, err := MarshalJSON(data)
if err != nil {
t.Fatalf("expected nil error, got %v", err)
}
if len(result) == 0 {
t.Fatal("expected non-empty result")
}
}
func TestBufpool_MarshalJSON_Bad(t *testing.T) {
// Channels cannot be marshalled
result, err := MarshalJSON(make(chan int))
if err == nil {
t.Fatal("expected error for non-marshallable type")
}
if result != nil {
t.Fatalf("expected nil result, got %v", result)
}
}
func TestBufpool_MarshalJSON_Ugly(t *testing.T) {
// nil value should produce "null"
result, err := MarshalJSON(nil)
if err != nil {
t.Fatalf("expected nil error, got %v", err)
}
if string(result) != "null" {
t.Fatalf("expected \"null\", got %q", string(result))
}
}
func TestBufpool_UnmarshalJSON_Good(t *testing.T) {
var target map[string]string
err := UnmarshalJSON([]byte(`{"key":"value"}`), &target)
if err != nil {
t.Fatalf("expected nil error, got %v", err)
}
if target["key"] != "value" {
t.Fatalf("expected value \"value\", got %q", target["key"])
}
}
func TestBufpool_UnmarshalJSON_Bad(t *testing.T) {
var target map[string]string
err := UnmarshalJSON([]byte(`not valid json`), &target)
if err == nil {
t.Fatal("expected error for invalid JSON")
}
}
func TestBufpool_UnmarshalJSON_Ugly(t *testing.T) {
// Empty JSON object into a map
var target map[string]string
err := UnmarshalJSON([]byte(`{}`), &target)
if err != nil {
t.Fatalf("expected nil error, got %v", err)
}
if len(target) != 0 {
t.Fatalf("expected empty map, got %d entries", len(target))
}
}

View file

@ -0,0 +1,77 @@
package mining
import (
"testing"
"time"
)
func TestMetrics_LatencyHistogram_Good(t *testing.T) {
histogram := NewLatencyHistogram(10)
histogram.Record(42 * time.Millisecond)
histogram.Record(58 * time.Millisecond)
if histogram.Count() != 2 {
t.Fatalf("expected count 2, got %d", histogram.Count())
}
avg := histogram.Average()
if avg != 50*time.Millisecond {
t.Fatalf("expected average 50ms, got %v", avg)
}
}
func TestMetrics_LatencyHistogram_Bad(t *testing.T) {
histogram := NewLatencyHistogram(10)
// No samples recorded — Average should be 0
if histogram.Average() != 0 {
t.Fatalf("expected 0 average for empty histogram, got %v", histogram.Average())
}
if histogram.Count() != 0 {
t.Fatalf("expected 0 count, got %d", histogram.Count())
}
}
func TestMetrics_LatencyHistogram_Ugly(t *testing.T) {
// Ring buffer overflow: maxSize=2, insert 3 samples
histogram := NewLatencyHistogram(2)
histogram.Record(10 * time.Millisecond)
histogram.Record(20 * time.Millisecond)
histogram.Record(30 * time.Millisecond)
if histogram.Count() != 2 {
t.Fatalf("expected count 2 after overflow, got %d", histogram.Count())
}
// Oldest sample (10ms) should have been evicted
avg := histogram.Average()
if avg != 25*time.Millisecond {
t.Fatalf("expected average 25ms (20+30)/2, got %v", avg)
}
}
func TestMetrics_RecordRequest_Good(t *testing.T) {
before := DefaultMetrics.RequestsTotal.Load()
RecordRequest(false, 5*time.Millisecond)
after := DefaultMetrics.RequestsTotal.Load()
if after != before+1 {
t.Fatalf("expected total to increase by 1, got %d -> %d", before, after)
}
}
func TestMetrics_RecordRequest_Bad(t *testing.T) {
beforeErr := DefaultMetrics.RequestsErrored.Load()
RecordRequest(true, 5*time.Millisecond)
afterErr := DefaultMetrics.RequestsErrored.Load()
if afterErr != beforeErr+1 {
t.Fatalf("expected errored to increase by 1, got %d -> %d", beforeErr, afterErr)
}
}
func TestMetrics_RecordRequest_Ugly(t *testing.T) {
snapshot := GetMetricsSnapshot()
if snapshot == nil {
t.Fatal("expected non-nil snapshot")
}
if _, ok := snapshot["requests_total"]; !ok {
t.Fatal("expected requests_total in snapshot")
}
}

View file

@ -0,0 +1,40 @@
package mining
import (
"testing"
)
func TestMiningProfile_RawConfig_MarshalJSON_Good(t *testing.T) {
raw := RawConfig([]byte(`{"pool":"pool.lthn.io:3333"}`))
data, err := raw.MarshalJSON()
if err != nil {
t.Fatalf("expected nil error, got %v", err)
}
if string(data) != `{"pool":"pool.lthn.io:3333"}` {
t.Fatalf("unexpected marshal result: %s", string(data))
}
}
func TestMiningProfile_RawConfig_MarshalJSON_Bad(t *testing.T) {
// nil RawConfig should marshal to "null"
var raw RawConfig
data, err := raw.MarshalJSON()
if err != nil {
t.Fatalf("expected nil error, got %v", err)
}
if string(data) != "null" {
t.Fatalf("expected \"null\", got %q", string(data))
}
}
func TestMiningProfile_RawConfig_MarshalJSON_Ugly(t *testing.T) {
// UnmarshalJSON on a non-nil pointer
raw := RawConfig([]byte(`{}`))
err := raw.UnmarshalJSON([]byte(`{"new":"data"}`))
if err != nil {
t.Fatalf("expected nil error, got %v", err)
}
if string(raw) != `{"new":"data"}` {
t.Fatalf("unexpected unmarshal result: %s", string(raw))
}
}

View file

@ -19,10 +19,10 @@ func TestRatelimiter_NewRateLimiter_Good(t *testing.T) {
defer rateLimiter.Stop()
if rateLimiter.requestsPerSecond != 10 {
t.Errorf("Expected requestsPerSecond 10, got %d", rl.requestsPerSecond)
t.Errorf("Expected requestsPerSecond 10, got %d", rateLimiter.requestsPerSecond)
}
if rateLimiter.burst != 20 {
t.Errorf("Expected burst 20, got %d", rl.burst)
t.Errorf("Expected burst 20, got %d", rateLimiter.burst)
}
}

View file

@ -0,0 +1,58 @@
package mining
import (
"context"
"sync/atomic"
"testing"
"time"
)
func TestSupervisor_RegisterTask_Good(t *testing.T) {
supervisor := NewTaskSupervisor()
defer supervisor.Stop()
var executed atomic.Bool
supervisor.RegisterTask("test-task", func(ctx context.Context) {
executed.Store(true)
<-ctx.Done()
}, time.Second, 0)
supervisor.Start()
time.Sleep(50 * time.Millisecond)
if !executed.Load() {
t.Fatal("expected task to have executed")
}
}
func TestSupervisor_RegisterTask_Bad(t *testing.T) {
supervisor := NewTaskSupervisor()
defer supervisor.Stop()
// Start with no tasks — should not panic
supervisor.Start()
_, _, found := supervisor.GetTaskStatus("nonexistent")
if found {
t.Fatal("expected task not found")
}
}
func TestSupervisor_RegisterTask_Ugly(t *testing.T) {
supervisor := NewTaskSupervisor()
var panicCount atomic.Int32
supervisor.RegisterTask("panicking-task", func(ctx context.Context) {
panicCount.Add(1)
panic("intentional panic for testing")
}, 10*time.Millisecond, 2)
supervisor.Start()
time.Sleep(100 * time.Millisecond)
supervisor.Stop()
// Task should have been restarted after panic
if panicCount.Load() < 2 {
t.Fatalf("expected at least 2 executions after panic recovery, got %d", panicCount.Load())
}
}

View file

@ -0,0 +1,31 @@
package mining
import (
"testing"
)
func TestVersion_GetVersion_Good(t *testing.T) {
result := GetVersion()
if result == "" {
t.Fatal("expected non-empty version string")
}
}
func TestVersion_GetVersion_Bad(t *testing.T) {
// Default version is "dev" when ldflags are not set
result := GetVersion()
if result != "dev" {
// Not a failure — just means ldflags were set
t.Logf("version is %q (ldflags may be set)", result)
}
}
func TestVersion_GetVersion_Ugly(t *testing.T) {
// All three version functions should return non-empty strings
if GetCommit() == "" {
t.Fatal("expected non-empty commit string")
}
if GetBuildDate() == "" {
t.Fatal("expected non-empty build date string")
}
}

69
pkg/node/bufpool_test.go Normal file
View file

@ -0,0 +1,69 @@
package node
import (
"testing"
)
func TestBufpool_MarshalJSON_Good(t *testing.T) {
data := map[string]string{"key": "value"}
result, err := MarshalJSON(data)
if err != nil {
t.Fatalf("expected nil error, got %v", err)
}
if len(result) == 0 {
t.Fatal("expected non-empty result")
}
}
func TestBufpool_MarshalJSON_Bad(t *testing.T) {
// Channels cannot be marshalled
result, err := MarshalJSON(make(chan int))
if err == nil {
t.Fatal("expected error for non-marshallable type")
}
if result != nil {
t.Fatalf("expected nil result, got %v", result)
}
}
func TestBufpool_MarshalJSON_Ugly(t *testing.T) {
// nil value should produce "null"
result, err := MarshalJSON(nil)
if err != nil {
t.Fatalf("expected nil error, got %v", err)
}
if string(result) != "null" {
t.Fatalf("expected \"null\", got %q", string(result))
}
}
func TestBufpool_UnmarshalJSON_Good(t *testing.T) {
var target map[string]string
err := UnmarshalJSON([]byte(`{"key":"value"}`), &target)
if err != nil {
t.Fatalf("expected nil error, got %v", err)
}
if target["key"] != "value" {
t.Fatalf("expected value \"value\", got %q", target["key"])
}
}
func TestBufpool_UnmarshalJSON_Bad(t *testing.T) {
var target map[string]string
err := UnmarshalJSON([]byte(`not valid json`), &target)
if err == nil {
t.Fatal("expected error for invalid JSON")
}
}
func TestBufpool_UnmarshalJSON_Ugly(t *testing.T) {
// Empty JSON object into a map
var target map[string]string
err := UnmarshalJSON([]byte(`{}`), &target)
if err != nil {
t.Fatalf("expected nil error, got %v", err)
}
if len(target) != 0 {
t.Fatalf("expected empty map, got %d entries", len(target))
}
}

View file

@ -41,8 +41,8 @@ func TestWorker_NewWorker_Good(t *testing.T) {
if worker == nil {
t.Fatal("NewWorker returned nil")
}
if worker.node != nodeManager {
t.Error("worker.node not set correctly")
if worker.nodeManager != nodeManager {
t.Error("worker.nodeManager not set correctly")
}
if worker.transport != transport {
t.Error("worker.transport not set correctly")