eq2go/internal/items/loot/loot_test.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()
}
}