mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-05 23:44:22 +00:00
299 lines
7.1 KiB
Go
299 lines
7.1 KiB
Go
package db_test
|
|
|
|
import (
|
|
"database/sql"
|
|
"testing"
|
|
"time"
|
|
|
|
"lemma/internal/db"
|
|
)
|
|
|
|
func TestScannerQueryRow(t *testing.T) {
|
|
mockSecrets := &mockSecretsService{}
|
|
testDB, err := db.NewTestDB(mockSecrets)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create test database: %v", err)
|
|
}
|
|
defer testDB.Close()
|
|
|
|
// Create a test table
|
|
_, err = testDB.TestDB().Exec(`
|
|
CREATE TABLE users (
|
|
id INTEGER PRIMARY KEY,
|
|
email TEXT NOT NULL,
|
|
created_at TIMESTAMP NOT NULL,
|
|
active BOOLEAN NOT NULL
|
|
)
|
|
`)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create test table: %v", err)
|
|
}
|
|
|
|
type User struct {
|
|
ID int
|
|
Email string
|
|
CreatedAt time.Time
|
|
Active bool
|
|
}
|
|
|
|
// Insert test data
|
|
now := time.Now().UTC().Truncate(time.Second)
|
|
_, err = testDB.TestDB().Exec(
|
|
"INSERT INTO users (id, email, created_at, active) VALUES (?, ?, ?, ?)",
|
|
1, "test@example.com", now, true,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("Failed to insert test data: %v", err)
|
|
}
|
|
|
|
// Test query row success
|
|
t.Run("QueryRow success", func(t *testing.T) {
|
|
scanner := db.NewScanner(testDB.TestDB(), db.DBTypeSQLite)
|
|
q := db.NewQuery(db.DBTypeSQLite)
|
|
q.Select("id", "email", "created_at", "active").
|
|
From("users").
|
|
Where("id = ").
|
|
Placeholder(1)
|
|
|
|
var user User
|
|
err := scanner.QueryRow(&user, q)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got %v", err)
|
|
}
|
|
|
|
if user.ID != 1 {
|
|
t.Errorf("Expected ID 1, got %d", user.ID)
|
|
}
|
|
if user.Email != "test@example.com" {
|
|
t.Errorf("Expected Email test@example.com, got %s", user.Email)
|
|
}
|
|
if !user.CreatedAt.Equal(now) {
|
|
t.Errorf("Expected CreatedAt %v, got %v", now, user.CreatedAt)
|
|
}
|
|
if !user.Active {
|
|
t.Errorf("Expected Active true, got %v", user.Active)
|
|
}
|
|
})
|
|
|
|
// Test query row no results
|
|
t.Run("QueryRow no results", func(t *testing.T) {
|
|
scanner := db.NewScanner(testDB.TestDB(), db.DBTypeSQLite)
|
|
q := db.NewQuery(db.DBTypeSQLite)
|
|
q.Select("id", "email", "created_at", "active").
|
|
From("users").
|
|
Where("id = ").
|
|
Placeholder(999)
|
|
|
|
var user User
|
|
err := scanner.QueryRow(&user, q)
|
|
|
|
if err != sql.ErrNoRows {
|
|
t.Errorf("Expected ErrNoRows, got %v", err)
|
|
}
|
|
})
|
|
|
|
// Test scanning a single value
|
|
t.Run("QueryRow single value", func(t *testing.T) {
|
|
scanner := db.NewScanner(testDB.TestDB(), db.DBTypeSQLite)
|
|
q := db.NewQuery(db.DBTypeSQLite)
|
|
q.Select("COUNT(*)").From("users")
|
|
|
|
var count int
|
|
err := scanner.QueryRow(&count, q)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got %v", err)
|
|
}
|
|
|
|
if count != 1 {
|
|
t.Errorf("Expected count 1, got %d", count)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestScannerQuery(t *testing.T) {
|
|
mockSecrets := &mockSecretsService{}
|
|
testDB, err := db.NewTestDB(mockSecrets)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create test database: %v", err)
|
|
}
|
|
defer testDB.Close()
|
|
|
|
// Create a test table
|
|
_, err = testDB.TestDB().Exec(`
|
|
CREATE TABLE users (
|
|
id INTEGER PRIMARY KEY,
|
|
email TEXT NOT NULL,
|
|
created_at TIMESTAMP NOT NULL,
|
|
active BOOLEAN NOT NULL
|
|
)
|
|
`)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create test table: %v", err)
|
|
}
|
|
|
|
type User struct {
|
|
ID int
|
|
Email string
|
|
CreatedAt time.Time
|
|
Active bool
|
|
}
|
|
|
|
// Insert test data
|
|
now := time.Now().UTC().Truncate(time.Second)
|
|
testUsers := []User{
|
|
{ID: 1, Email: "user1@example.com", CreatedAt: now, Active: true},
|
|
{ID: 2, Email: "user2@example.com", CreatedAt: now, Active: false},
|
|
{ID: 3, Email: "user3@example.com", CreatedAt: now, Active: true},
|
|
}
|
|
|
|
for _, user := range testUsers {
|
|
_, err = testDB.TestDB().Exec(
|
|
"INSERT INTO users (id, email, created_at, active) VALUES (?, ?, ?, ?)",
|
|
user.ID, user.Email, user.CreatedAt, user.Active,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("Failed to insert test data: %v", err)
|
|
}
|
|
}
|
|
|
|
// Test query multiple rows
|
|
t.Run("Query multiple rows", func(t *testing.T) {
|
|
scanner := db.NewScanner(testDB.TestDB(), db.DBTypeSQLite)
|
|
q := db.NewQuery(db.DBTypeSQLite)
|
|
q.Select("id", "email", "created_at", "active").
|
|
From("users").
|
|
OrderBy("id ASC")
|
|
|
|
var users []User
|
|
err := scanner.Query(&users, q)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got %v", err)
|
|
}
|
|
|
|
if len(users) != len(testUsers) {
|
|
t.Errorf("Expected %d users, got %d", len(testUsers), len(users))
|
|
}
|
|
|
|
for i, u := range users {
|
|
if u.ID != testUsers[i].ID {
|
|
t.Errorf("Expected user[%d].ID %d, got %d", i, testUsers[i].ID, u.ID)
|
|
}
|
|
if u.Email != testUsers[i].Email {
|
|
t.Errorf("Expected user[%d].Email %s, got %s", i, testUsers[i].Email, u.Email)
|
|
}
|
|
if !u.CreatedAt.Equal(testUsers[i].CreatedAt) {
|
|
t.Errorf("Expected user[%d].CreatedAt %v, got %v", i, testUsers[i].CreatedAt, u.CreatedAt)
|
|
}
|
|
if u.Active != testUsers[i].Active {
|
|
t.Errorf("Expected user[%d].Active %v, got %v", i, testUsers[i].Active, u.Active)
|
|
}
|
|
}
|
|
})
|
|
|
|
// Test query with filter
|
|
t.Run("Query with filter", func(t *testing.T) {
|
|
scanner := db.NewScanner(testDB.TestDB(), db.DBTypeSQLite)
|
|
q := db.NewQuery(db.DBTypeSQLite)
|
|
q.Select("id", "email", "created_at", "active").
|
|
From("users").
|
|
Where("active = ").
|
|
Placeholder(true).
|
|
OrderBy("id ASC")
|
|
|
|
var users []User
|
|
err := scanner.Query(&users, q)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got %v", err)
|
|
}
|
|
|
|
if len(users) != 2 {
|
|
t.Errorf("Expected 2 users, got %d", len(users))
|
|
}
|
|
|
|
for _, u := range users {
|
|
if !u.Active {
|
|
t.Errorf("Expected only active users, got inactive user: %+v", u)
|
|
}
|
|
}
|
|
})
|
|
|
|
// Test query empty result
|
|
t.Run("Query empty result", func(t *testing.T) {
|
|
scanner := db.NewScanner(testDB.TestDB(), db.DBTypeSQLite)
|
|
q := db.NewQuery(db.DBTypeSQLite)
|
|
q.Select("id", "email", "created_at", "active").
|
|
From("users").
|
|
Where("id > ").
|
|
Placeholder(100)
|
|
|
|
var users []User
|
|
err := scanner.Query(&users, q)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got %v", err)
|
|
}
|
|
|
|
if len(users) != 0 {
|
|
t.Errorf("Expected 0 users, got %d", len(users))
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestScanErrors(t *testing.T) {
|
|
mockSecrets := &mockSecretsService{}
|
|
testDB, err := db.NewTestDB(mockSecrets)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create test database: %v", err)
|
|
}
|
|
defer testDB.Close()
|
|
|
|
scanner := db.NewScanner(testDB.TestDB(), db.DBTypeSQLite)
|
|
q := db.NewQuery(db.DBTypeSQLite)
|
|
q.Select("1")
|
|
|
|
// Test non-pointer
|
|
t.Run("QueryRow non-pointer", func(t *testing.T) {
|
|
var user struct{}
|
|
err := scanner.QueryRow(user, q) // Passing non-pointer
|
|
|
|
if err == nil {
|
|
t.Error("Expected error for non-pointer, got nil")
|
|
}
|
|
})
|
|
|
|
// Test pointer to non-slice for Query
|
|
t.Run("Query pointer to non-slice", func(t *testing.T) {
|
|
var user struct{}
|
|
err := scanner.Query(&user, q) // Passing pointer to struct, not slice
|
|
|
|
if err == nil {
|
|
t.Error("Expected error for non-slice pointer, got nil")
|
|
}
|
|
})
|
|
|
|
// Test non-pointer for Query
|
|
t.Run("Query non-pointer", func(t *testing.T) {
|
|
var users []struct{}
|
|
err := scanner.Query(users, q) // Passing non-pointer
|
|
|
|
if err == nil {
|
|
t.Error("Expected error for non-pointer, got nil")
|
|
}
|
|
})
|
|
}
|
|
|
|
// Mock secrets service for testing
|
|
type mockSecretsService struct{}
|
|
|
|
func (m *mockSecretsService) Encrypt(plaintext string) (string, error) {
|
|
return plaintext, nil
|
|
}
|
|
|
|
func (m *mockSecretsService) Decrypt(ciphertext string) (string, error) {
|
|
return ciphertext, nil
|
|
}
|