package store import ( "strings" "testing" "testing/fstest" ) func TestParseMigrationVersion(t *testing.T) { cases := []struct { name string want int wantErr string }{ {"0001_initial.sql", 1, ""}, {"0042_add_oauth_clients.sql", 42, ""}, {"0001.sql", 0, "expected NNNN_name.sql"}, // no underscore {"_orphan.sql", 0, "expected NNNN_name.sql"}, // empty version {"abc_notnumeric.sql", 0, "non-numeric version"}, // not a number {"0000_zero.sql", 0, "version must be > 0"}, // zero rejected } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { got, err := parseMigrationVersion(tc.name) switch { case tc.wantErr == "" && err != nil: t.Errorf("unexpected error: %v", err) case tc.wantErr != "" && err == nil: t.Errorf("expected error containing %q, got nil", tc.wantErr) case tc.wantErr != "" && !strings.Contains(err.Error(), tc.wantErr): t.Errorf("error %q does not contain %q", err, tc.wantErr) case tc.wantErr == "" && got != tc.want: t.Errorf("got %d, want %d", got, tc.want) } }) } } func TestLoadMigrations_SortsByVersion(t *testing.T) { fsys := fstest.MapFS{ "m/0003_c.sql": {Data: []byte("-- c")}, "m/0001_a.sql": {Data: []byte("-- a")}, "m/0002_b.sql": {Data: []byte("-- b")}, } got, err := loadMigrations(fsys, "m") if err != nil { t.Fatalf("unexpected error: %v", err) } if len(got) != 3 { t.Fatalf("got %d migrations, want 3", len(got)) } for i, want := range []int{1, 2, 3} { if got[i].version != want { t.Errorf("migrations[%d].version = %d, want %d", i, got[i].version, want) } } } func TestLoadMigrations_SkipsNonSQL(t *testing.T) { fsys := fstest.MapFS{ "m/0001_a.sql": {Data: []byte("-- a")}, "m/README.md": {Data: []byte("ignore me")}, "m/notes.txt": {Data: []byte("ignore me too")}, } got, err := loadMigrations(fsys, "m") if err != nil { t.Fatalf("unexpected error: %v", err) } if len(got) != 1 { t.Errorf("got %d migrations, want 1 (non-.sql must be skipped)", len(got)) } } func TestLoadMigrations_RejectsDuplicateVersion(t *testing.T) { fsys := fstest.MapFS{ "m/0001_a.sql": {Data: []byte("-- a")}, "m/0001_b.sql": {Data: []byte("-- b")}, } _, err := loadMigrations(fsys, "m") if err == nil || !strings.Contains(err.Error(), "duplicate migration version 1") { t.Errorf("want duplicate-version error, got %v", err) } } func TestLoadMigrations_RejectsBadFilename(t *testing.T) { fsys := fstest.MapFS{ "m/nogood.sql": {Data: []byte("-- bad")}, } _, err := loadMigrations(fsys, "m") if err == nil || !strings.Contains(err.Error(), "expected NNNN_name.sql") { t.Errorf("want bad-filename error, got %v", err) } } func TestLoadMigrations_MissingDir(t *testing.T) { _, err := loadMigrations(fstest.MapFS{}, "nope") if err == nil || !strings.Contains(err.Error(), "read migrations dir") { t.Errorf("want missing-dir error, got %v", err) } }