test: expand channelserver coverage from 12% to 16%

Add comprehensive tests for handler files:
- handlers_object: object creation, positioning, binary ops
- handlers_semaphore: create, acquire, release, check, delete
- handlers_reserve: stub handlers and reserve188/18B
- handlers_event: registration, release, feature weapons
- handlers_mutex: create, open, close, delete operations
- handlers_campaign: enumerate, state, apply
- handlers_bbs: user status, SNS status, article apply
- handlers_tournament: info, entry, acquire
- handlers_users: user binary operations
- handlers_clients: client enumeration
- handlers_rengoku: ranking
- handlers_register: raviente semaphore functions
- handlers_tower: tower info, tenrouirai, seibatu ranking

All tests pass with race detection enabled.
This commit is contained in:
Houmgaor
2026-02-02 11:42:47 +01:00
parent 0f1684564d
commit 711916f4a1
13 changed files with 2114 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
package channelserver
import (
"testing"
"erupe-ce/config"
"erupe-ce/network/mhfpacket"
)
func TestHandleMsgMhfGetBbsUserStatus(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetBbsUserStatus{
AckHandle: 12345,
}
handleMsgMhfGetBbsUserStatus(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 TestHandleMsgMhfGetBbsSnsStatus(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetBbsSnsStatus{
AckHandle: 12345,
}
handleMsgMhfGetBbsSnsStatus(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 TestHandleMsgMhfApplyBbsArticle(t *testing.T) {
server := createMockServer()
server.erupeConfig = &config.Config{
ScreenshotAPIURL: "http://example.com/api",
}
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfApplyBbsArticle{
AckHandle: 12345,
}
handleMsgMhfApplyBbsArticle(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")
}
}

View File

@@ -0,0 +1,70 @@
package channelserver
import (
"testing"
"erupe-ce/network/mhfpacket"
)
func TestHandleMsgMhfEnumerateCampaign(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfEnumerateCampaign{
AckHandle: 12345,
}
handleMsgMhfEnumerateCampaign(session, pkt)
// Verify response packet was queued (fail response expected)
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 TestHandleMsgMhfStateCampaign(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfStateCampaign{
AckHandle: 12345,
}
handleMsgMhfStateCampaign(session, pkt)
// Verify response packet was queued (fail response expected)
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 TestHandleMsgMhfApplyCampaign(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfApplyCampaign{
AckHandle: 12345,
}
handleMsgMhfApplyCampaign(session, pkt)
// Verify response packet was queued (fail response expected)
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("Response packet should have data")
}
default:
t.Error("No response packet queued")
}
}

View File

@@ -0,0 +1,150 @@
package channelserver
import (
"testing"
"erupe-ce/network/mhfpacket"
)
func TestHandleMsgSysEnumerateClient_StageNotExists(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgSysEnumerateClient{
AckHandle: 12345,
StageID: "nonexistent_stage",
Get: 0,
}
handleMsgSysEnumerateClient(session, pkt)
// Verify response packet was queued (failure expected)
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 TestHandleMsgSysEnumerateClient_AllClients(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Create stage with clients
stage := NewStage("test_stage")
server.stages["test_stage"] = stage
client1 := createMockSession(100, server)
client2 := createMockSession(200, server)
stage.clients[client1] = client1.charID
stage.clients[client2] = client2.charID
pkt := &mhfpacket.MsgSysEnumerateClient{
AckHandle: 12345,
StageID: "test_stage",
Get: 0, // All clients
}
handleMsgSysEnumerateClient(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 TestHandleMsgSysEnumerateClient_NotReady(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Create stage with reserved slots
stage := NewStage("test_stage")
server.stages["test_stage"] = stage
stage.reservedClientSlots[100] = false // Not ready
stage.reservedClientSlots[200] = true // Ready
pkt := &mhfpacket.MsgSysEnumerateClient{
AckHandle: 12345,
StageID: "test_stage",
Get: 1, // Not ready
}
handleMsgSysEnumerateClient(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 TestHandleMsgSysEnumerateClient_Ready(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Create stage with reserved slots
stage := NewStage("test_stage")
server.stages["test_stage"] = stage
stage.reservedClientSlots[100] = false // Not ready
stage.reservedClientSlots[200] = true // Ready
pkt := &mhfpacket.MsgSysEnumerateClient{
AckHandle: 12345,
StageID: "test_stage",
Get: 2, // Ready
}
handleMsgSysEnumerateClient(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 TestHandleMsgMhfShutClient(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgMhfShutClient panicked: %v", r)
}
}()
handleMsgMhfShutClient(session, nil)
}
func TestHandleMsgSysHideClient(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysHideClient panicked: %v", r)
}
}()
handleMsgSysHideClient(session, nil)
}

View File

@@ -0,0 +1,161 @@
package channelserver
import (
"testing"
"erupe-ce/network/mhfpacket"
)
func TestHandleMsgMhfRegisterEvent(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfRegisterEvent{
AckHandle: 12345,
Unk2: 1,
Unk4: 2,
}
handleMsgMhfRegisterEvent(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 TestHandleMsgMhfReleaseEvent(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfReleaseEvent{
AckHandle: 12345,
}
handleMsgMhfReleaseEvent(session, pkt)
// Verify response packet was queued (with special error code 0x41)
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 TestHandleMsgMhfEnumerateEvent(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfEnumerateEvent{
AckHandle: 12345,
}
handleMsgMhfEnumerateEvent(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 TestHandleMsgMhfGetRestrictionEvent(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgMhfGetRestrictionEvent panicked: %v", r)
}
}()
handleMsgMhfGetRestrictionEvent(session, nil)
}
func TestHandleMsgMhfSetRestrictionEvent(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfSetRestrictionEvent{
AckHandle: 12345,
}
handleMsgMhfSetRestrictionEvent(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 TestGenerateFeatureWeapons(t *testing.T) {
tests := []struct {
name string
count int
}{
{"single weapon", 1},
{"few weapons", 3},
{"normal count", 7},
{"max weapons", 14},
{"over max", 20}, // Should cap at 14
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := generateFeatureWeapons(tt.count)
// Result should be non-zero for positive counts
if tt.count > 0 && result.ActiveFeatures == 0 {
t.Error("Expected non-zero ActiveFeatures")
}
// Should not exceed max value (2^14 - 1 = 16383)
if result.ActiveFeatures > 16383 {
t.Errorf("ActiveFeatures = %d, exceeds max of 16383", result.ActiveFeatures)
}
})
}
}
func TestGenerateFeatureWeapons_Randomness(t *testing.T) {
// Generate multiple times and verify some variation
results := make(map[uint32]int)
iterations := 100
for i := 0; i < iterations; i++ {
result := generateFeatureWeapons(5)
results[result.ActiveFeatures]++
}
// Should have some variation (not all the same)
if len(results) == 1 {
t.Error("Expected some variation in generated weapons")
}
}
func TestGenerateFeatureWeapons_ZeroCount(t *testing.T) {
result := generateFeatureWeapons(0)
// Should return 0 for no weapons
if result.ActiveFeatures != 0 {
t.Errorf("Expected 0 for zero count, got %d", result.ActiveFeatures)
}
}

View File

@@ -0,0 +1,77 @@
package channelserver
import (
"testing"
)
// Test that all mutex handlers don't panic (they are empty implementations)
func TestHandleMsgSysCreateMutex(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysCreateMutex panicked: %v", r)
}
}()
handleMsgSysCreateMutex(session, nil)
}
func TestHandleMsgSysCreateOpenMutex(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysCreateOpenMutex panicked: %v", r)
}
}()
handleMsgSysCreateOpenMutex(session, nil)
}
func TestHandleMsgSysDeleteMutex(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysDeleteMutex panicked: %v", r)
}
}()
handleMsgSysDeleteMutex(session, nil)
}
func TestHandleMsgSysOpenMutex(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysOpenMutex panicked: %v", r)
}
}()
handleMsgSysOpenMutex(session, nil)
}
func TestHandleMsgSysCloseMutex(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysCloseMutex panicked: %v", r)
}
}()
handleMsgSysCloseMutex(session, nil)
}

