179 lines
5.8 KiB
Go
179 lines
5.8 KiB
Go
package common
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func loadCurrencyWarsTestCatalog(t *testing.T) *CurrencyWarsCatalog {
|
|
t.Helper()
|
|
raw, err := ReadResourceFile("resources/CurrencyWarsCatalog.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var catalog CurrencyWarsCatalog
|
|
if err := json.Unmarshal(raw, &catalog); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := catalog.validate(catalog.ClientVersion); err != nil {
|
|
t.Fatalf("validate captured CW catalog: %v", err)
|
|
}
|
|
if err := catalog.resolveActivity(); err != nil {
|
|
t.Fatalf("resolve captured CW activities: %v", err)
|
|
}
|
|
if err := catalog.validateRoutes(); err != nil {
|
|
t.Fatalf("validate captured CW routes: %v", err)
|
|
}
|
|
if err := catalog.validateCapturedGameplay(); err != nil {
|
|
t.Fatalf("validate captured CW role/stage data: %v", err)
|
|
}
|
|
if err := catalog.validateEntrance(); err != nil {
|
|
t.Fatalf("validate captured CW entrance: %v", err)
|
|
}
|
|
return &catalog
|
|
}
|
|
|
|
func TestCurrencyWarsCapturedCatalogAndConfiguredVersion(t *testing.T) {
|
|
catalog := loadCurrencyWarsTestCatalog(t)
|
|
if len(catalog.ActivitySchedules()) == 0 || len(catalog.CapturedRoles) == 0 || len(catalog.CapturedStages) == 0 {
|
|
t.Fatal("captured CW activity, role, or stage data is empty")
|
|
}
|
|
if err := catalog.validate(catalog.ClientVersion + "-mismatch"); err == nil {
|
|
t.Fatal("CW catalog accepted a different Client version")
|
|
}
|
|
}
|
|
|
|
func TestCurrencyWarsCatalogLookupsReturnIsolatedCopies(t *testing.T) {
|
|
catalog := loadCurrencyWarsTestCatalog(t)
|
|
|
|
roleBefore, err := catalog.CapturedRole(catalog.CapturedRoles[0].Config.ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
role, err := catalog.CapturedRole(catalog.CapturedRoles[0].Config.ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(role.Config.TraitList) > 0 {
|
|
role.Config.TraitList[0]++
|
|
}
|
|
roleAfter, err := catalog.CapturedRole(catalog.CapturedRoles[0].Config.ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(roleBefore.Config.TraitList) > 0 && roleAfter.Config.TraitList[0] != roleBefore.Config.TraitList[0] {
|
|
t.Fatal("mutating a returned CW role changed catalog data")
|
|
}
|
|
|
|
stageBefore, err := catalog.CapturedStage(catalog.CapturedStages[0].ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
stage, err := catalog.CapturedStage(catalog.CapturedStages[0].ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(stage.EnvironmentBuffList) > 0 {
|
|
stage.EnvironmentBuffList[0]++
|
|
}
|
|
stageAfter, err := catalog.CapturedStage(catalog.CapturedStages[0].ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(stageBefore.EnvironmentBuffList) > 0 && stageAfter.EnvironmentBuffList[0] != stageBefore.EnvironmentBuffList[0] {
|
|
t.Fatal("mutating a returned CW stage changed catalog data")
|
|
}
|
|
|
|
routeID := catalog.StageRoutes[0].RouteID
|
|
routeBefore, err := catalog.RouteNodes(routeID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
route, err := catalog.RouteNodes(routeID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
route[0].NodeTemplateID++
|
|
routeAfter, err := catalog.RouteNodes(routeID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if routeAfter[0].NodeTemplateID != routeBefore[0].NodeTemplateID {
|
|
t.Fatal("mutating a returned CW route changed catalog data")
|
|
}
|
|
}
|
|
|
|
func TestCurrencyWarsCapturedEconomyRules(t *testing.T) {
|
|
catalog := loadCurrencyWarsTestCatalog(t)
|
|
role := catalog.CapturedRoles[0]
|
|
|
|
price, err := catalog.BaseSalePrice(role.Config.ID, role.DefaultStar)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if price != role.DefaultSellPrice {
|
|
t.Fatalf("captured base sale price = %d, want native row value %d", price, role.DefaultSellPrice)
|
|
}
|
|
if _, err := catalog.BaseSalePrice(role.Config.ID, role.MaxStar+1); err == nil {
|
|
t.Fatal("sale price accepted an uncaptured star rank")
|
|
}
|
|
|
|
deposit, err := catalog.IntegerRule("GridFight_DepositPerInterest")
|
|
if err != nil || deposit <= 0 {
|
|
t.Fatalf("invalid captured deposit rule %d: %v", deposit, err)
|
|
}
|
|
gold := uint32(deposit*3 + deposit/2)
|
|
interest, err := catalog.BaseInterest(gold, 2)
|
|
if err != nil || interest != 2 {
|
|
t.Fatalf("base interest = %d, %v; want integer division capped at 2", interest, err)
|
|
}
|
|
zeroCapped, err := catalog.BaseInterest(gold, 0)
|
|
if err != nil || zeroCapped != 0 {
|
|
t.Fatalf("zero-cap interest = %d, %v; want 0", zeroCapped, err)
|
|
}
|
|
}
|
|
|
|
func TestCurrencyWarsSnapshotRevisionPreventsStaleWrites(t *testing.T) {
|
|
t.Chdir(t.TempDir())
|
|
const assemblyHash = "abababababababababababababababababababababababababababababababab"
|
|
if err := os.WriteFile("persistent", []byte(`{"other_service":{"counter":9007199254740993}}`), 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
first := NewCurrencyWarsSnapshot(42, "4.6.53", assemblyHash, []byte{0x0a, 0x01, 0x01})
|
|
revision, err := CommitCurrencyWarsSnapshot(0, first)
|
|
if err != nil || revision != 1 {
|
|
t.Fatalf("first CW commit = revision %d, %v; want revision 1", revision, err)
|
|
}
|
|
|
|
stale := NewCurrencyWarsSnapshot(42, "4.6.53", assemblyHash, []byte{0x0a, 0x01, 0x02})
|
|
if _, err := CommitCurrencyWarsSnapshot(0, stale); err != ErrCurrencyWarsSaveConflict {
|
|
t.Fatalf("stale CW commit error = %v; want save conflict", err)
|
|
}
|
|
|
|
saved, err := ReadCurrencyWarsSnapshot(42, "4.6.53", assemblyHash)
|
|
if err != nil || saved.Revision != 1 || !bytes.Equal(saved.WireData, first.WireData) {
|
|
t.Fatalf("stale write changed saved CW snapshot: %+v, %v", saved, err)
|
|
}
|
|
|
|
next := NewCurrencyWarsSnapshot(42, "4.6.53", assemblyHash, []byte{0x0a, 0x01, 0x03})
|
|
revision, err = CommitCurrencyWarsSnapshot(1, next)
|
|
if err != nil || revision != 2 {
|
|
t.Fatalf("next CW commit = revision %d, %v; want revision 2", revision, err)
|
|
}
|
|
if _, err := ReadCurrencyWarsSnapshot(42, "6.1", assemblyHash); err == nil {
|
|
t.Fatal("CW snapshot accepted a different Client version")
|
|
}
|
|
|
|
persistent, err := os.ReadFile("persistent")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !bytes.Contains(persistent, []byte(`"other_service"`)) || !bytes.Contains(persistent, []byte("9007199254740993")) {
|
|
t.Fatalf("CW commit failed to preserve unrelated persistent data: %s", strings.TrimSpace(string(persistent)))
|
|
}
|
|
}
|