chore: clean .gitignore cache

This commit is contained in:
GitHub Actions
2026-01-26 19:21:33 +00:00
parent 1b1b3a70b1
commit e5f0fec5db
1483 changed files with 0 additions and 472793 deletions

View File

@@ -1,88 +0,0 @@
package testutil
import (
"testing"
"gorm.io/gorm"
)
// WithTx runs a test function within a transaction that is always rolled back.
// This provides test isolation without the overhead of creating new databases.
//
// Usage Example:
//
// func TestSomething(t *testing.T) {
// sharedDB := setupSharedDB(t) // Create once per package
// testutil.WithTx(t, sharedDB, func(tx *gorm.DB) {
// // Use tx for all DB operations in this test
// tx.Create(&models.User{Name: "test"})
// // Transaction automatically rolled back at end
// })
// }
func WithTx(t *testing.T, db *gorm.DB, fn func(tx *gorm.DB)) {
t.Helper()
tx := db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
panic(r)
}
tx.Rollback()
}()
fn(tx)
}
// GetTestTx returns a transaction that will be rolled back when the test completes.
// This is useful for tests that need to pass the transaction to multiple functions.
//
// Usage Example:
//
// func TestSomething(t *testing.T) {
// t.Parallel() // Safe to run in parallel with transaction isolation
// sharedDB := getSharedDB(t)
// tx := testutil.GetTestTx(t, sharedDB)
// // Use tx for all DB operations
// tx.Create(&models.User{Name: "test"})
// // Transaction automatically rolled back via t.Cleanup()
// }
//
// Note: When using GetTestTx with t.Parallel(), ensure the shared DB is safe for
// concurrent access (e.g., using ?cache=shared for SQLite).
func GetTestTx(t *testing.T, db *gorm.DB) *gorm.DB {
t.Helper()
tx := db.Begin()
t.Cleanup(func() {
tx.Rollback()
})
return tx
}
// Best Practices for Transaction-Based Testing:
//
// 1. Create a shared DB once per test package (not per test):
// var sharedDB *gorm.DB
// func init() {
// db, _ := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
// db.AutoMigrate(&models.User{}, &models.Setting{})
// sharedDB = db
// }
//
// 2. Use transactions for test isolation:
// func TestUser(t *testing.T) {
// t.Parallel()
// tx := testutil.GetTestTx(t, sharedDB)
// // Test operations using tx
// }
//
// 3. When NOT to use transaction rollbacks:
// - Tests that need specific DB schemas per test
// - Tests that intentionally test transaction behavior
// - Tests that require nil DB values
// - Tests using in-memory :memory: (already fast enough)
// - Complex tests with custom setup/teardown logic
//
// 4. Benefits of transaction rollbacks:
// - Faster than creating new databases (especially for disk-based DBs)
// - Automatic cleanup (no manual teardown needed)
// - Enables safe use of t.Parallel() for concurrent test execution
// - Reduces disk I/O and memory usage in CI environments

View File

