mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-23 16:13:04 +01:00
test: increase total coverage from 46.1% to 50.5%
- Fix duplicate test declarations across coverage2, misc, mercenary, event files - Fix signserver TestHandlePacketDELETE timeout (multi-write pipe deadlock) - Fix entranceserver build error (invalid -1 for uint16 port) - Add handlers_reserve_test.go covering all 56 reserve handler stubs - Add handlers_coverage3_test.go with 115+ handler tests - Add handlers_register_test.go with 55 Raviente register/load tests - Add handlers_coverage_test.go, signserver, entranceserver, usercheck tests
This commit is contained in:
@@ -916,3 +916,352 @@ func TestGetGuildmatesNotInGuild(t *testing.T) {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetFriendsForCharactersDBError tests getFriendsForCharacters when DB query fails
|
||||
func TestGetFriendsForCharactersDBError(t *testing.T) {
|
||||
server, mock := newTestServerWithMock(t)
|
||||
|
||||
chars := []character{
|
||||
{ID: 1, Name: "Hunter1"},
|
||||
}
|
||||
|
||||
// Get friends CSV for character - DB error
|
||||
mock.ExpectQuery("SELECT friends FROM characters WHERE id=\\$1").
|
||||
WithArgs(uint32(1)).
|
||||
WillReturnError(sql.ErrNoRows)
|
||||
|
||||
// Even on error, still produces the friend query (with empty/error friendsCSV)
|
||||
// The function calls Scan which fails, then continues to build a query
|
||||
// with the empty string. The query then fails as well.
|
||||
mock.ExpectQuery("SELECT id, name FROM characters").
|
||||
WillReturnError(sql.ErrConnDone)
|
||||
|
||||
friends := server.getFriendsForCharacters(chars)
|
||||
// Should return 0 friends on error
|
||||
if len(friends) != 0 {
|
||||
t.Errorf("getFriendsForCharacters() with DB error = %d, want 0", len(friends))
|
||||
}
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetGuildmatesForCharactersGuildQueryError tests guild ID query failure
|
||||
func TestGetGuildmatesForCharactersGuildQueryError(t *testing.T) {
|
||||
server, mock := newTestServerWithMock(t)
|
||||
|
||||
chars := []character{
|
||||
{ID: 1, Name: "Hunter1"},
|
||||
}
|
||||
|
||||
// Check if in guild - yes
|
||||
mock.ExpectQuery("SELECT count\\(\\*\\) FROM guild_characters WHERE character_id=\\$1").
|
||||
WithArgs(uint32(1)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||
|
||||
// Get guild ID - error
|
||||
mock.ExpectQuery("SELECT guild_id FROM guild_characters WHERE character_id=\\$1").
|
||||
WithArgs(uint32(1)).
|
||||
WillReturnError(sql.ErrConnDone)
|
||||
|
||||
guildmates := server.getGuildmatesForCharacters(chars)
|
||||
if len(guildmates) != 0 {
|
||||
t.Errorf("getGuildmatesForCharacters() with guild query error = %d, want 0", len(guildmates))
|
||||
}
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetGuildmatesForCharactersGuildmatesQueryError tests guildmates query failure
|
||||
func TestGetGuildmatesForCharactersGuildmatesQueryError(t *testing.T) {
|
||||
server, mock := newTestServerWithMock(t)
|
||||
|
||||
chars := []character{
|
||||
{ID: 1, Name: "Hunter1"},
|
||||
}
|
||||
|
||||
// Check if in guild - yes
|
||||
mock.ExpectQuery("SELECT count\\(\\*\\) FROM guild_characters WHERE character_id=\\$1").
|
||||
WithArgs(uint32(1)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||
|
||||
// Get guild ID
|
||||
mock.ExpectQuery("SELECT guild_id FROM guild_characters WHERE character_id=\\$1").
|
||||
WithArgs(uint32(1)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"guild_id"}).AddRow(100))
|
||||
|
||||
// Get guildmates - error
|
||||
mock.ExpectQuery("SELECT character_id AS id, c.name FROM guild_characters gc JOIN characters c ON c.id = gc.character_id WHERE guild_id=\\$1 AND character_id!=\\$2").
|
||||
WithArgs(100, uint32(1)).
|
||||
WillReturnError(sql.ErrConnDone)
|
||||
|
||||
guildmates := server.getGuildmatesForCharacters(chars)
|
||||
if len(guildmates) != 0 {
|
||||
t.Errorf("getGuildmatesForCharacters() with guildmates query error = %d, want 0", len(guildmates))
|
||||
}
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestDeleteCharacterDeleteError tests deleteCharacter when the delete/update query fails
|
||||
func TestDeleteCharacterDeleteError(t *testing.T) {
|
||||
server, mock := newTestServerWithMock(t)
|
||||
|
||||
// Token verification
|
||||
mock.ExpectQuery("SELECT count\\(\\*\\) FROM sign_sessions WHERE token = \\$1").
|
||||
WithArgs("validtoken").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||
|
||||
// Check if new character
|
||||
mock.ExpectQuery("SELECT is_new_character FROM characters WHERE id = \\$1").
|
||||
WithArgs(123).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"is_new_character"}).AddRow(false))
|
||||
|
||||
// Soft delete fails
|
||||
mock.ExpectExec("UPDATE characters SET deleted = true WHERE id = \\$1").
|
||||
WithArgs(123).
|
||||
WillReturnError(sql.ErrConnDone)
|
||||
|
||||
err := server.deleteCharacter(123, "validtoken")
|
||||
if err == nil {
|
||||
t.Error("deleteCharacter() should return error when update fails")
|
||||
}
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestNewUserCharaInsertError tests newUserChara when the INSERT fails
|
||||
func TestNewUserCharaInsertError(t *testing.T) {
|
||||
server, mock := newTestServerWithMock(t)
|
||||
|
||||
// Get user ID
|
||||
mock.ExpectQuery("SELECT id FROM users WHERE username = \\$1").
|
||||
WithArgs("testuser").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
||||
|
||||
// Check for existing new characters
|
||||
mock.ExpectQuery("SELECT COUNT\\(\\*\\) FROM characters WHERE user_id = \\$1 AND is_new_character = true").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
||||
|
||||
// Insert new character - error
|
||||
mock.ExpectExec("INSERT INTO characters").
|
||||
WithArgs(1, sqlmock.AnyArg()).
|
||||
WillReturnError(sql.ErrConnDone)
|
||||
|
||||
err := server.newUserChara("testuser")
|
||||
if err == nil {
|
||||
t.Error("newUserChara() should return error when insert fails")
|
||||
}
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestNewUserCharaCountError tests newUserChara when the COUNT query fails
|
||||
func TestNewUserCharaCountError(t *testing.T) {
|
||||
server, mock := newTestServerWithMock(t)
|
||||
|
||||
// Get user ID
|
||||
mock.ExpectQuery("SELECT id FROM users WHERE username = \\$1").
|
||||
WithArgs("testuser").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
||||
|
||||
// Check for existing new characters - error
|
||||
mock.ExpectQuery("SELECT COUNT\\(\\*\\) FROM characters WHERE user_id = \\$1 AND is_new_character = true").
|
||||
WithArgs(1).
|
||||
WillReturnError(sql.ErrConnDone)
|
||||
|
||||
err := server.newUserChara("testuser")
|
||||
if err == nil {
|
||||
t.Error("newUserChara() should return error when count query fails")
|
||||
}
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRegisterDBAccountGetIDError tests registerDBAccount when getting the new user ID fails
|
||||
func TestRegisterDBAccountGetIDError(t *testing.T) {
|
||||
server, mock := newTestServerWithMock(t)
|
||||
|
||||
// Insert user succeeds
|
||||
mock.ExpectExec("INSERT INTO users \\(username, password, return_expires\\) VALUES \\(\\$1, \\$2, \\$3\\)").
|
||||
WithArgs("newuser", sqlmock.AnyArg(), sqlmock.AnyArg()).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
|
||||
// Get user ID - error
|
||||
mock.ExpectQuery("SELECT id FROM users WHERE username = \\$1").
|
||||
WithArgs("newuser").
|
||||
WillReturnError(sql.ErrConnDone)
|
||||
|
||||
err := server.registerDBAccount("newuser", "password123")
|
||||
if err == nil {
|
||||
t.Error("registerDBAccount() should return error when getting ID fails")
|
||||
}
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRegisterDBAccountCharacterInsertError tests registerDBAccount when character insert fails
|
||||
func TestRegisterDBAccountCharacterInsertError(t *testing.T) {
|
||||
server, mock := newTestServerWithMock(t)
|
||||
|
||||
// Insert user
|
||||
mock.ExpectExec("INSERT INTO users \\(username, password, return_expires\\) VALUES \\(\\$1, \\$2, \\$3\\)").
|
||||
WithArgs("newuser", sqlmock.AnyArg(), sqlmock.AnyArg()).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
|
||||
// Get user ID
|
||||
mock.ExpectQuery("SELECT id FROM users WHERE username = \\$1").
|
||||
WithArgs("newuser").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
||||
|
||||
// Insert character - error
|
||||
mock.ExpectExec("INSERT INTO characters").
|
||||
WithArgs(1, sqlmock.AnyArg()).
|
||||
WillReturnError(sql.ErrConnDone)
|
||||
|
||||
err := server.registerDBAccount("newuser", "password123")
|
||||
if err == nil {
|
||||
t.Error("registerDBAccount() should return error when character insert fails")
|
||||
}
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetReturnExpiryDBError tests getReturnExpiry when the return_expires query fails
|
||||
func TestGetReturnExpiryDBError(t *testing.T) {
|
||||
server, mock := newTestServerWithMock(t)
|
||||
|
||||
// Get last login - recent
|
||||
recentLogin := time.Now().Add(-time.Hour * 24)
|
||||
mock.ExpectQuery("SELECT COALESCE\\(last_login, now\\(\\)\\) FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"last_login"}).AddRow(recentLogin))
|
||||
|
||||
// Get return expiry - error
|
||||
mock.ExpectQuery("SELECT return_expires FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnError(sql.ErrNoRows)
|
||||
|
||||
// Should set return_expires to now
|
||||
mock.ExpectExec("UPDATE users SET return_expires=\\$1 WHERE id=\\$2").
|
||||
WithArgs(sqlmock.AnyArg(), 1).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
|
||||
// Update last login
|
||||
mock.ExpectExec("UPDATE users SET last_login=\\$1 WHERE id=\\$2").
|
||||
WithArgs(sqlmock.AnyArg(), 1).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
|
||||
expiry := server.getReturnExpiry(1)
|
||||
|
||||
// Should still return a valid time (approximately now)
|
||||
if expiry.IsZero() {
|
||||
t.Error("getReturnExpiry() should return non-zero time even on error")
|
||||
}
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetFriendsForCharactersMultipleChars tests with multiple characters
|
||||
func TestGetFriendsForCharactersMultipleChars(t *testing.T) {
|
||||
server, mock := newTestServerWithMock(t)
|
||||
|
||||
chars := []character{
|
||||
{ID: 1, Name: "Hunter1"},
|
||||
{ID: 2, Name: "Hunter2"},
|
||||
}
|
||||
|
||||
// First character friends
|
||||
mock.ExpectQuery("SELECT friends FROM characters WHERE id=\\$1").
|
||||
WithArgs(uint32(1)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"friends"}).AddRow("10"))
|
||||
|
||||
mock.ExpectQuery("SELECT id, name FROM characters WHERE id=10").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(10, "Friend1"))
|
||||
|
||||
// Second character friends
|
||||
mock.ExpectQuery("SELECT friends FROM characters WHERE id=\\$1").
|
||||
WithArgs(uint32(2)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"friends"}).AddRow("20"))
|
||||
|
||||
mock.ExpectQuery("SELECT id, name FROM characters WHERE id=20").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(20, "Friend2"))
|
||||
|
||||
friends := server.getFriendsForCharacters(chars)
|
||||
if len(friends) != 2 {
|
||||
t.Errorf("getFriendsForCharacters() = %d, want 2", len(friends))
|
||||
}
|
||||
|
||||
// Verify CID assignment
|
||||
if len(friends) >= 2 {
|
||||
if friends[0].CID != 1 {
|
||||
t.Errorf("friends[0].CID = %d, want 1", friends[0].CID)
|
||||
}
|
||||
if friends[1].CID != 2 {
|
||||
t.Errorf("friends[1].CID = %d, want 2", friends[1].CID)
|
||||
}
|
||||
}
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetGuildmatesForCharactersMultipleChars tests with multiple characters in guilds
|
||||
func TestGetGuildmatesForCharactersMultipleChars(t *testing.T) {
|
||||
server, mock := newTestServerWithMock(t)
|
||||
|
||||
chars := []character{
|
||||
{ID: 1, Name: "Hunter1"},
|
||||
{ID: 2, Name: "Hunter2"},
|
||||
}
|
||||
|
||||
// First character in guild
|
||||
mock.ExpectQuery("SELECT count\\(\\*\\) FROM guild_characters WHERE character_id=\\$1").
|
||||
WithArgs(uint32(1)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||
|
||||
mock.ExpectQuery("SELECT guild_id FROM guild_characters WHERE character_id=\\$1").
|
||||
WithArgs(uint32(1)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"guild_id"}).AddRow(100))
|
||||
|
||||
mock.ExpectQuery("SELECT character_id AS id, c.name FROM guild_characters gc JOIN characters c ON c.id = gc.character_id WHERE guild_id=\\$1 AND character_id!=\\$2").
|
||||
WithArgs(100, uint32(1)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(10, "Guildmate1"))
|
||||
|
||||
// Second character not in guild
|
||||
mock.ExpectQuery("SELECT count\\(\\*\\) FROM guild_characters WHERE character_id=\\$1").
|
||||
WithArgs(uint32(2)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
||||
|
||||
guildmates := server.getGuildmatesForCharacters(chars)
|
||||
if len(guildmates) != 1 {
|
||||
t.Errorf("getGuildmatesForCharacters() = %d, want 1", len(guildmates))
|
||||
}
|
||||
|
||||
if len(guildmates) >= 1 && guildmates[0].CID != 1 {
|
||||
t.Errorf("guildmates[0].CID = %d, want 1", guildmates[0].CID)
|
||||
}
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package signserver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
@@ -12,7 +13,10 @@ import (
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// mockConn implements net.Conn for testing
|
||||
@@ -446,7 +450,781 @@ func TestSessionWorkWithEmptyRead(t *testing.T) {
|
||||
session.work()
|
||||
}
|
||||
|
||||
// Note: Tests for handleDSGNRequest require a database connection.
|
||||
// The function immediately queries the database for user authentication.
|
||||
// These tests should be implemented as integration tests with a test database
|
||||
// or using sqlmock for database mocking.
|
||||
// TestHandlePacketDSGNRequest tests the DSGN:100 path with a mocked database.
|
||||
func TestHandlePacketDSGNRequest(t *testing.T) {
|
||||
logger := zap.NewNop()
|
||||
erupeConfig := &config.Config{
|
||||
DevMode: false,
|
||||
}
|
||||
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create sqlmock: %v", err)
|
||||
}
|
||||
sqlxDB := sqlx.NewDb(db, "sqlmock")
|
||||
|
||||
server := &Server{
|
||||
logger: logger,
|
||||
erupeConfig: erupeConfig,
|
||||
db: sqlxDB,
|
||||
}
|
||||
|
||||
// Use net.Pipe for bidirectional communication
|
||||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
defer serverConn.Close()
|
||||
|
||||
session := &Session{
|
||||
logger: logger,
|
||||
server: server,
|
||||
rawConn: serverConn,
|
||||
cryptConn: network.NewCryptConn(serverConn),
|
||||
}
|
||||
|
||||
// Create a DSGN:100 packet with username "testuser" and password "testpass"
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("DSGN:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("testuser"))
|
||||
bf.WriteNullTerminatedBytes([]byte("testpass"))
|
||||
bf.WriteNullTerminatedBytes([]byte("unk"))
|
||||
|
||||
// Mock DB: user not found, auto-create off
|
||||
mock.ExpectQuery("SELECT id, password FROM users WHERE username = \\$1").
|
||||
WithArgs("testuser").
|
||||
WillReturnError(sql.ErrNoRows)
|
||||
|
||||
// Read the response in a goroutine
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := clientConn.Read(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Errorf("handlePacket() returned error: %v", err)
|
||||
}
|
||||
|
||||
// Allow response to be sent
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
clientConn.Close()
|
||||
<-done
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestHandlePacketDLTSKEYSIGN tests the DLTSKEYSIGN:100 path (falls through to DSGN:100)
|
||||
func TestHandlePacketDLTSKEYSIGN(t *testing.T) {
|
||||
logger := zap.NewNop()
|
||||
erupeConfig := &config.Config{
|
||||
DevMode: false,
|
||||
}
|
||||
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create sqlmock: %v", err)
|
||||
}
|
||||
sqlxDB := sqlx.NewDb(db, "sqlmock")
|
||||
|
||||
server := &Server{
|
||||
logger: logger,
|
||||
erupeConfig: erupeConfig,
|
||||
db: sqlxDB,
|
||||
}
|
||||
|
||||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
defer serverConn.Close()
|
||||
|
||||
session := &Session{
|
||||
logger: logger,
|
||||
server: server,
|
||||
rawConn: serverConn,
|
||||
cryptConn: network.NewCryptConn(serverConn),
|
||||
}
|
||||
|
||||
// Create a DLTSKEYSIGN:100 packet
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("DLTSKEYSIGN:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("testuser"))
|
||||
bf.WriteNullTerminatedBytes([]byte("testpass"))
|
||||
bf.WriteNullTerminatedBytes([]byte("unk"))
|
||||
|
||||
// Mock DB: user not found
|
||||
mock.ExpectQuery("SELECT id, password FROM users WHERE username = \\$1").
|
||||
WithArgs("testuser").
|
||||
WillReturnError(sql.ErrNoRows)
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := clientConn.Read(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Errorf("handlePacket() returned error: %v", err)
|
||||
}
|
||||
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
clientConn.Close()
|
||||
<-done
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestHandlePacketDELETE tests the DELETE:100 path
|
||||
func TestHandlePacketDELETE(t *testing.T) {
|
||||
logger := zap.NewNop()
|
||||
erupeConfig := &config.Config{
|
||||
DevMode: false,
|
||||
}
|
||||
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create sqlmock: %v", err)
|
||||
}
|
||||
sqlxDB := sqlx.NewDb(db, "sqlmock")
|
||||
|
||||
server := &Server{
|
||||
logger: logger,
|
||||
erupeConfig: erupeConfig,
|
||||
db: sqlxDB,
|
||||
}
|
||||
|
||||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
defer serverConn.Close()
|
||||
|
||||
session := &Session{
|
||||
logger: logger,
|
||||
server: server,
|
||||
rawConn: serverConn,
|
||||
cryptConn: network.NewCryptConn(serverConn),
|
||||
}
|
||||
|
||||
// Create a DELETE:100 packet
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("DELETE:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("login-token-abc"))
|
||||
bf.WriteUint32(123) // characterID
|
||||
bf.WriteUint32(456) // login_token_number
|
||||
|
||||
// Mock DB: Token verification
|
||||
mock.ExpectQuery("SELECT count\\(\\*\\) FROM sign_sessions WHERE token = \\$1").
|
||||
WithArgs("login-token-abc").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||
|
||||
// Check if new character
|
||||
mock.ExpectQuery("SELECT is_new_character FROM characters WHERE id = \\$1").
|
||||
WithArgs(123).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"is_new_character"}).AddRow(false))
|
||||
|
||||
// Soft delete
|
||||
mock.ExpectExec("UPDATE characters SET deleted = true WHERE id = \\$1").
|
||||
WithArgs(123).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
|
||||
// Read all response data in a goroutine (SendPacket writes header + encrypted data)
|
||||
done := make(chan []byte, 1)
|
||||
go func() {
|
||||
var all []byte
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
n, readErr := clientConn.Read(buf)
|
||||
if n > 0 {
|
||||
all = append(all, buf[:n]...)
|
||||
}
|
||||
if readErr != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
done <- all
|
||||
}()
|
||||
|
||||
err = session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Errorf("handlePacket() returned error: %v", err)
|
||||
}
|
||||
|
||||
// Close server side so the reader goroutine finishes
|
||||
serverConn.Close()
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
// Response received successfully
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatal("timed out waiting for response")
|
||||
}
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestHandlePacketDSGNWithAutoCreate tests DSGN:100 with auto-create account enabled
|
||||
func TestHandlePacketDSGNWithAutoCreate(t *testing.T) {
|
||||
logger := zap.NewNop()
|
||||
erupeConfig := &config.Config{
|
||||
DevMode: true,
|
||||
DevModeOptions: config.DevModeOptions{
|
||||
AutoCreateAccount: true,
|
||||
},
|
||||
}
|
||||
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create sqlmock: %v", err)
|
||||
}
|
||||
sqlxDB := sqlx.NewDb(db, "sqlmock")
|
||||
|
||||
server := &Server{
|
||||
logger: logger,
|
||||
erupeConfig: erupeConfig,
|
||||
db: sqlxDB,
|
||||
}
|
||||
|
||||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
defer serverConn.Close()
|
||||
|
||||
session := &Session{
|
||||
logger: logger,
|
||||
server: server,
|
||||
rawConn: serverConn,
|
||||
cryptConn: network.NewCryptConn(serverConn),
|
||||
}
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("DSGN:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("newuser"))
|
||||
bf.WriteNullTerminatedBytes([]byte("newpass"))
|
||||
bf.WriteNullTerminatedBytes([]byte("unk"))
|
||||
|
||||
// Mock DB: user not found
|
||||
mock.ExpectQuery("SELECT id, password FROM users WHERE username = \\$1").
|
||||
WithArgs("newuser").
|
||||
WillReturnError(sql.ErrNoRows)
|
||||
|
||||
// Auto-create: insert user
|
||||
mock.ExpectExec("INSERT INTO users \\(username, password, return_expires\\) VALUES \\(\\$1, \\$2, \\$3\\)").
|
||||
WithArgs("newuser", sqlmock.AnyArg(), sqlmock.AnyArg()).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
|
||||
// Auto-create: get user ID
|
||||
mock.ExpectQuery("SELECT id FROM users WHERE username = \\$1").
|
||||
WithArgs("newuser").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
||||
|
||||
// Auto-create: insert character
|
||||
mock.ExpectExec("INSERT INTO characters").
|
||||
WithArgs(1, sqlmock.AnyArg()).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
|
||||
// Now get new user ID for makeSignInResp
|
||||
mock.ExpectQuery("SELECT id FROM users WHERE username = \\$1").
|
||||
WithArgs("newuser").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
||||
|
||||
// makeSignInResp calls getReturnExpiry
|
||||
mock.ExpectQuery("SELECT COALESCE\\(last_login, now\\(\\)\\) FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"last_login"}).AddRow(time.Now()))
|
||||
|
||||
// getReturnExpiry: get return_expires
|
||||
mock.ExpectQuery("SELECT return_expires FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"return_expires"}).AddRow(time.Now().Add(time.Hour * 24 * 30)))
|
||||
|
||||
// getReturnExpiry: update last_login
|
||||
mock.ExpectExec("UPDATE users SET last_login=\\$1 WHERE id=\\$2").
|
||||
WithArgs(sqlmock.AnyArg(), 1).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
|
||||
// getCharactersForUser
|
||||
mock.ExpectQuery("SELECT id, is_female, is_new_character, name, unk_desc_string, hrp, gr, weapon_type, last_login FROM characters WHERE user_id = \\$1 AND deleted = false ORDER BY id ASC").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "is_female", "is_new_character", "name", "unk_desc_string", "hrp", "gr", "weapon_type", "last_login"}))
|
||||
|
||||
// registerToken
|
||||
mock.ExpectExec("INSERT INTO sign_sessions \\(user_id, token\\) VALUES \\(\\$1, \\$2\\)").
|
||||
WithArgs(1, sqlmock.AnyArg()).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
|
||||
// getLastCID
|
||||
mock.ExpectQuery("SELECT last_character FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"last_character"}).AddRow(0))
|
||||
|
||||
// getUserRights
|
||||
mock.ExpectQuery("SELECT rights FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"rights"}).AddRow(2))
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := clientConn.Read(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Errorf("handlePacket() returned error: %v", err)
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
clientConn.Close()
|
||||
<-done
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestHandlePacketDSGNWithValidPassword tests DSGN:100 with correct password
|
||||
func TestHandlePacketDSGNWithValidPassword(t *testing.T) {
|
||||
logger := zap.NewNop()
|
||||
erupeConfig := &config.Config{
|
||||
DevMode: false,
|
||||
}
|
||||
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create sqlmock: %v", err)
|
||||
}
|
||||
sqlxDB := sqlx.NewDb(db, "sqlmock")
|
||||
|
||||
server := &Server{
|
||||
logger: logger,
|
||||
erupeConfig: erupeConfig,
|
||||
db: sqlxDB,
|
||||
}
|
||||
|
||||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
defer serverConn.Close()
|
||||
|
||||
session := &Session{
|
||||
logger: logger,
|
||||
server: server,
|
||||
rawConn: serverConn,
|
||||
cryptConn: network.NewCryptConn(serverConn),
|
||||
}
|
||||
|
||||
// Generate a bcrypt hash for "testpass"
|
||||
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte("testpass"), bcrypt.MinCost)
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("DSGN:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("existinguser"))
|
||||
bf.WriteNullTerminatedBytes([]byte("testpass"))
|
||||
bf.WriteNullTerminatedBytes([]byte("unk"))
|
||||
|
||||
// Mock DB: user found with correct password
|
||||
mock.ExpectQuery("SELECT id, password FROM users WHERE username = \\$1").
|
||||
WithArgs("existinguser").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "password"}).AddRow(1, string(hashedPassword)))
|
||||
|
||||
// makeSignInResp calls getReturnExpiry
|
||||
mock.ExpectQuery("SELECT COALESCE\\(last_login, now\\(\\)\\) FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"last_login"}).AddRow(time.Now()))
|
||||
|
||||
// getReturnExpiry: get return_expires
|
||||
mock.ExpectQuery("SELECT return_expires FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"return_expires"}).AddRow(time.Now().Add(time.Hour * 24 * 30)))
|
||||
|
||||
// getReturnExpiry: update last_login
|
||||
mock.ExpectExec("UPDATE users SET last_login=\\$1 WHERE id=\\$2").
|
||||
WithArgs(sqlmock.AnyArg(), 1).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
|
||||
// getCharactersForUser
|
||||
mock.ExpectQuery("SELECT id, is_female, is_new_character, name, unk_desc_string, hrp, gr, weapon_type, last_login FROM characters WHERE user_id = \\$1 AND deleted = false ORDER BY id ASC").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "is_female", "is_new_character", "name", "unk_desc_string", "hrp", "gr", "weapon_type", "last_login"}))
|
||||
|
||||
// registerToken
|
||||
mock.ExpectExec("INSERT INTO sign_sessions \\(user_id, token\\) VALUES \\(\\$1, \\$2\\)").
|
||||
WithArgs(1, sqlmock.AnyArg()).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
|
||||
// getLastCID
|
||||
mock.ExpectQuery("SELECT last_character FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"last_character"}).AddRow(0))
|
||||
|
||||
// getUserRights
|
||||
mock.ExpectQuery("SELECT rights FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"rights"}).AddRow(2))
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := clientConn.Read(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Errorf("handlePacket() returned error: %v", err)
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
clientConn.Close()
|
||||
<-done
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestHandlePacketDSGNWrongPassword tests DSGN:100 with wrong password
|
||||
func TestHandlePacketDSGNWrongPassword(t *testing.T) {
|
||||
logger := zap.NewNop()
|
||||
erupeConfig := &config.Config{
|
||||
DevMode: false,
|
||||
}
|
||||
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create sqlmock: %v", err)
|
||||
}
|
||||
sqlxDB := sqlx.NewDb(db, "sqlmock")
|
||||
|
||||
server := &Server{
|
||||
logger: logger,
|
||||
erupeConfig: erupeConfig,
|
||||
db: sqlxDB,
|
||||
}
|
||||
|
||||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
defer serverConn.Close()
|
||||
|
||||
session := &Session{
|
||||
logger: logger,
|
||||
server: server,
|
||||
rawConn: serverConn,
|
||||
cryptConn: network.NewCryptConn(serverConn),
|
||||
}
|
||||
|
||||
// Generate a bcrypt hash for "correctpass"
|
||||
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte("correctpass"), bcrypt.MinCost)
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("DSGN:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("testuser"))
|
||||
bf.WriteNullTerminatedBytes([]byte("wrongpass")) // Wrong password
|
||||
bf.WriteNullTerminatedBytes([]byte("unk"))
|
||||
|
||||
// Mock DB: user found but password will not match
|
||||
mock.ExpectQuery("SELECT id, password FROM users WHERE username = \\$1").
|
||||
WithArgs("testuser").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "password"}).AddRow(1, string(hashedPassword)))
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := clientConn.Read(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Errorf("handlePacket() returned error: %v", err)
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
clientConn.Close()
|
||||
<-done
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestHandlePacketDSGNWithDBError tests DSGN:100 with a database error
|
||||
func TestHandlePacketDSGNWithDBError(t *testing.T) {
|
||||
logger := zap.NewNop()
|
||||
erupeConfig := &config.Config{
|
||||
DevMode: false,
|
||||
}
|
||||
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create sqlmock: %v", err)
|
||||
}
|
||||
sqlxDB := sqlx.NewDb(db, "sqlmock")
|
||||
|
||||
server := &Server{
|
||||
logger: logger,
|
||||
erupeConfig: erupeConfig,
|
||||
db: sqlxDB,
|
||||
}
|
||||
|
||||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
defer serverConn.Close()
|
||||
|
||||
session := &Session{
|
||||
logger: logger,
|
||||
server: server,
|
||||
rawConn: serverConn,
|
||||
cryptConn: network.NewCryptConn(serverConn),
|
||||
}
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("DSGN:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("testuser"))
|
||||
bf.WriteNullTerminatedBytes([]byte("testpass"))
|
||||
bf.WriteNullTerminatedBytes([]byte("unk"))
|
||||
|
||||
// Mock DB: generic error
|
||||
mock.ExpectQuery("SELECT id, password FROM users WHERE username = \\$1").
|
||||
WithArgs("testuser").
|
||||
WillReturnError(sql.ErrConnDone)
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := clientConn.Read(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Errorf("handlePacket() returned error: %v", err)
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
clientConn.Close()
|
||||
<-done
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestHandlePacketDSGNNewCharaRequest tests DSGN:100 with the '+' suffix for new character
|
||||
func TestHandlePacketDSGNNewCharaRequest(t *testing.T) {
|
||||
logger := zap.NewNop()
|
||||
erupeConfig := &config.Config{
|
||||
DevMode: false,
|
||||
}
|
||||
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create sqlmock: %v", err)
|
||||
}
|
||||
sqlxDB := sqlx.NewDb(db, "sqlmock")
|
||||
|
||||
server := &Server{
|
||||
logger: logger,
|
||||
erupeConfig: erupeConfig,
|
||||
db: sqlxDB,
|
||||
}
|
||||
|
||||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
defer serverConn.Close()
|
||||
|
||||
session := &Session{
|
||||
logger: logger,
|
||||
server: server,
|
||||
rawConn: serverConn,
|
||||
cryptConn: network.NewCryptConn(serverConn),
|
||||
}
|
||||
|
||||
// Generate a bcrypt hash for "testpass"
|
||||
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte("testpass"), bcrypt.MinCost)
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("DSGN:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("testuser+")) // '+' suffix means new character request
|
||||
bf.WriteNullTerminatedBytes([]byte("testpass"))
|
||||
bf.WriteNullTerminatedBytes([]byte("unk"))
|
||||
|
||||
// Mock DB: user found
|
||||
mock.ExpectQuery("SELECT id, password FROM users WHERE username = \\$1").
|
||||
WithArgs("testuser").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "password"}).AddRow(1, string(hashedPassword)))
|
||||
|
||||
// newUserChara: get user ID
|
||||
mock.ExpectQuery("SELECT id FROM users WHERE username = \\$1").
|
||||
WithArgs("testuser").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
||||
|
||||
// newUserChara: check existing new chars
|
||||
mock.ExpectQuery("SELECT COUNT\\(\\*\\) FROM characters WHERE user_id = \\$1 AND is_new_character = true").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
||||
|
||||
// newUserChara: insert character
|
||||
mock.ExpectExec("INSERT INTO characters").
|
||||
WithArgs(1, sqlmock.AnyArg()).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
|
||||
// makeSignInResp calls
|
||||
mock.ExpectQuery("SELECT COALESCE\\(last_login, now\\(\\)\\) FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"last_login"}).AddRow(time.Now()))
|
||||
|
||||
mock.ExpectQuery("SELECT return_expires FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"return_expires"}).AddRow(time.Now().Add(time.Hour * 24 * 30)))
|
||||
|
||||
mock.ExpectExec("UPDATE users SET last_login=\\$1 WHERE id=\\$2").
|
||||
WithArgs(sqlmock.AnyArg(), 1).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
|
||||
mock.ExpectQuery("SELECT id, is_female, is_new_character, name, unk_desc_string, hrp, gr, weapon_type, last_login FROM characters WHERE user_id = \\$1 AND deleted = false ORDER BY id ASC").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "is_female", "is_new_character", "name", "unk_desc_string", "hrp", "gr", "weapon_type", "last_login"}))
|
||||
|
||||
mock.ExpectExec("INSERT INTO sign_sessions \\(user_id, token\\) VALUES \\(\\$1, \\$2\\)").
|
||||
WithArgs(1, sqlmock.AnyArg()).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
|
||||
mock.ExpectQuery("SELECT last_character FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"last_character"}).AddRow(0))
|
||||
|
||||
mock.ExpectQuery("SELECT rights FROM users WHERE id=\\$1").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"rights"}).AddRow(2))
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := clientConn.Read(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Errorf("handlePacket() returned error: %v", err)
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
clientConn.Close()
|
||||
<-done
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestHandlePacketDSGNWithDevModeOutboundLogging tests dev mode outbound logging
|
||||
func TestHandlePacketDSGNWithDevModeOutboundLogging(t *testing.T) {
|
||||
logger := zap.NewNop()
|
||||
erupeConfig := &config.Config{
|
||||
DevMode: true,
|
||||
DevModeOptions: config.DevModeOptions{
|
||||
LogOutboundMessages: true,
|
||||
},
|
||||
}
|
||||
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create sqlmock: %v", err)
|
||||
}
|
||||
sqlxDB := sqlx.NewDb(db, "sqlmock")
|
||||
|
||||
server := &Server{
|
||||
logger: logger,
|
||||
erupeConfig: erupeConfig,
|
||||
db: sqlxDB,
|
||||
}
|
||||
|
||||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
defer serverConn.Close()
|
||||
|
||||
session := &Session{
|
||||
logger: logger,
|
||||
server: server,
|
||||
rawConn: serverConn,
|
||||
cryptConn: network.NewCryptConn(serverConn),
|
||||
}
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("DSGN:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("testuser"))
|
||||
bf.WriteNullTerminatedBytes([]byte("testpass"))
|
||||
bf.WriteNullTerminatedBytes([]byte("unk"))
|
||||
|
||||
// Mock DB: user not found, dev mode but no auto create
|
||||
mock.ExpectQuery("SELECT id, password FROM users WHERE username = \\$1").
|
||||
WithArgs("testuser").
|
||||
WillReturnError(sql.ErrNoRows)
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := clientConn.Read(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Errorf("handlePacket() returned error: %v", err)
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
clientConn.Close()
|
||||
<-done
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unfulfilled expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user