package rules import ( "testing" ) // Test Rule creation and basic functionality func TestRule(t *testing.T) { // Test NewRule with default values rule := NewRule() if rule == nil { t.Fatal("NewRule() returned nil") } if rule.GetCategory() != 0 { t.Errorf("Expected category 0, got %d", rule.GetCategory()) } if rule.GetType() != 0 { t.Errorf("Expected type 0, got %d", rule.GetType()) } if rule.GetValue() != "" { t.Errorf("Expected empty value, got %s", rule.GetValue()) } if rule.GetCombined() != "NONE" { t.Errorf("Expected combined 'NONE', got %s", rule.GetCombined()) } // Test NewRuleWithValues rule2 := NewRuleWithValues(CategoryPlayer, PlayerMaxLevel, "50", "Player:MaxLevel") if rule2 == nil { t.Fatal("NewRuleWithValues() returned nil") } if rule2.GetCategory() != CategoryPlayer { t.Errorf("Expected category %d, got %d", CategoryPlayer, rule2.GetCategory()) } if rule2.GetType() != PlayerMaxLevel { t.Errorf("Expected type %d, got %d", PlayerMaxLevel, rule2.GetType()) } if rule2.GetValue() != "50" { t.Errorf("Expected value '50', got %s", rule2.GetValue()) } if rule2.GetCombined() != "Player:MaxLevel" { t.Errorf("Expected combined 'Player:MaxLevel', got %s", rule2.GetCombined()) } // Test type conversion methods if rule2.GetInt32() != 50 { t.Errorf("Expected int32 50, got %d", rule2.GetInt32()) } if rule2.GetBool() != true { t.Errorf("Expected bool true, got %t", rule2.GetBool()) } // Test SetValue rule2.SetValue("100") if rule2.GetValue() != "100" { t.Errorf("Expected value '100' after SetValue, got %s", rule2.GetValue()) } if rule2.GetInt32() != 100 { t.Errorf("Expected int32 100 after SetValue, got %d", rule2.GetInt32()) } } // Test Rule copy constructor func TestRuleCopy(t *testing.T) { original := NewRuleWithValues(CategoryCombat, CombatMaxRange, "4.0", "Combat:MaxCombatRange") copy := NewRuleFromRule(original) if copy == nil { t.Fatal("NewRuleFromRule() returned nil") } if copy.GetCategory() != original.GetCategory() { t.Errorf("Copy category mismatch: expected %d, got %d", original.GetCategory(), copy.GetCategory()) } if copy.GetType() != original.GetType() { t.Errorf("Copy type mismatch: expected %d, got %d", original.GetType(), copy.GetType()) } if copy.GetValue() != original.GetValue() { t.Errorf("Copy value mismatch: expected %s, got %s", original.GetValue(), copy.GetValue()) } if copy.GetCombined() != original.GetCombined() { t.Errorf("Copy combined mismatch: expected %s, got %s", original.GetCombined(), copy.GetCombined()) } // Test that they are independent copies copy.SetValue("8.0") if original.GetValue() == copy.GetValue() { t.Error("Original and copy are not independent after modification") } } // Test RuleSet creation and basic operations func TestRuleSet(t *testing.T) { ruleSet := NewRuleSet() if ruleSet == nil { t.Fatal("NewRuleSet() returned nil") } if ruleSet.GetID() != 0 { t.Errorf("Expected ID 0, got %d", ruleSet.GetID()) } if ruleSet.GetName() != "" { t.Errorf("Expected empty name, got %s", ruleSet.GetName()) } // Test SetID and SetName ruleSet.SetID(1) ruleSet.SetName("Test Rule Set") if ruleSet.GetID() != 1 { t.Errorf("Expected ID 1, got %d", ruleSet.GetID()) } if ruleSet.GetName() != "Test Rule Set" { t.Errorf("Expected name 'Test Rule Set', got %s", ruleSet.GetName()) } // Test adding rules rule1 := NewRuleWithValues(CategoryPlayer, PlayerMaxLevel, "50", "Player:MaxLevel") rule2 := NewRuleWithValues(CategoryCombat, CombatMaxRange, "4.0", "Combat:MaxCombatRange") ruleSet.AddRule(rule1) ruleSet.AddRule(rule2) // Test rule retrieval retrievedRule1 := ruleSet.GetRule(CategoryPlayer, PlayerMaxLevel) if retrievedRule1 == nil { t.Fatal("GetRule() returned nil for added rule") } if retrievedRule1.GetValue() != "50" { t.Errorf("Retrieved rule value mismatch: expected '50', got %s", retrievedRule1.GetValue()) } // Test rule retrieval by name retrievedRule2 := ruleSet.GetRuleByName("Combat", "MaxCombatRange") if retrievedRule2 == nil { t.Fatal("GetRuleByName() returned nil for added rule") } if retrievedRule2.GetValue() != "4.0" { t.Errorf("Retrieved rule value mismatch: expected '4.0', got %s", retrievedRule2.GetValue()) } // Test Size if ruleSet.Size() != 2 { t.Errorf("Expected size 2, got %d", ruleSet.Size()) } // Test HasRule if !ruleSet.HasRule(CategoryPlayer, PlayerMaxLevel) { t.Error("HasRule() returned false for existing rule") } if ruleSet.HasRule(CategorySpawn, SpawnSpeedMultiplier) { t.Error("HasRule() returned true for non-existing rule") } } // Test RuleSet copy functionality func TestRuleSetCopy(t *testing.T) { original := NewRuleSet() original.SetID(1) original.SetName("Original") rule1 := NewRuleWithValues(CategoryPlayer, PlayerMaxLevel, "50", "Player:MaxLevel") rule2 := NewRuleWithValues(CategoryCombat, CombatMaxRange, "4.0", "Combat:MaxCombatRange") original.AddRule(rule1) original.AddRule(rule2) // Test copy constructor copy := NewRuleSetFromRuleSet(original) if copy == nil { t.Fatal("NewRuleSetFromRuleSet() returned nil") } if copy.GetID() != original.GetID() { t.Errorf("Copy ID mismatch: expected %d, got %d", original.GetID(), copy.GetID()) } if copy.GetName() != original.GetName() { t.Errorf("Copy name mismatch: expected %s, got %s", original.GetName(), copy.GetName()) } if copy.Size() != original.Size() { t.Errorf("Copy size mismatch: expected %d, got %d", original.Size(), copy.Size()) } // Test that rules were copied correctly copyRule := copy.GetRule(CategoryPlayer, PlayerMaxLevel) if copyRule == nil { t.Fatal("Copied rule set is missing expected rule") } if copyRule.GetValue() != "50" { t.Errorf("Copied rule value mismatch: expected '50', got %s", copyRule.GetValue()) } } // Test RuleManager initialization func TestRuleManager(t *testing.T) { ruleManager := NewRuleManager() if ruleManager == nil { t.Fatal("NewRuleManager() returned nil") } if !ruleManager.IsInitialized() { t.Error("RuleManager should be initialized after creation") } // Test getting a default rule rule := ruleManager.GetGlobalRule(CategoryPlayer, PlayerMaxLevel) if rule == nil { t.Fatal("GetGlobalRule() returned nil for default rule") } // Should return the default value from Init() if rule.GetValue() != "50" { t.Errorf("Expected default value '50', got %s", rule.GetValue()) } // Test getting rule by name rule2 := ruleManager.GetGlobalRuleByName("Player", "MaxLevel") if rule2 == nil { t.Fatal("GetGlobalRuleByName() returned nil for default rule") } if rule2.GetValue() != "50" { t.Errorf("Expected default value '50', got %s", rule2.GetValue()) } // Test blank rule for non-existent rule blankRule := ruleManager.GetGlobalRule(9999, 9999) if blankRule == nil { t.Fatal("GetGlobalRule() should return blank rule for non-existent rule") } if blankRule.IsValid() { t.Error("Blank rule should not be valid") } } // Test RuleManager rule set operations func TestRuleManagerRuleSets(t *testing.T) { ruleManager := NewRuleManager() // Create a test rule set ruleSet := NewRuleSet() ruleSet.SetID(1) ruleSet.SetName("Test Set") // Add some rules to it rule1 := NewRuleWithValues(CategoryPlayer, PlayerMaxLevel, "60", "Player:MaxLevel") ruleSet.AddRule(rule1) // Add the rule set to the manager if !ruleManager.AddRuleSet(ruleSet) { t.Fatal("AddRuleSet() returned false") } // Test getting the rule set retrievedRuleSet := ruleManager.GetRuleSet(1) if retrievedRuleSet == nil { t.Fatal("GetRuleSet() returned nil") } if retrievedRuleSet.GetName() != "Test Set" { t.Errorf("Retrieved rule set name mismatch: expected 'Test Set', got %s", retrievedRuleSet.GetName()) } // Test duplicate rule set duplicateRuleSet := NewRuleSet() duplicateRuleSet.SetID(1) duplicateRuleSet.SetName("Duplicate") if ruleManager.AddRuleSet(duplicateRuleSet) { t.Error("AddRuleSet() should return false for duplicate ID") } // Test GetNumRuleSets if ruleManager.GetNumRuleSets() != 1 { t.Errorf("Expected 1 rule set, got %d", ruleManager.GetNumRuleSets()) } // Test setting global rule set if !ruleManager.SetGlobalRuleSet(1) { t.Fatal("SetGlobalRuleSet() returned false") } // Test that global rule now returns the overridden value globalRule := ruleManager.GetGlobalRule(CategoryPlayer, PlayerMaxLevel) if globalRule == nil { t.Fatal("GetGlobalRule() returned nil after setting global rule set") } if globalRule.GetValue() != "60" { t.Errorf("Expected overridden value '60', got %s", globalRule.GetValue()) } } // Test category and type name functions func TestCategoryNames(t *testing.T) { // Test GetCategoryName name := GetCategoryName(CategoryPlayer) if name != "Player" { t.Errorf("Expected category name 'Player', got %s", name) } // Test unknown category unknownName := GetCategoryName(9999) if unknownName != "Unknown" { t.Errorf("Expected 'Unknown' for invalid category, got %s", unknownName) } // Test GetCategoryByName category, exists := GetCategoryByName("Player") if !exists { t.Error("GetCategoryByName() should find 'Player' category") } if category != CategoryPlayer { t.Errorf("Expected category %d, got %d", CategoryPlayer, category) } // Test unknown category name _, exists = GetCategoryByName("NonExistent") if exists { t.Error("GetCategoryByName() should not find non-existent category") } } // Test rule validation func TestRuleValidation(t *testing.T) { ruleManager := NewRuleManager() // Test valid rule err := ruleManager.ValidateRule(CategoryPlayer, PlayerMaxLevel, "50") if err != nil { t.Errorf("ValidateRule() returned error for valid rule: %v", err) } // Test rule value too long longValue := make([]byte, MaxRuleValueLength+1) for i := range longValue { longValue[i] = 'a' } err = ruleManager.ValidateRule(CategoryPlayer, PlayerMaxLevel, string(longValue)) if err != ErrRuleValueTooLong { t.Errorf("ValidateRule() should return ErrRuleValueTooLong for long value") } } // Test RuleManagerAdapter func TestRuleManagerAdapter(t *testing.T) { ruleManager := NewRuleManager() adapter := NewRuleManagerAdapter(ruleManager, 0) if adapter == nil { t.Fatal("NewRuleManagerAdapter() returned nil") } // Test basic rule access rule := adapter.GetRule(CategoryPlayer, PlayerMaxLevel) if rule == nil { t.Fatal("Adapter GetRule() returned nil") } if rule.GetValue() != "50" { t.Errorf("Expected value '50', got %s", rule.GetValue()) } // Test convenience methods intValue := adapter.GetInt32(CategoryPlayer, PlayerMaxLevel) if intValue != 50 { t.Errorf("Expected int32 50, got %d", intValue) } boolValue := adapter.GetBool(CategoryPlayer, PlayerMaxLevel) if !boolValue { t.Error("Expected bool true for value '50'") } stringValue := adapter.GetString(CategoryPlayer, PlayerMaxLevel) if stringValue != "50" { t.Errorf("Expected string '50', got %s", stringValue) } // Test zone ID if adapter.GetZoneID() != 0 { t.Errorf("Expected zone ID 0, got %d", adapter.GetZoneID()) } adapter.SetZoneID(100) if adapter.GetZoneID() != 100 { t.Errorf("Expected zone ID 100 after SetZoneID, got %d", adapter.GetZoneID()) } } // Benchmark rule access performance func BenchmarkRuleAccess(b *testing.B) { ruleManager := NewRuleManager() b.ResetTimer() for i := 0; i < b.N; i++ { _ = ruleManager.GetGlobalRule(CategoryPlayer, PlayerMaxLevel) } } // Benchmark rule manager creation func BenchmarkRuleManagerCreation(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { _ = NewRuleManager() } }