Files
GaCy-GO/internal/sdkserver/api_battle_report_live_test.go

147 lines
6.1 KiB
Go

package sdkserver
import (
"encoding/base64"
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"time"
"gac-hkrpg-go/internal/common"
goproto "gac-hkrpg-go/protocol/proto"
"google.golang.org/protobuf/proto"
)
func TestLiveBattleReportRoundTripAndExpiry(t *testing.T) {
configPath := filepath.Join(t.TempDir(), "server.json")
config := `{"account_name":"fixture","player_uid":52022,"activity_schedule":{"begin_time":0,"end_time":100},"srtool":{"lease_file":"fixture-session.json","lease_seconds":30},"battle_diagnostics":{"live_report_stale_seconds":10},"client_version":"fixture","game_host":"localhost","game_port":32101,"sdk_host":"localhost","sdk_port":32102,"public_game_host":"localhost","public_sdk_url":"http://localhost:32102"}`
if err := os.WriteFile(configPath, []byte(config), 0600); err != nil {
t.Fatal(err)
}
t.Setenv("GAC_CONFIG", configPath)
t.Setenv("GAC_LIVE_BATTLE_STALE_SECONDS", "10")
defer clearLiveBattleReport()
statistics := &goproto.BattleStatistics{
TotalBattleTurns: 2,
BattleAvatarList: []*goproto.AvatarBattleInfo{{
Id: 1204, StageId: 1052106, TotalDamage: 400,
AttackTypeDamage: []*goproto.AttackDamageProperty{{AttackType: "Normal", Damage: 400}},
}},
MonsterList: []*goproto.MonsterBattleInfo{{MonsterId: 5035011, TotalDamageTaken: 400}},
}
wire, err := proto.Marshal(statistics)
if err != nil {
t.Fatal(err)
}
requestBody, err := json.Marshal(liveBattleReportRequest{
Active: true, StatisticsBase64: base64.StdEncoding.EncodeToString(wire),
})
if err != nil {
t.Fatal(err)
}
post := httptest.NewRequest(http.MethodPost, "/api/battle_report/live", strings.NewReader(string(requestBody)))
postResponse := httptest.NewRecorder()
apiBattleReportLive(postResponse, post)
if postResponse.Code != http.StatusOK {
t.Fatalf("live POST status = %d, body = %s", postResponse.Code, postResponse.Body.String())
}
getResponse := httptest.NewRecorder()
apiBattleReport(getResponse, httptest.NewRequest(http.MethodGet, "/api/battle_report", nil))
var result struct {
IsLive bool `json:"is_live"`
Revision int64 `json:"revision"`
Report common.BattleReport `json:"report"`
}
if err := json.Unmarshal(getResponse.Body.Bytes(), &result); err != nil {
t.Fatal(err)
}
if !result.IsLive || result.Report.EndStatus != "LIVE" || result.Report.StageID != 1052106 {
t.Fatalf("unexpected live response: %+v", result)
}
if result.Report.TeamTotalDamage != 400 || result.Report.Avatars[0].DamagePercent != 100 || result.Revision == 0 {
t.Fatalf("unexpected live damage values: %+v", result.Report)
}
avatarSnapshots := []*goproto.AvatarBattleInfo{
{
Id: 1409, StageId: 1052106, TotalDamage: 600, TotalTurns: 2,
AttackTypeDamage: []*goproto.AttackDamageProperty{{AttackType: "BPSkill", Damage: 600}},
},
{
Id: 1507, StageId: 1052106, TotalDamage: 400, TotalTurns: 1,
AttackTypeDamage: []*goproto.AttackDamageProperty{{AttackType: "Normal", Damage: 400}},
},
}
avatarStatisticsBase64 := make([]string, 0, len(avatarSnapshots))
for _, avatar := range avatarSnapshots {
wire, err := proto.Marshal(avatar)
if err != nil {
t.Fatal(err)
}
avatarStatisticsBase64 = append(avatarStatisticsBase64, base64.StdEncoding.EncodeToString(wire))
}
requestBody, err = json.Marshal(liveBattleReportRequest{
Active: true,
AvatarStatisticsBase64: avatarStatisticsBase64,
TotalBattleTurns: 3,
})
if err != nil {
t.Fatal(err)
}
post = httptest.NewRequest(http.MethodPost, "/api/battle_report/live", strings.NewReader(string(requestBody)))
postResponse = httptest.NewRecorder()
apiBattleReportLive(postResponse, post)
if postResponse.Code != http.StatusOK {
t.Fatalf("avatar snapshot POST status = %d, body = %s", postResponse.Code, postResponse.Body.String())
}
getResponse = httptest.NewRecorder()
apiBattleReport(getResponse, httptest.NewRequest(http.MethodGet, "/api/battle_report", nil))
if err := json.Unmarshal(getResponse.Body.Bytes(), &result); err != nil {
t.Fatal(err)
}
if !result.IsLive || result.Report.TotalBattleTurns != 3 || result.Report.TeamTotalDamage != 1000 {
t.Fatalf("unexpected avatar-only live report: %+v", result)
}
if len(result.Report.Avatars) != 2 || result.Report.Avatars[0].DamagePercent != 60 || result.Report.Avatars[1].DamagePercent != 40 {
t.Fatalf("unexpected avatar-only live shares: %+v", result.Report.Avatars)
}
if result.Report.Avatars[0].AttackTypeDamage["BPSkill"] != 600 || result.Report.Avatars[1].AttackTypeDamage["Normal"] != 400 {
t.Fatalf("unexpected avatar-only live breakdown: %+v", result.Report.Avatars)
}
servantWire, _ := proto.Marshal(&goproto.BattleAvatarServantInfo{AvatarId: avatarSnapshots[1].Id, EntityId: 88, TotalDamage: 1000})
requestBody, _ = json.Marshal(liveBattleReportRequest{
Active: true, AvatarStatisticsBase64: avatarStatisticsBase64,
ServantStatisticsBase64: []string{base64.StdEncoding.EncodeToString(servantWire)},
ServantBreakdowns: []liveAvatarBreakdown{{Damage: map[string]float64{"BPSkill": 900}}},
})
postResponse = httptest.NewRecorder()
apiBattleReportLive(postResponse, httptest.NewRequest(http.MethodPost, "/api/battle_report/live", strings.NewReader(string(requestBody))))
if postResponse.Code != http.StatusOK {
t.Fatalf("servant POST: %s", postResponse.Body.String())
}
getResponse = httptest.NewRecorder()
apiBattleReport(getResponse, httptest.NewRequest(http.MethodGet, "/api/battle_report", nil))
if err := json.Unmarshal(getResponse.Body.Bytes(), &result); err != nil {
t.Fatal(err)
}
owner := result.Report.Avatars[1]
if !result.IsLive || result.Report.TeamTotalDamage != 2000 || owner.TotalDamage != 1400 || owner.MemospriteDamage != 1000 ||
owner.DamagePercent != 70 || owner.AttackTypeDamage["BPSkill"] != 900 {
t.Fatalf("servant data lost through live API: report=%+v owner=%+v", result.Report, owner)
}
liveBattleReportState.Lock()
liveBattleReportState.received = time.Now().Add(-11 * time.Second)
liveBattleReportState.Unlock()
if _, _, live, err := latestLiveBattleReport(); err != nil || live {
t.Fatalf("expired live report should be ignored, live=%t err=%v", live, err)
}
}