2026-04-04 10:39:59 +00:00
|
|
|
package proxy
|
|
|
|
|
|
|
|
|
|
import "testing"
|
|
|
|
|
|
|
|
|
|
func TestEventBus_Dispatch_Good(t *testing.T) {
|
|
|
|
|
bus := NewEventBus()
|
|
|
|
|
called := false
|
|
|
|
|
bus.Subscribe(EventLogin, func(event Event) {
|
|
|
|
|
called = event.Miner != nil
|
|
|
|
|
})
|
|
|
|
|
bus.Dispatch(Event{Type: EventLogin, Miner: &Miner{}})
|
|
|
|
|
if !called {
|
|
|
|
|
t.Fatal("expected handler to be called")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestEventBus_Dispatch_Bad(t *testing.T) {
|
|
|
|
|
bus := NewEventBus()
|
|
|
|
|
bus.Subscribe(EventLogin, nil)
|
|
|
|
|
bus.Dispatch(Event{Type: EventLogin})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestEventBus_Dispatch_Ugly(t *testing.T) {
|
|
|
|
|
bus := NewEventBus()
|
|
|
|
|
count := 0
|
|
|
|
|
bus.Subscribe(EventLogin, func(event Event) { count++ })
|
|
|
|
|
bus.Subscribe(EventLogin, func(event Event) { count++ })
|
|
|
|
|
bus.Dispatch(Event{Type: EventLogin})
|
|
|
|
|
if count != 2 {
|
|
|
|
|
t.Fatalf("expected both handlers to run, got %d", count)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestStats_Summary_Good(t *testing.T) {
|
|
|
|
|
stats := NewStats()
|
|
|
|
|
stats.OnAccept(Event{Diff: 120, Latency: 80})
|
|
|
|
|
summary := stats.Summary()
|
|
|
|
|
if summary.Accepted != 1 || summary.Hashes != 120 {
|
|
|
|
|
t.Fatalf("unexpected summary: %+v", summary)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestStats_Summary_Bad(t *testing.T) {
|
|
|
|
|
stats := NewStats()
|
|
|
|
|
stats.OnReject(Event{Error: "Low difficulty share"})
|
|
|
|
|
summary := stats.Summary()
|
|
|
|
|
if summary.Rejected != 1 || summary.Invalid != 1 {
|
|
|
|
|
t.Fatalf("unexpected summary: %+v", summary)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestStats_Summary_Ugly(t *testing.T) {
|
|
|
|
|
stats := NewStats()
|
|
|
|
|
stats.OnAccept(Event{Diff: 100, Latency: 10})
|
|
|
|
|
stats.Tick()
|
|
|
|
|
stats.OnAccept(Event{Diff: 200, Latency: 20})
|
|
|
|
|
summary := stats.Summary()
|
|
|
|
|
if summary.TopDiff[0] != 200 || summary.TopDiff[1] != 100 {
|
|
|
|
|
t.Fatalf("unexpected best shares: %+v", summary.TopDiff)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestWorkers_List_Good(t *testing.T) {
|
|
|
|
|
bus := NewEventBus()
|
|
|
|
|
workers := NewWorkers(WorkersByRigID, bus)
|
|
|
|
|
miner := &Miner{id: 1, user: "wallet", rigID: "rig-a", ip: "10.0.0.1"}
|
|
|
|
|
bus.Dispatch(Event{Type: EventLogin, Miner: miner})
|
|
|
|
|
bus.Dispatch(Event{Type: EventAccept, Miner: miner, Diff: 600})
|
|
|
|
|
records := workers.List()
|
|
|
|
|
if len(records) != 1 || records[0].Name != "rig-a" || records[0].Accepted != 1 {
|
|
|
|
|
t.Fatalf("unexpected worker records: %+v", records)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestWorkers_List_Bad(t *testing.T) {
|
|
|
|
|
bus := NewEventBus()
|
|
|
|
|
workers := NewWorkers(WorkersDisabled, bus)
|
|
|
|
|
bus.Dispatch(Event{Type: EventLogin, Miner: &Miner{id: 1, user: "wallet"}})
|
|
|
|
|
if len(workers.List()) != 0 {
|
|
|
|
|
t.Fatal("expected no worker records when disabled")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestWorkers_List_Ugly(t *testing.T) {
|
|
|
|
|
bus := NewEventBus()
|
|
|
|
|
workers := NewWorkers(WorkersByRigID, bus)
|
|
|
|
|
miner := &Miner{id: 1, user: "wallet", ip: "10.0.0.1"}
|
|
|
|
|
bus.Dispatch(Event{Type: EventLogin, Miner: miner})
|
|
|
|
|
bus.Dispatch(Event{Type: EventReject, Miner: miner, Error: "Low difficulty share"})
|
|
|
|
|
records := workers.List()
|
|
|
|
|
if len(records) != 1 || records[0].Name != "wallet" || records[0].Invalid != 1 {
|
|
|
|
|
t.Fatalf("unexpected worker records: %+v", records)
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-04 11:53:03 +00:00
|
|
|
|
|
|
|
|
func TestWorkers_CustomDiffStats_Good(t *testing.T) {
|
|
|
|
|
bus := NewEventBus()
|
|
|
|
|
workers := NewWorkers(WorkersByUser, bus)
|
|
|
|
|
workers.SetCustomDiffStats(true)
|
|
|
|
|
|
|
|
|
|
firstMiner := &Miner{id: 1, user: "wallet", customDiff: 1000}
|
|
|
|
|
secondMiner := &Miner{id: 2, user: "wallet", customDiff: 2000}
|
|
|
|
|
bus.Dispatch(Event{Type: EventLogin, Miner: firstMiner})
|
|
|
|
|
bus.Dispatch(Event{Type: EventLogin, Miner: secondMiner})
|
|
|
|
|
|
|
|
|
|
records := workers.List()
|
|
|
|
|
if len(records) != 2 || records[0].Name == records[1].Name {
|
|
|
|
|
t.Fatalf("expected separate custom-diff buckets, got %+v", records)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestWorkers_CustomDiffStats_Bad(t *testing.T) {
|
|
|
|
|
bus := NewEventBus()
|
|
|
|
|
workers := NewWorkers(WorkersByUser, bus)
|
|
|
|
|
workers.SetCustomDiffStats(true)
|
|
|
|
|
|
|
|
|
|
firstMiner := &Miner{id: 1, user: "wallet", customDiff: 1000}
|
|
|
|
|
secondMiner := &Miner{id: 2, user: "wallet", customDiff: 1000}
|
|
|
|
|
bus.Dispatch(Event{Type: EventLogin, Miner: firstMiner})
|
|
|
|
|
bus.Dispatch(Event{Type: EventLogin, Miner: secondMiner})
|
|
|
|
|
|
|
|
|
|
records := workers.List()
|
|
|
|
|
if len(records) != 1 {
|
|
|
|
|
t.Fatalf("expected identical custom-diff bucket to merge, got %+v", records)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestWorkers_CustomDiffStats_Ugly(t *testing.T) {
|
|
|
|
|
bus := NewEventBus()
|
|
|
|
|
workers := NewWorkers(WorkersByUser, bus)
|
|
|
|
|
|
|
|
|
|
firstMiner := &Miner{id: 1, user: "wallet", customDiff: 1000}
|
|
|
|
|
secondMiner := &Miner{id: 2, user: "wallet", customDiff: 2000}
|
|
|
|
|
bus.Dispatch(Event{Type: EventLogin, Miner: firstMiner})
|
|
|
|
|
bus.Dispatch(Event{Type: EventLogin, Miner: secondMiner})
|
|
|
|
|
|
|
|
|
|
records := workers.List()
|
|
|
|
|
if len(records) != 1 || records[0].Name != "wallet" {
|
|
|
|
|
t.Fatalf("expected default worker bucketing to ignore custom diff, got %+v", records)
|
|
|
|
|
}
|
|
|
|
|
}
|