package adapter_test import ( "context" "database/sql" "errors" "os" "strings" "testing" "time" "unicode" "gitea.dwysokinski.me/twhelp/dcbot/internal/adapter/internal/bunmodel" "gitea.dwysokinski.me/twhelp/dcbot/internal/domain" "github.com/cenkalti/backoff/v4" "github.com/google/uuid" "github.com/pressly/goose/v3" "github.com/stretchr/testify/require" "github.com/uptrace/bun" "github.com/uptrace/bun/dbfixture" "github.com/uptrace/bun/dialect/pgdialect" "github.com/uptrace/bun/driver/pgdriver" ) func newBunDB(tb testing.TB) *bun.DB { tb.Helper() schema := generateSchema() sqldb := sql.OpenDB( pgdriver.NewConnector( pgdriver.WithDSN(os.Getenv(envDBDSN)), pgdriver.WithConnParams(map[string]any{ "search_path": schema, }), ), ) bunDB := bun.NewDB(sqldb, pgdialect.New()) tb.Cleanup(func() { _ = bunDB.Close() }) require.NoError(tb, retry(bunDB.Ping), "couldn't ping DB") _, err := bunDB.Exec("CREATE SCHEMA ?", bun.Safe(schema)) require.NoError(tb, err, "couldn't create schema") runMigrations(tb, sqldb) return bunDB } func runMigrations(tb testing.TB, db *sql.DB) { tb.Helper() require.NoError(tb, goose.Up(db, "")) } type bunfixture struct { *dbfixture.Fixture } func loadFixtures(tb testing.TB, bunDB *bun.DB) *bunfixture { tb.Helper() // ensure that models are registered bunDB.RegisterModel(&bunmodel.Group{}, &bunmodel.Monitor{}) fixture := dbfixture.New(bunDB) err := fixture.Load(context.Background(), os.DirFS("testdata"), "fixture.yml") require.NoError(tb, err, "couldn't load fixtures") return &bunfixture{fixture} } func (f *bunfixture) group(tb testing.TB, id string) domain.GroupWithMonitors { tb.Helper() row, err := f.Row("Group." + id) require.NoError(tb, err) g, ok := row.(*bunmodel.Group) require.True(tb, ok) return g.ToDomain() } func (f *bunfixture) groups(tb testing.TB) []domain.GroupWithMonitors { tb.Helper() //nolint:lll ids := []string{"group-1-server-1", "group-2-server-1", "group-1-server-2", "group-2-server-2", "group-3-server-1", "group-3-server-2"} groups := make([]domain.GroupWithMonitors, 0, len(ids)) for _, id := range ids { groups = append(groups, f.group(tb, id)) } return groups } func (f *bunfixture) monitor(tb testing.TB, id string) domain.Monitor { tb.Helper() row, err := f.Row("Monitor." + id) require.NoError(tb, err) m, ok := row.(*bunmodel.Monitor) require.True(tb, ok) return m.ToDomain() } func generateSchema() string { return strings.TrimFunc(strings.ReplaceAll(uuid.NewString(), "-", "_"), unicode.IsNumber) } func retry(op func() error) error { bo := backoff.NewExponentialBackOff() bo.MaxInterval = time.Second * 5 bo.MaxElapsedTime = 30 * time.Second if err := backoff.Retry(op, bo); err != nil { if bo.NextBackOff() == backoff.Stop { return errors.New("reached retry deadline") } return err } return nil }