Files
golib/jwt/tablemanager_test.go
Haelnorr 1b25e2f0a5 Refactor database interface to use *sql.DB directly
Simplified the database layer by removing custom interface wrappers
and using standard library *sql.DB and *sql.Tx types directly.

Changes:
- Removed DBConnection and DBTransaction interfaces from database.go
- Removed NewDBConnection() wrapper function
- Updated TokenGenerator to use *sql.DB instead of DBConnection
- Updated all validation and revocation methods to accept *sql.Tx
- Updated TableManager to work with *sql.DB directly
- Updated all tests to use db.Begin() instead of custom wrappers
- Fixed GeneratorConfig.DB field (was DBConn)
- Updated documentation in doc.go with correct API usage

Benefits:
- Simpler API with fewer abstractions
- Works directly with database/sql standard library
- Compatible with GORM (via gormDB.DB()) and Bun (share same *sql.DB)
- Easier to understand and maintain
- No unnecessary wrapper layers

Breaking changes:
- GeneratorConfig.DBConn renamed to GeneratorConfig.DB
- Removed NewDBConnection() function - pass *sql.DB directly
- ValidateAccess/ValidateRefresh now accept *sql.Tx instead of DBTransaction
- Token.Revoke/CheckNotRevoked now accept *sql.Tx instead of DBTransaction

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-11 17:39:30 +11:00

222 lines
6.2 KiB
Go

