Files
relspecgo/pkg/readers/sqldir/reader_test.go
Hein adfe126758
Some checks failed
CI / Test (1.24) (push) Successful in -25m17s
CI / Test (1.25) (push) Successful in -25m15s
CI / Build (push) Successful in -25m45s
CI / Lint (push) Successful in -25m31s
Integration Tests / Integration Tests (push) Failing after -25m58s
Added a scripts execution ability
2025-12-31 00:44:14 +02:00

376 lines
10 KiB
Go

package sqldir
import (
"os"
"path/filepath"
"testing"
"git.warky.dev/wdevs/relspecgo/pkg/readers"
)
func TestReader_ReadDatabase(t *testing.T) {
// Create temporary test directory
tempDir, err := os.MkdirTemp("", "sqldir-test-*")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
defer os.RemoveAll(tempDir)
// Create test SQL files with both underscore and hyphen separators
testFiles := map[string]string{
"1_001_create_users.sql": "CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT);",
"1_002_create_posts.sql": "CREATE TABLE posts (id SERIAL PRIMARY KEY, user_id INT);",
"2_001_add_indexes.sql": "CREATE INDEX idx_posts_user_id ON posts(user_id);",
"1_003_seed_data.pgsql": "INSERT INTO users (name) VALUES ('Alice'), ('Bob');",
"10-10-create-newid.pgsql": "CREATE TABLE newid (id SERIAL PRIMARY KEY);",
"2-005-add-column.sql": "ALTER TABLE users ADD COLUMN email TEXT;",
}
for filename, content := range testFiles {
filePath := filepath.Join(tempDir, filename)
if err := os.WriteFile(filePath, []byte(content), 0644); err != nil {
t.Fatalf("Failed to create test file %s: %v", filename, err)
}
}
// Create subdirectory with additional script
subDir := filepath.Join(tempDir, "migrations")
if err := os.MkdirAll(subDir, 0755); err != nil {
t.Fatalf("Failed to create subdirectory: %v", err)
}
subFile := filepath.Join(subDir, "3_001_add_column.sql")
if err := os.WriteFile(subFile, []byte("ALTER TABLE users ADD COLUMN email TEXT;"), 0644); err != nil {
t.Fatalf("Failed to create subdirectory file: %v", err)
}
// Create reader
reader := NewReader(&readers.ReaderOptions{
FilePath: tempDir,
Metadata: map[string]any{
"schema_name": "test_schema",
"database_name": "test_db",
},
})
// Read database
db, err := reader.ReadDatabase()
if err != nil {
t.Fatalf("ReadDatabase failed: %v", err)
}
// Verify database
if db.Name != "test_db" {
t.Errorf("Expected database name 'test_db', got '%s'", db.Name)
}
if len(db.Schemas) != 1 {
t.Fatalf("Expected 1 schema, got %d", len(db.Schemas))
}
schema := db.Schemas[0]
if schema.Name != "test_schema" {
t.Errorf("Expected schema name 'test_schema', got '%s'", schema.Name)
}
// Verify scripts (should be 7 total: 4 underscore + 2 hyphen + 1 subdirectory)
if len(schema.Scripts) != 7 {
t.Fatalf("Expected 7 scripts, got %d", len(schema.Scripts))
}
// Verify script details
expectedScripts := []struct {
name string
priority int
sequence uint
}{
{"create_users", 1, 1},
{"create_posts", 1, 2},
{"seed_data", 1, 3},
{"add_indexes", 2, 1},
{"add-column", 2, 5},
{"add_column", 3, 1},
{"create-newid", 10, 10},
}
scriptMap := make(map[string]*struct {
priority int
sequence uint
sql string
})
for _, script := range schema.Scripts {
scriptMap[script.Name] = &struct {
priority int
sequence uint
sql string
}{
priority: script.Priority,
sequence: script.Sequence,
sql: script.SQL,
}
}
for _, expected := range expectedScripts {
script, exists := scriptMap[expected.name]
if !exists {
t.Errorf("Expected script '%s' not found", expected.name)
continue
}
if script.priority != expected.priority {
t.Errorf("Script '%s': expected priority %d, got %d",
expected.name, expected.priority, script.priority)
}
if script.sequence != expected.sequence {
t.Errorf("Script '%s': expected sequence %d, got %d",
expected.name, expected.sequence, script.sequence)
}
if script.sql == "" {
t.Errorf("Script '%s': SQL content is empty", expected.name)
}
}
}
func TestReader_ReadSchema(t *testing.T) {
// Create temporary test directory
tempDir, err := os.MkdirTemp("", "sqldir-test-*")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
defer os.RemoveAll(tempDir)
// Create test SQL file
testFile := filepath.Join(tempDir, "1_001_test.sql")
if err := os.WriteFile(testFile, []byte("SELECT 1;"), 0644); err != nil {
t.Fatalf("Failed to create test file: %v", err)
}
// Create reader
reader := NewReader(&readers.ReaderOptions{
FilePath: tempDir,
})
// Read schema
schema, err := reader.ReadSchema()
if err != nil {
t.Fatalf("ReadSchema failed: %v", err)
}
// Verify schema
if schema.Name != "public" {
t.Errorf("Expected default schema name 'public', got '%s'", schema.Name)
}
if len(schema.Scripts) != 1 {
t.Fatalf("Expected 1 script, got %d", len(schema.Scripts))
}
}
func TestReader_InvalidDirectory(t *testing.T) {
reader := NewReader(&readers.ReaderOptions{
FilePath: "/nonexistent/directory",
})
_, err := reader.ReadDatabase()
if err == nil {
t.Error("Expected error for nonexistent directory, got nil")
}
}
func TestReader_EmptyDirectory(t *testing.T) {
// Create temporary empty directory
tempDir, err := os.MkdirTemp("", "sqldir-test-*")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
defer os.RemoveAll(tempDir)
reader := NewReader(&readers.ReaderOptions{
FilePath: tempDir,
})
db, err := reader.ReadDatabase()
if err != nil {
t.Fatalf("ReadDatabase failed: %v", err)
}
if len(db.Schemas[0].Scripts) != 0 {
t.Errorf("Expected 0 scripts in empty directory, got %d", len(db.Schemas[0].Scripts))
}
}
func TestReader_InvalidFilename(t *testing.T) {
// Create temporary test directory
tempDir, err := os.MkdirTemp("", "sqldir-test-*")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
defer os.RemoveAll(tempDir)
// Create files with various invalid patterns
invalidFiles := []string{
"invalid.sql", // No priority/sequence
"1_test.sql", // Missing sequence
"test_1_2.sql", // Wrong order
"a_001_test.sql", // Non-numeric priority
"1_abc_test.sql", // Non-numeric sequence
"1_001_test.txt", // Wrong extension
"1_001_test.sql.backup", // Wrong extension
}
for _, filename := range invalidFiles {
filePath := filepath.Join(tempDir, filename)
if err := os.WriteFile(filePath, []byte("SELECT 1;"), 0644); err != nil {
t.Fatalf("Failed to create test file %s: %v", filename, err)
}
}
// Create one valid file
validFile := filepath.Join(tempDir, "1_001_valid.sql")
if err := os.WriteFile(validFile, []byte("SELECT 1;"), 0644); err != nil {
t.Fatalf("Failed to create valid file: %v", err)
}
reader := NewReader(&readers.ReaderOptions{
FilePath: tempDir,
})
db, err := reader.ReadDatabase()
if err != nil {
t.Fatalf("ReadDatabase failed: %v", err)
}
// Should only have the valid file
if len(db.Schemas[0].Scripts) != 1 {
t.Errorf("Expected 1 script (invalid files should be skipped), got %d", len(db.Schemas[0].Scripts))
}
if db.Schemas[0].Scripts[0].Name != "valid" {
t.Errorf("Expected script name 'valid', got '%s'", db.Schemas[0].Scripts[0].Name)
}
}
func TestReader_ReadTable(t *testing.T) {
reader := NewReader(&readers.ReaderOptions{})
_, err := reader.ReadTable()
if err == nil {
t.Error("Expected error for ReadTable (not supported), got nil")
}
}
func TestReader_HyphenFormat(t *testing.T) {
// Create temporary test directory
tempDir, err := os.MkdirTemp("", "sqldir-test-hyphen-*")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
defer os.RemoveAll(tempDir)
// Create test files with hyphen separators
testFiles := map[string]string{
"1-001-create-table.sql": "CREATE TABLE test (id INT);",
"1-002-insert-data.pgsql": "INSERT INTO test VALUES (1);",
"10-10-create-newid.pgsql": "CREATE TABLE newid (id SERIAL);",
"2-005-add-index.sql": "CREATE INDEX idx_test ON test(id);",
}
for filename, content := range testFiles {
filePath := filepath.Join(tempDir, filename)
if err := os.WriteFile(filePath, []byte(content), 0644); err != nil {
t.Fatalf("Failed to create test file %s: %v", filename, err)
}
}
// Create reader
reader := NewReader(&readers.ReaderOptions{
FilePath: tempDir,
})
// Read database
db, err := reader.ReadDatabase()
if err != nil {
t.Fatalf("ReadDatabase failed: %v", err)
}
schema := db.Schemas[0]
if len(schema.Scripts) != 4 {
t.Fatalf("Expected 4 scripts, got %d", len(schema.Scripts))
}
// Verify specific hyphen-formatted scripts
expectedScripts := map[string]struct {
priority int
sequence uint
}{
"create-table": {1, 1},
"insert-data": {1, 2},
"add-index": {2, 5},
"create-newid": {10, 10},
}
for _, script := range schema.Scripts {
expected, exists := expectedScripts[script.Name]
if !exists {
t.Errorf("Unexpected script: %s", script.Name)
continue
}
if script.Priority != expected.priority {
t.Errorf("Script '%s': expected priority %d, got %d",
script.Name, expected.priority, script.Priority)
}
if script.Sequence != expected.sequence {
t.Errorf("Script '%s': expected sequence %d, got %d",
script.Name, expected.sequence, script.Sequence)
}
}
}
func TestReader_MixedFormat(t *testing.T) {
// Test that both underscore and hyphen formats can be mixed
tempDir, err := os.MkdirTemp("", "sqldir-test-mixed-*")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
defer os.RemoveAll(tempDir)
testFiles := map[string]string{
"1_001_underscore.sql": "SELECT 1;",
"1-002-hyphen.sql": "SELECT 2;",
"2_003_underscore.sql": "SELECT 3;",
"2-004-hyphen.sql": "SELECT 4;",
}
for filename, content := range testFiles {
filePath := filepath.Join(tempDir, filename)
if err := os.WriteFile(filePath, []byte(content), 0644); err != nil {
t.Fatalf("Failed to create test file %s: %v", filename, err)
}
}
reader := NewReader(&readers.ReaderOptions{
FilePath: tempDir,
})
db, err := reader.ReadDatabase()
if err != nil {
t.Fatalf("ReadDatabase failed: %v", err)
}
schema := db.Schemas[0]
if len(schema.Scripts) != 4 {
t.Fatalf("Expected 4 scripts (mixed format), got %d", len(schema.Scripts))
}
// Verify both formats are parsed correctly
names := make(map[string]bool)
for _, script := range schema.Scripts {
names[script.Name] = true
}
expectedNames := []string{"underscore", "hyphen", "underscore", "hyphen"}
for _, name := range expectedNames {
if !names[name] {
t.Errorf("Expected script name '%s' not found", name)
}
}
}