mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
SaveColumn and SaveMercenary now check RowsAffected() and return a wrapped ErrCharacterNotFound when 0 rows are updated, preventing silent data loss when a character ID is missing or mismatched. AdjustInt already detects this via its RETURNING scan — no change. Daily mission packet structs (Get/SetDailyMission*) now parse the AckHandle instead of returning NOT IMPLEMENTED, letting handlers send empty-list success ACKs and avoiding client softlocks. Also adds tests for dashboard stats endpoint and for five guild repo methods (SetAllianceRecruiting, RolloverDailyRP, AddWeeklyBonusUsers, InsertKillLog, ClearTreasureHunt) that had no coverage.
228 lines
7.3 KiB
Go
228 lines
7.3 KiB
Go
package channelserver
|
|
|
|
// Tests for guild subsystem methods not covered by repo_guild_test.go:
|
|
// - SetAllianceRecruiting (repo_guild_alliance.go)
|
|
// - RolloverDailyRP (repo_guild_rp.go)
|
|
// - AddWeeklyBonusUsers (repo_guild_rp.go)
|
|
// - InsertKillLog (repo_guild_hunt.go)
|
|
// - ClearTreasureHunt (repo_guild_hunt.go)
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestSetAllianceRecruiting(t *testing.T) {
|
|
db := SetupTestDB(t)
|
|
defer TeardownTestDB(t, db)
|
|
|
|
userID := CreateTestUser(t, db, "sar_user")
|
|
charID := CreateTestCharacter(t, db, userID, "SAR_Leader")
|
|
guildID := CreateTestGuild(t, db, charID, "SAR_Guild")
|
|
repo := NewGuildRepository(db)
|
|
|
|
if err := repo.CreateAlliance("SAR_Alliance", guildID); err != nil {
|
|
t.Fatalf("CreateAlliance failed: %v", err)
|
|
}
|
|
alliances, err := repo.ListAlliances()
|
|
if err != nil {
|
|
t.Fatalf("ListAlliances failed: %v", err)
|
|
}
|
|
if len(alliances) == 0 {
|
|
t.Fatal("Expected at least 1 alliance")
|
|
}
|
|
allianceID := alliances[0].ID
|
|
|
|
// Default should be false.
|
|
if alliances[0].Recruiting {
|
|
t.Error("Expected initial Recruiting=false")
|
|
}
|
|
|
|
if err := repo.SetAllianceRecruiting(allianceID, true); err != nil {
|
|
t.Fatalf("SetAllianceRecruiting(true) failed: %v", err)
|
|
}
|
|
alliance, err := repo.GetAllianceByID(allianceID)
|
|
if err != nil {
|
|
t.Fatalf("GetAllianceByID after set true failed: %v", err)
|
|
}
|
|
if !alliance.Recruiting {
|
|
t.Error("Expected Recruiting=true after SetAllianceRecruiting(true)")
|
|
}
|
|
|
|
if err := repo.SetAllianceRecruiting(allianceID, false); err != nil {
|
|
t.Fatalf("SetAllianceRecruiting(false) failed: %v", err)
|
|
}
|
|
alliance, err = repo.GetAllianceByID(allianceID)
|
|
if err != nil {
|
|
t.Fatalf("GetAllianceByID after set false failed: %v", err)
|
|
}
|
|
if alliance.Recruiting {
|
|
t.Error("Expected Recruiting=false after SetAllianceRecruiting(false)")
|
|
}
|
|
}
|
|
|
|
func TestRolloverDailyRP(t *testing.T) {
|
|
db := SetupTestDB(t)
|
|
defer TeardownTestDB(t, db)
|
|
|
|
userID := CreateTestUser(t, db, "rollover_user")
|
|
charID := CreateTestCharacter(t, db, userID, "Rollover_Leader")
|
|
guildID := CreateTestGuild(t, db, charID, "Rollover_Guild")
|
|
repo := NewGuildRepository(db)
|
|
|
|
// Set rp_today for the member so we can verify the rollover.
|
|
if _, err := db.Exec("UPDATE guild_characters SET rp_today = 50 WHERE character_id = $1", charID); err != nil {
|
|
t.Fatalf("Failed to set rp_today: %v", err)
|
|
}
|
|
|
|
noon := time.Now().UTC()
|
|
if err := repo.RolloverDailyRP(guildID, noon); err != nil {
|
|
t.Fatalf("RolloverDailyRP failed: %v", err)
|
|
}
|
|
|
|
var rpToday, rpYesterday int
|
|
if err := db.QueryRow("SELECT rp_today, rp_yesterday FROM guild_characters WHERE character_id = $1", charID).
|
|
Scan(&rpToday, &rpYesterday); err != nil {
|
|
t.Fatalf("Failed to read rp values: %v", err)
|
|
}
|
|
if rpToday != 0 {
|
|
t.Errorf("Expected rp_today=0 after rollover, got %d", rpToday)
|
|
}
|
|
if rpYesterday != 50 {
|
|
t.Errorf("Expected rp_yesterday=50 after rollover, got %d", rpYesterday)
|
|
}
|
|
}
|
|
|
|
func TestRolloverDailyRP_Idempotent(t *testing.T) {
|
|
db := SetupTestDB(t)
|
|
defer TeardownTestDB(t, db)
|
|
|
|
userID := CreateTestUser(t, db, "idem_rollover_user")
|
|
charID := CreateTestCharacter(t, db, userID, "Idem_Rollover_Leader")
|
|
guildID := CreateTestGuild(t, db, charID, "Idem_Rollover_Guild")
|
|
repo := NewGuildRepository(db)
|
|
|
|
if _, err := db.Exec("UPDATE guild_characters SET rp_today = 100 WHERE character_id = $1", charID); err != nil {
|
|
t.Fatalf("Failed to set rp_today: %v", err)
|
|
}
|
|
|
|
noon := time.Now().UTC()
|
|
if err := repo.RolloverDailyRP(guildID, noon); err != nil {
|
|
t.Fatalf("First RolloverDailyRP failed: %v", err)
|
|
}
|
|
// Second call with same noon should be a no-op (rp_reset_at >= noon).
|
|
if err := repo.RolloverDailyRP(guildID, noon); err != nil {
|
|
t.Fatalf("Second RolloverDailyRP (idempotent) failed: %v", err)
|
|
}
|
|
|
|
var rpToday int
|
|
_ = db.QueryRow("SELECT rp_today FROM guild_characters WHERE character_id = $1", charID).Scan(&rpToday)
|
|
if rpToday != 0 {
|
|
t.Errorf("Expected rp_today=0 after idempotent rollover, got %d", rpToday)
|
|
}
|
|
}
|
|
|
|
func TestAddWeeklyBonusUsers(t *testing.T) {
|
|
db := SetupTestDB(t)
|
|
defer TeardownTestDB(t, db)
|
|
|
|
userID := CreateTestUser(t, db, "wbu_user")
|
|
charID := CreateTestCharacter(t, db, userID, "WBU_Leader")
|
|
guildID := CreateTestGuild(t, db, charID, "WBU_Guild")
|
|
repo := NewGuildRepository(db)
|
|
|
|
if err := repo.AddWeeklyBonusUsers(guildID, 3); err != nil {
|
|
t.Fatalf("AddWeeklyBonusUsers failed: %v", err)
|
|
}
|
|
|
|
// Verify the column incremented.
|
|
var wbu int
|
|
if err := db.QueryRow("SELECT weekly_bonus_users FROM guilds WHERE id = $1", guildID).Scan(&wbu); err != nil {
|
|
t.Fatalf("Failed to read weekly_bonus_users: %v", err)
|
|
}
|
|
if wbu != 3 {
|
|
t.Errorf("Expected weekly_bonus_users=3, got %d", wbu)
|
|
}
|
|
|
|
// Add again and verify accumulation.
|
|
if err := repo.AddWeeklyBonusUsers(guildID, 2); err != nil {
|
|
t.Fatalf("Second AddWeeklyBonusUsers failed: %v", err)
|
|
}
|
|
if err := db.QueryRow("SELECT weekly_bonus_users FROM guilds WHERE id = $1", guildID).Scan(&wbu); err != nil {
|
|
t.Fatalf("Failed to read weekly_bonus_users after second add: %v", err)
|
|
}
|
|
if wbu != 5 {
|
|
t.Errorf("Expected weekly_bonus_users=5 after second add, got %d", wbu)
|
|
}
|
|
}
|
|
|
|
func TestInsertKillLogAndCount(t *testing.T) {
|
|
db := SetupTestDB(t)
|
|
defer TeardownTestDB(t, db)
|
|
|
|
userID := CreateTestUser(t, db, "kill_log_user")
|
|
charID := CreateTestCharacter(t, db, userID, "Kill_Logger")
|
|
guildID := CreateTestGuild(t, db, charID, "Kill_Guild")
|
|
repo := NewGuildRepository(db)
|
|
|
|
// Set box_claimed to 1 hour ago so kills inserted now are within the window.
|
|
if _, err := db.Exec("UPDATE guild_characters SET box_claimed = now() - interval '1 hour' WHERE character_id = $1", charID); err != nil {
|
|
t.Fatalf("Failed to set box_claimed: %v", err)
|
|
}
|
|
|
|
if err := repo.InsertKillLog(charID, 42, 2, time.Now()); err != nil {
|
|
t.Fatalf("InsertKillLog failed: %v", err)
|
|
}
|
|
|
|
count, err := repo.CountGuildKills(guildID, charID)
|
|
if err != nil {
|
|
t.Fatalf("CountGuildKills failed: %v", err)
|
|
}
|
|
if count != 1 {
|
|
t.Errorf("Expected 1 kill log entry, got %d", count)
|
|
}
|
|
}
|
|
|
|
func TestClearTreasureHunt(t *testing.T) {
|
|
db := SetupTestDB(t)
|
|
defer TeardownTestDB(t, db)
|
|
|
|
userID := CreateTestUser(t, db, "cth_user")
|
|
charID := CreateTestCharacter(t, db, userID, "CTH_Leader")
|
|
guildID := CreateTestGuild(t, db, charID, "CTH_Guild")
|
|
repo := NewGuildRepository(db)
|
|
|
|
// Create and register a hunt.
|
|
if err := repo.CreateHunt(guildID, charID, 7, 1, []byte{}, ""); err != nil {
|
|
t.Fatalf("CreateHunt failed: %v", err)
|
|
}
|
|
hunt, err := repo.GetPendingHunt(charID)
|
|
if err != nil || hunt == nil {
|
|
t.Fatalf("GetPendingHunt failed or nil: %v", err)
|
|
}
|
|
if err := repo.RegisterHuntReport(hunt.HuntID, charID); err != nil {
|
|
t.Fatalf("RegisterHuntReport failed: %v", err)
|
|
}
|
|
|
|
// Verify treasure_hunt is set.
|
|
var th interface{}
|
|
if err := db.QueryRow("SELECT treasure_hunt FROM guild_characters WHERE character_id = $1", charID).Scan(&th); err != nil {
|
|
t.Fatalf("Failed to read treasure_hunt: %v", err)
|
|
}
|
|
if th == nil {
|
|
t.Error("Expected treasure_hunt to be set after RegisterHuntReport")
|
|
}
|
|
|
|
// Clear it.
|
|
if err := repo.ClearTreasureHunt(charID); err != nil {
|
|
t.Fatalf("ClearTreasureHunt failed: %v", err)
|
|
}
|
|
|
|
if err := db.QueryRow("SELECT treasure_hunt FROM guild_characters WHERE character_id = $1", charID).Scan(&th); err != nil {
|
|
t.Fatalf("Failed to read treasure_hunt after clear: %v", err)
|
|
}
|
|
if th != nil {
|
|
t.Errorf("Expected treasure_hunt=nil after ClearTreasureHunt, got %v", th)
|
|
}
|
|
}
|