Files
bd2/go/internal/server/commerce/catalog_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

96 lines
3.4 KiB
Go

package commerce
import (
"bd2server/internal/server/gameconfig"
"bd2server/internal/server/gamedata"
"math"
"testing"
)
func testDesign() *gamedata.CashCatalog {
return &gamedata.CashCatalog{Products: []gamedata.CashProductDesign{
{Key: gamedata.CashProductKey{GroupID: 1, ProductID: 1, SaleGroup: 1}, GoogleSKU: "recharge", AppleSKU: "recharge-ios", PriceType: 1, PriceCount: 2200, Recharge: true, NominalPaidDiamonds: 100},
{Key: gamedata.CashProductKey{GroupID: 1, ProductID: 2, SaleGroup: 1}, GoogleSKU: "recharge", AppleSKU: "recharge-ios", PriceType: 1, PriceCount: 2200, Recharge: true, NominalPaidDiamonds: 100},
{Key: gamedata.CashProductKey{GroupID: 2, ProductID: 1, SaleGroup: 1}, GoogleSKU: "skin", AppleSKU: "skin-ios", PriceType: 1, PriceCount: 5501},
{Key: gamedata.CashProductKey{GroupID: 3, ProductID: 1}, GoogleSKU: "native", PriceType: 2, PriceCount: 100},
}}
}
func TestCashPricesAliasesAndIsolation(t *testing.T) {
for _, currency := range []string{"free", "gold", "diamonds", "ban", ""} {
cfg := gameconfig.Default().Purchases
cfg.DiamondRecharge.Currency = currency
c, err := NewCatalog("test", testDesign(), cfg)
if err != nil {
t.Fatal(err)
}
m := c.Manifest()
if m.SchemaVersion != 1 || len(m.Products) != 6 {
t.Fatalf("manifest %+v", m)
}
skin, err := c.Quote(gamedata.CashProductKey{GroupID: 2, ProductID: 1, SaleGroup: 1}, 2)
if err != nil || skin.Cost != 502 || skin.ItemType != 2 || skin.Currency != "paid_diamonds" {
t.Fatalf("ordinary goods affected by %q: %+v %v", currency, skin, err)
}
recharge, err := c.Quote(gamedata.CashProductKey{GroupID: 1, ProductID: 1, SaleGroup: 1}, 1)
if currency == "ban" || currency == "" {
if err == nil {
t.Fatal("disabled recharge accepted")
}
continue
}
if err != nil {
t.Fatal(err)
}
want := uint64(0)
if currency == "gold" {
want = 100000
}
if currency == "diamonds" {
want = 100
}
if recharge.Cost != want {
t.Fatalf("currency %s cost=%d", currency, recharge.Cost)
}
second, _ := c.Quote(gamedata.CashProductKey{GroupID: 1, ProductID: 2, SaleGroup: 1}, 1)
if second.Cost != recharge.Cost {
t.Fatal("first purchase incorrectly doubled cost")
}
m.Products[0].SKU = "changed"
if c.Manifest().Products[0].SKU == "changed" {
t.Fatal("manifest mutable through caller")
}
if _, err = c.Quote(gamedata.CashProductKey{GroupID: 3, ProductID: 1}, 1); err == nil {
t.Fatal("native wallet item intercepted")
}
}
}
func TestMonetaryBoundsAndBaseline(t *testing.T) {
for _, v := range [][3]uint64{{math.MaxUint64, 2, 1}, {1, 0, 1}, {1, 1, 0}, {math.MaxInt32 + 1, 1, 1}} {
if _, err := ceilRatio(v[0], v[1], v[2]); err == nil {
t.Fatalf("accepted %v", v)
}
}
d := testDesign()
d.Products[0].PriceCount = 2000
d.Products[1].PriceCount = 2000
c, err := NewCatalog("test", d, gameconfig.Default().Purchases)
if err != nil {
t.Fatal(err)
}
p, _ := c.Quote(d.Products[2].Key, 1)
if p.Cost != 276 {
t.Fatalf("baseline not derived dynamically: %+v", p)
}
if _, err = c.Quote(d.Products[2].Key, math.MaxInt32); err == nil {
t.Fatal("overflow accepted")
}
if _, err = c.Quote(d.Products[2].Key, 0); err == nil {
t.Fatal("zero purchase accepted")
}
d.Products[0].Recharge = false
d.Products[1].Recharge = false
if _, err = NewCatalog("test", d, gameconfig.Default().Purchases); err == nil {
t.Fatal("missing baseline accepted")
}
}