107 lines
2.9 KiB
Go
107 lines
2.9 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/gorilla/websocket"
|
|
|
|
apimw "github.com/Silo-Server/silo-server/internal/api/middleware"
|
|
"github.com/Silo-Server/silo-server/internal/auth"
|
|
"github.com/Silo-Server/silo-server/internal/playback"
|
|
)
|
|
|
|
func TestHandleSessionWebSocket_RequiresHelloBeforeRealtimeReady(t *testing.T) {
|
|
sessionMgr := playback.NewSessionManager(0, 0)
|
|
session, err := sessionMgr.StartSession(1, "profile-1", 100, playback.PlayDirect, false)
|
|
if err != nil {
|
|
t.Fatalf("StartSession: %v", err)
|
|
}
|
|
|
|
handler := NewPlaybackHandler(sessionMgr)
|
|
handler.RealtimeHub = playback.NewRealtimeHub()
|
|
|
|
router := chi.NewRouter()
|
|
router.Get("/playback/ws/{session_id}", func(w http.ResponseWriter, r *http.Request) {
|
|
ctx := apimw.SetClaims(r.Context(), &auth.Claims{UserID: 1, Role: "user", TokenType: auth.TokenTypeAccess})
|
|
handler.HandleSessionWebSocket(w, r.WithContext(ctx))
|
|
})
|
|
|
|
server := httptest.NewServer(router)
|
|
defer server.Close()
|
|
|
|
wsURL := "ws" + strings.TrimPrefix(server.URL, "http") + "/playback/ws/" + session.ID
|
|
conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
|
|
if err != nil {
|
|
t.Fatalf("Dial websocket: %v", err)
|
|
}
|
|
defer conn.Close()
|
|
|
|
got, err := sessionMgr.GetSession(session.ID)
|
|
if err != nil {
|
|
t.Fatalf("GetSession before hello: %v", err)
|
|
}
|
|
if got.HasRealtimeConnection {
|
|
t.Fatal("session should not be realtime-ready before hello")
|
|
}
|
|
if got.HasWebSocket {
|
|
t.Fatal("session should not report playback control before hello")
|
|
}
|
|
|
|
if err := conn.WriteJSON(playback.HelloEnvelope{
|
|
Type: playback.RealtimeMessageTypeHello,
|
|
SessionID: session.ID,
|
|
Client: playback.HelloClientInfo{
|
|
Name: "ios",
|
|
Version: "1.0.0",
|
|
},
|
|
Capabilities: playback.HelloCapabilities{
|
|
Commands: []playback.CommandName{
|
|
playback.CommandPause,
|
|
playback.CommandUnpause,
|
|
playback.CommandStop,
|
|
playback.CommandTerminate,
|
|
},
|
|
},
|
|
}); err != nil {
|
|
t.Fatalf("WriteJSON hello: %v", err)
|
|
}
|
|
|
|
waitForPlaybackRealtimeState(t, sessionMgr, session.ID, true)
|
|
|
|
if err := conn.Close(); err != nil {
|
|
t.Fatalf("Close websocket: %v", err)
|
|
}
|
|
|
|
waitForPlaybackRealtimeState(t, sessionMgr, session.ID, false)
|
|
}
|
|
|
|
func waitForPlaybackRealtimeState(t *testing.T, sessionMgr *playback.SessionManager, sessionID string, want bool) {
|
|
t.Helper()
|
|
|
|
deadline := time.Now().Add(time.Second)
|
|
for time.Now().Before(deadline) {
|
|
session, err := sessionMgr.GetSession(sessionID)
|
|
if err == nil && session != nil && session.HasRealtimeConnection == want && session.HasWebSocket == want {
|
|
return
|
|
}
|
|
time.Sleep(10 * time.Millisecond)
|
|
}
|
|
|
|
session, err := sessionMgr.GetSession(sessionID)
|
|
if err != nil {
|
|
t.Fatalf("GetSession after wait: %v", err)
|
|
}
|
|
t.Fatalf(
|
|
"session realtime state = %v/%v, want %v/%v",
|
|
session.HasRealtimeConnection,
|
|
session.HasWebSocket,
|
|
want,
|
|
want,
|
|
)
|
|
}
|