Files
bd2/go/internal/server/session/level_reward_transaction_test.go
T
Flechazo d04791dd31 feat(server): add colored logs, level rewards, hunting dispatch and fiend hunt
Persist claims, AP, teams and presets with session receipts and atomic request rollback. Read rewards and growth from GameData; replace fixed Fiend Hunt user state and preserve the account initialization contract.
2026-10-04 21:27:19 +08:00

99 lines
2.8 KiB
Go

package session
import (
"encoding/base64"
"encoding/json"
"path/filepath"
"testing"
"bd2server/internal/server/accountstate"
"bd2server/internal/server/cryptox"
"bd2server/internal/server/gamedata"
"bd2server/internal/server/missions"
"bd2server/internal/server/player"
"bd2server/internal/server/protocol"
"bd2server/internal/server/wire"
)
func TestLevelRewardBatchRollsBackWalletInventoryAndClaimTogether(t *testing.T) {
path := filepath.Join(t.TempDir(), "state.db")
repo, err := accountstate.Open(path)
if err != nil {
t.Fatal(err)
}
defer repo.Close()
inv, err := player.OpenInventory(repo, &player.Starter{Version: "2.35.10"})
if err != nil {
t.Fatal(err)
}
wallet, err := player.OpenWallet(repo, player.Currency{Gold: 12})
if err != nil {
t.Fatal(err)
}
if err := inv.EnsurePersisted(); err != nil {
t.Fatal(err)
}
if err := wallet.EnsurePersisted(); err != nil {
t.Fatal(err)
}
design := &gamedata.MissionDesign{}
m, err := missions.Open(repo, design, inv)
if err != nil {
t.Fatal(err)
}
if err := m.AttachWallet(wallet); err != nil {
t.Fatal(err)
}
levels := &gamedata.AchievementLevelDesign{Levels: []gamedata.AchievementLevel{{ID: 1, NeedEXP: 10, Rewards: []gamedata.Reward{{Type: 4, Count: 100}, {Type: 8, ID: 987, Count: 3}}}}}
if err := m.AttachUserLevelRewards(levels); err != nil {
t.Fatal(err)
}
server, err := NewServer(fakeLogin{}, m, &mutatingDomain{store: repo})
if err != nil {
t.Fatal(err)
}
if err := server.AttachStateStore(repo); err != nil {
t.Fatal(err)
}
session := login(t, server)
request := wire.AppendVarint(wire.AppendVarint(nil, 1, 2), 2, 1)
batch := []protocol.BatchRequest{
{Path: "/UserLevelReward", RequestData: base64.StdEncoding.EncodeToString(request)},
{Path: "/InjectedFailure", RequestData: base64.StdEncoding.EncodeToString(wire.AppendVarint(nil, 1, 3))},
}
plain, _ := json.Marshal(batch)
body, _ := cryptox.EncryptBase64(plain, server.KeyForTest())
if _, err := server.DispatchRaw("/BatchRequest", []byte(body), "s="+session.Cookie); err == nil {
t.Fatal("failing batch accepted")
}
if err := repo.Close(); err != nil {
t.Fatal(err)
}
reopened, err := accountstate.Open(path)
if err != nil {
t.Fatal(err)
}
defer reopened.Close()
inv, err = player.OpenInventory(reopened, &player.Starter{Version: "2.35.10"})
if err != nil {
t.Fatal(err)
}
wallet, err = player.OpenWallet(reopened, player.Currency{})
if err != nil {
t.Fatal(err)
}
m, err = missions.Open(reopened, design, inv)
if err != nil {
t.Fatal(err)
}
if err := m.AttachUserLevelRewards(levels); err != nil {
t.Fatal(err)
}
if got, err := m.LevelRewardCount(); err != nil || got != 0 {
t.Fatalf("claim survived rollback: %d %v", got, err)
}
if len(inv.All()) != 0 || wallet.Snapshot().Gold != 12 {
t.Fatalf("rewards survived rollback: %+v %+v", inv.All(), wallet.Snapshot())
}
}