744 lines
20 KiB
Go
744 lines
20 KiB
Go
package achievements
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// MockLogger implements the Logger interface for testing
|
|
type MockLogger struct {
|
|
InfoMessages []string
|
|
ErrorMessages []string
|
|
DebugMessages []string
|
|
WarningMessages []string
|
|
}
|
|
|
|
func (ml *MockLogger) LogInfo(system, format string, args ...any) {
|
|
ml.InfoMessages = append(ml.InfoMessages, fmt.Sprintf(format, args...))
|
|
}
|
|
|
|
func (ml *MockLogger) LogError(system, format string, args ...any) {
|
|
ml.ErrorMessages = append(ml.ErrorMessages, fmt.Sprintf(format, args...))
|
|
}
|
|
|
|
func (ml *MockLogger) LogDebug(system, format string, args ...any) {
|
|
ml.DebugMessages = append(ml.DebugMessages, fmt.Sprintf(format, args...))
|
|
}
|
|
|
|
func (ml *MockLogger) LogWarning(system, format string, args ...any) {
|
|
ml.WarningMessages = append(ml.WarningMessages, fmt.Sprintf(format, args...))
|
|
}
|
|
|
|
// MockDatabase implements basic database operations for testing
|
|
type MockDatabase struct {
|
|
achievements []Achievement
|
|
playerAchievements map[uint32][]PlayerAchievement
|
|
requirements map[uint32][]Requirement
|
|
rewards map[uint32][]Reward
|
|
}
|
|
|
|
func NewMockDatabase() *MockDatabase {
|
|
return &MockDatabase{
|
|
achievements: []Achievement{},
|
|
playerAchievements: make(map[uint32][]PlayerAchievement),
|
|
requirements: make(map[uint32][]Requirement),
|
|
rewards: make(map[uint32][]Reward),
|
|
}
|
|
}
|
|
|
|
func (db *MockDatabase) Query(query string, args ...any) (*MockRows, error) {
|
|
// Simulate database queries based on the query string
|
|
if query == `
|
|
SELECT id, achievement_id, title, uncompleted_text, completed_text,
|
|
category, expansion, icon, point_value, qty_req, hide_achievement,
|
|
unknown3a, unknown3b, max_version
|
|
FROM achievements
|
|
ORDER BY achievement_id
|
|
` {
|
|
return &MockRows{
|
|
achievements: db.achievements,
|
|
position: 0,
|
|
queryType: "achievements",
|
|
}, nil
|
|
}
|
|
|
|
// Handle other query types as needed
|
|
return &MockRows{queryType: "unknown"}, nil
|
|
}
|
|
|
|
func (db *MockDatabase) Exec(query string, args ...any) (any, error) {
|
|
// Mock exec operations
|
|
return nil, nil
|
|
}
|
|
|
|
// MockRows simulates database rows for testing
|
|
type MockRows struct {
|
|
achievements []Achievement
|
|
position int
|
|
queryType string
|
|
closed bool
|
|
}
|
|
|
|
func (rows *MockRows) Next() bool {
|
|
if rows.closed {
|
|
return false
|
|
}
|
|
if rows.queryType == "achievements" {
|
|
return rows.position < len(rows.achievements)
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (rows *MockRows) Scan(dest ...any) error {
|
|
if rows.queryType == "achievements" && rows.position < len(rows.achievements) {
|
|
achievement := &rows.achievements[rows.position]
|
|
|
|
// Scan values in order expected by the query
|
|
if len(dest) >= 14 {
|
|
*dest[0].(*uint32) = achievement.ID
|
|
*dest[1].(*uint32) = achievement.AchievementID
|
|
*dest[2].(*string) = achievement.Title
|
|
*dest[3].(*string) = achievement.UncompletedText
|
|
*dest[4].(*string) = achievement.CompletedText
|
|
*dest[5].(*string) = achievement.Category
|
|
*dest[6].(*string) = achievement.Expansion
|
|
*dest[7].(*uint16) = achievement.Icon
|
|
*dest[8].(*uint32) = achievement.PointValue
|
|
*dest[9].(*uint32) = achievement.QtyRequired
|
|
|
|
var hideInt int
|
|
if achievement.Hide {
|
|
hideInt = 1
|
|
}
|
|
*dest[10].(*int) = hideInt
|
|
|
|
*dest[11].(*uint32) = achievement.Unknown3A
|
|
*dest[12].(*uint32) = achievement.Unknown3B
|
|
*dest[13].(*uint32) = achievement.MaxVersion
|
|
}
|
|
|
|
rows.position++
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (rows *MockRows) Close() error {
|
|
rows.closed = true
|
|
return nil
|
|
}
|
|
|
|
func (rows *MockRows) Err() error {
|
|
return nil
|
|
}
|
|
|
|
// Test data setup
|
|
func createTestAchievements() []Achievement {
|
|
return []Achievement{
|
|
{
|
|
ID: 1,
|
|
AchievementID: 100,
|
|
Title: "First Kill",
|
|
UncompletedText: "Kill your first enemy",
|
|
CompletedText: "You have killed your first enemy!",
|
|
Category: CategoryCombat,
|
|
Expansion: ExpansionBase,
|
|
Icon: 1001,
|
|
PointValue: 10,
|
|
QtyRequired: 1,
|
|
Hide: false,
|
|
Requirements: []Requirement{
|
|
{AchievementID: 100, Name: "Kill Enemy", QtyRequired: 1},
|
|
},
|
|
Rewards: []Reward{
|
|
{AchievementID: 100, Reward: "10 Experience Points"},
|
|
},
|
|
},
|
|
{
|
|
ID: 2,
|
|
AchievementID: 101,
|
|
Title: "Explorer",
|
|
UncompletedText: "Discover 5 new locations",
|
|
CompletedText: "You have explored many locations!",
|
|
Category: CategoryExploration,
|
|
Expansion: ExpansionBase,
|
|
Icon: 1002,
|
|
PointValue: 25,
|
|
QtyRequired: 5,
|
|
Hide: false,
|
|
Requirements: []Requirement{
|
|
{AchievementID: 101, Name: "Discover Location", QtyRequired: 5},
|
|
},
|
|
Rewards: []Reward{
|
|
{AchievementID: 101, Reward: "Map Fragment"},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func setupTestManager() (*AchievementManager, *MockLogger, *MockDatabase) {
|
|
logger := &MockLogger{}
|
|
mockDB := NewMockDatabase()
|
|
|
|
// Add test data
|
|
mockDB.achievements = createTestAchievements()
|
|
|
|
config := AchievementConfig{
|
|
EnablePacketUpdates: true,
|
|
AutoCompleteOnReached: true,
|
|
EnableStatistics: true,
|
|
MaxCachedPlayers: 100,
|
|
}
|
|
|
|
// Create manager without database initially for isolated testing
|
|
manager := NewAchievementManager(nil, logger, config)
|
|
|
|
return manager, logger, mockDB
|
|
}
|
|
|
|
func TestNewAchievementManager(t *testing.T) {
|
|
logger := &MockLogger{}
|
|
config := AchievementConfig{
|
|
EnablePacketUpdates: true,
|
|
MaxCachedPlayers: 100,
|
|
}
|
|
|
|
manager := NewAchievementManager(nil, logger, config)
|
|
|
|
if manager == nil {
|
|
t.Fatal("NewAchievementManager returned nil")
|
|
}
|
|
|
|
if manager.logger != logger {
|
|
t.Error("Logger not set correctly")
|
|
}
|
|
|
|
if manager.config != config {
|
|
t.Error("Config not set correctly")
|
|
}
|
|
|
|
if len(manager.achievements) != 0 {
|
|
t.Error("Expected empty achievements map")
|
|
}
|
|
}
|
|
|
|
func TestAchievementManagerInitializeWithoutDatabase(t *testing.T) {
|
|
manager, logger, _ := setupTestManager()
|
|
|
|
// Initialize with no database (should handle gracefully)
|
|
ctx := context.Background()
|
|
err := manager.Initialize(ctx)
|
|
|
|
if err != nil {
|
|
t.Fatalf("Initialize failed: %v", err)
|
|
}
|
|
|
|
// Should have no achievements loaded
|
|
if len(manager.achievements) != 0 {
|
|
t.Error("Expected no achievements without database")
|
|
}
|
|
|
|
// Logger should have recorded the initialization
|
|
if len(logger.InfoMessages) == 0 {
|
|
t.Error("Expected initialization log message")
|
|
}
|
|
}
|
|
|
|
func TestGetAchievement(t *testing.T) {
|
|
manager, _, _ := setupTestManager()
|
|
|
|
// Manually add achievements for testing
|
|
testAchievements := createTestAchievements()
|
|
for i := range testAchievements {
|
|
manager.achievements[testAchievements[i].AchievementID] = &testAchievements[i]
|
|
}
|
|
|
|
// Test existing achievement
|
|
achievement, exists := manager.GetAchievement(100)
|
|
if !exists {
|
|
t.Error("Expected achievement 100 to exist")
|
|
}
|
|
if achievement.Title != "First Kill" {
|
|
t.Errorf("Expected title 'First Kill', got '%s'", achievement.Title)
|
|
}
|
|
|
|
// Test non-existing achievement
|
|
_, exists = manager.GetAchievement(999)
|
|
if exists {
|
|
t.Error("Expected achievement 999 to not exist")
|
|
}
|
|
}
|
|
|
|
func TestGetAllAchievements(t *testing.T) {
|
|
manager, _, _ := setupTestManager()
|
|
|
|
// Manually add achievements for testing
|
|
testAchievements := createTestAchievements()
|
|
for i := range testAchievements {
|
|
manager.achievements[testAchievements[i].AchievementID] = &testAchievements[i]
|
|
}
|
|
|
|
// Build indexes
|
|
for _, achievement := range manager.achievements {
|
|
manager.categoryIndex[achievement.Category] = append(manager.categoryIndex[achievement.Category], achievement)
|
|
manager.expansionIndex[achievement.Expansion] = append(manager.expansionIndex[achievement.Expansion], achievement)
|
|
}
|
|
|
|
achievements := manager.GetAllAchievements()
|
|
|
|
if len(achievements) != 2 {
|
|
t.Errorf("Expected 2 achievements, got %d", len(achievements))
|
|
}
|
|
}
|
|
|
|
func TestGetAchievementsByCategory(t *testing.T) {
|
|
manager, _, _ := setupTestManager()
|
|
|
|
// Manually add achievements and build indexes
|
|
testAchievements := createTestAchievements()
|
|
for i := range testAchievements {
|
|
manager.achievements[testAchievements[i].AchievementID] = &testAchievements[i]
|
|
manager.categoryIndex[testAchievements[i].Category] = append(manager.categoryIndex[testAchievements[i].Category], &testAchievements[i])
|
|
}
|
|
|
|
combatAchievements := manager.GetAchievementsByCategory(CategoryCombat)
|
|
if len(combatAchievements) != 1 {
|
|
t.Errorf("Expected 1 combat achievement, got %d", len(combatAchievements))
|
|
}
|
|
|
|
explorationAchievements := manager.GetAchievementsByCategory(CategoryExploration)
|
|
if len(explorationAchievements) != 1 {
|
|
t.Errorf("Expected 1 exploration achievement, got %d", len(explorationAchievements))
|
|
}
|
|
}
|
|
|
|
func TestGetAchievementsByExpansion(t *testing.T) {
|
|
manager, _, _ := setupTestManager()
|
|
|
|
// Manually add achievements and build indexes
|
|
testAchievements := createTestAchievements()
|
|
for i := range testAchievements {
|
|
manager.achievements[testAchievements[i].AchievementID] = &testAchievements[i]
|
|
manager.expansionIndex[testAchievements[i].Expansion] = append(manager.expansionIndex[testAchievements[i].Expansion], &testAchievements[i])
|
|
}
|
|
|
|
baseAchievements := manager.GetAchievementsByExpansion(ExpansionBase)
|
|
if len(baseAchievements) != 2 {
|
|
t.Errorf("Expected 2 base expansion achievements, got %d", len(baseAchievements))
|
|
}
|
|
}
|
|
|
|
func TestGetCategories(t *testing.T) {
|
|
manager, _, _ := setupTestManager()
|
|
|
|
// Manually build category index
|
|
manager.categoryIndex[CategoryCombat] = []*Achievement{}
|
|
manager.categoryIndex[CategoryExploration] = []*Achievement{}
|
|
|
|
categories := manager.GetCategories()
|
|
|
|
if len(categories) != 2 {
|
|
t.Errorf("Expected 2 categories, got %d", len(categories))
|
|
}
|
|
|
|
// Check that both categories exist
|
|
categoryMap := make(map[string]bool)
|
|
for _, category := range categories {
|
|
categoryMap[category] = true
|
|
}
|
|
|
|
if !categoryMap[CategoryCombat] {
|
|
t.Error("Expected Combat category")
|
|
}
|
|
if !categoryMap[CategoryExploration] {
|
|
t.Error("Expected Exploration category")
|
|
}
|
|
}
|
|
|
|
func TestGetExpansions(t *testing.T) {
|
|
manager, _, _ := setupTestManager()
|
|
|
|
// Manually build expansion index
|
|
manager.expansionIndex[ExpansionBase] = []*Achievement{}
|
|
|
|
expansions := manager.GetExpansions()
|
|
|
|
if len(expansions) != 1 {
|
|
t.Errorf("Expected 1 expansion, got %d", len(expansions))
|
|
}
|
|
if expansions[0] != ExpansionBase {
|
|
t.Errorf("Expected expansion '%s', got '%s'", ExpansionBase, expansions[0])
|
|
}
|
|
}
|
|
|
|
func TestUpdatePlayerProgress(t *testing.T) {
|
|
manager, logger, _ := setupTestManager()
|
|
|
|
// Add test achievement
|
|
testAchievement := &Achievement{
|
|
AchievementID: 100,
|
|
Title: "Test Achievement",
|
|
QtyRequired: 5,
|
|
PointValue: 10,
|
|
}
|
|
manager.achievements[100] = testAchievement
|
|
|
|
ctx := context.Background()
|
|
characterID := uint32(12345)
|
|
achievementID := uint32(100)
|
|
|
|
// Test updating progress
|
|
err := manager.UpdatePlayerProgress(ctx, characterID, achievementID, 3)
|
|
if err != nil {
|
|
t.Fatalf("UpdatePlayerProgress failed: %v", err)
|
|
}
|
|
|
|
// Verify progress was set
|
|
progress, err := manager.GetPlayerAchievementProgress(characterID, achievementID)
|
|
if err != nil {
|
|
t.Fatalf("GetPlayerAchievementProgress failed: %v", err)
|
|
}
|
|
if progress != 3 {
|
|
t.Errorf("Expected progress 3, got %d", progress)
|
|
}
|
|
|
|
// Test auto-completion when reaching required quantity
|
|
err = manager.UpdatePlayerProgress(ctx, characterID, achievementID, 5)
|
|
if err != nil {
|
|
t.Fatalf("UpdatePlayerProgress failed: %v", err)
|
|
}
|
|
|
|
// Should be completed now
|
|
completed, err := manager.IsPlayerAchievementCompleted(characterID, achievementID)
|
|
if err != nil {
|
|
t.Fatalf("IsPlayerAchievementCompleted failed: %v", err)
|
|
}
|
|
if !completed {
|
|
t.Error("Expected achievement to be completed")
|
|
}
|
|
|
|
// Check that completion was logged
|
|
found := false
|
|
for _, msg := range logger.InfoMessages {
|
|
if msg == fmt.Sprintf("Character %d completed achievement %d", characterID, achievementID) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Error("Expected completion log message")
|
|
}
|
|
}
|
|
|
|
func TestCompletePlayerAchievement(t *testing.T) {
|
|
manager, logger, _ := setupTestManager()
|
|
|
|
// Add test achievement
|
|
manager.achievements[100] = &Achievement{AchievementID: 100, Title: "Test"}
|
|
|
|
ctx := context.Background()
|
|
characterID := uint32(12345)
|
|
achievementID := uint32(100)
|
|
|
|
// Complete the achievement
|
|
err := manager.CompletePlayerAchievement(ctx, characterID, achievementID)
|
|
if err != nil {
|
|
t.Fatalf("CompletePlayerAchievement failed: %v", err)
|
|
}
|
|
|
|
// Verify completion
|
|
completed, err := manager.IsPlayerAchievementCompleted(characterID, achievementID)
|
|
if err != nil {
|
|
t.Fatalf("IsPlayerAchievementCompleted failed: %v", err)
|
|
}
|
|
if !completed {
|
|
t.Error("Expected achievement to be completed")
|
|
}
|
|
|
|
// Check that completion was logged
|
|
found := false
|
|
for _, msg := range logger.InfoMessages {
|
|
if msg == fmt.Sprintf("Character %d completed achievement %d", characterID, achievementID) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Error("Expected completion log message")
|
|
}
|
|
|
|
// Test completing already completed achievement (should not log again)
|
|
originalLogCount := len(logger.InfoMessages)
|
|
err = manager.CompletePlayerAchievement(ctx, characterID, achievementID)
|
|
if err != nil {
|
|
t.Fatalf("CompletePlayerAchievement failed on already completed: %v", err)
|
|
}
|
|
|
|
if len(logger.InfoMessages) != originalLogCount {
|
|
t.Error("Expected no additional log message for already completed achievement")
|
|
}
|
|
}
|
|
|
|
func TestGetPlayerAchievements(t *testing.T) {
|
|
manager, _, _ := setupTestManager()
|
|
|
|
characterID := uint32(12345)
|
|
|
|
// Test with no achievements
|
|
achievements, err := manager.GetPlayerAchievements(characterID)
|
|
if err != nil {
|
|
t.Fatalf("GetPlayerAchievements failed: %v", err)
|
|
}
|
|
if len(achievements) != 0 {
|
|
t.Error("Expected empty achievements map")
|
|
}
|
|
|
|
// Add an achievement manually
|
|
manager.playerAchievements[characterID] = map[uint32]*PlayerAchievement{
|
|
100: {
|
|
CharacterID: characterID,
|
|
AchievementID: 100,
|
|
Progress: 3,
|
|
CompletedDate: time.Now(),
|
|
},
|
|
}
|
|
|
|
// Test with achievements
|
|
achievements, err = manager.GetPlayerAchievements(characterID)
|
|
if err != nil {
|
|
t.Fatalf("GetPlayerAchievements failed: %v", err)
|
|
}
|
|
if len(achievements) != 1 {
|
|
t.Errorf("Expected 1 achievement, got %d", len(achievements))
|
|
}
|
|
|
|
achievement, exists := achievements[100]
|
|
if !exists {
|
|
t.Error("Expected achievement 100 to exist")
|
|
}
|
|
if achievement.Progress != 3 {
|
|
t.Errorf("Expected progress 3, got %d", achievement.Progress)
|
|
}
|
|
}
|
|
|
|
func TestGetPlayerStatistics(t *testing.T) {
|
|
manager, _, _ := setupTestManager()
|
|
|
|
// Add test achievements
|
|
manager.achievements[100] = &Achievement{AchievementID: 100, PointValue: 10, Category: CategoryCombat}
|
|
manager.achievements[101] = &Achievement{AchievementID: 101, PointValue: 25, Category: CategoryExploration}
|
|
|
|
characterID := uint32(12345)
|
|
|
|
// Add player achievements - one completed, one in progress
|
|
manager.playerAchievements[characterID] = map[uint32]*PlayerAchievement{
|
|
100: {
|
|
CharacterID: characterID,
|
|
AchievementID: 100,
|
|
Progress: 10,
|
|
CompletedDate: time.Now(), // Completed
|
|
},
|
|
101: {
|
|
CharacterID: characterID,
|
|
AchievementID: 101,
|
|
Progress: 3,
|
|
CompletedDate: time.Time{}, // In progress
|
|
},
|
|
}
|
|
|
|
stats, err := manager.GetPlayerStatistics(characterID)
|
|
if err != nil {
|
|
t.Fatalf("GetPlayerStatistics failed: %v", err)
|
|
}
|
|
|
|
if stats.CharacterID != characterID {
|
|
t.Errorf("Expected character ID %d, got %d", characterID, stats.CharacterID)
|
|
}
|
|
if stats.TotalAchievements != 2 {
|
|
t.Errorf("Expected 2 total achievements, got %d", stats.TotalAchievements)
|
|
}
|
|
if stats.CompletedCount != 1 {
|
|
t.Errorf("Expected 1 completed achievement, got %d", stats.CompletedCount)
|
|
}
|
|
if stats.InProgressCount != 1 {
|
|
t.Errorf("Expected 1 in-progress achievement, got %d", stats.InProgressCount)
|
|
}
|
|
if stats.TotalPointsEarned != 10 {
|
|
t.Errorf("Expected 10 points earned, got %d", stats.TotalPointsEarned)
|
|
}
|
|
if stats.TotalPointsAvailable != 35 {
|
|
t.Errorf("Expected 35 points available, got %d", stats.TotalPointsAvailable)
|
|
}
|
|
if stats.CompletedByCategory[CategoryCombat] != 1 {
|
|
t.Errorf("Expected 1 combat achievement completed, got %d", stats.CompletedByCategory[CategoryCombat])
|
|
}
|
|
}
|
|
|
|
func TestInvalidAchievementOperations(t *testing.T) {
|
|
manager, _, _ := setupTestManager()
|
|
|
|
ctx := context.Background()
|
|
characterID := uint32(12345)
|
|
invalidAchievementID := uint32(999)
|
|
|
|
// Test updating progress for non-existent achievement
|
|
err := manager.UpdatePlayerProgress(ctx, characterID, invalidAchievementID, 1)
|
|
if err == nil {
|
|
t.Error("Expected error for invalid achievement ID")
|
|
}
|
|
|
|
// Test completing non-existent achievement
|
|
err = manager.CompletePlayerAchievement(ctx, characterID, invalidAchievementID)
|
|
if err == nil {
|
|
t.Error("Expected error for invalid achievement ID")
|
|
}
|
|
}
|
|
|
|
func TestThreadSafety(t *testing.T) {
|
|
manager, _, _ := setupTestManager()
|
|
|
|
// Add test achievement
|
|
manager.achievements[100] = &Achievement{
|
|
AchievementID: 100,
|
|
QtyRequired: 10,
|
|
PointValue: 10,
|
|
}
|
|
|
|
ctx := context.Background()
|
|
characterID := uint32(12345)
|
|
achievementID := uint32(100)
|
|
|
|
// Test concurrent access
|
|
done := make(chan bool, 10)
|
|
|
|
// Start 10 concurrent operations
|
|
for i := 0; i < 10; i++ {
|
|
go func(progress uint32) {
|
|
defer func() { done <- true }()
|
|
|
|
// Update progress
|
|
err := manager.UpdatePlayerProgress(ctx, characterID, achievementID, progress)
|
|
if err != nil {
|
|
t.Errorf("UpdatePlayerProgress failed: %v", err)
|
|
return
|
|
}
|
|
|
|
// Read progress
|
|
_, err = manager.GetPlayerAchievementProgress(characterID, achievementID)
|
|
if err != nil {
|
|
t.Errorf("GetPlayerAchievementProgress failed: %v", err)
|
|
return
|
|
}
|
|
|
|
// Check completion status
|
|
_, err = manager.IsPlayerAchievementCompleted(characterID, achievementID)
|
|
if err != nil {
|
|
t.Errorf("IsPlayerAchievementCompleted failed: %v", err)
|
|
return
|
|
}
|
|
}(uint32(i + 1))
|
|
}
|
|
|
|
// Wait for all operations to complete
|
|
for i := 0; i < 10; i++ {
|
|
<-done
|
|
}
|
|
}
|
|
|
|
func TestPacketBuilding(t *testing.T) {
|
|
manager, logger, _ := setupTestManager()
|
|
|
|
// Add test achievement
|
|
manager.achievements[100] = &Achievement{
|
|
AchievementID: 100,
|
|
Title: "Test Achievement",
|
|
CompletedText: "Completed!",
|
|
UncompletedText: "Not completed",
|
|
Category: CategoryCombat,
|
|
Expansion: ExpansionBase,
|
|
Icon: 1001,
|
|
PointValue: 10,
|
|
QtyRequired: 1,
|
|
Hide: false,
|
|
}
|
|
|
|
characterID := uint32(12345)
|
|
clientVersion := int32(1096)
|
|
|
|
// Test sending packet with no player achievements (should not error)
|
|
err := manager.SendPlayerAchievementsPacket(characterID, clientVersion)
|
|
if err != nil {
|
|
t.Fatalf("SendPlayerAchievementsPacket failed: %v", err)
|
|
}
|
|
|
|
// Should have debug message about packet building
|
|
found := false
|
|
expectedMsg := fmt.Sprintf("Built achievement list packet for character %d (0 achievements)", characterID)
|
|
for _, msg := range logger.DebugMessages {
|
|
if expectedMsg == msg {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Errorf("Expected debug message '%s', got messages: %v", expectedMsg, logger.DebugMessages)
|
|
}
|
|
}
|
|
|
|
func TestShutdown(t *testing.T) {
|
|
manager, logger, _ := setupTestManager()
|
|
|
|
ctx := context.Background()
|
|
err := manager.Shutdown(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Shutdown failed: %v", err)
|
|
}
|
|
|
|
// Should have info message about shutdown
|
|
found := false
|
|
for _, msg := range logger.InfoMessages {
|
|
if msg == "Shutting down achievement manager" {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Error("Expected shutdown log message")
|
|
}
|
|
}
|
|
|
|
// Benchmark tests
|
|
func BenchmarkGetAchievement(b *testing.B) {
|
|
manager, _, _ := setupTestManager()
|
|
|
|
// Add many achievements
|
|
for i := uint32(0); i < 1000; i++ {
|
|
manager.achievements[i] = &Achievement{AchievementID: i, Title: fmt.Sprintf("Achievement %d", i)}
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, _ = manager.GetAchievement(uint32(i % 1000))
|
|
}
|
|
}
|
|
|
|
func BenchmarkUpdatePlayerProgress(b *testing.B) {
|
|
manager, _, _ := setupTestManager()
|
|
|
|
// Add test achievement
|
|
manager.achievements[100] = &Achievement{
|
|
AchievementID: 100,
|
|
QtyRequired: 1000000, // High value so it doesn't auto-complete
|
|
PointValue: 10,
|
|
}
|
|
|
|
ctx := context.Background()
|
|
characterID := uint32(12345)
|
|
achievementID := uint32(100)
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_ = manager.UpdatePlayerProgress(ctx, characterID, achievementID, uint32(i))
|
|
}
|
|
} |