style: run gofmt across entire codebase

330 non-vendor files had minor formatting inconsistencies
(comment alignment, whitespace). No logic changes.
This commit is contained in:
Houmgaor
2026-02-23 21:28:30 +01:00
parent 385b974adc
commit 48639942f6
330 changed files with 1841 additions and 1809 deletions

View File

@@ -3,8 +3,8 @@ package api
import (
"context"
"database/sql"
"erupe-ce/common/token"
"errors"
"erupe-ce/common/token"
"fmt"
"time"

View File

@@ -67,11 +67,11 @@ func TestUserIDFromTokenScenarios(t *testing.T) {
// TestGetReturnExpiryCalculation tests the return expiry calculation logic
func TestGetReturnExpiryCalculation(t *testing.T) {
tests := []struct {
name string
lastLogin time.Time
currentTime time.Time
shouldUpdate bool
description string
name string
lastLogin time.Time
currentTime time.Time
shouldUpdate bool
description string
}{
{
name: "RecentLogin",
@@ -126,10 +126,10 @@ func TestGetReturnExpiryCalculation(t *testing.T) {
// TestCharacterCreationConstraints tests character creation constraints
func TestCharacterCreationConstraints(t *testing.T) {
tests := []struct {
name string
currentCount int
allowCreation bool
description string
name string
currentCount int
allowCreation bool
description string
}{
{
name: "NoCharacters",
@@ -170,22 +170,22 @@ func TestCharacterCreationConstraints(t *testing.T) {
// TestCharacterDeletionLogic tests the character deletion behavior
func TestCharacterDeletionLogic(t *testing.T) {
tests := []struct {
name string
name string
isNewCharacter bool
expectedAction string
description string
description string
}{
{
name: "NewCharacterDeletion",
isNewCharacter: true,
expectedAction: "DELETE",
description: "New characters should be hard deleted",
description: "New characters should be hard deleted",
},
{
name: "FinalizedCharacterDeletion",
isNewCharacter: false,
expectedAction: "SOFT_DELETE",
description: "Finalized characters should be soft deleted (marked as deleted)",
description: "Finalized characters should be soft deleted (marked as deleted)",
},
}
@@ -367,10 +367,10 @@ func TestCreateLoginTokenContext(t *testing.T) {
// TestPasswordValidation tests password validation logic
func TestPasswordValidation(t *testing.T) {
tests := []struct {
name string
password string
isValid bool
reason string
name string
password string
isValid bool
reason string
}{
{
name: "NormalPassword",

View File

@@ -10,8 +10,8 @@ import (
"testing"
"time"
cfg "erupe-ce/config"
"erupe-ce/common/gametime"
cfg "erupe-ce/config"
"go.uber.org/zap"
)
@@ -150,9 +150,9 @@ func TestLoginEndpointEmptyCredentials(t *testing.T) {
}
tests := []struct {
name string
username string
password string
name string
username string
password string
wantPanic bool // Note: will panic without real DB
}{
{"EmptyUsername", "", "password", true},

View File

@@ -36,23 +36,23 @@ type ChannelRegistry interface {
// SessionSnapshot is an immutable copy of session data taken under lock.
type SessionSnapshot struct {
CharID uint32
Name string
StageID string
ServerIP net.IP
ServerPort uint16
UserBinary3 []byte // Copy of userBinaryParts index 3
CharID uint32
Name string
StageID string
ServerIP net.IP
ServerPort uint16
UserBinary3 []byte // Copy of userBinaryParts index 3
}
// StageSnapshot is an immutable copy of stage data taken under lock.
type StageSnapshot struct {
ServerIP net.IP
ServerPort uint16
StageID string
ClientCount int
Reserved int
MaxPlayers uint16
RawBinData0 []byte
RawBinData1 []byte
RawBinData3 []byte
ServerIP net.IP
ServerPort uint16
StageID string
ClientCount int
Reserved int
MaxPlayers uint16
RawBinData0 []byte
RawBinData1 []byte
RawBinData3 []byte
}

View File

@@ -45,7 +45,7 @@ func NewMockNetConn() *MockNetConn {
func (m *MockNetConn) Read(b []byte) (n int, err error) {
m.mu.Lock()
defer m.mu.Unlock()
if m.closed {
return 0, io.EOF
}
@@ -58,7 +58,7 @@ func (m *MockNetConn) Read(b []byte) (n int, err error) {
func (m *MockNetConn) Write(b []byte) (n int, err error) {
m.mu.Lock()
defer m.mu.Unlock()
if m.closed {
return 0, io.ErrClosedPipe
}
@@ -130,7 +130,7 @@ func TestClientConnection_GracefulLoginLogout(t *testing.T) {
// Simulate client connecting
mockConn := NewMockNetConn()
session := createTestSessionForServerWithChar(server, charID, "ClientChar")
// In real scenario, this would be set up by the connection handler
// For testing, we test handlers directly without starting packet loops
@@ -394,11 +394,11 @@ func TestClientConnection_SaveDuringCombat(t *testing.T) {
t.Log("Simulating save/logout while in quest/stage")
session := createTestSessionForServerWithChar(server, charID, "CombatChar")
// Simulate being in a stage (quest)
// In real scenario, session.stage would be set when entering quest
// For now, we'll just test the basic save/logout flow
// Note: Not calling Start() - testing handlers directly
time.Sleep(50 * time.Millisecond)
@@ -596,4 +596,3 @@ func TestClientConnection_PacketDuringLogout(t *testing.T) {
t.Log("Race outcome: logout handler wrote last - marker byte overwritten (valid)")
}
}

View File

@@ -69,9 +69,9 @@ func TestDecompress_WithValidHeader(t *testing.T) {
func TestDecompress_WithoutHeader(t *testing.T) {
tests := []struct {
name string
input []byte
expectError bool
name string
input []byte
expectError bool
expectOriginal bool // Expect original data returned
}{
{

View File

@@ -9,6 +9,6 @@ const (
// Raviente semaphore constants
const (
raviSemaphoreStride = 0x10000 // ID spacing between hs_l0* semaphores
raviSemaphoreStride = 0x10000 // ID spacing between hs_l0* semaphores
raviSemaphoreMax = uint16(127) // max players per Raviente semaphore
)

View File

@@ -297,9 +297,9 @@ func TestGetAchData_Level7SilverTrophy(t *testing.T) {
// produces the correct gold trophy and the last threshold as Required/Progress.
func TestGetAchData_MaxedOut_AllCurves(t *testing.T) {
tests := []struct {
name string
id uint8
score int32
name string
id uint8
score int32
lastThresh int32
}{
// Curve 0: {5,15,30,50,100,150,200,300} sum=850, last=300
@@ -383,11 +383,11 @@ func TestGetAchData_Curve2_FestaWins(t *testing.T) {
wantReq uint32
}{
{0, 0, 0, 1},
{1, 1, 0, 2}, // Exactly at first threshold
{2, 1, 1, 2}, // One into second threshold
{3, 2, 0, 3}, // Exactly at second cumulative
{36, 8, 8, 8}, // Max level (sum of all thresholds)
{100, 8, 8, 8}, // Well above max
{1, 1, 0, 2}, // Exactly at first threshold
{2, 1, 1, 2}, // One into second threshold
{3, 2, 0, 3}, // Exactly at second cumulative
{36, 8, 8, 8}, // Max level (sum of all thresholds)
{100, 8, 8, 8}, // Well above max
}
for _, tt := range tests {

View File

@@ -35,9 +35,9 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
tmp := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload)
const (
timerPayloadSize = 0x10 // expected payload length for timer packets
timerPayloadSize = 0x10 // expected payload length for timer packets
timerSubtype = uint16(0x0002) // timer data subtype identifier
timerFlag = uint8(0x18) // timer flag byte
timerFlag = uint8(0x18) // timer flag byte
)
if pkt.BroadcastType == BroadcastTypeStage && pkt.MessageType == BinaryMessageTypeData && len(pkt.RawDataPayload) == timerPayloadSize {
if tmp.ReadUint16() == timerSubtype && tmp.ReadUint8() == timerFlag {

View File

@@ -154,7 +154,7 @@ func TestBroadcastTypes(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.SetBE() // Targeted uses BE
msg := &binpacket.MsgBinTargeted{
TargetCharIDs: []uint32{1, 2, 3},
TargetCharIDs: []uint32{1, 2, 3},
RawDataPayload: []byte{0xDE, 0xAD, 0xBE, 0xEF},
}
_ = msg.Build(bf)
@@ -218,8 +218,8 @@ func TestBroadcastTypes(t *testing.T) {
// TestBinaryMessageTypes verifies different message types are handled
func TestBinaryMessageTypes(t *testing.T) {
tests := []struct {
name string
messageType uint8
name string
messageType uint8
buildPayload func() []byte
}{
{

View File

@@ -4,8 +4,8 @@ import (
"fmt"
"testing"
cfg "erupe-ce/config"
"erupe-ce/common/byteframe"
cfg "erupe-ce/config"
"erupe-ce/network/mhfpacket"
"go.uber.org/zap"
)
@@ -13,12 +13,12 @@ import (
// TestHandleMsgSysEnumerateClient tests client enumeration in stages
func TestHandleMsgSysEnumerateClient(t *testing.T) {
tests := []struct {
name string
stageID string
getType uint8
setupStage func(*Server, string)
wantClientCount int
wantFailure bool
name string
stageID string
getType uint8
setupStage func(*Server, string)
wantClientCount int
wantFailure bool
}{
{
name: "enumerate_all_clients",

View File

@@ -1256,4 +1256,3 @@ func TestParseChatCommand_UnknownCommand(t *testing.T) {
t.Errorf("chat responses = %d, want 0 (unknown command is silent)", n)
}
}

View File

@@ -141,8 +141,8 @@ func TestHandleMsgMhfMercenaryHuntdata_RequestTypeIs1(t *testing.T) {
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfMercenaryHuntdata{
AckHandle: 12345,
RequestType: 1,
AckHandle: 12345,
RequestType: 1,
}
handleMsgMhfMercenaryHuntdata(session, pkt)
@@ -162,8 +162,8 @@ func TestHandleMsgMhfMercenaryHuntdata_RequestTypeIs0(t *testing.T) {
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfMercenaryHuntdata{
AckHandle: 12345,
RequestType: 0,
AckHandle: 12345,
RequestType: 0,
}
handleMsgMhfMercenaryHuntdata(session, pkt)
@@ -183,8 +183,8 @@ func TestHandleMsgMhfMercenaryHuntdata_RequestTypeIs2(t *testing.T) {
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfMercenaryHuntdata{
AckHandle: 12345,
RequestType: 2,
AckHandle: 12345,
RequestType: 2,
}
handleMsgMhfMercenaryHuntdata(session, pkt)

View File

@@ -17,7 +17,7 @@ func TestHandleMsgMhfGetPaperData_Case0(t *testing.T) {
handleMsgMhfGetPaperData(session, &mhfpacket.MsgMhfGetPaperData{
AckHandle: 1,
DataType: 0,
DataType: 0,
})
select {
@@ -36,7 +36,7 @@ func TestHandleMsgMhfGetPaperData_Case5(t *testing.T) {
handleMsgMhfGetPaperData(session, &mhfpacket.MsgMhfGetPaperData{
AckHandle: 1,
DataType: 5,
DataType: 5,
})
select {
@@ -55,7 +55,7 @@ func TestHandleMsgMhfGetPaperData_Case6(t *testing.T) {
handleMsgMhfGetPaperData(session, &mhfpacket.MsgMhfGetPaperData{
AckHandle: 1,
DataType: 6,
DataType: 6,
})
select {
@@ -75,7 +75,7 @@ func TestHandleMsgMhfGetPaperData_GreaterThan1000_KnownKey(t *testing.T) {
// 6001 is a known key in paperGiftData
handleMsgMhfGetPaperData(session, &mhfpacket.MsgMhfGetPaperData{
AckHandle: 1,
DataType: 6001,
DataType: 6001,
})
select {
@@ -95,7 +95,7 @@ func TestHandleMsgMhfGetPaperData_GreaterThan1000_UnknownKey(t *testing.T) {
// 9999 is not a known key in paperGiftData
handleMsgMhfGetPaperData(session, &mhfpacket.MsgMhfGetPaperData{
AckHandle: 1,
DataType: 9999,
DataType: 9999,
})
select {
@@ -114,7 +114,7 @@ func TestHandleMsgMhfGetPaperData_DefaultUnknownLessThan1000(t *testing.T) {
// Unknown type < 1000, hits default case then falls to else branch
handleMsgMhfGetPaperData(session, &mhfpacket.MsgMhfGetPaperData{
AckHandle: 1,
DataType: 99,
DataType: 99,
})
select {

View File

@@ -10,12 +10,12 @@ import (
// TestCharacterSaveDataPersistenceEdgeCases tests edge cases in character savedata persistence
func TestCharacterSaveDataPersistenceEdgeCases(t *testing.T) {
tests := []struct {
name string
charID uint32
charName string
isNew bool
playtime uint32
wantValid bool
name string
charID uint32
charName string
isNew bool
playtime uint32
wantValid bool
}{
{
name: "valid_new_character",
@@ -85,34 +85,34 @@ func TestCharacterSaveDataPersistenceEdgeCases(t *testing.T) {
// TestSaveDataCompressionRoundTrip tests compression/decompression edge cases
func TestSaveDataCompressionRoundTrip(t *testing.T) {
tests := []struct {
name string
dataSize int
name string
dataSize int
dataPattern byte
compresses bool
compresses bool
}{
{
name: "empty_data",
dataSize: 0,
name: "empty_data",
dataSize: 0,
dataPattern: 0x00,
compresses: true,
compresses: true,
},
{
name: "small_data",
dataSize: 10,
name: "small_data",
dataSize: 10,
dataPattern: 0xFF,
compresses: false, // Small data may not compress well
compresses: false, // Small data may not compress well
},
{
name: "highly_repetitive_data",
dataSize: 1000,
name: "highly_repetitive_data",
dataSize: 1000,
dataPattern: 0xAA,
compresses: true, // Highly repetitive should compress
compresses: true, // Highly repetitive should compress
},
{
name: "random_data",
dataSize: 500,
name: "random_data",
dataSize: 500,
dataPattern: 0x00, // Will be varied by position
compresses: false,
compresses: false,
},
}
@@ -149,34 +149,34 @@ func TestSaveDataCompressionRoundTrip(t *testing.T) {
// TestSaveDataPointerHandling tests edge cases in save data pointer management
func TestSaveDataPointerHandling(t *testing.T) {
tests := []struct {
name string
pointerCount int
name string
pointerCount int
maxPointerValue int
valid bool
valid bool
}{
{
name: "no_pointers",
pointerCount: 0,
name: "no_pointers",
pointerCount: 0,
maxPointerValue: 0,
valid: true,
valid: true,
},
{
name: "single_pointer",
pointerCount: 1,
name: "single_pointer",
pointerCount: 1,
maxPointerValue: 100,
valid: true,
valid: true,
},
{
name: "multiple_pointers",
pointerCount: 10,
name: "multiple_pointers",
pointerCount: 10,
maxPointerValue: 5000,
valid: true,
valid: true,
},
{
name: "max_pointers",
pointerCount: 100,
name: "max_pointers",
pointerCount: 100,
maxPointerValue: 1000000,
valid: true,
valid: true,
},
}
@@ -321,12 +321,12 @@ func TestSaveDataRPHandling(t *testing.T) {
// TestSaveDataHousingDataHandling tests various housing/decorative data fields
func TestSaveDataHousingDataHandling(t *testing.T) {
tests := []struct {
name string
houseTier []byte
houseData []byte
name string
houseTier []byte
houseData []byte
bookshelfData []byte
galleryData []byte
validEmpty bool
galleryData []byte
validEmpty bool
}{
{
name: "all_empty_housing",
@@ -588,8 +588,8 @@ func TestSaveDataBoundaryValues(t *testing.T) {
// TestSaveDataSerialization tests savedata can be serialized to binary format
func TestSaveDataSerialization(t *testing.T) {
tests := []struct {
name string
charID uint32
name string
charID uint32
playtime uint32
}{
{
@@ -643,18 +643,18 @@ func TestSaveDataTimestampHandling(t *testing.T) {
expectFresh bool
}{
{
name: "just_saved",
ageSeconds: 0,
name: "just_saved",
ageSeconds: 0,
expectFresh: true,
},
{
name: "recent_save",
ageSeconds: 60,
name: "recent_save",
ageSeconds: 60,
expectFresh: true,
},
{
name: "old_save",
ageSeconds: 86400, // 1 day old
name: "old_save",
ageSeconds: 86400, // 1 day old
expectFresh: false,
},
}
@@ -745,9 +745,9 @@ func TestDataCorruptionRecovery(t *testing.T) {
// TestChecksumValidation tests savedata checksum validation
func TestChecksumValidation(t *testing.T) {
tests := []struct {
name string
data []byte
checksumValid bool
name string
data []byte
checksumValid bool
}{
{
name: "valid_checksum",
@@ -794,11 +794,11 @@ func TestChecksumValidation(t *testing.T) {
// TestSaveDataBackupRestoration tests backup and restoration functionality
func TestSaveDataBackupRestoration(t *testing.T) {
tests := []struct {
name string
originalCharID uint32
originalPlaytime uint32
hasBackup bool
canRestore bool
name string
originalCharID uint32
originalPlaytime uint32
hasBackup bool
canRestore bool
}{
{
name: "backup_with_restore",
@@ -862,11 +862,11 @@ func TestSaveDataBackupRestoration(t *testing.T) {
// TestSaveDataVersionMigration tests savedata version migration and compatibility
func TestSaveDataVersionMigration(t *testing.T) {
tests := []struct {
name string
sourceVersion int
targetVersion int
canMigrate bool
dataLoss bool
name string
sourceVersion int
targetVersion int
canMigrate bool
dataLoss bool
}{
{
name: "same_version",
@@ -932,10 +932,10 @@ func TestSaveDataVersionMigration(t *testing.T) {
// TestSaveDataRollback tests rollback to previous savedata state
func TestSaveDataRollback(t *testing.T) {
tests := []struct {
name string
snapshots int
canRollback bool
rollbackSteps int
name string
snapshots int
canRollback bool
rollbackSteps int
}{
{
name: "single_snapshot",
@@ -1048,18 +1048,18 @@ func TestSaveDataConcurrentAccess(t *testing.T) {
concurrentWrites int
}{
{
name: "multiple_readers",
concurrentReads: 5,
name: "multiple_readers",
concurrentReads: 5,
concurrentWrites: 0,
},
{
name: "multiple_writers",
concurrentReads: 0,
name: "multiple_writers",
concurrentReads: 0,
concurrentWrites: 3,
},
{
name: "mixed_access",
concurrentReads: 3,
name: "mixed_access",
concurrentReads: 3,
concurrentWrites: 2,
},
}

View File

@@ -125,19 +125,19 @@ func TestScenarioSaveErrorHandling(t *testing.T) {
// 3. The function should return early after sending fail ACK
tests := []struct {
name string
name string
scenarioData []byte
wantError bool
wantError bool
}{
{
name: "valid_scenario_data",
name: "valid_scenario_data",
scenarioData: []byte{0x01, 0x02, 0x03},
wantError: false,
wantError: false,
},
{
name: "empty_scenario_data",
name: "empty_scenario_data",
scenarioData: []byte{},
wantError: false, // Empty data is valid
wantError: false, // Empty data is valid
},
}

View File

@@ -13,10 +13,10 @@ import (
// Diva Defense event duration constants (all values in seconds)
const (
divaPhaseDuration = 601200 // 6d 23h = first song phase
divaInterlude = 3900 // 65 min = gap between phases
divaPhaseDuration = 601200 // 6d 23h = first song phase
divaInterlude = 3900 // 65 min = gap between phases
divaWeekDuration = secsPerWeek // 7 days = subsequent phase length
divaTotalLifespan = 2977200 // ~34.5 days = full event window
divaTotalLifespan = 2977200 // ~34.5 days = full event window
)
func cleanupDiva(s *Session) {

View File

@@ -106,4 +106,3 @@ func TestHandleMsgMhfEnumerateRanking_State3(t *testing.T) {
t.Error("No response packet queued")
}
}

View File

@@ -326,8 +326,8 @@ func TestHandleMsgMhfPlayStepupGacha_Success(t *testing.T) {
func TestHandleMsgMhfGetStepupStatus_FreshStep(t *testing.T) {
server := createMockServer()
gachaRepo := &mockGachaRepo{
stepupStep: 2,
stepupTime: time.Now(), // recent, not stale
stepupStep: 2,
stepupTime: time.Now(), // recent, not stale
hasEntryType: true,
}
server.gachaRepo = gachaRepo

View File

@@ -33,8 +33,8 @@ func TestLoadGuildCooking_WithActiveMeals(t *testing.T) {
server := createMockServer()
guildMock := &mockGuildRepoOps{
meals: []*GuildMeal{
{ID: 1, MealID: 100, Level: 3, CreatedAt: TimeAdjusted()}, // active (within 60 min)
{ID: 2, MealID: 200, Level: 1, CreatedAt: TimeAdjusted().Add(-2 * time.Hour)}, // expired
{ID: 1, MealID: 100, Level: 3, CreatedAt: TimeAdjusted()}, // active (within 60 min)
{ID: 2, MealID: 200, Level: 1, CreatedAt: TimeAdjusted().Add(-2 * time.Hour)}, // expired
},
}
guildMock.guild = &Guild{ID: 10}

View File

@@ -599,9 +599,9 @@ func newNullTermBF(data []byte) *byteframe.ByteFrame {
func newMottoBF(sub, main uint8) *byteframe.ByteFrame {
bf := byteframe.NewByteFrame()
bf.WriteUint16(0) // skipped
bf.WriteUint8(sub) // SubMotto
bf.WriteUint8(main) // MainMotto
bf.WriteUint16(0) // skipped
bf.WriteUint8(sub) // SubMotto
bf.WriteUint8(main) // MainMotto
_, _ = bf.Seek(0, 0)
return bf
}

View File

@@ -208,4 +208,3 @@ func TestUpdateRights_Error(t *testing.T) {
t.Fatal("updateRights should queue a packet even on error")
}
}

View File

@@ -2,9 +2,9 @@ package channelserver
import (
"erupe-ce/common/byteframe"
cfg "erupe-ce/config"
"erupe-ce/common/mhfitem"
"erupe-ce/common/token"
cfg "erupe-ce/config"
"erupe-ce/network/mhfpacket"
"testing"
@@ -699,7 +699,7 @@ func TestWarehouseItemSerialization(t *testing.T) {
items []mhfitem.MHFItemStack
}{
{
name: "empty_warehouse",
name: "empty_warehouse",
items: []mhfitem.MHFItemStack{},
},
{
@@ -747,11 +747,11 @@ func TestWarehouseEquipmentSerialization(t *testing.T) {
equipment: []mhfitem.MHFEquipment{},
},
{
name: "single_equipment",
name: "single_equipment",
equipment: createTestEquipment([]uint16{100}, []uint32{1}),
},
{
name: "multiple_equipment",
name: "multiple_equipment",
equipment: createTestEquipment([]uint16{100, 101, 102}, []uint32{1, 2, 3}),
},
}
@@ -837,16 +837,16 @@ func TestWarehouseItemDiff(t *testing.T) {
// TestWarehouseEquipmentMerge verifies equipment merging logic
func TestWarehouseEquipmentMerge(t *testing.T) {
tests := []struct {
name string
oldEquip []mhfitem.MHFEquipment
newEquip []mhfitem.MHFEquipment
wantMerged int
name string
oldEquip []mhfitem.MHFEquipment
newEquip []mhfitem.MHFEquipment
wantMerged int
}{
{
name: "merge_empty",
oldEquip: []mhfitem.MHFEquipment{},
newEquip: []mhfitem.MHFEquipment{},
wantMerged: 0,
name: "merge_empty",
oldEquip: []mhfitem.MHFEquipment{},
newEquip: []mhfitem.MHFEquipment{},
wantMerged: 0,
},
{
name: "add_new_equipment",

View File

@@ -45,10 +45,10 @@ func TestUserGetItems_ParsesData(t *testing.T) {
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
bf.WriteUint32(100) // warehouseID
bf.WriteUint16(500) // itemID
bf.WriteUint16(3) // quantity
bf.WriteUint32(0) // unk0
server := createMockServer()
userMock := &mockUserRepoForItems{itemBoxData: bf.Data()}

View File

@@ -86,9 +86,9 @@ func TestGetAirouDetails_Empty(t *testing.T) {
func TestGetAirouDetails_SingleCat(t *testing.T) {
input := Airou{
ID: 42,
Name: []byte("TestCat"),
Task: 4,
ID: 42,
Name: []byte("TestCat"),
Task: 4,
Personality: 3,
Class: 2,
Experience: 1500,
@@ -175,16 +175,16 @@ func TestGetAirouDetails_ExtraTrailingBytes(t *testing.T) {
catBuf := new(bytes.Buffer)
_ = binary.Write(catBuf, binary.BigEndian, uint32(99)) // catID
catBuf.WriteByte(0) // skip
catBuf.Write(make([]byte, 18)) // name
catBuf.WriteByte(3) // currentTask
catBuf.Write(make([]byte, 16)) // appearance skip
catBuf.WriteByte(1) // personality
catBuf.WriteByte(2) // class
catBuf.Write(make([]byte, 5)) // affection skip
catBuf.WriteByte(0) // skip
catBuf.Write(make([]byte, 18)) // name
catBuf.WriteByte(3) // currentTask
catBuf.Write(make([]byte, 16)) // appearance skip
catBuf.WriteByte(1) // personality
catBuf.WriteByte(2) // class
catBuf.Write(make([]byte, 5)) // affection skip
_ = binary.Write(catBuf, binary.BigEndian, uint32(500)) // experience
catBuf.WriteByte(0) // weapon equipped bool
catBuf.WriteByte(6) // weaponType
catBuf.WriteByte(0) // weapon equipped bool
catBuf.WriteByte(6) // weaponType
_ = binary.Write(catBuf, binary.BigEndian, uint16(50)) // weaponID
catData := catBuf.Bytes()
@@ -238,8 +238,8 @@ func TestHandleMsgMhfMercenaryHuntdata_Unk0_1(t *testing.T) {
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfMercenaryHuntdata{
AckHandle: 12345,
RequestType: 1,
AckHandle: 12345,
RequestType: 1,
}
handleMsgMhfMercenaryHuntdata(session, pkt)
@@ -260,8 +260,8 @@ func TestHandleMsgMhfMercenaryHuntdata_Unk0_0(t *testing.T) {
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfMercenaryHuntdata{
AckHandle: 12345,
RequestType: 0,
AckHandle: 12345,
RequestType: 0,
}
handleMsgMhfMercenaryHuntdata(session, pkt)

View File

@@ -73,10 +73,10 @@ func TestBackportQuestBasic(t *testing.T) {
// TestFindSubSliceIndices tests byte slice pattern finding
func TestFindSubSliceIndices(t *testing.T) {
tests := []struct {
name string
data []byte
pattern []byte
expected int
name string
data []byte
pattern []byte
expected int
}{
{
name: "single_match",
@@ -213,9 +213,9 @@ func TestEnumerateQuestBasicStructure(t *testing.T) {
bf := byteframe.NewByteFrame()
// Build a minimal response structure
bf.WriteUint16(0) // Returned count
bf.WriteUint16(0) // Returned count
bf.WriteUint16(uint16(time.Now().Unix() & 0xFFFF)) // Unix timestamp offset
bf.WriteUint16(0) // Tune values count
bf.WriteUint16(0) // Tune values count
data := bf.Data()
@@ -301,12 +301,12 @@ func TestEnumerateQuestTuneValuesEncoding(t *testing.T) {
// TestEventQuestCycleCalculation tests event quest cycle calculations
func TestEventQuestCycleCalculation(t *testing.T) {
tests := []struct {
name string
startTime time.Time
activeDays int
inactiveDays int
currentTime time.Time
shouldBeActive bool
name string
startTime time.Time
activeDays int
inactiveDays int
currentTime time.Time
shouldBeActive bool
}{
{
name: "active_period",
@@ -409,8 +409,8 @@ func TestMakeEventQuestPacketStructure(t *testing.T) {
questType := uint8(16)
bf.WriteUint32(questID)
bf.WriteUint32(0) // Unk
bf.WriteUint8(0) // Unk
bf.WriteUint32(0) // Unk
bf.WriteUint8(0) // Unk
bf.WriteUint8(maxPlayers)
bf.WriteUint8(questType)
bf.WriteBool(true) // Multi-player
@@ -626,13 +626,13 @@ func TestGetUdBonusQuestInfoStructure(t *testing.T) {
bf.SetLE()
// Example UD bonus quest info entry
bf.WriteUint8(0) // Unk0
bf.WriteUint8(0) // Unk1
bf.WriteUint32(uint32(time.Now().Unix())) // StartTime
bf.WriteUint32(uint32(time.Now().Add(30*24*time.Hour).Unix())) // EndTime
bf.WriteUint32(0) // Unk4
bf.WriteUint8(0) // Unk5
bf.WriteUint8(0) // Unk6
bf.WriteUint8(0) // Unk0
bf.WriteUint8(0) // Unk1
bf.WriteUint32(uint32(time.Now().Unix())) // StartTime
bf.WriteUint32(uint32(time.Now().Add(30 * 24 * time.Hour).Unix())) // EndTime
bf.WriteUint32(0) // Unk4
bf.WriteUint8(0) // Unk5
bf.WriteUint8(0) // Unk6
data := bf.Data()
@@ -646,8 +646,8 @@ func TestGetUdBonusQuestInfoStructure(t *testing.T) {
bf2 := byteframe.NewByteFrameFromBytes(data)
bf2.SetLE()
bf2.ReadUint8() // Unk0
bf2.ReadUint8() // Unk1
bf2.ReadUint8() // Unk0
bf2.ReadUint8() // Unk1
startTime := bf2.ReadUint32()
endTime := bf2.ReadUint32()
bf2.ReadUint32() // Unk4
@@ -665,9 +665,9 @@ func BenchmarkQuestEnumeration(b *testing.B) {
bf := byteframe.NewByteFrame()
// Build a response with tune values
bf.WriteUint16(0) // Returned count
bf.WriteUint16(0) // Returned count
bf.WriteUint16(uint16(time.Now().Unix() & 0xFFFF))
bf.WriteUint16(100) // 100 tune values
bf.WriteUint16(100) // 100 tune values
for j := 0; j < 100; j++ {
bf.WriteUint16(uint16(j))

View File

@@ -155,11 +155,11 @@ func TestRengokuData_SaveLoadRoundTrip(t *testing.T) {
// Build a realistic payload with non-zero skill data
payload := buildRengokuTestPayload(
15, 18519, // MP: 15 stages, 18519 points
4, 381, // SP: 4 stages, 381 points
[3]uint16{0x0012, 0x0034, 0x0056}, // skill slot IDs
15, 18519, // MP: 15 stages, 18519 points
4, 381, // SP: 4 stages, 381 points
[3]uint16{0x0012, 0x0034, 0x0056}, // skill slot IDs
[3]uint32{0x00110001, 0x00220002, 0x00330003}, // equipped skills
[3]uint32{100, 200, 300}, // skill points invested
[3]uint32{100, 200, 300}, // skill points invested
)
// === SAVE ===
@@ -212,8 +212,8 @@ func TestRengokuData_SaveLoadRoundTrip_AcrossSessions(t *testing.T) {
session1 := createTestSessionForServerWithChar(server, charID, "RengokuChar2")
payload := buildRengokuTestPayload(
80, 342295, // MP: deep run
38, 54634, // SP: deep run
80, 342295, // MP: deep run
38, 54634, // SP: deep run
[3]uint16{0x00AA, 0x00BB, 0x00CC},
[3]uint32{0xDEAD0001, 0xBEEF0002, 0xCAFE0003},
[3]uint32{500, 750, 1000},
@@ -1052,9 +1052,9 @@ func TestRengokuData_LargePayload(t *testing.T) {
}
// Ensure valid score region at offsets 71-90
binary.BigEndian.PutUint32(payload[71:75], 20) // maxStageMp
binary.BigEndian.PutUint32(payload[75:79], 30000) // maxScoreMp
binary.BigEndian.PutUint32(payload[83:87], 10) // maxStageSp
binary.BigEndian.PutUint32(payload[87:91], 15000) // maxScoreSp
binary.BigEndian.PutUint32(payload[75:79], 30000) // maxScoreMp
binary.BigEndian.PutUint32(payload[83:87], 10) // maxStageSp
binary.BigEndian.PutUint32(payload[87:91], 15000) // maxScoreSp
savePkt := &mhfpacket.MsgMhfSaveRengokuData{
AckHandle: 10001,

View File

@@ -5,8 +5,8 @@ import (
"testing"
"time"
cfg "erupe-ce/config"
"erupe-ce/common/mhfitem"
cfg "erupe-ce/config"
"erupe-ce/network/mhfpacket"
"erupe-ce/server/channelserver/compression/nullcomp"
)
@@ -263,7 +263,7 @@ func TestSaveLoad_CurrentEquipment(t *testing.T) {
copy(saveData[88:], []byte("TestChar\x00"))
// Set weapon type at known offset (simplified)
weaponTypeOffset := 500 // Example offset
weaponTypeOffset := 500 // Example offset
saveData[weaponTypeOffset] = 0x03 // Great Sword
compressed, err := nullcomp.Compress(saveData)
@@ -377,10 +377,10 @@ func TestSaveLoad_Transmog(t *testing.T) {
setSize := 76 // G10+
numSets := 1
transmogData := make([]byte, 2+numSets*(2+setSize))
transmogData[0] = 1 // version
transmogData[0] = 1 // version
transmogData[1] = byte(numSets) // count
transmogData[2] = 0 // index high byte
transmogData[3] = 1 // index low byte (set #1)
transmogData[2] = 0 // index high byte
transmogData[3] = 1 // index low byte (set #1)
// Save transmog data
pkt := &mhfpacket.MsgMhfSaveDecoMyset{

View File

@@ -223,11 +223,11 @@ func TestHandleMsgMhfAcquireExchangeShop_RecordsPurchases(t *testing.T) {
// Build payload: 2 exchanges, one with non-zero hash, one with zero hash
payload := byteframe.NewByteFrame()
payload.WriteUint16(2) // count
payload.WriteUint32(12345) // itemHash 1
payload.WriteUint32(3) // buyCount 1
payload.WriteUint32(0) // itemHash 2 (zero, should be skipped)
payload.WriteUint32(1) // buyCount 2
payload.WriteUint16(2) // count
payload.WriteUint32(12345) // itemHash 1
payload.WriteUint32(3) // buyCount 1
payload.WriteUint32(0) // itemHash 2 (zero, should be skipped)
payload.WriteUint32(1) // buyCount 2
pkt := &mhfpacket.MsgMhfAcquireExchangeShop{
AckHandle: 100,

View File

@@ -18,7 +18,6 @@ func TestCreateStageSuccess(t *testing.T) {
mock := &MockCryptConn{sentPackets: make([][]byte, 0)}
s := createTestSession(mock)
// Create a new stage
pkt := &mhfpacket.MsgSysCreateStage{
StageID: "test_stage_1",
@@ -46,7 +45,6 @@ func TestCreateStageDuplicate(t *testing.T) {
mock := &MockCryptConn{sentPackets: make([][]byte, 0)}
s := createTestSession(mock)
// Create first stage
pkt1 := &mhfpacket.MsgSysCreateStage{
StageID: "test_stage",
@@ -76,7 +74,6 @@ func TestStageLocking(t *testing.T) {
mock := &MockCryptConn{sentPackets: make([][]byte, 0)}
s := createTestSession(mock)
// Create a stage
stage := NewStage("locked_stage")
stage.host = s
@@ -105,7 +102,6 @@ func TestStageReservation(t *testing.T) {
mock := &MockCryptConn{sentPackets: make([][]byte, 0)}
s := createTestSession(mock)
// Create a stage
stage := NewStage("reserved_stage")
stage.host = s
@@ -164,7 +160,7 @@ func TestStageBinaryData(t *testing.T) {
stage := NewStage("binary_stage")
stage.rawBinaryData = make(map[stageBinaryKey][]byte)
s.stage = stage
s.server.stages.Store("binary_stage", stage)
// Store binary data directly
@@ -231,7 +227,6 @@ func TestIsStageFull(t *testing.T) {
stage.clients[client] = uint32(i)
}
s.server.stages.Store("full_test_stage", stage)
result := isStageFull(s, "full_test_stage")
@@ -303,7 +298,6 @@ func TestDestructEmptyStages(t *testing.T) {
mock := &MockCryptConn{sentPackets: make([][]byte, 0)}
s := createTestSession(mock)
// Create stages with different client counts
emptyStage := NewStage("empty_stage")
emptyStage.clients = make(map[*Session]uint32)
@@ -423,7 +417,6 @@ func TestConcurrentStageOperations(t *testing.T) {
mock := &MockCryptConn{sentPackets: make([][]byte, 0)}
baseSession := createTestSession(mock)
// Create a stage
stage := NewStage("concurrent_stage")
stage.clients = make(map[*Session]uint32)

View File

@@ -12,7 +12,7 @@ func TestHandleMsgMhfInfoTournament_Type0(t *testing.T) {
pkt := &mhfpacket.MsgMhfInfoTournament{
AckHandle: 12345,
QueryType: 0,
QueryType: 0,
}
handleMsgMhfInfoTournament(session, pkt)
@@ -34,7 +34,7 @@ func TestHandleMsgMhfInfoTournament_Type1(t *testing.T) {
pkt := &mhfpacket.MsgMhfInfoTournament{
AckHandle: 12345,
QueryType: 1,
QueryType: 1,
}
handleMsgMhfInfoTournament(session, pkt)

View File

@@ -35,7 +35,7 @@ func TestHandleMsgMhfGetTenrouirai_Default(t *testing.T) {
pkt := &mhfpacket.MsgMhfGetTenrouirai{
AckHandle: 12345,
Unk0: 0,
DataType: 0,
DataType: 0,
}
handleMsgMhfGetTenrouirai(session, pkt)

View File

@@ -19,22 +19,22 @@ func IntegrationTest_PacketQueueFlow(t *testing.T) {
}
tests := []struct {
name string
packetCount int
queueDelay time.Duration
wantPackets int
name string
packetCount int
queueDelay time.Duration
wantPackets int
}{
{
name: "sequential_packets",
packetCount: 10,
queueDelay: 10 * time.Millisecond,
wantPackets: 10,
name: "sequential_packets",
packetCount: 10,
queueDelay: 10 * time.Millisecond,
wantPackets: 10,
},
{
name: "rapid_fire_packets",
packetCount: 50,
queueDelay: 1 * time.Millisecond,
wantPackets: 50,
name: "rapid_fire_packets",
packetCount: 50,
queueDelay: 1 * time.Millisecond,
wantPackets: 50,
},
}
@@ -44,7 +44,7 @@ func IntegrationTest_PacketQueueFlow(t *testing.T) {
s := &Session{
sendPackets: make(chan packet, 100),
server: &Server{
server: &Server{
erupeConfig: &cfg.Config{
DebugOptions: cfg.DebugOptions{
LogOutboundMessages: false,
@@ -126,7 +126,7 @@ func IntegrationTest_ConcurrentQueueing(t *testing.T) {
},
},
}
s.cryptConn = mock
s.cryptConn = mock
go s.sendLoop()
@@ -224,7 +224,7 @@ func IntegrationTest_AckPacketFlow(t *testing.T) {
},
},
}
s.cryptConn = mock
s.cryptConn = mock
go s.sendLoop()
@@ -289,7 +289,7 @@ func IntegrationTest_MixedPacketTypes(t *testing.T) {
},
},
}
s.cryptConn = mock
s.cryptConn = mock
go s.sendLoop()
@@ -345,7 +345,7 @@ func IntegrationTest_PacketOrderPreservation(t *testing.T) {
},
},
}
s.cryptConn = mock
s.cryptConn = mock
go s.sendLoop()
@@ -403,7 +403,7 @@ func IntegrationTest_QueueBackpressure(t *testing.T) {
},
},
}
s.cryptConn = mock
s.cryptConn = mock
go s.sendLoop()
@@ -443,10 +443,10 @@ func IntegrationTest_GuildEnumerationFlow(t *testing.T) {
}
tests := []struct {
name string
guildCount int
name string
guildCount int
membersPerGuild int
wantValid bool
wantValid bool
}{
{
name: "single_guild",
@@ -530,22 +530,22 @@ func IntegrationTest_ConcurrentClientAccess(t *testing.T) {
}
tests := []struct {
name string
name string
concurrentClients int
packetsPerClient int
wantTotalPackets int
}{
{
name: "two_concurrent_clients",
name: "two_concurrent_clients",
concurrentClients: 2,
packetsPerClient: 5,
wantTotalPackets: 10,
wantTotalPackets: 10,
},
{
name: "five_concurrent_clients",
name: "five_concurrent_clients",
concurrentClients: 5,
packetsPerClient: 10,
wantTotalPackets: 50,
wantTotalPackets: 50,
},
}

View File

@@ -174,34 +174,51 @@ func (m *mockCharacterRepo) LoadColumn(_ uint32, column string) ([]byte, error)
}
return m.columns[column], nil
}
func (m *mockCharacterRepo) SaveColumn(_ uint32, column string, data []byte) error { m.columns[column] = data; return m.saveErr }
func (m *mockCharacterRepo) GetName(_ uint32) (string, error) { return "TestChar", nil }
func (m *mockCharacterRepo) GetUserID(_ uint32) (uint32, error) { return 1, nil }
func (m *mockCharacterRepo) UpdateLastLogin(_ uint32, _ int64) error { return nil }
func (m *mockCharacterRepo) UpdateTimePlayed(_ uint32, _ int) error { return nil }
func (m *mockCharacterRepo) GetCharIDsByUserID(_ uint32) ([]uint32, error) { return nil, nil }
func (m *mockCharacterRepo) SaveBool(_ uint32, col string, v bool) error { m.bools[col] = v; return nil }
func (m *mockCharacterRepo) SaveString(_ uint32, col string, v string) error { m.strings[col] = v; return nil }
func (m *mockCharacterRepo) ReadBool(_ uint32, col string) (bool, error) { return m.bools[col], nil }
func (m *mockCharacterRepo) ReadString(_ uint32, col string) (string, error) { return m.strings[col], nil }
func (m *mockCharacterRepo) SaveColumn(_ uint32, column string, data []byte) error {
m.columns[column] = data
return m.saveErr
}
func (m *mockCharacterRepo) GetName(_ uint32) (string, error) { return "TestChar", nil }
func (m *mockCharacterRepo) GetUserID(_ uint32) (uint32, error) { return 1, nil }
func (m *mockCharacterRepo) UpdateLastLogin(_ uint32, _ int64) error { return nil }
func (m *mockCharacterRepo) UpdateTimePlayed(_ uint32, _ int) error { return nil }
func (m *mockCharacterRepo) GetCharIDsByUserID(_ uint32) ([]uint32, error) { return nil, nil }
func (m *mockCharacterRepo) SaveBool(_ uint32, col string, v bool) error {
m.bools[col] = v
return nil
}
func (m *mockCharacterRepo) SaveString(_ uint32, col string, v string) error {
m.strings[col] = v
return nil
}
func (m *mockCharacterRepo) ReadBool(_ uint32, col string) (bool, error) { return m.bools[col], nil }
func (m *mockCharacterRepo) ReadString(_ uint32, col string) (string, error) {
return m.strings[col], nil
}
func (m *mockCharacterRepo) LoadColumnWithDefault(_ uint32, col string, def []byte) ([]byte, error) {
if d, ok := m.columns[col]; ok {
return d, nil
}
return def, nil
}
func (m *mockCharacterRepo) SetDeleted(_ uint32) error { return nil }
func (m *mockCharacterRepo) UpdateDailyCafe(_ uint32, _ time.Time, _, _ uint32) error { return nil }
func (m *mockCharacterRepo) ResetDailyQuests(_ uint32) error { return nil }
func (m *mockCharacterRepo) ReadEtcPoints(_ uint32) (uint32, uint32, uint32, error) { return 0, 0, 0, nil }
func (m *mockCharacterRepo) ResetCafeTime(_ uint32, _ time.Time) error { return nil }
func (m *mockCharacterRepo) UpdateGuildPostChecked(_ uint32) error { return nil }
func (m *mockCharacterRepo) ReadGuildPostChecked(_ uint32) (time.Time, error) { return time.Time{}, nil }
func (m *mockCharacterRepo) SaveMercenary(_ uint32, _ []byte, _ uint32) error { return nil }
func (m *mockCharacterRepo) UpdateGCPAndPact(_ uint32, _ uint32, _ uint32) error { return nil }
func (m *mockCharacterRepo) FindByRastaID(_ int) (uint32, string, error) { return 0, "", nil }
func (m *mockCharacterRepo) SaveCharacterData(_ uint32, _ []byte, _, _ uint16, _ bool, _ uint8, _ uint16) error { return nil }
func (m *mockCharacterRepo) SaveHouseData(_ uint32, _ []byte, _, _, _, _, _ []byte) error { return nil }
func (m *mockCharacterRepo) SetDeleted(_ uint32) error { return nil }
func (m *mockCharacterRepo) UpdateDailyCafe(_ uint32, _ time.Time, _, _ uint32) error { return nil }
func (m *mockCharacterRepo) ResetDailyQuests(_ uint32) error { return nil }
func (m *mockCharacterRepo) ReadEtcPoints(_ uint32) (uint32, uint32, uint32, error) {
return 0, 0, 0, nil
}
func (m *mockCharacterRepo) ResetCafeTime(_ uint32, _ time.Time) error { return nil }
func (m *mockCharacterRepo) UpdateGuildPostChecked(_ uint32) error { return nil }
func (m *mockCharacterRepo) ReadGuildPostChecked(_ uint32) (time.Time, error) {
return time.Time{}, nil
}
func (m *mockCharacterRepo) SaveMercenary(_ uint32, _ []byte, _ uint32) error { return nil }
func (m *mockCharacterRepo) UpdateGCPAndPact(_ uint32, _ uint32, _ uint32) error { return nil }
func (m *mockCharacterRepo) FindByRastaID(_ int) (uint32, string, error) { return 0, "", nil }
func (m *mockCharacterRepo) SaveCharacterData(_ uint32, _ []byte, _, _ uint16, _ bool, _ uint8, _ uint16) error {
return nil
}
func (m *mockCharacterRepo) SaveHouseData(_ uint32, _ []byte, _, _, _, _, _ []byte) error { return nil }
func (m *mockCharacterRepo) LoadSaveData(_ uint32) (uint32, []byte, bool, string, error) {
return m.loadSaveDataID, m.loadSaveDataData, m.loadSaveDataNew, m.loadSaveDataName, m.loadSaveDataErr
}
@@ -209,10 +226,10 @@ func (m *mockCharacterRepo) LoadSaveData(_ uint32) (uint32, []byte, bool, string
// --- mockGoocooRepo ---
type mockGoocooRepo struct {
slots map[uint32][]byte
ensureCalled bool
clearCalled []uint32
savedSlots map[uint32][]byte
slots map[uint32][]byte
ensureCalled bool
clearCalled []uint32
savedSlots map[uint32][]byte
}
func newMockGoocooRepo() *mockGoocooRepo {
@@ -265,77 +282,87 @@ func (m *mockGuildRepoForMail) GetMembers(_ uint32, _ bool) ([]*GuildMember, err
}
// Stub out all other GuildRepo methods.
func (m *mockGuildRepoForMail) GetByID(_ uint32) (*Guild, error) { return nil, errNotFound }
func (m *mockGuildRepoForMail) ListAll() ([]*Guild, error) { return nil, nil }
func (m *mockGuildRepoForMail) GetByID(_ uint32) (*Guild, error) { return nil, errNotFound }
func (m *mockGuildRepoForMail) ListAll() ([]*Guild, error) { return nil, nil }
func (m *mockGuildRepoForMail) Create(_ uint32, _ string) (int32, error) { return 0, nil }
func (m *mockGuildRepoForMail) Save(_ *Guild) error { return nil }
func (m *mockGuildRepoForMail) Disband(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) RemoveCharacter(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) AcceptApplication(_, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) Save(_ *Guild) error { return nil }
func (m *mockGuildRepoForMail) Disband(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) RemoveCharacter(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) AcceptApplication(_, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) CreateApplication(_, _, _ uint32, _ GuildApplicationType) error {
return nil
}
func (m *mockGuildRepoForMail) CreateApplicationWithMail(_, _, _ uint32, _ GuildApplicationType, _, _ uint32, _, _ string) error {
return nil
}
func (m *mockGuildRepoForMail) CancelInvitation(_, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) RejectApplication(_, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) ArrangeCharacters(_ []uint32) error { return nil }
func (m *mockGuildRepoForMail) CancelInvitation(_, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) RejectApplication(_, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) ArrangeCharacters(_ []uint32) error { return nil }
func (m *mockGuildRepoForMail) GetApplication(_, _ uint32, _ GuildApplicationType) (*GuildApplication, error) {
return nil, nil
}
func (m *mockGuildRepoForMail) HasApplication(_, _ uint32) (bool, error) { return false, nil }
func (m *mockGuildRepoForMail) GetItemBox(_ uint32) ([]byte, error) { return nil, nil }
func (m *mockGuildRepoForMail) SaveItemBox(_ uint32, _ []byte) error { return nil }
func (m *mockGuildRepoForMail) GetCharacterMembership(_ uint32) (*GuildMember, error) { return nil, nil }
func (m *mockGuildRepoForMail) SaveMember(_ *GuildMember) error { return nil }
func (m *mockGuildRepoForMail) SetRecruiting(_ uint32, _ bool) error { return nil }
func (m *mockGuildRepoForMail) SetPugiOutfits(_ uint32, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) SetRecruiter(_ uint32, _ bool) error { return nil }
func (m *mockGuildRepoForMail) AddMemberDailyRP(_ uint32, _ uint16) error { return nil }
func (m *mockGuildRepoForMail) HasApplication(_, _ uint32) (bool, error) { return false, nil }
func (m *mockGuildRepoForMail) GetItemBox(_ uint32) ([]byte, error) { return nil, nil }
func (m *mockGuildRepoForMail) SaveItemBox(_ uint32, _ []byte) error { return nil }
func (m *mockGuildRepoForMail) GetCharacterMembership(_ uint32) (*GuildMember, error) {
return nil, nil
}
func (m *mockGuildRepoForMail) SaveMember(_ *GuildMember) error { return nil }
func (m *mockGuildRepoForMail) SetRecruiting(_ uint32, _ bool) error { return nil }
func (m *mockGuildRepoForMail) SetPugiOutfits(_ uint32, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) SetRecruiter(_ uint32, _ bool) error { return nil }
func (m *mockGuildRepoForMail) AddMemberDailyRP(_ uint32, _ uint16) error { return nil }
func (m *mockGuildRepoForMail) ExchangeEventRP(_ uint32, _ uint16) (uint32, error) { return 0, nil }
func (m *mockGuildRepoForMail) AddRankRP(_ uint32, _ uint16) error { return nil }
func (m *mockGuildRepoForMail) AddEventRP(_ uint32, _ uint16) error { return nil }
func (m *mockGuildRepoForMail) GetRoomRP(_ uint32) (uint16, error) { return 0, nil }
func (m *mockGuildRepoForMail) SetRoomRP(_ uint32, _ uint16) error { return nil }
func (m *mockGuildRepoForMail) AddRoomRP(_ uint32, _ uint16) error { return nil }
func (m *mockGuildRepoForMail) SetRoomExpiry(_ uint32, _ time.Time) error { return nil }
func (m *mockGuildRepoForMail) ListPosts(_ uint32, _ int) ([]*MessageBoardPost, error) { return nil, nil }
func (m *mockGuildRepoForMail) CreatePost(_, _, _ uint32, _ int, _, _ string, _ int) error { return nil }
func (m *mockGuildRepoForMail) DeletePost(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) UpdatePost(_ uint32, _, _ string) error { return nil }
func (m *mockGuildRepoForMail) UpdatePostStamp(_, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) GetPostLikedBy(_ uint32) (string, error) { return "", nil }
func (m *mockGuildRepoForMail) SetPostLikedBy(_ uint32, _ string) error { return nil }
func (m *mockGuildRepoForMail) CountNewPosts(_ uint32, _ time.Time) (int, error) { return 0, nil }
func (m *mockGuildRepoForMail) GetAllianceByID(_ uint32) (*GuildAlliance, error) { return nil, nil }
func (m *mockGuildRepoForMail) ListAlliances() ([]*GuildAlliance, error) { return nil, nil }
func (m *mockGuildRepoForMail) CreateAlliance(_ string, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) DeleteAlliance(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) RemoveGuildFromAlliance(_, _, _, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) AddRankRP(_ uint32, _ uint16) error { return nil }
func (m *mockGuildRepoForMail) AddEventRP(_ uint32, _ uint16) error { return nil }
func (m *mockGuildRepoForMail) GetRoomRP(_ uint32) (uint16, error) { return 0, nil }
func (m *mockGuildRepoForMail) SetRoomRP(_ uint32, _ uint16) error { return nil }
func (m *mockGuildRepoForMail) AddRoomRP(_ uint32, _ uint16) error { return nil }
func (m *mockGuildRepoForMail) SetRoomExpiry(_ uint32, _ time.Time) error { return nil }
func (m *mockGuildRepoForMail) ListPosts(_ uint32, _ int) ([]*MessageBoardPost, error) {
return nil, nil
}
func (m *mockGuildRepoForMail) CreatePost(_, _, _ uint32, _ int, _, _ string, _ int) error {
return nil
}
func (m *mockGuildRepoForMail) DeletePost(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) UpdatePost(_ uint32, _, _ string) error { return nil }
func (m *mockGuildRepoForMail) UpdatePostStamp(_, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) GetPostLikedBy(_ uint32) (string, error) { return "", nil }
func (m *mockGuildRepoForMail) SetPostLikedBy(_ uint32, _ string) error { return nil }
func (m *mockGuildRepoForMail) CountNewPosts(_ uint32, _ time.Time) (int, error) { return 0, nil }
func (m *mockGuildRepoForMail) GetAllianceByID(_ uint32) (*GuildAlliance, error) { return nil, nil }
func (m *mockGuildRepoForMail) ListAlliances() ([]*GuildAlliance, error) { return nil, nil }
func (m *mockGuildRepoForMail) CreateAlliance(_ string, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) DeleteAlliance(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) RemoveGuildFromAlliance(_, _, _, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) ListAdventures(_ uint32) ([]*GuildAdventure, error) { return nil, nil }
func (m *mockGuildRepoForMail) CreateAdventure(_, _ uint32, _, _ int64) error { return nil }
func (m *mockGuildRepoForMail) CreateAdventureWithCharge(_, _, _ uint32, _, _ int64) error { return nil }
func (m *mockGuildRepoForMail) CollectAdventure(_ uint32, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) ChargeAdventure(_ uint32, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) GetPendingHunt(_ uint32) (*TreasureHunt, error) { return nil, nil }
func (m *mockGuildRepoForMail) ListGuildHunts(_, _ uint32) ([]*TreasureHunt, error) { return nil, nil }
func (m *mockGuildRepoForMail) CreateHunt(_, _, _, _ uint32, _ []byte, _ string) error { return nil }
func (m *mockGuildRepoForMail) AcquireHunt(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) RegisterHuntReport(_, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) CollectHunt(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) ClaimHuntReward(_, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) ListMeals(_ uint32) ([]*GuildMeal, error) { return nil, nil }
func (m *mockGuildRepoForMail) CreateMeal(_, _, _ uint32, _ time.Time) (uint32, error) { return 0, nil }
func (m *mockGuildRepoForMail) UpdateMeal(_, _, _ uint32, _ time.Time) error { return nil }
func (m *mockGuildRepoForMail) ClaimHuntBox(_ uint32, _ time.Time) error { return nil }
func (m *mockGuildRepoForMail) ListGuildKills(_, _ uint32) ([]*GuildKill, error) { return nil, nil }
func (m *mockGuildRepoForMail) CountGuildKills(_, _ uint32) (int, error) { return 0, nil }
func (m *mockGuildRepoForMail) ClearTreasureHunt(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) CreateAdventure(_, _ uint32, _, _ int64) error { return nil }
func (m *mockGuildRepoForMail) CreateAdventureWithCharge(_, _, _ uint32, _, _ int64) error {
return nil
}
func (m *mockGuildRepoForMail) CollectAdventure(_ uint32, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) ChargeAdventure(_ uint32, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) GetPendingHunt(_ uint32) (*TreasureHunt, error) { return nil, nil }
func (m *mockGuildRepoForMail) ListGuildHunts(_, _ uint32) ([]*TreasureHunt, error) { return nil, nil }
func (m *mockGuildRepoForMail) CreateHunt(_, _, _, _ uint32, _ []byte, _ string) error { return nil }
func (m *mockGuildRepoForMail) AcquireHunt(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) RegisterHuntReport(_, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) CollectHunt(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) ClaimHuntReward(_, _ uint32) error { return nil }
func (m *mockGuildRepoForMail) ListMeals(_ uint32) ([]*GuildMeal, error) { return nil, nil }
func (m *mockGuildRepoForMail) CreateMeal(_, _, _ uint32, _ time.Time) (uint32, error) { return 0, nil }
func (m *mockGuildRepoForMail) UpdateMeal(_, _, _ uint32, _ time.Time) error { return nil }
func (m *mockGuildRepoForMail) ClaimHuntBox(_ uint32, _ time.Time) error { return nil }
func (m *mockGuildRepoForMail) ListGuildKills(_, _ uint32) ([]*GuildKill, error) { return nil, nil }
func (m *mockGuildRepoForMail) CountGuildKills(_, _ uint32) (int, error) { return 0, nil }
func (m *mockGuildRepoForMail) ClearTreasureHunt(_ uint32) error { return nil }
func (m *mockGuildRepoForMail) InsertKillLog(_ uint32, _ int, _ uint8, _ time.Time) error { return nil }
func (m *mockGuildRepoForMail) ListInvitedCharacters(_ uint32) ([]*ScoutedCharacter, error) { return nil, nil }
func (m *mockGuildRepoForMail) RolloverDailyRP(_ uint32, _ time.Time) error { return nil }
func (m *mockGuildRepoForMail) AddWeeklyBonusUsers(_ uint32, _ uint8) error { return nil }
func (m *mockGuildRepoForMail) ListInvitedCharacters(_ uint32) ([]*ScoutedCharacter, error) {
return nil, nil
}
func (m *mockGuildRepoForMail) RolloverDailyRP(_ uint32, _ time.Time) error { return nil }
func (m *mockGuildRepoForMail) AddWeeklyBonusUsers(_ uint32, _ uint8) error { return nil }
// --- mockGuildRepoOps (enhanced guild repo for ops/scout/board tests) ---
@@ -371,7 +398,7 @@ type mockGuildRepoOps struct {
// Alliance
alliance *GuildAlliance
getAllianceErr error
getAllianceErr error
createAllianceErr error
deleteAllianceErr error
removeAllyErr error
@@ -386,29 +413,29 @@ type mockGuildRepoOps struct {
updateMealErr error
// Adventure
adventures []*GuildAdventure
listAdvErr error
createAdvErr error
collectAdvID uint32
chargeAdvID uint32
chargeAdvAmount uint32
adventures []*GuildAdventure
listAdvErr error
createAdvErr error
collectAdvID uint32
chargeAdvID uint32
chargeAdvAmount uint32
// Treasure hunt
pendingHunt *TreasureHunt
guildHunts []*TreasureHunt
listHuntsErr error
acquireHuntID uint32
reportHuntID uint32
collectHuntID uint32
claimHuntID uint32
createHuntErr error
pendingHunt *TreasureHunt
guildHunts []*TreasureHunt
listHuntsErr error
acquireHuntID uint32
reportHuntID uint32
collectHuntID uint32
claimHuntID uint32
createHuntErr error
// Hunt data
guildKills []*GuildKill
listKillsErr error
countKills int
countKillsErr error
claimBoxCalled bool
guildKills []*GuildKill
listKillsErr error
countKills int
countKillsErr error
claimBoxCalled bool
// Data
membership *GuildMember
@@ -623,46 +650,56 @@ func (m *mockUserRepoForItems) SetItemBox(_ uint32, data []byte) error {
}
// Stub all other UserRepo methods.
func (m *mockUserRepoForItems) GetGachaPoints(_ uint32) (uint32, uint32, uint32, error) { return 0, 0, 0, nil }
func (m *mockUserRepoForItems) GetTrialCoins(_ uint32) (uint16, error) { return 0, nil }
func (m *mockUserRepoForItems) DeductTrialCoins(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) DeductPremiumCoins(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) AddPremiumCoins(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) AddTrialCoins(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) DeductFrontierPoints(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) AddFrontierPoints(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) AdjustFrontierPointsDeduct(_ uint32, _ int) (uint32, error) { return 0, nil }
func (m *mockUserRepoForItems) AdjustFrontierPointsCredit(_ uint32, _ int) (uint32, error) { return 0, nil }
func (m *mockUserRepoForItems) AddFrontierPointsFromGacha(_ uint32, _ uint32, _ uint8) error { return nil }
func (m *mockUserRepoForItems) GetRights(_ uint32) (uint32, error) { return 0, nil }
func (m *mockUserRepoForItems) SetRights(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) IsOp(_ uint32) (bool, error) { return false, nil }
func (m *mockUserRepoForItems) SetLastCharacter(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) GetTimer(_ uint32) (bool, error) { return false, nil }
func (m *mockUserRepoForItems) SetTimer(_ uint32, _ bool) error { return nil }
func (m *mockUserRepoForItems) CountByPSNID(_ string) (int, error) { return 0, nil }
func (m *mockUserRepoForItems) SetPSNID(_ uint32, _ string) error { return nil }
func (m *mockUserRepoForItems) GetDiscordToken(_ uint32) (string, error) { return "", nil }
func (m *mockUserRepoForItems) SetDiscordToken(_ uint32, _ string) error { return nil }
func (m *mockUserRepoForItems) LinkDiscord(_ string, _ string) (string, error) { return "", nil }
func (m *mockUserRepoForItems) SetPasswordByDiscordID(_ string, _ []byte) error { return nil }
func (m *mockUserRepoForItems) GetByIDAndUsername(_ uint32) (uint32, string, error) { return 0, "", nil }
func (m *mockUserRepoForItems) BanUser(_ uint32, _ *time.Time) error { return nil }
func (m *mockUserRepoForItems) GetGachaPoints(_ uint32) (uint32, uint32, uint32, error) {
return 0, 0, 0, nil
}
func (m *mockUserRepoForItems) GetTrialCoins(_ uint32) (uint16, error) { return 0, nil }
func (m *mockUserRepoForItems) DeductTrialCoins(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) DeductPremiumCoins(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) AddPremiumCoins(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) AddTrialCoins(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) DeductFrontierPoints(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) AddFrontierPoints(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) AdjustFrontierPointsDeduct(_ uint32, _ int) (uint32, error) {
return 0, nil
}
func (m *mockUserRepoForItems) AdjustFrontierPointsCredit(_ uint32, _ int) (uint32, error) {
return 0, nil
}
func (m *mockUserRepoForItems) AddFrontierPointsFromGacha(_ uint32, _ uint32, _ uint8) error {
return nil
}
func (m *mockUserRepoForItems) GetRights(_ uint32) (uint32, error) { return 0, nil }
func (m *mockUserRepoForItems) SetRights(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) IsOp(_ uint32) (bool, error) { return false, nil }
func (m *mockUserRepoForItems) SetLastCharacter(_ uint32, _ uint32) error { return nil }
func (m *mockUserRepoForItems) GetTimer(_ uint32) (bool, error) { return false, nil }
func (m *mockUserRepoForItems) SetTimer(_ uint32, _ bool) error { return nil }
func (m *mockUserRepoForItems) CountByPSNID(_ string) (int, error) { return 0, nil }
func (m *mockUserRepoForItems) SetPSNID(_ uint32, _ string) error { return nil }
func (m *mockUserRepoForItems) GetDiscordToken(_ uint32) (string, error) { return "", nil }
func (m *mockUserRepoForItems) SetDiscordToken(_ uint32, _ string) error { return nil }
func (m *mockUserRepoForItems) LinkDiscord(_ string, _ string) (string, error) { return "", nil }
func (m *mockUserRepoForItems) SetPasswordByDiscordID(_ string, _ []byte) error { return nil }
func (m *mockUserRepoForItems) GetByIDAndUsername(_ uint32) (uint32, string, error) {
return 0, "", nil
}
func (m *mockUserRepoForItems) BanUser(_ uint32, _ *time.Time) error { return nil }
// --- mockStampRepoForItems ---
type mockStampRepoForItems struct {
checkedTime time.Time
checkedErr error
totals [2]uint16 // total, redeemed
totalsErr error
initCalled bool
checkedTime time.Time
checkedErr error
totals [2]uint16 // total, redeemed
totalsErr error
initCalled bool
incrementCalled bool
setCalled bool
exchangeResult [2]uint16
exchangeErr error
yearlyResult [2]uint16
yearlyErr error
setCalled bool
exchangeResult [2]uint16
exchangeErr error
yearlyResult [2]uint16
yearlyErr error
// Monthly item fields
monthlyClaimed time.Time
@@ -736,27 +773,33 @@ func (m *mockHouseRepoForItems) SetWarehouseItemData(_ uint32, index uint8, data
return m.setErr
}
func (m *mockHouseRepoForItems) InitializeWarehouse(_ uint32) error { return nil }
func (m *mockHouseRepoForItems) InitializeWarehouse(_ uint32) error { return nil }
// Stub all other HouseRepo methods.
func (m *mockHouseRepoForItems) UpdateInterior(_ uint32, _ []byte) error { return nil }
func (m *mockHouseRepoForItems) GetHouseByCharID(_ uint32) (HouseData, error) { return HouseData{}, nil }
func (m *mockHouseRepoForItems) SearchHousesByName(_ string) ([]HouseData, error) { return nil, nil }
func (m *mockHouseRepoForItems) UpdateHouseState(_ uint32, _ uint8, _ string) error { return nil }
func (m *mockHouseRepoForItems) GetHouseAccess(_ uint32) (uint8, string, error) { return 0, "", nil }
func (m *mockHouseRepoForItems) UpdateInterior(_ uint32, _ []byte) error { return nil }
func (m *mockHouseRepoForItems) GetHouseByCharID(_ uint32) (HouseData, error) {
return HouseData{}, nil
}
func (m *mockHouseRepoForItems) SearchHousesByName(_ string) ([]HouseData, error) { return nil, nil }
func (m *mockHouseRepoForItems) UpdateHouseState(_ uint32, _ uint8, _ string) error { return nil }
func (m *mockHouseRepoForItems) GetHouseAccess(_ uint32) (uint8, string, error) { return 0, "", nil }
func (m *mockHouseRepoForItems) GetHouseContents(_ uint32) ([]byte, []byte, []byte, []byte, []byte, []byte, []byte, error) {
return nil, nil, nil, nil, nil, nil, nil, nil
}
func (m *mockHouseRepoForItems) GetMission(_ uint32) ([]byte, error) { return nil, nil }
func (m *mockHouseRepoForItems) UpdateMission(_ uint32, _ []byte) error { return nil }
func (m *mockHouseRepoForItems) GetMission(_ uint32) ([]byte, error) { return nil, nil }
func (m *mockHouseRepoForItems) UpdateMission(_ uint32, _ []byte) error { return nil }
func (m *mockHouseRepoForItems) GetWarehouseNames(_ uint32) ([10]string, [10]string, error) {
return [10]string{}, [10]string{}, nil
}
func (m *mockHouseRepoForItems) RenameWarehouseBox(_ uint32, _ uint8, _ uint8, _ string) error { return nil }
func (m *mockHouseRepoForItems) GetWarehouseEquipData(_ uint32, _ uint8) ([]byte, error) { return nil, nil }
func (m *mockHouseRepoForItems) SetWarehouseEquipData(_ uint32, _ uint8, _ []byte) error { return nil }
func (m *mockHouseRepoForItems) GetTitles(_ uint32) ([]Title, error) { return nil, nil }
func (m *mockHouseRepoForItems) AcquireTitle(_ uint16, _ uint32) error { return nil }
func (m *mockHouseRepoForItems) RenameWarehouseBox(_ uint32, _ uint8, _ uint8, _ string) error {
return nil
}
func (m *mockHouseRepoForItems) GetWarehouseEquipData(_ uint32, _ uint8) ([]byte, error) {
return nil, nil
}
func (m *mockHouseRepoForItems) SetWarehouseEquipData(_ uint32, _ uint8, _ []byte) error { return nil }
func (m *mockHouseRepoForItems) GetTitles(_ uint32) ([]Title, error) { return nil, nil }
func (m *mockHouseRepoForItems) AcquireTitle(_ uint16, _ uint32) error { return nil }
// --- mockSessionRepo ---
@@ -766,11 +809,13 @@ type mockSessionRepo struct {
clearErr error
updateErr error
boundToken string
boundToken string
clearedToken string
}
func (m *mockSessionRepo) ValidateLoginToken(_ string, _ uint32, _ uint32) error { return m.validateErr }
func (m *mockSessionRepo) ValidateLoginToken(_ string, _ uint32, _ uint32) error {
return m.validateErr
}
func (m *mockSessionRepo) BindSession(token string, _ uint16, _ uint32) error {
m.boundToken = token
return m.bindErr
@@ -816,10 +861,10 @@ type mockGachaRepo struct {
deletedBox bool
// Shop
gachas []Gacha
listShopErr error
shopType int
allEntries []GachaEntry
gachas []Gacha
listShopErr error
shopType int
allEntries []GachaEntry
allEntriesErr error
weightDivisor float64
@@ -873,8 +918,8 @@ func (m *mockGachaRepo) DeleteBoxEntries(_ uint32, _ uint32) error {
m.deletedBox = true
return nil
}
func (m *mockGachaRepo) ListShop() ([]Gacha, error) { return m.gachas, m.listShopErr }
func (m *mockGachaRepo) GetShopType(_ uint32) (int, error) { return m.shopType, nil }
func (m *mockGachaRepo) ListShop() ([]Gacha, error) { return m.gachas, m.listShopErr }
func (m *mockGachaRepo) GetShopType(_ uint32) (int, error) { return m.shopType, nil }
func (m *mockGachaRepo) GetAllEntries(_ uint32) ([]GachaEntry, error) {
return m.allEntries, m.allEntriesErr
}
@@ -917,11 +962,11 @@ type mockUserRepoGacha struct {
mockUserRepoForItems
gachaFP, gachaGP, gachaGT uint32
trialCoins uint16
deductTrialErr error
deductPremiumErr error
deductFPErr error
addFPFromGachaErr error
trialCoins uint16
deductTrialErr error
deductPremiumErr error
deductFPErr error
addFPFromGachaErr error
fpDeductBalance uint32
fpDeductErr error
@@ -952,4 +997,4 @@ func (m *mockUserRepoGacha) AdjustFrontierPointsCredit(_ uint32, _ int) (uint32,
return m.fpCreditBalance, m.fpCreditErr
}
func (m *mockUserRepoGacha) SetLastCharacter(_ uint32, _ uint32) error { return m.setLastCharErr }
func (m *mockUserRepoGacha) GetRights(_ uint32) (uint32, error) { return m.rights, m.rightsErr }
func (m *mockUserRepoGacha) GetRights(_ uint32) (uint32, error) { return m.rights, m.rightsErr }

View File

@@ -25,19 +25,19 @@ import (
// SaveHandlerMonitor tracks calls to save handlers
type SaveHandlerMonitor struct {
mu sync.Mutex
savedataCallCount int
hunterNaviCallCount int
kouryouPointCallCount int
warehouseCallCount int
decomysetCallCount int
savedataAtLogout bool
lastSavedataTime time.Time
lastHunterNaviTime time.Time
lastKouryouPointTime time.Time
lastWarehouseTime time.Time
lastDecomysetTime time.Time
logoutTime time.Time
mu sync.Mutex
savedataCallCount int
hunterNaviCallCount int
kouryouPointCallCount int
warehouseCallCount int
decomysetCallCount int
savedataAtLogout bool
lastSavedataTime time.Time
lastHunterNaviTime time.Time
lastKouryouPointTime time.Time
lastWarehouseTime time.Time
lastDecomysetTime time.Time
logoutTime time.Time
}
func (m *SaveHandlerMonitor) RecordSavedata() {
@@ -79,7 +79,7 @@ func (m *SaveHandlerMonitor) RecordLogout() {
m.mu.Lock()
defer m.mu.Unlock()
m.logoutTime = time.Now()
// Check if savedata was called within 5 seconds before logout
if !m.lastSavedataTime.IsZero() && m.logoutTime.Sub(m.lastSavedataTime) < 5*time.Second {
m.savedataAtLogout = true
@@ -89,7 +89,7 @@ func (m *SaveHandlerMonitor) RecordLogout() {
func (m *SaveHandlerMonitor) GetStats() string {
m.mu.Lock()
defer m.mu.Unlock()
return fmt.Sprintf(`Save Handler Statistics:
- Savedata calls: %d (last: %v)
- HunterNavi calls: %d (last: %v)
@@ -385,7 +385,7 @@ func TestSequential_RepeatedLogoutLoginCycles(t *testing.T) {
// Verify data after each cycle
var savedCompressed []byte
_ = db.QueryRow("SELECT savedata FROM characters WHERE id = $1", charID).Scan(&savedCompressed)
if len(savedCompressed) > 0 {
decompressed, err := nullcomp.Decompress(savedCompressed)
if err != nil {
@@ -393,7 +393,7 @@ func TestSequential_RepeatedLogoutLoginCycles(t *testing.T) {
} else if len(decompressed) > 7001 {
savedCycle := (int(decompressed[7000]) << 8) | int(decompressed[7001])
if savedCycle != cycle {
t.Errorf("Cycle %d: ❌ Data corruption - expected cycle %d, got %d",
t.Errorf("Cycle %d: ❌ Data corruption - expected cycle %d, got %d",
cycle, cycle, savedCycle)
} else {
t.Logf("Cycle %d: ✓ Data correct", cycle)
@@ -431,7 +431,7 @@ func TestRealtime_SaveDataTimestamps(t *testing.T) {
saveData := make([]byte, 150000)
copy(saveData[88:], []byte("TimestampChar\x00"))
compressed, _ := nullcomp.Compress(saveData)
savePkt := &mhfpacket.MsgMhfSavedata{
SaveType: 0,
AckHandle: 11001,
@@ -477,7 +477,7 @@ func TestRealtime_SaveDataTimestamps(t *testing.T) {
if !lastSaveTime.IsZero() && !logoutTime.IsZero() {
gap := logoutTime.Sub(lastSaveTime)
t.Logf("Time between last save and logout: %v", gap.Round(time.Millisecond))
if gap > 50*time.Millisecond {
t.Log("⚠️ Significant gap between last save and logout")
t.Log("Player changes after last save would be LOST")
@@ -498,4 +498,3 @@ func containsAny(s string, substrs []string) bool {
}
return false
}

View File

@@ -6,8 +6,8 @@ import (
"testing"
"time"
cfg "erupe-ce/config"
"erupe-ce/common/mhfitem"
cfg "erupe-ce/config"
"erupe-ce/network/clientctx"
"erupe-ce/network/mhfpacket"
"erupe-ce/server/channelserver/compression/nullcomp"
@@ -18,9 +18,9 @@ import (
// ============================================================================
// SESSION LIFECYCLE INTEGRATION TESTS
// Full end-to-end tests that simulate the complete player session lifecycle
//
//
// These tests address the core issue: handler-level tests don't catch problems
// with the logout flow. Players report data loss because logout doesn't
// with the logout flow. Players report data loss because logout doesn't
// trigger save handlers.
//
// Test Strategy:
@@ -580,16 +580,16 @@ func createTestServerWithDB(t *testing.T, db *sqlx.DB) *Server {
// Create minimal server for testing
// Note: This may need adjustment based on actual Server initialization
server := &Server{
db: db,
sessions: make(map[net.Conn]*Session),
db: db,
sessions: make(map[net.Conn]*Session),
userBinary: NewUserBinaryStore(),
minidata: NewMinidataStore(),
semaphore: make(map[string]*Semaphore),
semaphore: make(map[string]*Semaphore),
erupeConfig: &cfg.Config{
RealClientMode: cfg.ZZ,
},
isShuttingDown: false,
done: make(chan struct{}),
isShuttingDown: false,
done: make(chan struct{}),
}
// Create logger
@@ -617,7 +617,7 @@ func createTestServerWithDB(t *testing.T, db *sqlx.DB) *Server {
func createTestSessionForServerWithChar(server *Server, charID uint32, name string) *Session {
mock := &MockCryptConn{sentPackets: make([][]byte, 0)}
mockNetConn := NewMockNetConn() // Create a mock net.Conn for the session map key
session := &Session{
logger: server.logger,
server: server,
@@ -638,4 +638,3 @@ func createTestSessionForServerWithChar(server *Server, charID uint32, name stri
return session
}

View File

@@ -43,13 +43,13 @@ type Config struct {
// own locks internally and may be acquired at any point.
type Server struct {
sync.Mutex
Registry ChannelRegistry
ID uint16
GlobalID string
IP string
Port uint16
logger *zap.Logger
db *sqlx.DB
Registry ChannelRegistry
ID uint16
GlobalID string
IP string
Port uint16
logger *zap.Logger
db *sqlx.DB
charRepo CharacterRepo
guildRepo GuildRepo
userRepo UserRepo
@@ -71,13 +71,13 @@ type Server struct {
miscRepo MiscRepo
scenarioRepo ScenarioRepo
mercenaryRepo MercenaryRepo
erupeConfig *cfg.Config
acceptConns chan net.Conn
deleteConns chan net.Conn
sessions map[net.Conn]*Session
listener net.Listener // Listener that is created when Server.Start is called.
isShuttingDown bool
done chan struct{} // Closed on Shutdown to wake background goroutines.
erupeConfig *cfg.Config
acceptConns chan net.Conn
deleteConns chan net.Conn
sessions map[net.Conn]*Session
listener net.Listener // Listener that is created when Server.Start is called.
isShuttingDown bool
done chan struct{} // Closed on Shutdown to wake background goroutines.
stages StageMap
@@ -107,28 +107,28 @@ type Server struct {
// NewServer creates a new Server type.
func NewServer(config *Config) *Server {
s := &Server{
ID: config.ID,
logger: config.Logger,
db: config.DB,
erupeConfig: config.ErupeConfig,
acceptConns: make(chan net.Conn),
deleteConns: make(chan net.Conn),
done: make(chan struct{}),
sessions: make(map[net.Conn]*Session),
userBinary: NewUserBinaryStore(),
minidata: NewMinidataStore(),
semaphore: make(map[string]*Semaphore),
semaphoreIndex: 7,
discordBot: config.DiscordBot,
name: config.Name,
ID: config.ID,
logger: config.Logger,
db: config.DB,
erupeConfig: config.ErupeConfig,
acceptConns: make(chan net.Conn),
deleteConns: make(chan net.Conn),
done: make(chan struct{}),
sessions: make(map[net.Conn]*Session),
userBinary: NewUserBinaryStore(),
minidata: NewMinidataStore(),
semaphore: make(map[string]*Semaphore),
semaphoreIndex: 7,
discordBot: config.DiscordBot,
name: config.Name,
raviente: &Raviente{
id: 1,
register: make([]uint32, 30),
state: make([]uint32, 30),
support: make([]uint32, 30),
},
questCache: NewQuestCache(config.ErupeConfig.QuestCacheExpiry),
handlerTable: buildHandlerTable(),
questCache: NewQuestCache(config.ErupeConfig.QuestCacheExpiry),
handlerTable: buildHandlerTable(),
}
s.charRepo = NewCharacterRepository(config.DB)

View File

@@ -36,9 +36,11 @@ func (m *mockConn) RemoteAddr() net.Addr {
return &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 12345}
}
func (m *mockConn) Read(b []byte) (n int, err error) { return 0, nil }
func (m *mockConn) Write(b []byte) (n int, err error) { return len(b), nil }
func (m *mockConn) LocalAddr() net.Addr { return &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 54321} }
func (m *mockConn) Read(b []byte) (n int, err error) { return 0, nil }
func (m *mockConn) Write(b []byte) (n int, err error) { return len(b), nil }
func (m *mockConn) LocalAddr() net.Addr {
return &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 54321}
}
func (m *mockConn) SetDeadline(t time.Time) error { return nil }
func (m *mockConn) SetReadDeadline(t time.Time) error { return nil }
func (m *mockConn) SetWriteDeadline(t time.Time) error { return nil }
@@ -53,10 +55,10 @@ func (m *mockConn) WasClosed() bool {
func createTestServer() *Server {
logger, _ := zap.NewDevelopment()
s := &Server{
ID: 1,
logger: logger,
sessions: make(map[net.Conn]*Session),
semaphore: make(map[string]*Semaphore),
ID: 1,
logger: logger,
sessions: make(map[net.Conn]*Session),
semaphore: make(map[string]*Semaphore),
questCache: NewQuestCache(0),
erupeConfig: &cfg.Config{
DebugOptions: cfg.DebugOptions{
@@ -79,15 +81,15 @@ func createTestServer() *Server {
func createTestSessionForServer(server *Server, conn net.Conn, charID uint32, name string) *Session {
mock := &MockCryptConn{sentPackets: make([][]byte, 0)}
s := &Session{
logger: server.logger,
server: server,
rawConn: conn,
cryptConn: mock,
sendPackets: make(chan packet, 20),
logger: server.logger,
server: server,
rawConn: conn,
cryptConn: mock,
sendPackets: make(chan packet, 20),
clientContext: &clientctx.ClientContext{},
lastPacket: time.Now(),
charID: charID,
Name: name,
lastPacket: time.Now(),
charID: charID,
Name: name,
}
return s
}

View File

@@ -319,4 +319,3 @@ func TestStageBroadcastMHF_EmptyStage(t *testing.T) {
// Should not panic with empty stage
stage.BroadcastMHF(pkt, nil)
}

View File

@@ -4,7 +4,7 @@ import (
"bytes"
"encoding/binary"
"io"
cfg "erupe-ce/config"
"erupe-ce/network"
"sync"
@@ -76,27 +76,27 @@ func createTestSession(mock network.Conn) *Session {
// with their own terminators instead of being concatenated
func TestPacketQueueIndividualSending(t *testing.T) {
tests := []struct {
name string
packetCount int
wantPackets int
name string
packetCount int
wantPackets int
wantTerminators int
}{
{
name: "single_packet",
packetCount: 1,
wantPackets: 1,
name: "single_packet",
packetCount: 1,
wantPackets: 1,
wantTerminators: 1,
},
{
name: "multiple_packets",
packetCount: 5,
wantPackets: 5,
name: "multiple_packets",
packetCount: 5,
wantPackets: 5,
wantTerminators: 5,
},
{
name: "many_packets",
packetCount: 20,
wantPackets: 20,
name: "many_packets",
packetCount: 20,
wantPackets: 20,
wantTerminators: 20,
},
}

View File

@@ -287,4 +287,3 @@ func TestStageNewMaxPlayers(t *testing.T) {
t.Errorf("initial maxPlayers = %d, want 127", stage.maxPlayers)
}
}

View File

@@ -10,9 +10,9 @@ import (
// convenient access to adjusted server time, daily/weekly boundaries, and the
// absolute game timestamp used by the MHF client.
func TimeAdjusted() time.Time { return gametime.Adjusted() }
func TimeMidnight() time.Time { return gametime.Midnight() }
func TimeWeekStart() time.Time { return gametime.WeekStart() }
func TimeWeekNext() time.Time { return gametime.WeekNext() }
func TimeMonthStart() time.Time { return gametime.MonthStart() }
func TimeGameAbsolute() uint32 { return gametime.GameAbsolute() }
func TimeAdjusted() time.Time { return gametime.Adjusted() }
func TimeMidnight() time.Time { return gametime.Midnight() }
func TimeWeekStart() time.Time { return gametime.WeekStart() }
func TimeWeekNext() time.Time { return gametime.WeekNext() }
func TimeMonthStart() time.Time { return gametime.MonthStart() }
func TimeGameAbsolute() uint32 { return gametime.GameAbsolute() }

View File

@@ -38,8 +38,8 @@ func (m *mockPacket) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext
func createMockServer() *Server {
logger, _ := zap.NewDevelopment()
s := &Server{
logger: logger,
erupeConfig: &cfg.Config{},
logger: logger,
erupeConfig: &cfg.Config{},
// stages is a StageMap (zero value is ready to use)
sessions: make(map[net.Conn]*Session),
handlerTable: buildHandlerTable(),

View File

@@ -124,6 +124,7 @@ func (bot *DiscordBot) RealtimeChannelSend(message string) (err error) {
return
}
// ReplaceTextAll replaces every match of regex in text by calling handler with
// the first capture group of each match and substituting the result.
func ReplaceTextAll(text string, regex *regexp.Regexp, handler func(input string) string) string {

View File

@@ -229,8 +229,8 @@ func TestNormalizeDiscordMessage_Integration(t *testing.T) {
contains: []string{"Hello", ":smile:"},
},
{
name: "mixed content",
input: "<@123456789012345678> sent :wave:",
name: "mixed content",
input: "<@123456789012345678> sent :wave:",
contains: []string{"sent"},
},
}

View File

@@ -23,11 +23,11 @@ func TestEncodeServerInfo_EmptyClanMemberLimits(t *testing.T) {
Port: 53310,
Entries: []cfg.EntranceServerInfo{
{
Name: "TestServer",
Description: "Test",
IP: "127.0.0.1",
Type: 0,
Recommended: 0,
Name: "TestServer",
Description: "Test",
IP: "127.0.0.1",
Type: 0,
Recommended: 0,
AllowedClientFlags: 0xFFFFFFFF,
Channels: []cfg.EntranceChannelInfo{
{
@@ -74,10 +74,10 @@ func TestEncodeServerInfo_EmptyClanMemberLimits(t *testing.T) {
func TestClanMemberLimitsBoundsChecking(t *testing.T) {
// Test the bounds checking logic directly
testCases := []struct {
name string
clanMemberLimits [][]uint8
expectedValue uint8
expectDefault bool
name string
clanMemberLimits [][]uint8
expectedValue uint8
expectDefault bool
}{
{"empty array", [][]uint8{}, 60, true},
{"single row with 2 columns", [][]uint8{{1, 50}}, 50, false},
@@ -112,7 +112,6 @@ func TestClanMemberLimitsBoundsChecking(t *testing.T) {
}
}
// TestEncodeServerInfo_WithMockRepo tests encodeServerInfo with a mock server repo
func TestEncodeServerInfo_WithMockRepo(t *testing.T) {
config := &cfg.Config{
@@ -123,11 +122,11 @@ func TestEncodeServerInfo_WithMockRepo(t *testing.T) {
Port: 53310,
Entries: []cfg.EntranceServerInfo{
{
Name: "TestServer",
Description: "Test",
IP: "127.0.0.1",
Type: 0,
Recommended: 0,
Name: "TestServer",
Description: "Test",
IP: "127.0.0.1",
Type: 0,
Recommended: 0,
AllowedClientFlags: 0xFFFFFFFF,
Channels: []cfg.EntranceChannelInfo{
{
@@ -218,11 +217,11 @@ func TestEncodeServerInfo_MissingSecondColumnClanMemberLimits(t *testing.T) {
Port: 53310,
Entries: []cfg.EntranceServerInfo{
{
Name: "TestServer",
Description: "Test",
IP: "127.0.0.1",
Type: 0,
Recommended: 0,
Name: "TestServer",
Description: "Test",
IP: "127.0.0.1",
Type: 0,
Recommended: 0,
AllowedClientFlags: 0xFFFFFFFF,
Channels: []cfg.EntranceChannelInfo{
{

View File

@@ -2,10 +2,10 @@ package signserver
import (
"erupe-ce/common/byteframe"
"erupe-ce/common/gametime"
ps "erupe-ce/common/pascalstring"
"erupe-ce/common/stringsupport"
cfg "erupe-ce/config"
"erupe-ce/common/gametime"
"fmt"
"strings"
"time"