mirror of https://github.com/jackc/pgx.git
235 lines
5.3 KiB
Go
235 lines
5.3 KiB
Go
package pool_test
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/jackc/pgx/pool"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestConnect(t *testing.T) {
|
|
pool, err := pool.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE"))
|
|
require.NoError(t, err)
|
|
pool.Close()
|
|
}
|
|
|
|
func TestConnectCancel(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
pool, err := pool.Connect(ctx, os.Getenv("PGX_TEST_DATABASE"))
|
|
assert.Nil(t, pool)
|
|
assert.Equal(t, context.Canceled, err)
|
|
}
|
|
|
|
func TestPoolAcquireAndConnRelease(t *testing.T) {
|
|
pool, err := pool.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE"))
|
|
require.NoError(t, err)
|
|
defer pool.Close()
|
|
|
|
c, err := pool.Acquire(context.Background())
|
|
require.NoError(t, err)
|
|
c.Release()
|
|
}
|
|
|
|
func TestPoolExec(t *testing.T) {
|
|
pool, err := pool.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE"))
|
|
require.NoError(t, err)
|
|
defer pool.Close()
|
|
|
|
testExec(t, pool)
|
|
}
|
|
|
|
func TestPoolQuery(t *testing.T) {
|
|
pool, err := pool.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE"))
|
|
require.NoError(t, err)
|
|
defer pool.Close()
|
|
|
|
// Test common usage
|
|
testQuery(t, pool)
|
|
waitForReleaseToComplete()
|
|
|
|
// Test expected pool behavior
|
|
rows, err := pool.Query("select generate_series(1,$1)", 10)
|
|
require.NoError(t, err)
|
|
|
|
stats := pool.Stat()
|
|
assert.Equal(t, 1, stats.AcquiredConns())
|
|
assert.Equal(t, 1, stats.TotalConns())
|
|
|
|
rows.Close()
|
|
assert.NoError(t, rows.Err())
|
|
waitForReleaseToComplete()
|
|
|
|
stats = pool.Stat()
|
|
assert.Equal(t, 0, stats.AcquiredConns())
|
|
assert.Equal(t, 1, stats.TotalConns())
|
|
|
|
}
|
|
|
|
func TestPoolQueryEx(t *testing.T) {
|
|
pool, err := pool.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE"))
|
|
require.NoError(t, err)
|
|
defer pool.Close()
|
|
|
|
// Test common usage
|
|
testQueryEx(t, pool)
|
|
waitForReleaseToComplete()
|
|
|
|
// Test expected pool behavior
|
|
|
|
rows, err := pool.QueryEx(context.Background(), "select generate_series(1,$1)", nil, 10)
|
|
require.NoError(t, err)
|
|
|
|
stats := pool.Stat()
|
|
assert.Equal(t, 1, stats.AcquiredConns())
|
|
assert.Equal(t, 1, stats.TotalConns())
|
|
|
|
rows.Close()
|
|
assert.NoError(t, rows.Err())
|
|
waitForReleaseToComplete()
|
|
|
|
stats = pool.Stat()
|
|
assert.Equal(t, 0, stats.AcquiredConns())
|
|
assert.Equal(t, 1, stats.TotalConns())
|
|
}
|
|
|
|
func TestPoolQueryRow(t *testing.T) {
|
|
pool, err := pool.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE"))
|
|
require.NoError(t, err)
|
|
defer pool.Close()
|
|
|
|
testQueryRow(t, pool)
|
|
waitForReleaseToComplete()
|
|
|
|
stats := pool.Stat()
|
|
assert.Equal(t, 0, stats.AcquiredConns())
|
|
assert.Equal(t, 1, stats.TotalConns())
|
|
}
|
|
|
|
func TestPoolQueryRowEx(t *testing.T) {
|
|
pool, err := pool.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE"))
|
|
require.NoError(t, err)
|
|
defer pool.Close()
|
|
|
|
testQueryRowEx(t, pool)
|
|
waitForReleaseToComplete()
|
|
|
|
stats := pool.Stat()
|
|
assert.Equal(t, 0, stats.AcquiredConns())
|
|
assert.Equal(t, 1, stats.TotalConns())
|
|
}
|
|
|
|
func TestConnReleaseRollsBackFailedTransaction(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
pool, err := pool.Connect(ctx, os.Getenv("PGX_TEST_DATABASE"))
|
|
require.NoError(t, err)
|
|
defer pool.Close()
|
|
|
|
c, err := pool.Acquire(ctx)
|
|
require.NoError(t, err)
|
|
|
|
pid := c.Conn().PID()
|
|
|
|
assert.Equal(t, byte('I'), c.Conn().TxStatus())
|
|
|
|
_, err = c.Exec(ctx, "begin")
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, byte('T'), c.Conn().TxStatus())
|
|
|
|
_, err = c.Exec(ctx, "selct")
|
|
assert.Error(t, err)
|
|
|
|
assert.Equal(t, byte('E'), c.Conn().TxStatus())
|
|
|
|
c.Release()
|
|
waitForReleaseToComplete()
|
|
|
|
c, err = pool.Acquire(ctx)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, pid, c.Conn().PID())
|
|
assert.Equal(t, byte('I'), c.Conn().TxStatus())
|
|
|
|
c.Release()
|
|
}
|
|
|
|
func TestConnReleaseRollsBackInTransaction(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
pool, err := pool.Connect(ctx, os.Getenv("PGX_TEST_DATABASE"))
|
|
require.NoError(t, err)
|
|
defer pool.Close()
|
|
|
|
c, err := pool.Acquire(ctx)
|
|
require.NoError(t, err)
|
|
|
|
pid := c.Conn().PID()
|
|
|
|
assert.Equal(t, byte('I'), c.Conn().TxStatus())
|
|
|
|
_, err = c.Exec(ctx, "begin")
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, byte('T'), c.Conn().TxStatus())
|
|
|
|
c.Release()
|
|
waitForReleaseToComplete()
|
|
|
|
c, err = pool.Acquire(ctx)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, pid, c.Conn().PID())
|
|
assert.Equal(t, byte('I'), c.Conn().TxStatus())
|
|
|
|
c.Release()
|
|
}
|
|
|
|
func TestConnReleaseDestroysClosedConn(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
pool, err := pool.Connect(ctx, os.Getenv("PGX_TEST_DATABASE"))
|
|
require.NoError(t, err)
|
|
defer pool.Close()
|
|
|
|
c, err := pool.Acquire(ctx)
|
|
require.NoError(t, err)
|
|
|
|
c.Conn().Close()
|
|
|
|
assert.Equal(t, 1, pool.Stat().TotalConns())
|
|
|
|
c.Release()
|
|
waitForReleaseToComplete()
|
|
|
|
assert.Equal(t, 0, pool.Stat().TotalConns())
|
|
}
|
|
|
|
func TestConnPoolQueryConcurrentLoad(t *testing.T) {
|
|
pool, err := pool.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE"))
|
|
require.NoError(t, err)
|
|
defer pool.Close()
|
|
|
|
n := 100
|
|
done := make(chan bool)
|
|
|
|
for i := 0; i < n; i++ {
|
|
go func() {
|
|
defer func() { done <- true }()
|
|
testQuery(t, pool)
|
|
testQueryEx(t, pool)
|
|
testQueryRow(t, pool)
|
|
testQueryRowEx(t, pool)
|
|
}()
|
|
}
|
|
|
|
for i := 0; i < n; i++ {
|
|
<-done
|
|
}
|
|
}
|