259 lines
7.0 KiB
Go
259 lines
7.0 KiB
Go
package items
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math/rand"
|
|
"testing"
|
|
|
|
"zombiezen.com/go/sqlite/sqlitex"
|
|
)
|
|
|
|
// setupTestDB creates a test database with minimal schema
|
|
func setupTestDB(t *testing.T) *sqlitex.Pool {
|
|
// Create unique database name to avoid test contamination
|
|
dbName := fmt.Sprintf("file: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 items (
|
|
id INTEGER PRIMARY KEY,
|
|
soe_id INTEGER DEFAULT 0,
|
|
name TEXT NOT NULL DEFAULT '',
|
|
description TEXT DEFAULT '',
|
|
icon INTEGER DEFAULT 0,
|
|
icon2 INTEGER DEFAULT 0,
|
|
icon_heroic_op INTEGER DEFAULT 0,
|
|
icon_heroic_op2 INTEGER DEFAULT 0,
|
|
icon_id INTEGER DEFAULT 0,
|
|
icon_backdrop INTEGER DEFAULT 0,
|
|
icon_border INTEGER DEFAULT 0,
|
|
icon_tint_red INTEGER DEFAULT 0,
|
|
icon_tint_green INTEGER DEFAULT 0,
|
|
icon_tint_blue INTEGER DEFAULT 0,
|
|
tier INTEGER DEFAULT 1,
|
|
level INTEGER DEFAULT 1,
|
|
success_sellback INTEGER DEFAULT 0,
|
|
stack_size INTEGER DEFAULT 1,
|
|
generic_info_show_name INTEGER DEFAULT 1,
|
|
generic_info_item_flags INTEGER DEFAULT 0,
|
|
generic_info_item_flags2 INTEGER DEFAULT 0,
|
|
generic_info_creator_flag INTEGER DEFAULT 0,
|
|
generic_info_condition INTEGER DEFAULT 100,
|
|
generic_info_weight INTEGER DEFAULT 10,
|
|
generic_info_skill_req1 INTEGER DEFAULT 0,
|
|
generic_info_skill_req2 INTEGER DEFAULT 0,
|
|
generic_info_skill_min_level INTEGER DEFAULT 0,
|
|
generic_info_item_type INTEGER DEFAULT 0,
|
|
generic_info_appearance_id INTEGER DEFAULT 0,
|
|
generic_info_appearance_red INTEGER DEFAULT 0,
|
|
generic_info_appearance_green INTEGER DEFAULT 0,
|
|
generic_info_appearance_blue INTEGER DEFAULT 0,
|
|
generic_info_appearance_highlight_red INTEGER DEFAULT 0,
|
|
generic_info_appearance_highlight_green INTEGER DEFAULT 0,
|
|
generic_info_appearance_highlight_blue INTEGER DEFAULT 0,
|
|
generic_info_collectable INTEGER DEFAULT 0,
|
|
generic_info_offers_quest_id INTEGER DEFAULT 0,
|
|
generic_info_part_of_quest_id INTEGER DEFAULT 0,
|
|
generic_info_max_charges INTEGER DEFAULT 0,
|
|
generic_info_adventure_classes INTEGER DEFAULT 0,
|
|
generic_info_tradeskill_classes INTEGER DEFAULT 0,
|
|
generic_info_adventure_default_level INTEGER DEFAULT 1,
|
|
generic_info_tradeskill_default_level INTEGER DEFAULT 1,
|
|
generic_info_usable INTEGER DEFAULT 0,
|
|
generic_info_harvest INTEGER DEFAULT 0,
|
|
generic_info_body_drop INTEGER DEFAULT 0,
|
|
generic_info_pvp_description INTEGER DEFAULT 0,
|
|
generic_info_merc_only INTEGER DEFAULT 0,
|
|
generic_info_mount_only INTEGER DEFAULT 0,
|
|
generic_info_set_id INTEGER DEFAULT 0,
|
|
generic_info_collectable_unk INTEGER DEFAULT 0,
|
|
generic_info_transmuted_material INTEGER DEFAULT 0,
|
|
broker_price INTEGER DEFAULT 0,
|
|
sell_price INTEGER DEFAULT 0,
|
|
max_sell_value INTEGER DEFAULT 0,
|
|
created TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
script_name TEXT DEFAULT '',
|
|
lua_script TEXT DEFAULT ''
|
|
);
|
|
|
|
CREATE TABLE item_mod_stats (
|
|
item_id INTEGER,
|
|
stat_type INTEGER,
|
|
stat_subtype INTEGER DEFAULT 0,
|
|
value REAL,
|
|
stat_name TEXT DEFAULT '',
|
|
level INTEGER DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE item_effects (
|
|
item_id INTEGER,
|
|
effect TEXT,
|
|
percentage INTEGER DEFAULT 0,
|
|
subbulletflag INTEGER DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE item_appearances (
|
|
item_id INTEGER,
|
|
type INTEGER,
|
|
red INTEGER DEFAULT 0,
|
|
green INTEGER DEFAULT 0,
|
|
blue INTEGER DEFAULT 0,
|
|
highlight_red INTEGER DEFAULT 0,
|
|
highlight_green INTEGER DEFAULT 0,
|
|
highlight_blue INTEGER DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE item_levels_override (
|
|
item_id INTEGER,
|
|
adventure_class INTEGER,
|
|
tradeskill_class INTEGER,
|
|
level INTEGER
|
|
);
|
|
|
|
CREATE TABLE item_mod_strings (
|
|
item_id INTEGER,
|
|
stat_string TEXT
|
|
);
|
|
|
|
CREATE TABLE item_details_weapon (
|
|
item_id INTEGER PRIMARY KEY,
|
|
wield_type INTEGER DEFAULT 2,
|
|
damage_low1 INTEGER DEFAULT 1,
|
|
damage_high1 INTEGER DEFAULT 2,
|
|
damage_low2 INTEGER DEFAULT 0,
|
|
damage_high2 INTEGER DEFAULT 0,
|
|
damage_low3 INTEGER DEFAULT 0,
|
|
damage_high3 INTEGER DEFAULT 0,
|
|
delay_hundredths INTEGER DEFAULT 300,
|
|
rating REAL DEFAULT 1.0
|
|
);
|
|
|
|
CREATE TABLE item_details_armor (
|
|
item_id INTEGER PRIMARY KEY,
|
|
mitigation_low INTEGER DEFAULT 1,
|
|
mitigation_high INTEGER DEFAULT 2
|
|
);
|
|
|
|
CREATE TABLE item_details_bag (
|
|
item_id INTEGER PRIMARY KEY,
|
|
num_slots INTEGER DEFAULT 6,
|
|
weight_reduction 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 TestNewItemDatabase(t *testing.T) {
|
|
pool := setupTestDB(t)
|
|
defer pool.Close()
|
|
|
|
idb := NewItemDatabase(pool)
|
|
if idb == nil {
|
|
t.Fatal("Expected non-nil ItemDatabase")
|
|
}
|
|
|
|
if idb.pool == nil {
|
|
t.Fatal("Expected non-nil database pool")
|
|
}
|
|
}
|
|
|
|
func TestItemDatabaseBasicOperation(t *testing.T) {
|
|
pool := setupTestDB(t)
|
|
defer pool.Close()
|
|
|
|
idb := NewItemDatabase(pool)
|
|
masterList := NewMasterItemList()
|
|
|
|
// Test that LoadItems doesn't crash (even with empty database)
|
|
err := idb.LoadItems(masterList)
|
|
if err != nil {
|
|
t.Fatalf("LoadItems should not fail with empty database: %v", err)
|
|
}
|
|
|
|
if masterList.GetItemCount() != 0 {
|
|
t.Errorf("Expected empty master list, got %d items", masterList.GetItemCount())
|
|
}
|
|
}
|
|
|
|
func TestItemDatabaseWithData(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 item
|
|
err = sqlitex.Execute(conn, `INSERT INTO items (id, name, generic_info_item_type) VALUES (?, ?, ?)`, &sqlitex.ExecOptions{
|
|
Args: []any{1, "Test Sword", ItemTypeWeapon},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to insert test item: %v", err)
|
|
}
|
|
|
|
// Insert weapon details
|
|
err = sqlitex.Execute(conn, `INSERT INTO item_details_weapon (item_id, damage_low1, damage_high1) VALUES (?, ?, ?)`, &sqlitex.ExecOptions{
|
|
Args: []any{1, 10, 15},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to insert weapon details: %v", err)
|
|
}
|
|
|
|
// Load items
|
|
idb := NewItemDatabase(pool)
|
|
masterList := NewMasterItemList()
|
|
|
|
err = idb.LoadItems(masterList)
|
|
if err != nil {
|
|
t.Fatalf("Failed to load items: %v", err)
|
|
}
|
|
|
|
if masterList.GetItemCount() != 1 {
|
|
t.Errorf("Expected 1 item, got %d items", masterList.GetItemCount())
|
|
}
|
|
|
|
// Verify the item was loaded correctly
|
|
item := masterList.GetItem(1)
|
|
if item == nil {
|
|
t.Fatal("Expected to find item with ID 1")
|
|
}
|
|
|
|
if item.Name != "Test Sword" {
|
|
t.Errorf("Expected item name 'Test Sword', got '%s'", item.Name)
|
|
}
|
|
|
|
if item.WeaponInfo == nil {
|
|
t.Error("Expected weapon info to be loaded")
|
|
} else {
|
|
if item.WeaponInfo.DamageLow1 != 10 {
|
|
t.Errorf("Expected damage low 10, got %d", item.WeaponInfo.DamageLow1)
|
|
}
|
|
if item.WeaponInfo.DamageHigh1 != 15 {
|
|
t.Errorf("Expected damage high 15, got %d", item.WeaponInfo.DamageHigh1)
|
|
}
|
|
}
|
|
} |