go-proxy/stats_test.go

174 lines
4.7 KiB
Go
Raw Permalink Normal View History

package proxy
import (
"sync"
"testing"
)
// TestStats_OnAccept_Good verifies that accepted counter, hashes, and topDiff are updated.
//
// stats := proxy.NewStats()
// stats.OnAccept(proxy.Event{Diff: 100000, Latency: 82})
// summary := stats.Summary()
// _ = summary.Accepted // 1
// _ = summary.Hashes // 100000
func TestStats_OnAccept_Good(t *testing.T) {
stats := NewStats()
stats.OnAccept(Event{Diff: 100000, Latency: 82})
summary := stats.Summary()
if summary.Accepted != 1 {
t.Fatalf("expected accepted 1, got %d", summary.Accepted)
}
if summary.Hashes != 100000 {
t.Fatalf("expected hashes 100000, got %d", summary.Hashes)
}
if summary.TopDiff[0] != 100000 {
t.Fatalf("expected top diff 100000, got %d", summary.TopDiff[0])
}
}
// TestStats_OnAccept_Bad verifies concurrent OnAccept calls do not race.
//
// stats := proxy.NewStats()
// // 100 goroutines each call OnAccept — no data race under -race flag.
func TestStats_OnAccept_Bad(t *testing.T) {
stats := NewStats()
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func(diff uint64) {
defer wg.Done()
stats.OnAccept(Event{Diff: diff, Latency: 10})
}(uint64(i + 1))
}
wg.Wait()
summary := stats.Summary()
if summary.Accepted != 100 {
t.Fatalf("expected 100 accepted, got %d", summary.Accepted)
}
}
// TestStats_OnAccept_Ugly verifies that 15 accepts with varying diffs fill all topDiff slots.
//
// stats := proxy.NewStats()
// // 15 accepts with diffs 1..15 → topDiff[9] is 6 (10th highest), not 0
func TestStats_OnAccept_Ugly(t *testing.T) {
stats := NewStats()
for i := 1; i <= 15; i++ {
stats.OnAccept(Event{Diff: uint64(i)})
}
summary := stats.Summary()
// top 10 should be 15, 14, 13, ..., 6
if summary.TopDiff[0] != 15 {
t.Fatalf("expected top diff[0]=15, got %d", summary.TopDiff[0])
}
if summary.TopDiff[9] != 6 {
t.Fatalf("expected top diff[9]=6, got %d", summary.TopDiff[9])
}
}
// TestStats_OnReject_Good verifies that rejected and invalid counters are updated.
//
// stats := proxy.NewStats()
// stats.OnReject(proxy.Event{Error: "Low difficulty share"})
func TestStats_OnReject_Good(t *testing.T) {
stats := NewStats()
stats.OnReject(Event{Error: "Low difficulty share"})
stats.OnReject(Event{Error: "Malformed share"})
summary := stats.Summary()
if summary.Rejected != 2 {
t.Fatalf("expected two rejected shares, got %d", summary.Rejected)
}
if summary.Invalid != 2 {
t.Fatalf("expected two invalid shares, got %d", summary.Invalid)
}
}
// TestStats_OnReject_Bad verifies that a non-invalid rejection increments rejected but not invalid.
//
// stats := proxy.NewStats()
// stats.OnReject(proxy.Event{Error: "Stale share"})
func TestStats_OnReject_Bad(t *testing.T) {
stats := NewStats()
stats.OnReject(Event{Error: "Stale share"})
summary := stats.Summary()
if summary.Rejected != 1 {
t.Fatalf("expected one rejected, got %d", summary.Rejected)
}
if summary.Invalid != 0 {
t.Fatalf("expected zero invalid for non-invalid reason, got %d", summary.Invalid)
}
}
// TestStats_OnReject_Ugly verifies an expired accepted share increments both accepted and expired.
//
// stats := proxy.NewStats()
// stats.OnAccept(proxy.Event{Diff: 1000, Expired: true})
func TestStats_OnReject_Ugly(t *testing.T) {
stats := NewStats()
stats.OnAccept(Event{Diff: 1000, Expired: true})
summary := stats.Summary()
if summary.Accepted != 1 {
t.Fatalf("expected accepted 1, got %d", summary.Accepted)
}
if summary.Expired != 1 {
t.Fatalf("expected expired 1, got %d", summary.Expired)
}
}
// TestStats_Tick_Good verifies that Tick advances the rolling window position.
//
// stats := proxy.NewStats()
// stats.OnAccept(proxy.Event{Diff: 500})
// stats.Tick()
// summary := stats.Summary()
func TestStats_Tick_Good(t *testing.T) {
stats := NewStats()
stats.OnAccept(Event{Diff: 500})
stats.Tick()
summary := stats.Summary()
// After one tick, the hashrate should still include the 500 diff
if summary.Hashrate[HashrateWindow60s] == 0 {
t.Fatalf("expected non-zero 60s hashrate after accept and tick")
}
}
// TestStats_OnLogin_OnClose_Good verifies miner count tracking.
//
// stats := proxy.NewStats()
// stats.OnLogin(proxy.Event{Miner: &proxy.Miner{}})
// stats.OnClose(proxy.Event{Miner: &proxy.Miner{}})
func TestStats_OnLogin_OnClose_Good(t *testing.T) {
stats := NewStats()
m := &Miner{}
stats.OnLogin(Event{Miner: m})
if got := stats.miners.Load(); got != 1 {
t.Fatalf("expected 1 miner, got %d", got)
}
if got := stats.maxMiners.Load(); got != 1 {
t.Fatalf("expected max miners 1, got %d", got)
}
stats.OnClose(Event{Miner: m})
if got := stats.miners.Load(); got != 0 {
t.Fatalf("expected 0 miners after close, got %d", got)
}
if got := stats.maxMiners.Load(); got != 1 {
t.Fatalf("expected max miners to remain 1, got %d", got)
}
}