test(storage): guard against duplicate goose migration version prefixes (#336)
* test(storage): guard against duplicate goose migration version prefixes Statically scans embedded migration filenames for repeated numeric version prefixes and fails with a clear message, catching the class of bug from #333 (two PRs adding 0014_*.sql independently) before goose.Up() would panic at runtime. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(storage): dedupe migration versions by goose's parsed int64, not raw string versionPrefix compared raw filename prefixes, so 014_x.sql and 0014_y.sql were treated as distinct even though goose.NumericComponent parses both to version 14 and panics on the collision. Use goose.NumericComponent directly so the test enforces goose's actual collision rule. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(storage): trim PR-specific framing from migration version test comment Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f98c5e56cc
commit
c53c4af8bd
|
|
@ -0,0 +1,39 @@
|
|||
package sqlite
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/pressly/goose/v3"
|
||||
)
|
||||
|
||||
// TestMigrationVersionsAreUnique scans the embedded migration filenames and
|
||||
// parses each version with goose.NumericComponent — the same function goose
|
||||
// itself uses — so prefixes that parse to the same int64 (e.g. "014" vs
|
||||
// "0014") are caught as a collision, not just identical strings. Catches the
|
||||
// conflict with a clear message instead of a goose panic at runtime.
|
||||
func TestMigrationVersionsAreUnique(t *testing.T) {
|
||||
entries, err := migrationsFS.ReadDir("migrations")
|
||||
if err != nil {
|
||||
t.Fatalf("read migrations dir: %v", err)
|
||||
}
|
||||
|
||||
seen := map[int64]string{} // parsed version -> filename
|
||||
for _, e := range entries {
|
||||
name := e.Name()
|
||||
if e.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
version, err := goose.NumericComponent(name)
|
||||
if err != nil {
|
||||
t.Errorf("migration %q has no version goose can parse: %v", name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if other, dup := seen[version]; dup {
|
||||
t.Errorf("duplicate migration version %d: %s vs %s", version, other, name)
|
||||
continue
|
||||
}
|
||||
seen[version] = name
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue