From eb66de8ef9a71881cd4296178d51c4f8ccb1694d Mon Sep 17 00:00:00 2001 From: Houmgaor Date: Fri, 20 Feb 2026 23:55:02 +0100 Subject: [PATCH] fix(channelserver): correct 3 test bugs causing 10 deterministic failures - Use users.frontier_points instead of characters.frontier_points (column moved in 9.2 schema migration) across savedata and session lifecycle tests - Use BYTEA column (otomoairou) instead of INTEGER column (kouryou_point) in repo_character Load/SaveColumn tests - Build blocked CSV from actual auto-incremented character IDs instead of hardcoded IDs in ListMember integration test - Fix nil charRepo panic in CompleteSaveLoadCycle by using SetTestDB() --- server/channelserver/handlers_clients_test.go | 20 ++++++++--------- .../handlers_savedata_integration_test.go | 20 ++++++++--------- server/channelserver/repo_character_test.go | 10 ++++----- .../session_lifecycle_integration_test.go | 22 +++++++++---------- 4 files changed, 35 insertions(+), 37 deletions(-) diff --git a/server/channelserver/handlers_clients_test.go b/server/channelserver/handlers_clients_test.go index 85fd876d2..fd6be26c8 100644 --- a/server/channelserver/handlers_clients_test.go +++ b/server/channelserver/handlers_clients_test.go @@ -160,22 +160,18 @@ func TestHandleMsgMhfListMember_Integration(t *testing.T) { tests := []struct { name string - blockedCSV string wantBlockCount int }{ { name: "no_blocked_users", - blockedCSV: "", wantBlockCount: 0, }, { name: "single_blocked_user", - blockedCSV: "2", wantBlockCount: 1, }, { name: "multiple_blocked_users", - blockedCSV: "2,3,4", wantBlockCount: 3, }, } @@ -187,17 +183,19 @@ func TestHandleMsgMhfListMember_Integration(t *testing.T) { charName := fmt.Sprintf("Char%d", i) charID := CreateTestCharacter(t, db, userID, charName) - // Create blocked characters - if tt.blockedCSV != "" { - // Create the blocked users - for i := 2; i <= 4; i++ { - blockedUserID := CreateTestUser(t, db, "blocked_user_"+tt.name+"_"+string(rune(i))) - CreateTestCharacter(t, db, blockedUserID, "BlockedChar_"+string(rune(i))) + // Create blocked characters and build CSV from their actual IDs + blockedCSV := "" + for j := 0; j < tt.wantBlockCount; j++ { + blockedUserID := CreateTestUser(t, db, fmt.Sprintf("blk_%s_%d", tt.name, j)) + blockedCharID := CreateTestCharacter(t, db, blockedUserID, fmt.Sprintf("Blk%d_%d", i, j)) + if blockedCSV != "" { + blockedCSV += "," } + blockedCSV += fmt.Sprintf("%d", blockedCharID) } // Set blocked list - _, err := db.Exec("UPDATE characters SET blocked = $1 WHERE id = $2", tt.blockedCSV, charID) + _, err := db.Exec("UPDATE characters SET blocked = $1 WHERE id = $2", blockedCSV, charID) if err != nil { t.Fatalf("Failed to update blocked list: %v", err) } diff --git a/server/channelserver/handlers_savedata_integration_test.go b/server/channelserver/handlers_savedata_integration_test.go index d9589d33c..dfbc27f0b 100644 --- a/server/channelserver/handlers_savedata_integration_test.go +++ b/server/channelserver/handlers_savedata_integration_test.go @@ -28,25 +28,25 @@ func TestSaveLoad_RoadPoints(t *testing.T) { defer TeardownTestDB(t, db) userID := CreateTestUser(t, db, "testuser") - charID := CreateTestCharacter(t, db, userID, "TestChar") + _ = CreateTestCharacter(t, db, userID, "TestChar") - // Set initial Road Points + // Set initial Road Points (frontier_points is on the users table since 9.2 migration) initialPoints := uint32(1000) - _, err := db.Exec("UPDATE characters SET frontier_points = $1 WHERE id = $2", initialPoints, charID) + _, err := db.Exec("UPDATE users SET frontier_points = $1 WHERE id = $2", initialPoints, userID) if err != nil { t.Fatalf("Failed to set initial road points: %v", err) } // Modify Road Points newPoints := uint32(2500) - _, err = db.Exec("UPDATE characters SET frontier_points = $1 WHERE id = $2", newPoints, charID) + _, err = db.Exec("UPDATE users SET frontier_points = $1 WHERE id = $2", newPoints, userID) if err != nil { t.Fatalf("Failed to update road points: %v", err) } // Verify Road Points persisted var savedPoints uint32 - err = db.QueryRow("SELECT frontier_points FROM characters WHERE id = $1", charID).Scan(&savedPoints) + err = db.QueryRow("SELECT frontier_points FROM users WHERE id = $1", userID).Scan(&savedPoints) if err != nil { t.Fatalf("Failed to query road points: %v", err) } @@ -468,9 +468,9 @@ func TestSaveLoad_CompleteSaveLoadCycle(t *testing.T) { s.Name = "SaveLoadTest" SetTestDB(s.server, db) - // 1. Set Road Points + // 1. Set Road Points (frontier_points is on the users table since 9.2 migration) rdpPoints := uint32(5000) - _, err := db.Exec("UPDATE characters SET frontier_points = $1 WHERE id = $2", rdpPoints, charID) + _, err := db.Exec("UPDATE users SET frontier_points = $1 WHERE id = $2", rdpPoints, userID) if err != nil { t.Fatalf("Failed to set RdP: %v", err) } @@ -506,7 +506,7 @@ func TestSaveLoad_CompleteSaveLoadCycle(t *testing.T) { mock2 := &MockCryptConn{sentPackets: make([][]byte, 0)} s2 := createTestSession(mock2) s2.charID = charID - s2.server.db = db + SetTestDB(s2.server, db) s2.server.userBinaryParts = make(map[userBinaryPartID][]byte) // Load character data @@ -520,9 +520,9 @@ func TestSaveLoad_CompleteSaveLoadCycle(t *testing.T) { t.Errorf("Character name not loaded correctly: got %q, want %q", s2.Name, "SaveLoadTest") } - // Verify Road Points persisted + // Verify Road Points persisted (frontier_points is on users table) var loadedRdP uint32 - _ = db.QueryRow("SELECT frontier_points FROM characters WHERE id = $1", charID).Scan(&loadedRdP) + _ = db.QueryRow("SELECT frontier_points FROM users WHERE id = $1", userID).Scan(&loadedRdP) if loadedRdP != rdpPoints { t.Errorf("RdP not persisted: got %d, want %d (BUG CONFIRMED)", loadedRdP, rdpPoints) } else { diff --git a/server/channelserver/repo_character_test.go b/server/channelserver/repo_character_test.go index ed7024992..4fc579b2e 100644 --- a/server/channelserver/repo_character_test.go +++ b/server/channelserver/repo_character_test.go @@ -22,12 +22,12 @@ func TestLoadColumn(t *testing.T) { // Write a known blob to a column blob := []byte{0xDE, 0xAD, 0xBE, 0xEF} - _, err := db.Exec("UPDATE characters SET kouryou_point=$1 WHERE id=$2", blob, charID) + _, err := db.Exec("UPDATE characters SET otomoairou=$1 WHERE id=$2", blob, charID) if err != nil { t.Fatalf("Setup failed: %v", err) } - data, err := repo.LoadColumn(charID, "kouryou_point") + data, err := repo.LoadColumn(charID, "otomoairou") if err != nil { t.Fatalf("LoadColumn failed: %v", err) } @@ -40,7 +40,7 @@ func TestLoadColumnNil(t *testing.T) { repo, _, charID := setupCharRepo(t) // Column should be NULL by default - data, err := repo.LoadColumn(charID, "kouryou_point") + data, err := repo.LoadColumn(charID, "otomoairou") if err != nil { t.Fatalf("LoadColumn failed: %v", err) } @@ -53,13 +53,13 @@ func TestSaveColumn(t *testing.T) { repo, db, charID := setupCharRepo(t) blob := []byte{0x01, 0x02, 0x03} - if err := repo.SaveColumn(charID, "kouryou_point", blob); err != nil { + if err := repo.SaveColumn(charID, "otomoairou", blob); err != nil { t.Fatalf("SaveColumn failed: %v", err) } // Verify via direct SELECT var got []byte - if err := db.QueryRow("SELECT kouryou_point FROM characters WHERE id=$1", charID).Scan(&got); err != nil { + if err := db.QueryRow("SELECT otomoairou FROM characters WHERE id=$1", charID).Scan(&got); err != nil { t.Fatalf("Verification query failed: %v", err) } if len(got) != 3 || got[0] != 0x01 || got[2] != 0x03 { diff --git a/server/channelserver/session_lifecycle_integration_test.go b/server/channelserver/session_lifecycle_integration_test.go index f276710f3..275a9da2e 100644 --- a/server/channelserver/session_lifecycle_integration_test.go +++ b/server/channelserver/session_lifecycle_integration_test.go @@ -52,9 +52,9 @@ func TestSessionLifecycle_BasicSaveLoadCycle(t *testing.T) { session1 := createTestSessionForServerWithChar(server, charID, "LifecycleChar") // Note: Not calling Start() since we're testing handlers directly, not packet processing - // Modify data via packet handlers + // Modify data via packet handlers (frontier_points is on users table since 9.2 migration) initialPoints := uint32(5000) - _, err := db.Exec("UPDATE characters SET frontier_points = $1 WHERE id = $2", initialPoints, charID) + _, err := db.Exec("UPDATE users SET frontier_points = $1 WHERE id = $2", initialPoints, userID) if err != nil { t.Fatalf("Failed to set initial road points: %v", err) } @@ -292,9 +292,9 @@ func TestSessionLifecycle_MultipleDataTypesPersistence(t *testing.T) { // ===== SESSION 1: Modify multiple data types ===== session1 := createTestSessionForServerWithChar(server, charID, "MultiChar") - // 1. Set Road Points + // 1. Set Road Points (frontier_points is on users table since 9.2 migration) rdpPoints := uint32(7500) - _, err := db.Exec("UPDATE characters SET frontier_points = $1 WHERE id = $2", rdpPoints, charID) + _, err := db.Exec("UPDATE users SET frontier_points = $1 WHERE id = $2", rdpPoints, userID) if err != nil { t.Fatalf("Failed to set RdP: %v", err) } @@ -362,9 +362,9 @@ func TestSessionLifecycle_MultipleDataTypesPersistence(t *testing.T) { allPassed := true - // Verify 1: Road Points + // Verify 1: Road Points (frontier_points is on users table) var loadedRdP uint32 - _ = db.QueryRow("SELECT frontier_points FROM characters WHERE id = $1", charID).Scan(&loadedRdP) + _ = db.QueryRow("SELECT frontier_points FROM users WHERE id = $1", userID).Scan(&loadedRdP) if loadedRdP != rdpPoints { t.Errorf("❌ RdP not persisted: got %d, want %d", loadedRdP, rdpPoints) allPassed = false @@ -446,9 +446,9 @@ func TestSessionLifecycle_DisconnectWithoutLogout(t *testing.T) { // ===== SESSION 1: Modify data then disconnect without explicit logout ===== session1 := createTestSessionForServerWithChar(server, charID, "DisconnectChar") - // Modify data + // Modify data (frontier_points is on users table since 9.2 migration) rdpPoints := uint32(9999) - _, err := db.Exec("UPDATE characters SET frontier_points = $1 WHERE id = $2", rdpPoints, charID) + _, err := db.Exec("UPDATE users SET frontier_points = $1 WHERE id = $2", rdpPoints, userID) if err != nil { t.Fatalf("Failed to set RdP: %v", err) } @@ -535,9 +535,9 @@ func TestSessionLifecycle_RapidReconnect(t *testing.T) { session := createTestSessionForServerWithChar(server, charID, "RapidChar") - // Modify road points each cycle + // Modify road points each cycle (frontier_points is on users table since 9.2 migration) points := uint32(1000 * cycle) - _, err := db.Exec("UPDATE characters SET frontier_points = $1 WHERE id = $2", points, charID) + _, err := db.Exec("UPDATE users SET frontier_points = $1 WHERE id = $2", points, userID) if err != nil { t.Fatalf("Cycle %d: Failed to update points: %v", cycle, err) } @@ -548,7 +548,7 @@ func TestSessionLifecycle_RapidReconnect(t *testing.T) { // Verify points persisted var loadedPoints uint32 - _ = db.QueryRow("SELECT frontier_points FROM characters WHERE id = $1", charID).Scan(&loadedPoints) + _ = db.QueryRow("SELECT frontier_points FROM users WHERE id = $1", userID).Scan(&loadedPoints) if loadedPoints != points { t.Errorf("❌ Cycle %d: Points not persisted: got %d, want %d", cycle, loadedPoints, points) } else {