mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 15:43:49 +01:00
Port test files from v9.2.x-stable branch to increase channelserver coverage from 13.8% to 25.6% (556 tests passing). Adapted all files to main's struct definitions: config import alias, Airou/CatDefinition rename, packet field mismatches, Raviente struct differences, and maxPlayers defaults. Removed tests referencing production code not yet on main (Player, FestivalColour, etc.). Excluded handlers_register_test.go (Raviente completely redesigned).
921 lines
20 KiB
Go
921 lines
20 KiB
Go
package channelserver
|
|
|
|
import (
|
|
"testing"
|
|
|
|
_config "erupe-ce/config"
|
|
"erupe-ce/network/mhfpacket"
|
|
)
|
|
|
|
// Tests for guild handlers that do not require database access.
|
|
|
|
func TestHandleMsgMhfEntryRookieGuild(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfEntryRookieGuild{
|
|
AckHandle: 12345,
|
|
Unk: 42,
|
|
}
|
|
|
|
handleMsgMhfEntryRookieGuild(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 TestHandleMsgMhfGenerateUdGuildMap(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfGenerateUdGuildMap{
|
|
AckHandle: 12345,
|
|
}
|
|
|
|
handleMsgMhfGenerateUdGuildMap(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 TestHandleMsgMhfCheckMonthlyItem(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfCheckMonthlyItem{
|
|
AckHandle: 12345,
|
|
Type: 0,
|
|
}
|
|
|
|
handleMsgMhfCheckMonthlyItem(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 TestHandleMsgMhfAcquireMonthlyItem(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfAcquireMonthlyItem{
|
|
AckHandle: 12345,
|
|
}
|
|
|
|
handleMsgMhfAcquireMonthlyItem(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 TestHandleMsgMhfEnumerateInvGuild(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfEnumerateInvGuild{
|
|
AckHandle: 12345,
|
|
}
|
|
|
|
handleMsgMhfEnumerateInvGuild(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 TestHandleMsgMhfOperationInvGuild(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfOperationInvGuild{
|
|
AckHandle: 12345,
|
|
Operation: 1,
|
|
}
|
|
|
|
handleMsgMhfOperationInvGuild(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")
|
|
}
|
|
}
|
|
|
|
// Tests for mercenary handlers that do not require database access.
|
|
|
|
func TestHandleMsgMhfMercenaryHuntdata_Unk0Is1(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfMercenaryHuntdata{
|
|
AckHandle: 12345,
|
|
Unk0: 1,
|
|
}
|
|
|
|
handleMsgMhfMercenaryHuntdata(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 TestHandleMsgMhfMercenaryHuntdata_Unk0Is0(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfMercenaryHuntdata{
|
|
AckHandle: 12345,
|
|
Unk0: 0,
|
|
}
|
|
|
|
handleMsgMhfMercenaryHuntdata(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 TestHandleMsgMhfMercenaryHuntdata_Unk0Is2(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfMercenaryHuntdata{
|
|
AckHandle: 12345,
|
|
Unk0: 2,
|
|
}
|
|
|
|
handleMsgMhfMercenaryHuntdata(session, pkt)
|
|
|
|
// Unk0=2 takes the else branch (same as 0)
|
|
select {
|
|
case p := <-session.sendPackets:
|
|
if len(p.data) == 0 {
|
|
t.Error("Response packet should have data")
|
|
}
|
|
default:
|
|
t.Error("No response packet queued")
|
|
}
|
|
}
|
|
|
|
// Tests for festa/ranking handlers.
|
|
|
|
func TestHandleMsgMhfEnumerateRanking_DefaultBranch(t *testing.T) {
|
|
server := createMockServer()
|
|
server.erupeConfig = &_config.Config{
|
|
DebugOptions: _config.DebugOptions{
|
|
TournamentOverride: 0,
|
|
},
|
|
}
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfEnumerateRanking{
|
|
AckHandle: 99999,
|
|
}
|
|
|
|
handleMsgMhfEnumerateRanking(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 TestHandleMsgMhfEnumerateRanking_NegativeState(t *testing.T) {
|
|
server := createMockServer()
|
|
server.erupeConfig = &_config.Config{
|
|
DebugOptions: _config.DebugOptions{
|
|
TournamentOverride: -1,
|
|
},
|
|
}
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfEnumerateRanking{
|
|
AckHandle: 99999,
|
|
}
|
|
|
|
handleMsgMhfEnumerateRanking(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")
|
|
}
|
|
}
|
|
|
|
// Tests for rengoku handlers.
|
|
|
|
func TestHandleMsgMhfGetRengokuRankingRank_ResponseData(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfGetRengokuRankingRank{
|
|
AckHandle: 55555,
|
|
}
|
|
|
|
handleMsgMhfGetRengokuRankingRank(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")
|
|
}
|
|
}
|
|
|
|
// Tests for empty handlers that are not covered in other test files.
|
|
|
|
func TestEmptyHandlers_Coverage2(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
tests := []struct {
|
|
name string
|
|
handler func(s *Session, p mhfpacket.MHFPacket)
|
|
}{
|
|
{"handleMsgSysCastedBinary", handleMsgSysCastedBinary},
|
|
{"handleMsgMhfResetTitle", handleMsgMhfResetTitle},
|
|
{"handleMsgMhfUpdateForceGuildRank", handleMsgMhfUpdateForceGuildRank},
|
|
{"handleMsgMhfUpdateGuild", handleMsgMhfUpdateGuild},
|
|
{"handleMsgMhfUpdateGuildcard", handleMsgMhfUpdateGuildcard},
|
|
}
|
|
|
|
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)
|
|
})
|
|
}
|
|
}
|
|
|
|
// Tests for handlers.go - handlers that produce responses without DB access.
|
|
|
|
func TestHandleMsgSysTerminalLog_MultipleEntries(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysTerminalLog{
|
|
AckHandle: 12345,
|
|
LogID: 200,
|
|
Entries: []mhfpacket.TerminalLogEntry{
|
|
{Type1: 10, Type2: 20},
|
|
{Type1: 11, Type2: 21},
|
|
{Type1: 12, Type2: 22},
|
|
},
|
|
}
|
|
|
|
handleMsgSysTerminalLog(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 TestHandleMsgSysTerminalLog_ZeroLogID(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysTerminalLog{
|
|
AckHandle: 12345,
|
|
LogID: 0,
|
|
Entries: []mhfpacket.TerminalLogEntry{},
|
|
}
|
|
|
|
handleMsgSysTerminalLog(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 TestHandleMsgSysPing_DifferentAckHandle(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysPing{
|
|
AckHandle: 0xFFFFFFFF,
|
|
}
|
|
|
|
handleMsgSysPing(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 TestHandleMsgSysTime_GetRemoteTimeFalse(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysTime{
|
|
GetRemoteTime: false,
|
|
}
|
|
|
|
handleMsgSysTime(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 TestHandleMsgSysIssueLogkey_LogKeyGenerated(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysIssueLogkey{
|
|
AckHandle: 77777,
|
|
}
|
|
|
|
handleMsgSysIssueLogkey(session, pkt)
|
|
|
|
// Verify that the logKey was set on the session
|
|
session.Lock()
|
|
keyLen := len(session.logKey)
|
|
session.Unlock()
|
|
|
|
if keyLen != 16 {
|
|
t.Errorf("logKey length = %d, want 16", keyLen)
|
|
}
|
|
|
|
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 TestHandleMsgSysIssueLogkey_Uniqueness(t *testing.T) {
|
|
server := createMockServer()
|
|
|
|
// Generate two logkeys and verify they differ
|
|
session1 := createMockSession(1, server)
|
|
session2 := createMockSession(2, server)
|
|
|
|
pkt1 := &mhfpacket.MsgSysIssueLogkey{AckHandle: 1}
|
|
pkt2 := &mhfpacket.MsgSysIssueLogkey{AckHandle: 2}
|
|
|
|
handleMsgSysIssueLogkey(session1, pkt1)
|
|
handleMsgSysIssueLogkey(session2, pkt2)
|
|
|
|
// Drain send packets
|
|
<-session1.sendPackets
|
|
<-session2.sendPackets
|
|
|
|
session1.Lock()
|
|
key1 := make([]byte, len(session1.logKey))
|
|
copy(key1, session1.logKey)
|
|
session1.Unlock()
|
|
|
|
session2.Lock()
|
|
key2 := make([]byte, len(session2.logKey))
|
|
copy(key2, session2.logKey)
|
|
session2.Unlock()
|
|
|
|
if len(key1) != 16 || len(key2) != 16 {
|
|
t.Fatalf("logKeys should be 16 bytes each, got %d and %d", len(key1), len(key2))
|
|
}
|
|
|
|
same := true
|
|
for i := range key1 {
|
|
if key1[i] != key2[i] {
|
|
same = false
|
|
break
|
|
}
|
|
}
|
|
if same {
|
|
t.Error("Two generated logkeys should differ (extremely unlikely to be the same)")
|
|
}
|
|
}
|
|
|
|
// Tests for event handlers.
|
|
|
|
func TestHandleMsgMhfReleaseEvent_ErrorCode(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfReleaseEvent{
|
|
AckHandle: 88888,
|
|
}
|
|
|
|
handleMsgMhfReleaseEvent(session, pkt)
|
|
|
|
// This handler manually sends a response with 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_Stub(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfEnumerateEvent{
|
|
AckHandle: 77777,
|
|
}
|
|
|
|
handleMsgMhfEnumerateEvent(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")
|
|
}
|
|
}
|
|
|
|
// Tests for achievement handler.
|
|
|
|
func TestHandleMsgMhfSetCaAchievementHist_Response(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfSetCaAchievementHist{
|
|
AckHandle: 44444,
|
|
}
|
|
|
|
handleMsgMhfSetCaAchievementHist(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")
|
|
}
|
|
}
|
|
|
|
// Test concurrent handler invocations to catch potential data races.
|
|
|
|
func TestHandlersConcurrentInvocations(t *testing.T) {
|
|
server := createMockServer()
|
|
|
|
done := make(chan struct{})
|
|
const numGoroutines = 10
|
|
|
|
for i := 0; i < numGoroutines; i++ {
|
|
go func(id uint32) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
t.Errorf("goroutine %d panicked: %v", id, r)
|
|
}
|
|
done <- struct{}{}
|
|
}()
|
|
|
|
session := createMockSession(id, server)
|
|
|
|
// Run several handlers concurrently
|
|
handleMsgSysPing(session, &mhfpacket.MsgSysPing{AckHandle: id})
|
|
<-session.sendPackets
|
|
|
|
handleMsgSysTime(session, &mhfpacket.MsgSysTime{GetRemoteTime: true})
|
|
<-session.sendPackets
|
|
|
|
handleMsgSysIssueLogkey(session, &mhfpacket.MsgSysIssueLogkey{AckHandle: id})
|
|
<-session.sendPackets
|
|
|
|
handleMsgMhfMercenaryHuntdata(session, &mhfpacket.MsgMhfMercenaryHuntdata{AckHandle: id, Unk0: 1})
|
|
<-session.sendPackets
|
|
|
|
handleMsgMhfEnumerateMercenaryLog(session, &mhfpacket.MsgMhfEnumerateMercenaryLog{AckHandle: id})
|
|
<-session.sendPackets
|
|
}(uint32(i + 100))
|
|
}
|
|
|
|
for i := 0; i < numGoroutines; i++ {
|
|
<-done
|
|
}
|
|
}
|
|
|
|
// Test record log handler with stage setup.
|
|
|
|
func TestHandleMsgSysRecordLog_RemovesReservation(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
stage := NewStage("test_stage_record")
|
|
session.stage = stage
|
|
stage.reservedClientSlots[session.charID] = true
|
|
|
|
pkt := &mhfpacket.MsgSysRecordLog{
|
|
AckHandle: 55555,
|
|
Data: make([]byte, 256),
|
|
}
|
|
|
|
handleMsgSysRecordLog(session, pkt)
|
|
|
|
if _, exists := stage.reservedClientSlots[session.charID]; exists {
|
|
t.Error("charID should be removed from reserved slots after record log")
|
|
}
|
|
|
|
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 TestHandleMsgSysRecordLog_NoExistingReservation(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
stage := NewStage("test_stage_no_reservation")
|
|
session.stage = stage
|
|
// No reservation exists for this charID
|
|
|
|
pkt := &mhfpacket.MsgSysRecordLog{
|
|
AckHandle: 55556,
|
|
Data: make([]byte, 256),
|
|
}
|
|
|
|
// Should not panic even if charID is not in reservedClientSlots
|
|
handleMsgSysRecordLog(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")
|
|
}
|
|
}
|
|
|
|
// Test unlock global sema handler.
|
|
|
|
func TestHandleMsgSysUnlockGlobalSema_Response(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysUnlockGlobalSema{
|
|
AckHandle: 66666,
|
|
}
|
|
|
|
handleMsgSysUnlockGlobalSema(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")
|
|
}
|
|
}
|
|
|
|
// Test handlers from handlers_event.go with edge cases.
|
|
|
|
func TestHandleMsgMhfSetRestrictionEvent_Response(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfSetRestrictionEvent{
|
|
AckHandle: 11111,
|
|
}
|
|
|
|
handleMsgMhfSetRestrictionEvent(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 TestHandleMsgMhfGetRestrictionEvent_Empty(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
t.Errorf("handleMsgMhfGetRestrictionEvent panicked: %v", r)
|
|
}
|
|
}()
|
|
|
|
handleMsgMhfGetRestrictionEvent(session, nil)
|
|
}
|
|
|
|
// Test handlers from handlers_mercenary.go - legend dispatch (no DB).
|
|
|
|
func TestHandleMsgMhfLoadLegendDispatch_Response(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgMhfLoadLegendDispatch{
|
|
AckHandle: 22222,
|
|
}
|
|
|
|
handleMsgMhfLoadLegendDispatch(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")
|
|
}
|
|
}
|
|
|
|
// Test multiple handler invocations on the same session to verify session state is not corrupted.
|
|
|
|
func TestMultipleHandlersOnSameSession(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
// Call multiple handlers in sequence
|
|
handleMsgSysPing(session, &mhfpacket.MsgSysPing{AckHandle: 1})
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Fatal("Expected packet from Ping handler")
|
|
}
|
|
|
|
handleMsgSysTime(session, &mhfpacket.MsgSysTime{GetRemoteTime: true})
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Fatal("Expected packet from Time handler")
|
|
}
|
|
|
|
handleMsgMhfRegisterEvent(session, &mhfpacket.MsgMhfRegisterEvent{AckHandle: 2, WorldID: 5, LandID: 10})
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Fatal("Expected packet from RegisterEvent handler")
|
|
}
|
|
|
|
handleMsgMhfReleaseEvent(session, &mhfpacket.MsgMhfReleaseEvent{AckHandle: 3})
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Fatal("Expected packet from ReleaseEvent handler")
|
|
}
|
|
|
|
handleMsgMhfEnumerateEvent(session, &mhfpacket.MsgMhfEnumerateEvent{AckHandle: 4})
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Fatal("Expected packet from EnumerateEvent handler")
|
|
}
|
|
|
|
handleMsgMhfSetCaAchievementHist(session, &mhfpacket.MsgMhfSetCaAchievementHist{AckHandle: 5})
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Fatal("Expected packet from SetCaAchievementHist handler")
|
|
}
|
|
|
|
handleMsgMhfGetRengokuRankingRank(session, &mhfpacket.MsgMhfGetRengokuRankingRank{AckHandle: 6})
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Fatal("Expected packet from GetRengokuRankingRank handler")
|
|
}
|
|
}
|
|
|
|
// Test festa timestamp generation.
|
|
|
|
func TestGenerateFestaTimestamps_Debug(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
tests := []struct {
|
|
name string
|
|
start uint32
|
|
}{
|
|
{"Debug_Start1", 1},
|
|
{"Debug_Start2", 2},
|
|
{"Debug_Start3", 3},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
timestamps := generateFestaTimestamps(session, tt.start, true)
|
|
if len(timestamps) != 5 {
|
|
t.Errorf("Expected 5 timestamps, got %d", len(timestamps))
|
|
}
|
|
for i, ts := range timestamps {
|
|
if ts == 0 {
|
|
t.Errorf("Timestamp %d should not be zero", i)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGenerateFestaTimestamps_NonDebug_FutureStart(t *testing.T) {
|
|
server := createMockServer()
|
|
session := createMockSession(1, server)
|
|
|
|
// Use a far-future start time so it does not trigger cleanup
|
|
futureStart := uint32(TimeAdjusted().Unix() + 5000000)
|
|
timestamps := generateFestaTimestamps(session, futureStart, false)
|
|
|
|
if len(timestamps) != 5 {
|
|
t.Errorf("Expected 5 timestamps, got %d", len(timestamps))
|
|
}
|
|
if timestamps[0] != futureStart {
|
|
t.Errorf("First timestamp = %d, want %d", timestamps[0], futureStart)
|
|
}
|
|
// Verify intervals
|
|
if timestamps[1] != timestamps[0]+604800 {
|
|
t.Errorf("Second timestamp should be start+604800, got %d", timestamps[1])
|
|
}
|
|
if timestamps[2] != timestamps[1]+604800 {
|
|
t.Errorf("Third timestamp should be second+604800, got %d", timestamps[2])
|
|
}
|
|
if timestamps[3] != timestamps[2]+9000 {
|
|
t.Errorf("Fourth timestamp should be third+9000, got %d", timestamps[3])
|
|
}
|
|
if timestamps[4] != timestamps[3]+1240200 {
|
|
t.Errorf("Fifth timestamp should be fourth+1240200, got %d", timestamps[4])
|
|
}
|
|
}
|
|
|
|
// Test trial struct from handlers_festa.go.
|
|
|
|
func TestFestaTrialStruct(t *testing.T) {
|
|
trial := FestaTrial{
|
|
ID: 100,
|
|
Objective: 2,
|
|
GoalID: 500,
|
|
TimesReq: 10,
|
|
Locale: 1,
|
|
Reward: 50,
|
|
}
|
|
if trial.ID != 100 {
|
|
t.Errorf("ID = %d, want 100", trial.ID)
|
|
}
|
|
if trial.Objective != 2 {
|
|
t.Errorf("Objective = %d, want 2", trial.Objective)
|
|
}
|
|
if trial.GoalID != 500 {
|
|
t.Errorf("GoalID = %d, want 500", trial.GoalID)
|
|
}
|
|
if trial.TimesReq != 10 {
|
|
t.Errorf("TimesReq = %d, want 10", trial.TimesReq)
|
|
}
|
|
}
|
|
|
|
// Test prize struct from handlers_festa.go.
|
|
|
|
func TestPrizeStruct(t *testing.T) {
|
|
prize := Prize{
|
|
ID: 1,
|
|
Tier: 2,
|
|
SoulsReq: 100,
|
|
ItemID: 0x1234,
|
|
NumItem: 5,
|
|
Claimed: 1,
|
|
}
|
|
if prize.ID != 1 {
|
|
t.Errorf("ID = %d, want 1", prize.ID)
|
|
}
|
|
if prize.Tier != 2 {
|
|
t.Errorf("Tier = %d, want 2", prize.Tier)
|
|
}
|
|
if prize.SoulsReq != 100 {
|
|
t.Errorf("SoulsReq = %d, want 100", prize.SoulsReq)
|
|
}
|
|
if prize.Claimed != 1 {
|
|
t.Errorf("Claimed = %d, want 1", prize.Claimed)
|
|
}
|
|
}
|
|
|
|
// Test Airou struct from handlers_mercenary.go.
|
|
|
|
func TestAirouStruct(t *testing.T) {
|
|
cat := Airou{
|
|
ID: 42,
|
|
Name: []byte("TestCat"),
|
|
Task: 4,
|
|
Personality: 2,
|
|
Class: 1,
|
|
Experience: 1500,
|
|
WeaponType: 6,
|
|
WeaponID: 100,
|
|
}
|
|
|
|
if cat.ID != 42 {
|
|
t.Errorf("ID = %d, want 42", cat.ID)
|
|
}
|
|
if cat.Task != 4 {
|
|
t.Errorf("Task = %d, want 4", cat.Task)
|
|
}
|
|
if cat.Experience != 1500 {
|
|
t.Errorf("Experience = %d, want 1500", cat.Experience)
|
|
}
|
|
if cat.WeaponType != 6 {
|
|
t.Errorf("WeaponType = %d, want 6", cat.WeaponType)
|
|
}
|
|
if cat.WeaponID != 100 {
|
|
t.Errorf("WeaponID = %d, want 100", cat.WeaponID)
|
|
}
|
|
}
|
|
|
|
// Test RengokuScore struct default values.
|
|
|
|
func TestRengokuScoreStruct_Fields(t *testing.T) {
|
|
score := RengokuScore{
|
|
Name: "Hunter",
|
|
Score: 99999,
|
|
}
|
|
|
|
if score.Name != "Hunter" {
|
|
t.Errorf("Name = %s, want Hunter", score.Name)
|
|
}
|
|
if score.Score != 99999 {
|
|
t.Errorf("Score = %d, want 99999", score.Score)
|
|
}
|
|
}
|