list_errors_test.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. package storage
  2. import (
  3. "database/sql"
  4. "testing"
  5. _ "github.com/mattn/go-sqlite3"
  6. )
  7. // Every list operation must report query and scan failures without terminating
  8. // the process or leaking the single database connection.
  9. func TestListOperationsReportErrors(t *testing.T) {
  10. tests := []struct {
  11. name, table, schema string
  12. call func(*SQLiteRepo) error
  13. }{
  14. {"menu", "menu", "id INTEGER, link TEXT, text TEXT, extra TEXT", func(r *SQLiteRepo) error { _, e := r.GetDropdownElementsWithError(); return e }},
  15. {"navbar", "navbar", "id INTEGER, png BLOB, link TEXT, redirect TEXT, extra TEXT", func(r *SQLiteRepo) error { _, e := r.GetNavBarLinksWithError(); return e }},
  16. {"assets", "assets", "id INTEGER, name TEXT, data BLOB, extra TEXT", func(r *SQLiteRepo) error { _, e := r.GetAssetsWithError(); return e }},
  17. {"admin", "admin", "id INTEGER, display_name TEXT, link TEXT, category TEXT, extra TEXT", func(r *SQLiteRepo) error { _, e := r.GetAdminTablesWithError(); return e }},
  18. {"category", "posts", "row INTEGER, id TEXT, title TEXT, created TEXT, body TEXT, category TEXT, sample TEXT, extra TEXT", func(r *SQLiteRepo) error { _, e := r.GetByCategoryWithError("test"); return e }},
  19. {"documents", "posts", "row INTEGER, id TEXT, title TEXT, created TEXT, body TEXT, category TEXT, sample TEXT, extra TEXT", func(r *SQLiteRepo) error { _, e := r.AllDocumentsWithError(); return e }},
  20. // NULL title causes Scan to fail after a successful query.
  21. {"images", "images", "id TEXT, title TEXT, desc TEXT, created TEXT, category TEXT, media_type TEXT", func(r *SQLiteRepo) error { _, e := r.GetAllImagesWithError(); return e }},
  22. {"images category", "images", "id TEXT, title TEXT, desc TEXT, created TEXT, category TEXT, media_type TEXT", func(r *SQLiteRepo) error { _, e := r.GetImagesByCategoryWithError("test"); return e }},
  23. }
  24. for _, tt := range tests {
  25. t.Run(tt.name, func(t *testing.T) {
  26. db, err := sql.Open("sqlite3", ":memory:")
  27. if err != nil {
  28. t.Fatal(err)
  29. }
  30. defer db.Close()
  31. db.SetMaxOpenConns(1)
  32. repo := NewSQLiteRepo(db, nil)
  33. if err := tt.call(repo); err == nil {
  34. t.Fatal("missing table: expected query error")
  35. }
  36. if _, err := db.Exec("CREATE TABLE " + tt.table + " (" + tt.schema + ")"); err != nil {
  37. t.Fatal(err)
  38. }
  39. if tt.table == "posts" || tt.table == "images" {
  40. _, err = db.Exec("INSERT INTO " + tt.table + " (category) VALUES ('test')")
  41. } else {
  42. _, err = db.Exec("INSERT INTO " + tt.table + " DEFAULT VALUES")
  43. }
  44. if err != nil {
  45. t.Fatal(err)
  46. }
  47. if err := tt.call(repo); err == nil {
  48. t.Fatal("bad row: expected scan error")
  49. }
  50. if stats := db.Stats(); stats.InUse != 0 {
  51. t.Fatalf("connection still in use: %+v", stats)
  52. }
  53. })
  54. }
  55. }
  56. func TestLegacyListMethodsDoNotExitOnQueryError(t *testing.T) {
  57. db, err := sql.Open("sqlite3", ":memory:")
  58. if err != nil {
  59. t.Fatal(err)
  60. }
  61. defer db.Close()
  62. repo := NewSQLiteRepo(db, nil)
  63. repo.GetDropdownElements()
  64. repo.GetNavBarLinks()
  65. repo.GetAssets()
  66. repo.GetAdminTables()
  67. repo.GetByCategory("test")
  68. repo.AllDocuments()
  69. repo.GetAllImages()
  70. repo.GetImagesByCategory("test")
  71. }