首次推送
This commit is contained in:
@@ -0,0 +1,248 @@
|
||||
package teamspeak
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestResetForConnectKeepsEventLoopAlive(t *testing.T) {
|
||||
c := newTestClient(t)
|
||||
voice := make(chan VoiceDataEvent, 1)
|
||||
c.OnVoiceData(func(event VoiceDataEvent) { voice <- event })
|
||||
|
||||
c.mu.Lock()
|
||||
c.resetForConnectLocked()
|
||||
c.mu.Unlock()
|
||||
c.notifyEvent(VoiceDataEvent{ClientID: 7, Sequence: 11, Data: []byte{1}})
|
||||
|
||||
select {
|
||||
case event := <-voice:
|
||||
if event.ClientID != 7 || event.Sequence != 11 {
|
||||
t.Fatalf("unexpected voice event: %+v", event)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("event loop stopped during connection reset")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnTextMessage_RegistersHandler(t *testing.T) {
|
||||
c := newTestClient(t)
|
||||
|
||||
called := make(chan TextMessage, 1)
|
||||
c.OnTextMessage(func(m TextMessage) { called <- m })
|
||||
c.rebuildMiddlewareChains()
|
||||
|
||||
c.finalEvtHandler(TextMessage{Message: "hi"})
|
||||
|
||||
select {
|
||||
case m := <-called:
|
||||
if m.Message != "hi" {
|
||||
t.Errorf("expected 'hi', got %q", m.Message)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Error("OnTextMessage handler not called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnClientLeave_RegistersHandler(t *testing.T) {
|
||||
c := newTestClient(t)
|
||||
|
||||
called := make(chan ClientLeftViewEvent, 1)
|
||||
c.OnClientLeave(func(e ClientLeftViewEvent) { called <- e })
|
||||
c.rebuildMiddlewareChains()
|
||||
|
||||
c.finalEvtHandler(ClientLeftViewEvent{ID: 5})
|
||||
|
||||
select {
|
||||
case e := <-called:
|
||||
if e.ID != 5 {
|
||||
t.Errorf("expected ID=5, got %d", e.ID)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Error("OnClientLeave handler not called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnDisconnected_RegistersHandler(t *testing.T) {
|
||||
c := newTestClient(t)
|
||||
|
||||
called := make(chan error, 1)
|
||||
c.OnDisconnected(func(err error) { called <- err })
|
||||
|
||||
// OnDisconnected handlers are called by onClosed; fire it directly.
|
||||
c.mu.Lock()
|
||||
handlers := c.disconnectedHandlers
|
||||
c.mu.Unlock()
|
||||
|
||||
for _, h := range handlers {
|
||||
go h(nil)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-called:
|
||||
case <-time.After(time.Second):
|
||||
t.Error("OnDisconnected handler not called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultipleHandlers_AllCalled(t *testing.T) {
|
||||
c := newTestClient(t)
|
||||
|
||||
a := make(chan struct{}, 1)
|
||||
b := make(chan struct{}, 1)
|
||||
c.OnTextMessage(func(_ TextMessage) { a <- struct{}{} })
|
||||
c.OnTextMessage(func(_ TextMessage) { b <- struct{}{} })
|
||||
c.rebuildMiddlewareChains()
|
||||
|
||||
c.finalEvtHandler(TextMessage{Message: "test"})
|
||||
|
||||
for _, ch := range []chan struct{}{a, b} {
|
||||
select {
|
||||
case <-ch:
|
||||
case <-time.After(time.Second):
|
||||
t.Error("not all handlers called")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUseCommandMiddleware_InterceptsCommands(t *testing.T) {
|
||||
c := newTestClient(t)
|
||||
|
||||
intercepted := make(chan string, 1)
|
||||
c.UseCommandMiddleware(func(next func(string) error) func(string) error {
|
||||
return func(cmd string) error {
|
||||
intercepted <- cmd
|
||||
|
||||
return next(cmd)
|
||||
}
|
||||
})
|
||||
|
||||
err := c.finalCmdHandler("test cmd")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case cmd := <-intercepted:
|
||||
if cmd != "test cmd" {
|
||||
t.Errorf("expected 'test cmd', got %q", cmd)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Error("middleware not called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUseCommandMiddleware_ChainOrder(t *testing.T) {
|
||||
c := newTestClient(t)
|
||||
|
||||
var order []string
|
||||
c.UseCommandMiddleware(
|
||||
func(next func(string) error) func(string) error {
|
||||
return func(cmd string) error {
|
||||
order = append(order, "first")
|
||||
|
||||
return next(cmd)
|
||||
}
|
||||
},
|
||||
func(next func(string) error) func(string) error {
|
||||
return func(cmd string) error {
|
||||
order = append(order, "second")
|
||||
|
||||
return next(cmd)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
_ = c.finalCmdHandler("x")
|
||||
|
||||
if len(order) != 2 || order[0] != "first" || order[1] != "second" {
|
||||
t.Errorf("unexpected middleware order: %v", order)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUseCommandMiddleware_CanShortCircuit(t *testing.T) {
|
||||
c := newTestClient(t)
|
||||
|
||||
sent := make(chan string, 1)
|
||||
c.UseCommandMiddleware(func(next func(string) error) func(string) error {
|
||||
return func(cmd string) error {
|
||||
if cmd == "blocked" {
|
||||
return nil // don't call next
|
||||
}
|
||||
|
||||
return next(cmd)
|
||||
}
|
||||
})
|
||||
|
||||
// Wrap the base handler to detect if it was called.
|
||||
origBase := c.finalCmdHandler
|
||||
c.finalCmdHandler = func(cmd string) error {
|
||||
sent <- cmd
|
||||
|
||||
return origBase(cmd)
|
||||
}
|
||||
// Re-apply middleware on top of new base.
|
||||
c.UseCommandMiddleware()
|
||||
|
||||
_ = c.SendCommandNoWait("blocked")
|
||||
|
||||
select {
|
||||
case <-sent:
|
||||
t.Error("short-circuited command should not reach base handler")
|
||||
case <-time.After(50 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
|
||||
func TestUseEventMiddleware_InterceptsEvents(t *testing.T) {
|
||||
c := newTestClient(t)
|
||||
|
||||
intercepted := make(chan any, 1)
|
||||
c.UseEventMiddleware(func(next func(any)) func(any) {
|
||||
return func(evt any) {
|
||||
intercepted <- evt
|
||||
next(evt)
|
||||
}
|
||||
})
|
||||
|
||||
c.finalEvtHandler(TextMessage{Message: "intercepted"})
|
||||
|
||||
select {
|
||||
case evt := <-intercepted:
|
||||
if m, ok := evt.(TextMessage); !ok || m.Message != "intercepted" {
|
||||
t.Errorf("unexpected event: %v", evt)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Error("event middleware not called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUseEventMiddleware_CanFilter(t *testing.T) {
|
||||
c := newTestClient(t)
|
||||
|
||||
reached := make(chan TextMessage, 1)
|
||||
c.OnTextMessage(func(m TextMessage) { reached <- m })
|
||||
|
||||
// Filter: block all text messages.
|
||||
c.UseEventMiddleware(func(next func(any)) func(any) {
|
||||
return func(evt any) {
|
||||
if _, ok := evt.(TextMessage); ok {
|
||||
return // drop
|
||||
}
|
||||
next(evt)
|
||||
}
|
||||
})
|
||||
|
||||
c.finalEvtHandler(TextMessage{Message: "filtered"})
|
||||
|
||||
select {
|
||||
case <-reached:
|
||||
t.Error("filtered event should not reach handler")
|
||||
case <-time.After(50 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
|
||||
func TestFinalEvtHandler_UnknownType_NoPanic(t *testing.T) {
|
||||
c := newTestClient(t)
|
||||
// Should not panic for an unhandled event type.
|
||||
c.finalEvtHandler(struct{ X int }{X: 42})
|
||||
}
|
||||
Reference in New Issue
Block a user