eq2go/internal/chat/channel_test.go

341 lines
8.7 KiB
Go

package chat
import (
"testing"
"eq2emu/internal/database"
)
func TestNew(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 channel
channel := New(db)
if channel == nil {
t.Fatal("New returned nil")
}
if !channel.IsNew() {
t.Error("New channel should be marked as new")
}
// Test setting values
channel.ID = 1001
channel.Name = "Test Channel"
channel.ChannelType = ChannelTypeCustom
if channel.GetID() != 1001 {
t.Errorf("Expected GetID() to return 1001, got %d", channel.GetID())
}
if channel.GetName() != "Test Channel" {
t.Errorf("Expected GetName() to return 'Test Channel', got %s", channel.GetName())
}
if channel.GetType() != ChannelTypeCustom {
t.Errorf("Expected GetType() to return %d, got %d", ChannelTypeCustom, channel.GetType())
}
}
func TestNewWithData(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()
channel := NewWithData(100, "Auction", ChannelTypeWorld, db)
if channel == nil {
t.Fatal("NewWithData returned nil")
}
if channel.GetID() != 100 {
t.Errorf("Expected ID 100, got %d", channel.GetID())
}
if channel.GetName() != "Auction" {
t.Errorf("Expected name 'Auction', got '%s'", channel.GetName())
}
if channel.GetType() != ChannelTypeWorld {
t.Errorf("Expected type %d, got %d", ChannelTypeWorld, channel.GetType())
}
if !channel.IsNew() {
t.Error("NewWithData should create new channel")
}
}
func TestChannelGettersAndSetters(t *testing.T) {
db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared")
defer db.Close()
channel := NewWithData(123, "Test Channel", ChannelTypeCustom, db)
// Test getters
if id := channel.GetID(); id != 123 {
t.Errorf("GetID() = %v, want 123", id)
}
if name := channel.GetName(); name != "Test Channel" {
t.Errorf("GetName() = %v, want Test Channel", name)
}
if channelType := channel.GetType(); channelType != ChannelTypeCustom {
t.Errorf("GetType() = %v, want %d", channelType, ChannelTypeCustom)
}
// Test setters
channel.SetName("Modified Channel")
if channel.GetName() != "Modified Channel" {
t.Errorf("SetName failed: got %v, want Modified Channel", channel.GetName())
}
channel.SetType(ChannelTypeWorld)
if channel.GetType() != ChannelTypeWorld {
t.Errorf("SetType failed: got %v, want %d", channel.GetType(), ChannelTypeWorld)
}
channel.SetLevelRestriction(10)
if channel.LevelRestriction != 10 {
t.Errorf("SetLevelRestriction failed: got %v, want 10", channel.LevelRestriction)
}
channel.SetPassword("secret")
if !channel.HasPassword() {
t.Error("HasPassword should return true after setting password")
}
if !channel.PasswordMatches("secret") {
t.Error("PasswordMatches should return true for correct password")
}
if channel.PasswordMatches("wrong") {
t.Error("PasswordMatches should return false for incorrect password")
}
}
func TestChannelMembership(t *testing.T) {
db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared")
defer db.Close()
channel := NewWithData(100, "Test", ChannelTypeCustom, db)
// Test empty channel
if !channel.IsEmpty() {
t.Error("New channel should be empty")
}
if channel.GetNumClients() != 0 {
t.Errorf("GetNumClients() = %v, want 0", channel.GetNumClients())
}
// Test joining channel
err := channel.JoinChannel(1001)
if err != nil {
t.Errorf("JoinChannel failed: %v", err)
}
if !channel.IsInChannel(1001) {
t.Error("IsInChannel should return true after joining")
}
if channel.IsEmpty() {
t.Error("Channel should not be empty after member joins")
}
if channel.GetNumClients() != 1 {
t.Errorf("GetNumClients() = %v, want 1", channel.GetNumClients())
}
// Test duplicate join
err = channel.JoinChannel(1001)
if err == nil {
t.Error("JoinChannel should fail for duplicate member")
}
// Test adding another member
err = channel.JoinChannel(1002)
if err != nil {
t.Errorf("JoinChannel failed: %v", err)
}
if channel.GetNumClients() != 2 {
t.Errorf("GetNumClients() = %v, want 2", channel.GetNumClients())
}
// Test getting members
members := channel.GetMembers()
if len(members) != 2 {
t.Errorf("GetMembers() returned %d members, want 2", len(members))
}
// Test leaving channel
err = channel.LeaveChannel(1001)
if err != nil {
t.Errorf("LeaveChannel failed: %v", err)
}
if channel.IsInChannel(1001) {
t.Error("IsInChannel should return false after leaving")
}
if channel.GetNumClients() != 1 {
t.Errorf("GetNumClients() = %v, want 1", channel.GetNumClients())
}
// Test leaving non-member
err = channel.LeaveChannel(9999)
if err == nil {
t.Error("LeaveChannel should fail for non-member")
}
}
func TestChannelRestrictions(t *testing.T) {
db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared")
defer db.Close()
channel := NewWithData(100, "Restricted", ChannelTypeWorld, db)
// Test level restrictions
channel.SetLevelRestriction(10)
if !channel.CanJoinChannelByLevel(10) {
t.Error("CanJoinChannelByLevel should return true for exact minimum")
}
if !channel.CanJoinChannelByLevel(15) {
t.Error("CanJoinChannelByLevel should return true for above minimum")
}
if channel.CanJoinChannelByLevel(5) {
t.Error("CanJoinChannelByLevel should return false for below minimum")
}
// Test race restrictions (bitmask)
channel.SetRacesAllowed(1 << 1) // Only race ID 1 allowed
if !channel.CanJoinChannelByRace(1) {
t.Error("CanJoinChannelByRace should return true for allowed race")
}
if channel.CanJoinChannelByRace(2) {
t.Error("CanJoinChannelByRace should return false for disallowed race")
}
// Test class restrictions (bitmask)
channel.SetClassesAllowed(1 << 5) // Only class ID 5 allowed
if !channel.CanJoinChannelByClass(5) {
t.Error("CanJoinChannelByClass should return true for allowed class")
}
if channel.CanJoinChannelByClass(1) {
t.Error("CanJoinChannelByClass should return false for disallowed class")
}
// Test ValidateJoin
err := channel.ValidateJoin(15, 1, 5, "")
if err != nil {
t.Errorf("ValidateJoin should succeed for valid player: %v", err)
}
err = channel.ValidateJoin(5, 1, 5, "")
if err == nil {
t.Error("ValidateJoin should fail for insufficient level")
}
err = channel.ValidateJoin(15, 2, 5, "")
if err == nil {
t.Error("ValidateJoin should fail for disallowed race")
}
err = channel.ValidateJoin(15, 1, 1, "")
if err == nil {
t.Error("ValidateJoin should fail for disallowed class")
}
// Test password validation
channel.SetPassword("secret")
err = channel.ValidateJoin(15, 1, 5, "secret")
if err != nil {
t.Errorf("ValidateJoin should succeed with correct password: %v", err)
}
err = channel.ValidateJoin(15, 1, 5, "wrong")
if err == nil {
t.Error("ValidateJoin should fail with incorrect password")
}
}
func TestChannelInfo(t *testing.T) {
db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared")
defer db.Close()
channel := NewWithData(100, "Info Test", ChannelTypeWorld, db)
channel.SetPassword("secret")
channel.SetLevelRestriction(10)
channel.JoinChannel(1001)
channel.JoinChannel(1002)
info := channel.GetChannelInfo()
if info.Name != "Info Test" {
t.Errorf("ChannelInfo.Name = %v, want Info Test", info.Name)
}
if !info.HasPassword {
t.Error("ChannelInfo.HasPassword should be true")
}
if info.MemberCount != 2 {
t.Errorf("ChannelInfo.MemberCount = %v, want 2", info.MemberCount)
}
if info.LevelRestriction != 10 {
t.Errorf("ChannelInfo.LevelRestriction = %v, want 10", info.LevelRestriction)
}
if info.ChannelType != ChannelTypeWorld {
t.Errorf("ChannelInfo.ChannelType = %v, want %d", info.ChannelType, ChannelTypeWorld)
}
}
func TestChannelCopy(t *testing.T) {
db, _ := database.NewSQLite("file::memory:?mode=memory&cache=shared")
defer db.Close()
original := NewWithData(500, "Original Channel", ChannelTypeWorld, db)
original.SetPassword("secret")
original.SetLevelRestriction(15)
original.JoinChannel(1001)
copy := original.Copy()
if copy == nil {
t.Fatal("Copy returned nil")
}
if copy == original {
t.Error("Copy returned same pointer as original")
}
if copy.GetID() != original.GetID() {
t.Errorf("Copy ID = %v, want %v", copy.GetID(), original.GetID())
}
if copy.GetName() != original.GetName() {
t.Errorf("Copy Name = %v, want %v", copy.GetName(), original.GetName())
}
if copy.Password != original.Password {
t.Errorf("Copy Password = %v, want %v", copy.Password, original.Password)
}
if !copy.IsNew() {
t.Error("Copy should always be marked as new")
}
// Verify modification independence
copy.SetName("Modified Copy")
if original.GetName() == "Modified Copy" {
t.Error("Modifying copy affected original")
}
}