package jwt
import (
"context"
"testing"
"github.com/DATA-DOG/go-sqlmock"
"github.com/stretchr/testify/require"
)
func TestNewTableManager(t *testing.T) {
db, _, err := sqlmock.New()
require.NoError(t, err)
defer db.Close()
dbType := DatabaseType{Type: DatabasePostgreSQL, Version: "15"}
config := DefaultTableConfig()
tm := NewTableManager(db, dbType, config)
require.NotNil(t, tm)
}
func TestGetCreateTableSQL_PostgreSQL(t *testing.T) {
db, _, err := sqlmock.New()
require.NoError(t, err)
defer db.Close()
dbType := DatabaseType{Type: DatabasePostgreSQL, Version: "15"}
config := DefaultTableConfig()
tm := NewTableManager(db, dbType, config)
sql, err := tm.getCreateTableSQL()
require.NoError(t, err)
require.Contains(t, sql, "CREATE TABLE IF NOT EXISTS jwtblacklist")
require.Contains(t, sql, "jti UUID PRIMARY KEY")
require.Contains(t, sql, "exp BIGINT NOT NULL")
require.Contains(t, sql, "sub INTEGER NOT NULL")
require.Contains(t, sql, "CREATE INDEX IF NOT EXISTS idx_jwtblacklist_exp")
require.Contains(t, sql, "CREATE INDEX IF NOT EXISTS idx_jwtblacklist_sub")
}
func TestGetCreateTableSQL_MySQL(t *testing.T) {
db, _, err := sqlmock.New()
require.NoError(t, err)
defer db.Close()
dbType := DatabaseType{Type: DatabaseMySQL, Version: "8.0"}
config := DefaultTableConfig()
tm := NewTableManager(db, dbType, config)
sql, err := tm.getCreateTableSQL()
require.NoError(t, err)
require.Contains(t, sql, "CREATE TABLE IF NOT EXISTS jwtblacklist")
require.Contains(t, sql, "jti CHAR(36) PRIMARY KEY")
require.Contains(t, sql, "exp BIGINT NOT NULL")
require.Contains(t, sql, "sub INT NOT NULL")
require.Contains(t, sql, "INDEX idx_exp")
require.Contains(t, sql, "ENGINE=InnoDB")
}
func TestGetCreateTableSQL_SQLite(t *testing.T) {
db, _, err := sqlmock.New()
require.NoError(t, err)
defer db.Close()
dbType := DatabaseType{Type: DatabaseSQLite, Version: "3.42"}
config := DefaultTableConfig()
tm := NewTableManager(db, dbType, config)
sql, err := tm.getCreateTableSQL()
require.NoError(t, err)
require.Contains(t, sql, "CREATE TABLE IF NOT EXISTS jwtblacklist")
require.Contains(t, sql, "jti TEXT PRIMARY KEY")
require.Contains(t, sql, "exp INTEGER NOT NULL")
require.Contains(t, sql, "sub INTEGER NOT NULL")
}
func TestGetCreateTableSQL_CustomTableName(t *testing.T) {
db, _, err := sqlmock.New()
require.NoError(t, err)
defer db.Close()
dbType := DatabaseType{Type: DatabasePostgreSQL, Version: "15"}
config := TableConfig{
TableName: "custom_blacklist",
AutoCreate: true,
EnableAutoCleanup: false,
CleanupInterval: 24,
}
tm := NewTableManager(db, dbType, config)
sql, err := tm.getCreateTableSQL()
require.NoError(t, err)
require.Contains(t, sql, "CREATE TABLE IF NOT EXISTS custom_blacklist")
require.Contains(t, sql, "CREATE INDEX IF NOT EXISTS idx_custom_blacklist_exp")
}
func TestGetCreateTableSQL_UnsupportedDB(t *testing.T) {
db, _, err := sqlmock.New()
require.NoError(t, err)
defer db.Close()
dbType := DatabaseType{Type: "unsupported", Version: "1.0"}
config := DefaultTableConfig()
tm := NewTableManager(db, dbType, config)
sql, err := tm.getCreateTableSQL()
require.Error(t, err)
require.Empty(t, sql)
require.Contains(t, err.Error(), "unsupported database type")
}
func TestTableExists_PostgreSQL(t *testing.T) {
db, mock, err := sqlmock.New()
require.NoError(t, err)
defer db.Close()
dbType := DatabaseType{Type: DatabasePostgreSQL, Version: "15"}
config := DefaultTableConfig()
tm := NewTableManager(db, dbType, config)
// Test table exists
mock.ExpectQuery("SELECT 1 FROM information_schema.tables").
WithArgs("jwtblacklist").
WillReturnRows(sqlmock.NewRows([]string{"1"}).AddRow(1))
exists, err := tm.tableExists(context.Background())
require.NoError(t, err)
require.True(t, exists)
// Test table doesn't exist
mock.ExpectQuery("SELECT 1 FROM information_schema.tables").
WithArgs("jwtblacklist").
WillReturnRows(sqlmock.NewRows([]string{"1"}))
exists, err = tm.tableExists(context.Background())
require.NoError(t, err)
require.False(t, exists)
require.NoError(t, mock.ExpectationsWereMet())
}
func TestCreateTable_AlreadyExists(t *testing.T) {
db, mock, err := sqlmock.New()
require.NoError(t, err)
defer db.Close()
dbType := DatabaseType{Type: DatabasePostgreSQL, Version: "15"}
config := DefaultTableConfig()
tm := NewTableManager(db, dbType, config)
// Mock table exists check
mock.ExpectQuery("SELECT 1 FROM information_schema.tables").
WithArgs("jwtblacklist").
WillReturnRows(sqlmock.NewRows([]string{"1"}).AddRow(1))
err = tm.CreateTable(context.Background())
require.NoError(t, err)
require.NoError(t, mock.ExpectationsWereMet())
}
func TestCreateTable_Success(t *testing.T) {
db, mock, err := sqlmock.New()
require.NoError(t, err)
defer db.Close()
dbType := DatabaseType{Type: DatabasePostgreSQL, Version: "15"}
config := DefaultTableConfig()
tm := NewTableManager(db, dbType, config)
// Mock table doesn't exist
mock.ExpectQuery("SELECT 1 FROM information_schema.tables").
WithArgs("jwtblacklist").
WillReturnRows(sqlmock.NewRows([]string{"1"}))
// Mock CREATE TABLE
mock.ExpectExec("CREATE TABLE IF NOT EXISTS jwtblacklist").
WillReturnResult(sqlmock.NewResult(0, 0))
err = tm.CreateTable(context.Background())
require.NoError(t, err)
require.NoError(t, mock.ExpectationsWereMet())
}
func TestSetupAutoCleanup_Disabled(t *testing.T) {
db, mock, err := sqlmock.New()
require.NoError(t, err)
defer db.Close()
dbType := DatabaseType{Type: DatabasePostgreSQL, Version: "15"}
config := TableConfig{
TableName: "jwtblacklist",
AutoCreate: true,
EnableAutoCleanup: false,
CleanupInterval: 24,
}
tm := NewTableManager(db, dbType, config)
err = tm.SetupAutoCleanup(context.Background())
require.NoError(t, err)
require.NoError(t, mock.ExpectationsWereMet())
}
func TestSetupAutoCleanup_SQLite(t *testing.T) {
db, mock, err := sqlmock.New()
require.NoError(t, err)
defer db.Close()
dbType := DatabaseType{Type: DatabaseSQLite, Version: "3.42"}
config := DefaultTableConfig()
tm := NewTableManager(db, dbType, config)
// SQLite doesn't support auto-cleanup, should return nil
err = tm.SetupAutoCleanup(context.Background())
require.NoError(t, err)
require.NoError(t, mock.ExpectationsWereMet())
}