orchard
mirrorEvery site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.
blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics
1package main
2
3import (
4 "testing"
5 "time"
6)
7
8func TestHubReachesEveryOpenTab(t *testing.T) {
9 h := NewHub()
10 a, closeA := h.Subscribe()
11 b, closeB := h.Subscribe()
12 defer closeA()
13 defer closeB()
14
15 h.Publish(HubEvent{Kind: "finished", ConvID: "c1", Title: "A title"})
16 for _, ch := range []<-chan HubEvent{a, b} {
17 select {
18 case ev := <-ch:
19 if ev.ConvID != "c1" || ev.Title != "A title" {
20 t.Errorf("got %#v", ev)
21 }
22 case <-time.After(time.Second):
23 t.Fatal("a subscriber was not told")
24 }
25 }
26}
27
28// A tab on a locked phone stops reading. Waiting on it would stall the turn
29// doing the publishing and every other tab with it, and these events are a hint
30// to go and re-read rather than a record that has to arrive.
31func TestHubDoesNotBlockOnATabThatStoppedReading(t *testing.T) {
32 h := NewHub()
33 _, cancel := h.Subscribe()
34 defer cancel()
35
36 done := make(chan struct{})
37 go func() {
38 for i := 0; i < hubBuffer*4; i++ {
39 h.Publish(HubEvent{Kind: "finished", ConvID: "c1"})
40 }
41 close(done)
42 }()
43 select {
44 case <-done:
45 case <-time.After(2 * time.Second):
46 t.Fatal("publishing blocked on a subscriber that was not reading")
47 }
48}
49
50// Unsubscribing has to be safe to call twice, since the handler defers it and
51// an error path calls it as well.
52func TestHubCancelIsIdempotent(t *testing.T) {
53 h := NewHub()
54 _, cancel := h.Subscribe()
55 cancel()
56 cancel()
57 h.Publish(HubEvent{Kind: "changed"})
58 if n := h.Len(); n != 0 {
59 t.Errorf("%d subscribers left after cancel", n)
60 }
61}