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.
99 lines
2.8 KiB
Go
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())
|
|
}
|
|
}
|