-
Notifications
You must be signed in to change notification settings - Fork 76
feat(etcd): use testcontainers-go for etcd tests #1721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -1,25 +1,44 @@ | ||||||||
package etcd | ||||||||
|
||||||||
import ( | ||||||||
"context" | ||||||||
"os" | ||||||||
"testing" | ||||||||
"time" | ||||||||
|
||||||||
"github.com/stretchr/testify/require" | ||||||||
|
||||||||
"github.com/testcontainers/testcontainers-go" | ||||||||
"github.com/testcontainers/testcontainers-go/modules/etcd" | ||||||||
) | ||||||||
|
||||||||
var testStore *Storage | ||||||||
const ( | ||||||||
// etcdImage is the default image used for running etcd in tests. | ||||||||
etcdImage = "gcr.io/etcd-development/etcd:v3.5.21" | ||||||||
ReneWerner87 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
etcdImageEnvVar string = "TEST_ETCD_IMAGE" | ||||||||
) | ||||||||
|
||||||||
func TestMain(m *testing.M) { | ||||||||
testStore = New(Config{ | ||||||||
Endpoints: []string{"localhost:2379"}, | ||||||||
}) | ||||||||
func newTestStore(t testing.TB) *Storage { | ||||||||
t.Helper() | ||||||||
|
||||||||
img := etcdImage | ||||||||
if imgFromEnv := os.Getenv(etcdImageEnvVar); imgFromEnv != "" { | ||||||||
img = imgFromEnv | ||||||||
} | ||||||||
|
||||||||
code := m.Run() | ||||||||
ctx := context.Background() | ||||||||
|
||||||||
Comment on lines
+29
to
30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add a timeout-bound context to prevent hanging tests
-ctx := context.Background()
+ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+defer cancel() This keeps the test suite responsive in CI environments. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents (early access)
|
||||||||
_ = testStore.Reset() | ||||||||
_ = testStore.Close() | ||||||||
os.Exit(code) | ||||||||
// create a 2-node cluster | ||||||||
c, err := etcd.Run(ctx, img, etcd.WithNodes("etcd-1", "etcd-2"), etcd.WithClusterToken("test-cluster")) | ||||||||
testcontainers.CleanupContainer(t, c) | ||||||||
require.NoError(t, err) | ||||||||
ReneWerner87 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
|
||||||||
hostPort, err := c.ClientEndpoint(ctx) | ||||||||
require.NoError(t, err) | ||||||||
|
||||||||
return New(Config{ | ||||||||
Endpoints: []string{hostPort}, | ||||||||
}) | ||||||||
} | ||||||||
|
||||||||
func TestSetEtcd_ShouldReturnNoError(t *testing.T) { | ||||||||
|
@@ -28,18 +47,27 @@ func TestSetEtcd_ShouldReturnNoError(t *testing.T) { | |||||||
val = []byte("doe") | ||||||||
) | ||||||||
|
||||||||
testStore := newTestStore(t) | ||||||||
defer testStore.Close() | ||||||||
|
||||||||
err := testStore.Set(key, val, 0) | ||||||||
require.NoError(t, err) | ||||||||
} | ||||||||
|
||||||||
func TestGetEtcd_ShouldReturnNil_WhenDocumentNotFound(t *testing.T) { | ||||||||
testStore := newTestStore(t) | ||||||||
defer testStore.Close() | ||||||||
|
||||||||
val, err := testStore.Get("not_found_key") | ||||||||
|
||||||||
require.NoError(t, err) | ||||||||
require.Zero(t, len(val)) | ||||||||
} | ||||||||
|
||||||||
func TestSetAndGet_GetShouldReturn_SettedValueWithoutError(t *testing.T) { | ||||||||
testStore := newTestStore(t) | ||||||||
defer testStore.Close() | ||||||||
|
||||||||
err := testStore.Set("test", []byte("fiber_test_value"), 0) | ||||||||
require.NoError(t, err) | ||||||||
|
||||||||
|
@@ -50,6 +78,9 @@ func TestSetAndGet_GetShouldReturn_SettedValueWithoutError(t *testing.T) { | |||||||
} | ||||||||
|
||||||||
func TestSetAndGet_GetShouldReturnNil_WhenTTLExpired(t *testing.T) { | ||||||||
testStore := newTestStore(t) | ||||||||
defer testStore.Close() | ||||||||
|
||||||||
err := testStore.Set("test", []byte("fiber_test_value"), 3*time.Second) | ||||||||
require.NoError(t, err) | ||||||||
|
||||||||
|
@@ -62,6 +93,9 @@ func TestSetAndGet_GetShouldReturnNil_WhenTTLExpired(t *testing.T) { | |||||||
} | ||||||||
|
||||||||
func TestSetAndDelete_DeleteShouldReturn_NoError(t *testing.T) { | ||||||||
testStore := newTestStore(t) | ||||||||
defer testStore.Close() | ||||||||
|
||||||||
err := testStore.Set("test", []byte("fiber_test_value"), 0) | ||||||||
require.NoError(t, err) | ||||||||
|
||||||||
|
@@ -73,6 +107,9 @@ func TestSetAndDelete_DeleteShouldReturn_NoError(t *testing.T) { | |||||||
} | ||||||||
|
||||||||
func TestSetAndReset_ResetShouldReturn_NoError(t *testing.T) { | ||||||||
testStore := newTestStore(t) | ||||||||
defer testStore.Close() | ||||||||
|
||||||||
err := testStore.Set("test", []byte("fiber_test_value"), 0) | ||||||||
require.NoError(t, err) | ||||||||
|
||||||||
|
@@ -84,15 +121,22 @@ func TestSetAndReset_ResetShouldReturn_NoError(t *testing.T) { | |||||||
} | ||||||||
|
||||||||
func TestClose_CloseShouldReturn_NoError(t *testing.T) { | ||||||||
testStore := newTestStore(t) | ||||||||
err := testStore.Close() | ||||||||
require.NoError(t, err) | ||||||||
} | ||||||||
|
||||||||
func TestGetConn_ReturnsNotNill(t *testing.T) { | ||||||||
testStore := newTestStore(t) | ||||||||
defer testStore.Close() | ||||||||
|
||||||||
require.True(t, testStore.Conn() != nil) | ||||||||
} | ||||||||
|
||||||||
func Benchmark_Etcd_Set(b *testing.B) { | ||||||||
testStore := newTestStore(b) | ||||||||
defer testStore.Close() | ||||||||
|
||||||||
b.ReportAllocs() | ||||||||
b.ResetTimer() | ||||||||
|
||||||||
|
@@ -105,6 +149,9 @@ func Benchmark_Etcd_Set(b *testing.B) { | |||||||
} | ||||||||
|
||||||||
func Benchmark_Etcd_Get(b *testing.B) { | ||||||||
testStore := newTestStore(b) | ||||||||
defer testStore.Close() | ||||||||
|
||||||||
err := testStore.Set("john", []byte("doe"), 0) | ||||||||
require.NoError(b, err) | ||||||||
|
||||||||
|
@@ -119,6 +166,9 @@ func Benchmark_Etcd_Get(b *testing.B) { | |||||||
} | ||||||||
|
||||||||
func Benchmark_Etcd_SetAndDelete(b *testing.B) { | ||||||||
testStore := newTestStore(b) | ||||||||
defer testStore.Close() | ||||||||
|
||||||||
b.ReportAllocs() | ||||||||
b.ResetTimer() | ||||||||
|
||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,75 @@ | ||
module github.com/gofiber/storage/etcd/v2 | ||
|
||
go 1.19 | ||
go 1.23.0 | ||
|
||
require ( | ||
github.com/stretchr/testify v1.10.0 | ||
go.etcd.io/etcd/client/v3 v3.5.12 | ||
github.com/testcontainers/testcontainers-go v0.37.0 | ||
github.com/testcontainers/testcontainers-go/modules/etcd v0.37.0 | ||
go.etcd.io/etcd/client/v3 v3.5.21 | ||
) | ||
|
||
require ( | ||
github.com/coreos/go-semver v0.3.1 // indirect | ||
dario.cat/mergo v1.0.1 // indirect | ||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect | ||
github.com/Microsoft/go-winio v0.6.2 // indirect | ||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect | ||
github.com/containerd/log v0.1.0 // indirect | ||
github.com/containerd/platforms v0.2.1 // indirect | ||
github.com/coreos/go-semver v0.3.0 // indirect | ||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect | ||
github.com/cpuguy83/dockercfg v0.3.2 // indirect | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/distribution/reference v0.6.0 // indirect | ||
github.com/docker/docker v28.0.1+incompatible // indirect | ||
github.com/docker/go-connections v0.5.0 // indirect | ||
github.com/docker/go-units v0.5.0 // indirect | ||
github.com/ebitengine/purego v0.8.2 // indirect | ||
github.com/felixge/httpsnoop v1.0.4 // indirect | ||
github.com/go-logr/logr v1.4.2 // indirect | ||
github.com/go-logr/stdr v1.2.2 // indirect | ||
github.com/go-ole/go-ole v1.2.6 // indirect | ||
github.com/gogo/protobuf v1.3.2 // indirect | ||
github.com/golang/protobuf v1.5.3 // indirect | ||
github.com/golang/protobuf v1.5.4 // indirect | ||
github.com/google/uuid v1.6.0 // indirect | ||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect | ||
github.com/klauspost/compress v1.17.4 // indirect | ||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect | ||
github.com/magiconair/properties v1.8.10 // indirect | ||
github.com/moby/docker-image-spec v1.3.1 // indirect | ||
github.com/moby/patternmatcher v0.6.0 // indirect | ||
github.com/moby/sys/sequential v0.5.0 // indirect | ||
github.com/moby/sys/user v0.1.0 // indirect | ||
github.com/moby/sys/userns v0.1.0 // indirect | ||
github.com/moby/term v0.5.0 // indirect | ||
github.com/morikuni/aec v1.0.0 // indirect | ||
github.com/opencontainers/go-digest v1.0.0 // indirect | ||
github.com/opencontainers/image-spec v1.1.1 // indirect | ||
github.com/pkg/errors v0.9.1 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
go.etcd.io/etcd/api/v3 v3.5.12 // indirect | ||
go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect | ||
go.uber.org/multierr v1.11.0 // indirect | ||
go.uber.org/zap v1.25.0 // indirect | ||
golang.org/x/net v0.23.0 // indirect | ||
golang.org/x/sys v0.18.0 // indirect | ||
golang.org/x/text v0.14.0 // indirect | ||
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect | ||
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect | ||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect | ||
google.golang.org/grpc v1.59.0 // indirect | ||
google.golang.org/protobuf v1.33.0 // indirect | ||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect | ||
github.com/shirou/gopsutil/v4 v4.25.1 // indirect | ||
github.com/sirupsen/logrus v1.9.3 // indirect | ||
github.com/tklauser/go-sysconf v0.3.12 // indirect | ||
github.com/tklauser/numcpus v0.6.1 // indirect | ||
github.com/yusufpapurcu/wmi v1.2.4 // indirect | ||
go.etcd.io/etcd/api/v3 v3.5.21 // indirect | ||
go.etcd.io/etcd/client/pkg/v3 v3.5.21 // indirect | ||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect | ||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect | ||
go.opentelemetry.io/otel v1.35.0 // indirect | ||
go.opentelemetry.io/otel/metric v1.35.0 // indirect | ||
go.opentelemetry.io/otel/trace v1.35.0 // indirect | ||
go.uber.org/atomic v1.7.0 // indirect | ||
go.uber.org/multierr v1.6.0 // indirect | ||
go.uber.org/zap v1.17.0 // indirect | ||
golang.org/x/crypto v0.37.0 // indirect | ||
golang.org/x/net v0.38.0 // indirect | ||
golang.org/x/sys v0.32.0 // indirect | ||
golang.org/x/text v0.24.0 // indirect | ||
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect | ||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect | ||
google.golang.org/grpc v1.70.0 // indirect | ||
google.golang.org/protobuf v1.36.5 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
Uh oh!
There was an error while loading. Please reload this page.