View File

@@ -0,0 +1,393 @@
package channelserver
import (
"testing"
"erupe-ce/network/mhfpacket"
)
func TestHandleMsgSysCreateObject(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Create a stage for the session
stage := NewStage("test_stage")
session.stage = stage
pkt := &mhfpacket.MsgSysCreateObject{
AckHandle: 12345,
X: 100.0,
Y: 50.0,
Z: -25.0,
Unk0: 0,
}
handleMsgSysCreateObject(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 object was created in stage
if len(stage.objects) != 1 {
t.Errorf("Stage should have 1 object, got %d", len(stage.objects))
}
}
func TestHandleMsgSysCreateObject_MultipleObjects(t *testing.T) {
server := createMockServer()
// Create multiple sessions that create objects
sessions := make([]*Session, 3)
stage := NewStage("test_stage")
for i := 0; i < 3; i++ {
sessions[i] = createMockSession(uint32(i+1), server)
sessions[i].stage = stage
pkt := &mhfpacket.MsgSysCreateObject{
AckHandle: uint32(12345 + i),
X: float32(i * 10),
Y: float32(i * 20),
Z: float32(i * 30),
}
handleMsgSysCreateObject(sessions[i], pkt)
// Drain send queue
select {
case <-sessions[i].sendPackets:
default:
}
}
// All objects should exist
if len(stage.objects) != 3 {
t.Errorf("Stage should have 3 objects, got %d", len(stage.objects))
}
}
func TestHandleMsgSysPositionObject(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Create a stage with an existing object
stage := NewStage("test_stage")
session.stage = stage
// Add another session to receive broadcast
session2 := createMockSession(2, server)
session2.stage = stage
stage.clients[session] = session.charID
stage.clients[session2] = session2.charID
// Create an object
stage.objects[session.charID] = &Object{
id: 1,
ownerCharID: session.charID,
x: 0,
y: 0,
z: 0,
}
pkt := &mhfpacket.MsgSysPositionObject{
ObjID: 1,
X: 100.0,
Y: 200.0,
Z: 300.0,
}
handleMsgSysPositionObject(session, pkt)
// Verify object position was updated
obj := stage.objects[session.charID]
if obj.x != 100.0 || obj.y != 200.0 || obj.z != 300.0 {
t.Errorf("Object position not updated: got (%f, %f, %f), want (100, 200, 300)",
obj.x, obj.y, obj.z)
}
// Verify broadcast was sent to session2
select {
case <-session2.sendPackets:
// Good - broadcast received
default:
t.Error("Position update should be broadcast to other sessions")
}
}
func TestHandleMsgSysPositionObject_NoObject(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
stage := NewStage("test_stage")
session.stage = stage
stage.clients[session] = session.charID
// Position update for non-existent object - should not panic
pkt := &mhfpacket.MsgSysPositionObject{
ObjID: 999,
X: 100.0,
Y: 200.0,
Z: 300.0,
}
// Should not panic
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysPositionObject panicked with non-existent object: %v", r)
}
}()
handleMsgSysPositionObject(session, pkt)
}
func TestHandleMsgSysDeleteObject(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysDeleteObject panicked: %v", r)
}
}()
handleMsgSysDeleteObject(session, nil)
}
func TestHandleMsgSysRotateObject(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysRotateObject panicked: %v", r)
}
}()
handleMsgSysRotateObject(session, nil)
}
func TestHandleMsgSysDuplicateObject(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysDuplicateObject panicked: %v", r)
}
}()
handleMsgSysDuplicateObject(session, nil)
}
func TestHandleMsgSysSetObjectBinary(t *testing.T) {
server := createMockServer()
server.userBinaryParts = make(map[userBinaryPartID][]byte)
session := createMockSession(1, server)
server.sessions[nil] = session // Add session to server
pkt := &mhfpacket.MsgSysSetObjectBinary{
RawDataPayload: []byte{0x01, 0x02, 0x03, 0x04},
}
handleMsgSysSetObjectBinary(session, pkt)
// Verify binary was stored
key := userBinaryPartID{charID: session.charID, index: 3}
if data, ok := server.userBinaryParts[key]; !ok {
t.Error("Object binary should be stored")
} else if len(data) != 4 {
t.Errorf("Object binary length = %d, want 4", len(data))
}
}
func TestHandleMsgSysGetObjectBinary(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysGetObjectBinary panicked: %v", r)
}
}()
handleMsgSysGetObjectBinary(session, nil)
}
func TestHandleMsgSysGetObjectOwner(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysGetObjectOwner panicked: %v", r)
}
}()
handleMsgSysGetObjectOwner(session, nil)
}
func TestHandleMsgSysUpdateObjectBinary(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysUpdateObjectBinary panicked: %v", r)
}
}()
handleMsgSysUpdateObjectBinary(session, nil)
}
func TestHandleMsgSysCleanupObject(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysCleanupObject panicked: %v", r)
}
}()
handleMsgSysCleanupObject(session, nil)
}
func TestHandleMsgSysAddObject(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysAddObject panicked: %v", r)
}
}()
handleMsgSysAddObject(session, nil)
}
func TestHandleMsgSysDelObject(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysDelObject panicked: %v", r)
}
}()
handleMsgSysDelObject(session, nil)
}
func TestHandleMsgSysDispObject(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysDispObject panicked: %v", r)
}
}()
handleMsgSysDispObject(session, nil)
}
func TestHandleMsgSysHideObject(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysHideObject panicked: %v", r)
}
}()
handleMsgSysHideObject(session, nil)
}
func TestObjectHandlers_SequentialCreateObject(t *testing.T) {
server := createMockServer()
stage := NewStage("test_stage")
// Create objects sequentially from multiple sessions
// Note: handleMsgSysCreateObject has a race condition in NextObjectID
// so we test sequential creation instead
for i := 0; i < 10; i++ {
session := createMockSession(uint32(i), server)
session.stage = stage
pkt := &mhfpacket.MsgSysCreateObject{
AckHandle: uint32(i),
X: float32(i),
Y: float32(i * 2),
Z: float32(i * 3),
}
handleMsgSysCreateObject(session, pkt)
// Drain send queue
select {
case <-session.sendPackets:
default:
}
}
// All objects should be created
if len(stage.objects) != 10 {
t.Errorf("Expected 10 objects, got %d", len(stage.objects))
}
}
func TestObjectHandlers_SequentialPositionUpdate(t *testing.T) {
server := createMockServer()
stage := NewStage("test_stage")
session := createMockSession(1, server)
session.stage = stage
stage.clients[session] = session.charID
// Create an object
stage.objects[session.charID] = &Object{
id: 1,
ownerCharID: session.charID,
x: 0,
y: 0,
z: 0,
}
// Sequentially update object position
for i := 0; i < 10; i++ {
pkt := &mhfpacket.MsgSysPositionObject{
ObjID: 1,
X: float32(i),
Y: float32(i * 2),
Z: float32(i * 3),
}
handleMsgSysPositionObject(session, pkt)
}
// Verify final position
obj := stage.objects[session.charID]
if obj.x != 9 || obj.y != 18 || obj.z != 27 {
t.Errorf("Object position not as expected: got (%f, %f, %f), want (9, 18, 27)",
obj.x, obj.y, obj.z)
}
}

