180 lines
6.0 KiB
Go
180 lines
6.0 KiB
Go
package gamedata
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/binary"
|
|
"os"
|
|
"testing"
|
|
)
|
|
|
|
func TestCharacterGrowthPromotionsAgainstInstalledVersion23510(t *testing.T) {
|
|
root := os.Getenv("BD2_TEST_GAMEDATA_ROOT")
|
|
if root == "" {
|
|
t.Skip("set BD2_TEST_GAMEDATA_ROOT for installed GameData integration test")
|
|
}
|
|
submitted := []PromotionCost{
|
|
{Type: 8, ID: 9, Count: 753},
|
|
{Type: 8, ID: 11, Count: 1},
|
|
{Type: 8, ID: 12, Count: 2},
|
|
{Type: 8, ID: 13, Count: 3},
|
|
{Type: 8, ID: 14, Count: 4},
|
|
{Type: 4, Count: 10000},
|
|
}
|
|
result, err := CharacterGrowthPromotions(root, "20260923193640", 6510, 1, 0, submitted)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if result.CharacterID != 6514 || result.Level != 100 || result.Exp != 0 || len(result.Costs) != 8 {
|
|
t.Fatalf("installed 2.35.10 combined promotion=%+v", result)
|
|
}
|
|
}
|
|
|
|
func testVarintField(dst []byte, field int, value uint64) []byte {
|
|
dst = binary.AppendUvarint(dst, uint64(field<<3))
|
|
return binary.AppendUvarint(dst, value)
|
|
}
|
|
|
|
func testPackedField(dst []byte, field int, values ...uint64) []byte {
|
|
var packed []byte
|
|
for _, value := range values {
|
|
packed = binary.AppendUvarint(packed, value)
|
|
}
|
|
dst = binary.AppendUvarint(dst, uint64(field<<3|2))
|
|
dst = binary.AppendUvarint(dst, uint64(len(packed)))
|
|
return append(dst, packed...)
|
|
}
|
|
|
|
func TestCharacterPromotionUsesCharAndGrowthTables(t *testing.T) {
|
|
db, err := sql.Open("sqlite", ":memory:")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
for _, schema := range []string{
|
|
"CREATE TABLE CharTable (id INTEGER PRIMARY KEY, ProtoBuf BLOB)",
|
|
"CREATE TABLE CharGrowthTable (id INTEGER PRIMARY KEY, ProtoBuf BLOB)",
|
|
"CREATE TABLE CharLevelTable (GroupId INTEGER, id INTEGER, ProtoBuf BLOB, PRIMARY KEY(GroupId,id))",
|
|
} {
|
|
if _, err := db.Exec(schema); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
current := testVarintField(nil, 1, 101)
|
|
current = testVarintField(current, 15, 351)
|
|
next := testVarintField(nil, 1, 102)
|
|
growth := testVarintField(nil, 1, 101)
|
|
growth = testPackedField(growth, 2, 1, 1000)
|
|
growth = testPackedField(growth, 3, 11, 0)
|
|
growth = testPackedField(growth, 4, 8, 4)
|
|
growth = testVarintField(growth, 9, 20)
|
|
if _, err := db.Exec("INSERT INTO CharTable VALUES (?,?),(?,?)", 350, current, 351, next); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := db.Exec("INSERT INTO CharGrowthTable VALUES (?,?)", 101, growth); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := db.Exec("INSERT INTO CharLevelTable VALUES (?,?,?)", 101, 20, []byte{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
nextID, costs, err := characterPromotion(db, 350, 20, 0)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if nextID != 351 || len(costs) != 2 || costs[0] != (PromotionCost{Type: 8, ID: 11, Count: 1}) || costs[1] != (PromotionCost{Type: 4, Count: 1000}) {
|
|
t.Fatalf("promotion next=%d costs=%+v", nextID, costs)
|
|
}
|
|
if _, _, err := characterPromotion(db, 350, 19, 0); err == nil {
|
|
t.Fatal("promotion before the stage cap was accepted")
|
|
}
|
|
}
|
|
|
|
func TestCharacterGrowthPromotionsCrossesTwoStagesWithCumulativeCosts(t *testing.T) {
|
|
db, err := sql.Open("sqlite", ":memory:")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
for _, schema := range []string{
|
|
"CREATE TABLE CharTable (id INTEGER PRIMARY KEY, ProtoBuf BLOB)",
|
|
"CREATE TABLE CharGrowthTable (id INTEGER PRIMARY KEY, ProtoBuf BLOB)",
|
|
"CREATE TABLE CharLevelTable (GroupId INTEGER, id INTEGER, ProtoBuf BLOB, PRIMARY KEY(GroupId,id))",
|
|
"CREATE TABLE ResourceTable (id INTEGER PRIMARY KEY, ProtoBuf BLOB)",
|
|
} {
|
|
if _, err := db.Exec(schema); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
for _, row := range []struct {
|
|
id, growth, next uint64
|
|
}{{352, 103, 353}, {353, 104, 354}, {354, 105, 0}} {
|
|
proto := testVarintField(nil, 1, row.growth)
|
|
if row.next != 0 {
|
|
proto = testVarintField(proto, 15, row.next)
|
|
}
|
|
if _, err := db.Exec("INSERT INTO CharTable VALUES (?,?)", row.id, proto); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
growth103 := testVarintField(nil, 1, 103)
|
|
growth103 = testPackedField(growth103, 2, 3, 3000)
|
|
growth103 = testPackedField(growth103, 3, 13, 0)
|
|
growth103 = testPackedField(growth103, 4, 8, 4)
|
|
growth103 = testVarintField(growth103, 9, 60)
|
|
growth104 := testVarintField(nil, 1, 104)
|
|
growth104 = testPackedField(growth104, 2, 4, 4000)
|
|
growth104 = testPackedField(growth104, 3, 14, 0)
|
|
growth104 = testPackedField(growth104, 4, 8, 4)
|
|
growth104 = testVarintField(growth104, 9, 80)
|
|
growth105 := testVarintField(testVarintField(nil, 1, 105), 9, 100)
|
|
for _, row := range []struct {
|
|
id uint64
|
|
proto []byte
|
|
}{{103, growth103}, {104, growth104}, {105, growth105}} {
|
|
if _, err := db.Exec("INSERT INTO CharGrowthTable VALUES (?,?)", row.id, row.proto); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
for _, curve := range []struct{ group, first, maximum uint64 }{{103, 1, 60}, {104, 60, 80}, {105, 80, 100}} {
|
|
for level := curve.first; level < curve.maximum; level++ {
|
|
proto := testVarintField(nil, 8, 10)
|
|
if _, err := db.Exec("INSERT INTO CharLevelTable VALUES (?,?,?)", curve.group, level, proto); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
resource := testVarintField(nil, 9, 10)
|
|
if _, err := db.Exec("INSERT INTO ResourceTable VALUES (?,?)", 9, resource); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
submitted := []PromotionCost{
|
|
{Type: 8, ID: 9, Count: 40},
|
|
{Type: 8, ID: 13, Count: 3},
|
|
{Type: 8, ID: 14, Count: 4},
|
|
{Type: 4, Count: 7000},
|
|
}
|
|
result, err := characterGrowthPromotions(db, 352, 60, 0, submitted)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if result.CharacterID != 354 || result.Level != 100 || result.Exp != 0 || len(result.Refunds) != 0 {
|
|
t.Fatalf("combined result=%+v", result)
|
|
}
|
|
if len(result.Costs) != 4 {
|
|
t.Fatalf("cumulative costs=%+v", result.Costs)
|
|
}
|
|
fromLevelOne := append([]PromotionCost(nil), submitted...)
|
|
fromLevelOne[0].Count = 99
|
|
result, err = characterGrowthPromotions(db, 352, 1, 0, fromLevelOne)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if result.CharacterID != 354 || result.Level != 100 || result.Exp != 0 {
|
|
t.Fatalf("level-one combined result=%+v", result)
|
|
}
|
|
bad := append([]PromotionCost(nil), submitted...)
|
|
bad[len(bad)-1].Count = 6000
|
|
if _, err := characterGrowthPromotions(db, 352, 60, 0, bad); err == nil {
|
|
t.Fatal("non-prefix aggregate gold was accepted")
|
|
}
|
|
}
|