eq2go/internal/rules/rules_test.go

430 lines
11 KiB
Go

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()
}
}