diff --git a/build.docker b/build.docker index 1bd7e70..fdec512 100644 --- a/build.docker +++ b/build.docker @@ -1,7 +1,7 @@ FROM golang:1.17 RUN apt-get update && apt-get install -y \ - rsync libssl-dev \ + rsync libssl-dev postgresql \ && rm -rf /var/lib/apt/lists/* RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.44.0 diff --git a/pgfixture/pg.go b/pgfixture/pg.go new file mode 100644 index 0000000..c4f3622 --- /dev/null +++ b/pgfixture/pg.go @@ -0,0 +1,63 @@ +package pgfixture + +import ( + "fmt" + "os" + "os/exec" + "testing" + "time" +) + +func Start(t *testing.T) string { + pgconn, ok := os.LookupEnv("PGCONN") + if ok { + t.Logf("using external database: PGCONN=%s", pgconn) + return pgconn + } + + _, err := exec.LookPath("initdb") + if err != nil { + t.Fatalf("initdb binary not found; is postgres installed?") + } + + _, err = exec.LookPath("postgres") + if err != nil { + t.Fatalf("postgres binary not found; is postgres installed?") + } + + pgdata := t.TempDir() + + cmd := exec.Command("initdb", "-N", "-D", pgdata) + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + if err := cmd.Run(); err != nil { + t.Fatalf("initdb failed: %v", err) + } + + pgrun := t.TempDir() + + cmd = exec.Command("postgres", "-D", pgdata, "-k", pgrun, "-F") + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + if err := cmd.Start(); err != nil { + t.Fatalf("postgres failed: %v", err) + } + + finished := make(chan error, 1) + go func() { + finished <- cmd.Wait() + }() + + select { + case <-finished: + t.Fatalf("postgres server terminated: %v", err) + + case <-time.After(time.Second / 2): + } + + t.Cleanup(func() { + _ = cmd.Process.Kill() + }) + + return fmt.Sprintf("host=%s database=postgres", pgrun) +} diff --git a/pgfixture/pg_test.go b/pgfixture/pg_test.go new file mode 100644 index 0000000..e2d5612 --- /dev/null +++ b/pgfixture/pg_test.go @@ -0,0 +1,34 @@ +package pgfixture_test + +import ( + "context" + "testing" + + "github.com/jackc/pgx/v4" + "github.com/stretchr/testify/require" + "gitlab.com/slon/shad-go/pgfixture" +) + +func TestLocalPostgres(t *testing.T) { + dsn := pgfixture.Start(t) + ctx := context.Background() + + conn, err := pgx.Connect(ctx, dsn) + require.NoError(t, err) + require.NoError(t, conn.Ping(ctx)) + + _, err = conn.Exec(ctx, `CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT);`) + require.NoError(t, err) + + _, err = conn.Exec(ctx, `INSERT INTO users (name) VALUES ($1);`, "Fedor") + require.NoError(t, err) + + row := conn.QueryRow(ctx, `SELECT id, name FROM users LIMIT 1;`) + + var id int + var name string + + require.NoError(t, row.Scan(&id, &name)) + require.Equal(t, 1, id) + require.Equal(t, name, "Fedor") +}