View File

@@ -0,0 +1,63 @@
package channelserver
import (
"testing"
)
func TestHandleMsgSysNotifyRegister(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysNotifyRegister panicked: %v", r)
}
}()
handleMsgSysNotifyRegister(session, nil)
}
func TestGetRaviSemaphore_None(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
result := getRaviSemaphore(server)
if result != nil {
t.Error("Expected nil when no raviente semaphore exists")
}
}
func TestGetRaviSemaphore_Found(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
// Create a raviente semaphore (matches prefix hs_l0u3B5 and suffix 3)
sema := NewSemaphore(server, "hs_l0u3B53", 32)
server.semaphore["hs_l0u3B53"] = sema
result := getRaviSemaphore(server)
if result == nil {
t.Error("Expected to find raviente semaphore")
}
if result.id_semaphore != "hs_l0u3B53" {
t.Errorf("Wrong semaphore returned: %s", result.id_semaphore)
}
}
func TestGetRaviSemaphore_WrongSuffix(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
// Create a semaphore with wrong suffix
sema := NewSemaphore(server, "hs_l0u3B51", 32)
server.semaphore["hs_l0u3B51"] = sema
result := getRaviSemaphore(server)
if result != nil {
t.Error("Should not match semaphore with wrong suffix")
}
}

