Files

129 lines
3.1 KiB
Go

package session
import (
"errors"
"sync"
"testing"
)
func TestBindGenerations(t *testing.T) {
r := NewRegistry()
gen1, replaced1 := r.Bind("a@b/c", nil, nil)
if gen1 != 1 || replaced1 {
t.Fatalf("first bind: gen=%d replaced=%v, want 1 false", gen1, replaced1)
}
gen2, replaced2 := r.Bind("a@b/c", nil, nil)
if gen2 != 2 || !replaced2 {
t.Fatalf("second bind: gen=%d replaced=%v, want 2 true", gen2, replaced2)
}
g, ok := r.Current("a@b/c")
if !ok || g != 2 {
t.Fatalf("Current = %d %v, want 2 true", g, ok)
}
_, ok = r.Current("other@b/c")
if ok {
t.Fatalf("unknown JID should not be current")
}
}
func TestReplaceClosesOldSlot(t *testing.T) {
r := NewRegistry()
var closedMu sync.Mutex
var closedGen uint64
closeFn := func(gen uint64) func() {
return func() {
closedMu.Lock()
closedGen = gen
closedMu.Unlock()
}
}
r.Bind("a@b/c", func([]byte) error { return nil }, closeFn(1))
_, replaced := r.Bind("a@b/c", func([]byte) error { return nil }, closeFn(2))
if !replaced {
t.Fatalf("expected replaced")
}
closedMu.Lock()
g := closedGen
closedMu.Unlock()
if g != 1 {
t.Fatalf("old slot closed gen=%d, want 1", g)
}
}
func TestSendStale(t *testing.T) {
r := NewRegistry()
var sent []byte
r.Bind("a@b/c", func(b []byte) error { sent = append([]byte(nil), b...); return nil }, func() {})
err := r.Send("a@b/c", 1, []byte("hello"))
if err != nil {
t.Fatalf("Send current gen: %v", err)
}
if string(sent) != "hello" {
t.Fatalf("sent = %q", sent)
}
if err := r.Send("a@b/c", 2, []byte("x")); !errors.Is(err, ErrStale) {
t.Fatalf("stale gen error = %v, want ErrStale", err)
}
if err := r.Send("unknown@b/c", 1, []byte("x")); !errors.Is(err, ErrStale) {
t.Fatalf("unknown jid error = %v, want ErrStale", err)
}
}
func TestBusFanOut(t *testing.T) {
b := NewBus()
var ready, announce, down, stanza int
o1 := &testObserver{
onReady: func() { ready++ },
onAnnounce: func() { announce++ },
onDown: func() { down++ },
onStanza: func() { stanza++ },
}
o2 := &testObserver{
onReady: func() { ready++ },
onAnnounce: func() { announce++ },
onDown: func() { down++ },
onStanza: func() { stanza++ },
}
b.Register(o1)
b.Register(o2)
b.SessionReady(ReadyEvent{})
b.AnnounceOK(ReadyEvent{})
b.SessionDown(DownEvent{})
b.Stanza(StanzaEvent{})
if ready != 2 || announce != 2 || down != 2 || stanza != 2 {
t.Fatalf("counts = %d/%d/%d/%d, want all 2", ready, announce, down, stanza)
}
}
func TestRemoveCurrentSlot(t *testing.T) {
r := NewRegistry()
r.Bind("a@b/c", nil, func() {})
if !r.Remove("a@b/c", 1) {
t.Fatalf("Remove current gen should succeed")
}
if _, ok := r.Current("a@b/c"); ok {
t.Fatalf("JID should no longer be current")
}
if r.Remove("a@b/c", 1) {
t.Fatalf("Remove same gen again should fail")
}
}
type testObserver struct {
onReady func()
onAnnounce func()
onDown func()
onStanza func()
}
func (o *testObserver) SessionReady(_ ReadyEvent) { o.onReady() }
func (o *testObserver) AnnounceOK(_ ReadyEvent) { o.onAnnounce() }
func (o *testObserver) SessionDown(_ DownEvent) { o.onDown() }
func (o *testObserver) Stanza(_ StanzaEvent) { o.onStanza() }