514 lines
13 KiB
Go
514 lines
13 KiB
Go
package entity
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestNewInfoStruct(t *testing.T) {
|
|
info := NewInfoStruct()
|
|
if info == nil {
|
|
t.Fatal("NewInfoStruct returned nil")
|
|
}
|
|
|
|
// Test default values
|
|
if info.GetName() != "" {
|
|
t.Errorf("Expected empty name, got %s", info.GetName())
|
|
}
|
|
|
|
if info.GetLevel() != 0 {
|
|
t.Errorf("Expected level 0, got %d", info.GetLevel())
|
|
}
|
|
|
|
if info.GetMaxConcentration() != 5 {
|
|
t.Errorf("Expected max concentration 5, got %d", info.GetMaxConcentration())
|
|
}
|
|
|
|
if info.GetCurConcentration() != 0 {
|
|
t.Errorf("Expected current concentration 0, got %d", info.GetCurConcentration())
|
|
}
|
|
}
|
|
|
|
func TestInfoStructBasicProperties(t *testing.T) {
|
|
info := NewInfoStruct()
|
|
|
|
// Test name
|
|
info.SetName("Test Character")
|
|
if info.GetName() != "Test Character" {
|
|
t.Errorf("Expected name 'Test Character', got %s", info.GetName())
|
|
}
|
|
|
|
// Test level
|
|
info.SetLevel(25)
|
|
if info.GetLevel() != 25 {
|
|
t.Errorf("Expected level 25, got %d", info.GetLevel())
|
|
}
|
|
|
|
// Test effective level
|
|
info.SetEffectiveLevel(30)
|
|
if info.GetEffectiveLevel() != 30 {
|
|
t.Errorf("Expected effective level 30, got %d", info.GetEffectiveLevel())
|
|
}
|
|
|
|
// Test class
|
|
info.SetClass1(5)
|
|
if info.GetClass1() != 5 {
|
|
t.Errorf("Expected class 5, got %d", info.GetClass1())
|
|
}
|
|
|
|
// Test race
|
|
info.SetRace(3)
|
|
if info.GetRace() != 3 {
|
|
t.Errorf("Expected race 3, got %d", info.GetRace())
|
|
}
|
|
|
|
// Test gender
|
|
info.SetGender(1)
|
|
if info.GetGender() != 1 {
|
|
t.Errorf("Expected gender 1, got %d", info.GetGender())
|
|
}
|
|
}
|
|
|
|
func TestInfoStructStats(t *testing.T) {
|
|
info := NewInfoStruct()
|
|
|
|
// Test strength
|
|
info.SetStr(15.5)
|
|
if info.GetStr() != 15.5 {
|
|
t.Errorf("Expected strength 15.5, got %f", info.GetStr())
|
|
}
|
|
|
|
// Test stamina
|
|
info.SetSta(20.0)
|
|
if info.GetSta() != 20.0 {
|
|
t.Errorf("Expected stamina 20.0, got %f", info.GetSta())
|
|
}
|
|
|
|
// Test agility
|
|
info.SetAgi(12.75)
|
|
if info.GetAgi() != 12.75 {
|
|
t.Errorf("Expected agility 12.75, got %f", info.GetAgi())
|
|
}
|
|
|
|
// Test wisdom
|
|
info.SetWis(18.25)
|
|
if info.GetWis() != 18.25 {
|
|
t.Errorf("Expected wisdom 18.25, got %f", info.GetWis())
|
|
}
|
|
|
|
// Test intelligence
|
|
info.SetIntel(22.5)
|
|
if info.GetIntel() != 22.5 {
|
|
t.Errorf("Expected intelligence 22.5, got %f", info.GetIntel())
|
|
}
|
|
}
|
|
|
|
func TestInfoStructConcentration(t *testing.T) {
|
|
info := NewInfoStruct()
|
|
|
|
// Test setting max concentration
|
|
info.SetMaxConcentration(15)
|
|
if info.GetMaxConcentration() != 15 {
|
|
t.Errorf("Expected max concentration 15, got %d", info.GetMaxConcentration())
|
|
}
|
|
|
|
// Test adding concentration
|
|
success := info.AddConcentration(5)
|
|
if !success {
|
|
t.Error("Expected AddConcentration to succeed")
|
|
}
|
|
|
|
if info.GetCurConcentration() != 5 {
|
|
t.Errorf("Expected current concentration 5, got %d", info.GetCurConcentration())
|
|
}
|
|
|
|
// Test adding concentration that would exceed maximum
|
|
success = info.AddConcentration(12)
|
|
if success {
|
|
t.Error("Expected AddConcentration to fail when exceeding maximum")
|
|
}
|
|
|
|
if info.GetCurConcentration() != 5 {
|
|
t.Errorf("Expected current concentration to remain 5, got %d", info.GetCurConcentration())
|
|
}
|
|
|
|
// Test adding concentration that exactly reaches maximum
|
|
success = info.AddConcentration(10)
|
|
if !success {
|
|
t.Error("Expected AddConcentration to succeed when exactly reaching maximum")
|
|
}
|
|
|
|
if info.GetCurConcentration() != 15 {
|
|
t.Errorf("Expected current concentration 15, got %d", info.GetCurConcentration())
|
|
}
|
|
|
|
// Test removing concentration
|
|
info.RemoveConcentration(7)
|
|
if info.GetCurConcentration() != 8 {
|
|
t.Errorf("Expected current concentration 8, got %d", info.GetCurConcentration())
|
|
}
|
|
|
|
// Test removing more concentration than available
|
|
info.RemoveConcentration(20)
|
|
if info.GetCurConcentration() != 0 {
|
|
t.Errorf("Expected current concentration to be clamped to 0, got %d", info.GetCurConcentration())
|
|
}
|
|
}
|
|
|
|
func TestInfoStructCoins(t *testing.T) {
|
|
info := NewInfoStruct()
|
|
|
|
// Test initial coins
|
|
if info.GetCoins() != 0 {
|
|
t.Errorf("Expected initial coins 0, got %d", info.GetCoins())
|
|
}
|
|
|
|
// Test adding copper
|
|
info.AddCoins(150) // 1 silver and 50 copper
|
|
totalCopper := info.GetCoins()
|
|
if totalCopper != 150 {
|
|
t.Errorf("Expected total coins 150, got %d", totalCopper)
|
|
}
|
|
|
|
// Test adding large amount that converts to higher denominations
|
|
info.AddCoins(1234567) // Should convert to plat, gold, silver, copper
|
|
expectedTotal := 150 + 1234567
|
|
totalCopper = info.GetCoins()
|
|
if totalCopper != int32(expectedTotal) {
|
|
t.Errorf("Expected total coins %d, got %d", expectedTotal, totalCopper)
|
|
}
|
|
|
|
// Test removing coins
|
|
success := info.RemoveCoins(100)
|
|
if !success {
|
|
t.Error("Expected RemoveCoins to succeed")
|
|
}
|
|
|
|
expectedTotal -= 100
|
|
totalCopper = info.GetCoins()
|
|
if totalCopper != int32(expectedTotal) {
|
|
t.Errorf("Expected total coins %d after removal, got %d", expectedTotal, totalCopper)
|
|
}
|
|
|
|
// Test removing more coins than available
|
|
success = info.RemoveCoins(9999999)
|
|
if success {
|
|
t.Error("Expected RemoveCoins to fail when removing more than available")
|
|
}
|
|
|
|
// Total should remain unchanged
|
|
totalCopper = info.GetCoins()
|
|
if totalCopper != int32(expectedTotal) {
|
|
t.Errorf("Expected total coins to remain %d, got %d", expectedTotal, totalCopper)
|
|
}
|
|
}
|
|
|
|
func TestInfoStructResistances(t *testing.T) {
|
|
info := NewInfoStruct()
|
|
|
|
// Test all resistance types
|
|
resistanceTypes := []string{"heat", "cold", "magic", "mental", "divine", "disease", "poison"}
|
|
expectedValues := []int16{10, 15, 20, 25, 30, 35, 40}
|
|
|
|
for i, resistType := range resistanceTypes {
|
|
expectedValue := expectedValues[i]
|
|
|
|
// Set resistance
|
|
info.SetResistance(resistType, expectedValue)
|
|
|
|
// Get resistance
|
|
actualValue := info.GetResistance(resistType)
|
|
if actualValue != expectedValue {
|
|
t.Errorf("Expected %s resistance %d, got %d", resistType, expectedValue, actualValue)
|
|
}
|
|
}
|
|
|
|
// Test invalid resistance type
|
|
unknownResist := info.GetResistance("unknown")
|
|
if unknownResist != 0 {
|
|
t.Errorf("Expected unknown resistance type to return 0, got %d", unknownResist)
|
|
}
|
|
|
|
// Setting invalid resistance type should not panic
|
|
info.SetResistance("unknown", 50) // Should be ignored
|
|
}
|
|
|
|
func TestInfoStructResetEffects(t *testing.T) {
|
|
info := NewInfoStruct()
|
|
|
|
// Set some base values first (these would normally be set during character creation)
|
|
info.str = 10.0
|
|
info.strBase = 10.0
|
|
info.sta = 12.0
|
|
info.staBase = 12.0
|
|
info.heat = 15
|
|
info.heatBase = 15
|
|
|
|
// Modify current values to simulate bonuses
|
|
info.SetStr(20.0)
|
|
info.SetSta(25.0)
|
|
info.SetResistance("heat", 30)
|
|
|
|
// Reset effects
|
|
info.ResetEffects()
|
|
|
|
// Check that values were reset to base
|
|
if info.GetStr() != 10.0 {
|
|
t.Errorf("Expected strength to reset to 10.0, got %f", info.GetStr())
|
|
}
|
|
|
|
if info.GetSta() != 12.0 {
|
|
t.Errorf("Expected stamina to reset to 12.0, got %f", info.GetSta())
|
|
}
|
|
|
|
if info.GetResistance("heat") != 15 {
|
|
t.Errorf("Expected heat resistance to reset to 15, got %d", info.GetResistance("heat"))
|
|
}
|
|
}
|
|
|
|
func TestInfoStructCalculatePrimaryStat(t *testing.T) {
|
|
info := NewInfoStruct()
|
|
|
|
// Set all stats to different values
|
|
info.SetStr(10.0)
|
|
info.SetSta(15.0)
|
|
info.SetAgi(8.0)
|
|
info.SetWis(20.0) // This should be the highest
|
|
info.SetIntel(12.0)
|
|
|
|
primaryStat := info.CalculatePrimaryStat()
|
|
if primaryStat != 20.0 {
|
|
t.Errorf("Expected primary stat 20.0 (wisdom), got %f", primaryStat)
|
|
}
|
|
|
|
// Test with intelligence being highest
|
|
info.SetIntel(25.0)
|
|
primaryStat = info.CalculatePrimaryStat()
|
|
if primaryStat != 25.0 {
|
|
t.Errorf("Expected primary stat 25.0 (intelligence), got %f", primaryStat)
|
|
}
|
|
|
|
// Test with all stats equal
|
|
info.SetStr(30.0)
|
|
info.SetSta(30.0)
|
|
info.SetAgi(30.0)
|
|
info.SetWis(30.0)
|
|
info.SetIntel(30.0)
|
|
|
|
primaryStat = info.CalculatePrimaryStat()
|
|
if primaryStat != 30.0 {
|
|
t.Errorf("Expected primary stat 30.0 (all equal), got %f", primaryStat)
|
|
}
|
|
}
|
|
|
|
func TestInfoStructClone(t *testing.T) {
|
|
info := NewInfoStruct()
|
|
|
|
// Set some values
|
|
info.SetName("Original Character")
|
|
info.SetLevel(15)
|
|
info.SetStr(20.0)
|
|
info.SetResistance("magic", 25)
|
|
info.AddConcentration(3)
|
|
|
|
// Clone the info struct
|
|
clone := info.Clone()
|
|
if clone == nil {
|
|
t.Fatal("Clone returned nil")
|
|
}
|
|
|
|
// Verify clone has same values
|
|
if clone.GetName() != "Original Character" {
|
|
t.Errorf("Expected cloned name 'Original Character', got %s", clone.GetName())
|
|
}
|
|
|
|
if clone.GetLevel() != 15 {
|
|
t.Errorf("Expected cloned level 15, got %d", clone.GetLevel())
|
|
}
|
|
|
|
if clone.GetStr() != 20.0 {
|
|
t.Errorf("Expected cloned strength 20.0, got %f", clone.GetStr())
|
|
}
|
|
|
|
if clone.GetResistance("magic") != 25 {
|
|
t.Errorf("Expected cloned magic resistance 25, got %d", clone.GetResistance("magic"))
|
|
}
|
|
|
|
if clone.GetCurConcentration() != 3 {
|
|
t.Errorf("Expected cloned concentration 3, got %d", clone.GetCurConcentration())
|
|
}
|
|
|
|
// Verify that modifying the clone doesn't affect the original
|
|
clone.SetName("Cloned Character")
|
|
clone.SetLevel(20)
|
|
|
|
if info.GetName() != "Original Character" {
|
|
t.Error("Original name was modified when clone was changed")
|
|
}
|
|
|
|
if info.GetLevel() != 15 {
|
|
t.Error("Original level was modified when clone was changed")
|
|
}
|
|
}
|
|
|
|
func TestInfoStructGetUptime(t *testing.T) {
|
|
info := NewInfoStruct()
|
|
|
|
// Test uptime (currently returns 0 as it's not implemented)
|
|
uptime := info.GetUptime()
|
|
if uptime != time.Duration(0) {
|
|
t.Errorf("Expected uptime to be 0 (not implemented), got %v", uptime)
|
|
}
|
|
}
|
|
|
|
func TestInfoStructConcurrency(t *testing.T) {
|
|
info := NewInfoStruct()
|
|
info.SetMaxConcentration(100)
|
|
|
|
var wg sync.WaitGroup
|
|
numGoroutines := 20
|
|
|
|
// Test concurrent access to basic properties
|
|
wg.Add(numGoroutines)
|
|
for i := 0; i < numGoroutines; i++ {
|
|
go func(index int) {
|
|
defer wg.Done()
|
|
|
|
// Each goroutine sets unique values
|
|
info.SetName("Character" + string(rune('A'+index)))
|
|
_ = info.GetName()
|
|
|
|
info.SetLevel(int16(10 + index))
|
|
_ = info.GetLevel()
|
|
|
|
info.SetStr(float32(10.0 + float32(index)))
|
|
_ = info.GetStr()
|
|
}(i)
|
|
}
|
|
wg.Wait()
|
|
|
|
// Test concurrent concentration operations
|
|
wg.Add(numGoroutines)
|
|
for i := 0; i < numGoroutines; i++ {
|
|
go func() {
|
|
defer wg.Done()
|
|
|
|
// Try to add concentration
|
|
if info.AddConcentration(1) {
|
|
// If successful, remove it after a short delay
|
|
time.Sleep(time.Microsecond)
|
|
info.RemoveConcentration(1)
|
|
}
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
|
|
// After all operations, concentration should be back to 0
|
|
// (This might not always be true due to race conditions, but shouldn't crash)
|
|
_ = info.GetCurConcentration()
|
|
|
|
// Test concurrent coin operations
|
|
wg.Add(numGoroutines)
|
|
for i := 0; i < numGoroutines; i++ {
|
|
go func(amount int32) {
|
|
defer wg.Done()
|
|
|
|
info.AddCoins(amount)
|
|
_ = info.GetCoins()
|
|
|
|
// Try to remove some coins
|
|
info.RemoveCoins(amount / 2)
|
|
}(int32(100 + i))
|
|
}
|
|
wg.Wait()
|
|
|
|
// Test concurrent resistance operations
|
|
wg.Add(numGoroutines)
|
|
for i := 0; i < numGoroutines; i++ {
|
|
go func(value int16) {
|
|
defer wg.Done()
|
|
|
|
info.SetResistance("heat", value)
|
|
_ = info.GetResistance("heat")
|
|
|
|
info.SetResistance("cold", value+1)
|
|
_ = info.GetResistance("cold")
|
|
}(int16(i))
|
|
}
|
|
wg.Wait()
|
|
}
|
|
|
|
func TestInfoStructLargeValues(t *testing.T) {
|
|
info := NewInfoStruct()
|
|
|
|
// Test with large coin amounts
|
|
largeCoinAmount := int32(2000000000) // 2 billion copper
|
|
info.AddCoins(largeCoinAmount)
|
|
|
|
totalCoins := info.GetCoins()
|
|
if totalCoins != largeCoinAmount {
|
|
t.Errorf("Expected large coin amount %d, got %d", largeCoinAmount, totalCoins)
|
|
}
|
|
|
|
// Test removing large amounts
|
|
success := info.RemoveCoins(largeCoinAmount)
|
|
if !success {
|
|
t.Error("Expected to be able to remove large coin amount")
|
|
}
|
|
|
|
if info.GetCoins() != 0 {
|
|
t.Errorf("Expected coins to be 0 after removing all, got %d", info.GetCoins())
|
|
}
|
|
|
|
// Test with maximum values
|
|
info.SetMaxConcentration(32767) // Max int16
|
|
info.SetLevel(32767)
|
|
|
|
if info.GetMaxConcentration() != 32767 {
|
|
t.Errorf("Expected max concentration 32767, got %d", info.GetMaxConcentration())
|
|
}
|
|
|
|
if info.GetLevel() != 32767 {
|
|
t.Errorf("Expected level 32767, got %d", info.GetLevel())
|
|
}
|
|
}
|
|
|
|
func TestInfoStructEdgeCases(t *testing.T) {
|
|
info := NewInfoStruct()
|
|
|
|
// Test negative values
|
|
info.SetStr(-5.0)
|
|
if info.GetStr() != -5.0 {
|
|
t.Errorf("Expected negative strength -5.0, got %f", info.GetStr())
|
|
}
|
|
|
|
// Test zero values
|
|
info.SetMaxConcentration(0)
|
|
success := info.AddConcentration(1)
|
|
if success {
|
|
t.Error("Expected AddConcentration to fail with max concentration 0")
|
|
}
|
|
|
|
// Test very small float values
|
|
info.SetAgi(0.001)
|
|
if info.GetAgi() != 0.001 {
|
|
t.Errorf("Expected small agility 0.001, got %f", info.GetAgi())
|
|
}
|
|
|
|
// Test empty string name
|
|
info.SetName("")
|
|
if info.GetName() != "" {
|
|
t.Errorf("Expected empty name, got '%s'", info.GetName())
|
|
}
|
|
|
|
// Test very long name
|
|
longName := string(make([]byte, 1000))
|
|
for i := range longName {
|
|
longName = longName[:i] + "A" + longName[i+1:]
|
|
}
|
|
info.SetName(longName)
|
|
if info.GetName() != longName {
|
|
t.Error("Expected to handle very long names")
|
|
}
|
|
} |