199 lines
4.9 KiB
Go
199 lines
4.9 KiB
Go
package loot
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math/rand"
|
|
"testing"
|
|
|
|
"zombiezen.com/go/sqlite/sqlitex"
|
|
)
|
|
|
|
// setupTestDB creates a test database with minimal schema
|
|
func setupTestDB(t testing.TB) *sqlitex.Pool {
|
|
// Create unique database name to avoid test contamination
|
|
dbName := fmt.Sprintf("file:loot_test_%s_%d.db?mode=memory&cache=shared", t.Name(), rand.Int63())
|
|
pool, err := sqlitex.NewPool(dbName, sqlitex.PoolOptions{
|
|
PoolSize: 10,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to create test database pool: %v", err)
|
|
}
|
|
|
|
// Create complete test schema matching the real database structure
|
|
schema := `
|
|
CREATE TABLE loottable (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT DEFAULT '',
|
|
mincoin INTEGER DEFAULT 0,
|
|
maxcoin INTEGER DEFAULT 0,
|
|
maxlootitems INTEGER DEFAULT 5,
|
|
lootdrop_probability REAL DEFAULT 100.0,
|
|
coin_probability REAL DEFAULT 75.0
|
|
);
|
|
|
|
CREATE TABLE lootdrop (
|
|
loot_table_id INTEGER,
|
|
item_id INTEGER,
|
|
item_charges INTEGER DEFAULT 1,
|
|
equip_item INTEGER DEFAULT 0,
|
|
probability REAL DEFAULT 25.0,
|
|
no_drop_quest_completed_id INTEGER DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE spawn_loot (
|
|
spawn_id INTEGER,
|
|
loottable_id INTEGER
|
|
);
|
|
|
|
CREATE TABLE loot_global (
|
|
type TEXT,
|
|
loot_table INTEGER,
|
|
value1 INTEGER DEFAULT 0,
|
|
value2 INTEGER DEFAULT 0,
|
|
value3 INTEGER DEFAULT 0,
|
|
value4 INTEGER DEFAULT 0
|
|
);
|
|
`
|
|
|
|
// Execute schema on connection
|
|
ctx := context.Background()
|
|
conn, err := pool.Take(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get connection: %v", err)
|
|
}
|
|
defer pool.Put(conn)
|
|
|
|
if err := sqlitex.ExecuteScript(conn, schema, nil); err != nil {
|
|
t.Fatalf("Failed to create test schema: %v", err)
|
|
}
|
|
|
|
return pool
|
|
}
|
|
|
|
func TestNewLootDatabase(t *testing.T) {
|
|
pool := setupTestDB(t)
|
|
defer pool.Close()
|
|
|
|
lootDB := NewLootDatabase(pool)
|
|
if lootDB == nil {
|
|
t.Fatal("Expected non-nil LootDatabase")
|
|
}
|
|
|
|
if lootDB.pool == nil {
|
|
t.Fatal("Expected non-nil database pool")
|
|
}
|
|
}
|
|
|
|
func TestLootDatabaseBasicOperation(t *testing.T) {
|
|
pool := setupTestDB(t)
|
|
defer pool.Close()
|
|
|
|
lootDB := NewLootDatabase(pool)
|
|
|
|
// Test that LoadAllLootData doesn't crash (even with empty database)
|
|
err := lootDB.LoadAllLootData()
|
|
if err != nil {
|
|
t.Fatalf("LoadAllLootData should not fail with empty database: %v", err)
|
|
}
|
|
|
|
// Test that GetLootTable returns nil for non-existent table
|
|
table := lootDB.GetLootTable(999)
|
|
if table != nil {
|
|
t.Error("Expected nil for non-existent loot table")
|
|
}
|
|
}
|
|
|
|
func TestLootDatabaseWithData(t *testing.T) {
|
|
pool := setupTestDB(t)
|
|
defer pool.Close()
|
|
|
|
// Insert test data
|
|
ctx := context.Background()
|
|
conn, err := pool.Take(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get connection: %v", err)
|
|
}
|
|
defer pool.Put(conn)
|
|
|
|
// Insert a test loot table
|
|
err = sqlitex.Execute(conn, `INSERT INTO loottable (id, name, mincoin, maxcoin, maxlootitems, lootdrop_probability, coin_probability) VALUES (?, ?, ?, ?, ?, ?, ?)`, &sqlitex.ExecOptions{
|
|
Args: []any{1, "Test Loot Table", 10, 50, 3, 75.0, 50.0},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to insert test loot table: %v", err)
|
|
}
|
|
|
|
// Insert test loot drops
|
|
err = sqlitex.Execute(conn, `INSERT INTO lootdrop (loot_table_id, item_id, item_charges, equip_item, probability, no_drop_quest_completed_id) VALUES (?, ?, ?, ?, ?, ?)`, &sqlitex.ExecOptions{
|
|
Args: []any{1, 101, 1, 0, 25.0, 0},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to insert test loot drop: %v", err)
|
|
}
|
|
|
|
// Insert spawn loot assignment
|
|
err = sqlitex.Execute(conn, `INSERT INTO spawn_loot (spawn_id, loottable_id) VALUES (?, ?)`, &sqlitex.ExecOptions{
|
|
Args: []any{1001, 1},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to insert spawn loot assignment: %v", err)
|
|
}
|
|
|
|
// Load all loot data
|
|
lootDB := NewLootDatabase(pool)
|
|
err = lootDB.LoadAllLootData()
|
|
if err != nil {
|
|
t.Fatalf("Failed to load loot data: %v", err)
|
|
}
|
|
|
|
// Verify loot table was loaded
|
|
table := lootDB.GetLootTable(1)
|
|
if table == nil {
|
|
t.Fatal("Expected to find loot table 1")
|
|
}
|
|
|
|
if table.Name != "Test Loot Table" {
|
|
t.Errorf("Expected table name 'Test Loot Table', got '%s'", table.Name)
|
|
}
|
|
|
|
if table.MinCoin != 10 {
|
|
t.Errorf("Expected min coin 10, got %d", table.MinCoin)
|
|
}
|
|
|
|
if table.MaxCoin != 50 {
|
|
t.Errorf("Expected max coin 50, got %d", table.MaxCoin)
|
|
}
|
|
|
|
if len(table.Drops) != 1 {
|
|
t.Errorf("Expected 1 loot drop, got %d", len(table.Drops))
|
|
} else {
|
|
drop := table.Drops[0]
|
|
if drop.ItemID != 101 {
|
|
t.Errorf("Expected item ID 101, got %d", drop.ItemID)
|
|
}
|
|
if drop.Probability != 25.0 {
|
|
t.Errorf("Expected probability 25.0, got %f", drop.Probability)
|
|
}
|
|
}
|
|
|
|
// Verify spawn loot assignment
|
|
tables := lootDB.GetSpawnLootTables(1001)
|
|
if len(tables) != 1 {
|
|
t.Errorf("Expected 1 loot table for spawn 1001, got %d", len(tables))
|
|
} else if tables[0] != 1 {
|
|
t.Errorf("Expected loot table ID 1 for spawn 1001, got %d", tables[0])
|
|
}
|
|
}
|
|
|
|
// Benchmark tests
|
|
func BenchmarkLootDatabaseCreation(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
pool := setupTestDB(b)
|
|
lootDB := NewLootDatabase(pool)
|
|
if lootDB == nil {
|
|
b.Fatal("Expected non-nil LootDatabase")
|
|
}
|
|
pool.Close()
|
|
}
|
|
} |