Files
bd2/go/internal/server/feature/feature_test.go
T
Flechazo d8771caef2 feat(all): add hunting and events, commerce and rewards, binary calendars, GameData caching and login diagnostics
Implement hunting AP and progress, event tasks, exchanges, games, stories and actions; connect battle and reward handling.

Add CashShop plugin and installation, server purchases and entitlements, recharge rules and plugin version metadata.

Distribute binary calendars independently; cache GameData in memory and fix single-connection query deadlocks.

Improve automatic login and recovery diagnostics; document configuration and release flows.
2026-10-05 11:50:31 +08:00

82 lines
3.6 KiB
Go

package feature
import (
"errors"
"testing"
"bd2server/internal/server/wire"
)
func TestHandleAuditedEmptyResponses(t *testing.T) {
for path, wantCode := range EmptyPacketCodes() {
t.Run(path, func(t *testing.T) {
gotCode, gotProto, ok, err := Handle(path, wire.AppendVarint(nil, 1, 42))
if err != nil || !ok || gotCode != wantCode || len(gotProto) != 0 {
t.Fatalf("Handle(%q): code=%d proto=%x ok=%t err=%v; want code=%d, empty, handled", path, gotCode, gotProto, ok, err, wantCode)
}
})
}
}
func TestHandleRejectsUnknownAndInvalidRequests(t *testing.T) {
for _, path := range []string{"/EventScheduleInfo", "/LoginEvent", "/ChargeCostInfo", "/EventMissionInfo", "/EventRewardHistory", "/PackEventStoryInfo", "/PackEventBattleInfo", "/Attendance", "/AttendanceInfo", "/FireWorksInfo", "/FriendshipSpecialEpisodeInfo", "/MiniEventHubInfo", "/PrestigeSkinInfo"} {
if _, _, ok, err := Handle(path, wire.AppendVarint(nil, 1, 1)); ok || err != nil {
t.Fatalf("stateful event route %s has stateless fallback", path)
}
}
for _, path := range []string{"/HuntDispatchInfo", "/HuntingGroundInfo", "/HuntingGroundInfoList", "/HuntingGroundEnter", "/UserLevelReward", "/FieldObjectInfo", "/WaypointInfo", "/WaypointSave", "/WaypointUse", "/AchievementInfo", "/AchievementUpdate", "/RecipeInfo", "/PackInfo", "/DeckInfo", "/RootSortIdInfo"} {
if _, _, handled, err := Handle(path, wire.AppendVarint(nil, 1, 1)); handled || err != nil {
t.Fatalf("stateful route %s still has a stateless success fallback", path)
}
}
if code, proto, ok, err := Handle("/not-a-real-endpoint", wire.AppendVarint(nil, 1, 1)); code != 0 || proto != nil || ok || err != nil {
t.Fatalf("unknown route was not fail-closed: code=%d proto=%x ok=%t err=%v", code, proto, ok, err)
}
if _, _, ok, err := Handle("/CharAwakeInfo", wire.AppendVarint(nil, 1, 1)); ok || err != nil {
t.Fatalf("stateful CharAwakeInfo must not be handled by feature defaults: ok=%v err=%v", ok, err)
}
for _, path := range []string{"/PackPreviewInfo", "/PackJamEvent", "/PresetInfo", "/DeckCostumeSettingInfo", "/FriendshipInfo", "/MasterTitleInfo", "/MasterTitleInfoUpdate"} {
if _, _, ok, err := Handle(path, wire.AppendVarint(nil, 1, 1)); ok || err != nil {
t.Fatalf("stateful %s must not be handled by feature defaults: ok=%v err=%v", path, ok, err)
}
}
for name, request := range map[string][]byte{
"empty": nil,
"no-sequence": wire.AppendVarint(nil, 2, 1),
"zero-sequence": wire.AppendVarint(nil, 1, 0),
"malformed": {0x08, 0x80},
} {
t.Run(name, func(t *testing.T) {
_, proto, ok, err := Handle("/QuestMaxClearInfo", request)
if !ok || proto != nil || !errors.Is(err, ErrInvalidRequest) {
t.Fatalf("invalid request: proto=%x ok=%t err=%v", proto, ok, err)
}
})
}
}
func TestEmptyPacketCodesReturnsCopy(t *testing.T) {
codes := EmptyPacketCodes()
codes["/QuestMaxClearInfo"] = -1
if code, _, ok, err := Handle("/QuestMaxClearInfo", wire.AppendVarint(nil, 1, 1)); err != nil || !ok || code != 137 {
t.Fatalf("registry escaped its copy: code=%d ok=%t err=%v", code, ok, err)
}
}
func TestStandaloneNativeDefaults(t *testing.T) {
for path, want := range map[string]int{
"/EquipInfo": 34,
"/TodayQuestInfo": 64,
"/UpdateAgeGate": 0,
"/ActiveMap": 0,
"/PvpBattleDeckInfo": 87,
"/PvpBattleHistory": 97,
"/PvpBattleOnceRewardInfo": 277,
} {
code, proto, ok, err := Handle(path, wire.AppendVarint(nil, 1, 55))
if err != nil || !ok || code != want || len(proto) != 0 {
t.Fatalf("%s: code=%d proto=%x ok=%v err=%v", path, code, proto, ok, err)
}
}
}