mirror of
				https://github.com/gofiber/storage.git
				synced 2025-10-31 11:46:32 +08:00 
			
		
		
		
	Merge branch 'main' into add-withcontext
* main: (168 commits) chore: read redis image for ruedis chore: align ruedis expiration test with redis chore: skip cluster tests chore: align valkey expiration test with redis chore: refine message fix: reuse valkey container in benchmarks chore: pass the redis-like image explicitly in tests fix: missing eval of redis image from env var chore: proper parallel layout chore: add integration tests to the redis helper module chore: verify mtls properly in tests chore(deps): bump github.com/aws/aws-sdk-go-v2/feature/s3/manager in /s3 chore(deps): bump github.com/aws/aws-sdk-go-v2/service/s3 in /s3 chore(deps): bump github.com/ClickHouse/clickhouse-go/v2 in /clickhouse chore(deps): bump github.com/minio/minio-go/v7 in /minio chore(deps): bump github.com/valkey-io/valkey-go in /valkey chore(deps): bump github.com/jackc/pgx/v5 in /postgres chore: add tests for the helper module chore: make sure the client gets the variable locally fix(coherence): set coherence log level to ERROR in benchmarks ...
This commit is contained in:
		| @@ -2,17 +2,52 @@ package rueidis | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/tls" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/stretchr/testify/require" | ||||
