Skip to content

Commit

Permalink
Add testcontainer tests for natskv
Browse files Browse the repository at this point in the history
  • Loading branch information
cavus700 committed Apr 19, 2024
1 parent 3c525a8 commit ddc21dd
Show file tree
Hide file tree
Showing 4 changed files with 364 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yaml
Expand Up @@ -16,6 +16,9 @@ jobs:
go: ["1.21", "1.22"]

steps:
- name: Use Docker in rootless mode.
uses: ScribeMD/rootless-docker@0.2.2

- name: Set up Go
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
Expand Down
231 changes: 231 additions & 0 deletions backend/natskv/natskv_test.go
@@ -0,0 +1,231 @@
package natskv_test

import (
"context"
"fmt"
"github.com/docker/docker/api/types/container"
"github.com/docker/go-connections/nat"
"github.com/nats-io/nats.go"
"github.com/sagikazarmark/crypt/backend/natskv"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
"os"
"reflect"
"sync"
"testing"
"time"
)

func init() {
_ = os.Setenv("TESTCONTAINERS_RYUK_DISABLED", "true")
}

func TestClient_Get(t *testing.T) {
ctx := testContext(t)
natsAddress := runNatsContainer(ctx, t)

// Prepare test
conn, err := nats.Connect(natsAddress)
if err != nil {
t.Fatal(err)
}

js, err := conn.JetStream()
if err != nil {
t.Fatal(err)
}

kv, err := js.CreateKeyValue(&nats.KeyValueConfig{
Bucket: "viper",
})
if err != nil {
t.Fatal(err)
}

wantConfig := []byte("foo: bar")
if _, err = kv.Put("config.yaml", wantConfig); err != nil {
t.Fatal(err)
}

// Execute test
client, err := natskv.New([]string{natsAddress})
if err != nil {
t.Fatalf("Failed to create natskv - %v", err)
}

gotConfig, err := client.Get("config.yaml")
if err != nil {
t.Fatal(err)
}

if !reflect.DeepEqual(gotConfig, []byte("foo: bar")) {
t.Fatalf("Unexpected config - got: %v, want: %v", gotConfig, wantConfig)
}
}

func TestClient_List(t *testing.T) {
ctx := testContext(t)
natsAddress := runNatsContainer(ctx, t)

// Prepare test
conn, err := nats.Connect(natsAddress)
if err != nil {
t.Fatal(err)
}

js, err := conn.JetStream()
if err != nil {
t.Fatal(err)
}

kv, err := js.CreateKeyValue(&nats.KeyValueConfig{
Bucket: "viper",
})
if err != nil {
t.Fatal(err)
}

wantConfigs := map[string][]byte{
"config.yaml": []byte("foo: bar"),
"second_config.yaml": []byte("foo: baz"),
}
for name, value := range wantConfigs {
if _, err = kv.Put(name, value); err != nil {
t.Fatal(err)
}
}

// Execute test
client, err := natskv.New([]string{natsAddress})
if err != nil {
t.Fatalf("Failed to create natskv - %v", err)
}

kvPairs, err := client.List("viper")
if err != nil {
t.Fatal(err)
}

for _, kvPair := range kvPairs {
if !reflect.DeepEqual(wantConfigs[kvPair.Key], kvPair.Value) {
t.Fatalf("Unexpected config - got: %v, want: %v", kvPair.Value, wantConfigs[kvPair.Key])
}
}
}

