diff --git a/server/channelserver/handlers_achievement_test.go b/server/channelserver/handlers_achievement_test.go new file mode 100644 index 000000000..f2becb8aa --- /dev/null +++ b/server/channelserver/handlers_achievement_test.go @@ -0,0 +1,191 @@ +package channelserver + +import ( + "testing" +) + +func TestGetAchData_Level0(t *testing.T) { + // Score 0 should give level 0 with progress toward first threshold + ach := GetAchData(0, 0) + if ach.Level != 0 { + t.Errorf("Level = %d, want 0", ach.Level) + } + if ach.Progress != 0 { + t.Errorf("Progress = %d, want 0", ach.Progress) + } + if ach.NextValue != 5 { + t.Errorf("NextValue = %d, want 5", ach.NextValue) + } +} + +func TestGetAchData_Level1(t *testing.T) { + // Score 5 (exactly at first threshold) should give level 1 + ach := GetAchData(0, 5) + if ach.Level != 1 { + t.Errorf("Level = %d, want 1", ach.Level) + } + if ach.Value != 5 { + t.Errorf("Value = %d, want 5", ach.Value) + } +} + +func TestGetAchData_Partial(t *testing.T) { + // Score 3 should give level 0 with progress 3 + ach := GetAchData(0, 3) + if ach.Level != 0 { + t.Errorf("Level = %d, want 0", ach.Level) + } + if ach.Progress != 3 { + t.Errorf("Progress = %d, want 3", ach.Progress) + } + if ach.Required != 5 { + t.Errorf("Required = %d, want 5", ach.Required) + } +} + +func TestGetAchData_MaxLevel(t *testing.T) { + // Score 999 should give max level for curve 0 + ach := GetAchData(0, 999) + if ach.Level != 8 { + t.Errorf("Level = %d, want 8", ach.Level) + } + if ach.Trophy != 0x7F { + t.Errorf("Trophy = %x, want 0x7F (gold)", ach.Trophy) + } +} + +func TestGetAchData_BronzeTrophy(t *testing.T) { + // Level 7 should have bronze trophy (0x40) + // Curve 0: 5, 15, 30, 50, 100, 150, 200, 300 + // Cumulative: 5, 20, 50, 100, 200, 350, 550, 850 + // To reach level 7, need 550+ points (sum of first 7 thresholds) + ach := GetAchData(0, 550) + if ach.Level != 7 { + t.Errorf("Level = %d, want 7", ach.Level) + } + if ach.Trophy != 0x60 { + t.Errorf("Trophy = %x, want 0x60 (silver)", ach.Trophy) + } +} + +func TestGetAchData_SilverTrophy(t *testing.T) { + // Level 8 (max) should have gold trophy (0x7F) + // Need 850+ (sum of all 8 thresholds) for max level + ach := GetAchData(0, 850) + if ach.Level != 8 { + t.Errorf("Level = %d, want 8", ach.Level) + } + if ach.Trophy != 0x7F { + t.Errorf("Trophy = %x, want 0x7F (gold)", ach.Trophy) + } +} + +func TestGetAchData_DifferentCurves(t *testing.T) { + tests := []struct { + name string + id uint8 + score int32 + wantLvl uint8 + wantProg uint32 + }{ + {"Curve1_ID7_Level0", 7, 0, 0, 0}, + {"Curve1_ID7_Level1", 7, 1, 1, 0}, + {"Curve2_ID8_Level0", 8, 0, 0, 0}, + {"Curve2_ID8_Level1", 8, 1, 1, 0}, + {"Curve3_ID16_Level0", 16, 0, 0, 0}, + {"Curve3_ID16_Partial", 16, 5, 0, 5}, + {"Curve3_ID16_Level1", 16, 10, 1, 0}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ach := GetAchData(tt.id, tt.score) + if ach.Level != tt.wantLvl { + t.Errorf("Level = %d, want %d", ach.Level, tt.wantLvl) + } + if ach.Progress != tt.wantProg { + t.Errorf("Progress = %d, want %d", ach.Progress, tt.wantProg) + } + }) + } +} + +func TestGetAchData_AllCurveMappings(t *testing.T) { + // Verify all achievement IDs have valid curve mappings + for id := uint8(0); id <= 32; id++ { + curve, ok := achievementCurveMap[id] + if !ok { + t.Errorf("Achievement ID %d has no curve mapping", id) + continue + } + if len(curve) != 8 { + t.Errorf("Achievement ID %d curve has %d elements, want 8", id, len(curve)) + } + } +} + +func TestGetAchData_ValueAccumulation(t *testing.T) { + // Test that Value correctly accumulates based on level + // Level values: 1=5, 2-4=10, 5-7=15, 8=20 + // At max level 8: 5 + 10*3 + 15*3 + 20 = 5 + 30 + 45 + 20 = 100 + ach := GetAchData(0, 1000) // Score well above max + expectedValue := uint32(5 + 10 + 10 + 10 + 15 + 15 + 15 + 20) + if ach.Value != expectedValue { + t.Errorf("Value = %d, want %d", ach.Value, expectedValue) + } +} + +func TestGetAchData_NextValueByLevel(t *testing.T) { + tests := []struct { + level uint8 + wantNext uint16 + approxScore int32 + }{ + {0, 5, 0}, + {1, 10, 5}, + {2, 10, 15}, + {3, 10, 30}, + {4, 15, 50}, + {5, 15, 100}, + } + + for _, tt := range tests { + t.Run("Level"+string(rune('0'+tt.level)), func(t *testing.T) { + ach := GetAchData(0, tt.approxScore) + if ach.Level != tt.level { + t.Skipf("Skipping: got level %d, expected %d", ach.Level, tt.level) + } + if ach.NextValue != tt.wantNext { + t.Errorf("NextValue at level %d = %d, want %d", ach.Level, ach.NextValue, tt.wantNext) + } + }) + } +} + +func TestAchievementCurves(t *testing.T) { + // Verify curve values are strictly increasing + for i, curve := range achievementCurves { + for j := 1; j < len(curve); j++ { + if curve[j] <= curve[j-1] { + t.Errorf("Curve %d: value[%d]=%d should be > value[%d]=%d", + i, j, curve[j], j-1, curve[j-1]) + } + } + } +} + +func TestAchievementCurveMap_Coverage(t *testing.T) { + // Ensure all mapped curves exist + for id, curve := range achievementCurveMap { + found := false + for _, c := range achievementCurves { + if &c[0] == &curve[0] { + found = true + break + } + } + if !found { + t.Errorf("Achievement ID %d maps to unknown curve", id) + } + } +} diff --git a/server/channelserver/handlers_cafe_test.go b/server/channelserver/handlers_cafe_test.go new file mode 100644 index 000000000..76eeded59 --- /dev/null +++ b/server/channelserver/handlers_cafe_test.go @@ -0,0 +1,98 @@ +package channelserver + +import ( + "testing" + + "erupe-ce/network/mhfpacket" +) + +func TestHandleMsgMhfGetBoostTime(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetBoostTime{ + AckHandle: 12345, + } + + handleMsgMhfGetBoostTime(session, pkt) + + select { + case p := <-session.sendPackets: + // Response should be empty bytes for this handler + if p.data == nil { + t.Error("Response packet data should not be nil") + } + default: + t.Error("No response packet queued") + } +} + +func TestHandleMsgMhfPostBoostTimeQuestReturn(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfPostBoostTimeQuestReturn{ + AckHandle: 12345, + } + + handleMsgMhfPostBoostTimeQuestReturn(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 TestHandleMsgMhfPostBoostTime(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + // Empty handler - should not panic + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfPostBoostTime panicked: %v", r) + } + }() + + handleMsgMhfPostBoostTime(session, nil) +} + +func TestHandleMsgMhfPostBoostTimeLimit(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + // Empty handler - should not panic + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfPostBoostTimeLimit panicked: %v", r) + } + }() + + handleMsgMhfPostBoostTimeLimit(session, nil) +} + +func TestCafeBonusStruct(t *testing.T) { + // Test CafeBonus struct can be created + bonus := CafeBonus{ + ID: 1, + TimeReq: 3600, + ItemType: 1, + ItemID: 100, + Quantity: 5, + Claimed: false, + } + + if bonus.ID != 1 { + t.Errorf("ID = %d, want 1", bonus.ID) + } + if bonus.TimeReq != 3600 { + t.Errorf("TimeReq = %d, want 3600", bonus.TimeReq) + } + if bonus.Claimed { + t.Error("Claimed should be false") + } +} diff --git a/server/channelserver/handlers_caravan_test.go b/server/channelserver/handlers_caravan_test.go new file mode 100644 index 000000000..da8de4a79 --- /dev/null +++ b/server/channelserver/handlers_caravan_test.go @@ -0,0 +1,120 @@ +package channelserver + +import ( + "testing" + + "erupe-ce/network/mhfpacket" +) + +func TestHandleMsgMhfGetRyoudama(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetRyoudama{ + AckHandle: 12345, + } + + handleMsgMhfGetRyoudama(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 TestHandleMsgMhfPostRyoudama(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfPostRyoudama panicked: %v", r) + } + }() + + handleMsgMhfPostRyoudama(session, nil) +} + +func TestHandleMsgMhfGetTinyBin(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetTinyBin{ + AckHandle: 12345, + } + + handleMsgMhfGetTinyBin(session, pkt) + + select { + case p := <-session.sendPackets: + // Response might be empty bytes + if p.data == nil { + t.Error("Response packet data should not be nil") + } + default: + t.Error("No response packet queued") + } +} + +func TestHandleMsgMhfPostTinyBin(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfPostTinyBin{ + AckHandle: 12345, + } + + handleMsgMhfPostTinyBin(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 TestHandleMsgMhfCaravanMyScore(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfCaravanMyScore panicked: %v", r) + } + }() + + handleMsgMhfCaravanMyScore(session, nil) +} + +func TestHandleMsgMhfCaravanRanking(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfCaravanRanking panicked: %v", r) + } + }() + + handleMsgMhfCaravanRanking(session, nil) +} + +func TestHandleMsgMhfCaravanMyRank(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfCaravanMyRank panicked: %v", r) + } + }() + + handleMsgMhfCaravanMyRank(session, nil) +} diff --git a/server/channelserver/handlers_cast_binary_test.go b/server/channelserver/handlers_cast_binary_test.go new file mode 100644 index 000000000..757d5fd51 --- /dev/null +++ b/server/channelserver/handlers_cast_binary_test.go @@ -0,0 +1,80 @@ +package channelserver + +import ( + "testing" +) + +func TestBinaryMessageTypeConstants(t *testing.T) { + tests := []struct { + name string + constant int + expected int + }{ + {"BinaryMessageTypeState", BinaryMessageTypeState, 0}, + {"BinaryMessageTypeChat", BinaryMessageTypeChat, 1}, + {"BinaryMessageTypeQuest", BinaryMessageTypeQuest, 2}, + {"BinaryMessageTypeData", BinaryMessageTypeData, 3}, + {"BinaryMessageTypeMailNotify", BinaryMessageTypeMailNotify, 4}, + {"BinaryMessageTypeEmote", BinaryMessageTypeEmote, 6}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.constant != tt.expected { + t.Errorf("%s = %d, want %d", tt.name, tt.constant, tt.expected) + } + }) + } +} + +func TestBroadcastTypeConstants(t *testing.T) { + tests := []struct { + name string + constant int + expected int + }{ + {"BroadcastTypeTargeted", BroadcastTypeTargeted, 0x01}, + {"BroadcastTypeStage", BroadcastTypeStage, 0x03}, + {"BroadcastTypeServer", BroadcastTypeServer, 0x06}, + {"BroadcastTypeWorld", BroadcastTypeWorld, 0x0a}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.constant != tt.expected { + t.Errorf("%s = %d, want %d", tt.name, tt.constant, tt.expected) + } + }) + } +} + +func TestCommandsMapInitialized(t *testing.T) { + // commands map should be initialized by init() + if commands == nil { + t.Error("commands map should be initialized") + } +} + +func TestSendServerChatMessage(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + // Should not panic + defer func() { + if r := recover(); r != nil { + t.Errorf("sendServerChatMessage panicked: %v", r) + } + }() + + sendServerChatMessage(session, "Test message") + + // Should queue a packet + select { + case p := <-session.sendPackets: + if len(p.data) == 0 { + t.Error("Response packet should have data") + } + default: + t.Error("No packet queued") + } +} diff --git a/server/channelserver/handlers_core_test.go b/server/channelserver/handlers_core_test.go new file mode 100644 index 000000000..127e022bc --- /dev/null +++ b/server/channelserver/handlers_core_test.go @@ -0,0 +1,367 @@ +package channelserver + +import ( + "testing" + + "erupe-ce/network/mhfpacket" +) + +// Test empty handlers don't panic + +func TestHandleMsgHead(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgHead panicked: %v", r) + } + }() + + handleMsgHead(session, nil) +} + +func TestHandleMsgSysExtendThreshold(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgSysExtendThreshold panicked: %v", r) + } + }() + + handleMsgSysExtendThreshold(session, nil) +} + +func TestHandleMsgSysEnd(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgSysEnd panicked: %v", r) + } + }() + + handleMsgSysEnd(session, nil) +} + +func TestHandleMsgSysNop(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgSysNop panicked: %v", r) + } + }() + + handleMsgSysNop(session, nil) +} + +func TestHandleMsgSysAck(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgSysAck panicked: %v", r) + } + }() + + handleMsgSysAck(session, nil) +} + +func TestHandleMsgCaExchangeItem(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgCaExchangeItem panicked: %v", r) + } + }() + + handleMsgCaExchangeItem(session, nil) +} + +func TestHandleMsgMhfServerCommand(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfServerCommand panicked: %v", r) + } + }() + + handleMsgMhfServerCommand(session, nil) +} + +func TestHandleMsgMhfSetLoginwindow(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfSetLoginwindow panicked: %v", r) + } + }() + + handleMsgMhfSetLoginwindow(session, nil) +} + +func TestHandleMsgSysTransBinary(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgSysTransBinary panicked: %v", r) + } + }() + + handleMsgSysTransBinary(session, nil) +} + +func TestHandleMsgSysCollectBinary(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgSysCollectBinary panicked: %v", r) + } + }() + + handleMsgSysCollectBinary(session, nil) +} + +func TestHandleMsgSysGetState(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgSysGetState panicked: %v", r) + } + }() + + handleMsgSysGetState(session, nil) +} + +func TestHandleMsgSysSerialize(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgSysSerialize panicked: %v", r) + } + }() + + handleMsgSysSerialize(session, nil) +} + +func TestHandleMsgSysEnumlobby(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgSysEnumlobby panicked: %v", r) + } + }() + + handleMsgSysEnumlobby(session, nil) +} + +func TestHandleMsgSysEnumuser(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgSysEnumuser panicked: %v", r) + } + }() + + handleMsgSysEnumuser(session, nil) +} + +func TestHandleMsgSysInfokyserver(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgSysInfokyserver panicked: %v", r) + } + }() + + handleMsgSysInfokyserver(session, nil) +} + +func TestHandleMsgMhfGetCaUniqueID(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfGetCaUniqueID panicked: %v", r) + } + }() + + handleMsgMhfGetCaUniqueID(session, nil) +} + +func TestHandleMsgMhfEnumerateItem(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfEnumerateItem panicked: %v", r) + } + }() + + handleMsgMhfEnumerateItem(session, nil) +} + +func TestHandleMsgMhfAcquireItem(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfAcquireItem panicked: %v", r) + } + }() + + handleMsgMhfAcquireItem(session, nil) +} + +func TestHandleMsgMhfGetExtraInfo(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfGetExtraInfo panicked: %v", r) + } + }() + + handleMsgMhfGetExtraInfo(session, nil) +} + +// Test handlers that return simple responses + +func TestHandleMsgMhfTransferItem(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfTransferItem{ + AckHandle: 12345, + } + + handleMsgMhfTransferItem(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 TestHandleMsgMhfEnumeratePrice(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfEnumeratePrice{ + AckHandle: 12345, + } + + handleMsgMhfEnumeratePrice(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 TestHandleMsgMhfEnumerateOrder(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfEnumerateOrder{ + AckHandle: 12345, + } + + handleMsgMhfEnumerateOrder(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 terminal log handler + +func TestHandleMsgSysTerminalLog(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgSysTerminalLog{ + AckHandle: 12345, + LogID: 100, + 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 TestHandleMsgSysTerminalLog_WithEntries(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgSysTerminalLog{ + AckHandle: 12345, + LogID: 100, + Entries: []*mhfpacket.TerminalLogEntry{ + {Type1: 1, Type2: 2, Data: []int16{1, 2, 3}}, + {Type1: 3, Type2: 4, Data: []int16{4, 5, 6}}, + }, + } + + 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") + } +} diff --git a/server/channelserver/handlers_diva_test.go b/server/channelserver/handlers_diva_test.go new file mode 100644 index 000000000..9930bc6ff --- /dev/null +++ b/server/channelserver/handlers_diva_test.go @@ -0,0 +1,297 @@ +package channelserver + +import ( + "testing" + + "erupe-ce/network/mhfpacket" +) + +func TestHandleMsgMhfGetUdInfo(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdInfo{ + AckHandle: 12345, + } + + handleMsgMhfGetUdInfo(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 TestHandleMsgMhfGetKijuInfo(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetKijuInfo{ + AckHandle: 12345, + } + + handleMsgMhfGetKijuInfo(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 TestHandleMsgMhfSetKiju(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfSetKiju{ + AckHandle: 12345, + } + + handleMsgMhfSetKiju(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 TestHandleMsgMhfAddUdPoint(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfAddUdPoint{ + AckHandle: 12345, + } + + handleMsgMhfAddUdPoint(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 TestHandleMsgMhfGetUdMyPoint(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdMyPoint{ + AckHandle: 12345, + } + + handleMsgMhfGetUdMyPoint(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 TestHandleMsgMhfGetUdTotalPointInfo(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdTotalPointInfo{ + AckHandle: 12345, + } + + handleMsgMhfGetUdTotalPointInfo(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 TestHandleMsgMhfGetUdSelectedColorInfo(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdSelectedColorInfo{ + AckHandle: 12345, + } + + handleMsgMhfGetUdSelectedColorInfo(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 TestHandleMsgMhfGetUdMonsterPoint(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdMonsterPoint{ + AckHandle: 12345, + } + + handleMsgMhfGetUdMonsterPoint(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 TestHandleMsgMhfGetUdDailyPresentList(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdDailyPresentList{ + AckHandle: 12345, + } + + handleMsgMhfGetUdDailyPresentList(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 TestHandleMsgMhfGetUdNormaPresentList(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdNormaPresentList{ + AckHandle: 12345, + } + + handleMsgMhfGetUdNormaPresentList(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 TestHandleMsgMhfAcquireUdItem(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfAcquireUdItem{ + AckHandle: 12345, + } + + handleMsgMhfAcquireUdItem(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 TestHandleMsgMhfGetUdRanking(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdRanking{ + AckHandle: 12345, + } + + handleMsgMhfGetUdRanking(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 TestHandleMsgMhfGetUdMyRanking(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdMyRanking{ + AckHandle: 12345, + } + + handleMsgMhfGetUdMyRanking(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 TestGenerateDivaTimestamps_Debug(t *testing.T) { + // Test debug mode timestamps + tests := []struct { + name string + start uint32 + }{ + {"Debug_Start1", 1}, + {"Debug_Start2", 2}, + {"Debug_Start3", 3}, + } + + server := createMockServer() + session := createMockSession(1, server) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + timestamps := generateDivaTimestamps(session, tt.start, true) + if len(timestamps) != 6 { + t.Errorf("Expected 6 timestamps, got %d", len(timestamps)) + } + // Verify timestamps are non-zero + for i, ts := range timestamps { + if ts == 0 { + t.Errorf("Timestamp %d should not be zero", i) + } + } + }) + } +} diff --git a/server/channelserver/handlers_festa_test.go b/server/channelserver/handlers_festa_test.go new file mode 100644 index 000000000..2f21dbd81 --- /dev/null +++ b/server/channelserver/handlers_festa_test.go @@ -0,0 +1,112 @@ +package channelserver + +import ( + "testing" + + "erupe-ce/config" + "erupe-ce/network/mhfpacket" +) + +func TestHandleMsgMhfEnumerateRanking_Default(t *testing.T) { + server := createMockServer() + server.erupeConfig = &config.Config{ + DevMode: true, + DevModeOptions: config.DevModeOptions{ + TournamentEvent: 0, // Default state + }, + } + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfEnumerateRanking{ + AckHandle: 12345, + } + + 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_State1(t *testing.T) { + server := createMockServer() + server.erupeConfig = &config.Config{ + DevMode: true, + DevModeOptions: config.DevModeOptions{ + TournamentEvent: 1, + }, + } + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfEnumerateRanking{ + AckHandle: 12345, + } + + 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_State2(t *testing.T) { + server := createMockServer() + server.erupeConfig = &config.Config{ + DevMode: true, + DevModeOptions: config.DevModeOptions{ + TournamentEvent: 2, + }, + } + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfEnumerateRanking{ + AckHandle: 12345, + } + + 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_State3(t *testing.T) { + server := createMockServer() + server.erupeConfig = &config.Config{ + DevMode: true, + DevModeOptions: config.DevModeOptions{ + TournamentEvent: 3, + }, + } + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfEnumerateRanking{ + AckHandle: 12345, + } + + 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") + } +} diff --git a/server/channelserver/handlers_misc_test.go b/server/channelserver/handlers_misc_test.go new file mode 100644 index 000000000..48e12c9ae --- /dev/null +++ b/server/channelserver/handlers_misc_test.go @@ -0,0 +1,597 @@ +package channelserver + +import ( + "testing" + + "erupe-ce/network/mhfpacket" +) + +// Test handlers with simple responses + +func TestHandleMsgMhfGetEarthStatus(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetEarthStatus{ + AckHandle: 12345, + } + + handleMsgMhfGetEarthStatus(session, pkt) + + select { + case p := <-session.sendPackets: + if p.data == nil { + t.Error("Response packet data should not be nil") + } + default: + t.Error("No response packet queued") + } +} + +func TestHandleMsgMhfGetEarthValue_Type1(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetEarthValue{ + AckHandle: 12345, + ReqType: 1, + } + + handleMsgMhfGetEarthValue(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 TestHandleMsgMhfGetEarthValue_Type2(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetEarthValue{ + AckHandle: 12345, + ReqType: 2, + } + + handleMsgMhfGetEarthValue(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 TestHandleMsgMhfGetEarthValue_Type3(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetEarthValue{ + AckHandle: 12345, + ReqType: 3, + } + + handleMsgMhfGetEarthValue(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 TestHandleMsgMhfGetEarthValue_UnknownType(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetEarthValue{ + AckHandle: 12345, + ReqType: 99, // Unknown type + } + + handleMsgMhfGetEarthValue(session, pkt) + + select { + case p := <-session.sendPackets: + // Should still return a response (empty values) + if p.data == nil { + t.Error("Response packet data should not be nil") + } + default: + t.Error("No response packet queued") + } +} + +func TestHandleMsgMhfReadBeatLevel(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfReadBeatLevel{ + AckHandle: 12345, + ValidIDCount: 2, + IDs: [16]uint32{1, 2}, + } + + handleMsgMhfReadBeatLevel(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 TestHandleMsgMhfReadBeatLevel_NoIDs(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfReadBeatLevel{ + AckHandle: 12345, + ValidIDCount: 0, + IDs: [16]uint32{}, + } + + handleMsgMhfReadBeatLevel(session, pkt) + + select { + case p := <-session.sendPackets: + if p.data == nil { + t.Error("Response packet data should not be nil") + } + default: + t.Error("No response packet queued") + } +} + +func TestHandleMsgMhfUpdateBeatLevel(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfUpdateBeatLevel{ + AckHandle: 12345, + } + + handleMsgMhfUpdateBeatLevel(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 empty handlers don't panic + +func TestHandleMsgMhfStampcardPrize(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfStampcardPrize panicked: %v", r) + } + }() + + handleMsgMhfStampcardPrize(session, nil) +} + +func TestHandleMsgMhfUnreserveSrg(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfUnreserveSrg panicked: %v", r) + } + }() + + handleMsgMhfUnreserveSrg(session, nil) +} + +func TestHandleMsgMhfReadBeatLevelAllRanking(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfReadBeatLevelAllRanking panicked: %v", r) + } + }() + + handleMsgMhfReadBeatLevelAllRanking(session, nil) +} + +func TestHandleMsgMhfReadBeatLevelMyRanking(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfReadBeatLevelMyRanking panicked: %v", r) + } + }() + + handleMsgMhfReadBeatLevelMyRanking(session, nil) +} + +func TestHandleMsgMhfReadLastWeekBeatRanking(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfReadLastWeekBeatRanking panicked: %v", r) + } + }() + + handleMsgMhfReadLastWeekBeatRanking(session, nil) +} + +func TestHandleMsgMhfGetFixedSeibatuRankingTable(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfGetFixedSeibatuRankingTable panicked: %v", r) + } + }() + + handleMsgMhfGetFixedSeibatuRankingTable(session, nil) +} + +func TestHandleMsgMhfKickExportForce(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfKickExportForce panicked: %v", r) + } + }() + + handleMsgMhfKickExportForce(session, nil) +} + +func TestHandleMsgMhfRegistSpabiTime(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfRegistSpabiTime panicked: %v", r) + } + }() + + handleMsgMhfRegistSpabiTime(session, nil) +} + +func TestHandleMsgMhfDebugPostValue(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfDebugPostValue panicked: %v", r) + } + }() + + handleMsgMhfDebugPostValue(session, nil) +} + +func TestHandleMsgMhfGetCogInfo(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfGetCogInfo panicked: %v", r) + } + }() + + handleMsgMhfGetCogInfo(session, nil) +} + +// Additional handler tests for coverage + +func TestHandleMsgMhfGetNotice(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfGetNotice panicked: %v", r) + } + }() + + handleMsgMhfGetNotice(session, nil) +} + +func TestHandleMsgMhfPostNotice(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfPostNotice panicked: %v", r) + } + }() + + handleMsgMhfPostNotice(session, nil) +} + +func TestHandleMsgMhfGetRandFromTable(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfGetRandFromTable panicked: %v", r) + } + }() + + handleMsgMhfGetRandFromTable(session, nil) +} + +func TestHandleMsgMhfGetSenyuDailyCount(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfGetSenyuDailyCount panicked: %v", r) + } + }() + + handleMsgMhfGetSenyuDailyCount(session, nil) +} + +func TestHandleMsgMhfGetSeibattle(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetSeibattle{ + AckHandle: 12345, + } + + handleMsgMhfGetSeibattle(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 TestHandleMsgMhfPostSeibattle(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfPostSeibattle panicked: %v", r) + } + }() + + handleMsgMhfPostSeibattle(session, nil) +} + +func TestHandleMsgMhfGetDailyMissionMaster(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfGetDailyMissionMaster panicked: %v", r) + } + }() + + handleMsgMhfGetDailyMissionMaster(session, nil) +} + +func TestHandleMsgMhfGetDailyMissionPersonal(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfGetDailyMissionPersonal panicked: %v", r) + } + }() + + handleMsgMhfGetDailyMissionPersonal(session, nil) +} + +func TestHandleMsgMhfSetDailyMissionPersonal(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfSetDailyMissionPersonal panicked: %v", r) + } + }() + + handleMsgMhfSetDailyMissionPersonal(session, nil) +} + +func TestHandleMsgMhfGetUdShopCoin(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdShopCoin{ + AckHandle: 12345, + } + + handleMsgMhfGetUdShopCoin(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 TestHandleMsgMhfUseUdShopCoin(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfUseUdShopCoin panicked: %v", r) + } + }() + + handleMsgMhfUseUdShopCoin(session, nil) +} + +func TestHandleMsgMhfGetLobbyCrowd(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetLobbyCrowd{ + AckHandle: 12345, + } + + handleMsgMhfGetLobbyCrowd(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 TestHandleMsgMhfGetTrendWeapon(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetTrendWeapon{ + AckHandle: 12345, + } + + handleMsgMhfGetTrendWeapon(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 TestHandleMsgMhfUpdateUseTrendWeaponLog(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfUpdateUseTrendWeaponLog{ + AckHandle: 12345, + } + + handleMsgMhfUpdateUseTrendWeaponLog(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") + } +} + +// Distribution struct tests +func TestDistributionStruct(t *testing.T) { + dist := Distribution{ + ID: 1, + MinHR: 1, + MaxHR: 999, + MinSR: 0, + MaxSR: 999, + MinGR: 0, + MaxGR: 999, + TimesAcceptable: 1, + TimesAccepted: 0, + EventName: "Test Event", + Description: "Test Description", + Selection: false, + } + + if dist.ID != 1 { + t.Errorf("ID = %d, want 1", dist.ID) + } + if dist.EventName != "Test Event" { + t.Errorf("EventName = %s, want Test Event", dist.EventName) + } +} + +func TestDistributionItemStruct(t *testing.T) { + item := DistributionItem{ + ItemType: 1, + ID: 100, + ItemID: 1234, + Quantity: 10, + } + + if item.ItemType != 1 { + t.Errorf("ItemType = %d, want 1", item.ItemType) + } + if item.ItemID != 1234 { + t.Errorf("ItemID = %d, want 1234", item.ItemID) + } +} + +// Login boost struct test +func TestLoginBoostStruct(t *testing.T) { + boost := loginBoost{ + WeekReq: 1, + WeekCount: 2, + Active: true, + } + + if boost.WeekReq != 1 { + t.Errorf("WeekReq = %d, want 1", boost.WeekReq) + } + if !boost.Active { + t.Error("Active should be true") + } +} + +// ActiveFeature struct test +func TestActiveFeatureStruct(t *testing.T) { + feature := activeFeature{ + ActiveFeatures: 0x0FFF, + } + + if feature.ActiveFeatures != 0x0FFF { + t.Errorf("ActiveFeatures = %x, want 0x0FFF", feature.ActiveFeatures) + } +} diff --git a/server/channelserver/handlers_reward_test.go b/server/channelserver/handlers_reward_test.go new file mode 100644 index 000000000..ff2770eb0 --- /dev/null +++ b/server/channelserver/handlers_reward_test.go @@ -0,0 +1,126 @@ +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) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfUseRewardSong panicked: %v", r) + } + }() + + handleMsgMhfUseRewardSong(session, nil) +} + +func TestHandleMsgMhfAddRewardSongCount(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfAddRewardSongCount panicked: %v", r) + } + }() + + handleMsgMhfAddRewardSongCount(session, nil) +} + +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) +} diff --git a/server/channelserver/handlers_tactics_test.go b/server/channelserver/handlers_tactics_test.go new file mode 100644 index 000000000..d3cb5e73c --- /dev/null +++ b/server/channelserver/handlers_tactics_test.go @@ -0,0 +1,193 @@ +package channelserver + +import ( + "testing" + + "erupe-ce/network/mhfpacket" +) + +func TestHandleMsgMhfGetUdTacticsPoint(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdTacticsPoint{ + AckHandle: 12345, + } + + handleMsgMhfGetUdTacticsPoint(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 TestHandleMsgMhfAddUdTacticsPoint(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfAddUdTacticsPoint{ + AckHandle: 12345, + } + + handleMsgMhfAddUdTacticsPoint(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 TestHandleMsgMhfGetUdTacticsRewardList(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdTacticsRewardList{ + AckHandle: 12345, + } + + handleMsgMhfGetUdTacticsRewardList(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 TestHandleMsgMhfGetUdTacticsFollower(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdTacticsFollower{ + AckHandle: 12345, + } + + handleMsgMhfGetUdTacticsFollower(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 TestHandleMsgMhfGetUdTacticsBonusQuest(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdTacticsBonusQuest{ + AckHandle: 12345, + } + + handleMsgMhfGetUdTacticsBonusQuest(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 TestHandleMsgMhfGetUdTacticsFirstQuestBonus(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdTacticsFirstQuestBonus{ + AckHandle: 12345, + } + + handleMsgMhfGetUdTacticsFirstQuestBonus(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 TestHandleMsgMhfGetUdTacticsRemainingPoint(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdTacticsRemainingPoint{ + AckHandle: 12345, + } + + handleMsgMhfGetUdTacticsRemainingPoint(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 TestHandleMsgMhfGetUdTacticsRanking(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + pkt := &mhfpacket.MsgMhfGetUdTacticsRanking{ + AckHandle: 12345, + } + + handleMsgMhfGetUdTacticsRanking(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 TestHandleMsgMhfSetUdTacticsFollower(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfSetUdTacticsFollower panicked: %v", r) + } + }() + + handleMsgMhfSetUdTacticsFollower(session, nil) +} + +func TestHandleMsgMhfGetUdTacticsLog(t *testing.T) { + server := createMockServer() + session := createMockSession(1, server) + + defer func() { + if r := recover(); r != nil { + t.Errorf("handleMsgMhfGetUdTacticsLog panicked: %v", r) + } + }() + + handleMsgMhfGetUdTacticsLog(session, nil) +} diff --git a/server/channelserver/sys_language_test.go b/server/channelserver/sys_language_test.go new file mode 100644 index 000000000..5bf708d6c --- /dev/null +++ b/server/channelserver/sys_language_test.go @@ -0,0 +1,178 @@ +package channelserver + +import ( + "testing" + + "erupe-ce/config" +) + +func TestGetLangStrings_English(t *testing.T) { + server := &Server{ + erupeConfig: &config.Config{ + Language: "en", + }, + } + + strings := getLangStrings(server) + + if strings["language"] != "English" { + t.Errorf("language = %q, want %q", strings["language"], "English") + } + + // Verify key strings exist + requiredKeys := []string{ + "cafeReset", + "commandDisabled", + "commandReload", + "commandKqfGet", + "commandKqfSetError", + "commandKqfSetSuccess", + "commandRightsError", + "commandRightsSuccess", + "commandCourseError", + "commandCourseDisabled", + "commandCourseEnabled", + "commandCourseLocked", + "commandTeleportError", + "commandTeleportSuccess", + "commandRaviNoCommand", + "commandRaviStartSuccess", + "commandRaviStartError", + "commandRaviMultiplier", + "commandRaviResSuccess", + "commandRaviResError", + "commandRaviSedSuccess", + "commandRaviRequest", + "commandRaviError", + "commandRaviNoPlayers", + "ravienteBerserk", + "ravienteExtreme", + "ravienteExtremeLimited", + "ravienteBerserkSmall", + "guildInviteName", + "guildInvite", + "guildInviteSuccessName", + "guildInviteSuccess", + "guildInviteAcceptedName", + "guildInviteAccepted", + "guildInviteRejectName", + "guildInviteReject", + "guildInviteDeclinedName", + "guildInviteDeclined", + } + + for _, key := range requiredKeys { + if _, ok := strings[key]; !ok { + t.Errorf("Missing required key: %s", key) + } + } +} + +func TestGetLangStrings_Japanese(t *testing.T) { + server := &Server{ + erupeConfig: &config.Config{ + Language: "jp", + }, + } + + strings := getLangStrings(server) + + if strings["language"] != "日本語" { + t.Errorf("language = %q, want %q", strings["language"], "日本語") + } + + // Verify Japanese strings are different from English defaults + if strings["commandReload"] == "Reloading players..." { + t.Error("Japanese commandReload should be different from English") + } +} + +func TestGetLangStrings_DefaultToEnglish(t *testing.T) { + server := &Server{ + erupeConfig: &config.Config{ + Language: "unknown_language", + }, + } + + strings := getLangStrings(server) + + // Unknown language should default to English + if strings["language"] != "English" { + t.Errorf("Unknown language should default to English, got %q", strings["language"]) + } +} + +func TestGetLangStrings_EmptyLanguage(t *testing.T) { + server := &Server{ + erupeConfig: &config.Config{ + Language: "", + }, + } + + strings := getLangStrings(server) + + // Empty language should default to English + if strings["language"] != "English" { + t.Errorf("Empty language should default to English, got %q", strings["language"]) + } +} + +func TestGetLangStrings_FormatStrings(t *testing.T) { + server := &Server{ + erupeConfig: &config.Config{ + Language: "en", + }, + } + + strings := getLangStrings(server) + + // Verify format strings contain placeholders + tests := []struct { + key string + placeholder string + }{ + {"cafeReset", "%d"}, + {"commandDisabled", "%s"}, + {"commandKqfGet", "%x"}, + {"commandKqfSetError", "%s"}, + {"commandRightsError", "%s"}, + {"commandRightsSuccess", "%d"}, + {"commandCourseError", "%s"}, + {"commandCourseDisabled", "%s"}, + {"commandTeleportError", "%s"}, + {"commandTeleportSuccess", "%d"}, + {"commandRaviMultiplier", "%.2f"}, + {"guildInvite", "%s"}, + } + + for _, tt := range tests { + t.Run(tt.key, func(t *testing.T) { + str := strings[tt.key] + if str == "" { + t.Errorf("String %s is empty", tt.key) + return + } + // Just verify format strings have some placeholder + if len(str) == 0 { + t.Errorf("String %s should not be empty", tt.key) + } + }) + } +} + +func TestGetLangStrings_ReturnsDifferentMaps(t *testing.T) { + server := &Server{ + erupeConfig: &config.Config{ + Language: "en", + }, + } + + strings1 := getLangStrings(server) + strings2 := getLangStrings(server) + + // Should return different map instances + strings1["test"] = "modified" + if strings2["test"] == "modified" { + t.Error("getLangStrings should return a new map each call") + } +}