package lagoon import ( "bytes" "database/sql" "encoding/base64" "os" "path/filepath" "strings" "testing" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/compass" "gorm.io/gorm" ) func TestUseRejectsNilSQL(t *testing.T) { _, err := Use(t.Context(), nil) if err == nil || !strings.Contains(err.Error(), "sql db is nil") { t.Fatalf("got %v", err) } } func TestPublishRejectsNilHandles(t *testing.T) { app := backpack.New(nil) if err := Publish(nil, nil, nil); err == nil { t.Fatal("want nil app error") } if err := Publish(app, nil, &gorm.DB{}); err == nil || !strings.Contains(err.Error(), "nil") { t.Fatalf("got %v", err) } } func TestDSNEmptyWithoutConfig(t *testing.T) { if DSN(nil) != "" { t.Fatal("nil config must yield empty DSN") } } func TestOpenFromAppMissingConfig(t *testing.T) { _, _, err := OpenFromApp(t.Context(), nil) if err == nil || !strings.Contains(err.Error(), "app config is missing") { t.Fatalf("got %v", err) } _, _, err = OpenFromApp(t.Context(), backpack.New(nil)) if err == nil || !strings.Contains(err.Error(), "app config is missing") { t.Fatalf("got %v", err) } } func TestSharedSQLPoolUsedByGORMAndClosed(t *testing.T) { _, dsn := dedicatedDB(t, "lagoon_shared") sqlDB, gdb, err := Open(t.Context(), dsn) if err != nil { t.Fatal(err) } raw, err := gdb.DB() if err != nil { t.Fatal(err) } if raw != sqlDB { t.Fatal("GORM is not using the shared *sql.DB") } app := backpack.New(nil) if err := Publish(app, sqlDB, gdb); err != nil { t.Fatal(err) } gotSQL, ok := app.Lookup[*sql.DB]() if !ok || gotSQL != sqlDB { t.Fatal("published *sql.DB is not the shared pool") } gotGORM, ok := app.Lookup[*gorm.DB]() if !ok || gotGORM != gdb { t.Fatal("published *gorm.DB is missing") } viaUse, err := Use(t.Context(), sqlDB) if err != nil { t.Fatal(err) } useRaw, err := viaUse.DB() if err != nil { t.Fatal(err) } if useRaw != sqlDB { t.Fatal("Use must open GORM on the caller pool, not a second connection") } if err := sqlDB.Close(); err != nil { t.Fatal(err) } if err := sqlDB.PingContext(t.Context()); err == nil { t.Fatal("closed pool must reject Ping") } if _, err := Use(t.Context(), sqlDB); err == nil { t.Fatal("Use must fail after the shared pool is closed") } } func TestOpenFromAppReadsDSN(t *testing.T) { _, dsn := dedicatedDB(t, "lagoon_from_app") dir := t.TempDir() if err := os.WriteFile(filepath.Join(dir, "app.yaml"), []byte("name: lagoon-test\n"), 0o644); err != nil { t.Fatal(err) } cfg, err := compass.Open(compass.Options{ Dir: dir, Environ: []string{ "SUMMER_ENV=development", "SUMMER_DATABASE__DSN=" + dsn, "SUMMER_APP__KEY=" + base64.StdEncoding.EncodeToString(bytes.Repeat([]byte("T"), 32)), }, }) if err != nil { t.Fatal(err) } if got := DSN(cfg); got != dsn { t.Fatalf("DSN = %q want %q", got, dsn) } sqlDB, gdb, err := OpenFromApp(t.Context(), backpack.New(cfg)) if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = sqlDB.Close() }) raw, err := gdb.DB() if err != nil { t.Fatal(err) } if raw != sqlDB { t.Fatal("OpenFromApp must share the same *sql.DB with GORM") } }