View File

@@ -0,0 +1,28 @@
package channelserver
import (
"testing"
"erupe-ce/network/mhfpacket"
)
func TestHandleMsgMhfGetRengokuRankingRank(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetRengokuRankingRank{
AckHandle: 12345,
}
handleMsgMhfGetRengokuRankingRank(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")
}
}

View File

@@ -0,0 +1,138 @@
package channelserver
import (
"testing"
"erupe-ce/network/mhfpacket"
)
// Test that reserve handlers with AckHandle respond correctly
func TestHandleMsgSysReserve188(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgSysReserve188{
AckHandle: 12345,
}
handleMsgSysReserve188(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 TestHandleMsgSysReserve18B(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgSysReserve18B{
AckHandle: 12345,
}
handleMsgSysReserve18B(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")
}
}
// Test that empty reserve handlers don't panic
func TestEmptyReserveHandlers(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
tests := []struct {
name string
handler func(s *Session, p mhfpacket.MHFPacket)
}{
{"handleMsgSysReserve55", handleMsgSysReserve55},
{"handleMsgSysReserve56", handleMsgSysReserve56},
{"handleMsgSysReserve57", handleMsgSysReserve57},
{"handleMsgSysReserve01", handleMsgSysReserve01},
{"handleMsgSysReserve02", handleMsgSysReserve02},
{"handleMsgSysReserve03", handleMsgSysReserve03},
{"handleMsgSysReserve04", handleMsgSysReserve04},
{"handleMsgSysReserve05", handleMsgSysReserve05},
{"handleMsgSysReserve06", handleMsgSysReserve06},
{"handleMsgSysReserve07", handleMsgSysReserve07},
{"handleMsgSysReserve0C", handleMsgSysReserve0C},
{"handleMsgSysReserve0D", handleMsgSysReserve0D},
{"handleMsgSysReserve0E", handleMsgSysReserve0E},
{"handleMsgSysReserve4A", handleMsgSysReserve4A},
{"handleMsgSysReserve4B", handleMsgSysReserve4B},
{"handleMsgSysReserve4C", handleMsgSysReserve4C},
{"handleMsgSysReserve4D", handleMsgSysReserve4D},
{"handleMsgSysReserve4E", handleMsgSysReserve4E},
{"handleMsgSysReserve4F", handleMsgSysReserve4F},
{"handleMsgSysReserve5C", handleMsgSysReserve5C},
{"handleMsgSysReserve5E", handleMsgSysReserve5E},
{"handleMsgSysReserve5F", handleMsgSysReserve5F},
{"handleMsgSysReserve71", handleMsgSysReserve71},
{"handleMsgSysReserve72", handleMsgSysReserve72},
{"handleMsgSysReserve73", handleMsgSysReserve73},
{"handleMsgSysReserve74", handleMsgSysReserve74},
{"handleMsgSysReserve75", handleMsgSysReserve75},
{"handleMsgSysReserve76", handleMsgSysReserve76},
{"handleMsgSysReserve77", handleMsgSysReserve77},
{"handleMsgSysReserve78", handleMsgSysReserve78},
{"handleMsgSysReserve79", handleMsgSysReserve79},
{"handleMsgSysReserve7A", handleMsgSysReserve7A},
{"handleMsgSysReserve7B", handleMsgSysReserve7B},
{"handleMsgSysReserve7C", handleMsgSysReserve7C},
{"handleMsgSysReserve7E", handleMsgSysReserve7E},
{"handleMsgMhfReserve10F", handleMsgMhfReserve10F},
{"handleMsgSysReserve180", handleMsgSysReserve180},
{"handleMsgSysReserve18E", handleMsgSysReserve18E},
{"handleMsgSysReserve18F", handleMsgSysReserve18F},
{"handleMsgSysReserve19E", handleMsgSysReserve19E},
{"handleMsgSysReserve19F", handleMsgSysReserve19F},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer func() {
if r := recover(); r != nil {
t.Errorf("%s panicked: %v", tt.name, r)
}
}()
// Call with nil packet - empty handlers should handle this
tt.handler(session, nil)
})
}
}
// Test reserve handlers are registered in handler table
func TestReserveHandlersRegistered(t *testing.T) {
if handlerTable == nil {
t.Fatal("handlerTable should be initialized")
}
// Check that reserve handlers exist in the table
reserveHandlerCount := 0
for _, handler := range handlerTable {
if handler != nil {
reserveHandlerCount++
}
}
if reserveHandlerCount < 50 {
t.Errorf("Expected at least 50 handlers registered, got %d", reserveHandlerCount)
}
}