func TestClient_Watch(t *testing.T) {
ctx := testContext(t)
natsAddress := runNatsContainer(ctx, t)

// Prepare test
conn, err := nats.Connect(natsAddress)
if err != nil {
t.Fatal(err)
}

js, err := conn.JetStream()
if err != nil {
t.Fatal(err)
}

kv, err := js.CreateKeyValue(&nats.KeyValueConfig{
Bucket: "viper",
})
if err != nil {
t.Fatal(err)
}

wantConfig := []byte("foo: bar")
if _, err = kv.Put("config.yaml", wantConfig); err != nil {
t.Fatal(err)
}

// Execute test
client, err := natskv.New([]string{natsAddress})
if err != nil {
t.Fatalf("Failed to create natskv - %v", err)
}

quit := make(chan bool)
respChan := client.Watch("config.yaml", quit)

updateWG := new(sync.WaitGroup)
updateWG.Add(1)

termWG := new(sync.WaitGroup)
termWG.Add(1)

updatedConfig := []byte("foo: update")
go func() {
defer termWG.Done()
for resp := range respChan {
if !reflect.DeepEqual(resp.Value, updatedConfig) {
t.Errorf("Unexpected config - got: %v, want: %v", resp.Value, updatedConfig)
}
updateWG.Done()
}
}()

if _, err = kv.Put("config.yaml", updatedConfig); err != nil {
t.Fatal(err)
}
updateWG.Wait()

close(quit)

termWG.Wait()
}

func testContext(t *testing.T) context.Context {
ctx := context.Background()
deadline, ok := t.Deadline()
if ok {
var cancel context.CancelFunc
ctx, cancel = context.WithDeadline(context.Background(), deadline)
t.Cleanup(cancel)
}

return ctx
}

func runNatsContainer(ctx context.Context, t testing.TB) string {
req := testcontainers.ContainerRequest{
Image: "nats:latest",
ExposedPorts: []string{"4222/tcp", "8222/tcp"},
Entrypoint: []string{"/nats-server"},
Cmd: []string{"-js", "-m", "8222"},
WaitingFor: wait.NewHTTPStrategy("/varz").
WithAllowInsecure(true).
WithPort("8222/tcp").
WithTLS(false).
WithStartupTimeout(15 * time.Second),
HostConfigModifier: func(config *container.HostConfig) {
config.AutoRemove = true
},
}
natsContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
})

if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
if err := natsContainer.Terminate(ctx); err != nil {
t.Fatalf("Failed to terminate nats container, error = %v", err)
}
})

ip, err := natsContainer.Host(ctx)
if err != nil {
t.Fatal(err)
}

var port nat.Port
if port, err = natsContainer.MappedPort(ctx, "4222/tcp"); err != nil {
t.Fatal(err)
}

return fmt.Sprintf("%s:%s", ip, port.Port())
}
35 changes: 34 additions & 1 deletion go.mod
Expand Up @@ -6,9 +6,12 @@ go 1.21

require (
cloud.google.com/go/firestore v1.15.0
github.com/docker/docker v25.0.5+incompatible
github.com/docker/go-connections v0.5.0
github.com/hashicorp/consul/api v1.28.2
github.com/nats-io/nats.go v1.34.1
github.com/pkg/errors v0.9.1
github.com/testcontainers/testcontainers-go v0.30.0
go.etcd.io/etcd/api/v3 v3.5.13
go.etcd.io/etcd/client/v2 v2.305.13
go.etcd.io/etcd/client/v3 v3.5.13
Expand All @@ -23,17 +26,29 @@ require (
cloud.google.com/go/auth/oauth2adapt v0.2.0 // indirect
cloud.google.com/go/compute/metadata v0.3.0 // indirect
cloud.google.com/go/longrunning v0.5.5 // indirect
dario.cat/mergo v1.0.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Microsoft/hcsshim v0.11.4 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/containerd/containerd v1.7.12 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect
github.com/distribution/reference v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/fatih/color v1.14.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.1 // 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/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
Expand All @@ -46,14 +61,30 @@ require (
github.com/hashicorp/serf v0.10.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.2 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // 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/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/nats-io/nkeys v0.4.7 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/shirou/gopsutil/v3 v3.23.12 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // 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.3 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.13 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
Expand All @@ -65,12 +96,14 @@ require (
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
golang.org/x/mod v0.16.0 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/oauth2 v0.19.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.13.0 // indirect
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect
Expand Down

0 comments on commit ddc21dd

Please sign in to comment.