- Fix .golangci.yml for v2 format (linters-settings -> linters.settings) - All production code now passes golangci-lint with zero issues - Line length 88, funlen 80/50, cyclop 15, dupl 100 - Extract shared helpers in db (scanChannels, scanInt64s, scanMessages) - Split runMigrations into applyMigration/execMigration - Fix fanOut return signature (remove unused int64) - Add fanOutSilent helper to avoid dogsled - Rewrite CLI code for lint compliance (nlreturn, wsl_v5, noctx, etc) - Rename CLI api package to chatapi to avoid revive var-naming - Fix all noinlineerr, mnd, perfsprint, funcorder issues - Fix db tests: extract helpers, add t.Parallel, proper error checks - Broker tests already clean - Handler integration tests still have lint issues (next commit)
119 lines
1.6 KiB
Go
119 lines
1.6 KiB
Go
package broker_test
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.eeqj.de/sneak/chat/internal/broker"
|
|
)
|
|
|
|
func TestNewBroker(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
b := broker.New()
|
|
if b == nil {
|
|
t.Fatal("expected non-nil broker")
|
|
}
|
|
}
|
|
|
|
func TestWaitAndNotify(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
b := broker.New()
|
|
ch := b.Wait(1)
|
|
|
|
go func() {
|
|
time.Sleep(10 * time.Millisecond)
|
|
b.Notify(1)
|
|
}()
|
|
|
|
select {
|
|
case <-ch:
|
|
case <-time.After(2 * time.Second):
|
|
t.Fatal("timeout")
|
|
}
|
|
}
|
|
|
|
func TestNotifyWithoutWaiters(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
b := broker.New()
|
|
b.Notify(42) // should not panic
|
|
}
|
|
|
|
func TestRemove(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
b := broker.New()
|
|
ch := b.Wait(1)
|
|
b.Remove(1, ch)
|
|
|
|
b.Notify(1)
|
|
|
|
select {
|
|
case <-ch:
|
|
t.Fatal("should not receive after remove")
|
|
case <-time.After(50 * time.Millisecond):
|
|
}
|
|
}
|
|
|
|
func TestMultipleWaiters(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
b := broker.New()
|
|
ch1 := b.Wait(1)
|
|
ch2 := b.Wait(1)
|
|
|
|
b.Notify(1)
|
|
|
|
select {
|
|
case <-ch1:
|
|
case <-time.After(time.Second):
|
|
t.Fatal("ch1 timeout")
|
|
}
|
|
|
|
select {
|
|
case <-ch2:
|
|
case <-time.After(time.Second):
|
|
t.Fatal("ch2 timeout")
|
|
}
|
|
}
|
|
|
|
func TestConcurrentWaitNotify(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
b := broker.New()
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
const concurrency = 100
|
|
|
|
for i := range concurrency {
|
|
wg.Add(1)
|
|
|
|
go func(uid int64) {
|
|
defer wg.Done()
|
|
|
|
ch := b.Wait(uid)
|
|
b.Notify(uid)
|
|
|
|
select {
|
|
case <-ch:
|
|
case <-time.After(time.Second):
|
|
t.Error("timeout")
|
|
}
|
|
}(int64(i % 10))
|
|
}
|
|
|
|
wg.Wait()
|
|
}
|
|
|
|
func TestRemoveNonexistent(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
b := broker.New()
|
|
ch := make(chan struct{}, 1)
|
|
b.Remove(999, ch) // should not panic
|
|
}
|