View File

@@ -0,0 +1,457 @@
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,
DataSize: 0,
RawDataPayload: []byte{},
}
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{
AckHandle: 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(server, "test_sema", 4)
server.semaphore["test_sema"] = sema
pkt := &mhfpacket.MsgSysDeleteSemaphore{
AckHandle: 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(server, "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.reservedClientSlots) == 0 && 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 != 32 {
t.Errorf("Raviente semaphore maxPlayers = %d, want 32", sema.maxPlayers)
}
}
func TestHandleMsgSysCreateAcquireSemaphore_Full(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
// Create semaphore with 1 player max
sema := NewSemaphore(server, "full_sema", 1)
server.semaphore["full_sema"] = sema
// Fill the semaphore
session1 := createMockSession(1, server)
sema.reservedClientSlots[session1.charID] = nil
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(server, "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 client was added
if _, exists := sema.clients[session]; !exists {
t.Error("Session should be added to semaphore clients")
}
}
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(server, "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(server, "remove_test", 4)
sema.clients[session] = session.charID
sema.reservedClientSlots[session.charID] = nil
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")
}
if _, exists := sema.reservedClientSlots[session.charID]; exists {
t.Error("Session should be removed from reserved slots")
}
}
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(server, "multi_test_"+string(rune('a'+i)), 4)
sema.clients[session] = session.charID
sema.reservedClientSlots[session.charID] = nil
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")
}
if _, exists := sema.reservedClientSlots[session.charID]; exists {
t.Error("Session should be removed from all reserved slots")
}
}
}
func TestDestructEmptySemaphores(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
session := createMockSession(1, server)
// Create empty semaphore
sema := NewSemaphore(server, "empty_sema", 4)
server.semaphore["empty_sema"] = sema
// Create non-empty semaphore
semaWithClients := NewSemaphore(server, "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")
}
}
func TestSemaphoreHandlers_MultipleCheck(t *testing.T) {
server := createMockServer()
server.semaphore = make(map[string]*Semaphore)
// Create semaphore
sema := NewSemaphore(server, "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:
}
}
}