@@ -1,304 +0,0 @@
package testutil
import (
"testing"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// testModel is a simple model for testing database operations
type testModel struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"not null"`
}
// setupTestDB creates a fresh in-memory SQLite database for testing
func setupTestDB(t *testing.T) *gorm.DB {
t.Helper()
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
if err != nil {
t.Fatalf("Failed to open test database: %v", err)
}
// Run migrations
if err := db.AutoMigrate(&testModel{}); err != nil {
t.Fatalf("Failed to migrate test database: %v", err)
}
return db
}
// TestWithTx_Success verifies that WithTx executes the function and rolls back the transaction
func TestWithTx_Success(t *testing.T) {
db := setupTestDB(t)
// Insert data within transaction
WithTx(t, db, func(tx *gorm.DB) {
record := &testModel{Name: "test-record"}
if err := tx.Create(record).Error; err != nil {
t.Fatalf("Failed to create record: %v", err)
}
// Verify record exists within transaction
var count int64
tx.Model(&testModel{}).Count(&count)
if count != 1 {
t.Errorf("Expected 1 record in transaction, got %d", count)
}
})
// Verify record was rolled back
var count int64
db.Model(&testModel{}).Count(&count)
if count != 0 {
t.Errorf("Expected 0 records after rollback, got %d", count)
}
}
// TestWithTx_Panic verifies that WithTx rolls back on panic and propagates the panic
func TestWithTx_Panic(t *testing.T) {
db := setupTestDB(t)
defer func() {
if r := recover(); r == nil {
t.Error("Expected panic to be propagated, but no panic occurred")
} else if r != "test panic" {
t.Errorf("Expected panic value 'test panic', got %v", r)
}
// Verify record was rolled back after panic
var count int64
db.Model(&testModel{}).Count(&count)
if count != 0 {
t.Errorf("Expected 0 records after panic rollback, got %d", count)
}
}()
WithTx(t, db, func(tx *gorm.DB) {
// Insert data
record := &testModel{Name: "panic-test"}
if err := tx.Create(record).Error; err != nil {
t.Fatalf("Failed to create record: %v", err)
}
// Trigger panic
panic("test panic")
})
}
// TestWithTx_MultipleOperations verifies WithTx works with multiple database operations
func TestWithTx_MultipleOperations(t *testing.T) {
db := setupTestDB(t)
WithTx(t, db, func(tx *gorm.DB) {
// Create multiple records
records := []testModel{
{Name: "record1"},
{Name: "record2"},
{Name: "record3"},
}
for _, record := range records {
if err := tx.Create(&record).Error; err != nil {
t.Fatalf("Failed to create record: %v", err)
}
}
// Update a record
if err := tx.Model(&testModel{}).Where("name = ?", "record2").Update("name", "updated").Error; err != nil {
t.Fatalf("Failed to update record: %v", err)
}
// Verify updates within transaction
var updated testModel
tx.Where("name = ?", "updated").First(&updated)
if updated.Name != "updated" {
t.Error("Update not visible within transaction")
}
})
// Verify all operations were rolled back
var count int64
db.Model(&testModel{}).Count(&count)
if count != 0 {
t.Errorf("Expected 0 records after rollback, got %d", count)
}
}
// TestGetTestTx_Cleanup verifies that GetTestTx registers cleanup and rolls back
func TestGetTestTx_Cleanup(t *testing.T) {
db := setupTestDB(t)
// Create a subtest to isolate cleanup
t.Run("Subtest", func(t *testing.T) {
tx := GetTestTx(t, db)
// Insert data
record := &testModel{Name: "cleanup-test"}
if err := tx.Create(record).Error; err != nil {
t.Fatalf("Failed to create record: %v", err)
}
// Verify record exists
var count int64
tx.Model(&testModel{}).Count(&count)
if count != 1 {
t.Errorf("Expected 1 record in transaction, got %d", count)
}
// When this subtest finishes, t.Cleanup should roll back the transaction
})
// Verify record was rolled back after subtest cleanup
var count int64
db.Model(&testModel{}).Count(&count)
if count != 0 {
t.Errorf("Expected 0 records after cleanup rollback, got %d", count)
}
}
// TestGetTestTx_MultipleTransactions verifies that multiple GetTestTx calls are isolated
func TestGetTestTx_MultipleTransactions(t *testing.T) {
db := setupTestDB(t)
// First transaction
t.Run("Transaction1", func(t *testing.T) {
tx := GetTestTx(t, db)
record := &testModel{Name: "tx1-record"}
if err := tx.Create(record).Error; err != nil {
t.Fatalf("Failed to create record: %v", err)
}
})
// Second transaction
t.Run("Transaction2", func(t *testing.T) {
tx := GetTestTx(t, db)
record := &testModel{Name: "tx2-record"}
if err := tx.Create(record).Error; err != nil {
t.Fatalf("Failed to create record: %v", err)
}
})
// Verify both transactions were rolled back
var count int64
db.Model(&testModel{}).Count(&count)
if count != 0 {
t.Errorf("Expected 0 records after all cleanups, got %d", count)
}
}
// TestGetTestTx_UsageInMultipleFunctions demonstrates passing tx between functions
func TestGetTestTx_UsageInMultipleFunctions(t *testing.T) {
db := setupTestDB(t)
t.Run("MultiFunction", func(t *testing.T) {
tx := GetTestTx(t, db)
// Helper function 1: Create
createRecord := func(tx *gorm.DB, name string) error {
return tx.Create(&testModel{Name: name}).Error
}
// Helper function 2: Count
countRecords := func(tx *gorm.DB) int64 {
var count int64
tx.Model(&testModel{}).Count(&count)
return count
}
// Use helper functions with the same transaction
if err := createRecord(tx, "func-test"); err != nil {
t.Fatalf("Failed to create record: %v", err)
}
count := countRecords(tx)
if count != 1 {
t.Errorf("Expected 1 record, got %d", count)
}
})
// Verify cleanup happened
var count int64
db.Model(&testModel{}).Count(&count)
if count != 0 {
t.Errorf("Expected 0 records after cleanup, got %d", count)
}
}
// TestGetTestTx_Parallel verifies isolation with multiple GetTestTx calls
// Note: SQLite doesn't handle concurrent writes well, so we test isolation without t.Parallel()
func TestGetTestTx_Parallel(t *testing.T) {
// Use shared database for isolation tests
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
if err != nil {
t.Fatalf("Failed to open shared test database: %v", err)
}
if err := db.AutoMigrate(&testModel{}); err != nil {
t.Fatalf("Failed to migrate test database: %v", err)
}
// Run isolated tests (demonstrating isolation without actual parallelism due to SQLite limitations)
t.Run("Isolation1", func(t *testing.T) {
tx := GetTestTx(t, db)
record := &testModel{Name: "isolation1"}
if err := tx.Create(record).Error; err != nil {
t.Fatalf("Failed to create record: %v", err)
}
var count int64
tx.Model(&testModel{}).Count(&count)
if count != 1 {
t.Errorf("Expected 1 record in isolation1 transaction, got %d", count)
}
})
t.Run("Isolation2", func(t *testing.T) {
tx := GetTestTx(t, db)
record := &testModel{Name: "isolation2"}
if err := tx.Create(record).Error; err != nil {
t.Fatalf("Failed to create record: %v", err)
}
var count int64
tx.Model(&testModel{}).Count(&count)
if count != 1 {
t.Errorf("Expected 1 record in isolation2 transaction, got %d", count)
}
})
// After all tests complete, verify all rolled back
var finalCount int64
db.Model(&testModel{}).Count(&finalCount)
if finalCount != 0 {
t.Errorf("Expected 0 records after isolated tests, got %d", finalCount)
}
}
// TestGetTestTx_WithActualTestFailure verifies cleanup happens even on test failure
func TestGetTestTx_WithActualTestFailure(t *testing.T) {
db := setupTestDB(t)
// This subtest will fail, but cleanup should still happen
t.Run("FailingSubtest", func(t *testing.T) {
tx := GetTestTx(t, db)
record := &testModel{Name: "will-be-rolled-back"}
if err := tx.Create(record).Error; err != nil {
t.Fatalf("Failed to create record: %v", err)
}
// Even though this test "fails" conceptually, cleanup should still run
// (We're not actually failing here to avoid failing the test suite)
})
// Verify cleanup happened despite the "failure"
var count int64
db.Model(&testModel{}).Count(&count)
if count != 0 {
t.Errorf("Expected 0 records after cleanup on failure, got %d", count)
}
}