migration_test.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. package storage
  2. import (
  3. "context"
  4. "database/sql"
  5. "os"
  6. "path/filepath"
  7. "testing"
  8. _ "github.com/mattn/go-sqlite3"
  9. )
  10. func migrationDB(t *testing.T, schema string) *sql.DB {
  11. t.Helper()
  12. db, err := sql.Open("sqlite3", filepath.Join(t.TempDir(), "test.db"))
  13. if err != nil {
  14. t.Fatal(err)
  15. }
  16. t.Cleanup(func() { db.Close() })
  17. if _, err = db.Exec(schema); err != nil {
  18. t.Fatal(err)
  19. }
  20. return db
  21. }
  22. func TestMigrateLegacyImages(t *testing.T) {
  23. db := migrationDB(t, `CREATE TABLE images (id TEXT, title TEXT)`)
  24. dir := t.TempDir()
  25. ids := []string{"00000000-0000-4000-8000-000000000001", "00000000-0000-4000-8000-000000000002", "00000000-0000-4000-8000-000000000003", "00000000-0000-4000-8000-000000000004", "../unsafe", "00000000-0000-4000-8000-000000000005"}
  26. for _, id := range ids {
  27. if _, err := db.Exec(`INSERT INTO images VALUES (?, 'title')`, id); err != nil {
  28. t.Fatal(err)
  29. }
  30. }
  31. files := [][]byte{[]byte("GIF89a\x00\x00\x00"), {0x1a, 0x45, 0xdf, 0xa3, 0x87, 0x42, 0x82, 0x84, 'w', 'e', 'b', 'm'}, {0x1a, 0x45, 0xdf, 0xa3, 0x8b, 0x42, 0x82, 0x88, 'm', 'a', 't', 'r', 'o', 's', 'k', 'a'}}
  32. for i, data := range files {
  33. if err := os.WriteFile(filepath.Join(dir, ids[i]), data, 0600); err != nil {
  34. t.Fatal(err)
  35. }
  36. }
  37. if err := os.Symlink(filepath.Join(dir, ids[0]), filepath.Join(dir, ids[5])); err != nil {
  38. t.Fatal(err)
  39. }
  40. report, err := MigrateLegacyImages(context.Background(), db, dir, "digital_art")
  41. if err != nil {
  42. t.Fatal(err)
  43. }
  44. if report != (MigrationReport{Examined: 6, Updated: 2, Unknown: 4}) {
  45. t.Fatalf("report: %+v", report)
  46. }
  47. for i, id := range ids {
  48. var category string
  49. var mt sql.NullString
  50. if err := db.QueryRow(`SELECT category, media_type FROM images WHERE id=?`, id).Scan(&category, &mt); err != nil {
  51. t.Fatal(err)
  52. }
  53. if category != "digital_art" {
  54. t.Fatal(category)
  55. }
  56. want := ""
  57. if i == 0 {
  58. want = "image/gif"
  59. }
  60. if i == 1 {
  61. want = "video/webm"
  62. }
  63. if mt.String != want || (want == "" && mt.Valid) {
  64. t.Fatalf("%s: %+v", id, mt)
  65. }
  66. }
  67. report, err = MigrateLegacyImages(context.Background(), db, dir, "other")
  68. if err != nil {
  69. t.Fatal(err)
  70. }
  71. if report != (MigrationReport{Examined: 4, Unknown: 4}) {
  72. t.Fatalf("second: %+v", report)
  73. }
  74. }
  75. func TestMigrateExistingColumns(t *testing.T) {
  76. db := migrationDB(t, `CREATE TABLE images (id TEXT, category TEXT, media_type TEXT NOT NULL DEFAULT '')`)
  77. id := "00000000-0000-4000-8000-000000000001"
  78. dir := t.TempDir()
  79. os.WriteFile(filepath.Join(dir, id), []byte("GIF89a"), 0600)
  80. if _, err := db.Exec(`INSERT INTO images VALUES (?, 'old', ''), (?, 'keep', 'custom/type')`, id, id); err != nil {
  81. t.Fatal(err)
  82. }
  83. report, err := MigrateLegacyImages(context.Background(), db, dir, "new")
  84. if err != nil {
  85. t.Fatal(err)
  86. }
  87. if report.Updated != 1 {
  88. t.Fatal(report)
  89. }
  90. var cat, mt string
  91. if err := db.QueryRow(`SELECT category, media_type FROM images WHERE category='keep'`).Scan(&cat, &mt); err != nil || mt != "custom/type" {
  92. t.Fatalf("%s %s %v", cat, mt, err)
  93. }
  94. }
  95. func TestMigrationRollback(t *testing.T) {
  96. db := migrationDB(t, `CREATE TABLE images (id TEXT); INSERT INTO images VALUES ('00000000-0000-4000-8000-000000000001'); CREATE TRIGGER reject_update BEFORE UPDATE ON images BEGIN SELECT RAISE(ABORT,'reject'); END;`)
  97. dir := t.TempDir()
  98. if err := os.WriteFile(filepath.Join(dir, "00000000-0000-4000-8000-000000000001"), []byte("GIF89a"), 0600); err != nil {
  99. t.Fatal(err)
  100. }
  101. if _, err := MigrateLegacyImages(context.Background(), db, dir, "digital_art"); err == nil {
  102. t.Fatal("expected error")
  103. }
  104. rows, err := db.Query(`PRAGMA table_info(images)`)
  105. if err != nil {
  106. t.Fatal(err)
  107. }
  108. defer rows.Close()
  109. count := 0
  110. for rows.Next() {
  111. count++
  112. }
  113. if count != 1 {
  114. t.Fatalf("DDL not rolled back: %d columns", count)
  115. }
  116. }