package migrations import ( "testing" ) func TestFilesEmbedded(t *testing.T) { // Test that migration files are properly embedded entries, err := Files.ReadDir(".") if err != nil { t.Fatalf("Failed to read embedded migrations: %v", err) } if len(entries) == 0 { t.Fatal("No migration files embedded") } // Verify we have SQL files hasSQL := false for _, entry := range entries { if !entry.IsDir() && len(entry.Name()) > 4 && entry.Name()[len(entry.Name())-4:] == ".sql" { hasSQL = true break } } if !hasSQL { t.Fatal("No .sql files found in embedded migrations") } } func TestMigrationFilesReadable(t *testing.T) { // Test that all embedded migration files can be read entries, err := Files.ReadDir(".") if err != nil { t.Fatalf("Failed to read embedded migrations: %v", err) } for _, entry := range entries { if entry.IsDir() { continue } // Skip non-SQL files name := entry.Name() if len(name) < 4 || name[len(name)-4:] != ".sql" { continue } content, err := Files.ReadFile(name) if err != nil { t.Errorf("Failed to read migration file %s: %v", name, err) continue } if len(content) == 0 { t.Errorf("Migration file %s is empty", name) } // Verify content looks like SQL contentStr := string(content) if len(contentStr) < 10 { t.Errorf("Migration file %s content too short", name) } } } func TestMigrationFileNaming(t *testing.T) { // Test that migration files follow naming convention (NNNN_description.sql) entries, err := Files.ReadDir(".") if err != nil { t.Fatalf("Failed to read embedded migrations: %v", err) } for _, entry := range entries { if entry.IsDir() { continue } name := entry.Name() if len(name) < 4 || name[len(name)-4:] != ".sql" { continue } // Check naming pattern: should start with digits followed by underscore if len(name) < 5 { t.Errorf("Migration file %s name too short", name) continue } // Should start with at least 4 digits hasPrefix := false for i := 0; i < 4 && i < len(name); i++ { if name[i] >= '0' && name[i] <= '9' { if i == 3 { hasPrefix = true } } else { break } } if !hasPrefix { t.Errorf("Migration file %s does not follow naming convention (should start with 4 digits)", name) } } } func TestMigrationFilesSorted(t *testing.T) { // Test that migration files can be sorted consistently entries, err := Files.ReadDir(".") if err != nil { t.Fatalf("Failed to read embedded migrations: %v", err) } var sqlFiles []string for _, entry := range entries { if entry.IsDir() { continue } name := entry.Name() if len(name) > 4 && name[len(name)-4:] == ".sql" { sqlFiles = append(sqlFiles, name) } } if len(sqlFiles) < 2 { t.Skip("Not enough SQL files to test sorting") } // Verify files can be compared for i := 1; i < len(sqlFiles); i++ { if sqlFiles[i] < sqlFiles[i-1] { t.Errorf("Files not sorted: %s should come before %s", sqlFiles[i-1], sqlFiles[i]) } } } func TestInitialMigrationContent(t *testing.T) { // Test that the initial migration file exists and has expected content content, err := Files.ReadFile("0001_init.sql") if err != nil { t.Skipf("0001_init.sql not found: %v", err) } contentStr := string(content) // Initial migration should contain CREATE TABLE statements if len(contentStr) < 50 { t.Error("Initial migration file seems too short") } // Should contain typical SQL keywords hasCreate := containsAny(contentStr, []string{"CREATE", "create"}) hasTable := containsAny(contentStr, []string{"TABLE", "table"}) if !hasCreate || !hasTable { t.Error("Initial migration should contain CREATE TABLE statements") } } func containsAny(s string, substrs []string) bool { for _, substr := range substrs { for i := 0; i <= len(s)-len(substr); i++ { if s[i:i+len(substr)] == substr { return true } } } return false }