98 lines
2.5 KiB
Go
98 lines
2.5 KiB
Go
|
|
package plugins
|
||
|
|
|
||
|
|
import (
|
||
|
|
"database/sql"
|
||
|
|
|
||
|
|
_ "github.com/mattn/go-sqlite3"
|
||
|
|
. "github.com/onsi/ginkgo/v2"
|
||
|
|
. "github.com/onsi/gomega"
|
||
|
|
)
|
||
|
|
|
||
|
|
var _ = Describe("migrateDB", func() {
|
||
|
|
var db *sql.DB
|
||
|
|
|
||
|
|
BeforeEach(func() {
|
||
|
|
var err error
|
||
|
|
db, err = sql.Open("sqlite3", ":memory:")
|
||
|
|
Expect(err).ToNot(HaveOccurred())
|
||
|
|
})
|
||
|
|
|
||
|
|
AfterEach(func() {
|
||
|
|
if db != nil {
|
||
|
|
db.Close()
|
||
|
|
}
|
||
|
|
})
|
||
|
|
|
||
|
|
getUserVersion := func() int {
|
||
|
|
var version int
|
||
|
|
Expect(db.QueryRow(`PRAGMA user_version`).Scan(&version)).To(Succeed())
|
||
|
|
return version
|
||
|
|
}
|
||
|
|
|
||
|
|
It("applies all migrations on a fresh database", func() {
|
||
|
|
migrations := []string{
|
||
|
|
`CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)`,
|
||
|
|
`ALTER TABLE test ADD COLUMN email TEXT`,
|
||
|
|
}
|
||
|
|
|
||
|
|
Expect(migrateDB(db, migrations)).To(Succeed())
|
||
|
|
Expect(getUserVersion()).To(Equal(2))
|
||
|
|
|
||
|
|
// Verify schema
|
||
|
|
_, err := db.Exec(`INSERT INTO test (id, name, email) VALUES (1, 'Alice', 'alice@test.com')`)
|
||
|
|
Expect(err).ToNot(HaveOccurred())
|
||
|
|
})
|
||
|
|
|
||
|
|
It("skips already applied migrations", func() {
|
||
|
|
migrations1 := []string{
|
||
|
|
`CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)`,
|
||
|
|
}
|
||
|
|
Expect(migrateDB(db, migrations1)).To(Succeed())
|
||
|
|
Expect(getUserVersion()).To(Equal(1))
|
||
|
|
|
||
|
|
// Add a new migration
|
||
|
|
migrations2 := []string{
|
||
|
|
`CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)`,
|
||
|
|
`ALTER TABLE test ADD COLUMN email TEXT`,
|
||
|
|
}
|
||
|
|
Expect(migrateDB(db, migrations2)).To(Succeed())
|
||
|
|
Expect(getUserVersion()).To(Equal(2))
|
||
|
|
|
||
|
|
// Verify the new column exists
|
||
|
|
_, err := db.Exec(`INSERT INTO test (id, name, email) VALUES (1, 'Alice', 'alice@test.com')`)
|
||
|
|
Expect(err).ToNot(HaveOccurred())
|
||
|
|
})
|
||
|
|
|
||
|
|
It("is a no-op when all migrations are applied", func() {
|
||
|
|
migrations := []string{
|
||
|
|
`CREATE TABLE test (id INTEGER PRIMARY KEY)`,
|
||
|
|
}
|
||
|
|
Expect(migrateDB(db, migrations)).To(Succeed())
|
||
|
|
Expect(migrateDB(db, migrations)).To(Succeed())
|
||
|
|
Expect(getUserVersion()).To(Equal(1))
|
||
|
|
})
|
||
|
|
|
||
|
|
It("is a no-op with empty migrations slice", func() {
|
||
|
|
Expect(migrateDB(db, nil)).To(Succeed())
|
||
|
|
Expect(getUserVersion()).To(Equal(0))
|
||
|
|
})
|
||
|
|
|
||
|
|
It("rolls back on failure", func() {
|
||
|
|
migrations := []string{
|
||
|
|
`CREATE TABLE test (id INTEGER PRIMARY KEY)`,
|
||
|
|
`INVALID SQL STATEMENT`,
|
||
|
|
}
|
||
|
|
|
||
|
|
err := migrateDB(db, migrations)
|
||
|
|
Expect(err).To(HaveOccurred())
|
||
|
|
Expect(err.Error()).To(ContainSubstring("migration 2 failed"))
|
||
|
|
|
||
|
|
// Version should remain 0 (rolled back)
|
||
|
|
Expect(getUserVersion()).To(Equal(0))
|
||
|
|
|
||
|
|
// Table should not exist (rolled back)
|
||
|
|
_, err = db.Exec(`INSERT INTO test (id) VALUES (1)`)
|
||
|
|
Expect(err).To(HaveOccurred())
|
||
|
|
})
|
||
|
|
})
|