|  | ||||
| 	testredis "github.com/gofiber/storage/testhelpers/redis" | ||||
| ) | ||||
|  | ||||
| var testStore = New(Config{ | ||||
| 	Reset: true, | ||||
| }) | ||||
| const ( | ||||
| 	// redisImage is the default image used for running Redis in tests. | ||||
| 	redisImage       = "docker.io/redis:7" | ||||
| 	redisImageEnvVar = "TEST_REDIS_IMAGE" | ||||
| ) | ||||
|  | ||||
| // newConfigFromContainer creates a Rueidis configuration using Testcontainers. | ||||
| // It configures the container based on the provided options and returns a Config | ||||
| // that can be used to connect to the container. | ||||
| // The container is cleaned up when the test completes. | ||||
| func newConfigFromContainer(t testing.TB, opts ...testredis.Option) Config { | ||||
| 	t.Helper() | ||||
|  | ||||
| 	img := redisImage | ||||
| 	if imgFromEnv := os.Getenv(redisImageEnvVar); imgFromEnv != "" { | ||||
| 		img = imgFromEnv | ||||
| 	} | ||||
|  | ||||
| 	redisCtr := testredis.Start(t, img, opts...) | ||||
|  | ||||
| 	cfg := Config{ | ||||
| 		Reset:       true, | ||||
| 		TLSConfig:   redisCtr.TLSConfig, | ||||
| 		InitAddress: redisCtr.Addrs, | ||||
| 		URL:         redisCtr.URL, | ||||
| 	} | ||||
|  | ||||
| 	return cfg | ||||
| } | ||||
|  | ||||
| // newTestStore creates a new Rueidis storage instance backed by Testcontainers. | ||||
| // It configures the container based on the provided options and returns a Storage | ||||
| // instance connected to the container. The caller is responsible for calling | ||||
| // Close() on the returned Storage when done. | ||||
| func newTestStore(t testing.TB, opts ...testredis.Option) *Storage { | ||||
| 	return New(newConfigFromContainer(t, opts...)) | ||||
| } | ||||
|  | ||||
| func Test_Rueidis_Set(t *testing.T) { | ||||
| 	var ( | ||||
| @@ -20,19 +55,22 @@ func Test_Rueidis_Set(t *testing.T) { | ||||
| 		val = []byte("doe") | ||||
| 	) | ||||
|  | ||||
| 	testStore := newTestStore(t) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	err := testStore.Set(key, val, 0) | ||||
| 	require.NoError(t, err) | ||||
| } | ||||
|  | ||||
| func Test_Rueidis_SetWithContext(t *testing.T) { | ||||
| 	var ( | ||||
| 		testStore = New(Config{ | ||||
| 			Reset: true, | ||||
| 		}) | ||||
| 		key = "john" | ||||
| 		val = []byte("doe") | ||||
| 	) | ||||
|  | ||||
| 	testStore := newTestStore(t) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	ctx, cancel := context.WithCancel(context.Background()) | ||||
| 	cancel() | ||||
|  | ||||
| @@ -46,6 +84,9 @@ func Test_Rueidis_Set_Override(t *testing.T) { | ||||
| 		val = []byte("doe") | ||||
| 	) | ||||
|  | ||||
| 	testStore := newTestStore(t) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	err := testStore.Set(key, val, 0) | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| @@ -59,6 +100,9 @@ func Test_Rueidis_Get(t *testing.T) { | ||||
| 		val = []byte("doe") | ||||
| 	) | ||||
|  | ||||
| 	testStore := newTestStore(t) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	err := testStore.Set(key, val, 0) | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| @@ -69,13 +113,13 @@ func Test_Rueidis_Get(t *testing.T) { | ||||
|  | ||||
| func Test_Rueidis_GetWithContext(t *testing.T) { | ||||
| 	var ( | ||||
| 		testStore = New(Config{ | ||||
| 			Reset: true, | ||||
| 		}) | ||||
| 		key = "john" | ||||
| 		val = []byte("doe") | ||||
| 	) | ||||
|  | ||||
| 	testStore := newTestStore(t) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	err := testStore.Set(key, val, 0) | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| @@ -87,21 +131,20 @@ func Test_Rueidis_GetWithContext(t *testing.T) { | ||||
| 	require.Zero(t, len(result)) | ||||
| } | ||||
|  | ||||
| func Test_Rueidis_Set_Expiration(t *testing.T) { | ||||
| func Test_Rueidis_Expiration(t *testing.T) { | ||||
| 	var ( | ||||
| 		key = "john" | ||||
| 		val = []byte("doe") | ||||
| 		exp = 1 * time.Second | ||||
| 	) | ||||
|  | ||||
| 	testStore := newTestStore(t) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	err := testStore.Set(key, val, exp) | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| 	time.Sleep(1100 * time.Millisecond) | ||||
| } | ||||
|  | ||||
| func Test_Rueidis_Get_Expired(t *testing.T) { | ||||
| 	key := "john" | ||||
|  | ||||
| 	result, err := testStore.Get(key) | ||||
| 	require.NoError(t, err) | ||||
| @@ -109,6 +152,9 @@ func Test_Rueidis_Get_Expired(t *testing.T) { | ||||
| } | ||||
|  | ||||
| func Test_Rueidis_Get_NotExist(t *testing.T) { | ||||
| 	testStore := newTestStore(t) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	result, err := testStore.Get("notexist") | ||||
| 	require.NoError(t, err) | ||||
| 	require.Zero(t, len(result)) | ||||
| @@ -120,6 +166,9 @@ func Test_Rueidis_Delete(t *testing.T) { | ||||
| 		val = []byte("doe") | ||||
| 	) | ||||
|  | ||||
| 	testStore := newTestStore(t) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	err := testStore.Set(key, val, 0) | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| @@ -133,13 +182,13 @@ func Test_Rueidis_Delete(t *testing.T) { | ||||
|  | ||||
| func Test_Rueidis_DeleteWithContext(t *testing.T) { | ||||
| 	var ( | ||||
| 		testStore = New(Config{ | ||||
| 			Reset: true, | ||||
| 		}) | ||||
| 		key = "john" | ||||
| 		val = []byte("doe") | ||||
| 	) | ||||
|  | ||||
| 	testStore := newTestStore(t) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	err := testStore.Set(key, val, 0) | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| @@ -157,6 +206,9 @@ func Test_Rueidis_DeleteWithContext(t *testing.T) { | ||||
| func Test_Rueidis_Reset(t *testing.T) { | ||||
| 	val := []byte("doe") | ||||
|  | ||||
| 	testStore := newTestStore(t) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	err := testStore.Set("john1", val, 0) | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| @@ -176,11 +228,11 @@ func Test_Rueidis_Reset(t *testing.T) { | ||||
| } | ||||
|  | ||||
| func Test_Rueidis_ResetWithContext(t *testing.T) { | ||||
| 	testStore := New(Config{ | ||||
| 		Reset: true, | ||||
| 	}) | ||||
| 	val := []byte("doe") | ||||
|  | ||||
| 	testStore := newTestStore(t) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	err := testStore.Set("john1", val, 0) | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| @@ -203,99 +255,123 @@ func Test_Rueidis_ResetWithContext(t *testing.T) { | ||||
| } | ||||
|  | ||||
| func Test_Rueidis_Close(t *testing.T) { | ||||
| 	testStore := newTestStore(t) | ||||
| 	require.Nil(t, testStore.Close()) | ||||
| } | ||||
|  | ||||
| func Test_Rueidis_Conn(t *testing.T) { | ||||
| 	testStore := newTestStore(t) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	require.True(t, testStore.Conn() != nil) | ||||
| } | ||||
|  | ||||
| func Test_Rueidis_WithTLS(t *testing.T) { | ||||
| 	cer, err := tls.LoadX509KeyPair("/home/runner/work/storage/storage/tls/client.crt", "/home/runner/work/storage/storage/tls/client.key") | ||||
| 	if err != nil { | ||||
| 		log.Println(err) | ||||
| 	testFn := func(t *testing.T, secureURL bool, mtlsDisabled bool) { | ||||
| 		t.Helper() | ||||
|  | ||||
| 		testStore := newTestStore(t, testredis.WithTLS(secureURL, mtlsDisabled)) | ||||
| 		defer testStore.Close() | ||||
|  | ||||
| 		var ( | ||||
| 			key = "clark" | ||||
| 			val = []byte("kent") | ||||
| 		) | ||||
|  | ||||
| 		err := testStore.Set(key, val, 0) | ||||
| 		require.NoError(t, err) | ||||
|  | ||||
| 		result, err := testStore.Get(key) | ||||
| 		require.NoError(t, err) | ||||
| 		require.Equal(t, val, result) | ||||
|  | ||||
| 		err = testStore.Delete(key) | ||||
| 		require.NoError(t, err) | ||||
| 	} | ||||
| 	tlsCfg := &tls.Config{ | ||||
| 		MinVersion:         tls.VersionTLS12, | ||||
| 		CurvePreferences:   []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256}, | ||||
| 		InsecureSkipVerify: true, | ||||
| 		Certificates:       []tls.Certificate{cer}, | ||||
| 		CipherSuites: []uint16{ | ||||
| 			tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, | ||||
| 			tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, | ||||
| 			tls.TLS_RSA_WITH_AES_256_GCM_SHA384, | ||||
| 			tls.TLS_RSA_WITH_AES_256_CBC_SHA, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	storeTLS := New(Config{ | ||||
| 		InitAddress: []string{"localhost:6380"}, | ||||
| 		TLSConfig:   tlsCfg, | ||||
| 	t.Run("insecure-url/mtls-disabled", func(t *testing.T) { | ||||
| 		testFn(t, false, true) | ||||
| 	}) | ||||
|  | ||||
| 	var ( | ||||
| 		key = "clark" | ||||
| 		val = []byte("kent") | ||||
| 	) | ||||
| 	t.Run("insecure-url/mtls-enabled", func(t *testing.T) { | ||||
| 		testFn(t, false, false) | ||||
| 	}) | ||||
|  | ||||
| 	err = storeTLS.Set(key, val, 0) | ||||
| 	require.NoError(t, err) | ||||
| 	t.Run("secure-url/mtls-disabled", func(t *testing.T) { | ||||
| 		testFn(t, true, true) | ||||
| 	}) | ||||
|  | ||||
| 	result, err := storeTLS.Get(key) | ||||
| 	require.NoError(t, err) | ||||
| 	require.Equal(t, val, result) | ||||
|  | ||||
| 	err = storeTLS.Delete(key) | ||||
| 	require.NoError(t, err) | ||||
| 	require.Nil(t, storeTLS.Close()) | ||||
| 	t.Run("secure-url/mtls-enabled", func(t *testing.T) { | ||||
| 		testFn(t, true, false) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func Test_Rueidis_With_HostPort(t *testing.T) { | ||||
| 	store := New(Config{ | ||||
| 		InitAddress: []string{"localhost:6379"}, | ||||
| 	}) | ||||
| 	testStore := newTestStore(t, testredis.WithHostPort()) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	var ( | ||||
| 		key = "bruce" | ||||
| 		val = []byte("wayne") | ||||
| 	) | ||||
|  | ||||
| 	err := store.Set(key, val, 0) | ||||
| 	err := testStore.Set(key, val, 0) | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| 	result, err := store.Get(key) | ||||
| 	result, err := testStore.Get(key) | ||||
| 	require.NoError(t, err) | ||||
| 	require.Equal(t, val, result) | ||||
|  | ||||
| 	err = store.Delete(key) | ||||
| 	err = testStore.Delete(key) | ||||
| 	require.NoError(t, err) | ||||
| 	require.Nil(t, store.Close()) | ||||
| 	require.Nil(t, testStore.Close()) | ||||
| } | ||||
|  | ||||
| func Test_Rueidis_With_URL(t *testing.T) { | ||||
| 	store := New(Config{ | ||||
| 		URL: "redis://localhost:6379", | ||||
| 	}) | ||||
| 	testStore := newTestStore(t, testredis.WithAddress(), testredis.WithURL(false)) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	var ( | ||||
| 		key = "bruce" | ||||
| 		val = []byte("wayne") | ||||
| 	) | ||||
|  | ||||
| 	err := store.Set(key, val, 0) | ||||
| 	err := testStore.Set(key, val, 0) | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| 	result, err := store.Get(key) | ||||
| 	result, err := testStore.Get(key) | ||||
| 	require.NoError(t, err) | ||||
| 	require.Equal(t, val, result) | ||||
|  | ||||
| 	err = store.Delete(key) | ||||
| 	err = testStore.Delete(key) | ||||
| 	require.NoError(t, err) | ||||
| 	require.Nil(t, store.Close()) | ||||
| 	require.Nil(t, testStore.Close()) | ||||
| } | ||||
|  | ||||
| func Test_Rueidis_With_TLS_URL(t *testing.T) { | ||||
| 	testStore := newTestStore(t, testredis.WithTLS(true, false), testredis.WithAddress(), testredis.WithURL(true)) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	var ( | ||||
| 		key = "bruce" | ||||
| 		val = []byte("wayne") | ||||
| 	) | ||||
|  | ||||
| 	err := testStore.Set(key, val, 0) | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| 	result, err := testStore.Get(key) | ||||
| 	require.NoError(t, err) | ||||
| 	require.Equal(t, val, result) | ||||
|  | ||||
| 	err = testStore.Delete(key) | ||||
| 	require.NoError(t, err) | ||||
| 	require.Nil(t, testStore.Close()) | ||||
| } | ||||
|  | ||||
| func Test_Rueidis_Cluster(t *testing.T) { | ||||
| 	t.Skip("TODO: Replace with containerized cluster when testcontainers-go Redis module supports clustering") | ||||
|  | ||||
| 	store := New(Config{ | ||||
| 		InitAddress: []string{ | ||||
| 			"localhost:7000", | ||||
| @@ -325,6 +401,9 @@ func Test_Rueidis_Cluster(t *testing.T) { | ||||
| } | ||||
|  | ||||
| func Benchmark_Rueidis_Set(b *testing.B) { | ||||
| 	testStore := newTestStore(b) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	b.ReportAllocs() | ||||
| 	b.ResetTimer() | ||||
|  | ||||
| @@ -337,6 +416,9 @@ func Benchmark_Rueidis_Set(b *testing.B) { | ||||
| } | ||||
|  | ||||
| func Benchmark_Rueidis_Get(b *testing.B) { | ||||
| 	testStore := newTestStore(b) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	err := testStore.Set("john", []byte("doe"), 0) | ||||
| 	require.NoError(b, err) | ||||
|  | ||||
| @@ -351,6 +433,9 @@ func Benchmark_Rueidis_Get(b *testing.B) { | ||||
| } | ||||
|  | ||||
| func Benchmark_Rueidis_SetAndDelete(b *testing.B) { | ||||
| 	testStore := newTestStore(b) | ||||
| 	defer testStore.Close() | ||||
|  | ||||
| 	b.ReportAllocs() | ||||
| 	b.ResetTimer() | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Manuel de la Peña
					Manuel de la Peña