mirror of
https://github.com/gofiber/storage.git
synced 2025-10-05 16:48:25 +08:00

This is not relevant for this PR, as Ryuk is responsible for terminating containers after the test session finishes
313 lines
6.4 KiB
Go
313 lines
6.4 KiB
Go
package postgres
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/testcontainers/testcontainers-go"
|
|
"github.com/testcontainers/testcontainers-go/modules/postgres"
|
|
"github.com/testcontainers/testcontainers-go/wait"
|
|
)
|
|
|
|
const (
|
|
// postgresImage is the default image used for running Postgres in tests.
|
|
postgresImage = "docker.io/postgres:16-alpine"
|
|
postgresImageEnvVar string = "TEST_POSTGRES_IMAGE"
|
|
postgresUser string = "username"
|
|
postgresPass string = "p4ssw0rd"
|
|
postgresDatabase string = "fiber"
|
|
)
|
|
|
|
func newTestStore(t testing.TB) (*Storage, error) {
|
|
t.Helper()
|
|
|
|
ctx := context.Background()
|
|
|
|
img := postgresImage
|
|
if imgFromEnv := os.Getenv(postgresImageEnvVar); imgFromEnv != "" {
|
|
img = imgFromEnv
|
|
}
|
|
|
|
c, err := postgres.Run(ctx, img,
|
|
postgres.WithUsername(postgresUser),
|
|
postgres.WithPassword(postgresPass),
|
|
postgres.WithDatabase(postgresDatabase),
|
|
testcontainers.WithWaitStrategy(
|
|
// First, we wait for the container to log readiness twice.
|
|
// This is because it will restart itself after the first startup.
|
|
wait.ForLog("database system is ready to accept connections").WithOccurrence(2),
|
|
),
|
|
)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
if c != nil {
|
|
require.NoError(t, c.Terminate(ctx))
|
|
}
|
|
})
|
|
|
|
conn, err := c.ConnectionString(ctx, "sslmode=disable")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return New(Config{
|
|
ConnectionURI: conn,
|
|
Reset: true,
|
|
}), nil
|
|
}
|
|
|
|
func Test_Postgres_Set(t *testing.T) {
|
|
var (
|
|
key = "john"
|
|
val = []byte("doe")
|
|
)
|
|
|
|
testStore, err := newTestStore(t)
|
|
require.NoError(t, err)
|
|
defer testStore.Close()
|
|
|
|
err = testStore.Set(key, val, 0)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func Test_Postgres_Set_Override(t *testing.T) {
|
|
var (
|
|
key = "john"
|
|
val = []byte("doe")
|
|
)
|
|
|
|
testStore, err := newTestStore(t)
|
|
require.NoError(t, err)
|
|
defer testStore.Close()
|
|
|
|
err = testStore.Set(key, val, 0)
|
|
require.NoError(t, err)
|
|
|
|
err = testStore.Set(key, val, 0)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func Test_Postgres_Get(t *testing.T) {
|
|
var (
|
|
key = "john"
|
|
val = []byte("doe")
|
|
)
|
|
|
|
testStore, err := newTestStore(t)
|
|
require.NoError(t, err)
|
|
defer testStore.Close()
|
|
|
|
err = testStore.Set(key, val, 0)
|
|
require.NoError(t, err)
|
|
|
|
result, err := testStore.Get(key)
|
|
require.NoError(t, err)
|
|
require.Equal(t, val, result)
|
|
}
|
|
|
|
func Test_Postgres_Set_Expiration(t *testing.T) {
|
|
var (
|
|
key = "john"
|
|
val = []byte("doe")
|
|
exp = 1 * time.Second
|
|
)
|
|
|
|
testStore, err := newTestStore(t)
|
|
require.NoError(t, err)
|
|
defer testStore.Close()
|
|
|
|
err = testStore.Set(key, val, exp)
|
|
require.NoError(t, err)
|
|
|
|
time.Sleep(1100 * time.Millisecond)
|
|
}
|
|
|
|
func Test_Postgres_Get_Expired(t *testing.T) {
|
|
key := "john"
|
|
|
|
testStore, err := newTestStore(t)
|
|
require.NoError(t, err)
|
|
defer testStore.Close()
|
|
|
|
result, err := testStore.Get(key)
|
|
require.NoError(t, err)
|
|
require.Zero(t, len(result))
|
|
}
|
|
|
|
func Test_Postgres_Get_NotExist(t *testing.T) {
|
|
testStore, err := newTestStore(t)
|
|
require.NoError(t, err)
|
|
defer testStore.Close()
|
|
|
|
result, err := testStore.Get("notexist")
|
|
require.NoError(t, err)
|
|
require.Zero(t, len(result))
|
|
}
|
|
|
|
func Test_Postgres_Delete(t *testing.T) {
|
|
var (
|
|
key = "john"
|
|
val = []byte("doe")
|
|
)
|
|
|
|
testStore, err := newTestStore(t)
|
|
require.NoError(t, err)
|
|
defer testStore.Close()
|
|
|
|
err = testStore.Set(key, val, 0)
|
|
require.NoError(t, err)
|
|
|
|
err = testStore.Delete(key)
|
|
require.NoError(t, err)
|
|
|
|
result, err := testStore.Get(key)
|
|
require.NoError(t, err)
|
|
require.Zero(t, len(result))
|
|
}
|
|
|
|
func Test_Postgres_Reset(t *testing.T) {
|
|
val := []byte("doe")
|
|
|
|
testStore, err := newTestStore(t)
|
|
require.NoError(t, err)
|
|
defer testStore.Close()
|
|
|
|
err = testStore.Set("john1", val, 0)
|
|
require.NoError(t, err)
|
|
|
|
err = testStore.Set("john2", val, 0)
|
|
require.NoError(t, err)
|
|
|
|
err = testStore.Reset()
|
|
require.NoError(t, err)
|
|
|
|
result, err := testStore.Get("john1")
|
|
require.NoError(t, err)
|
|
require.Zero(t, len(result))
|
|
|
|
result, err = testStore.Get("john2")
|
|
require.NoError(t, err)
|
|
require.Zero(t, len(result))
|
|
}
|
|
|
|
func Test_Postgres_GC(t *testing.T) {
|
|
testVal := []byte("doe")
|
|
|
|
testStore, err := newTestStore(t)
|
|
require.NoError(t, err)
|
|
defer testStore.Close()
|
|
|
|
// This key should expire
|
|
err = testStore.Set("john", testVal, time.Nanosecond)
|
|
require.NoError(t, err)
|
|
|
|
testStore.gc(time.Now())
|
|
row := testStore.db.QueryRow(context.Background(), testStore.sqlSelect, "john")
|
|
err = row.Scan(nil, nil)
|
|
require.Equal(t, pgx.ErrNoRows, err)
|
|
|
|
// This key should not expire
|
|
err = testStore.Set("john", testVal, 0)
|
|
require.NoError(t, err)
|
|
|
|
testStore.gc(time.Now())
|
|
val, err := testStore.Get("john")
|
|
require.NoError(t, err)
|
|
require.Equal(t, testVal, val)
|
|
}
|
|
|
|
func Test_Postgres_Non_UTF8(t *testing.T) {
|
|
val := []byte("0xF5")
|
|
|
|
testStore, err := newTestStore(t)
|
|
require.NoError(t, err)
|
|
defer testStore.Close()
|
|
|
|
err = testStore.Set("0xF6", val, 0)
|
|
require.NoError(t, err)
|
|
|
|
result, err := testStore.Get("0xF6")
|
|
require.NoError(t, err)
|
|
require.Equal(t, val, result)
|
|
}
|
|
|
|
func Test_SslRequiredMode(t *testing.T) {
|
|
defer func() {
|
|
if recover() == nil {
|
|
require.Equalf(t, true, nil, "Connection was established with a `require`")
|
|
}
|
|
}()
|
|
_ = New(Config{
|
|
Reset: true,
|
|
})
|
|
}
|
|
|
|
func Test_Postgres_Conn(t *testing.T) {
|
|
testStore, err := newTestStore(t)
|
|
require.NoError(t, err)
|
|
defer testStore.Close()
|
|
|
|
require.True(t, testStore.Conn() != nil)
|
|
}
|
|
|
|
func Test_Postgres_Close(t *testing.T) {
|
|
testStore, err := newTestStore(t)
|
|
require.NoError(t, err)
|
|
defer testStore.Close()
|
|
|
|
require.Nil(t, testStore.Close())
|
|
}
|
|
|
|
func Benchmark_Postgres_Set(b *testing.B) {
|
|
testStore, err := newTestStore(b)
|
|
require.NoError(b, err)
|
|
defer testStore.Close()
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
err = testStore.Set("john", []byte("doe"), 0)
|
|
}
|
|
|
|
require.NoError(b, err)
|
|
}
|
|
|
|
func Benchmark_Postgres_Get(b *testing.B) {
|
|
testStore, err := newTestStore(b)
|
|
require.NoError(b, err)
|
|
defer testStore.Close()
|
|
|
|
err = testStore.Set("john", []byte("doe"), 0)
|
|
require.NoError(b, err)
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, err = testStore.Get("john")
|
|
}
|
|
|
|
require.NoError(b, err)
|
|
}
|
|
|
|
func Benchmark_Postgres_SetAndDelete(b *testing.B) {
|
|
testStore, err := newTestStore(b)
|
|
require.NoError(b, err)
|
|
defer testStore.Close()
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_ = testStore.Set("john", []byte("doe"), 0)
|
|
err = testStore.Delete("john")
|
|
}
|
|
|
|
require.NoError(b, err)
|
|
}
|