package main import ( "database/sql" "fmt" "os" "strings" "testing" ) func TestReadMigrations(t *testing.T) { n := len(migrations) entries, err := os.ReadDir(migrationDir) if err != nil { t.Fatalf("Failed to determine number of migration files: %v", err) } nMigrationFiles := len(entries) if n != nMigrationFiles { t.Fatalf("Expected %d migration files but got %d.", nMigrationFiles, n) } for i, migration := range migrations { path := migrationPath(i) expectation := fmt.Sprintf("PRAGMA user_version = %d;", i+1) if !strings.HasPrefix(migration, expectation) { t.Fatalf("Expected '%s' at start of '%s'.", expectation, path) } } } func TestTransaction(t *testing.T) { db, _ := emptyDB(t) newVersion := 1 err := Transaction(db, func(tx *sql.Tx) error { // valid statement _, err := tx.Exec(fmt.Sprintf("PRAGMA user_version = %d;", newVersion)) if err != nil { return err } // invalid statement which should roll back the whole transaction _, err = tx.Exec("PRAGMA user_version THIS IS SYNTAX ERROR TALKING!!!") if err != nil { return err } return nil }) if err == nil { t.Fatal("Error was not detected.") } version, err := UserVersion(db) if err != nil { t.Fatalf("Failed to get user_version: %v", err) } if version == newVersion { t.Fatal("Valid statement was not rolled back.") } expectedVersion := 0 if version != expectedVersion { t.Fatalf("Expected user_version %d but got %d", expectedVersion, version) } } func TestMigrate(t *testing.T) { db, _ := emptyDB(t) userVersion, err := UserVersion(db) if err != nil { t.Fatalf("Failed to get initial user_version: %v", err) } if userVersion != 0 { t.Fatalf("Expected user_version 0 but got %d.", userVersion) } for i := range migrations { path := migrationPath(i) err := Migrate(db, i) if err != nil { t.Fatalf("Failed to execute migration %s: %v", path, err) } userVersion, err = UserVersion(db) if err != nil { t.Fatalf("Failed to get user_version after migration: %v", err) } expected := i + 1 if userVersion != expected { t.Fatalf( "Expected user_version %d after running %s but got %d.", expected, path, userVersion, ) } } } func TestUserVersion(t *testing.T) { db, _ := emptyDB(t) expectedVersion := 42 err := Transaction(db, func(tx *sql.Tx) error { _, err := tx.Exec(fmt.Sprintf("PRAGMA user_version = %d;", expectedVersion)) if err != nil { return err } return nil }) if err != nil { t.Fatalf("Failed to set user expectedVersion: %v", err) } version, err := UserVersion(db) if err != nil { t.Fatalf("Could not execute function to test: %v", err) } if version != expectedVersion { t.Fatalf("Expected user_version %d but got %d.", expectedVersion, version) } } func TestMigrateToLatest(t *testing.T) { db, _ := emptyDB(t) err := MigrateToLatest(db) if err != nil { t.Fatalf("Could not execute function to test: %v", err) } v, err := UserVersion(db) if err != nil { t.Fatalf("Could not get user_version after migration: %v", err) } latest := len(migrations) if v != latest { t.Fatalf("Expected user_version %d but got %d.", latest, v) } futureUserVersion := 10000 err = Transaction(db, func(tx *sql.Tx) error { _, err := tx.Exec(fmt.Sprintf("PRAGMA user_version = %d;", futureUserVersion)) if err != nil { return err } return nil }) err = MigrateToLatest(db) if err != nil { t.Fatalf("Could not execute function to test with future DB: %v", err) } v, err = UserVersion(db) if err != nil { t.Fatalf("Could not get user_version after migration with future DB: %v", err) } if v != futureUserVersion { t.Fatalf("Expected user_version %d but got %d.", futureUserVersion, v) } }