287 lines
7.9 KiB
Go
287 lines
7.9 KiB
Go
package achievements
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
|
|
"eq2emu/internal/database"
|
|
)
|
|
|
|
// TestSimpleAchievement tests the basic new Achievement functionality
|
|
func TestSimpleAchievement(t *testing.T) {
|
|
db, err := database.NewSQLite("file::memory:?mode=memory&cache=shared")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create test database: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
// Test creating a new achievement
|
|
achievement := New(db)
|
|
if achievement == nil {
|
|
t.Fatal("New returned nil")
|
|
}
|
|
|
|
if !achievement.IsNew() {
|
|
t.Error("New achievement should be marked as new")
|
|
}
|
|
|
|
// Test setting values
|
|
achievement.AchievementID = 1001
|
|
achievement.Title = "Test Achievement"
|
|
achievement.Category = "Testing"
|
|
|
|
if achievement.GetID() != 1001 {
|
|
t.Errorf("Expected GetID() to return 1001, got %d", achievement.GetID())
|
|
}
|
|
|
|
// Test adding requirements and rewards
|
|
achievement.AddRequirement("kill_monsters", 10)
|
|
achievement.AddReward("experience:1000")
|
|
|
|
if len(achievement.Requirements) != 1 {
|
|
t.Errorf("Expected 1 requirement, got %d", len(achievement.Requirements))
|
|
}
|
|
|
|
if len(achievement.Rewards) != 1 {
|
|
t.Errorf("Expected 1 reward, got %d", len(achievement.Rewards))
|
|
}
|
|
|
|
// Test Clone
|
|
clone := achievement.Clone()
|
|
if clone == nil {
|
|
t.Fatal("Clone returned nil")
|
|
}
|
|
|
|
if clone.AchievementID != achievement.AchievementID {
|
|
t.Errorf("Expected clone ID %d, got %d", achievement.AchievementID, clone.AchievementID)
|
|
}
|
|
|
|
if clone.Title != achievement.Title {
|
|
t.Errorf("Expected clone title %s, got %s", achievement.Title, clone.Title)
|
|
}
|
|
}
|
|
|
|
// TestMasterList tests the bespoke master list implementation
|
|
func TestMasterList(t *testing.T) {
|
|
masterList := NewMasterList()
|
|
|
|
if masterList == nil {
|
|
t.Fatal("NewMasterList returned nil")
|
|
}
|
|
|
|
if masterList.Size() != 0 {
|
|
t.Errorf("Expected size 0, got %d", masterList.Size())
|
|
}
|
|
|
|
// Create test database
|
|
db, err := database.NewSQLite("file::memory:?mode=memory&cache=shared")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create test database: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
// Create achievements for testing
|
|
achievement1 := New(db)
|
|
achievement1.AchievementID = 1001
|
|
achievement1.Title = "Test Achievement 1"
|
|
achievement1.Category = "Testing"
|
|
achievement1.Expansion = "Classic"
|
|
|
|
achievement2 := New(db)
|
|
achievement2.AchievementID = 1002
|
|
achievement2.Title = "Test Achievement 2"
|
|
achievement2.Category = "Combat"
|
|
achievement2.Expansion = "Classic"
|
|
|
|
achievement3 := New(db)
|
|
achievement3.AchievementID = 1003
|
|
achievement3.Title = "Test Achievement 3"
|
|
achievement3.Category = "Testing"
|
|
achievement3.Expansion = "Expansion1"
|
|
|
|
// Test adding
|
|
if !masterList.AddAchievement(achievement1) {
|
|
t.Error("Should successfully add achievement1")
|
|
}
|
|
|
|
if !masterList.AddAchievement(achievement2) {
|
|
t.Error("Should successfully add achievement2")
|
|
}
|
|
|
|
if !masterList.AddAchievement(achievement3) {
|
|
t.Error("Should successfully add achievement3")
|
|
}
|
|
|
|
if masterList.Size() != 3 {
|
|
t.Errorf("Expected size 3, got %d", masterList.Size())
|
|
}
|
|
|
|
// Test duplicate add (should fail)
|
|
if masterList.AddAchievement(achievement1) {
|
|
t.Error("Should not add duplicate achievement")
|
|
}
|
|
|
|
// Test retrieving
|
|
retrieved := masterList.GetAchievement(1001)
|
|
if retrieved == nil {
|
|
t.Error("Should retrieve added achievement")
|
|
}
|
|
|
|
if retrieved.Title != "Test Achievement 1" {
|
|
t.Errorf("Expected title 'Test Achievement 1', got '%s'", retrieved.Title)
|
|
}
|
|
|
|
// Test category filtering
|
|
testingAchievements := masterList.GetAchievementsByCategory("Testing")
|
|
if len(testingAchievements) != 2 {
|
|
t.Errorf("Expected 2 achievements in Testing category, got %d", len(testingAchievements))
|
|
}
|
|
|
|
combatAchievements := masterList.GetAchievementsByCategory("Combat")
|
|
if len(combatAchievements) != 1 {
|
|
t.Errorf("Expected 1 achievement in Combat category, got %d", len(combatAchievements))
|
|
}
|
|
|
|
// Test expansion filtering
|
|
classicAchievements := masterList.GetAchievementsByExpansion("Classic")
|
|
if len(classicAchievements) != 2 {
|
|
t.Errorf("Expected 2 achievements in Classic expansion, got %d", len(classicAchievements))
|
|
}
|
|
|
|
expansion1Achievements := masterList.GetAchievementsByExpansion("Expansion1")
|
|
if len(expansion1Achievements) != 1 {
|
|
t.Errorf("Expected 1 achievement in Expansion1, got %d", len(expansion1Achievements))
|
|
}
|
|
|
|
// Test combined filtering
|
|
combined := masterList.GetAchievementsByCategoryAndExpansion("Testing", "Classic")
|
|
if len(combined) != 1 {
|
|
t.Errorf("Expected 1 achievement matching Testing+Classic, got %d", len(combined))
|
|
}
|
|
|
|
// Test metadata caching
|
|
categories := masterList.GetCategories()
|
|
if len(categories) != 2 {
|
|
t.Errorf("Expected 2 unique categories, got %d", len(categories))
|
|
}
|
|
|
|
expansions := masterList.GetExpansions()
|
|
if len(expansions) != 2 {
|
|
t.Errorf("Expected 2 unique expansions, got %d", len(expansions))
|
|
}
|
|
|
|
// Test clone
|
|
clone := masterList.GetAchievementClone(1001)
|
|
if clone == nil {
|
|
t.Error("Should return cloned achievement")
|
|
}
|
|
|
|
if clone.Title != "Test Achievement 1" {
|
|
t.Errorf("Expected cloned title 'Test Achievement 1', got '%s'", clone.Title)
|
|
}
|
|
|
|
// Test GetAllAchievements
|
|
allAchievements := masterList.GetAllAchievements()
|
|
if len(allAchievements) != 3 {
|
|
t.Errorf("Expected 3 achievements in GetAll, got %d", len(allAchievements))
|
|
}
|
|
|
|
// Test update
|
|
updatedAchievement := New(db)
|
|
updatedAchievement.AchievementID = 1001
|
|
updatedAchievement.Title = "Updated Achievement"
|
|
updatedAchievement.Category = "Updated"
|
|
updatedAchievement.Expansion = "Updated"
|
|
|
|
if err := masterList.UpdateAchievement(updatedAchievement); err != nil {
|
|
t.Errorf("Update should succeed: %v", err)
|
|
}
|
|
|
|
// Verify update worked
|
|
retrievedUpdated := masterList.GetAchievement(1001)
|
|
if retrievedUpdated.Title != "Updated Achievement" {
|
|
t.Errorf("Expected updated title 'Updated Achievement', got '%s'", retrievedUpdated.Title)
|
|
}
|
|
|
|
// Verify category index updated
|
|
updatedCategoryAchievements := masterList.GetAchievementsByCategory("Updated")
|
|
if len(updatedCategoryAchievements) != 1 {
|
|
t.Errorf("Expected 1 achievement in Updated category, got %d", len(updatedCategoryAchievements))
|
|
}
|
|
|
|
// Test removal
|
|
if !masterList.RemoveAchievement(1001) {
|
|
t.Error("Should successfully remove achievement")
|
|
}
|
|
|
|
if masterList.Size() != 2 {
|
|
t.Errorf("Expected size 2 after removal, got %d", masterList.Size())
|
|
}
|
|
|
|
// Test clear
|
|
masterList.Clear()
|
|
if masterList.Size() != 0 {
|
|
t.Errorf("Expected size 0 after clear, got %d", masterList.Size())
|
|
}
|
|
}
|
|
|
|
// TestMasterListConcurrency tests thread safety of the master list
|
|
func TestMasterListConcurrency(t *testing.T) {
|
|
masterList := NewMasterList()
|
|
|
|
// Create test database
|
|
db, err := database.NewSQLite("file::memory:?mode=memory&cache=shared")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create test database: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
const numWorkers = 10
|
|
const achievementsPerWorker = 100
|
|
var wg sync.WaitGroup
|
|
|
|
// Concurrently add achievements
|
|
wg.Add(numWorkers)
|
|
for i := 0; i < numWorkers; i++ {
|
|
go func(workerID int) {
|
|
defer wg.Done()
|
|
for j := 0; j < achievementsPerWorker; j++ {
|
|
achievement := New(db)
|
|
achievement.AchievementID = uint32(workerID*achievementsPerWorker + j + 1)
|
|
achievement.Title = "Concurrent Test"
|
|
achievement.Category = "Concurrency"
|
|
achievement.Expansion = "Test"
|
|
masterList.AddAchievement(achievement)
|
|
}
|
|
}(i)
|
|
}
|
|
|
|
// Concurrently read achievements
|
|
wg.Add(numWorkers)
|
|
for i := 0; i < numWorkers; i++ {
|
|
go func() {
|
|
defer wg.Done()
|
|
for j := 0; j < achievementsPerWorker; j++ {
|
|
// Random reads
|
|
_ = masterList.GetAchievement(uint32(j + 1))
|
|
_ = masterList.GetAchievementsByCategory("Concurrency")
|
|
_ = masterList.GetAchievementsByExpansion("Test")
|
|
_ = masterList.Size()
|
|
}
|
|
}()
|
|
}
|
|
|
|
wg.Wait()
|
|
|
|
// Verify final state
|
|
expectedSize := numWorkers * achievementsPerWorker
|
|
if masterList.Size() != expectedSize {
|
|
t.Errorf("Expected size %d, got %d", expectedSize, masterList.Size())
|
|
}
|
|
|
|
categories := masterList.GetCategories()
|
|
if len(categories) != 1 || categories[0] != "Concurrency" {
|
|
t.Errorf("Expected 1 category 'Concurrency', got %v", categories)
|
|
}
|
|
}
|