129 lines
3.1 KiB
Go
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() }
|