package channelserver import ( "testing" "time" "erupe-ce/common/byteframe" "erupe-ce/common/mhfitem" "erupe-ce/network/mhfpacket" ) // --- userGetItems tests --- func TestUserGetItems_NilData(t *testing.T) { server := createMockServer() userMock := &mockUserRepoForItems{itemBoxData: nil} server.userRepo = userMock session := createMockSession(1, server) session.userID = 1 items := userGetItems(session) if len(items) != 0 { t.Errorf("Expected empty items, got %d", len(items)) } } func TestUserGetItems_DBError(t *testing.T) { server := createMockServer() userMock := &mockUserRepoForItems{itemBoxErr: errNotFound} server.userRepo = userMock session := createMockSession(1, server) session.userID = 1 items := userGetItems(session) if len(items) != 0 { t.Errorf("Expected empty items on error, got %d", len(items)) } } func TestUserGetItems_ParsesData(t *testing.T) { // Build serialized item box with 1 item bf := byteframe.NewByteFrame() bf.WriteUint16(1) // numStacks bf.WriteUint16(0) // unused // Item stack: warehouseID(4) + itemID(2) + quantity(2) + unk0(4) = 12 bytes bf.WriteUint32(100) // warehouseID bf.WriteUint16(500) // itemID bf.WriteUint16(3) // quantity bf.WriteUint32(0) // unk0 server := createMockServer() userMock := &mockUserRepoForItems{itemBoxData: bf.Data()} server.userRepo = userMock session := createMockSession(1, server) session.userID = 1 items := userGetItems(session) if len(items) != 1 { t.Fatalf("Expected 1 item, got %d", len(items)) } if items[0].Item.ItemID != 500 { t.Errorf("ItemID = %d, want 500", items[0].Item.ItemID) } if items[0].Quantity != 3 { t.Errorf("Quantity = %d, want 3", items[0].Quantity) } } // --- handleMsgMhfCheckWeeklyStamp tests --- func TestCheckWeeklyStamp_InvalidType(t *testing.T) { server := createMockServer() session := createMockSession(1, server) pkt := &mhfpacket.MsgMhfCheckWeeklyStamp{ AckHandle: 100, StampType: "invalid", } handleMsgMhfCheckWeeklyStamp(session, pkt) select { case <-session.sendPackets: default: t.Error("No response packet queued") } } func TestCheckWeeklyStamp_FirstCheck(t *testing.T) { server := createMockServer() stampMock := &mockStampRepoForItems{ checkedErr: errNotFound, // no existing record totals: [2]uint16{0, 0}, } server.stampRepo = stampMock session := createMockSession(1, server) pkt := &mhfpacket.MsgMhfCheckWeeklyStamp{ AckHandle: 100, StampType: "hl", } handleMsgMhfCheckWeeklyStamp(session, pkt) if !stampMock.initCalled { t.Error("Init should be called on first check") } select { case p := <-session.sendPackets: if len(p.data) < 14 { t.Errorf("Response too short: %d bytes", len(p.data)) } default: t.Error("No response packet queued") } } func TestCheckWeeklyStamp_WithinWeek(t *testing.T) { server := createMockServer() stampMock := &mockStampRepoForItems{ checkedTime: TimeAdjusted(), // checked right now (within this week) totals: [2]uint16{3, 1}, } server.stampRepo = stampMock session := createMockSession(1, server) pkt := &mhfpacket.MsgMhfCheckWeeklyStamp{ AckHandle: 100, StampType: "hl", } handleMsgMhfCheckWeeklyStamp(session, pkt) if stampMock.incrementCalled { t.Error("IncrementTotal should not be called within same week") } select { case <-session.sendPackets: default: t.Error("No response packet queued") } } func TestCheckWeeklyStamp_WeekRollover(t *testing.T) { server := createMockServer() stampMock := &mockStampRepoForItems{ checkedTime: TimeWeekStart().Add(-24 * time.Hour), // before this week totals: [2]uint16{5, 2}, } server.stampRepo = stampMock session := createMockSession(1, server) pkt := &mhfpacket.MsgMhfCheckWeeklyStamp{ AckHandle: 100, StampType: "ex", } handleMsgMhfCheckWeeklyStamp(session, pkt) if !stampMock.incrementCalled { t.Error("IncrementTotal should be called after week rollover") } select { case <-session.sendPackets: default: t.Error("No response packet queued") } } func TestCheckWeeklyStamp_GetTotalsError(t *testing.T) { server := createMockServer() stampMock := &mockStampRepoForItems{ checkedTime: TimeAdjusted(), totalsErr: errNotFound, } server.stampRepo = stampMock session := createMockSession(1, server) pkt := &mhfpacket.MsgMhfCheckWeeklyStamp{ AckHandle: 100, StampType: "hl", } // Should not panic; logs warning, returns zeros handleMsgMhfCheckWeeklyStamp(session, pkt) select { case <-session.sendPackets: default: t.Error("No response packet queued") } } // --- handleMsgMhfExchangeWeeklyStamp tests --- func TestExchangeWeeklyStamp_InvalidType(t *testing.T) { server := createMockServer() session := createMockSession(1, server) pkt := &mhfpacket.MsgMhfExchangeWeeklyStamp{ AckHandle: 100, StampType: "invalid", } handleMsgMhfExchangeWeeklyStamp(session, pkt) select { case <-session.sendPackets: default: t.Error("No response packet queued") } } func TestExchangeWeeklyStamp_HL(t *testing.T) { server := createMockServer() stampMock := &mockStampRepoForItems{ exchangeResult: [2]uint16{10, 5}, } houseMock := newMockHouseRepoForItems() server.stampRepo = stampMock server.houseRepo = houseMock session := createMockSession(1, server) pkt := &mhfpacket.MsgMhfExchangeWeeklyStamp{ AckHandle: 100, StampType: "hl", } handleMsgMhfExchangeWeeklyStamp(session, pkt) // Verify warehouse gift box was updated (index 10) if houseMock.setData[10] == nil { t.Error("Gift box should be updated with ticket item") } // Parse the gift box to verify the item if len(houseMock.setData[10]) > 0 { bf := byteframe.NewByteFrameFromBytes(houseMock.setData[10]) count := bf.ReadUint16() if count != 1 { t.Errorf("Expected 1 item in gift box, got %d", count) } bf.ReadUint16() // unused item := mhfitem.ReadWarehouseItem(bf) if item.Item.ItemID != 1630 { t.Errorf("ItemID = %d, want 1630 (HL ticket)", item.Item.ItemID) } } select { case <-session.sendPackets: default: t.Error("No response packet queued") } } func TestExchangeWeeklyStamp_EX(t *testing.T) { server := createMockServer() stampMock := &mockStampRepoForItems{ exchangeResult: [2]uint16{10, 5}, } houseMock := newMockHouseRepoForItems() server.stampRepo = stampMock server.houseRepo = houseMock session := createMockSession(1, server) pkt := &mhfpacket.MsgMhfExchangeWeeklyStamp{ AckHandle: 100, StampType: "ex", } handleMsgMhfExchangeWeeklyStamp(session, pkt) if houseMock.setData[10] == nil { t.Error("Gift box should be updated with ticket item") } if len(houseMock.setData[10]) > 0 { bf := byteframe.NewByteFrameFromBytes(houseMock.setData[10]) count := bf.ReadUint16() if count != 1 { t.Errorf("Expected 1 item in gift box, got %d", count) } bf.ReadUint16() // unused item := mhfitem.ReadWarehouseItem(bf) if item.Item.ItemID != 1631 { t.Errorf("ItemID = %d, want 1631 (EX ticket)", item.Item.ItemID) } } select { case <-session.sendPackets: default: t.Error("No response packet queued") } } func TestExchangeWeeklyStamp_ExchangeError(t *testing.T) { server := createMockServer() stampMock := &mockStampRepoForItems{ exchangeErr: errNotFound, } server.stampRepo = stampMock session := createMockSession(1, server) pkt := &mhfpacket.MsgMhfExchangeWeeklyStamp{ AckHandle: 100, StampType: "hl", } handleMsgMhfExchangeWeeklyStamp(session, pkt) // Should return fail ack select { case <-session.sendPackets: default: t.Error("No response packet queued") } } // Tests consolidated from handlers_coverage3_test.go func TestNonTrivialHandlers_NoDB_Items(t *testing.T) { server := createMockServer() t.Run("handleMsgMhfTransferItem", func(t *testing.T) { session := createMockSession(1, server) handleMsgMhfTransferItem(session, &mhfpacket.MsgMhfTransferItem{AckHandle: 1}) select { case p := <-session.sendPackets: if len(p.data) == 0 { t.Error("response should have data") } default: t.Error("no response queued") } }) t.Run("handleMsgMhfEnumerateOrder", func(t *testing.T) { session := createMockSession(1, server) handleMsgMhfEnumerateOrder(session, &mhfpacket.MsgMhfEnumerateOrder{AckHandle: 1}) select { case p := <-session.sendPackets: if len(p.data) == 0 { t.Error("response should have data") } default: t.Error("no response queued") } }) t.Run("handleMsgMhfEnumeratePrice", func(t *testing.T) { session := createMockSession(1, server) handleMsgMhfEnumeratePrice(session, &mhfpacket.MsgMhfEnumeratePrice{AckHandle: 1}) select { case p := <-session.sendPackets: if len(p.data) == 0 { t.Error("response should have data") } default: t.Error("no response queued") } }) } func TestExchangeWeeklyStamp_Yearly(t *testing.T) { server := createMockServer() stampMock := &mockStampRepoForItems{ yearlyResult: [2]uint16{20, 10}, } houseMock := newMockHouseRepoForItems() server.stampRepo = stampMock server.houseRepo = houseMock session := createMockSession(1, server) pkt := &mhfpacket.MsgMhfExchangeWeeklyStamp{ AckHandle: 100, StampType: "ex", ExchangeType: 10, // Yearly } handleMsgMhfExchangeWeeklyStamp(session, pkt) if houseMock.setData[10] == nil { t.Error("Gift box should be updated with yearly ticket") } if len(houseMock.setData[10]) > 0 { bf := byteframe.NewByteFrameFromBytes(houseMock.setData[10]) count := bf.ReadUint16() if count != 1 { t.Errorf("Expected 1 item in gift box, got %d", count) } bf.ReadUint16() // unused item := mhfitem.ReadWarehouseItem(bf) if item.Item.ItemID != 2210 { t.Errorf("ItemID = %d, want 2210 (yearly ticket)", item.Item.ItemID) } } select { case <-session.sendPackets: default: t.Error("No response packet queued") } } // --- handleMsgMhfEnumerateUnionItem tests --- func TestEnumerateUnionItem_WithItems(t *testing.T) { server := createMockServer() // Build serialized item box with 1 item bf := byteframe.NewByteFrame() bf.WriteUint16(1) // numStacks bf.WriteUint16(0) // unused bf.WriteUint32(100) // warehouseID bf.WriteUint16(500) // itemID bf.WriteUint16(3) // quantity bf.WriteUint32(0) // unk0 userMock := &mockUserRepoForItems{itemBoxData: bf.Data()} server.userRepo = userMock session := createMockSession(1, server) session.userID = 1 pkt := &mhfpacket.MsgMhfEnumerateUnionItem{AckHandle: 100} handleMsgMhfEnumerateUnionItem(session, pkt) select { case p := <-session.sendPackets: if len(p.data) == 0 { t.Error("Response should have data") } default: t.Error("No response packet queued") } } func TestEnumerateUnionItem_Empty(t *testing.T) { server := createMockServer() userMock := &mockUserRepoForItems{itemBoxData: nil} server.userRepo = userMock session := createMockSession(1, server) session.userID = 1 pkt := &mhfpacket.MsgMhfEnumerateUnionItem{AckHandle: 100} handleMsgMhfEnumerateUnionItem(session, pkt) select { case <-session.sendPackets: default: t.Error("No response packet queued") } } // --- handleMsgMhfUpdateUnionItem tests --- func TestUpdateUnionItem(t *testing.T) { server := createMockServer() bf := byteframe.NewByteFrame() bf.WriteUint16(1) // numStacks bf.WriteUint16(0) // unused bf.WriteUint32(100) // warehouseID bf.WriteUint16(500) // itemID bf.WriteUint16(3) // quantity bf.WriteUint32(0) // unk0 userMock := &mockUserRepoForItems{itemBoxData: bf.Data()} server.userRepo = userMock session := createMockSession(1, server) session.userID = 1 pkt := &mhfpacket.MsgMhfUpdateUnionItem{ AckHandle: 100, UpdatedItems: []mhfitem.MHFItemStack{}, } handleMsgMhfUpdateUnionItem(session, pkt) select { case <-session.sendPackets: default: t.Error("No response packet queued") } } // Tests consolidated from handlers_core_test.go func TestHandleMsgMhfGetExtraInfo(t *testing.T) { server := createMockServer() session := createMockSession(1, server) defer func() { if r := recover(); r != nil { t.Errorf("handleMsgMhfGetExtraInfo panicked: %v", r) } }() handleMsgMhfGetExtraInfo(session, nil) } func TestHandleMsgMhfTransferItem(t *testing.T) { server := createMockServer() session := createMockSession(1, server) pkt := &mhfpacket.MsgMhfTransferItem{ AckHandle: 12345, } handleMsgMhfTransferItem(session, pkt) select { case p := <-session.sendPackets: if len(p.data) == 0 { t.Error("Response packet should have data") } default: t.Error("No response packet queued") } } func TestHandleMsgMhfEnumeratePrice(t *testing.T) { server := createMockServer() session := createMockSession(1, server) pkt := &mhfpacket.MsgMhfEnumeratePrice{ AckHandle: 12345, } handleMsgMhfEnumeratePrice(session, pkt) select { case p := <-session.sendPackets: if len(p.data) == 0 { t.Error("Response packet should have data") } default: t.Error("No response packet queued") } } func TestHandleMsgMhfEnumerateOrder(t *testing.T) { server := createMockServer() session := createMockSession(1, server) pkt := &mhfpacket.MsgMhfEnumerateOrder{ AckHandle: 12345, } handleMsgMhfEnumerateOrder(session, pkt) select { case p := <-session.sendPackets: if len(p.data) == 0 { t.Error("Response packet should have data") } default: t.Error("No response packet queued") } }