package repo_test import ( "context" "database/sql" "errors" "os" "reflect" "testing" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/stdlib" _ "github.com/mattn/go-sqlite3" "code.uint32.ru/tiny/repo" ) type My struct { A string B int } func TestSqlite3(t *testing.T) { db, err := sql.Open("sqlite3", "test.db") if err != nil { t.Fatal(err) } defer os.Remove("test.db") defer db.Close() ctx := context.Background() dotest(ctx, db, t) } func TestPGX(t *testing.T) { dsn, ok := os.LookupEnv("PGX_DSN") if !ok { t.SkipNow() } conf, err := pgx.ParseConfig(dsn) if err != nil { t.Fatal(err) } conf.DefaultQueryExecMode = pgx.QueryExecModeSimpleProtocol conf.DescriptionCacheCapacity = 0 conf.StatementCacheCapacity = 0 db, err := sql.Open("pgx", stdlib.RegisterConnConfig(conf)) if err != nil { t.Fatal(err) } defer db.Close() ctx := context.Background() dotest(ctx, db, t) } func TestOpenOrCreateFails(t *testing.T) { ctx := context.Background() if _, err := repo.OpenOrCreate[My](ctx, nil, ""); err == nil { t.Errorf("must fail on empty tablename") } if _, err := repo.OpenOrCreate[My](ctx, nil, "test"); err == nil { t.Errorf("must fail on nil DB instance") } } func dotest(ctx context.Context, db *sql.DB, t *testing.T) { r, err := repo.OpenOrCreate[My](ctx, db, "my_test") if err != nil { t.Fatal(err) } testID := "watermelon" incorrectID := "surelynonexistant" one := &My{ A: "hello", B: 42, } if err := r.Create(ctx, testID, one); err != nil { t.Fatal(err) } if err := r.Create(ctx, testID, one); err == nil { // can not insert with same id t.Errorf("insert of the same id dows not fail") } two, err := r.Read(ctx, testID) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(one, two) { t.Errorf("instances are not equal") t.Logf("%+v", one) t.Logf("%+v", two) } one.B = 13 if err := r.Update(ctx, testID, one); err != nil { t.Error(err) } two, err = r.Read(ctx, testID) if err != nil { t.Error(err) } if !reflect.DeepEqual(one, two) { t.Errorf("instances are not equal") t.Logf("%+v", one) t.Logf("%+v", two) } if err := r.Delete(ctx, testID); err != nil { t.Error(err) } if err := r.Delete(ctx, testID); err == nil || !errors.Is(err, repo.ErrNotFound) { // can only delete once t.Errorf("incorrect error on delete for non-existing id, want: %v, have: %v", repo.ErrNotFound, err) } if err := r.Purge(ctx, testID); err != nil { t.Error(err) } if err := r.Purge(ctx, testID); err == nil || !errors.Is(err, repo.ErrNotFound) { // can only purge once t.Errorf("incorrect error on delete for non-existing id, want: %v, have: %v", repo.ErrNotFound, err) } if _, err := r.Read(ctx, incorrectID); err == nil || !errors.Is(err, repo.ErrNotFound) { t.Errorf("incorrect error on read for non-existing id, want: %v, have: %v", repo.ErrNotFound, err) } if err := r.Update(ctx, incorrectID, one); err == nil || !errors.Is(err, repo.ErrNotFound) { t.Errorf("incorrect error on update for non-existing id, want: %v, have: %v", repo.ErrNotFound, err) } if err := r.Delete(ctx, incorrectID); err == nil || !errors.Is(err, repo.ErrNotFound) { t.Errorf("incorrect error on delete for non-existing id, want: %v, have: %v", repo.ErrNotFound, err) } if err := r.Purge(ctx, incorrectID); err == nil || !errors.Is(err, repo.ErrNotFound) { t.Errorf("incorrect error on purge for non-existing id, want: %v, have: %v", repo.ErrNotFound, err) } }