View File

@@ -0,0 +1,79 @@
package channelserver
import (
"testing"
"erupe-ce/network/mhfpacket"
)
func TestHandleMsgMhfInfoTournament_Type0(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfInfoTournament{
AckHandle: 12345,
Unk0: 0,
}
handleMsgMhfInfoTournament(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 TestHandleMsgMhfInfoTournament_Type1(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfInfoTournament{
AckHandle: 12345,
Unk0: 1,
}
handleMsgMhfInfoTournament(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 TestHandleMsgMhfEntryTournament(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgMhfEntryTournament panicked: %v", r)
}
}()
handleMsgMhfEntryTournament(session, nil)
}
func TestHandleMsgMhfAcquireTournament(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgMhfAcquireTournament panicked: %v", r)
}
}()
handleMsgMhfAcquireTournament(session, nil)
}

View File

@@ -0,0 +1,296 @@
package channelserver
import (
"testing"
"erupe-ce/network/mhfpacket"
)
func TestHandleMsgMhfGetTowerInfo_TowerRankPoint(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetTowerInfo{
AckHandle: 12345,
InfoType: mhfpacket.TowerInfoTypeTowerRankPoint,
}
handleMsgMhfGetTowerInfo(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 TestHandleMsgMhfGetTowerInfo_GetOwnTowerSkill(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetTowerInfo{
AckHandle: 12345,
InfoType: mhfpacket.TowerInfoTypeGetOwnTowerSkill,
}
handleMsgMhfGetTowerInfo(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 TestHandleMsgMhfGetTowerInfo_TowerTouhaHistory(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetTowerInfo{
AckHandle: 12345,
InfoType: mhfpacket.TowerInfoTypeTowerTouhaHistory,
}
handleMsgMhfGetTowerInfo(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 TestHandleMsgMhfGetTowerInfo_Unk5(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetTowerInfo{
AckHandle: 12345,
InfoType: mhfpacket.TowerInfoTypeUnk5,
}
handleMsgMhfGetTowerInfo(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 TestHandleMsgMhfPostTowerInfo(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfPostTowerInfo{
AckHandle: 12345,
}
handleMsgMhfPostTowerInfo(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 TestHandleMsgMhfGetTenrouirai_Type1(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetTenrouirai{
AckHandle: 12345,
Unk0: 1,
}
handleMsgMhfGetTenrouirai(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 TestHandleMsgMhfGetTenrouirai_Type4(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetTenrouirai{
AckHandle: 12345,
Unk0: 0,
Unk2: 4,
}
handleMsgMhfGetTenrouirai(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 TestHandleMsgMhfGetTenrouirai_Default(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetTenrouirai{
AckHandle: 12345,
Unk0: 0,
Unk2: 0,
}
handleMsgMhfGetTenrouirai(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 TestHandleMsgMhfPostTenrouirai(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfPostTenrouirai{
AckHandle: 12345,
}
handleMsgMhfPostTenrouirai(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 TestHandleMsgMhfGetBreakSeibatuLevelReward(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgMhfGetBreakSeibatuLevelReward panicked: %v", r)
}
}()
handleMsgMhfGetBreakSeibatuLevelReward(session, nil)
}
func TestHandleMsgMhfGetWeeklySeibatuRankingReward(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetWeeklySeibatuRankingReward{
AckHandle: 12345,
}
handleMsgMhfGetWeeklySeibatuRankingReward(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 TestHandleMsgMhfPresentBox(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfPresentBox{
AckHandle: 12345,
}
handleMsgMhfPresentBox(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 TestHandleMsgMhfGetGemInfo(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetGemInfo{
AckHandle: 12345,
}
handleMsgMhfGetGemInfo(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 TestHandleMsgMhfPostGemInfo(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgMhfPostGemInfo panicked: %v", r)
}
}()
handleMsgMhfPostGemInfo(session, nil)
}

View File

@@ -0,0 +1,128 @@
package channelserver
import (
"testing"
"erupe-ce/network/mhfpacket"
)
func TestHandleMsgSysInsertUser(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysInsertUser panicked: %v", r)
}
}()
handleMsgSysInsertUser(session, nil)
}
func TestHandleMsgSysDeleteUser(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysDeleteUser panicked: %v", r)
}
}()
handleMsgSysDeleteUser(session, nil)
}
func TestHandleMsgSysNotifyUserBinary(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgSysNotifyUserBinary panicked: %v", r)
}
}()
handleMsgSysNotifyUserBinary(session, nil)
}
func TestHandleMsgSysGetUserBinary_FromCache(t *testing.T) {
server := createMockServer()
server.userBinaryParts = make(map[userBinaryPartID][]byte)
session := createMockSession(1, server)
// Pre-populate cache
key := userBinaryPartID{charID: 100, index: 1}
server.userBinaryParts[key] = []byte{0x01, 0x02, 0x03, 0x04}
pkt := &mhfpacket.MsgSysGetUserBinary{
AckHandle: 12345,
CharID: 100,
BinaryType: 1,
}
handleMsgSysGetUserBinary(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 TestHandleMsgSysGetUserBinary_NotInCache(t *testing.T) {
server := createMockServer()
server.userBinaryParts = make(map[userBinaryPartID][]byte)
session := createMockSession(1, server)
// Don't populate cache - will fall back to DB (which is nil in test)
pkt := &mhfpacket.MsgSysGetUserBinary{
AckHandle: 12345,
CharID: 100,
BinaryType: 1,
}
// This will panic when trying to access nil db, which is expected
// in the test environment without database setup
defer func() {
if r := recover(); r != nil {
// Expected - no database in test
t.Log("Expected panic due to nil database in test")
}
}()
handleMsgSysGetUserBinary(session, pkt)
}
func TestUserBinaryPartID_AsMapKey(t *testing.T) {
// Test that userBinaryPartID works as map key
parts := make(map[userBinaryPartID][]byte)
key1 := userBinaryPartID{charID: 1, index: 0}
key2 := userBinaryPartID{charID: 1, index: 1}
key3 := userBinaryPartID{charID: 2, index: 0}
parts[key1] = []byte{0x01}
parts[key2] = []byte{0x02}
parts[key3] = []byte{0x03}
if len(parts) != 3 {
t.Errorf("Expected 3 parts, got %d", len(parts))
}
if parts[key1][0] != 0x01 {
t.Error("Key1 data mismatch")
}
if parts[key2][0] != 0x02 {
t.Error("Key2 data mismatch")
}
if parts[key3][0] != 0x03 {
t.Error("Key3 data mismatch")
}
}