Files
Erupe/server/channelserver/handlers_simple_test.go
Houmgaor 81b2b85a8b test: increase total coverage from 31.3% to 40.7%
Add batch Parse/Build tests for ~150 mhfpacket types, net.Pipe-based
round-trip tests for CryptConn Send/ReadPacket, overflow panic tests
for all byteframe Read types, and additional empty handler coverage.
2026-02-08 14:30:02 +01:00

318 lines
7.9 KiB
Go

package channelserver
import (
"testing"
"time"
"erupe-ce/network/mhfpacket"
)
// Test simple handler patterns that don't require database
func TestHandlerMsgMhfSexChanger(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfSexChanger{
AckHandle: 12345,
}
// Should not panic
handleMsgMhfSexChanger(session, pkt)
// Should queue a response
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 TestHandlerMsgMhfEnterTournamentQuest(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Should not panic with nil packet (empty handler)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgMhfEnterTournamentQuest panicked: %v", r)
}
}()
handleMsgMhfEnterTournamentQuest(session, nil)
}
func TestHandlerMsgMhfGetUdBonusQuestInfo(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetUdBonusQuestInfo{
AckHandle: 12345,
}
handleMsgMhfGetUdBonusQuestInfo(session, pkt)
// Should queue a response
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 acknowledge handlers work correctly
func TestAckResponseFormats(t *testing.T) {
server := createMockServer()
tests := []struct {
name string
handler func(s *Session, ackHandle uint32, data []byte)
}{
{"doAckBufSucceed", doAckBufSucceed},
{"doAckBufFail", doAckBufFail},
{"doAckSimpleSucceed", doAckSimpleSucceed},
{"doAckSimpleFail", doAckSimpleFail},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
session := createMockSession(1, server)
testData := []byte{0x01, 0x02, 0x03, 0x04}
tt.handler(session, 99999, testData)
select {
case pkt := <-session.sendPackets:
if pkt.data == nil {
t.Error("Packet data should not be nil")
}
default:
t.Error("Handler should queue a packet")
}
})
}
}
func TestStubHandlers(t *testing.T) {
server := createMockServer()
tests := []struct {
name string
handler func(s *Session, ackHandle uint32)
}{
{"stubEnumerateNoResults", stubEnumerateNoResults},
{"stubGetNoResults", stubGetNoResults},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
session := createMockSession(1, server)
tt.handler(session, 12345)
select {
case pkt := <-session.sendPackets:
if pkt.data == nil {
t.Error("Packet data should not be nil")
}
default:
t.Error("Stub handler should queue a packet")
}
})
}
}
// Test packet queueing
func TestSessionQueueSendMHF(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgSysAck{
AckHandle: 12345,
IsBufferResponse: false,
ErrorCode: 0,
AckData: []byte{0x00},
}
session.QueueSendMHF(pkt)
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("Queued packet should have data")
}
default:
t.Error("QueueSendMHF should queue a packet")
}
}
func TestSessionQueueSendNonBlocking(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
data := []byte{0x01, 0x02, 0x03, 0x04}
session.QueueSendNonBlocking(data)
select {
case p := <-session.sendPackets:
if len(p.data) != 4 {
t.Errorf("Queued data len = %d, want 4", len(p.data))
}
if p.nonBlocking != true {
t.Error("Packet should be marked as non-blocking")
}
default:
t.Error("QueueSendNonBlocking should queue data")
}
}
func TestSessionQueueSendNonBlocking_FullQueue(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Fill the queue
for i := 0; i < 20; i++ {
session.sendPackets <- packet{data: []byte{byte(i)}, nonBlocking: true}
}
// Non-blocking send should not block when queue is full
// It should drop the packet instead
done := make(chan bool, 1)
go func() {
session.QueueSendNonBlocking([]byte{0xFF})
done <- true
}()
// Wait for completion with a reasonable timeout
// The function should return immediately (dropping the packet)
select {
case <-done:
// Good - didn't block, function completed
case <-time.After(100 * time.Millisecond):
t.Error("QueueSendNonBlocking blocked on full queue")
}
}
// Additional handler tests for coverage
func TestHandleMsgMhfGetGuildWeeklyBonusMaster(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetGuildWeeklyBonusMaster{
AckHandle: 12345,
}
handleMsgMhfGetGuildWeeklyBonusMaster(session, pkt)
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 TestHandleMsgMhfGetGuildWeeklyBonusActiveCount(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetGuildWeeklyBonusActiveCount{
AckHandle: 12345,
}
handleMsgMhfGetGuildWeeklyBonusActiveCount(session, pkt)
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 TestHandleMsgMhfAddGuildWeeklyBonusExceptionalUser(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfAddGuildWeeklyBonusExceptionalUser{
AckHandle: 12345,
}
handleMsgMhfAddGuildWeeklyBonusExceptionalUser(session, pkt)
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 TestEmptyHandlers_NoDb(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Test handlers that are empty and should not panic
tests := []struct {
name string
handler func(s *Session, p mhfpacket.MHFPacket)
}{
{"handleMsgHead", handleMsgHead},
{"handleMsgSysExtendThreshold", handleMsgSysExtendThreshold},
{"handleMsgSysEnd", handleMsgSysEnd},
{"handleMsgSysNop", handleMsgSysNop},
{"handleMsgSysAck", handleMsgSysAck},
{"handleMsgSysUpdateRight", handleMsgSysUpdateRight},
{"handleMsgSysAuthQuery", handleMsgSysAuthQuery},
{"handleMsgSysAuthTerminal", handleMsgSysAuthTerminal},
{"handleMsgCaExchangeItem", handleMsgCaExchangeItem},
{"handleMsgMhfServerCommand", handleMsgMhfServerCommand},
{"handleMsgMhfSetLoginwindow", handleMsgMhfSetLoginwindow},
{"handleMsgSysTransBinary", handleMsgSysTransBinary},
{"handleMsgSysCollectBinary", handleMsgSysCollectBinary},
{"handleMsgSysGetState", handleMsgSysGetState},
{"handleMsgSysSerialize", handleMsgSysSerialize},
{"handleMsgSysEnumlobby", handleMsgSysEnumlobby},
{"handleMsgSysEnumuser", handleMsgSysEnumuser},
{"handleMsgSysInfokyserver", handleMsgSysInfokyserver},
{"handleMsgMhfGetCaUniqueID", handleMsgMhfGetCaUniqueID},
{"handleMsgMhfEnumerateItem", handleMsgMhfEnumerateItem},
{"handleMsgMhfAcquireItem", handleMsgMhfAcquireItem},
{"handleMsgMhfGetExtraInfo", handleMsgMhfGetExtraInfo},
{"handleMsgMhfGetCogInfo", handleMsgMhfGetCogInfo},
{"handleMsgMhfStampcardPrize", handleMsgMhfStampcardPrize},
{"handleMsgMhfUnreserveSrg", handleMsgMhfUnreserveSrg},
{"handleMsgMhfKickExportForce", handleMsgMhfKickExportForce},
{"handleMsgSysSetStatus", handleMsgSysSetStatus},
{"handleMsgSysEcho", handleMsgSysEcho},
{"handleMsgMhfUseUdShopCoin", handleMsgMhfUseUdShopCoin},
{"handleMsgMhfEnterTournamentQuest", handleMsgMhfEnterTournamentQuest},
}
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)
}
}()
tt.handler(session, nil)
})
}
}