diff --git a/config/config_test.go b/config/config_test.go index 1bce54ee2..fcbca1132 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -475,6 +475,37 @@ func TestChannelStruct(t *testing.T) { } } +func TestModeString(t *testing.T) { + tests := []struct { + mode Mode + want string + }{ + {S1, "S1.0"}, + {S15, "S1.5"}, + {S2, "S2.0"}, + {S6, "S6.0"}, + {F1, "FW.1"}, + {F5, "FW.5"}, + {G1, "G1"}, + {G10, "G10"}, + {Z1, "Z1"}, + {Z2, "Z2"}, + {ZZ, "ZZ"}, + {Mode(0), "Unknown"}, + {Mode(-1), "Unknown"}, + {Mode(100), "Unknown"}, + } + + for _, tt := range tests { + t.Run(tt.want, func(t *testing.T) { + got := tt.mode.String() + if got != tt.want { + t.Errorf("Mode(%d).String() = %s, want %s", tt.mode, got, tt.want) + } + }) + } +} + func TestConfigCompleteStructure(t *testing.T) { // Test building a complete config structure cfg := &Config{ diff --git a/network/binpacket/binpacket_test.go b/network/binpacket/binpacket_test.go index c5476a794..0c2728a25 100644 --- a/network/binpacket/binpacket_test.go +++ b/network/binpacket/binpacket_test.go @@ -399,3 +399,32 @@ func TestMsgBinChatAllTypes(t *testing.T) { }) } } + +func TestMsgBinMailNotifyParsePanics(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Error("Parse() should panic with 'implement me'") + } + }() + + m := MsgBinMailNotify{} + bf := byteframe.NewByteFrame() + _ = m.Parse(bf) +} + +func TestMsgBinMailNotifyBuildLongName(t *testing.T) { + m := MsgBinMailNotify{ + SenderName: "ThisIsAVeryLongPlayerNameThatExceeds21Characters", + } + + bf := byteframe.NewByteFrame() + err := m.Build(bf) + if err != nil { + t.Fatalf("Build() error = %v", err) + } + + // Data should still be 22 bytes (1 + 21) + if len(bf.Data()) != 22 { + t.Errorf("Data len = %d, want 22", len(bf.Data())) + } +} diff --git a/network/mhfpacket/msg_comprehensive_test.go b/network/mhfpacket/msg_comprehensive_test.go new file mode 100644 index 000000000..2f989465b --- /dev/null +++ b/network/mhfpacket/msg_comprehensive_test.go @@ -0,0 +1,1152 @@ +package mhfpacket + +import ( + "io" + "testing" + + "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" +) + +// TestAllOpcodesFromOpcode verifies that FromOpcode returns non-nil packets for all known opcodes +func TestAllOpcodesFromOpcode(t *testing.T) { + // All opcodes from opcode_to_packet.go + opcodes := []network.PacketID{ + network.MSG_HEAD, + network.MSG_SYS_reserve01, + network.MSG_SYS_reserve02, + network.MSG_SYS_reserve03, + network.MSG_SYS_reserve04, + network.MSG_SYS_reserve05, + network.MSG_SYS_reserve06, + network.MSG_SYS_reserve07, + network.MSG_SYS_ADD_OBJECT, + network.MSG_SYS_DEL_OBJECT, + network.MSG_SYS_DISP_OBJECT, + network.MSG_SYS_HIDE_OBJECT, + network.MSG_SYS_reserve0C, + network.MSG_SYS_reserve0D, + network.MSG_SYS_reserve0E, + network.MSG_SYS_EXTEND_THRESHOLD, + network.MSG_SYS_END, + network.MSG_SYS_NOP, + network.MSG_SYS_ACK, + network.MSG_SYS_TERMINAL_LOG, + network.MSG_SYS_LOGIN, + network.MSG_SYS_LOGOUT, + network.MSG_SYS_SET_STATUS, + network.MSG_SYS_PING, + network.MSG_SYS_CAST_BINARY, + network.MSG_SYS_HIDE_CLIENT, + network.MSG_SYS_TIME, + network.MSG_SYS_CASTED_BINARY, + network.MSG_SYS_GET_FILE, + network.MSG_SYS_ISSUE_LOGKEY, + network.MSG_SYS_RECORD_LOG, + network.MSG_SYS_ECHO, + network.MSG_SYS_CREATE_STAGE, + network.MSG_SYS_STAGE_DESTRUCT, + network.MSG_SYS_ENTER_STAGE, + network.MSG_SYS_BACK_STAGE, + network.MSG_SYS_MOVE_STAGE, + network.MSG_SYS_LEAVE_STAGE, + network.MSG_SYS_LOCK_STAGE, + network.MSG_SYS_UNLOCK_STAGE, + network.MSG_SYS_RESERVE_STAGE, + network.MSG_SYS_UNRESERVE_STAGE, + network.MSG_SYS_SET_STAGE_PASS, + network.MSG_SYS_WAIT_STAGE_BINARY, + network.MSG_SYS_SET_STAGE_BINARY, + network.MSG_SYS_GET_STAGE_BINARY, + network.MSG_SYS_ENUMERATE_CLIENT, + network.MSG_SYS_ENUMERATE_STAGE, + network.MSG_SYS_CREATE_MUTEX, + network.MSG_SYS_CREATE_OPEN_MUTEX, + network.MSG_SYS_DELETE_MUTEX, + network.MSG_SYS_OPEN_MUTEX, + network.MSG_SYS_CLOSE_MUTEX, + network.MSG_SYS_CREATE_SEMAPHORE, + network.MSG_SYS_CREATE_ACQUIRE_SEMAPHORE, + network.MSG_SYS_DELETE_SEMAPHORE, + network.MSG_SYS_ACQUIRE_SEMAPHORE, + network.MSG_SYS_RELEASE_SEMAPHORE, + network.MSG_SYS_LOCK_GLOBAL_SEMA, + network.MSG_SYS_UNLOCK_GLOBAL_SEMA, + network.MSG_SYS_CHECK_SEMAPHORE, + network.MSG_SYS_OPERATE_REGISTER, + network.MSG_SYS_LOAD_REGISTER, + network.MSG_SYS_NOTIFY_REGISTER, + network.MSG_SYS_CREATE_OBJECT, + network.MSG_SYS_DELETE_OBJECT, + network.MSG_SYS_POSITION_OBJECT, + network.MSG_SYS_ROTATE_OBJECT, + network.MSG_SYS_DUPLICATE_OBJECT, + network.MSG_SYS_SET_OBJECT_BINARY, + network.MSG_SYS_GET_OBJECT_BINARY, + network.MSG_SYS_GET_OBJECT_OWNER, + network.MSG_SYS_UPDATE_OBJECT_BINARY, + network.MSG_SYS_CLEANUP_OBJECT, + network.MSG_SYS_reserve4A, + network.MSG_SYS_reserve4B, + network.MSG_SYS_reserve4C, + network.MSG_SYS_reserve4D, + network.MSG_SYS_reserve4E, + network.MSG_SYS_reserve4F, + network.MSG_SYS_INSERT_USER, + network.MSG_SYS_DELETE_USER, + network.MSG_SYS_SET_USER_BINARY, + network.MSG_SYS_GET_USER_BINARY, + network.MSG_SYS_NOTIFY_USER_BINARY, + network.MSG_SYS_reserve55, + network.MSG_SYS_reserve56, + network.MSG_SYS_reserve57, + network.MSG_SYS_UPDATE_RIGHT, + network.MSG_SYS_AUTH_QUERY, + network.MSG_SYS_AUTH_DATA, + network.MSG_SYS_AUTH_TERMINAL, + network.MSG_SYS_reserve5C, + network.MSG_SYS_RIGHTS_RELOAD, + network.MSG_SYS_reserve5E, + network.MSG_SYS_reserve5F, + network.MSG_MHF_SAVEDATA, + network.MSG_MHF_LOADDATA, + network.MSG_MHF_LIST_MEMBER, + network.MSG_MHF_OPR_MEMBER, + network.MSG_MHF_ENUMERATE_DIST_ITEM, + network.MSG_MHF_APPLY_DIST_ITEM, + network.MSG_MHF_ACQUIRE_DIST_ITEM, + network.MSG_MHF_GET_DIST_DESCRIPTION, + network.MSG_MHF_SEND_MAIL, + network.MSG_MHF_READ_MAIL, + network.MSG_MHF_LIST_MAIL, + network.MSG_MHF_OPRT_MAIL, + network.MSG_MHF_LOAD_FAVORITE_QUEST, + network.MSG_MHF_SAVE_FAVORITE_QUEST, + network.MSG_MHF_REGISTER_EVENT, + network.MSG_MHF_RELEASE_EVENT, + network.MSG_MHF_TRANSIT_MESSAGE, + network.MSG_SYS_reserve71, + network.MSG_SYS_reserve72, + network.MSG_SYS_reserve73, + network.MSG_SYS_reserve74, + network.MSG_SYS_reserve75, + network.MSG_SYS_reserve76, + network.MSG_SYS_reserve77, + network.MSG_SYS_reserve78, + network.MSG_SYS_reserve79, + network.MSG_SYS_reserve7A, + network.MSG_SYS_reserve7B, + network.MSG_SYS_reserve7C, + network.MSG_CA_EXCHANGE_ITEM, + network.MSG_SYS_reserve7E, + network.MSG_MHF_PRESENT_BOX, + network.MSG_MHF_SERVER_COMMAND, + network.MSG_MHF_SHUT_CLIENT, + network.MSG_MHF_ANNOUNCE, + network.MSG_MHF_SET_LOGINWINDOW, + network.MSG_SYS_TRANS_BINARY, + network.MSG_SYS_COLLECT_BINARY, + network.MSG_SYS_GET_STATE, + network.MSG_SYS_SERIALIZE, + network.MSG_SYS_ENUMLOBBY, + network.MSG_SYS_ENUMUSER, + network.MSG_SYS_INFOKYSERVER, + network.MSG_MHF_GET_CA_UNIQUE_ID, + network.MSG_MHF_SET_CA_ACHIEVEMENT, + network.MSG_MHF_CARAVAN_MY_SCORE, + network.MSG_MHF_CARAVAN_RANKING, + network.MSG_MHF_CARAVAN_MY_RANK, + network.MSG_MHF_CREATE_GUILD, + network.MSG_MHF_OPERATE_GUILD, + network.MSG_MHF_OPERATE_GUILD_MEMBER, + network.MSG_MHF_INFO_GUILD, + network.MSG_MHF_ENUMERATE_GUILD, + network.MSG_MHF_UPDATE_GUILD, + network.MSG_MHF_ARRANGE_GUILD_MEMBER, + network.MSG_MHF_ENUMERATE_GUILD_MEMBER, + network.MSG_MHF_ENUMERATE_CAMPAIGN, + network.MSG_MHF_STATE_CAMPAIGN, + network.MSG_MHF_APPLY_CAMPAIGN, + network.MSG_MHF_ENUMERATE_ITEM, + network.MSG_MHF_ACQUIRE_ITEM, + network.MSG_MHF_TRANSFER_ITEM, + network.MSG_MHF_MERCENARY_HUNTDATA, + network.MSG_MHF_ENTRY_ROOKIE_GUILD, + network.MSG_MHF_ENUMERATE_QUEST, + network.MSG_MHF_ENUMERATE_EVENT, + network.MSG_MHF_ENUMERATE_PRICE, + network.MSG_MHF_ENUMERATE_RANKING, + network.MSG_MHF_ENUMERATE_ORDER, + network.MSG_MHF_ENUMERATE_SHOP, + network.MSG_MHF_GET_EXTRA_INFO, + network.MSG_MHF_UPDATE_INTERIOR, + network.MSG_MHF_ENUMERATE_HOUSE, + network.MSG_MHF_UPDATE_HOUSE, + network.MSG_MHF_LOAD_HOUSE, + network.MSG_MHF_OPERATE_WAREHOUSE, + network.MSG_MHF_ENUMERATE_WAREHOUSE, + network.MSG_MHF_UPDATE_WAREHOUSE, + network.MSG_MHF_ACQUIRE_TITLE, + network.MSG_MHF_ENUMERATE_TITLE, + network.MSG_MHF_ENUMERATE_GUILD_ITEM, + network.MSG_MHF_UPDATE_GUILD_ITEM, + network.MSG_MHF_ENUMERATE_UNION_ITEM, + network.MSG_MHF_UPDATE_UNION_ITEM, + network.MSG_MHF_CREATE_JOINT, + network.MSG_MHF_OPERATE_JOINT, + network.MSG_MHF_INFO_JOINT, + network.MSG_MHF_UPDATE_GUILD_ICON, + network.MSG_MHF_INFO_FESTA, + network.MSG_MHF_ENTRY_FESTA, + network.MSG_MHF_CHARGE_FESTA, + network.MSG_MHF_ACQUIRE_FESTA, + network.MSG_MHF_STATE_FESTA_U, + network.MSG_MHF_STATE_FESTA_G, + network.MSG_MHF_ENUMERATE_FESTA_MEMBER, + network.MSG_MHF_VOTE_FESTA, + network.MSG_MHF_ACQUIRE_CAFE_ITEM, + network.MSG_MHF_UPDATE_CAFEPOINT, + network.MSG_MHF_CHECK_DAILY_CAFEPOINT, + network.MSG_MHF_GET_COG_INFO, + network.MSG_MHF_CHECK_MONTHLY_ITEM, + network.MSG_MHF_ACQUIRE_MONTHLY_ITEM, + network.MSG_MHF_CHECK_WEEKLY_STAMP, + network.MSG_MHF_EXCHANGE_WEEKLY_STAMP, + network.MSG_MHF_CREATE_MERCENARY, + network.MSG_MHF_SAVE_MERCENARY, + network.MSG_MHF_READ_MERCENARY_W, + network.MSG_MHF_READ_MERCENARY_M, + network.MSG_MHF_CONTRACT_MERCENARY, + network.MSG_MHF_ENUMERATE_MERCENARY_LOG, + network.MSG_MHF_ENUMERATE_GUACOT, + network.MSG_MHF_UPDATE_GUACOT, + network.MSG_MHF_INFO_TOURNAMENT, + network.MSG_MHF_ENTRY_TOURNAMENT, + network.MSG_MHF_ENTER_TOURNAMENT_QUEST, + network.MSG_MHF_ACQUIRE_TOURNAMENT, + network.MSG_MHF_GET_ACHIEVEMENT, + network.MSG_MHF_RESET_ACHIEVEMENT, + network.MSG_MHF_ADD_ACHIEVEMENT, + network.MSG_MHF_PAYMENT_ACHIEVEMENT, + network.MSG_MHF_DISPLAYED_ACHIEVEMENT, + network.MSG_MHF_INFO_SCENARIO_COUNTER, + network.MSG_MHF_SAVE_SCENARIO_DATA, + network.MSG_MHF_LOAD_SCENARIO_DATA, + network.MSG_MHF_GET_BBS_SNS_STATUS, + network.MSG_MHF_APPLY_BBS_ARTICLE, + network.MSG_MHF_GET_ETC_POINTS, + network.MSG_MHF_UPDATE_ETC_POINT, + network.MSG_MHF_GET_MYHOUSE_INFO, + network.MSG_MHF_UPDATE_MYHOUSE_INFO, + network.MSG_MHF_GET_WEEKLY_SCHEDULE, + network.MSG_MHF_ENUMERATE_INV_GUILD, + network.MSG_MHF_OPERATION_INV_GUILD, + network.MSG_MHF_STAMPCARD_STAMP, + network.MSG_MHF_STAMPCARD_PRIZE, + network.MSG_MHF_UNRESERVE_SRG, + network.MSG_MHF_LOAD_PLATE_DATA, + network.MSG_MHF_SAVE_PLATE_DATA, + network.MSG_MHF_LOAD_PLATE_BOX, + network.MSG_MHF_SAVE_PLATE_BOX, + network.MSG_MHF_READ_GUILDCARD, + network.MSG_MHF_UPDATE_GUILDCARD, + network.MSG_MHF_READ_BEAT_LEVEL, + network.MSG_MHF_UPDATE_BEAT_LEVEL, + network.MSG_MHF_READ_BEAT_LEVEL_ALL_RANKING, + network.MSG_MHF_READ_BEAT_LEVEL_MY_RANKING, + network.MSG_MHF_READ_LAST_WEEK_BEAT_RANKING, + network.MSG_MHF_ACCEPT_READ_REWARD, + network.MSG_MHF_GET_ADDITIONAL_BEAT_REWARD, + network.MSG_MHF_GET_FIXED_SEIBATU_RANKING_TABLE, + network.MSG_MHF_GET_BBS_USER_STATUS, + network.MSG_MHF_KICK_EXPORT_FORCE, + network.MSG_MHF_GET_BREAK_SEIBATU_LEVEL_REWARD, + network.MSG_MHF_GET_WEEKLY_SEIBATU_RANKING_REWARD, + network.MSG_MHF_GET_EARTH_STATUS, + network.MSG_MHF_LOAD_PARTNER, + network.MSG_MHF_SAVE_PARTNER, + network.MSG_MHF_GET_GUILD_MISSION_LIST, + network.MSG_MHF_GET_GUILD_MISSION_RECORD, + network.MSG_MHF_ADD_GUILD_MISSION_COUNT, + network.MSG_MHF_SET_GUILD_MISSION_TARGET, + network.MSG_MHF_CANCEL_GUILD_MISSION_TARGET, + network.MSG_MHF_LOAD_OTOMO_AIROU, + network.MSG_MHF_SAVE_OTOMO_AIROU, + network.MSG_MHF_ENUMERATE_GUILD_TRESURE, + network.MSG_MHF_ENUMERATE_AIROULIST, + network.MSG_MHF_REGIST_GUILD_TRESURE, + network.MSG_MHF_ACQUIRE_GUILD_TRESURE, + network.MSG_MHF_OPERATE_GUILD_TRESURE_REPORT, + network.MSG_MHF_GET_GUILD_TRESURE_SOUVENIR, + network.MSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIR, + network.MSG_MHF_ENUMERATE_FESTA_INTERMEDIATE_PRIZE, + network.MSG_MHF_ACQUIRE_FESTA_INTERMEDIATE_PRIZE, + network.MSG_MHF_LOAD_DECO_MYSET, + network.MSG_MHF_SAVE_DECO_MYSET, + network.MSG_MHF_reserve10F, + network.MSG_MHF_LOAD_GUILD_COOKING, + network.MSG_MHF_REGIST_GUILD_COOKING, + network.MSG_MHF_LOAD_GUILD_ADVENTURE, + network.MSG_MHF_REGIST_GUILD_ADVENTURE, + network.MSG_MHF_ACQUIRE_GUILD_ADVENTURE, + network.MSG_MHF_CHARGE_GUILD_ADVENTURE, + network.MSG_MHF_LOAD_LEGEND_DISPATCH, + network.MSG_MHF_LOAD_HUNTER_NAVI, + network.MSG_MHF_SAVE_HUNTER_NAVI, + network.MSG_MHF_REGIST_SPABI_TIME, + network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTER, + network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNT, + network.MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER, + network.MSG_MHF_GET_TOWER_INFO, + network.MSG_MHF_POST_TOWER_INFO, + network.MSG_MHF_GET_GEM_INFO, + network.MSG_MHF_POST_GEM_INFO, + network.MSG_MHF_GET_EARTH_VALUE, + network.MSG_MHF_DEBUG_POST_VALUE, + network.MSG_MHF_GET_PAPER_DATA, + network.MSG_MHF_GET_NOTICE, + network.MSG_MHF_POST_NOTICE, + network.MSG_MHF_GET_BOOST_TIME, + network.MSG_MHF_POST_BOOST_TIME, + network.MSG_MHF_GET_BOOST_TIME_LIMIT, + network.MSG_MHF_POST_BOOST_TIME_LIMIT, + network.MSG_MHF_ENUMERATE_FESTA_PERSONAL_PRIZE, + network.MSG_MHF_ACQUIRE_FESTA_PERSONAL_PRIZE, + network.MSG_MHF_GET_RAND_FROM_TABLE, + network.MSG_MHF_GET_CAFE_DURATION, + network.MSG_MHF_GET_CAFE_DURATION_BONUS_INFO, + network.MSG_MHF_RECEIVE_CAFE_DURATION_BONUS, + network.MSG_MHF_POST_CAFE_DURATION_BONUS_RECEIVED, + network.MSG_MHF_GET_GACHA_POINT, + network.MSG_MHF_USE_GACHA_POINT, + network.MSG_MHF_EXCHANGE_FPOINT_2_ITEM, + network.MSG_MHF_EXCHANGE_ITEM_2_FPOINT, + network.MSG_MHF_GET_FPOINT_EXCHANGE_LIST, + network.MSG_MHF_PLAY_STEPUP_GACHA, + network.MSG_MHF_RECEIVE_GACHA_ITEM, + network.MSG_MHF_GET_STEPUP_STATUS, + network.MSG_MHF_PLAY_FREE_GACHA, + network.MSG_MHF_GET_TINY_BIN, + network.MSG_MHF_POST_TINY_BIN, + network.MSG_MHF_GET_SENYU_DAILY_COUNT, + network.MSG_MHF_GET_GUILD_TARGET_MEMBER_NUM, + network.MSG_MHF_GET_BOOST_RIGHT, + network.MSG_MHF_START_BOOST_TIME, + network.MSG_MHF_POST_BOOST_TIME_QUEST_RETURN, + network.MSG_MHF_GET_BOX_GACHA_INFO, + network.MSG_MHF_PLAY_BOX_GACHA, + network.MSG_MHF_RESET_BOX_GACHA_INFO, + network.MSG_MHF_GET_SEIBATTLE, + network.MSG_MHF_POST_SEIBATTLE, + network.MSG_MHF_GET_RYOUDAMA, + network.MSG_MHF_POST_RYOUDAMA, + network.MSG_MHF_GET_TENROUIRAI, + network.MSG_MHF_POST_TENROUIRAI, + network.MSG_MHF_POST_GUILD_SCOUT, + network.MSG_MHF_CANCEL_GUILD_SCOUT, + network.MSG_MHF_ANSWER_GUILD_SCOUT, + network.MSG_MHF_GET_GUILD_SCOUT_LIST, + network.MSG_MHF_GET_GUILD_MANAGE_RIGHT, + network.MSG_MHF_SET_GUILD_MANAGE_RIGHT, + network.MSG_MHF_PLAY_NORMAL_GACHA, + network.MSG_MHF_GET_DAILY_MISSION_MASTER, + network.MSG_MHF_GET_DAILY_MISSION_PERSONAL, + network.MSG_MHF_SET_DAILY_MISSION_PERSONAL, + network.MSG_MHF_GET_GACHA_PLAY_HISTORY, + network.MSG_MHF_GET_REJECT_GUILD_SCOUT, + network.MSG_MHF_SET_REJECT_GUILD_SCOUT, + network.MSG_MHF_GET_CA_ACHIEVEMENT_HIST, + network.MSG_MHF_SET_CA_ACHIEVEMENT_HIST, + network.MSG_MHF_GET_KEEP_LOGIN_BOOST_STATUS, + network.MSG_MHF_USE_KEEP_LOGIN_BOOST, + network.MSG_MHF_GET_UD_SCHEDULE, + network.MSG_MHF_GET_UD_INFO, + network.MSG_MHF_GET_KIJU_INFO, + network.MSG_MHF_SET_KIJU, + network.MSG_MHF_ADD_UD_POINT, + network.MSG_MHF_GET_UD_MY_POINT, + network.MSG_MHF_GET_UD_TOTAL_POINT_INFO, + network.MSG_MHF_GET_UD_BONUS_QUEST_INFO, + network.MSG_MHF_GET_UD_SELECTED_COLOR_INFO, + network.MSG_MHF_GET_UD_MONSTER_POINT, + network.MSG_MHF_GET_UD_DAILY_PRESENT_LIST, + network.MSG_MHF_GET_UD_NORMA_PRESENT_LIST, + network.MSG_MHF_GET_UD_RANKING_REWARD_LIST, + network.MSG_MHF_ACQUIRE_UD_ITEM, + network.MSG_MHF_GET_REWARD_SONG, + network.MSG_MHF_USE_REWARD_SONG, + network.MSG_MHF_ADD_REWARD_SONG_COUNT, + network.MSG_MHF_GET_UD_RANKING, + network.MSG_MHF_GET_UD_MY_RANKING, + network.MSG_MHF_ACQUIRE_MONTHLY_REWARD, + network.MSG_MHF_GET_UD_GUILD_MAP_INFO, + network.MSG_MHF_GENERATE_UD_GUILD_MAP, + network.MSG_MHF_GET_UD_TACTICS_POINT, + network.MSG_MHF_ADD_UD_TACTICS_POINT, + network.MSG_MHF_GET_UD_TACTICS_RANKING, + network.MSG_MHF_GET_UD_TACTICS_REWARD_LIST, + network.MSG_MHF_GET_UD_TACTICS_LOG, + network.MSG_MHF_GET_EQUIP_SKIN_HIST, + network.MSG_MHF_UPDATE_EQUIP_SKIN_HIST, + network.MSG_MHF_GET_UD_TACTICS_FOLLOWER, + network.MSG_MHF_SET_UD_TACTICS_FOLLOWER, + network.MSG_MHF_GET_UD_SHOP_COIN, + network.MSG_MHF_USE_UD_SHOP_COIN, + network.MSG_MHF_GET_ENHANCED_MINIDATA, + network.MSG_MHF_SET_ENHANCED_MINIDATA, + network.MSG_MHF_SEX_CHANGER, + network.MSG_MHF_GET_LOBBY_CROWD, + network.MSG_SYS_reserve180, + network.MSG_MHF_GUILD_HUNTDATA, + network.MSG_MHF_ADD_KOURYOU_POINT, + network.MSG_MHF_GET_KOURYOU_POINT, + network.MSG_MHF_EXCHANGE_KOURYOU_POINT, + network.MSG_MHF_GET_UD_TACTICS_BONUS_QUEST, + network.MSG_MHF_GET_UD_TACTICS_FIRST_QUEST_BONUS, + network.MSG_MHF_GET_UD_TACTICS_REMAINING_POINT, + network.MSG_SYS_reserve188, + network.MSG_MHF_LOAD_PLATE_MYSET, + network.MSG_MHF_SAVE_PLATE_MYSET, + network.MSG_SYS_reserve18B, + network.MSG_MHF_GET_RESTRICTION_EVENT, + network.MSG_MHF_SET_RESTRICTION_EVENT, + network.MSG_SYS_reserve18E, + network.MSG_SYS_reserve18F, + network.MSG_MHF_GET_TREND_WEAPON, + network.MSG_MHF_UPDATE_USE_TREND_WEAPON_LOG, + network.MSG_SYS_reserve192, + network.MSG_SYS_reserve193, + network.MSG_SYS_reserve194, + network.MSG_MHF_SAVE_RENGOKU_DATA, + network.MSG_MHF_LOAD_RENGOKU_DATA, + network.MSG_MHF_GET_RENGOKU_BINARY, + network.MSG_MHF_ENUMERATE_RENGOKU_RANKING, + network.MSG_MHF_GET_RENGOKU_RANKING_RANK, + network.MSG_MHF_ACQUIRE_EXCHANGE_SHOP, + network.MSG_SYS_reserve19B, + network.MSG_MHF_SAVE_MEZFES_DATA, + network.MSG_MHF_LOAD_MEZFES_DATA, + network.MSG_SYS_reserve19E, + network.MSG_SYS_reserve19F, + network.MSG_MHF_UPDATE_FORCE_GUILD_RANK, + network.MSG_MHF_RESET_TITLE, + network.MSG_MHF_ENUMERATE_GUILD_MESSAGE_BOARD, + network.MSG_MHF_UPDATE_GUILD_MESSAGE_BOARD, + network.MSG_SYS_reserve1A4, + network.MSG_MHF_REGIST_GUILD_ADVENTURE_DIVA, + network.MSG_SYS_reserve1A6, + network.MSG_SYS_reserve1A7, + network.MSG_SYS_reserve1A8, + network.MSG_SYS_reserve1A9, + network.MSG_SYS_reserve1AA, + network.MSG_SYS_reserve1AB, + network.MSG_SYS_reserve1AC, + network.MSG_SYS_reserve1AD, + network.MSG_SYS_reserve1AE, + network.MSG_SYS_reserve1AF, + } + + for _, opcode := range opcodes { + t.Run(opcode.String(), func(t *testing.T) { + pkt := FromOpcode(opcode) + if pkt == nil { + t.Errorf("FromOpcode(%s) returned nil", opcode) + return + } + // Verify Opcode() returns the correct value + if pkt.Opcode() != opcode { + t.Errorf("Opcode() = %s, want %s", pkt.Opcode(), opcode) + } + }) + } +} + +// TestAckHandlePacketsParse tests parsing of packets with simple AckHandle uint32 field +func TestAckHandlePacketsParse(t *testing.T) { + testCases := []struct { + name string + opcode network.PacketID + }{ + {"MsgMhfGetAchievement", network.MSG_MHF_GET_ACHIEVEMENT}, + {"MsgMhfGetTowerInfo", network.MSG_MHF_GET_TOWER_INFO}, + {"MsgMhfGetGemInfo", network.MSG_MHF_GET_GEM_INFO}, + {"MsgMhfGetBoostTime", network.MSG_MHF_GET_BOOST_TIME}, + {"MsgMhfGetCafeDuration", network.MSG_MHF_GET_CAFE_DURATION}, + {"MsgMhfGetGachaPoint", network.MSG_MHF_GET_GACHA_POINT}, + {"MsgMhfLoadPartner", network.MSG_MHF_LOAD_PARTNER}, + {"MsgMhfLoadOtomoAirou", network.MSG_MHF_LOAD_OTOMO_AIROU}, + {"MsgMhfLoadPlateData", network.MSG_MHF_LOAD_PLATE_DATA}, + {"MsgMhfLoadPlateBox", network.MSG_MHF_LOAD_PLATE_BOX}, + {"MsgMhfLoadDecoMyset", network.MSG_MHF_LOAD_DECO_MYSET}, + {"MsgMhfLoadGuildCooking", network.MSG_MHF_LOAD_GUILD_COOKING}, + {"MsgMhfLoadGuildAdventure", network.MSG_MHF_LOAD_GUILD_ADVENTURE}, + {"MsgMhfLoadHunterNavi", network.MSG_MHF_LOAD_HUNTER_NAVI}, + {"MsgMhfInfoFesta", network.MSG_MHF_INFO_FESTA}, + {"MsgMhfInfoTournament", network.MSG_MHF_INFO_TOURNAMENT}, + {"MsgMhfEnumerateQuest", network.MSG_MHF_ENUMERATE_QUEST}, + {"MsgMhfEnumerateEvent", network.MSG_MHF_ENUMERATE_EVENT}, + {"MsgMhfEnumerateShop", network.MSG_MHF_ENUMERATE_SHOP}, + {"MsgMhfEnumerateRanking", network.MSG_MHF_ENUMERATE_RANKING}, + {"MsgMhfEnumerateOrder", network.MSG_MHF_ENUMERATE_ORDER}, + {"MsgMhfEnumerateCampaign", network.MSG_MHF_ENUMERATE_CAMPAIGN}, + {"MsgMhfGetWeeklySchedule", network.MSG_MHF_GET_WEEKLY_SCHEDULE}, + {"MsgMhfGetUdSchedule", network.MSG_MHF_GET_UD_SCHEDULE}, + {"MsgMhfGetUdInfo", network.MSG_MHF_GET_UD_INFO}, + {"MsgMhfGetKijuInfo", network.MSG_MHF_GET_KIJU_INFO}, + } + + ctx := &clientctx.ClientContext{} + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + pkt := FromOpcode(tc.opcode) + if pkt == nil { + t.Skipf("FromOpcode(%s) returned nil", tc.opcode) + return + } + + // Create test data - most of these packets read AckHandle + additional data + bf := byteframe.NewByteFrame() + bf.WriteUint32(0x12345678) // AckHandle + // Write extra padding bytes for packets that expect more data + for i := 0; i < 32; i++ { + bf.WriteUint32(uint32(i)) + } + bf.Seek(0, io.SeekStart) + + // Parse should not panic + err := pkt.Parse(bf, ctx) + if err != nil { + t.Logf("Parse() returned error (may be expected): %v", err) + } + }) + } +} + +// TestAddAchievementParse tests MsgMhfAddAchievement Parse +func TestAddAchievementParse(t *testing.T) { + tests := []struct { + name string + achievementID uint8 + unk1 uint16 + unk2 uint16 + }{ + {"typical values", 1, 100, 200}, + {"zero values", 0, 0, 0}, + {"max values", 255, 65535, 65535}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bf := byteframe.NewByteFrame() + bf.WriteUint8(tt.achievementID) + bf.WriteUint16(tt.unk1) + bf.WriteUint16(tt.unk2) + bf.Seek(0, io.SeekStart) + + pkt := &MsgMhfAddAchievement{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.AchievementID != tt.achievementID { + t.Errorf("AchievementID = %d, want %d", pkt.AchievementID, tt.achievementID) + } + if pkt.Unk1 != tt.unk1 { + t.Errorf("Unk1 = %d, want %d", pkt.Unk1, tt.unk1) + } + if pkt.Unk2 != tt.unk2 { + t.Errorf("Unk2 = %d, want %d", pkt.Unk2, tt.unk2) + } + }) + } +} + +// TestGetAchievementParse tests MsgMhfGetAchievement Parse +func TestGetAchievementParse(t *testing.T) { + tests := []struct { + name string + ackHandle uint32 + charID uint32 + unk1 uint32 + }{ + {"typical values", 1, 12345, 0}, + {"large values", 0xFFFFFFFF, 0xDEADBEEF, 0xCAFEBABE}, + {"zero values", 0, 0, 0}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bf := byteframe.NewByteFrame() + bf.WriteUint32(tt.ackHandle) + bf.WriteUint32(tt.charID) + bf.WriteUint32(tt.unk1) + bf.Seek(0, io.SeekStart) + + pkt := &MsgMhfGetAchievement{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.AckHandle != tt.ackHandle { + t.Errorf("AckHandle = %d, want %d", pkt.AckHandle, tt.ackHandle) + } + if pkt.CharID != tt.charID { + t.Errorf("CharID = %d, want %d", pkt.CharID, tt.charID) + } + if pkt.Unk1 != tt.unk1 { + t.Errorf("Unk1 = %d, want %d", pkt.Unk1, tt.unk1) + } + }) + } +} + +// TestBuildNotImplemented tests that Build returns error for packets without implementation +func TestBuildNotImplemented(t *testing.T) { + packetsToTest := []MHFPacket{ + &MsgMhfAddAchievement{}, + &MsgMhfGetAchievement{}, + &MsgMhfAcquireItem{}, + &MsgMhfEnumerateGuild{}, + &MsgMhfInfoGuild{}, + &MsgMhfCreateGuild{}, + &MsgMhfOperateGuild{}, + &MsgMhfOperateGuildMember{}, + &MsgMhfUpdateGuild{}, + &MsgMhfArrangeGuildMember{}, + &MsgMhfEnumerateGuildMember{}, + &MsgMhfInfoFesta{}, + &MsgMhfEntryFesta{}, + &MsgMhfChargeFesta{}, + &MsgMhfAcquireFesta{}, + &MsgMhfVoteFesta{}, + &MsgMhfInfoTournament{}, + &MsgMhfEntryTournament{}, + &MsgMhfAcquireTournament{}, + } + + for _, pkt := range packetsToTest { + t.Run(pkt.Opcode().String(), func(t *testing.T) { + bf := byteframe.NewByteFrame() + err := pkt.Build(bf, &clientctx.ClientContext{}) + if err == nil { + t.Logf("Build() did not return error (implementation may exist)") + } else { + // Expected - Build is not implemented + if err.Error() != "NOT IMPLEMENTED" { + t.Logf("Build() returned unexpected error: %v", err) + } + } + }) + } +} + +// TestReservePacketsOpcode tests that reserve packets have correct opcodes +func TestReservePacketsOpcode(t *testing.T) { + reservePackets := []struct { + opcode network.PacketID + }{ + {network.MSG_SYS_reserve01}, + {network.MSG_SYS_reserve02}, + {network.MSG_SYS_reserve03}, + {network.MSG_SYS_reserve04}, + {network.MSG_SYS_reserve05}, + {network.MSG_SYS_reserve06}, + {network.MSG_SYS_reserve07}, + {network.MSG_SYS_reserve0C}, + {network.MSG_SYS_reserve0D}, + {network.MSG_SYS_reserve0E}, + {network.MSG_SYS_reserve4A}, + {network.MSG_SYS_reserve4B}, + {network.MSG_SYS_reserve4C}, + {network.MSG_SYS_reserve4D}, + {network.MSG_SYS_reserve4E}, + {network.MSG_SYS_reserve4F}, + {network.MSG_SYS_reserve55}, + {network.MSG_SYS_reserve56}, + {network.MSG_SYS_reserve57}, + {network.MSG_SYS_reserve5C}, + {network.MSG_SYS_reserve5E}, + {network.MSG_SYS_reserve5F}, + {network.MSG_SYS_reserve71}, + {network.MSG_SYS_reserve72}, + {network.MSG_SYS_reserve73}, + {network.MSG_SYS_reserve74}, + {network.MSG_SYS_reserve75}, + {network.MSG_SYS_reserve76}, + {network.MSG_SYS_reserve77}, + {network.MSG_SYS_reserve78}, + {network.MSG_SYS_reserve79}, + {network.MSG_SYS_reserve7A}, + {network.MSG_SYS_reserve7B}, + {network.MSG_SYS_reserve7C}, + {network.MSG_SYS_reserve7E}, + {network.MSG_SYS_reserve180}, + {network.MSG_SYS_reserve188}, + {network.MSG_SYS_reserve18B}, + {network.MSG_SYS_reserve18E}, + {network.MSG_SYS_reserve18F}, + {network.MSG_SYS_reserve192}, + {network.MSG_SYS_reserve193}, + {network.MSG_SYS_reserve194}, + {network.MSG_SYS_reserve19B}, + {network.MSG_SYS_reserve19E}, + {network.MSG_SYS_reserve19F}, + {network.MSG_SYS_reserve1A4}, + {network.MSG_SYS_reserve1A6}, + {network.MSG_SYS_reserve1A7}, + {network.MSG_SYS_reserve1A8}, + {network.MSG_SYS_reserve1A9}, + {network.MSG_SYS_reserve1AA}, + {network.MSG_SYS_reserve1AB}, + {network.MSG_SYS_reserve1AC}, + {network.MSG_SYS_reserve1AD}, + {network.MSG_SYS_reserve1AE}, + {network.MSG_SYS_reserve1AF}, + } + + for _, tc := range reservePackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + pkt := FromOpcode(tc.opcode) + if pkt == nil { + t.Errorf("FromOpcode(%s) returned nil", tc.opcode) + return + } + if pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestMHFPacketsOpcode tests Opcode() method for various MHF packets +func TestMHFPacketsOpcode(t *testing.T) { + mhfPackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfSavedata{}, network.MSG_MHF_SAVEDATA}, + {&MsgMhfLoaddata{}, network.MSG_MHF_LOADDATA}, + {&MsgMhfListMember{}, network.MSG_MHF_LIST_MEMBER}, + {&MsgMhfOprMember{}, network.MSG_MHF_OPR_MEMBER}, + {&MsgMhfEnumerateDistItem{}, network.MSG_MHF_ENUMERATE_DIST_ITEM}, + {&MsgMhfApplyDistItem{}, network.MSG_MHF_APPLY_DIST_ITEM}, + {&MsgMhfAcquireDistItem{}, network.MSG_MHF_ACQUIRE_DIST_ITEM}, + {&MsgMhfGetDistDescription{}, network.MSG_MHF_GET_DIST_DESCRIPTION}, + {&MsgMhfSendMail{}, network.MSG_MHF_SEND_MAIL}, + {&MsgMhfReadMail{}, network.MSG_MHF_READ_MAIL}, + {&MsgMhfListMail{}, network.MSG_MHF_LIST_MAIL}, + {&MsgMhfOprtMail{}, network.MSG_MHF_OPRT_MAIL}, + {&MsgMhfLoadFavoriteQuest{}, network.MSG_MHF_LOAD_FAVORITE_QUEST}, + {&MsgMhfSaveFavoriteQuest{}, network.MSG_MHF_SAVE_FAVORITE_QUEST}, + {&MsgMhfRegisterEvent{}, network.MSG_MHF_REGISTER_EVENT}, + {&MsgMhfReleaseEvent{}, network.MSG_MHF_RELEASE_EVENT}, + {&MsgMhfTransitMessage{}, network.MSG_MHF_TRANSIT_MESSAGE}, + {&MsgMhfPresentBox{}, network.MSG_MHF_PRESENT_BOX}, + {&MsgMhfServerCommand{}, network.MSG_MHF_SERVER_COMMAND}, + {&MsgMhfShutClient{}, network.MSG_MHF_SHUT_CLIENT}, + {&MsgMhfAnnounce{}, network.MSG_MHF_ANNOUNCE}, + {&MsgMhfSetLoginwindow{}, network.MSG_MHF_SET_LOGINWINDOW}, + {&MsgMhfGetCaUniqueID{}, network.MSG_MHF_GET_CA_UNIQUE_ID}, + {&MsgMhfSetCaAchievement{}, network.MSG_MHF_SET_CA_ACHIEVEMENT}, + {&MsgMhfCaravanMyScore{}, network.MSG_MHF_CARAVAN_MY_SCORE}, + {&MsgMhfCaravanRanking{}, network.MSG_MHF_CARAVAN_RANKING}, + {&MsgMhfCaravanMyRank{}, network.MSG_MHF_CARAVAN_MY_RANK}, + } + + for _, tc := range mhfPackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestGuildPacketsOpcode tests guild-related packets +func TestGuildPacketsOpcode(t *testing.T) { + guildPackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfCreateGuild{}, network.MSG_MHF_CREATE_GUILD}, + {&MsgMhfOperateGuild{}, network.MSG_MHF_OPERATE_GUILD}, + {&MsgMhfOperateGuildMember{}, network.MSG_MHF_OPERATE_GUILD_MEMBER}, + {&MsgMhfInfoGuild{}, network.MSG_MHF_INFO_GUILD}, + {&MsgMhfEnumerateGuild{}, network.MSG_MHF_ENUMERATE_GUILD}, + {&MsgMhfUpdateGuild{}, network.MSG_MHF_UPDATE_GUILD}, + {&MsgMhfArrangeGuildMember{}, network.MSG_MHF_ARRANGE_GUILD_MEMBER}, + {&MsgMhfEnumerateGuildMember{}, network.MSG_MHF_ENUMERATE_GUILD_MEMBER}, + {&MsgMhfEnumerateGuildItem{}, network.MSG_MHF_ENUMERATE_GUILD_ITEM}, + {&MsgMhfUpdateGuildItem{}, network.MSG_MHF_UPDATE_GUILD_ITEM}, + {&MsgMhfUpdateGuildIcon{}, network.MSG_MHF_UPDATE_GUILD_ICON}, + {&MsgMhfEnumerateGuildTresure{}, network.MSG_MHF_ENUMERATE_GUILD_TRESURE}, + {&MsgMhfRegistGuildTresure{}, network.MSG_MHF_REGIST_GUILD_TRESURE}, + {&MsgMhfAcquireGuildTresure{}, network.MSG_MHF_ACQUIRE_GUILD_TRESURE}, + {&MsgMhfOperateGuildTresureReport{}, network.MSG_MHF_OPERATE_GUILD_TRESURE_REPORT}, + {&MsgMhfGetGuildTresureSouvenir{}, network.MSG_MHF_GET_GUILD_TRESURE_SOUVENIR}, + {&MsgMhfAcquireGuildTresureSouvenir{}, network.MSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIR}, + {&MsgMhfLoadGuildCooking{}, network.MSG_MHF_LOAD_GUILD_COOKING}, + {&MsgMhfRegistGuildCooking{}, network.MSG_MHF_REGIST_GUILD_COOKING}, + {&MsgMhfLoadGuildAdventure{}, network.MSG_MHF_LOAD_GUILD_ADVENTURE}, + {&MsgMhfRegistGuildAdventure{}, network.MSG_MHF_REGIST_GUILD_ADVENTURE}, + {&MsgMhfAcquireGuildAdventure{}, network.MSG_MHF_ACQUIRE_GUILD_ADVENTURE}, + {&MsgMhfChargeGuildAdventure{}, network.MSG_MHF_CHARGE_GUILD_ADVENTURE}, + {&MsgMhfGetGuildMissionList{}, network.MSG_MHF_GET_GUILD_MISSION_LIST}, + {&MsgMhfGetGuildMissionRecord{}, network.MSG_MHF_GET_GUILD_MISSION_RECORD}, + {&MsgMhfAddGuildMissionCount{}, network.MSG_MHF_ADD_GUILD_MISSION_COUNT}, + {&MsgMhfSetGuildMissionTarget{}, network.MSG_MHF_SET_GUILD_MISSION_TARGET}, + {&MsgMhfCancelGuildMissionTarget{}, network.MSG_MHF_CANCEL_GUILD_MISSION_TARGET}, + {&MsgMhfGetGuildWeeklyBonusMaster{}, network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTER}, + {&MsgMhfGetGuildWeeklyBonusActiveCount{}, network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNT}, + {&MsgMhfAddGuildWeeklyBonusExceptionalUser{}, network.MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER}, + {&MsgMhfGetGuildTargetMemberNum{}, network.MSG_MHF_GET_GUILD_TARGET_MEMBER_NUM}, + {&MsgMhfPostGuildScout{}, network.MSG_MHF_POST_GUILD_SCOUT}, + {&MsgMhfCancelGuildScout{}, network.MSG_MHF_CANCEL_GUILD_SCOUT}, + {&MsgMhfAnswerGuildScout{}, network.MSG_MHF_ANSWER_GUILD_SCOUT}, + {&MsgMhfGetGuildScoutList{}, network.MSG_MHF_GET_GUILD_SCOUT_LIST}, + {&MsgMhfGetGuildManageRight{}, network.MSG_MHF_GET_GUILD_MANAGE_RIGHT}, + {&MsgMhfSetGuildManageRight{}, network.MSG_MHF_SET_GUILD_MANAGE_RIGHT}, + {&MsgMhfGetRejectGuildScout{}, network.MSG_MHF_GET_REJECT_GUILD_SCOUT}, + {&MsgMhfSetRejectGuildScout{}, network.MSG_MHF_SET_REJECT_GUILD_SCOUT}, + {&MsgMhfGuildHuntdata{}, network.MSG_MHF_GUILD_HUNTDATA}, + {&MsgMhfUpdateForceGuildRank{}, network.MSG_MHF_UPDATE_FORCE_GUILD_RANK}, + {&MsgMhfEnumerateGuildMessageBoard{}, network.MSG_MHF_ENUMERATE_GUILD_MESSAGE_BOARD}, + {&MsgMhfUpdateGuildMessageBoard{}, network.MSG_MHF_UPDATE_GUILD_MESSAGE_BOARD}, + } + + for _, tc := range guildPackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestFestaPacketsOpcode tests festa-related packets +func TestFestaPacketsOpcode(t *testing.T) { + festaPackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfInfoFesta{}, network.MSG_MHF_INFO_FESTA}, + {&MsgMhfEntryFesta{}, network.MSG_MHF_ENTRY_FESTA}, + {&MsgMhfChargeFesta{}, network.MSG_MHF_CHARGE_FESTA}, + {&MsgMhfAcquireFesta{}, network.MSG_MHF_ACQUIRE_FESTA}, + {&MsgMhfStateFestaU{}, network.MSG_MHF_STATE_FESTA_U}, + {&MsgMhfStateFestaG{}, network.MSG_MHF_STATE_FESTA_G}, + {&MsgMhfEnumerateFestaMember{}, network.MSG_MHF_ENUMERATE_FESTA_MEMBER}, + {&MsgMhfVoteFesta{}, network.MSG_MHF_VOTE_FESTA}, + {&MsgMhfEnumerateFestaIntermediatePrize{}, network.MSG_MHF_ENUMERATE_FESTA_INTERMEDIATE_PRIZE}, + {&MsgMhfAcquireFestaIntermediatePrize{}, network.MSG_MHF_ACQUIRE_FESTA_INTERMEDIATE_PRIZE}, + {&MsgMhfEnumerateFestaPersonalPrize{}, network.MSG_MHF_ENUMERATE_FESTA_PERSONAL_PRIZE}, + {&MsgMhfAcquireFestaPersonalPrize{}, network.MSG_MHF_ACQUIRE_FESTA_PERSONAL_PRIZE}, + } + + for _, tc := range festaPackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestCafePacketsOpcode tests cafe-related packets +func TestCafePacketsOpcode(t *testing.T) { + cafePackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfAcquireCafeItem{}, network.MSG_MHF_ACQUIRE_CAFE_ITEM}, + {&MsgMhfUpdateCafepoint{}, network.MSG_MHF_UPDATE_CAFEPOINT}, + {&MsgMhfCheckDailyCafepoint{}, network.MSG_MHF_CHECK_DAILY_CAFEPOINT}, + {&MsgMhfGetCafeDuration{}, network.MSG_MHF_GET_CAFE_DURATION}, + {&MsgMhfGetCafeDurationBonusInfo{}, network.MSG_MHF_GET_CAFE_DURATION_BONUS_INFO}, + {&MsgMhfReceiveCafeDurationBonus{}, network.MSG_MHF_RECEIVE_CAFE_DURATION_BONUS}, + {&MsgMhfPostCafeDurationBonusReceived{}, network.MSG_MHF_POST_CAFE_DURATION_BONUS_RECEIVED}, + } + + for _, tc := range cafePackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestGachaPacketsOpcode tests gacha-related packets +func TestGachaPacketsOpcode(t *testing.T) { + gachaPackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfGetGachaPoint{}, network.MSG_MHF_GET_GACHA_POINT}, + {&MsgMhfUseGachaPoint{}, network.MSG_MHF_USE_GACHA_POINT}, + {&MsgMhfPlayStepupGacha{}, network.MSG_MHF_PLAY_STEPUP_GACHA}, + {&MsgMhfReceiveGachaItem{}, network.MSG_MHF_RECEIVE_GACHA_ITEM}, + {&MsgMhfGetStepupStatus{}, network.MSG_MHF_GET_STEPUP_STATUS}, + {&MsgMhfPlayFreeGacha{}, network.MSG_MHF_PLAY_FREE_GACHA}, + {&MsgMhfGetBoxGachaInfo{}, network.MSG_MHF_GET_BOX_GACHA_INFO}, + {&MsgMhfPlayBoxGacha{}, network.MSG_MHF_PLAY_BOX_GACHA}, + {&MsgMhfResetBoxGachaInfo{}, network.MSG_MHF_RESET_BOX_GACHA_INFO}, + {&MsgMhfPlayNormalGacha{}, network.MSG_MHF_PLAY_NORMAL_GACHA}, + {&MsgMhfGetGachaPlayHistory{}, network.MSG_MHF_GET_GACHA_PLAY_HISTORY}, + } + + for _, tc := range gachaPackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestUDPacketsOpcode tests UD (Ultimate Devastation) related packets +func TestUDPacketsOpcode(t *testing.T) { + udPackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfGetUdSchedule{}, network.MSG_MHF_GET_UD_SCHEDULE}, + {&MsgMhfGetUdInfo{}, network.MSG_MHF_GET_UD_INFO}, + {&MsgMhfAddUdPoint{}, network.MSG_MHF_ADD_UD_POINT}, + {&MsgMhfGetUdMyPoint{}, network.MSG_MHF_GET_UD_MY_POINT}, + {&MsgMhfGetUdTotalPointInfo{}, network.MSG_MHF_GET_UD_TOTAL_POINT_INFO}, + {&MsgMhfGetUdBonusQuestInfo{}, network.MSG_MHF_GET_UD_BONUS_QUEST_INFO}, + {&MsgMhfGetUdSelectedColorInfo{}, network.MSG_MHF_GET_UD_SELECTED_COLOR_INFO}, + {&MsgMhfGetUdMonsterPoint{}, network.MSG_MHF_GET_UD_MONSTER_POINT}, + {&MsgMhfGetUdDailyPresentList{}, network.MSG_MHF_GET_UD_DAILY_PRESENT_LIST}, + {&MsgMhfGetUdNormaPresentList{}, network.MSG_MHF_GET_UD_NORMA_PRESENT_LIST}, + {&MsgMhfGetUdRankingRewardList{}, network.MSG_MHF_GET_UD_RANKING_REWARD_LIST}, + {&MsgMhfAcquireUdItem{}, network.MSG_MHF_ACQUIRE_UD_ITEM}, + {&MsgMhfGetUdRanking{}, network.MSG_MHF_GET_UD_RANKING}, + {&MsgMhfGetUdMyRanking{}, network.MSG_MHF_GET_UD_MY_RANKING}, + {&MsgMhfGetUdGuildMapInfo{}, network.MSG_MHF_GET_UD_GUILD_MAP_INFO}, + {&MsgMhfGenerateUdGuildMap{}, network.MSG_MHF_GENERATE_UD_GUILD_MAP}, + {&MsgMhfGetUdTacticsPoint{}, network.MSG_MHF_GET_UD_TACTICS_POINT}, + {&MsgMhfAddUdTacticsPoint{}, network.MSG_MHF_ADD_UD_TACTICS_POINT}, + {&MsgMhfGetUdTacticsRanking{}, network.MSG_MHF_GET_UD_TACTICS_RANKING}, + {&MsgMhfGetUdTacticsRewardList{}, network.MSG_MHF_GET_UD_TACTICS_REWARD_LIST}, + {&MsgMhfGetUdTacticsLog{}, network.MSG_MHF_GET_UD_TACTICS_LOG}, + {&MsgMhfGetUdTacticsFollower{}, network.MSG_MHF_GET_UD_TACTICS_FOLLOWER}, + {&MsgMhfSetUdTacticsFollower{}, network.MSG_MHF_SET_UD_TACTICS_FOLLOWER}, + {&MsgMhfGetUdShopCoin{}, network.MSG_MHF_GET_UD_SHOP_COIN}, + {&MsgMhfUseUdShopCoin{}, network.MSG_MHF_USE_UD_SHOP_COIN}, + {&MsgMhfGetUdTacticsBonusQuest{}, network.MSG_MHF_GET_UD_TACTICS_BONUS_QUEST}, + {&MsgMhfGetUdTacticsFirstQuestBonus{}, network.MSG_MHF_GET_UD_TACTICS_FIRST_QUEST_BONUS}, + {&MsgMhfGetUdTacticsRemainingPoint{}, network.MSG_MHF_GET_UD_TACTICS_REMAINING_POINT}, + } + + for _, tc := range udPackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestRengokuPacketsOpcode tests rengoku (purgatory tower) related packets +func TestRengokuPacketsOpcode(t *testing.T) { + rengokuPackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfSaveRengokuData{}, network.MSG_MHF_SAVE_RENGOKU_DATA}, + {&MsgMhfLoadRengokuData{}, network.MSG_MHF_LOAD_RENGOKU_DATA}, + {&MsgMhfGetRengokuBinary{}, network.MSG_MHF_GET_RENGOKU_BINARY}, + {&MsgMhfEnumerateRengokuRanking{}, network.MSG_MHF_ENUMERATE_RENGOKU_RANKING}, + {&MsgMhfGetRengokuRankingRank{}, network.MSG_MHF_GET_RENGOKU_RANKING_RANK}, + } + + for _, tc := range rengokuPackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestMezFesPacketsOpcode tests Mezeporta Festival related packets +func TestMezFesPacketsOpcode(t *testing.T) { + mezfesPackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfSaveMezfesData{}, network.MSG_MHF_SAVE_MEZFES_DATA}, + {&MsgMhfLoadMezfesData{}, network.MSG_MHF_LOAD_MEZFES_DATA}, + } + + for _, tc := range mezfesPackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestWarehousePacketsOpcode tests warehouse related packets +func TestWarehousePacketsOpcode(t *testing.T) { + warehousePackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfOperateWarehouse{}, network.MSG_MHF_OPERATE_WAREHOUSE}, + {&MsgMhfEnumerateWarehouse{}, network.MSG_MHF_ENUMERATE_WAREHOUSE}, + {&MsgMhfUpdateWarehouse{}, network.MSG_MHF_UPDATE_WAREHOUSE}, + } + + for _, tc := range warehousePackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestMercenaryPacketsOpcode tests mercenary related packets +func TestMercenaryPacketsOpcode(t *testing.T) { + mercenaryPackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfMercenaryHuntdata{}, network.MSG_MHF_MERCENARY_HUNTDATA}, + {&MsgMhfCreateMercenary{}, network.MSG_MHF_CREATE_MERCENARY}, + {&MsgMhfSaveMercenary{}, network.MSG_MHF_SAVE_MERCENARY}, + {&MsgMhfReadMercenaryW{}, network.MSG_MHF_READ_MERCENARY_W}, + {&MsgMhfReadMercenaryM{}, network.MSG_MHF_READ_MERCENARY_M}, + {&MsgMhfContractMercenary{}, network.MSG_MHF_CONTRACT_MERCENARY}, + {&MsgMhfEnumerateMercenaryLog{}, network.MSG_MHF_ENUMERATE_MERCENARY_LOG}, + } + + for _, tc := range mercenaryPackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestHousePacketsOpcode tests house related packets +func TestHousePacketsOpcode(t *testing.T) { + housePackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfUpdateInterior{}, network.MSG_MHF_UPDATE_INTERIOR}, + {&MsgMhfEnumerateHouse{}, network.MSG_MHF_ENUMERATE_HOUSE}, + {&MsgMhfUpdateHouse{}, network.MSG_MHF_UPDATE_HOUSE}, + {&MsgMhfLoadHouse{}, network.MSG_MHF_LOAD_HOUSE}, + {&MsgMhfGetMyhouseInfo{}, network.MSG_MHF_GET_MYHOUSE_INFO}, + {&MsgMhfUpdateMyhouseInfo{}, network.MSG_MHF_UPDATE_MYHOUSE_INFO}, + } + + for _, tc := range housePackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestBoostPacketsOpcode tests boost related packets +func TestBoostPacketsOpcode(t *testing.T) { + boostPackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfGetBoostTime{}, network.MSG_MHF_GET_BOOST_TIME}, + {&MsgMhfPostBoostTime{}, network.MSG_MHF_POST_BOOST_TIME}, + {&MsgMhfGetBoostTimeLimit{}, network.MSG_MHF_GET_BOOST_TIME_LIMIT}, + {&MsgMhfPostBoostTimeLimit{}, network.MSG_MHF_POST_BOOST_TIME_LIMIT}, + {&MsgMhfGetBoostRight{}, network.MSG_MHF_GET_BOOST_RIGHT}, + {&MsgMhfStartBoostTime{}, network.MSG_MHF_START_BOOST_TIME}, + {&MsgMhfPostBoostTimeQuestReturn{}, network.MSG_MHF_POST_BOOST_TIME_QUEST_RETURN}, + {&MsgMhfGetKeepLoginBoostStatus{}, network.MSG_MHF_GET_KEEP_LOGIN_BOOST_STATUS}, + {&MsgMhfUseKeepLoginBoost{}, network.MSG_MHF_USE_KEEP_LOGIN_BOOST}, + } + + for _, tc := range boostPackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestTournamentPacketsOpcode tests tournament related packets +func TestTournamentPacketsOpcode(t *testing.T) { + tournamentPackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfInfoTournament{}, network.MSG_MHF_INFO_TOURNAMENT}, + {&MsgMhfEntryTournament{}, network.MSG_MHF_ENTRY_TOURNAMENT}, + {&MsgMhfEnterTournamentQuest{}, network.MSG_MHF_ENTER_TOURNAMENT_QUEST}, + {&MsgMhfAcquireTournament{}, network.MSG_MHF_ACQUIRE_TOURNAMENT}, + } + + for _, tc := range tournamentPackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestPlatePacketsOpcode tests plate related packets +func TestPlatePacketsOpcode(t *testing.T) { + platePackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfLoadPlateData{}, network.MSG_MHF_LOAD_PLATE_DATA}, + {&MsgMhfSavePlateData{}, network.MSG_MHF_SAVE_PLATE_DATA}, + {&MsgMhfLoadPlateBox{}, network.MSG_MHF_LOAD_PLATE_BOX}, + {&MsgMhfSavePlateBox{}, network.MSG_MHF_SAVE_PLATE_BOX}, + {&MsgMhfLoadPlateMyset{}, network.MSG_MHF_LOAD_PLATE_MYSET}, + {&MsgMhfSavePlateMyset{}, network.MSG_MHF_SAVE_PLATE_MYSET}, + } + + for _, tc := range platePackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} + +// TestScenarioPacketsOpcode tests scenario related packets +func TestScenarioPacketsOpcode(t *testing.T) { + scenarioPackets := []struct { + pkt MHFPacket + opcode network.PacketID + }{ + {&MsgMhfInfoScenarioCounter{}, network.MSG_MHF_INFO_SCENARIO_COUNTER}, + {&MsgMhfSaveScenarioData{}, network.MSG_MHF_SAVE_SCENARIO_DATA}, + {&MsgMhfLoadScenarioData{}, network.MSG_MHF_LOAD_SCENARIO_DATA}, + } + + for _, tc := range scenarioPackets { + t.Run(tc.opcode.String(), func(t *testing.T) { + if tc.pkt.Opcode() != tc.opcode { + t.Errorf("Opcode() = %s, want %s", tc.pkt.Opcode(), tc.opcode) + } + }) + } +} diff --git a/network/mhfpacket/msg_mhf_packets_test.go b/network/mhfpacket/msg_mhf_packets_test.go new file mode 100644 index 000000000..db719ef13 --- /dev/null +++ b/network/mhfpacket/msg_mhf_packets_test.go @@ -0,0 +1,537 @@ +package mhfpacket + +import ( + "io" + "testing" + + "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" +) + +// TestMsgMhfSavedataParse tests parsing MsgMhfSavedata +func TestMsgMhfSavedataParse(t *testing.T) { + pkt := FromOpcode(network.MSG_MHF_SAVEDATA) + if pkt == nil { + t.Fatal("FromOpcode(MSG_MHF_SAVEDATA) returned nil") + } + if pkt.Opcode() != network.MSG_MHF_SAVEDATA { + t.Errorf("Opcode() = %s, want MSG_MHF_SAVEDATA", pkt.Opcode()) + } +} + +// TestMsgMhfLoaddataParse tests parsing MsgMhfLoaddata +func TestMsgMhfLoaddataParse(t *testing.T) { + pkt := FromOpcode(network.MSG_MHF_LOADDATA) + if pkt == nil { + t.Fatal("FromOpcode(MSG_MHF_LOADDATA) returned nil") + } + if pkt.Opcode() != network.MSG_MHF_LOADDATA { + t.Errorf("Opcode() = %s, want MSG_MHF_LOADDATA", pkt.Opcode()) + } +} + +// TestMsgMhfListMemberOpcode tests MsgMhfListMember Opcode +func TestMsgMhfListMemberOpcode(t *testing.T) { + pkt := &MsgMhfListMember{} + if pkt.Opcode() != network.MSG_MHF_LIST_MEMBER { + t.Errorf("Opcode() = %s, want MSG_MHF_LIST_MEMBER", pkt.Opcode()) + } +} + +// TestMsgMhfOprMemberOpcode tests MsgMhfOprMember Opcode +func TestMsgMhfOprMemberOpcode(t *testing.T) { + pkt := &MsgMhfOprMember{} + if pkt.Opcode() != network.MSG_MHF_OPR_MEMBER { + t.Errorf("Opcode() = %s, want MSG_MHF_OPR_MEMBER", pkt.Opcode()) + } +} + +// TestMsgMhfEnumerateDistItemOpcode tests MsgMhfEnumerateDistItem Opcode +func TestMsgMhfEnumerateDistItemOpcode(t *testing.T) { + pkt := &MsgMhfEnumerateDistItem{} + if pkt.Opcode() != network.MSG_MHF_ENUMERATE_DIST_ITEM { + t.Errorf("Opcode() = %s, want MSG_MHF_ENUMERATE_DIST_ITEM", pkt.Opcode()) + } +} + +// TestMsgMhfApplyDistItemOpcode tests MsgMhfApplyDistItem Opcode +func TestMsgMhfApplyDistItemOpcode(t *testing.T) { + pkt := &MsgMhfApplyDistItem{} + if pkt.Opcode() != network.MSG_MHF_APPLY_DIST_ITEM { + t.Errorf("Opcode() = %s, want MSG_MHF_APPLY_DIST_ITEM", pkt.Opcode()) + } +} + +// TestMsgMhfAcquireDistItemOpcode tests MsgMhfAcquireDistItem Opcode +func TestMsgMhfAcquireDistItemOpcode(t *testing.T) { + pkt := &MsgMhfAcquireDistItem{} + if pkt.Opcode() != network.MSG_MHF_ACQUIRE_DIST_ITEM { + t.Errorf("Opcode() = %s, want MSG_MHF_ACQUIRE_DIST_ITEM", pkt.Opcode()) + } +} + +// TestMsgMhfGetDistDescriptionOpcode tests MsgMhfGetDistDescription Opcode +func TestMsgMhfGetDistDescriptionOpcode(t *testing.T) { + pkt := &MsgMhfGetDistDescription{} + if pkt.Opcode() != network.MSG_MHF_GET_DIST_DESCRIPTION { + t.Errorf("Opcode() = %s, want MSG_MHF_GET_DIST_DESCRIPTION", pkt.Opcode()) + } +} + +// TestMsgMhfSendMailOpcode tests MsgMhfSendMail Opcode +func TestMsgMhfSendMailOpcode(t *testing.T) { + pkt := &MsgMhfSendMail{} + if pkt.Opcode() != network.MSG_MHF_SEND_MAIL { + t.Errorf("Opcode() = %s, want MSG_MHF_SEND_MAIL", pkt.Opcode()) + } +} + +// TestMsgMhfReadMailOpcode tests MsgMhfReadMail Opcode +func TestMsgMhfReadMailOpcode(t *testing.T) { + pkt := &MsgMhfReadMail{} + if pkt.Opcode() != network.MSG_MHF_READ_MAIL { + t.Errorf("Opcode() = %s, want MSG_MHF_READ_MAIL", pkt.Opcode()) + } +} + +// TestMsgMhfListMailOpcode tests MsgMhfListMail Opcode +func TestMsgMhfListMailOpcode(t *testing.T) { + pkt := &MsgMhfListMail{} + if pkt.Opcode() != network.MSG_MHF_LIST_MAIL { + t.Errorf("Opcode() = %s, want MSG_MHF_LIST_MAIL", pkt.Opcode()) + } +} + +// TestMsgMhfOprtMailOpcode tests MsgMhfOprtMail Opcode +func TestMsgMhfOprtMailOpcode(t *testing.T) { + pkt := &MsgMhfOprtMail{} + if pkt.Opcode() != network.MSG_MHF_OPRT_MAIL { + t.Errorf("Opcode() = %s, want MSG_MHF_OPRT_MAIL", pkt.Opcode()) + } +} + +// TestMsgMhfLoadFavoriteQuestOpcode tests MsgMhfLoadFavoriteQuest Opcode +func TestMsgMhfLoadFavoriteQuestOpcode(t *testing.T) { + pkt := &MsgMhfLoadFavoriteQuest{} + if pkt.Opcode() != network.MSG_MHF_LOAD_FAVORITE_QUEST { + t.Errorf("Opcode() = %s, want MSG_MHF_LOAD_FAVORITE_QUEST", pkt.Opcode()) + } +} + +// TestMsgMhfSaveFavoriteQuestOpcode tests MsgMhfSaveFavoriteQuest Opcode +func TestMsgMhfSaveFavoriteQuestOpcode(t *testing.T) { + pkt := &MsgMhfSaveFavoriteQuest{} + if pkt.Opcode() != network.MSG_MHF_SAVE_FAVORITE_QUEST { + t.Errorf("Opcode() = %s, want MSG_MHF_SAVE_FAVORITE_QUEST", pkt.Opcode()) + } +} + +// TestMsgMhfRegisterEventOpcode tests MsgMhfRegisterEvent Opcode +func TestMsgMhfRegisterEventOpcode(t *testing.T) { + pkt := &MsgMhfRegisterEvent{} + if pkt.Opcode() != network.MSG_MHF_REGISTER_EVENT { + t.Errorf("Opcode() = %s, want MSG_MHF_REGISTER_EVENT", pkt.Opcode()) + } +} + +// TestMsgMhfReleaseEventOpcode tests MsgMhfReleaseEvent Opcode +func TestMsgMhfReleaseEventOpcode(t *testing.T) { + pkt := &MsgMhfReleaseEvent{} + if pkt.Opcode() != network.MSG_MHF_RELEASE_EVENT { + t.Errorf("Opcode() = %s, want MSG_MHF_RELEASE_EVENT", pkt.Opcode()) + } +} + +// TestMsgMhfTransitMessageOpcode tests MsgMhfTransitMessage Opcode +func TestMsgMhfTransitMessageOpcode(t *testing.T) { + pkt := &MsgMhfTransitMessage{} + if pkt.Opcode() != network.MSG_MHF_TRANSIT_MESSAGE { + t.Errorf("Opcode() = %s, want MSG_MHF_TRANSIT_MESSAGE", pkt.Opcode()) + } +} + +// TestMsgMhfPresentBoxOpcode tests MsgMhfPresentBox Opcode +func TestMsgMhfPresentBoxOpcode(t *testing.T) { + pkt := &MsgMhfPresentBox{} + if pkt.Opcode() != network.MSG_MHF_PRESENT_BOX { + t.Errorf("Opcode() = %s, want MSG_MHF_PRESENT_BOX", pkt.Opcode()) + } +} + +// TestMsgMhfServerCommandOpcode tests MsgMhfServerCommand Opcode +func TestMsgMhfServerCommandOpcode(t *testing.T) { + pkt := &MsgMhfServerCommand{} + if pkt.Opcode() != network.MSG_MHF_SERVER_COMMAND { + t.Errorf("Opcode() = %s, want MSG_MHF_SERVER_COMMAND", pkt.Opcode()) + } +} + +// TestMsgMhfShutClientOpcode tests MsgMhfShutClient Opcode +func TestMsgMhfShutClientOpcode(t *testing.T) { + pkt := &MsgMhfShutClient{} + if pkt.Opcode() != network.MSG_MHF_SHUT_CLIENT { + t.Errorf("Opcode() = %s, want MSG_MHF_SHUT_CLIENT", pkt.Opcode()) + } +} + +// TestMsgMhfAnnounceOpcode tests MsgMhfAnnounce Opcode +func TestMsgMhfAnnounceOpcode(t *testing.T) { + pkt := &MsgMhfAnnounce{} + if pkt.Opcode() != network.MSG_MHF_ANNOUNCE { + t.Errorf("Opcode() = %s, want MSG_MHF_ANNOUNCE", pkt.Opcode()) + } +} + +// TestMsgMhfSetLoginwindowOpcode tests MsgMhfSetLoginwindow Opcode +func TestMsgMhfSetLoginwindowOpcode(t *testing.T) { + pkt := &MsgMhfSetLoginwindow{} + if pkt.Opcode() != network.MSG_MHF_SET_LOGINWINDOW { + t.Errorf("Opcode() = %s, want MSG_MHF_SET_LOGINWINDOW", pkt.Opcode()) + } +} + +// TestMsgMhfGetCaUniqueIDOpcode tests MsgMhfGetCaUniqueID Opcode +func TestMsgMhfGetCaUniqueIDOpcode(t *testing.T) { + pkt := &MsgMhfGetCaUniqueID{} + if pkt.Opcode() != network.MSG_MHF_GET_CA_UNIQUE_ID { + t.Errorf("Opcode() = %s, want MSG_MHF_GET_CA_UNIQUE_ID", pkt.Opcode()) + } +} + +// TestMsgMhfSetCaAchievementOpcode tests MsgMhfSetCaAchievement Opcode +func TestMsgMhfSetCaAchievementOpcode(t *testing.T) { + pkt := &MsgMhfSetCaAchievement{} + if pkt.Opcode() != network.MSG_MHF_SET_CA_ACHIEVEMENT { + t.Errorf("Opcode() = %s, want MSG_MHF_SET_CA_ACHIEVEMENT", pkt.Opcode()) + } +} + +// TestMsgMhfCaravanMyScoreOpcode tests MsgMhfCaravanMyScore Opcode +func TestMsgMhfCaravanMyScoreOpcode(t *testing.T) { + pkt := &MsgMhfCaravanMyScore{} + if pkt.Opcode() != network.MSG_MHF_CARAVAN_MY_SCORE { + t.Errorf("Opcode() = %s, want MSG_MHF_CARAVAN_MY_SCORE", pkt.Opcode()) + } +} + +// TestMsgMhfCaravanRankingOpcode tests MsgMhfCaravanRanking Opcode +func TestMsgMhfCaravanRankingOpcode(t *testing.T) { + pkt := &MsgMhfCaravanRanking{} + if pkt.Opcode() != network.MSG_MHF_CARAVAN_RANKING { + t.Errorf("Opcode() = %s, want MSG_MHF_CARAVAN_RANKING", pkt.Opcode()) + } +} + +// TestMsgMhfCaravanMyRankOpcode tests MsgMhfCaravanMyRank Opcode +func TestMsgMhfCaravanMyRankOpcode(t *testing.T) { + pkt := &MsgMhfCaravanMyRank{} + if pkt.Opcode() != network.MSG_MHF_CARAVAN_MY_RANK { + t.Errorf("Opcode() = %s, want MSG_MHF_CARAVAN_MY_RANK", pkt.Opcode()) + } +} + +// TestMsgMhfEnumerateQuestOpcode tests MsgMhfEnumerateQuest Opcode +func TestMsgMhfEnumerateQuestOpcode(t *testing.T) { + pkt := &MsgMhfEnumerateQuest{} + if pkt.Opcode() != network.MSG_MHF_ENUMERATE_QUEST { + t.Errorf("Opcode() = %s, want MSG_MHF_ENUMERATE_QUEST", pkt.Opcode()) + } +} + +// TestMsgMhfEnumerateEventOpcode tests MsgMhfEnumerateEvent Opcode +func TestMsgMhfEnumerateEventOpcode(t *testing.T) { + pkt := &MsgMhfEnumerateEvent{} + if pkt.Opcode() != network.MSG_MHF_ENUMERATE_EVENT { + t.Errorf("Opcode() = %s, want MSG_MHF_ENUMERATE_EVENT", pkt.Opcode()) + } +} + +// TestMsgMhfEnumeratePriceOpcode tests MsgMhfEnumeratePrice Opcode +func TestMsgMhfEnumeratePriceOpcode(t *testing.T) { + pkt := &MsgMhfEnumeratePrice{} + if pkt.Opcode() != network.MSG_MHF_ENUMERATE_PRICE { + t.Errorf("Opcode() = %s, want MSG_MHF_ENUMERATE_PRICE", pkt.Opcode()) + } +} + +// TestMsgMhfEnumerateRankingOpcode tests MsgMhfEnumerateRanking Opcode +func TestMsgMhfEnumerateRankingOpcode(t *testing.T) { + pkt := &MsgMhfEnumerateRanking{} + if pkt.Opcode() != network.MSG_MHF_ENUMERATE_RANKING { + t.Errorf("Opcode() = %s, want MSG_MHF_ENUMERATE_RANKING", pkt.Opcode()) + } +} + +// TestMsgMhfEnumerateOrderOpcode tests MsgMhfEnumerateOrder Opcode +func TestMsgMhfEnumerateOrderOpcode(t *testing.T) { + pkt := &MsgMhfEnumerateOrder{} + if pkt.Opcode() != network.MSG_MHF_ENUMERATE_ORDER { + t.Errorf("Opcode() = %s, want MSG_MHF_ENUMERATE_ORDER", pkt.Opcode()) + } +} + +// TestMsgMhfEnumerateShopOpcode tests MsgMhfEnumerateShop Opcode +func TestMsgMhfEnumerateShopOpcode(t *testing.T) { + pkt := &MsgMhfEnumerateShop{} + if pkt.Opcode() != network.MSG_MHF_ENUMERATE_SHOP { + t.Errorf("Opcode() = %s, want MSG_MHF_ENUMERATE_SHOP", pkt.Opcode()) + } +} + +// TestMsgMhfGetExtraInfoOpcode tests MsgMhfGetExtraInfo Opcode +func TestMsgMhfGetExtraInfoOpcode(t *testing.T) { + pkt := &MsgMhfGetExtraInfo{} + if pkt.Opcode() != network.MSG_MHF_GET_EXTRA_INFO { + t.Errorf("Opcode() = %s, want MSG_MHF_GET_EXTRA_INFO", pkt.Opcode()) + } +} + +// TestMsgMhfEnumerateItemOpcode tests MsgMhfEnumerateItem Opcode +func TestMsgMhfEnumerateItemOpcode(t *testing.T) { + pkt := &MsgMhfEnumerateItem{} + if pkt.Opcode() != network.MSG_MHF_ENUMERATE_ITEM { + t.Errorf("Opcode() = %s, want MSG_MHF_ENUMERATE_ITEM", pkt.Opcode()) + } +} + +// TestMsgMhfAcquireItemOpcode tests MsgMhfAcquireItem Opcode +func TestMsgMhfAcquireItemOpcode(t *testing.T) { + pkt := &MsgMhfAcquireItem{} + if pkt.Opcode() != network.MSG_MHF_ACQUIRE_ITEM { + t.Errorf("Opcode() = %s, want MSG_MHF_ACQUIRE_ITEM", pkt.Opcode()) + } +} + +// TestMsgMhfTransferItemOpcode tests MsgMhfTransferItem Opcode +func TestMsgMhfTransferItemOpcode(t *testing.T) { + pkt := &MsgMhfTransferItem{} + if pkt.Opcode() != network.MSG_MHF_TRANSFER_ITEM { + t.Errorf("Opcode() = %s, want MSG_MHF_TRANSFER_ITEM", pkt.Opcode()) + } +} + +// TestMsgMhfEntryRookieGuildOpcode tests MsgMhfEntryRookieGuild Opcode +func TestMsgMhfEntryRookieGuildOpcode(t *testing.T) { + pkt := &MsgMhfEntryRookieGuild{} + if pkt.Opcode() != network.MSG_MHF_ENTRY_ROOKIE_GUILD { + t.Errorf("Opcode() = %s, want MSG_MHF_ENTRY_ROOKIE_GUILD", pkt.Opcode()) + } +} + +// TestMsgCaExchangeItemOpcode tests MsgCaExchangeItem Opcode +func TestMsgCaExchangeItemOpcode(t *testing.T) { + pkt := &MsgCaExchangeItem{} + if pkt.Opcode() != network.MSG_CA_EXCHANGE_ITEM { + t.Errorf("Opcode() = %s, want MSG_CA_EXCHANGE_ITEM", pkt.Opcode()) + } +} + +// TestMsgMhfEnumerateCampaignOpcode tests MsgMhfEnumerateCampaign Opcode +func TestMsgMhfEnumerateCampaignOpcode(t *testing.T) { + pkt := &MsgMhfEnumerateCampaign{} + if pkt.Opcode() != network.MSG_MHF_ENUMERATE_CAMPAIGN { + t.Errorf("Opcode() = %s, want MSG_MHF_ENUMERATE_CAMPAIGN", pkt.Opcode()) + } +} + +// TestMsgMhfStateCampaignOpcode tests MsgMhfStateCampaign Opcode +func TestMsgMhfStateCampaignOpcode(t *testing.T) { + pkt := &MsgMhfStateCampaign{} + if pkt.Opcode() != network.MSG_MHF_STATE_CAMPAIGN { + t.Errorf("Opcode() = %s, want MSG_MHF_STATE_CAMPAIGN", pkt.Opcode()) + } +} + +// TestMsgMhfApplyCampaignOpcode tests MsgMhfApplyCampaign Opcode +func TestMsgMhfApplyCampaignOpcode(t *testing.T) { + pkt := &MsgMhfApplyCampaign{} + if pkt.Opcode() != network.MSG_MHF_APPLY_CAMPAIGN { + t.Errorf("Opcode() = %s, want MSG_MHF_APPLY_CAMPAIGN", pkt.Opcode()) + } +} + +// TestMsgMhfCreateJointOpcode tests MsgMhfCreateJoint Opcode +func TestMsgMhfCreateJointOpcode(t *testing.T) { + pkt := &MsgMhfCreateJoint{} + if pkt.Opcode() != network.MSG_MHF_CREATE_JOINT { + t.Errorf("Opcode() = %s, want MSG_MHF_CREATE_JOINT", pkt.Opcode()) + } +} + +// TestMsgMhfOperateJointOpcode tests MsgMhfOperateJoint Opcode +func TestMsgMhfOperateJointOpcode(t *testing.T) { + pkt := &MsgMhfOperateJoint{} + if pkt.Opcode() != network.MSG_MHF_OPERATE_JOINT { + t.Errorf("Opcode() = %s, want MSG_MHF_OPERATE_JOINT", pkt.Opcode()) + } +} + +// TestMsgMhfInfoJointOpcode tests MsgMhfInfoJoint Opcode +func TestMsgMhfInfoJointOpcode(t *testing.T) { + pkt := &MsgMhfInfoJoint{} + if pkt.Opcode() != network.MSG_MHF_INFO_JOINT { + t.Errorf("Opcode() = %s, want MSG_MHF_INFO_JOINT", pkt.Opcode()) + } +} + +// TestMsgMhfGetCogInfoOpcode tests MsgMhfGetCogInfo Opcode +func TestMsgMhfGetCogInfoOpcode(t *testing.T) { + pkt := &MsgMhfGetCogInfo{} + if pkt.Opcode() != network.MSG_MHF_GET_COG_INFO { + t.Errorf("Opcode() = %s, want MSG_MHF_GET_COG_INFO", pkt.Opcode()) + } +} + +// TestMsgMhfCheckMonthlyItemOpcode tests MsgMhfCheckMonthlyItem Opcode +func TestMsgMhfCheckMonthlyItemOpcode(t *testing.T) { + pkt := &MsgMhfCheckMonthlyItem{} + if pkt.Opcode() != network.MSG_MHF_CHECK_MONTHLY_ITEM { + t.Errorf("Opcode() = %s, want MSG_MHF_CHECK_MONTHLY_ITEM", pkt.Opcode()) + } +} + +// TestMsgMhfAcquireMonthlyItemOpcode tests MsgMhfAcquireMonthlyItem Opcode +func TestMsgMhfAcquireMonthlyItemOpcode(t *testing.T) { + pkt := &MsgMhfAcquireMonthlyItem{} + if pkt.Opcode() != network.MSG_MHF_ACQUIRE_MONTHLY_ITEM { + t.Errorf("Opcode() = %s, want MSG_MHF_ACQUIRE_MONTHLY_ITEM", pkt.Opcode()) + } +} + +// TestMsgMhfCheckWeeklyStampOpcode tests MsgMhfCheckWeeklyStamp Opcode +func TestMsgMhfCheckWeeklyStampOpcode(t *testing.T) { + pkt := &MsgMhfCheckWeeklyStamp{} + if pkt.Opcode() != network.MSG_MHF_CHECK_WEEKLY_STAMP { + t.Errorf("Opcode() = %s, want MSG_MHF_CHECK_WEEKLY_STAMP", pkt.Opcode()) + } +} + +// TestMsgMhfExchangeWeeklyStampOpcode tests MsgMhfExchangeWeeklyStamp Opcode +func TestMsgMhfExchangeWeeklyStampOpcode(t *testing.T) { + pkt := &MsgMhfExchangeWeeklyStamp{} + if pkt.Opcode() != network.MSG_MHF_EXCHANGE_WEEKLY_STAMP { + t.Errorf("Opcode() = %s, want MSG_MHF_EXCHANGE_WEEKLY_STAMP", pkt.Opcode()) + } +} + +// TestMsgMhfCreateMercenaryOpcode tests MsgMhfCreateMercenary Opcode +func TestMsgMhfCreateMercenaryOpcode(t *testing.T) { + pkt := &MsgMhfCreateMercenary{} + if pkt.Opcode() != network.MSG_MHF_CREATE_MERCENARY { + t.Errorf("Opcode() = %s, want MSG_MHF_CREATE_MERCENARY", pkt.Opcode()) + } +} + +// TestMsgMhfEnumerateMercenaryLogOpcode tests MsgMhfEnumerateMercenaryLog Opcode +func TestMsgMhfEnumerateMercenaryLogOpcode(t *testing.T) { + pkt := &MsgMhfEnumerateMercenaryLog{} + if pkt.Opcode() != network.MSG_MHF_ENUMERATE_MERCENARY_LOG { + t.Errorf("Opcode() = %s, want MSG_MHF_ENUMERATE_MERCENARY_LOG", pkt.Opcode()) + } +} + +// TestMsgMhfEnumerateGuacotOpcode tests MsgMhfEnumerateGuacot Opcode +func TestMsgMhfEnumerateGuacotOpcode(t *testing.T) { + pkt := &MsgMhfEnumerateGuacot{} + if pkt.Opcode() != network.MSG_MHF_ENUMERATE_GUACOT { + t.Errorf("Opcode() = %s, want MSG_MHF_ENUMERATE_GUACOT", pkt.Opcode()) + } +} + +// TestMsgMhfUpdateGuacotOpcode tests MsgMhfUpdateGuacot Opcode +func TestMsgMhfUpdateGuacotOpcode(t *testing.T) { + pkt := &MsgMhfUpdateGuacot{} + if pkt.Opcode() != network.MSG_MHF_UPDATE_GUACOT { + t.Errorf("Opcode() = %s, want MSG_MHF_UPDATE_GUACOT", pkt.Opcode()) + } +} + +// TestMsgMhfEnterTournamentQuestOpcode tests MsgMhfEnterTournamentQuest Opcode +func TestMsgMhfEnterTournamentQuestOpcode(t *testing.T) { + pkt := &MsgMhfEnterTournamentQuest{} + if pkt.Opcode() != network.MSG_MHF_ENTER_TOURNAMENT_QUEST { + t.Errorf("Opcode() = %s, want MSG_MHF_ENTER_TOURNAMENT_QUEST", pkt.Opcode()) + } +} + +// TestMsgMhfResetAchievementOpcode tests MsgMhfResetAchievement Opcode +func TestMsgMhfResetAchievementOpcode(t *testing.T) { + pkt := &MsgMhfResetAchievement{} + if pkt.Opcode() != network.MSG_MHF_RESET_ACHIEVEMENT { + t.Errorf("Opcode() = %s, want MSG_MHF_RESET_ACHIEVEMENT", pkt.Opcode()) + } +} + +// TestMsgMhfPaymentAchievementOpcode tests MsgMhfPaymentAchievement Opcode +func TestMsgMhfPaymentAchievementOpcode(t *testing.T) { + pkt := &MsgMhfPaymentAchievement{} + if pkt.Opcode() != network.MSG_MHF_PAYMENT_ACHIEVEMENT { + t.Errorf("Opcode() = %s, want MSG_MHF_PAYMENT_ACHIEVEMENT", pkt.Opcode()) + } +} + +// TestMsgMhfDisplayedAchievementOpcode tests MsgMhfDisplayedAchievement Opcode +func TestMsgMhfDisplayedAchievementOpcode(t *testing.T) { + pkt := &MsgMhfDisplayedAchievement{} + if pkt.Opcode() != network.MSG_MHF_DISPLAYED_ACHIEVEMENT { + t.Errorf("Opcode() = %s, want MSG_MHF_DISPLAYED_ACHIEVEMENT", pkt.Opcode()) + } +} + +// TestMsgMhfGetBbsSnsStatusOpcode tests MsgMhfGetBbsSnsStatus Opcode +func TestMsgMhfGetBbsSnsStatusOpcode(t *testing.T) { + pkt := &MsgMhfGetBbsSnsStatus{} + if pkt.Opcode() != network.MSG_MHF_GET_BBS_SNS_STATUS { + t.Errorf("Opcode() = %s, want MSG_MHF_GET_BBS_SNS_STATUS", pkt.Opcode()) + } +} + +// TestMsgMhfApplyBbsArticleOpcode tests MsgMhfApplyBbsArticle Opcode +func TestMsgMhfApplyBbsArticleOpcode(t *testing.T) { + pkt := &MsgMhfApplyBbsArticle{} + if pkt.Opcode() != network.MSG_MHF_APPLY_BBS_ARTICLE { + t.Errorf("Opcode() = %s, want MSG_MHF_APPLY_BBS_ARTICLE", pkt.Opcode()) + } +} + +// TestMsgMhfGetEtcPointsOpcode tests MsgMhfGetEtcPoints Opcode +func TestMsgMhfGetEtcPointsOpcode(t *testing.T) { + pkt := &MsgMhfGetEtcPoints{} + if pkt.Opcode() != network.MSG_MHF_GET_ETC_POINTS { + t.Errorf("Opcode() = %s, want MSG_MHF_GET_ETC_POINTS", pkt.Opcode()) + } +} + +// TestMsgMhfUpdateEtcPointOpcode tests MsgMhfUpdateEtcPoint Opcode +func TestMsgMhfUpdateEtcPointOpcode(t *testing.T) { + pkt := &MsgMhfUpdateEtcPoint{} + if pkt.Opcode() != network.MSG_MHF_UPDATE_ETC_POINT { + t.Errorf("Opcode() = %s, want MSG_MHF_UPDATE_ETC_POINT", pkt.Opcode()) + } +} + +// TestAchievementPacketParse tests simple achievement packet parsing +func TestAchievementPacketParse(t *testing.T) { + bf := byteframe.NewByteFrame() + bf.WriteUint8(5) // AchievementID + bf.WriteUint16(100) // Unk1 + bf.WriteUint16(200) // Unk2 + bf.Seek(0, io.SeekStart) + + pkt := &MsgMhfAddAchievement{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.AchievementID != 5 { + t.Errorf("AchievementID = %d, want 5", pkt.AchievementID) + } + if pkt.Unk1 != 100 { + t.Errorf("Unk1 = %d, want 100", pkt.Unk1) + } + if pkt.Unk2 != 200 { + t.Errorf("Unk2 = %d, want 200", pkt.Unk2) + } +} diff --git a/network/mhfpacket/msg_parse_test.go b/network/mhfpacket/msg_parse_test.go new file mode 100644 index 000000000..29050701c --- /dev/null +++ b/network/mhfpacket/msg_parse_test.go @@ -0,0 +1,298 @@ +package mhfpacket + +import ( + "io" + "testing" + + "erupe-ce/common/byteframe" + "erupe-ce/network/clientctx" +) + +// TestMsgMhfGetAchievementParse tests MsgMhfGetAchievement parsing +func TestMsgMhfGetAchievementDetailedParse(t *testing.T) { + bf := byteframe.NewByteFrame() + bf.WriteUint32(0x12345678) // AckHandle + bf.WriteUint32(54321) // CharID + bf.WriteUint32(99999) // Unk1 + bf.Seek(0, io.SeekStart) + + pkt := &MsgMhfGetAchievement{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.AckHandle != 0x12345678 { + t.Errorf("AckHandle = 0x%X, want 0x12345678", pkt.AckHandle) + } + if pkt.CharID != 54321 { + t.Errorf("CharID = %d, want 54321", pkt.CharID) + } + if pkt.Unk1 != 99999 { + t.Errorf("Unk1 = %d, want 99999", pkt.Unk1) + } +} + +// TestMsgMhfAddAchievementDetailedParse tests MsgMhfAddAchievement parsing +func TestMsgMhfAddAchievementDetailedParse(t *testing.T) { + bf := byteframe.NewByteFrame() + bf.WriteUint8(42) // AchievementID + bf.WriteUint16(12345) // Unk1 + bf.WriteUint16(0xFFFF) // Unk2 - max value + bf.Seek(0, io.SeekStart) + + pkt := &MsgMhfAddAchievement{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.AchievementID != 42 { + t.Errorf("AchievementID = %d, want 42", pkt.AchievementID) + } + if pkt.Unk1 != 12345 { + t.Errorf("Unk1 = %d, want 12345", pkt.Unk1) + } + if pkt.Unk2 != 0xFFFF { + t.Errorf("Unk2 = %d, want 65535", pkt.Unk2) + } +} + +// TestMsgSysCastBinaryDetailedParse tests MsgSysCastBinary parsing with various payloads +func TestMsgSysCastBinaryDetailedParse(t *testing.T) { + tests := []struct { + name string + unk0 uint16 + unk1 uint16 + broadcastType uint8 + messageType uint8 + payload []byte + }{ + {"empty payload", 0, 0, 1, 2, []byte{}}, + {"typical payload", 100, 200, 0x10, 0x20, []byte{0x01, 0x02, 0x03}}, + {"chat message", 0, 0, 0x01, 0x01, []byte("Hello, World!")}, + {"binary data", 0xFFFF, 0xFFFF, 0xFF, 0xFF, []byte{0xDE, 0xAD, 0xBE, 0xEF}}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bf := byteframe.NewByteFrame() + bf.WriteUint16(tt.unk0) + bf.WriteUint16(tt.unk1) + bf.WriteUint8(tt.broadcastType) + bf.WriteUint8(tt.messageType) + bf.WriteUint16(uint16(len(tt.payload))) + bf.WriteBytes(tt.payload) + bf.Seek(0, io.SeekStart) + + pkt := &MsgSysCastBinary{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.Unk0 != tt.unk0 { + t.Errorf("Unk0 = %d, want %d", pkt.Unk0, tt.unk0) + } + if pkt.Unk1 != tt.unk1 { + t.Errorf("Unk1 = %d, want %d", pkt.Unk1, tt.unk1) + } + if pkt.BroadcastType != tt.broadcastType { + t.Errorf("BroadcastType = %d, want %d", pkt.BroadcastType, tt.broadcastType) + } + if pkt.MessageType != tt.messageType { + t.Errorf("MessageType = %d, want %d", pkt.MessageType, tt.messageType) + } + if len(pkt.RawDataPayload) != len(tt.payload) { + t.Errorf("RawDataPayload len = %d, want %d", len(pkt.RawDataPayload), len(tt.payload)) + } + }) + } +} + +// TestMsgSysCreateSemaphoreDetailedParse tests MsgSysCreateSemaphore parsing +func TestMsgSysCreateSemaphoreDetailedParse(t *testing.T) { + tests := []struct { + name string + ackHandle uint32 + unk0 uint16 + payload []byte + }{ + {"minimal", 1, 0, []byte{}}, + {"typical", 0xABCD1234, 100, []byte{0x01, 0x02, 0x03, 0x04}}, + {"maxed", 0xFFFFFFFF, 0xFFFF, make([]byte, 256)}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bf := byteframe.NewByteFrame() + bf.WriteUint32(tt.ackHandle) + bf.WriteUint16(tt.unk0) + bf.WriteUint16(uint16(len(tt.payload))) + bf.WriteBytes(tt.payload) + bf.Seek(0, io.SeekStart) + + pkt := &MsgSysCreateSemaphore{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.AckHandle != tt.ackHandle { + t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, tt.ackHandle) + } + if pkt.Unk0 != tt.unk0 { + t.Errorf("Unk0 = %d, want %d", pkt.Unk0, tt.unk0) + } + if pkt.DataSize != uint16(len(tt.payload)) { + t.Errorf("DataSize = %d, want %d", pkt.DataSize, len(tt.payload)) + } + if len(pkt.RawDataPayload) != len(tt.payload) { + t.Errorf("RawDataPayload len = %d, want %d", len(pkt.RawDataPayload), len(tt.payload)) + } + }) + } +} + +// TestMsgSysLogoutParse tests MsgSysLogout parsing +func TestMsgSysLogoutDetailedParse(t *testing.T) { + tests := []struct { + unk0 uint8 + }{ + {0}, + {1}, + {100}, + {255}, + } + + for _, tt := range tests { + bf := byteframe.NewByteFrame() + bf.WriteUint8(tt.unk0) + bf.Seek(0, io.SeekStart) + + pkt := &MsgSysLogout{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.Unk0 != tt.unk0 { + t.Errorf("Unk0 = %d, want %d", pkt.Unk0, tt.unk0) + } + } +} + +// TestMsgSysBackStageParse tests MsgSysBackStage parsing +func TestMsgSysBackStageDetailedParse(t *testing.T) { + tests := []struct { + ackHandle uint32 + }{ + {0}, + {1}, + {0x12345678}, + {0xFFFFFFFF}, + } + + for _, tt := range tests { + bf := byteframe.NewByteFrame() + bf.WriteUint32(tt.ackHandle) + bf.Seek(0, io.SeekStart) + + pkt := &MsgSysBackStage{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.AckHandle != tt.ackHandle { + t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, tt.ackHandle) + } + } +} + +// TestMsgSysUnlockStageParse tests MsgSysUnlockStage parsing +func TestMsgSysUnlockStageDetailedParse(t *testing.T) { + tests := []struct { + unk0 uint16 + }{ + {0}, + {1}, + {100}, + {0xFFFF}, + } + + for _, tt := range tests { + bf := byteframe.NewByteFrame() + bf.WriteUint16(tt.unk0) + bf.Seek(0, io.SeekStart) + + pkt := &MsgSysUnlockStage{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.Unk0 != tt.unk0 { + t.Errorf("Unk0 = %d, want %d", pkt.Unk0, tt.unk0) + } + } +} + +// TestMsgSysPingParse tests MsgSysPing parsing +func TestMsgSysPingDetailedParse(t *testing.T) { + tests := []struct { + ackHandle uint32 + }{ + {0}, + {0xABCDEF12}, + {0xFFFFFFFF}, + } + + for _, tt := range tests { + bf := byteframe.NewByteFrame() + bf.WriteUint32(tt.ackHandle) + bf.Seek(0, io.SeekStart) + + pkt := &MsgSysPing{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.AckHandle != tt.ackHandle { + t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, tt.ackHandle) + } + } +} + +// TestMsgSysTimeParse tests MsgSysTime parsing +func TestMsgSysTimeDetailedParse(t *testing.T) { + tests := []struct { + getRemoteTime bool + timestamp uint32 + }{ + {false, 0}, + {true, 1577836800}, // 2020-01-01 00:00:00 + {false, 0xFFFFFFFF}, + } + + for _, tt := range tests { + bf := byteframe.NewByteFrame() + bf.WriteBool(tt.getRemoteTime) + bf.WriteUint32(tt.timestamp) + bf.Seek(0, io.SeekStart) + + pkt := &MsgSysTime{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.GetRemoteTime != tt.getRemoteTime { + t.Errorf("GetRemoteTime = %v, want %v", pkt.GetRemoteTime, tt.getRemoteTime) + } + if pkt.Timestamp != tt.timestamp { + t.Errorf("Timestamp = %d, want %d", pkt.Timestamp, tt.timestamp) + } + } +} diff --git a/network/mhfpacket/msg_sys_packets_test.go b/network/mhfpacket/msg_sys_packets_test.go new file mode 100644 index 000000000..a2168ef0e --- /dev/null +++ b/network/mhfpacket/msg_sys_packets_test.go @@ -0,0 +1,641 @@ +package mhfpacket + +import ( + "io" + "testing" + + "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" +) + +// TestMsgSysCastBinaryParse tests parsing MsgSysCastBinary +func TestMsgSysCastBinaryParse(t *testing.T) { + tests := []struct { + name string + unk0 uint16 + unk1 uint16 + broadcastType uint8 + messageType uint8 + payload []byte + }{ + {"empty payload", 0, 0, 1, 2, []byte{}}, + {"small payload", 100, 200, 3, 4, []byte{0xAA, 0xBB, 0xCC}}, + {"large payload", 0xFFFF, 0xFFFF, 0xFF, 0xFF, make([]byte, 100)}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bf := byteframe.NewByteFrame() + bf.WriteUint16(tt.unk0) + bf.WriteUint16(tt.unk1) + bf.WriteUint8(tt.broadcastType) + bf.WriteUint8(tt.messageType) + bf.WriteUint16(uint16(len(tt.payload))) + bf.WriteBytes(tt.payload) + bf.Seek(0, io.SeekStart) + + pkt := &MsgSysCastBinary{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.Unk0 != tt.unk0 { + t.Errorf("Unk0 = %d, want %d", pkt.Unk0, tt.unk0) + } + if pkt.Unk1 != tt.unk1 { + t.Errorf("Unk1 = %d, want %d", pkt.Unk1, tt.unk1) + } + if pkt.BroadcastType != tt.broadcastType { + t.Errorf("BroadcastType = %d, want %d", pkt.BroadcastType, tt.broadcastType) + } + if pkt.MessageType != tt.messageType { + t.Errorf("MessageType = %d, want %d", pkt.MessageType, tt.messageType) + } + if len(pkt.RawDataPayload) != len(tt.payload) { + t.Errorf("RawDataPayload len = %d, want %d", len(pkt.RawDataPayload), len(tt.payload)) + } + }) + } +} + +// TestMsgSysCastBinaryOpcode tests Opcode method +func TestMsgSysCastBinaryOpcode(t *testing.T) { + pkt := &MsgSysCastBinary{} + if pkt.Opcode() != network.MSG_SYS_CAST_BINARY { + t.Errorf("Opcode() = %s, want MSG_SYS_CAST_BINARY", pkt.Opcode()) + } +} + +// TestMsgSysCreateSemaphoreParse tests parsing MsgSysCreateSemaphore +func TestMsgSysCreateSemaphoreParse(t *testing.T) { + tests := []struct { + name string + ackHandle uint32 + unk0 uint16 + payload []byte + }{ + {"empty payload", 1, 0, []byte{}}, + {"with data", 0x12345678, 100, []byte{0x01, 0x02, 0x03, 0x04}}, + {"max values", 0xFFFFFFFF, 0xFFFF, make([]byte, 50)}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bf := byteframe.NewByteFrame() + bf.WriteUint32(tt.ackHandle) + bf.WriteUint16(tt.unk0) + bf.WriteUint16(uint16(len(tt.payload))) + bf.WriteBytes(tt.payload) + bf.Seek(0, io.SeekStart) + + pkt := &MsgSysCreateSemaphore{} + err := pkt.Parse(bf, &clientctx.ClientContext{}) + if err != nil { + t.Fatalf("Parse() error = %v", err) + } + + if pkt.AckHandle != tt.ackHandle { + t.Errorf("AckHandle = %d, want %d", pkt.AckHandle, tt.ackHandle) + } + if pkt.Unk0 != tt.unk0 { + t.Errorf("Unk0 = %d, want %d", pkt.Unk0, tt.unk0) + } + if pkt.DataSize != uint16(len(tt.payload)) { + t.Errorf("DataSize = %d, want %d", pkt.DataSize, len(tt.payload)) + } + if len(pkt.RawDataPayload) != len(tt.payload) { + t.Errorf("RawDataPayload len = %d, want %d", len(pkt.RawDataPayload), len(tt.payload)) + } + }) + } +} + +// TestMsgSysCreateSemaphoreOpcode tests Opcode method +func TestMsgSysCreateSemaphoreOpcode(t *testing.T) { + pkt := &MsgSysCreateSemaphore{} + if pkt.Opcode() != network.MSG_SYS_CREATE_SEMAPHORE { + t.Errorf("Opcode() = %s, want MSG_SYS_CREATE_SEMAPHORE", pkt.Opcode()) + } +} + +// TestMsgSysCastedBinaryOpcode tests Opcode method +func TestMsgSysCastedBinaryOpcode(t *testing.T) { + pkt := &MsgSysCastedBinary{} + if pkt.Opcode() != network.MSG_SYS_CASTED_BINARY { + t.Errorf("Opcode() = %s, want MSG_SYS_CASTED_BINARY", pkt.Opcode()) + } +} + +// TestMsgSysSetStageBinaryOpcode tests Opcode method +func TestMsgSysSetStageBinaryOpcode(t *testing.T) { + pkt := &MsgSysSetStageBinary{} + if pkt.Opcode() != network.MSG_SYS_SET_STAGE_BINARY { + t.Errorf("Opcode() = %s, want MSG_SYS_SET_STAGE_BINARY", pkt.Opcode()) + } +} + +// TestMsgSysGetStageBinaryOpcode tests Opcode method +func TestMsgSysGetStageBinaryOpcode(t *testing.T) { + pkt := &MsgSysGetStageBinary{} + if pkt.Opcode() != network.MSG_SYS_GET_STAGE_BINARY { + t.Errorf("Opcode() = %s, want MSG_SYS_GET_STAGE_BINARY", pkt.Opcode()) + } +} + +// TestMsgSysWaitStageBinaryOpcode tests Opcode method +func TestMsgSysWaitStageBinaryOpcode(t *testing.T) { + pkt := &MsgSysWaitStageBinary{} + if pkt.Opcode() != network.MSG_SYS_WAIT_STAGE_BINARY { + t.Errorf("Opcode() = %s, want MSG_SYS_WAIT_STAGE_BINARY", pkt.Opcode()) + } +} + +// TestMsgSysEnumerateClientOpcode tests Opcode method +func TestMsgSysEnumerateClientOpcode(t *testing.T) { + pkt := &MsgSysEnumerateClient{} + if pkt.Opcode() != network.MSG_SYS_ENUMERATE_CLIENT { + t.Errorf("Opcode() = %s, want MSG_SYS_ENUMERATE_CLIENT", pkt.Opcode()) + } +} + +// TestMsgSysEnumerateStageOpcode tests Opcode method +func TestMsgSysEnumerateStageOpcode(t *testing.T) { + pkt := &MsgSysEnumerateStage{} + if pkt.Opcode() != network.MSG_SYS_ENUMERATE_STAGE { + t.Errorf("Opcode() = %s, want MSG_SYS_ENUMERATE_STAGE", pkt.Opcode()) + } +} + +// TestMsgSysCreateMutexOpcode tests Opcode method +func TestMsgSysCreateMutexOpcode(t *testing.T) { + pkt := &MsgSysCreateMutex{} + if pkt.Opcode() != network.MSG_SYS_CREATE_MUTEX { + t.Errorf("Opcode() = %s, want MSG_SYS_CREATE_MUTEX", pkt.Opcode()) + } +} + +// TestMsgSysCreateOpenMutexOpcode tests Opcode method +func TestMsgSysCreateOpenMutexOpcode(t *testing.T) { + pkt := &MsgSysCreateOpenMutex{} + if pkt.Opcode() != network.MSG_SYS_CREATE_OPEN_MUTEX { + t.Errorf("Opcode() = %s, want MSG_SYS_CREATE_OPEN_MUTEX", pkt.Opcode()) + } +} + +// TestMsgSysDeleteMutexOpcode tests Opcode method +func TestMsgSysDeleteMutexOpcode(t *testing.T) { + pkt := &MsgSysDeleteMutex{} + if pkt.Opcode() != network.MSG_SYS_DELETE_MUTEX { + t.Errorf("Opcode() = %s, want MSG_SYS_DELETE_MUTEX", pkt.Opcode()) + } +} + +// TestMsgSysOpenMutexOpcode tests Opcode method +func TestMsgSysOpenMutexOpcode(t *testing.T) { + pkt := &MsgSysOpenMutex{} + if pkt.Opcode() != network.MSG_SYS_OPEN_MUTEX { + t.Errorf("Opcode() = %s, want MSG_SYS_OPEN_MUTEX", pkt.Opcode()) + } +} + +// TestMsgSysCloseMutexOpcode tests Opcode method +func TestMsgSysCloseMutexOpcode(t *testing.T) { + pkt := &MsgSysCloseMutex{} + if pkt.Opcode() != network.MSG_SYS_CLOSE_MUTEX { + t.Errorf("Opcode() = %s, want MSG_SYS_CLOSE_MUTEX", pkt.Opcode()) + } +} + +// TestMsgSysDeleteSemaphoreOpcode tests Opcode method +func TestMsgSysDeleteSemaphoreOpcode(t *testing.T) { + pkt := &MsgSysDeleteSemaphore{} + if pkt.Opcode() != network.MSG_SYS_DELETE_SEMAPHORE { + t.Errorf("Opcode() = %s, want MSG_SYS_DELETE_SEMAPHORE", pkt.Opcode()) + } +} + +// TestMsgSysAcquireSemaphoreOpcode tests Opcode method +func TestMsgSysAcquireSemaphoreOpcode(t *testing.T) { + pkt := &MsgSysAcquireSemaphore{} + if pkt.Opcode() != network.MSG_SYS_ACQUIRE_SEMAPHORE { + t.Errorf("Opcode() = %s, want MSG_SYS_ACQUIRE_SEMAPHORE", pkt.Opcode()) + } +} + +// TestMsgSysReleaseSemaphoreOpcode tests Opcode method +func TestMsgSysReleaseSemaphoreOpcode(t *testing.T) { + pkt := &MsgSysReleaseSemaphore{} + if pkt.Opcode() != network.MSG_SYS_RELEASE_SEMAPHORE { + t.Errorf("Opcode() = %s, want MSG_SYS_RELEASE_SEMAPHORE", pkt.Opcode()) + } +} + +// TestMsgSysCheckSemaphoreOpcode tests Opcode method +func TestMsgSysCheckSemaphoreOpcode(t *testing.T) { + pkt := &MsgSysCheckSemaphore{} + if pkt.Opcode() != network.MSG_SYS_CHECK_SEMAPHORE { + t.Errorf("Opcode() = %s, want MSG_SYS_CHECK_SEMAPHORE", pkt.Opcode()) + } +} + +// TestMsgSysCreateAcquireSemaphoreOpcode tests Opcode method +func TestMsgSysCreateAcquireSemaphoreOpcode(t *testing.T) { + pkt := &MsgSysCreateAcquireSemaphore{} + if pkt.Opcode() != network.MSG_SYS_CREATE_ACQUIRE_SEMAPHORE { + t.Errorf("Opcode() = %s, want MSG_SYS_CREATE_ACQUIRE_SEMAPHORE", pkt.Opcode()) + } +} + +// TestMsgSysOperateRegisterOpcode tests Opcode method +func TestMsgSysOperateRegisterOpcode(t *testing.T) { + pkt := &MsgSysOperateRegister{} + if pkt.Opcode() != network.MSG_SYS_OPERATE_REGISTER { + t.Errorf("Opcode() = %s, want MSG_SYS_OPERATE_REGISTER", pkt.Opcode()) + } +} + +// TestMsgSysLoadRegisterOpcode tests Opcode method +func TestMsgSysLoadRegisterOpcode(t *testing.T) { + pkt := &MsgSysLoadRegister{} + if pkt.Opcode() != network.MSG_SYS_LOAD_REGISTER { + t.Errorf("Opcode() = %s, want MSG_SYS_LOAD_REGISTER", pkt.Opcode()) + } +} + +// TestMsgSysNotifyRegisterOpcode tests Opcode method +func TestMsgSysNotifyRegisterOpcode(t *testing.T) { + pkt := &MsgSysNotifyRegister{} + if pkt.Opcode() != network.MSG_SYS_NOTIFY_REGISTER { + t.Errorf("Opcode() = %s, want MSG_SYS_NOTIFY_REGISTER", pkt.Opcode()) + } +} + +// TestMsgSysCreateObjectOpcode tests Opcode method +func TestMsgSysCreateObjectOpcode(t *testing.T) { + pkt := &MsgSysCreateObject{} + if pkt.Opcode() != network.MSG_SYS_CREATE_OBJECT { + t.Errorf("Opcode() = %s, want MSG_SYS_CREATE_OBJECT", pkt.Opcode()) + } +} + +// TestMsgSysDeleteObjectOpcode tests Opcode method +func TestMsgSysDeleteObjectOpcode(t *testing.T) { + pkt := &MsgSysDeleteObject{} + if pkt.Opcode() != network.MSG_SYS_DELETE_OBJECT { + t.Errorf("Opcode() = %s, want MSG_SYS_DELETE_OBJECT", pkt.Opcode()) + } +} + +// TestMsgSysPositionObjectOpcode tests Opcode method +func TestMsgSysPositionObjectOpcode(t *testing.T) { + pkt := &MsgSysPositionObject{} + if pkt.Opcode() != network.MSG_SYS_POSITION_OBJECT { + t.Errorf("Opcode() = %s, want MSG_SYS_POSITION_OBJECT", pkt.Opcode()) + } +} + +// TestMsgSysRotateObjectOpcode tests Opcode method +func TestMsgSysRotateObjectOpcode(t *testing.T) { + pkt := &MsgSysRotateObject{} + if pkt.Opcode() != network.MSG_SYS_ROTATE_OBJECT { + t.Errorf("Opcode() = %s, want MSG_SYS_ROTATE_OBJECT", pkt.Opcode()) + } +} + +// TestMsgSysDuplicateObjectOpcode tests Opcode method +func TestMsgSysDuplicateObjectOpcode(t *testing.T) { + pkt := &MsgSysDuplicateObject{} + if pkt.Opcode() != network.MSG_SYS_DUPLICATE_OBJECT { + t.Errorf("Opcode() = %s, want MSG_SYS_DUPLICATE_OBJECT", pkt.Opcode()) + } +} + +// TestMsgSysSetObjectBinaryOpcode tests Opcode method +func TestMsgSysSetObjectBinaryOpcode(t *testing.T) { + pkt := &MsgSysSetObjectBinary{} + if pkt.Opcode() != network.MSG_SYS_SET_OBJECT_BINARY { + t.Errorf("Opcode() = %s, want MSG_SYS_SET_OBJECT_BINARY", pkt.Opcode()) + } +} + +// TestMsgSysGetObjectBinaryOpcode tests Opcode method +func TestMsgSysGetObjectBinaryOpcode(t *testing.T) { + pkt := &MsgSysGetObjectBinary{} + if pkt.Opcode() != network.MSG_SYS_GET_OBJECT_BINARY { + t.Errorf("Opcode() = %s, want MSG_SYS_GET_OBJECT_BINARY", pkt.Opcode()) + } +} + +// TestMsgSysGetObjectOwnerOpcode tests Opcode method +func TestMsgSysGetObjectOwnerOpcode(t *testing.T) { + pkt := &MsgSysGetObjectOwner{} + if pkt.Opcode() != network.MSG_SYS_GET_OBJECT_OWNER { + t.Errorf("Opcode() = %s, want MSG_SYS_GET_OBJECT_OWNER", pkt.Opcode()) + } +} + +// TestMsgSysUpdateObjectBinaryOpcode tests Opcode method +func TestMsgSysUpdateObjectBinaryOpcode(t *testing.T) { + pkt := &MsgSysUpdateObjectBinary{} + if pkt.Opcode() != network.MSG_SYS_UPDATE_OBJECT_BINARY { + t.Errorf("Opcode() = %s, want MSG_SYS_UPDATE_OBJECT_BINARY", pkt.Opcode()) + } +} + +// TestMsgSysCleanupObjectOpcode tests Opcode method +func TestMsgSysCleanupObjectOpcode(t *testing.T) { + pkt := &MsgSysCleanupObject{} + if pkt.Opcode() != network.MSG_SYS_CLEANUP_OBJECT { + t.Errorf("Opcode() = %s, want MSG_SYS_CLEANUP_OBJECT", pkt.Opcode()) + } +} + +// TestMsgSysInsertUserOpcode tests Opcode method +func TestMsgSysInsertUserOpcode(t *testing.T) { + pkt := &MsgSysInsertUser{} + if pkt.Opcode() != network.MSG_SYS_INSERT_USER { + t.Errorf("Opcode() = %s, want MSG_SYS_INSERT_USER", pkt.Opcode()) + } +} + +// TestMsgSysDeleteUserOpcode tests Opcode method +func TestMsgSysDeleteUserOpcode(t *testing.T) { + pkt := &MsgSysDeleteUser{} + if pkt.Opcode() != network.MSG_SYS_DELETE_USER { + t.Errorf("Opcode() = %s, want MSG_SYS_DELETE_USER", pkt.Opcode()) + } +} + +// TestMsgSysSetUserBinaryOpcode tests Opcode method +func TestMsgSysSetUserBinaryOpcode(t *testing.T) { + pkt := &MsgSysSetUserBinary{} + if pkt.Opcode() != network.MSG_SYS_SET_USER_BINARY { + t.Errorf("Opcode() = %s, want MSG_SYS_SET_USER_BINARY", pkt.Opcode()) + } +} + +// TestMsgSysGetUserBinaryOpcode tests Opcode method +func TestMsgSysGetUserBinaryOpcode(t *testing.T) { + pkt := &MsgSysGetUserBinary{} + if pkt.Opcode() != network.MSG_SYS_GET_USER_BINARY { + t.Errorf("Opcode() = %s, want MSG_SYS_GET_USER_BINARY", pkt.Opcode()) + } +} + +// TestMsgSysNotifyUserBinaryOpcode tests Opcode method +func TestMsgSysNotifyUserBinaryOpcode(t *testing.T) { + pkt := &MsgSysNotifyUserBinary{} + if pkt.Opcode() != network.MSG_SYS_NOTIFY_USER_BINARY { + t.Errorf("Opcode() = %s, want MSG_SYS_NOTIFY_USER_BINARY", pkt.Opcode()) + } +} + +// TestMsgSysUpdateRightOpcode tests Opcode method +func TestMsgSysUpdateRightOpcode(t *testing.T) { + pkt := &MsgSysUpdateRight{} + if pkt.Opcode() != network.MSG_SYS_UPDATE_RIGHT { + t.Errorf("Opcode() = %s, want MSG_SYS_UPDATE_RIGHT", pkt.Opcode()) + } +} + +// TestMsgSysAuthQueryOpcode tests Opcode method +func TestMsgSysAuthQueryOpcode(t *testing.T) { + pkt := &MsgSysAuthQuery{} + if pkt.Opcode() != network.MSG_SYS_AUTH_QUERY { + t.Errorf("Opcode() = %s, want MSG_SYS_AUTH_QUERY", pkt.Opcode()) + } +} + +// TestMsgSysAuthDataOpcode tests Opcode method +func TestMsgSysAuthDataOpcode(t *testing.T) { + pkt := &MsgSysAuthData{} + if pkt.Opcode() != network.MSG_SYS_AUTH_DATA { + t.Errorf("Opcode() = %s, want MSG_SYS_AUTH_DATA", pkt.Opcode()) + } +} + +// TestMsgSysAuthTerminalOpcode tests Opcode method +func TestMsgSysAuthTerminalOpcode(t *testing.T) { + pkt := &MsgSysAuthTerminal{} + if pkt.Opcode() != network.MSG_SYS_AUTH_TERMINAL { + t.Errorf("Opcode() = %s, want MSG_SYS_AUTH_TERMINAL", pkt.Opcode()) + } +} + +// TestMsgSysRightsReloadOpcode tests Opcode method +func TestMsgSysRightsReloadOpcode(t *testing.T) { + pkt := &MsgSysRightsReload{} + if pkt.Opcode() != network.MSG_SYS_RIGHTS_RELOAD { + t.Errorf("Opcode() = %s, want MSG_SYS_RIGHTS_RELOAD", pkt.Opcode()) + } +} + +// TestMsgSysTerminalLogOpcode tests Opcode method +func TestMsgSysTerminalLogOpcode(t *testing.T) { + pkt := &MsgSysTerminalLog{} + if pkt.Opcode() != network.MSG_SYS_TERMINAL_LOG { + t.Errorf("Opcode() = %s, want MSG_SYS_TERMINAL_LOG", pkt.Opcode()) + } +} + +// TestMsgSysIssueLogkeyOpcode tests Opcode method +func TestMsgSysIssueLogkeyOpcode(t *testing.T) { + pkt := &MsgSysIssueLogkey{} + if pkt.Opcode() != network.MSG_SYS_ISSUE_LOGKEY { + t.Errorf("Opcode() = %s, want MSG_SYS_ISSUE_LOGKEY", pkt.Opcode()) + } +} + +// TestMsgSysRecordLogOpcode tests Opcode method +func TestMsgSysRecordLogOpcode(t *testing.T) { + pkt := &MsgSysRecordLog{} + if pkt.Opcode() != network.MSG_SYS_RECORD_LOG { + t.Errorf("Opcode() = %s, want MSG_SYS_RECORD_LOG", pkt.Opcode()) + } +} + +// TestMsgSysEchoOpcode tests Opcode method +func TestMsgSysEchoOpcode(t *testing.T) { + pkt := &MsgSysEcho{} + if pkt.Opcode() != network.MSG_SYS_ECHO { + t.Errorf("Opcode() = %s, want MSG_SYS_ECHO", pkt.Opcode()) + } +} + +// TestMsgSysGetFileOpcode tests Opcode method +func TestMsgSysGetFileOpcode(t *testing.T) { + pkt := &MsgSysGetFile{} + if pkt.Opcode() != network.MSG_SYS_GET_FILE { + t.Errorf("Opcode() = %s, want MSG_SYS_GET_FILE", pkt.Opcode()) + } +} + +// TestMsgSysHideClientOpcode tests Opcode method +func TestMsgSysHideClientOpcode(t *testing.T) { + pkt := &MsgSysHideClient{} + if pkt.Opcode() != network.MSG_SYS_HIDE_CLIENT { + t.Errorf("Opcode() = %s, want MSG_SYS_HIDE_CLIENT", pkt.Opcode()) + } +} + +// TestMsgSysSetStatusOpcode tests Opcode method +func TestMsgSysSetStatusOpcode(t *testing.T) { + pkt := &MsgSysSetStatus{} + if pkt.Opcode() != network.MSG_SYS_SET_STATUS { + t.Errorf("Opcode() = %s, want MSG_SYS_SET_STATUS", pkt.Opcode()) + } +} + +// TestMsgSysStageDestructOpcode tests Opcode method +func TestMsgSysStageDestructOpcode(t *testing.T) { + pkt := &MsgSysStageDestruct{} + if pkt.Opcode() != network.MSG_SYS_STAGE_DESTRUCT { + t.Errorf("Opcode() = %s, want MSG_SYS_STAGE_DESTRUCT", pkt.Opcode()) + } +} + +// TestMsgSysLeaveStageOpcode tests Opcode method +func TestMsgSysLeaveStageOpcode(t *testing.T) { + pkt := &MsgSysLeaveStage{} + if pkt.Opcode() != network.MSG_SYS_LEAVE_STAGE { + t.Errorf("Opcode() = %s, want MSG_SYS_LEAVE_STAGE", pkt.Opcode()) + } +} + +// TestMsgSysReserveStageOpcode tests Opcode method +func TestMsgSysReserveStageOpcode(t *testing.T) { + pkt := &MsgSysReserveStage{} + if pkt.Opcode() != network.MSG_SYS_RESERVE_STAGE { + t.Errorf("Opcode() = %s, want MSG_SYS_RESERVE_STAGE", pkt.Opcode()) + } +} + +// TestMsgSysUnreserveStageOpcode tests Opcode method +func TestMsgSysUnreserveStageOpcode(t *testing.T) { + pkt := &MsgSysUnreserveStage{} + if pkt.Opcode() != network.MSG_SYS_UNRESERVE_STAGE { + t.Errorf("Opcode() = %s, want MSG_SYS_UNRESERVE_STAGE", pkt.Opcode()) + } +} + +// TestMsgSysSetStagePassOpcode tests Opcode method +func TestMsgSysSetStagePassOpcode(t *testing.T) { + pkt := &MsgSysSetStagePass{} + if pkt.Opcode() != network.MSG_SYS_SET_STAGE_PASS { + t.Errorf("Opcode() = %s, want MSG_SYS_SET_STAGE_PASS", pkt.Opcode()) + } +} + +// TestMsgSysLockGlobalSemaOpcode tests Opcode method +func TestMsgSysLockGlobalSemaOpcode(t *testing.T) { + pkt := &MsgSysLockGlobalSema{} + if pkt.Opcode() != network.MSG_SYS_LOCK_GLOBAL_SEMA { + t.Errorf("Opcode() = %s, want MSG_SYS_LOCK_GLOBAL_SEMA", pkt.Opcode()) + } +} + +// TestMsgSysUnlockGlobalSemaOpcode tests Opcode method +func TestMsgSysUnlockGlobalSemaOpcode(t *testing.T) { + pkt := &MsgSysUnlockGlobalSema{} + if pkt.Opcode() != network.MSG_SYS_UNLOCK_GLOBAL_SEMA { + t.Errorf("Opcode() = %s, want MSG_SYS_UNLOCK_GLOBAL_SEMA", pkt.Opcode()) + } +} + +// TestMsgSysTransBinaryOpcode tests Opcode method +func TestMsgSysTransBinaryOpcode(t *testing.T) { + pkt := &MsgSysTransBinary{} + if pkt.Opcode() != network.MSG_SYS_TRANS_BINARY { + t.Errorf("Opcode() = %s, want MSG_SYS_TRANS_BINARY", pkt.Opcode()) + } +} + +// TestMsgSysCollectBinaryOpcode tests Opcode method +func TestMsgSysCollectBinaryOpcode(t *testing.T) { + pkt := &MsgSysCollectBinary{} + if pkt.Opcode() != network.MSG_SYS_COLLECT_BINARY { + t.Errorf("Opcode() = %s, want MSG_SYS_COLLECT_BINARY", pkt.Opcode()) + } +} + +// TestMsgSysGetStateOpcode tests Opcode method +func TestMsgSysGetStateOpcode(t *testing.T) { + pkt := &MsgSysGetState{} + if pkt.Opcode() != network.MSG_SYS_GET_STATE { + t.Errorf("Opcode() = %s, want MSG_SYS_GET_STATE", pkt.Opcode()) + } +} + +// TestMsgSysSerializeOpcode tests Opcode method +func TestMsgSysSerializeOpcode(t *testing.T) { + pkt := &MsgSysSerialize{} + if pkt.Opcode() != network.MSG_SYS_SERIALIZE { + t.Errorf("Opcode() = %s, want MSG_SYS_SERIALIZE", pkt.Opcode()) + } +} + +// TestMsgSysEnumlobbyOpcode tests Opcode method +func TestMsgSysEnumlobbyOpcode(t *testing.T) { + pkt := &MsgSysEnumlobby{} + if pkt.Opcode() != network.MSG_SYS_ENUMLOBBY { + t.Errorf("Opcode() = %s, want MSG_SYS_ENUMLOBBY", pkt.Opcode()) + } +} + +// TestMsgSysEnumuserOpcode tests Opcode method +func TestMsgSysEnumuserOpcode(t *testing.T) { + pkt := &MsgSysEnumuser{} + if pkt.Opcode() != network.MSG_SYS_ENUMUSER { + t.Errorf("Opcode() = %s, want MSG_SYS_ENUMUSER", pkt.Opcode()) + } +} + +// TestMsgSysInfokyserverOpcode tests Opcode method +func TestMsgSysInfokyserverOpcode(t *testing.T) { + pkt := &MsgSysInfokyserver{} + if pkt.Opcode() != network.MSG_SYS_INFOKYSERVER { + t.Errorf("Opcode() = %s, want MSG_SYS_INFOKYSERVER", pkt.Opcode()) + } +} + +// TestMsgSysExtendThresholdOpcode tests Opcode method +func TestMsgSysExtendThresholdOpcode(t *testing.T) { + pkt := &MsgSysExtendThreshold{} + if pkt.Opcode() != network.MSG_SYS_EXTEND_THRESHOLD { + t.Errorf("Opcode() = %s, want MSG_SYS_EXTEND_THRESHOLD", pkt.Opcode()) + } +} + +// TestMsgSysAddObjectOpcode tests Opcode method +func TestMsgSysAddObjectOpcode(t *testing.T) { + pkt := &MsgSysAddObject{} + if pkt.Opcode() != network.MSG_SYS_ADD_OBJECT { + t.Errorf("Opcode() = %s, want MSG_SYS_ADD_OBJECT", pkt.Opcode()) + } +} + +// TestMsgSysDelObjectOpcode tests Opcode method +func TestMsgSysDelObjectOpcode(t *testing.T) { + pkt := &MsgSysDelObject{} + if pkt.Opcode() != network.MSG_SYS_DEL_OBJECT { + t.Errorf("Opcode() = %s, want MSG_SYS_DEL_OBJECT", pkt.Opcode()) + } +} + +// TestMsgSysDispObjectOpcode tests Opcode method +func TestMsgSysDispObjectOpcode(t *testing.T) { + pkt := &MsgSysDispObject{} + if pkt.Opcode() != network.MSG_SYS_DISP_OBJECT { + t.Errorf("Opcode() = %s, want MSG_SYS_DISP_OBJECT", pkt.Opcode()) + } +} + +// TestMsgSysHideObjectOpcode tests Opcode method +func TestMsgSysHideObjectOpcode(t *testing.T) { + pkt := &MsgSysHideObject{} + if pkt.Opcode() != network.MSG_SYS_HIDE_OBJECT { + t.Errorf("Opcode() = %s, want MSG_SYS_HIDE_OBJECT", pkt.Opcode()) + } +} diff --git a/server/channelserver/compression/deltacomp/deltacomp_test.go b/server/channelserver/compression/deltacomp/deltacomp_test.go index 11da4fc9f..e21fff5e4 100644 --- a/server/channelserver/compression/deltacomp/deltacomp_test.go +++ b/server/channelserver/compression/deltacomp/deltacomp_test.go @@ -111,3 +111,87 @@ func TestDeltaPatch(t *testing.T) { }) } } + +func TestApplyDataDiffEmptyDiff(t *testing.T) { + baseData := []byte{1, 2, 3, 4, 5} + diff := []byte{} + + result := ApplyDataDiff(diff, baseData) + if !bytes.Equal(result, baseData) { + t.Errorf("ApplyDataDiff with empty diff should return base data") + } +} + +func TestApplyDataDiffEmptyBase(t *testing.T) { + baseData := []byte{} + diff := []byte{} + + result := ApplyDataDiff(diff, baseData) + if len(result) != 0 { + t.Errorf("ApplyDataDiff with empty base and diff should return empty") + } +} + +func TestCheckReadUint8Error(t *testing.T) { + r := bytes.NewReader([]byte{}) + _, err := checkReadUint8(r) + if err == nil { + t.Error("checkReadUint8 on empty reader should return error") + } +} + +func TestCheckReadUint16Error(t *testing.T) { + r := bytes.NewReader([]byte{0x01}) // Only 1 byte, need 2 + _, err := checkReadUint16(r) + if err == nil { + t.Error("checkReadUint16 with insufficient data should return error") + } +} + +func TestCheckReadUint16Success(t *testing.T) { + r := bytes.NewReader([]byte{0x12, 0x34}) + val, err := checkReadUint16(r) + if err != nil { + t.Errorf("checkReadUint16 error = %v", err) + } + if val != 0x1234 { + t.Errorf("checkReadUint16 = 0x%04X, want 0x1234", val) + } +} + +func TestReadCountError(t *testing.T) { + r := bytes.NewReader([]byte{}) + _, err := readCount(r) + if err == nil { + t.Error("readCount on empty reader should return error") + } +} + +func TestReadCountExtended(t *testing.T) { + // When count8 is 0, read count16 + r := bytes.NewReader([]byte{0x00, 0x01, 0x00}) // count8=0, count16=256 + count, err := readCount(r) + if err != nil { + t.Errorf("readCount error = %v", err) + } + if count != 256 { + t.Errorf("readCount = %d, want 256", count) + } +} + +func TestReadCountExtendedError(t *testing.T) { + // count8 is 0 but not enough bytes for count16 + r := bytes.NewReader([]byte{0x00, 0x01}) + _, err := readCount(r) + if err == nil { + t.Error("readCount with insufficient data for count16 should return error") + } +} + +func TestCheckReadUint16EmptyReader(t *testing.T) { + r := bytes.NewReader([]byte{}) + _, err := checkReadUint16(r) + if err == nil { + t.Error("checkReadUint16 on empty reader should return error") + } +} diff --git a/server/channelserver/timeserver/time_mode_test.go b/server/channelserver/timeserver/time_mode_test.go new file mode 100644 index 000000000..91785094f --- /dev/null +++ b/server/channelserver/timeserver/time_mode_test.go @@ -0,0 +1,150 @@ +package timeserver + +import ( + "testing" + "time" +) + +func TestPFaddTime(t *testing.T) { + // Save original state + originalPnewtime := Pnewtime + defer func() { Pnewtime = originalPnewtime }() + + Pnewtime = 0 + + // First call should return 24 + result := PFadd_time() + if result != time.Duration(24) { + t.Errorf("PFadd_time() = %v, want 24", result) + } + + // Second call should return 48 + result = PFadd_time() + if result != time.Duration(48) { + t.Errorf("PFadd_time() second call = %v, want 48", result) + } + + // Check Pfixtimer is updated + if Pfixtimer != time.Duration(48) { + t.Errorf("Pfixtimer = %v, want 48", Pfixtimer) + } +} + +func TestTimeCurrent(t *testing.T) { + result := TimeCurrent() + if result.IsZero() { + t.Error("TimeCurrent() returned zero time") + } + + // Result should be in the past (7 years ago) + now := time.Now() + diff := now.Year() - result.Year() + if diff != 7 { + t.Errorf("TimeCurrent() year diff = %d, want 7", diff) + } +} + +func TestTimeMidnight(t *testing.T) { + result := Time_midnight() + if result.IsZero() { + t.Error("Time_midnight() returned zero time") + } + + // Result should be midnight (with hour added, so 1:00 AM) + if result.Minute() != 0 { + t.Errorf("Time_midnight() minute = %d, want 0", result.Minute()) + } + if result.Second() != 0 { + t.Errorf("Time_midnight() second = %d, want 0", result.Second()) + } +} + +func TestTimeStatic(t *testing.T) { + // Reset state for testing + DoOnce_t = false + Fix_t = time.Time{} + + result := Time_static() + if result.IsZero() { + t.Error("Time_static() returned zero time") + } + + // Calling again should return same time (static) + result2 := Time_static() + if !result.Equal(result2) { + t.Error("Time_static() should return same time on second call") + } +} + +func TestTstaticMidnight(t *testing.T) { + // Reset state for testing + DoOnce_midnight = false + Fix_midnight = time.Time{} + + result := Tstatic_midnight() + if result.IsZero() { + t.Error("Tstatic_midnight() returned zero time") + } + + // Calling again should return same time (static) + result2 := Tstatic_midnight() + if !result.Equal(result2) { + t.Error("Tstatic_midnight() should return same time on second call") + } +} + +func TestTimeCurrentWeekUint8(t *testing.T) { + result := Time_Current_Week_uint8() + + // Week of month should be 1-5 + if result < 1 || result > 5 { + t.Errorf("Time_Current_Week_uint8() = %d, expected 1-5", result) + } +} + +func TestTimeCurrentWeekUint32(t *testing.T) { + result := Time_Current_Week_uint32() + + // Week of month should be 1-5 + if result < 1 || result > 5 { + t.Errorf("Time_Current_Week_uint32() = %d, expected 1-5", result) + } +} + +func TestDetectDay(t *testing.T) { + result := Detect_Day() + + // Result should be bool, and true only on Wednesday + isWednesday := time.Now().Weekday() == time.Wednesday + if result != isWednesday { + t.Errorf("Detect_Day() = %v, expected %v (today is %v)", result, isWednesday, time.Now().Weekday()) + } +} + +func TestGlobalVariables(t *testing.T) { + // Test that global variables exist and have expected default types + _ = DoOnce_midnight + _ = DoOnce_t2 + _ = DoOnce_t + _ = Fix_midnight + _ = Fix_t2 + _ = Fix_t + _ = Pfixtimer + _ = Pnewtime +} + +func TestTimeConsistency(t *testing.T) { + // Test that TimeCurrent and Time_midnight are on the same day + current := TimeCurrent() + midnight := Time_midnight() + + if current.Year() != midnight.Year() { + t.Errorf("Year mismatch: current=%d, midnight=%d", current.Year(), midnight.Year()) + } + if current.Month() != midnight.Month() { + t.Errorf("Month mismatch: current=%v, midnight=%v", current.Month(), midnight.Month()) + } + if current.Day() != midnight.Day() { + t.Errorf("Day mismatch: current=%d, midnight=%d", current.Day(), midnight.Day()) + } +} diff --git a/server/entranceserver/entrance_server_test.go b/server/entranceserver/entrance_server_test.go new file mode 100644 index 000000000..e0e5a53f4 --- /dev/null +++ b/server/entranceserver/entrance_server_test.go @@ -0,0 +1,62 @@ +package entranceserver + +import ( + "testing" + + "erupe-ce/config" +) + +func TestNewServer(t *testing.T) { + cfg := &Config{ + Logger: nil, + DB: nil, + ErupeConfig: &config.Config{}, + } + + s := NewServer(cfg) + if s == nil { + t.Fatal("NewServer() returned nil") + } + if s.isShuttingDown { + t.Error("New server should not be shutting down") + } + if s.erupeConfig == nil { + t.Error("erupeConfig should not be nil") + } +} + +func TestNewServerWithNilConfig(t *testing.T) { + cfg := &Config{} + s := NewServer(cfg) + if s == nil { + t.Fatal("NewServer() returned nil for empty config") + } +} + +func TestServerType(t *testing.T) { + s := &Server{} + if s.isShuttingDown { + t.Error("Zero value server should not be shutting down") + } + if s.listener != nil { + t.Error("Zero value server should have nil listener") + } +} + +func TestConfigFields(t *testing.T) { + cfg := &Config{ + Logger: nil, + DB: nil, + ErupeConfig: nil, + } + + if cfg.Logger != nil { + t.Error("Config Logger should be nil") + } + if cfg.DB != nil { + t.Error("Config DB should be nil") + } + if cfg.ErupeConfig != nil { + t.Error("Config ErupeConfig should be nil") + } +} diff --git a/server/signserver/sign_server_test.go b/server/signserver/sign_server_test.go index 65e95df8f..9846009f5 100644 --- a/server/signserver/sign_server_test.go +++ b/server/signserver/sign_server_test.go @@ -210,3 +210,59 @@ func TestFailureRespIsMinimal(t *testing.T) { } } } + +func TestNewServer(t *testing.T) { + // Test that NewServer creates a valid server + cfg := &Config{ + Logger: nil, + DB: nil, + ErupeConfig: nil, + } + + s := NewServer(cfg) + if s == nil { + t.Fatal("NewServer() returned nil") + } + if s.isShuttingDown { + t.Error("New server should not be shutting down") + } +} + +func TestNewServerWithNilConfig(t *testing.T) { + // Testing with nil fields in config + cfg := &Config{} + s := NewServer(cfg) + if s == nil { + t.Fatal("NewServer() returned nil for empty config") + } +} + +func TestServerType(t *testing.T) { + // Test Server struct fields + s := &Server{} + if s.isShuttingDown { + t.Error("Zero value server should not be shutting down") + } + if s.sessions != nil { + t.Error("Zero value server should have nil sessions map") + } +} + +func TestConfigFields(t *testing.T) { + // Test Config struct fields + cfg := &Config{ + Logger: nil, + DB: nil, + ErupeConfig: nil, + } + + if cfg.Logger != nil { + t.Error("Config Logger should be nil") + } + if cfg.DB != nil { + t.Error("Config DB should be nil") + } + if cfg.ErupeConfig != nil { + t.Error("Config ErupeConfig should be nil") + } +}