Files
Erupe/server/channelserver/handlers_reward_test.go
Houmgaor c43be33680 feat(shutdown): graceful drain + configurable countdown
Add ShutdownAndDrain to the channel server (issue #179 non-breaking
subset): on SIGTERM/SIGINT, force-close all active sessions so that
logoutPlayer runs for each one (saves character data, cleans up stages
and semaphores), then poll until the session map empties or a 30-second
context deadline passes.  Existing Shutdown() is unchanged.

Add ShutdownCountdownSeconds int config field (default 10) alongside
DisableSoftCrash so operators can tune the broadcast countdown without
patching code.  A zero value falls back to 10 for safety.

Fix pre-existing test failures: MsgMhfAddRewardSongCount has a complete
Parse() implementation so it no longer belongs in the "NOT IMPLEMENTED"
parse test list; its handler test is updated to pass a real packet and
assert an ACK response instead of calling with nil.
2026-03-21 01:36:31 +01:00

237 lines
5.4 KiB
Go

package channelserver
import (
"testing"
"erupe-ce/network/mhfpacket"
)
func TestHandleMsgMhfGetAdditionalBeatReward(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetAdditionalBeatReward{
AckHandle: 12345,
}
handleMsgMhfGetAdditionalBeatReward(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 TestHandleMsgMhfGetUdRankingRewardList(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetUdRankingRewardList{
AckHandle: 12345,
}
handleMsgMhfGetUdRankingRewardList(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 TestHandleMsgMhfGetRewardSong(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfGetRewardSong{
AckHandle: 12345,
}
handleMsgMhfGetRewardSong(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 TestHandleMsgMhfUseRewardSong(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfUseRewardSong{AckHandle: 12345}
handleMsgMhfUseRewardSong(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 TestHandleMsgMhfAddRewardSongCount(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfAddRewardSongCount{AckHandle: 42}
handleMsgMhfAddRewardSongCount(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 TestHandleMsgMhfAcquireMonthlyReward(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfAcquireMonthlyReward{
AckHandle: 12345,
}
handleMsgMhfAcquireMonthlyReward(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 TestHandleMsgMhfAcceptReadReward(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
defer func() {
if r := recover(); r != nil {
t.Errorf("handleMsgMhfAcceptReadReward panicked: %v", r)
}
}()
handleMsgMhfAcceptReadReward(session, nil)
}
// Tests consolidated from handlers_coverage3_test.go
func TestSimpleAckHandlers_RewardGo(t *testing.T) {
server := createMockServer()
tests := []struct {
name string
fn func(s *Session)
}{
{"handleMsgMhfGetRewardSong", func(s *Session) {
handleMsgMhfGetRewardSong(s, &mhfpacket.MsgMhfGetRewardSong{AckHandle: 1})
}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
session := createMockSession(1, server)
tt.fn(session)
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Errorf("%s: response should have data", tt.name)
}
default:
t.Errorf("%s: no response queued", tt.name)
}
})
}
}
func TestNonTrivialHandlers_RewardGo(t *testing.T) {
server := createMockServer()
tests := []struct {
name string
fn func(s *Session)
}{
{"handleMsgMhfGetAdditionalBeatReward", func(s *Session) {
handleMsgMhfGetAdditionalBeatReward(s, &mhfpacket.MsgMhfGetAdditionalBeatReward{AckHandle: 1})
}},
{"handleMsgMhfGetUdRankingRewardList", func(s *Session) {
handleMsgMhfGetUdRankingRewardList(s, &mhfpacket.MsgMhfGetUdRankingRewardList{AckHandle: 1})
}},
{"handleMsgMhfAcquireMonthlyReward", func(s *Session) {
handleMsgMhfAcquireMonthlyReward(s, &mhfpacket.MsgMhfAcquireMonthlyReward{AckHandle: 1})
}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
session := createMockSession(1, server)
tt.fn(session)
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Errorf("%s: response should have data", tt.name)
}
default:
t.Errorf("%s: no response queued", tt.name)
}
})
}
}
func TestEmptyHandlers_MiscFiles_Reward(t *testing.T) {
server := createMockServer()
session := createMockSession(1, server)
// Handlers that accept nil and take no action (no AckHandle).
nilSafeTests := []struct {
name string
fn func()
}{
{"handleMsgMhfAcceptReadReward", func() { handleMsgMhfAcceptReadReward(session, nil) }},
}
for _, tt := range nilSafeTests {
t.Run(tt.name, func(t *testing.T) {
defer func() {
if r := recover(); r != nil {
t.Errorf("%s panicked: %v", tt.name, r)
}
}()
tt.fn()
})
}
// handleMsgMhfUseRewardSong is a real handler (requires a typed packet).
t.Run("handleMsgMhfUseRewardSong", func(t *testing.T) {
pkt := &mhfpacket.MsgMhfUseRewardSong{AckHandle: 1}
handleMsgMhfUseRewardSong(session, pkt)
select {
case p := <-session.sendPackets:
if len(p.data) == 0 {
t.Error("handleMsgMhfUseRewardSong: response should have data")
}
default:
t.Error("handleMsgMhfUseRewardSong: no response queued")
}
})
}