Files
Erupe/server/channelserver/handlers_semaphore_test.go
Houmgaor d0837e779c refactor(channelserver): consolidate tests into matching source test files
Move ~300 test functions from 21 catch-all files (handlers_core_test.go,
handlers_coverage*_test.go, *_coverage_test.go) into the *_test.go file
matching each handler's source file. This makes tests discoverable by
convention: tests for handlers_guild.go live in handlers_guild_test.go.

New files: handlers_guild_mission_test.go, sys_time_test.go.
No test logic changed — pure file reorganization.
2026-02-26 23:41:44 +01:00

614 lines
16 KiB
Go

package channelserver
import (
"testing"
"erupe-ce/network/mhfpacket"
)
func TestHandleMsgSysCreateSemaphore(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgSysCreateSemaphore{
AckHandle: 12345,
Unk0: 0,
}
handleMsgSysCreateSemaphore(session, pkt)
// Verify response packet was queued
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("Response packet should have data")
}
default:
t.Error("No response packet queued")
}
}
func TestHandleMsgSysDeleteSemaphore_NoSemaphores(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgSysDeleteSemaphore{
SemaphoreID: 12345,
}
// Should not panic when no semaphores exist
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysDeleteSemaphore panicked: %v", r)
}
}()
handleMsgSysDeleteSemaphore(session, pkt)
}
func TestHandleMsgSysDeleteSemaphore_WithSemaphore(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
session := createMockSession(1, server)
// Create a semaphore
sema := NewSemaphore(session, "test_sema", 4)
server.semaphore["test_sema"] = sema
pkt := &mhfpacket.MsgSysDeleteSemaphore{
SemaphoreID: sema.id,
}
handleMsgSysDeleteSemaphore(session, pkt)
// Semaphore should be deleted
if _, exists := server.semaphore["test_sema"]; exists {
t.Error("Semaphore should be deleted")
}
}
func TestHandleMsgSysCreateAcquireSemaphore_NewSemaphore(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
session := createMockSession(1, server)
pkt := &mhfpacket.MsgSysCreateAcquireSemaphore{
AckHandle: 12345,
Unk0: 0,
PlayerCount: 4,
SemaphoreID: "test_semaphore",
}
handleMsgSysCreateAcquireSemaphore(session, pkt)
// Verify response packet was queued
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("Response packet should have data")
}
default:
t.Error("No response packet queued")
}
// Verify semaphore was created
if _, exists := server.semaphore["test_semaphore"]; !exists {
t.Error("Semaphore should be created")
}
}
func TestHandleMsgSysCreateAcquireSemaphore_ExistingSemaphore(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
session := createMockSession(1, server)
// Pre-create semaphore
sema := NewSemaphore(session, "existing_sema", 4)
server.semaphore["existing_sema"] = sema
pkt := &mhfpacket.MsgSysCreateAcquireSemaphore{
AckHandle: 12345,
Unk0: 0,
PlayerCount: 4,
SemaphoreID: "existing_sema",
}
handleMsgSysCreateAcquireSemaphore(session, pkt)
// Verify response packet was queued
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("Response packet should have data")
}
default:
t.Error("No response packet queued")
}
// Verify client was added to semaphore
if len(sema.clients) == 0 {
t.Error("Session should be added to semaphore")
}
}
func TestHandleMsgSysCreateAcquireSemaphore_RavienteSemaphore(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
session := createMockSession(1, server)
// Test raviente semaphore (special prefix)
pkt := &mhfpacket.MsgSysCreateAcquireSemaphore{
AckHandle: 12345,
Unk0: 0,
PlayerCount: 32,
SemaphoreID: "hs_l0u3B51", // Raviente prefix + suffix
}
handleMsgSysCreateAcquireSemaphore(session, pkt)
// Verify response packet was queued
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("Response packet should have data")
}
default:
t.Error("No response packet queued")
}
// Verify raviente semaphore was created with special settings
if sema, exists := server.semaphore["hs_l0u3B51"]; !exists {
t.Error("Raviente semaphore should be created")
} else if sema.maxPlayers != 127 {
t.Errorf("Raviente semaphore maxPlayers = %d, want 127", sema.maxPlayers)
}
}
func TestHandleMsgSysCreateAcquireSemaphore_Full(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
// Create semaphore with 1 player max
session1 := createMockSession(1, server)
sema := NewSemaphore(session1, "full_sema", 1)
server.semaphore["full_sema"] = sema
// Fill the semaphore
sema.clients[session1] = session1.charID
// Try to acquire with another session
session2 := createMockSession(2, server)
pkt := &mhfpacket.MsgSysCreateAcquireSemaphore{
AckHandle: 12345,
Unk0: 0,
PlayerCount: 1,
SemaphoreID: "full_sema",
}
handleMsgSysCreateAcquireSemaphore(session2, pkt)
// Should still respond (with failure indication)
select {
case p := <-session2.sendPackets:
if len(p.data) == 0 {
t.Error("Response packet should have data even for full semaphore")
}
default:
t.Error("No response packet queued")
}
}
func TestHandleMsgSysAcquireSemaphore_Exists(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
session := createMockSession(1, server)
// Create semaphore
sema := NewSemaphore(session, "acquire_test", 4)
server.semaphore["acquire_test"] = sema
pkt := &mhfpacket.MsgSysAcquireSemaphore{
AckHandle: 12345,
SemaphoreID: "acquire_test",
}
handleMsgSysAcquireSemaphore(session, pkt)
// Verify response packet was queued
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("Response packet should have data")
}
default:
t.Error("No response packet queued")
}
// Verify host was set
if sema.host != session {
t.Error("Session should be set as semaphore host")
}
}
func TestHandleMsgSysAcquireSemaphore_NotExists(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
session := createMockSession(1, server)
pkt := &mhfpacket.MsgSysAcquireSemaphore{
AckHandle: 12345,
SemaphoreID: "nonexistent",
}
handleMsgSysAcquireSemaphore(session, pkt)
// Should respond with failure
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("Response packet should have data")
}
default:
t.Error("No response packet queued")
}
}
func TestHandleMsgSysReleaseSemaphore(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (mostly empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysReleaseSemaphore panicked: %v", r)
}
}()
pkt := &mhfpacket.MsgSysReleaseSemaphore{}
handleMsgSysReleaseSemaphore(session, pkt)
}
func TestHandleMsgSysCheckSemaphore_Exists(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
session := createMockSession(1, server)
// Create semaphore
sema := NewSemaphore(session, "check_test", 4)
server.semaphore["check_test"] = sema
pkt := &mhfpacket.MsgSysCheckSemaphore{
AckHandle: 12345,
SemaphoreID: "check_test",
}
handleMsgSysCheckSemaphore(session, pkt)
// Verify response indicates semaphore exists
select {
case p := <-session.sendPackets:
if len(p.data) < 4 {
t.Error("Response packet should have at least 4 bytes")
}
default:
t.Error("No response packet queued")
}
}
func TestHandleMsgSysCheckSemaphore_NotExists(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
session := createMockSession(1, server)
pkt := &mhfpacket.MsgSysCheckSemaphore{
AckHandle: 12345,
SemaphoreID: "nonexistent",
}
handleMsgSysCheckSemaphore(session, pkt)
// Verify response indicates semaphore does not exist
select {
case p := <-session.sendPackets:
if len(p.data) < 4 {
t.Error("Response packet should have at least 4 bytes")
}
default:
t.Error("No response packet queued")
}
}
func TestRemoveSessionFromSemaphore(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
session := createMockSession(1, server)
// Create semaphore and add session
sema := NewSemaphore(session, "remove_test", 4)
sema.clients[session] = session.charID
server.semaphore["remove_test"] = sema
// Remove session
removeSessionFromSemaphore(session)
// Verify session was removed
if _, exists := sema.clients[session]; exists {
t.Error("Session should be removed from clients")
}
}
func TestRemoveSessionFromSemaphore_MultipleSemaphores(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
session := createMockSession(1, server)
// Create multiple semaphores with the session
for i := 0; i < 3; i++ {
sema := NewSemaphore(session, "multi_test_"+string(rune('a'+i)), 4)
sema.clients[session] = session.charID
server.semaphore["multi_test_"+string(rune('a'+i))] = sema
}
// Remove session from all
removeSessionFromSemaphore(session)
// Verify session was removed from all semaphores
for _, sema := range server.semaphore {
if _, exists := sema.clients[session]; exists {
t.Error("Session should be removed from all semaphore clients")
}
}
}
func TestDestructEmptySemaphores(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
session := createMockSession(1, server)
// Create empty semaphore
sema := NewSemaphore(session, "empty_sema", 4)
server.semaphore["empty_sema"] = sema
// Create non-empty semaphore
semaWithClients := NewSemaphore(session, "with_clients", 4)
semaWithClients.clients[session] = session.charID
server.semaphore["with_clients"] = semaWithClients
destructEmptySemaphores(session)
// Empty semaphore should be deleted
if _, exists := server.semaphore["empty_sema"]; exists {
t.Error("Empty semaphore should be deleted")
}
// Non-empty semaphore should remain
if _, exists := server.semaphore["with_clients"]; !exists {
t.Error("Non-empty semaphore should remain")
}
}
func TestSemaphoreHandlers_SequentialAcquire(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
// Sequentially try to create/acquire the same semaphore
// Note: the handler has race conditions when accessed concurrently
for i := 0; i < 5; i++ {
session := createMockSession(uint32(i), server)
pkt := &mhfpacket.MsgSysCreateAcquireSemaphore{
AckHandle: uint32(i),
Unk0: 0,
PlayerCount: 4,
SemaphoreID: "sequential_test",
}
handleMsgSysCreateAcquireSemaphore(session, pkt)
// Drain send queue
select {
case <-session.sendPackets:
default:
}
}
// Semaphore should exist
if _, exists := server.semaphore["sequential_test"]; !exists {
t.Error("Semaphore should exist after sequential acquires")
}
}
// Tests consolidated from handlers_coverage3_test.go
func TestSimpleAckHandlers_SemaphoreGo(t *testing.T) {
server := createMockServer()
t.Run("handleMsgSysCreateSemaphore", func(t *testing.T) {
session := createMockSession(1, server)
handleMsgSysCreateSemaphore(session, &mhfpacket.MsgSysCreateSemaphore{AckHandle: 1})
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("handleMsgSysCreateSemaphore: response should have data")
}
default:
t.Error("handleMsgSysCreateSemaphore: no response queued")
}
})
}
func TestHandleMsgSysCreateAcquireSemaphore_Coverage3(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
t.Run("creates_new_semaphore", func(t *testing.T) {
session := createMockSession(1, server)
handleMsgSysCreateAcquireSemaphore(session, &mhfpacket.MsgSysCreateAcquireSemaphore{
AckHandle: 1,
SemaphoreID: "test_sema_c3_1",
})
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("response should have data")
}
default:
t.Error("no response queued")
}
if _, exists := server.semaphore["test_sema_c3_1"]; !exists {
t.Error("semaphore should have been created in server map")
}
})
t.Run("acquires_existing_semaphore", func(t *testing.T) {
session := createMockSession(2, server)
handleMsgSysCreateAcquireSemaphore(session, &mhfpacket.MsgSysCreateAcquireSemaphore{
AckHandle: 2,
SemaphoreID: "test_sema_c3_1",
})
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("response should have data")
}
default:
t.Error("no response queued")
}
})
t.Run("creates_ravi_semaphore", func(t *testing.T) {
session := createMockSession(3, server)
handleMsgSysCreateAcquireSemaphore(session, &mhfpacket.MsgSysCreateAcquireSemaphore{
AckHandle: 3,
SemaphoreID: "hs_l0u3B51_c3",
})
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("response should have data")
}
default:
t.Error("no response queued")
}
if _, exists := server.semaphore["hs_l0u3B51_c3"]; !exists {
t.Error("ravi semaphore should have been created")
}
})
}
func TestHandleMsgSysCheckSemaphore_Coverage3(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
t.Run("semaphore_not_exists", func(t *testing.T) {
session := createMockSession(1, server)
handleMsgSysCheckSemaphore(session, &mhfpacket.MsgSysCheckSemaphore{
AckHandle: 1,
SemaphoreID: "nonexistent_c3",
})
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("response should have data")
}
default:
t.Error("no response queued")
}
})
t.Run("semaphore_exists", func(t *testing.T) {
session := createMockSession(1, server)
server.semaphore["existing_sema_c3"] = NewSemaphore(session, "existing_sema_c3", 1)
handleMsgSysCheckSemaphore(session, &mhfpacket.MsgSysCheckSemaphore{
AckHandle: 1,
SemaphoreID: "existing_sema_c3",
})
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("response should have data")
}
default:
t.Error("no response queued")
}
})
}
func TestHandleMsgSysAcquireSemaphore_Coverage3(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
t.Run("semaphore_exists", func(t *testing.T) {
session := createMockSession(1, server)
server.semaphore["acquire_sema_c3"] = NewSemaphore(session, "acquire_sema_c3", 1)
handleMsgSysAcquireSemaphore(session, &mhfpacket.MsgSysAcquireSemaphore{
AckHandle: 1,
SemaphoreID: "acquire_sema_c3",
})
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("response should have data")
}
default:
t.Error("no response queued")
}
})
t.Run("semaphore_not_exists", func(t *testing.T) {
session := createMockSession(1, server)
handleMsgSysAcquireSemaphore(session, &mhfpacket.MsgSysAcquireSemaphore{
AckHandle: 1,
SemaphoreID: "nonexistent_sema_c3",
})
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("response should have data")
}
default:
t.Error("no response queued")
}
})
}
func TestEmptyHandlers_MiscFiles_Semaphore(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysReleaseSemaphore panicked: %v", r)
}
}()
handleMsgSysReleaseSemaphore(session, nil)
}
func TestSemaphoreHandlers_MultipleCheck(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
// Create semaphore
helperSession := createMockSession(99, server)
sema := NewSemaphore(helperSession, "check_multiple", 4)
server.semaphore["check_multiple"] = sema
// Check the semaphore from multiple sessions sequentially
for i := 0; i < 5; i++ {
session := createMockSession(uint32(i), server)
pkt := &mhfpacket.MsgSysCheckSemaphore{
AckHandle: uint32(i),
SemaphoreID: "check_multiple",
}
handleMsgSysCheckSemaphore(session, pkt)
// Drain send queue
select {
case <-session.sendPackets:
default:
}
}
}