package connectsrv_test import ( "context" "net/http" "net/http/httptest" "testing" "time" "connectrpc.com/connect" "scrabble/gateway/internal/backendclient" "scrabble/gateway/internal/config" "scrabble/gateway/internal/connectsrv" "scrabble/gateway/internal/push" "scrabble/gateway/internal/ratelimit" "scrabble/gateway/internal/session" "scrabble/gateway/internal/transcode" edgev1 "scrabble/gateway/proto/edge/v1" "scrabble/gateway/proto/edge/v1/edgev1connect" fb "scrabble/pkg/fbs/scrabblefb" ) // newEdge wires a connectsrv.Server over a fake backend and returns a Connect // client plus a cleanup func. func newEdge(t *testing.T, backendHandler http.HandlerFunc) (edgev1connect.GatewayClient, func()) { t.Helper() backendSrv := httptest.NewServer(backendHandler) backend, err := backendclient.New(backendSrv.URL, "localhost:9090", 2*time.Second) if err != nil { t.Fatalf("backendclient: %v", err) } edge := connectsrv.NewServer(connectsrv.Deps{ Registry: transcode.NewRegistry(backend, nil), Sessions: session.NewCache(backend, time.Minute, 100), Limiter: ratelimit.New(), Hub: push.NewHub(0), RateLimit: config.DefaultRateLimit(), Heartbeat: 15 * time.Second, }) edgeSrv := httptest.NewServer(edge.HTTPHandler()) client := edgev1connect.NewGatewayClient(http.DefaultClient, edgeSrv.URL) return client, func() { edgeSrv.Close() _ = backend.Close() backendSrv.Close() } } func TestExecuteGuestAuthOK(t *testing.T) { client, cleanup := newEdge(t, func(w http.ResponseWriter, r *http.Request) { _, _ = w.Write([]byte(`{"token":"tok","user_id":"u-1","is_guest":true,"display_name":"Guest"}`)) }) defer cleanup() resp, err := client.Execute(context.Background(), connect.NewRequest(&edgev1.ExecuteRequest{ MessageType: transcode.MsgAuthGuest, RequestId: "req-1", })) if err != nil { t.Fatalf("execute: %v", err) } if resp.Msg.GetResultCode() != "ok" || resp.Msg.GetRequestId() != "req-1" { t.Fatalf("result = %q req_id = %q", resp.Msg.GetResultCode(), resp.Msg.GetRequestId()) } sess := fb.GetRootAsSession(resp.Msg.GetPayload(), 0) if string(sess.Token()) != "tok" || !sess.IsGuest() { t.Fatalf("session decoded wrong: %q guest=%v", sess.Token(), sess.IsGuest()) } } func TestExecuteAuthedRequiresSession(t *testing.T) { client, cleanup := newEdge(t, func(w http.ResponseWriter, r *http.Request) { t.Error("backend must not be called without a session") }) defer cleanup() _, err := client.Execute(context.Background(), connect.NewRequest(&edgev1.ExecuteRequest{ MessageType: transcode.MsgProfileGet, })) if connect.CodeOf(err) != connect.CodeUnauthenticated { t.Fatalf("code = %v, want Unauthenticated", connect.CodeOf(err)) } } func TestExecuteUnknownMessageType(t *testing.T) { client, cleanup := newEdge(t, func(w http.ResponseWriter, r *http.Request) {}) defer cleanup() _, err := client.Execute(context.Background(), connect.NewRequest(&edgev1.ExecuteRequest{ MessageType: "does.not.exist", })) if connect.CodeOf(err) != connect.CodeNotFound { t.Fatalf("code = %v, want NotFound", connect.CodeOf(err)) } }