430 lines
14 KiB
Go
430 lines
14 KiB
Go
package router
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"chatapp3-golang/internal/common"
|
|
"chatapp3-golang/internal/integration"
|
|
"chatapp3-golang/internal/service/gameprovider"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func TestPublicRoomGameListResponseKeepsLegacyProviderFields(t *testing.T) {
|
|
resp := publicRoomGameListResponse(&gameprovider.RoomGameListResponse{
|
|
Items: []gameprovider.RoomGameListItem{
|
|
{
|
|
ID: 9527,
|
|
GameID: "bs_1046",
|
|
GameType: "BAISHUN",
|
|
Provider: "BAISHUN",
|
|
ProviderGameID: "1046",
|
|
Name: "Lucky77Pro",
|
|
},
|
|
},
|
|
})
|
|
|
|
if len(resp.Items) != 1 {
|
|
t.Fatalf("items = %d, want 1", len(resp.Items))
|
|
}
|
|
item := resp.Items[0]
|
|
if item.Provider != "BAISHUN" {
|
|
t.Fatalf("provider = %q, want BAISHUN", item.Provider)
|
|
}
|
|
if item.VendorType != "BAISHUN" {
|
|
t.Fatalf("vendorType = %q, want BAISHUN", item.VendorType)
|
|
}
|
|
if item.ProviderGameID != "1046" {
|
|
t.Fatalf("providerGameId = %q, want 1046", item.ProviderGameID)
|
|
}
|
|
if item.VendorGameID != "1046" {
|
|
t.Fatalf("vendorGameId = %q, want 1046", item.VendorGameID)
|
|
}
|
|
}
|
|
|
|
func TestPublicRoomGameListResponseMapsLingxianToLeaderForOldClients(t *testing.T) {
|
|
resp := publicRoomGameListResponse(&gameprovider.RoomGameListResponse{
|
|
Items: []gameprovider.RoomGameListItem{
|
|
{
|
|
ID: 9528,
|
|
GameID: "1090",
|
|
GameType: "LINGXIAN",
|
|
Provider: "LINGXIAN",
|
|
ProviderGameID: "1090",
|
|
Name: "Lingxian Game",
|
|
LaunchParams: map[string]any{"gameType": "LINGXIAN", "screenMode": "half"},
|
|
},
|
|
},
|
|
})
|
|
|
|
if len(resp.Items) != 1 {
|
|
t.Fatalf("items = %d, want 1", len(resp.Items))
|
|
}
|
|
item := resp.Items[0]
|
|
if item.Provider != "LEADER" {
|
|
t.Fatalf("provider = %q, want LEADER", item.Provider)
|
|
}
|
|
if item.GameType != "LEADER" {
|
|
t.Fatalf("gameType = %q, want LEADER", item.GameType)
|
|
}
|
|
if item.VendorType != "LEADER" {
|
|
t.Fatalf("vendorType = %q, want LEADER", item.VendorType)
|
|
}
|
|
if got := item.LaunchParams["gameType"]; got != "LEADER" {
|
|
t.Fatalf("launchParams.gameType = %v, want LEADER", got)
|
|
}
|
|
if got := item.LaunchParams["screenMode"]; got != "half" {
|
|
t.Fatalf("launchParams.screenMode = %v, want half", got)
|
|
}
|
|
}
|
|
|
|
func TestPublicRoomGameListResponseMapsHotgameAliasesToLeaderForOldClients(t *testing.T) {
|
|
for _, alias := range []string{"HOTGAME", "HOT_GAME", "REYOU", "LALU"} {
|
|
resp := publicRoomGameListResponse(&gameprovider.RoomGameListResponse{
|
|
Items: []gameprovider.RoomGameListItem{
|
|
{
|
|
ID: 9530,
|
|
GameID: "hg_1",
|
|
GameType: alias,
|
|
Provider: alias,
|
|
ProviderGameID: "1",
|
|
Name: "Hotgame",
|
|
LaunchParams: map[string]any{"gameType": alias, "screenMode": "seven"},
|
|
},
|
|
},
|
|
})
|
|
|
|
if len(resp.Items) != 1 {
|
|
t.Fatalf("%s items = %d, want 1", alias, len(resp.Items))
|
|
}
|
|
item := resp.Items[0]
|
|
if item.Provider != "LEADER" {
|
|
t.Fatalf("%s provider = %q, want LEADER", alias, item.Provider)
|
|
}
|
|
if item.GameType != "LEADER" {
|
|
t.Fatalf("%s gameType = %q, want LEADER", alias, item.GameType)
|
|
}
|
|
if item.VendorType != "LEADER" {
|
|
t.Fatalf("%s vendorType = %q, want LEADER", alias, item.VendorType)
|
|
}
|
|
if got := item.LaunchParams["gameType"]; got != "LEADER" {
|
|
t.Fatalf("%s launchParams.gameType = %v, want LEADER", alias, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPublicLaunchKeepsLegacyBridgeAndProviderFields(t *testing.T) {
|
|
launchConfig := map[string]any{"code": "launch-code"}
|
|
resp := publicLaunch(&gameprovider.LaunchResponse{
|
|
ID: 9527,
|
|
GameSessionID: "bs_room_1",
|
|
Provider: "BAISHUN",
|
|
GameID: "bs_1046",
|
|
ProviderGameID: "1046",
|
|
LaunchConfig: launchConfig,
|
|
RoomState: gameprovider.RoomStateResponse{
|
|
RoomID: "room-1",
|
|
State: "PLAYING",
|
|
Provider: "BAISHUN",
|
|
CurrentProviderGameID: "1046",
|
|
},
|
|
})
|
|
|
|
if resp.Provider != "BAISHUN" {
|
|
t.Fatalf("provider = %q, want BAISHUN", resp.Provider)
|
|
}
|
|
if resp.VendorType != "BAISHUN" {
|
|
t.Fatalf("vendorType = %q, want BAISHUN", resp.VendorType)
|
|
}
|
|
if resp.VendorGameID != "1046" {
|
|
t.Fatalf("vendorGameId = %q, want 1046", resp.VendorGameID)
|
|
}
|
|
bridgeConfig, ok := resp.BridgeConfig.(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("bridgeConfig type = %T, want map[string]any", resp.BridgeConfig)
|
|
}
|
|
if got := bridgeConfig["code"]; got != "launch-code" {
|
|
t.Fatalf("bridgeConfig[code] = %v, want launch-code", got)
|
|
}
|
|
if resp.RoomState.Provider != "BAISHUN" {
|
|
t.Fatalf("roomState.provider = %q, want BAISHUN", resp.RoomState.Provider)
|
|
}
|
|
if resp.RoomState.CurrentVendorGameID != "1046" {
|
|
t.Fatalf("roomState.currentVendorGameId = %q, want 1046", resp.RoomState.CurrentVendorGameID)
|
|
}
|
|
}
|
|
|
|
func TestPublicLaunchMapsLingxianToLeaderForOldClients(t *testing.T) {
|
|
resp := publicLaunch(&gameprovider.LaunchResponse{
|
|
ID: 9528,
|
|
GameSessionID: "lx_1_1090",
|
|
Provider: "LINGXIAN",
|
|
GameID: "1090",
|
|
ProviderGameID: "1090",
|
|
LaunchConfig: map[string]any{"uid": "user-1"},
|
|
RoomState: gameprovider.RoomStateResponse{
|
|
RoomID: "room-1",
|
|
State: "PLAYING",
|
|
Provider: "LINGXIAN",
|
|
CurrentProviderGameID: "1090",
|
|
},
|
|
})
|
|
|
|
if resp.Provider != "LEADER" {
|
|
t.Fatalf("provider = %q, want LEADER", resp.Provider)
|
|
}
|
|
if resp.VendorType != "LEADER" {
|
|
t.Fatalf("vendorType = %q, want LEADER", resp.VendorType)
|
|
}
|
|
if resp.RoomState.Provider != "LEADER" {
|
|
t.Fatalf("roomState.provider = %q, want LEADER", resp.RoomState.Provider)
|
|
}
|
|
}
|
|
|
|
func TestGameProviderRoutesReturnEmptyWhenVisibilityPolicyDenies(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
provider := &routeStubProvider{}
|
|
engine := gin.New()
|
|
registerGameProviderRoutes(
|
|
engine,
|
|
routeStubAuthGateway{},
|
|
gameprovider.NewRegistry(provider),
|
|
gameprovider.NewVisibilityPolicy(
|
|
routeStubVisibilityGateway{
|
|
region: integration.UserRegion{RegionID: "2046066409959649281", RegionCode: "土耳其"},
|
|
level: integration.UserLevel{WealthLevel: 2},
|
|
targetRegionCode: "土耳其",
|
|
},
|
|
routeStubIPCountryResolver{countryCode: "TR"},
|
|
),
|
|
)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/app/game/room/list?roomId=1", nil)
|
|
req.Header.Set("Authorization", "Bearer token")
|
|
rec := httptest.NewRecorder()
|
|
engine.ServeHTTP(rec, req)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want %d: %s", rec.Code, http.StatusOK, rec.Body.String())
|
|
}
|
|
var payload struct {
|
|
Body struct {
|
|
Items []publicRoomGameItem `json:"items"`
|
|
} `json:"body"`
|
|
}
|
|
if err := json.Unmarshal(rec.Body.Bytes(), &payload); err != nil {
|
|
t.Fatalf("response json error = %v: %s", err, rec.Body.String())
|
|
}
|
|
if len(payload.Body.Items) != 0 {
|
|
t.Fatalf("items = %d, want 0", len(payload.Body.Items))
|
|
}
|
|
if provider.listRoomCalls != 0 {
|
|
t.Fatalf("provider list calls = %d, want 0", provider.listRoomCalls)
|
|
}
|
|
}
|
|
|
|
func TestGameProviderRoutesReturnProvidersWhenVisibilityPolicyAllows(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
engine := gin.New()
|
|
registerGameProviderRoutes(
|
|
engine,
|
|
routeStubAuthGateway{},
|
|
gameprovider.NewRegistry(&routeStubProvider{}),
|
|
gameprovider.NewVisibilityPolicy(
|
|
routeStubVisibilityGateway{
|
|
region: integration.UserRegion{RegionID: "2046066409959649281", RegionCode: "土耳其"},
|
|
level: integration.UserLevel{WealthLevel: 3},
|
|
targetRegionCode: "土耳其",
|
|
},
|
|
routeStubIPCountryResolver{countryCode: "ZA"},
|
|
),
|
|
)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/app/game/providers", nil)
|
|
req.Header.Set("Authorization", "Bearer token")
|
|
req.Header.Set("X-Real-IP", "88.255.1.1")
|
|
rec := httptest.NewRecorder()
|
|
engine.ServeHTTP(rec, req)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want %d: %s", rec.Code, http.StatusOK, rec.Body.String())
|
|
}
|
|
var payload struct {
|
|
Body struct {
|
|
Items []gameprovider.ProviderSummary `json:"items"`
|
|
} `json:"body"`
|
|
}
|
|
if err := json.Unmarshal(rec.Body.Bytes(), &payload); err != nil {
|
|
t.Fatalf("response json error = %v: %s", err, rec.Body.String())
|
|
}
|
|
if len(payload.Body.Items) != 1 {
|
|
t.Fatalf("providers = %d, want 1", len(payload.Body.Items))
|
|
}
|
|
if payload.Body.Items[0].Key != "TEST" {
|
|
t.Fatalf("provider key = %q, want TEST", payload.Body.Items[0].Key)
|
|
}
|
|
}
|
|
|
|
func TestProviderLaunchFallsBackToRegistryWhenLegacyProviderCannotFindGame(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
engine := gin.New()
|
|
registerGameProviderRoutes(
|
|
engine,
|
|
routeStubAuthGateway{},
|
|
gameprovider.NewRegistry(
|
|
&routeLaunchStubProvider{key: "LINGXIAN"},
|
|
&routeLaunchStubProvider{key: "HOTGAME", matchGameID: "hg_1"},
|
|
),
|
|
nil,
|
|
)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/app/game/providers/LEADER/launch", strings.NewReader(`{"roomId":"room-1","gameId":"hg_1"}`))
|
|
req.Header.Set("Authorization", "Bearer token")
|
|
req.Header.Set("Content-Type", "application/json")
|
|
rec := httptest.NewRecorder()
|
|
engine.ServeHTTP(rec, req)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want %d: %s", rec.Code, http.StatusOK, rec.Body.String())
|
|
}
|
|
var payload struct {
|
|
Body publicLaunchResponse `json:"body"`
|
|
}
|
|
if err := json.Unmarshal(rec.Body.Bytes(), &payload); err != nil {
|
|
t.Fatalf("response json error = %v: %s", err, rec.Body.String())
|
|
}
|
|
if payload.Body.GameID != "hg_1" {
|
|
t.Fatalf("gameId = %q, want hg_1", payload.Body.GameID)
|
|
}
|
|
if payload.Body.Provider != "LEADER" {
|
|
t.Fatalf("provider = %q, want LEADER for old-client compat", payload.Body.Provider)
|
|
}
|
|
if payload.Body.GameSessionID != "hg-session" {
|
|
t.Fatalf("gameSessionId = %q, want hg-session", payload.Body.GameSessionID)
|
|
}
|
|
}
|
|
|
|
type routeStubAuthGateway struct{}
|
|
|
|
func (routeStubAuthGateway) AuthenticateToken(context.Context, string) (integration.UserCredential, error) {
|
|
return integration.UserCredential{UserID: integration.Int64Value(1001), SysOrigin: "LIKEI"}, nil
|
|
}
|
|
|
|
func (routeStubAuthGateway) AuthenticateConsoleToken(context.Context, string) (integration.ConsoleAccount, error) {
|
|
return integration.ConsoleAccount{}, nil
|
|
}
|
|
|
|
type routeStubVisibilityGateway struct {
|
|
region integration.UserRegion
|
|
level integration.UserLevel
|
|
targetRegionCode string
|
|
}
|
|
|
|
func (s routeStubVisibilityGateway) GetUserRegion(context.Context, int64, string) (integration.UserRegion, error) {
|
|
return s.region, nil
|
|
}
|
|
|
|
func (s routeStubVisibilityGateway) GetUserLevel(context.Context, string, int64) (integration.UserLevel, error) {
|
|
return s.level, nil
|
|
}
|
|
|
|
func (s routeStubVisibilityGateway) ResolveRegionCodeByCountryCode(context.Context, string, string) (string, error) {
|
|
return s.targetRegionCode, nil
|
|
}
|
|
|
|
type routeStubIPCountryResolver struct {
|
|
countryCode string
|
|
}
|
|
|
|
func (s routeStubIPCountryResolver) CountryCode(context.Context, string) (string, error) {
|
|
return s.countryCode, nil
|
|
}
|
|
|
|
type routeStubProvider struct {
|
|
listRoomCalls int
|
|
}
|
|
|
|
func (p *routeStubProvider) Key() string { return "TEST" }
|
|
|
|
func (p *routeStubProvider) DisplayName() string { return "Test Provider" }
|
|
|
|
func (p *routeStubProvider) SupportsLaunch(context.Context, gameprovider.AuthUser, gameprovider.LaunchRequest) (bool, error) {
|
|
return false, nil
|
|
}
|
|
|
|
func (p *routeStubProvider) ListShortcutGames(context.Context, gameprovider.AuthUser, string) ([]gameprovider.RoomGameListItem, error) {
|
|
return []gameprovider.RoomGameListItem{{ID: 1, GameID: "test_1", Provider: "TEST", ProviderGameID: "1", Name: "Test Game"}}, nil
|
|
}
|
|
|
|
func (p *routeStubProvider) ListRoomGames(context.Context, gameprovider.AuthUser, string, string) (*gameprovider.RoomGameListResponse, error) {
|
|
p.listRoomCalls++
|
|
return &gameprovider.RoomGameListResponse{
|
|
Items: []gameprovider.RoomGameListItem{{ID: 1, GameID: "test_1", Provider: "TEST", ProviderGameID: "1", Name: "Test Game"}},
|
|
}, nil
|
|
}
|
|
|
|
func (p *routeStubProvider) GetRoomState(context.Context, gameprovider.AuthUser, string) (*gameprovider.RoomStateResponse, error) {
|
|
return &gameprovider.RoomStateResponse{}, nil
|
|
}
|
|
|
|
func (p *routeStubProvider) LaunchGame(context.Context, gameprovider.AuthUser, gameprovider.LaunchRequest, string) (*gameprovider.LaunchResponse, error) {
|
|
return nil, common.NewAppError(http.StatusBadRequest, "unsupported", "unsupported")
|
|
}
|
|
|
|
func (p *routeStubProvider) CloseGame(context.Context, gameprovider.AuthUser, gameprovider.CloseRequest) (*gameprovider.RoomStateResponse, error) {
|
|
return &gameprovider.RoomStateResponse{}, nil
|
|
}
|
|
|
|
type routeLaunchStubProvider struct {
|
|
key string
|
|
matchGameID string
|
|
}
|
|
|
|
func (p *routeLaunchStubProvider) Key() string { return p.key }
|
|
|
|
func (p *routeLaunchStubProvider) DisplayName() string { return p.key }
|
|
|
|
func (p *routeLaunchStubProvider) SupportsLaunch(_ context.Context, _ gameprovider.AuthUser, req gameprovider.LaunchRequest) (bool, error) {
|
|
return p.matchGameID != "" && req.GameID == p.matchGameID, nil
|
|
}
|
|
|
|
func (p *routeLaunchStubProvider) ListShortcutGames(context.Context, gameprovider.AuthUser, string) ([]gameprovider.RoomGameListItem, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (p *routeLaunchStubProvider) ListRoomGames(context.Context, gameprovider.AuthUser, string, string) (*gameprovider.RoomGameListResponse, error) {
|
|
return &gameprovider.RoomGameListResponse{}, nil
|
|
}
|
|
|
|
func (p *routeLaunchStubProvider) GetRoomState(context.Context, gameprovider.AuthUser, string) (*gameprovider.RoomStateResponse, error) {
|
|
return &gameprovider.RoomStateResponse{}, nil
|
|
}
|
|
|
|
func (p *routeLaunchStubProvider) LaunchGame(_ context.Context, _ gameprovider.AuthUser, req gameprovider.LaunchRequest, _ string) (*gameprovider.LaunchResponse, error) {
|
|
if p.matchGameID == "" || req.GameID != p.matchGameID {
|
|
return nil, common.NewAppError(http.StatusNotFound, "game_not_found", "game not found")
|
|
}
|
|
return &gameprovider.LaunchResponse{
|
|
GameSessionID: "hg-session",
|
|
Provider: p.key,
|
|
GameID: req.GameID,
|
|
ProviderGameID: "1",
|
|
Entry: gameprovider.LaunchEntry{LaunchMode: "H5_REMOTE"},
|
|
RoomState: gameprovider.RoomStateResponse{
|
|
RoomID: req.RoomID,
|
|
State: "PLAYING",
|
|
Provider: p.key,
|
|
GameSessionID: "hg-session",
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (p *routeLaunchStubProvider) CloseGame(context.Context, gameprovider.AuthUser, gameprovider.CloseRequest) (*gameprovider.RoomStateResponse, error) {
|
|
return &gameprovider.RoomStateResponse{}, nil
|
|
}
|