diff --git a/server/channelserver/handlers_character_test.go b/server/channelserver/handlers_character_test.go index 1646fcc3d..f88a205f3 100644 --- a/server/channelserver/handlers_character_test.go +++ b/server/channelserver/handlers_character_test.go @@ -2,7 +2,9 @@ package channelserver import ( "bytes" + "database/sql" "encoding/binary" + "errors" "testing" cfg "erupe-ce/config" @@ -571,3 +573,175 @@ func BenchmarkDecompress(b *testing.B) { _ = save.Decompress() } } + +// --- Mock-based GetCharacterSaveData tests --- + +func TestGetCharacterSaveData_NilSavedata(t *testing.T) { + server := createMockServer() + mock := newMockCharacterRepo() + mock.loadSaveDataID = 42 + mock.loadSaveDataName = "Hunter" + mock.loadSaveDataNew = true + server.charRepo = mock + session := createMockSession(42, server) + + result, err := GetCharacterSaveData(session, 42) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if result == nil { + t.Fatal("expected non-nil result") + } + if result.CharID != 42 { + t.Errorf("CharID = %d, want 42", result.CharID) + } + if result.Name != "Hunter" { + t.Errorf("Name = %q, want %q", result.Name, "Hunter") + } + if !result.IsNewCharacter { + t.Error("IsNewCharacter should be true") + } +} + +func TestGetCharacterSaveData_NotFound(t *testing.T) { + server := createMockServer() + mock := newMockCharacterRepo() + mock.loadSaveDataErr = sql.ErrNoRows + server.charRepo = mock + session := createMockSession(1, server) + + result, err := GetCharacterSaveData(session, 999) + if err == nil { + t.Fatal("expected error for missing character") + } + if result != nil { + t.Error("expected nil result for missing character") + } +} + +func TestGetCharacterSaveData_DBError(t *testing.T) { + server := createMockServer() + mock := newMockCharacterRepo() + mock.loadSaveDataErr = errors.New("connection refused") + server.charRepo = mock + session := createMockSession(1, server) + + result, err := GetCharacterSaveData(session, 1) + if err == nil { + t.Fatal("expected error on DB failure") + } + if result != nil { + t.Error("expected nil result on DB failure") + } +} + +func TestGetCharacterSaveData_WithCompressedData(t *testing.T) { + server := createMockServer() + mock := newMockCharacterRepo() + + // Create minimal valid savedata and compress it + saveData := make([]byte, 150000) + copy(saveData[88:], append([]byte("TestHunter"), 0x00)) + compressed, err := nullcomp.Compress(saveData) + if err != nil { + t.Fatalf("failed to compress test savedata: %v", err) + } + + mock.loadSaveDataID = 10 + mock.loadSaveDataData = compressed + mock.loadSaveDataName = "TestHunter" + mock.loadSaveDataNew = false + server.charRepo = mock + session := createMockSession(10, server) + + result, err := GetCharacterSaveData(session, 10) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if result == nil { + t.Fatal("expected non-nil result") + } + if result.CharID != 10 { + t.Errorf("CharID = %d, want 10", result.CharID) + } + if result.IsNewCharacter { + t.Error("IsNewCharacter should be false") + } + if result.Name != "TestHunter" { + t.Errorf("Name = %q, want %q", result.Name, "TestHunter") + } +} + +func TestGetCharacterSaveData_NewCharacterSkipsDecompress(t *testing.T) { + // When savedata is nil AND IsNewCharacter=true, GetCharacterSaveData + // returns a valid result without decompressing. + server := createMockServer() + mock := newMockCharacterRepo() + mock.loadSaveDataID = 5 + mock.loadSaveDataName = "NewPlayer" + mock.loadSaveDataNew = true + // loadSaveDataData is nil + server.charRepo = mock + session := createMockSession(5, server) + + result, err := GetCharacterSaveData(session, 5) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if result == nil { + t.Fatal("expected non-nil result") + } + if !result.IsNewCharacter { + t.Error("IsNewCharacter should be true") + } + if result.CharID != 5 { + t.Errorf("CharID = %d, want 5", result.CharID) + } +} + +func TestGetCharacterSaveData_ConfigMode(t *testing.T) { + server := createMockServer() + mock := newMockCharacterRepo() + + saveData := make([]byte, 150000) + copy(saveData[88:], append([]byte("ModeTest"), 0x00)) + compressed, err := nullcomp.Compress(saveData) + if err != nil { + t.Fatalf("failed to compress: %v", err) + } + + mock.loadSaveDataID = 1 + mock.loadSaveDataData = compressed + mock.loadSaveDataName = "ModeTest" + server.charRepo = mock + + modes := []struct { + mode cfg.Mode + name string + }{ + {cfg.S6, "S6"}, + {cfg.F5, "F5"}, + {cfg.G10, "G10"}, + {cfg.Z2, "Z2"}, + {cfg.ZZ, "ZZ"}, + } + for _, tc := range modes { + mode := tc.mode + t.Run(tc.name, func(t *testing.T) { + server.erupeConfig.RealClientMode = mode + session := createMockSession(1, server) + + result, err := GetCharacterSaveData(session, 1) + if err != nil { + t.Fatalf("unexpected error for mode %v: %v", mode, err) + } + if result.Mode != mode { + t.Errorf("Mode = %v, want %v", result.Mode, mode) + } + expectedPointers := getPointers(mode) + if len(result.Pointers) != len(expectedPointers) { + t.Errorf("Pointers count = %d, want %d", len(result.Pointers), len(expectedPointers)) + } + }) + } +} diff --git a/server/channelserver/repo_distribution.go b/server/channelserver/repo_distribution.go index c54e047cb..7ef8a42f6 100644 --- a/server/channelserver/repo_distribution.go +++ b/server/channelserver/repo_distribution.go @@ -33,7 +33,7 @@ func (r *DistributionRepository) List(charID uint32, distType uint8) ([]Distribu if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() var dists []Distribution for rows.Next() { @@ -52,7 +52,7 @@ func (r *DistributionRepository) GetItems(distributionID uint32) ([]Distribution if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() var items []DistributionItem for rows.Next() { diff --git a/server/channelserver/repo_festa.go b/server/channelserver/repo_festa.go index 7458bc290..ca3d61b34 100644 --- a/server/channelserver/repo_festa.go +++ b/server/channelserver/repo_festa.go @@ -63,7 +63,7 @@ func (r *FestaRepository) GetFestaEvents() ([]FestaEvent, error) { if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var e FestaEvent if err := rows.StructScan(&e); err != nil { @@ -103,7 +103,7 @@ func (r *FestaRepository) GetTrialsWithMonopoly() ([]FestaTrial, error) { if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var trial FestaTrial if err := rows.StructScan(&trial); err != nil { @@ -213,7 +213,7 @@ func (r *FestaRepository) ListPrizes(charID uint32, prizeType string) ([]Prize, if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var prize Prize if err := rows.StructScan(&prize); err != nil { diff --git a/server/channelserver/repo_gacha.go b/server/channelserver/repo_gacha.go index f361b8706..b2efcf303 100644 --- a/server/channelserver/repo_gacha.go +++ b/server/channelserver/repo_gacha.go @@ -38,7 +38,7 @@ func (r *GachaRepository) GetRewardPool(gachaID uint32) ([]GachaEntry, error) { if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var entry GachaEntry if err := rows.StructScan(&entry); err == nil { @@ -58,7 +58,7 @@ func (r *GachaRepository) GetItemsForEntry(entryID uint32) ([]GachaItem, error) if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var item GachaItem if err := rows.StructScan(&item); err == nil { @@ -78,7 +78,7 @@ func (r *GachaRepository) GetGuaranteedItems(rollType uint8, gachaID uint32) ([] if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var item GachaItem if err := rows.StructScan(&item); err == nil { @@ -155,7 +155,7 @@ func (r *GachaRepository) GetBoxEntryIDs(gachaID uint32, charID uint32) ([]uint3 if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var id uint32 if err := rows.Scan(&id); err == nil { @@ -194,7 +194,7 @@ func (r *GachaRepository) ListShop() ([]Gacha, error) { if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var g Gacha if err := rows.StructScan(&g); err == nil { @@ -224,7 +224,7 @@ func (r *GachaRepository) GetAllEntries(gachaID uint32) ([]GachaEntry, error) { if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var entry GachaEntry if err := rows.StructScan(&entry); err == nil { diff --git a/server/channelserver/repo_guild.go b/server/channelserver/repo_guild.go index 68087a3d0..4eb0c27a9 100644 --- a/server/channelserver/repo_guild.go +++ b/server/channelserver/repo_guild.go @@ -115,7 +115,7 @@ func (r *GuildRepository) GetByID(guildID uint32) (*Guild, error) { if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() if !rows.Next() { return nil, nil } @@ -144,7 +144,7 @@ func (r *GuildRepository) GetByCharID(charID uint32) (*Guild, error) { if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() if !rows.Next() { return nil, nil } @@ -157,7 +157,7 @@ func (r *GuildRepository) ListAll() ([]*Guild, error) { if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() var guilds []*Guild for rows.Next() { @@ -370,7 +370,7 @@ func (r *GuildRepository) GetMembers(guildID uint32, applicants bool) ([]*GuildM if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() members := make([]*GuildMember, 0) for rows.Next() { @@ -390,7 +390,7 @@ func (r *GuildRepository) GetCharacterMembership(charID uint32) (*GuildMember, e if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() if !rows.Next() { return nil, nil @@ -486,7 +486,7 @@ func (r *GuildRepository) ListPosts(guildID uint32, postType int) ([]*MessageBoa if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() var posts []*MessageBoardPost for rows.Next() { post := &MessageBoardPost{} @@ -504,7 +504,7 @@ func (r *GuildRepository) CreatePost(guildID, authorID, stampID uint32, postType if err != nil { return err } - defer tx.Rollback() + defer func() { _ = tx.Rollback() }() if _, err := tx.Exec( `INSERT INTO guild_posts (guild_id, author_id, stamp_id, post_type, title, body) VALUES ($1, $2, $3, $4, $5, $6)`, @@ -585,7 +585,7 @@ func (r *GuildRepository) GetAllianceByID(allianceID uint32) (*GuildAlliance, er if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() if !rows.Next() { return nil, nil } @@ -598,7 +598,7 @@ func (r *GuildRepository) ListAlliances() ([]*GuildAlliance, error) { if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() var alliances []*GuildAlliance for rows.Next() { alliance, err := r.scanAllianceWithGuilds(rows) @@ -679,7 +679,7 @@ func (r *GuildRepository) ListAdventures(guildID uint32) ([]*GuildAdventure, err if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() var adventures []*GuildAdventure for rows.Next() { adv := &GuildAdventure{} @@ -714,7 +714,7 @@ func (r *GuildRepository) CollectAdventure(adventureID uint32, charID uint32) er if err != nil { return err } - defer tx.Rollback() + defer func() { _ = tx.Rollback() }() var collectedBy string err = tx.QueryRow("SELECT collected_by FROM guild_adventures WHERE id = $1 FOR UPDATE", adventureID).Scan(&collectedBy) @@ -766,7 +766,7 @@ func (r *GuildRepository) ListGuildHunts(guildID, charID uint32) ([]*TreasureHun if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() var hunts []*TreasureHunt for rows.Next() { hunt := &TreasureHunt{} @@ -821,7 +821,7 @@ func (r *GuildRepository) ListMeals(guildID uint32) ([]*GuildMeal, error) { if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() var meals []*GuildMeal for rows.Next() { meal := &GuildMeal{} @@ -871,7 +871,7 @@ func (r *GuildRepository) ListGuildKills(guildID, charID uint32) ([]*GuildKill, if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() var kills []*GuildKill for rows.Next() { kill := &GuildKill{} @@ -928,7 +928,7 @@ func (r *GuildRepository) ListInvitedCharacters(guildID uint32) ([]*ScoutedChara if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() var chars []*ScoutedCharacter for rows.Next() { sc := &ScoutedCharacter{} diff --git a/server/channelserver/repo_guild_test.go b/server/channelserver/repo_guild_test.go index 7dcc4e571..84449de52 100644 --- a/server/channelserver/repo_guild_test.go +++ b/server/channelserver/repo_guild_test.go @@ -935,10 +935,14 @@ func TestRemoveGuildFromAllianceSub1(t *testing.T) { t.Fatalf("CreateAlliance failed: %v", err) } var allianceID uint32 - db.QueryRow("SELECT id FROM guild_alliances WHERE parent_id=$1", guildID).Scan(&allianceID) + if err := db.QueryRow("SELECT id FROM guild_alliances WHERE parent_id=$1", guildID).Scan(&allianceID); err != nil { + t.Fatalf("Failed to get alliance ID: %v", err) + } // Add sub1 - db.Exec("UPDATE guild_alliances SET sub1_id=$1 WHERE id=$2", guild2, allianceID) + if _, err := db.Exec("UPDATE guild_alliances SET sub1_id=$1 WHERE id=$2", guild2, allianceID); err != nil { + t.Fatalf("Failed to set sub1: %v", err) + } // Remove sub1 if err := repo.RemoveGuildFromAlliance(allianceID, guild2, guild2, 0); err != nil { @@ -972,8 +976,12 @@ func TestRemoveGuildFromAllianceSub1ShiftsSub2(t *testing.T) { t.Fatalf("CreateAlliance failed: %v", err) } var allianceID uint32 - db.QueryRow("SELECT id FROM guild_alliances WHERE parent_id=$1", guildID).Scan(&allianceID) - db.Exec("UPDATE guild_alliances SET sub1_id=$1, sub2_id=$2 WHERE id=$3", guild2, guild3, allianceID) + if err := db.QueryRow("SELECT id FROM guild_alliances WHERE parent_id=$1", guildID).Scan(&allianceID); err != nil { + t.Fatalf("Failed to get alliance ID: %v", err) + } + if _, err := db.Exec("UPDATE guild_alliances SET sub1_id=$1, sub2_id=$2 WHERE id=$3", guild2, guild3, allianceID); err != nil { + t.Fatalf("Failed to set sub guilds: %v", err) + } // Remove sub1 — sub2 should shift into sub1's slot if err := repo.RemoveGuildFromAlliance(allianceID, guild2, guild2, guild3); err != nil { @@ -1010,8 +1018,12 @@ func TestRemoveGuildFromAllianceSub2(t *testing.T) { t.Fatalf("CreateAlliance failed: %v", err) } var allianceID uint32 - db.QueryRow("SELECT id FROM guild_alliances WHERE parent_id=$1", guildID).Scan(&allianceID) - db.Exec("UPDATE guild_alliances SET sub1_id=$1, sub2_id=$2 WHERE id=$3", guild2, guild3, allianceID) + if err := db.QueryRow("SELECT id FROM guild_alliances WHERE parent_id=$1", guildID).Scan(&allianceID); err != nil { + t.Fatalf("Failed to get alliance ID: %v", err) + } + if _, err := db.Exec("UPDATE guild_alliances SET sub1_id=$1, sub2_id=$2 WHERE id=$3", guild2, guild3, allianceID); err != nil { + t.Fatalf("Failed to set sub guilds: %v", err) + } // Remove sub2 directly if err := repo.RemoveGuildFromAlliance(allianceID, guild3, guild2, guild3); err != nil { @@ -1093,7 +1105,9 @@ func TestChargeAdventure(t *testing.T) { } var charge uint32 - db.QueryRow("SELECT charge FROM guild_adventures WHERE id=$1", advID).Scan(&charge) + if err := db.QueryRow("SELECT charge FROM guild_adventures WHERE id=$1", advID).Scan(&charge); err != nil { + t.Fatalf("Failed to get charge: %v", err) + } if charge != 25 { t.Errorf("Expected charge=25, got %d", charge) } @@ -1194,7 +1208,9 @@ func TestAcquireHunt(t *testing.T) { // Verify in DB var acquired bool - db.QueryRow("SELECT acquired FROM guild_hunts WHERE id=$1", hunt.HuntID).Scan(&acquired) + if err := db.QueryRow("SELECT acquired FROM guild_hunts WHERE id=$1", hunt.HuntID).Scan(&acquired); err != nil { + t.Fatalf("Failed to get acquired: %v", err) + } if !acquired { t.Error("Expected acquired=true in DB") } @@ -1208,7 +1224,9 @@ func TestListGuildHunts(t *testing.T) { t.Fatalf("CreateHunt failed: %v", err) } hunt, _ := repo.GetPendingHunt(charID) - repo.AcquireHunt(hunt.HuntID) + if err := repo.AcquireHunt(hunt.HuntID); err != nil { + t.Fatalf("AcquireHunt failed: %v", err) + } // Create a level-1 hunt (should not appear) if err := repo.CreateHunt(guildID, charID, 20, 1, nil, ""); err != nil { @@ -1240,7 +1258,9 @@ func TestRegisterHuntReport(t *testing.T) { } var treasureHunt *uint32 - db.QueryRow("SELECT treasure_hunt FROM guild_characters WHERE character_id=$1", charID).Scan(&treasureHunt) + if err := db.QueryRow("SELECT treasure_hunt FROM guild_characters WHERE character_id=$1", charID).Scan(&treasureHunt); err != nil { + t.Fatalf("Failed to get treasure_hunt: %v", err) + } if treasureHunt == nil || *treasureHunt != hunt.HuntID { t.Errorf("Expected treasure_hunt=%d, got %v", hunt.HuntID, treasureHunt) } @@ -1253,7 +1273,9 @@ func TestCollectHunt(t *testing.T) { t.Fatalf("CreateHunt failed: %v", err) } hunt, _ := repo.GetPendingHunt(charID) - repo.RegisterHuntReport(hunt.HuntID, charID) + if err := repo.RegisterHuntReport(hunt.HuntID, charID); err != nil { + t.Fatalf("RegisterHuntReport failed: %v", err) + } if err := repo.CollectHunt(hunt.HuntID); err != nil { t.Fatalf("CollectHunt failed: %v", err) @@ -1261,14 +1283,18 @@ func TestCollectHunt(t *testing.T) { // Hunt should be marked collected var collected bool - db.QueryRow("SELECT collected FROM guild_hunts WHERE id=$1", hunt.HuntID).Scan(&collected) + if err := db.QueryRow("SELECT collected FROM guild_hunts WHERE id=$1", hunt.HuntID).Scan(&collected); err != nil { + t.Fatalf("Failed to scan collected: %v", err) + } if !collected { t.Error("Expected collected=true") } // Character's treasure_hunt should be cleared var treasureHunt *uint32 - db.QueryRow("SELECT treasure_hunt FROM guild_characters WHERE character_id=$1", charID).Scan(&treasureHunt) + if err := db.QueryRow("SELECT treasure_hunt FROM guild_characters WHERE character_id=$1", charID).Scan(&treasureHunt); err != nil { + t.Fatalf("Failed to get treasure_hunt: %v", err) + } if treasureHunt != nil { t.Errorf("Expected treasure_hunt=NULL, got %v", *treasureHunt) } @@ -1287,7 +1313,9 @@ func TestClaimHuntReward(t *testing.T) { } var count int - db.QueryRow("SELECT COUNT(*) FROM guild_hunts_claimed WHERE hunt_id=$1 AND character_id=$2", hunt.HuntID, charID).Scan(&count) + if err := db.QueryRow("SELECT COUNT(*) FROM guild_hunts_claimed WHERE hunt_id=$1 AND character_id=$2", hunt.HuntID, charID).Scan(&count); err != nil { + t.Fatalf("Failed to scan claimed count: %v", err) + } if count != 1 { t.Errorf("Expected 1 claimed entry, got %d", count) } @@ -1365,7 +1393,9 @@ func TestClaimHuntBox(t *testing.T) { } var got time.Time - db.QueryRow("SELECT box_claimed FROM guild_characters WHERE character_id=$1", charID).Scan(&got) + if err := db.QueryRow("SELECT box_claimed FROM guild_characters WHERE character_id=$1", charID).Scan(&got); err != nil { + t.Fatalf("Failed to scan box_claimed: %v", err) + } if !got.Equal(claimedAt) { t.Errorf("Expected box_claimed=%v, got %v", claimedAt, got) } @@ -1376,11 +1406,17 @@ func TestListAndCountGuildKills(t *testing.T) { // Set box_claimed to the past so kills after it are visible past := time.Now().Add(-1 * time.Hour).UTC().Truncate(time.Second) - repo.ClaimHuntBox(charID, past) + if err := repo.ClaimHuntBox(charID, past); err != nil { + t.Fatalf("ClaimHuntBox failed: %v", err) + } // Insert kill logs for this character - db.Exec("INSERT INTO kill_logs (character_id, monster, quantity, timestamp) VALUES ($1, 100, 1, NOW())", charID) - db.Exec("INSERT INTO kill_logs (character_id, monster, quantity, timestamp) VALUES ($1, 200, 1, NOW())", charID) + if _, err := db.Exec("INSERT INTO kill_logs (character_id, monster, quantity, timestamp) VALUES ($1, 100, 1, NOW())", charID); err != nil { + t.Fatalf("Failed to insert kill log: %v", err) + } + if _, err := db.Exec("INSERT INTO kill_logs (character_id, monster, quantity, timestamp) VALUES ($1, 200, 1, NOW())", charID); err != nil { + t.Fatalf("Failed to insert kill log: %v", err) + } kills, err := repo.ListGuildKills(guildID, charID) if err != nil { @@ -1403,7 +1439,9 @@ func TestListGuildKillsEmpty(t *testing.T) { repo, _, guildID, charID := setupGuildRepo(t) // Set box_claimed to now — no kills after it - repo.ClaimHuntBox(charID, time.Now().UTC()) + if err := repo.ClaimHuntBox(charID, time.Now().UTC()); err != nil { + t.Fatalf("ClaimHuntBox failed: %v", err) + } kills, err := repo.ListGuildKills(guildID, charID) if err != nil { @@ -1433,7 +1471,9 @@ func TestDisbandCleansUpAlliance(t *testing.T) { } var allianceID uint32 - db.QueryRow("SELECT id FROM guild_alliances WHERE parent_id=$1", guildID).Scan(&allianceID) + if err := db.QueryRow("SELECT id FROM guild_alliances WHERE parent_id=$1", guildID).Scan(&allianceID); err != nil { + t.Fatalf("Failed to scan alliance ID: %v", err) + } if err := repo.Disband(guildID); err != nil { t.Fatalf("Disband failed: %v", err) diff --git a/server/channelserver/repo_house.go b/server/channelserver/repo_house.go index 6fc17c165..f976a71f5 100644 --- a/server/channelserver/repo_house.go +++ b/server/channelserver/repo_house.go @@ -46,7 +46,7 @@ func (r *HouseRepository) SearchHousesByName(name string) ([]HouseData, error) { if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var house HouseData if err := rows.StructScan(&house); err == nil { @@ -194,7 +194,7 @@ func (r *HouseRepository) GetTitles(charID uint32) ([]Title, error) { if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var title Title if err := rows.StructScan(&title); err == nil { diff --git a/server/channelserver/repo_mercenary.go b/server/channelserver/repo_mercenary.go index 6ecff1e4a..e844ae24a 100644 --- a/server/channelserver/repo_mercenary.go +++ b/server/channelserver/repo_mercenary.go @@ -44,7 +44,7 @@ func (r *MercenaryRepository) GetMercenaryLoans(charID uint32) ([]MercenaryLoan, if err != nil { return nil, fmt.Errorf("query mercenary loans: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() var result []MercenaryLoan for rows.Next() { var l MercenaryLoan @@ -69,7 +69,7 @@ func (r *MercenaryRepository) GetGuildHuntCatsUsed(charID uint32) ([]GuildHuntCa if err != nil { return nil, fmt.Errorf("query guild hunt cats: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() var result []GuildHuntCatUsage for rows.Next() { var u GuildHuntCatUsage @@ -90,7 +90,7 @@ func (r *MercenaryRepository) GetGuildAirou(guildID uint32) ([][]byte, error) { if err != nil { return nil, fmt.Errorf("query guild airou: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() var result [][]byte for rows.Next() { var data []byte diff --git a/server/channelserver/repo_misc.go b/server/channelserver/repo_misc.go index f12d61010..f99eaa536 100644 --- a/server/channelserver/repo_misc.go +++ b/server/channelserver/repo_misc.go @@ -22,7 +22,7 @@ func (r *MiscRepository) GetTrendWeapons(weaponType uint8) ([]uint16, error) { if err != nil { return nil, fmt.Errorf("query trend_weapons: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() var result []uint16 for rows.Next() { var id uint16 diff --git a/server/channelserver/repo_mocks_test.go b/server/channelserver/repo_mocks_test.go index f30f96cd2..e48597b2b 100644 --- a/server/channelserver/repo_mocks_test.go +++ b/server/channelserver/repo_mocks_test.go @@ -118,6 +118,13 @@ type mockCharacterRepo struct { adjustErr error readErr error saveErr error + + // LoadSaveData mock fields + loadSaveDataID uint32 + loadSaveDataData []byte + loadSaveDataNew bool + loadSaveDataName string + loadSaveDataErr error } func newMockCharacterRepo() *mockCharacterRepo { @@ -194,7 +201,9 @@ func (m *mockCharacterRepo) UpdateGCPAndPact(_ uint32, _ uint32, _ uint32) error 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 0, nil, false, "", nil } +func (m *mockCharacterRepo) LoadSaveData(_ uint32) (uint32, []byte, bool, string, error) { + return m.loadSaveDataID, m.loadSaveDataData, m.loadSaveDataNew, m.loadSaveDataName, m.loadSaveDataErr +} // --- mockGoocooRepo --- diff --git a/server/channelserver/repo_scenario.go b/server/channelserver/repo_scenario.go index 3caa0a22b..242e98f6d 100644 --- a/server/channelserver/repo_scenario.go +++ b/server/channelserver/repo_scenario.go @@ -22,7 +22,7 @@ func (r *ScenarioRepository) GetCounters() ([]Scenario, error) { if err != nil { return nil, fmt.Errorf("query scenario_counter: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() var result []Scenario for rows.Next() { var s Scenario diff --git a/server/channelserver/repo_tower.go b/server/channelserver/repo_tower.go index 2f5d0d2d9..f87e2cf58 100644 --- a/server/channelserver/repo_tower.go +++ b/server/channelserver/repo_tower.go @@ -124,7 +124,7 @@ func (r *TowerRepository) GetTenrouiraiMissionScores(guildID uint32, missionInde if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() var scores []TenrouiraiCharScore for rows.Next() { var cs TenrouiraiCharScore diff --git a/server/channelserver/testhelpers_db.go b/server/channelserver/testhelpers_db.go index 15f561db3..5bcbd1779 100644 --- a/server/channelserver/testhelpers_db.go +++ b/server/channelserver/testhelpers_db.go @@ -173,9 +173,7 @@ func applyUpdateSchema(t *testing.T, db *sqlx.DB, projectRoot string) { if stmt == "" { continue } - if _, err := db.Exec(stmt); err != nil { - // Silently ignore — these are expected for role mismatches, already-applied changes, etc. - } + _, _ = db.Exec(stmt) // Errors expected for role mismatches, already-applied changes, etc. } } @@ -260,7 +258,7 @@ func truncateAllTables(t *testing.T, db *sqlx.DB) { if err != nil { t.Fatalf("Failed to list tables for truncation: %v", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() var tables []string for rows.Next() {