Skip to content

Commit

Permalink
More tests
Browse files Browse the repository at this point in the history
  • Loading branch information
z4kn4fein committed Mar 23, 2024
1 parent d3fdb60 commit 0070001
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 23 deletions.
2 changes: 1 addition & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ func (t *TlsConfig) LoadTlsOptions() (*tls.Config, error) {
if cert, err := tls.LoadX509KeyPair(c.Cert, c.Key); err == nil {
conf.Certificates = append(conf.Certificates, cert)
} else {
return nil, fmt.Errorf("failed to load the certificate and key pair: %s", err)
return nil, fmt.Errorf("failed to load the certificate and key files: %s", err)
}
}
return conf, nil
Expand Down
123 changes: 104 additions & 19 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -673,23 +673,108 @@ default_user_attributes:
}

func TestGrpcConfig_KeepAlive(t *testing.T) {
conf := KeepAliveConfig{MaxConnectionIdle: 1, MaxConnectionAge: 2, MaxConnectionAgeGrace: 3, Time: 4, Timeout: 5}
param, ok := conf.ToParams()

assert.True(t, ok)
assert.Equal(t, 1*time.Second, param.MaxConnectionIdle)
assert.Equal(t, 2*time.Second, param.MaxConnectionAge)
assert.Equal(t, 3*time.Second, param.MaxConnectionAgeGrace)
assert.Equal(t, 4*time.Second, param.Time)
assert.Equal(t, 5*time.Second, param.Timeout)

conf = KeepAliveConfig{MaxConnectionIdle: 1}
param, ok = conf.ToParams()

assert.True(t, ok)
assert.Equal(t, 1*time.Second, param.MaxConnectionIdle)
assert.Equal(t, time.Duration(0), param.MaxConnectionAge)
assert.Equal(t, time.Duration(0), param.MaxConnectionAgeGrace)
assert.Equal(t, time.Duration(0), param.Time)
assert.Equal(t, time.Duration(0), param.Timeout)
t.Run("valid", func(t *testing.T) {
conf := KeepAliveConfig{MaxConnectionIdle: 1, MaxConnectionAge: 2, MaxConnectionAgeGrace: 3, Time: 4, Timeout: 5}
param, ok := conf.ToParams()

assert.True(t, ok)
assert.Equal(t, 1*time.Second, param.MaxConnectionIdle)
assert.Equal(t, 2*time.Second, param.MaxConnectionAge)
assert.Equal(t, 3*time.Second, param.MaxConnectionAgeGrace)
assert.Equal(t, 4*time.Second, param.Time)
assert.Equal(t, 5*time.Second, param.Timeout)

conf = KeepAliveConfig{MaxConnectionIdle: 1}
param, ok = conf.ToParams()

assert.True(t, ok)
assert.Equal(t, 1*time.Second, param.MaxConnectionIdle)
assert.Equal(t, time.Duration(0), param.MaxConnectionAge)
assert.Equal(t, time.Duration(0), param.MaxConnectionAgeGrace)
assert.Equal(t, time.Duration(0), param.Time)
assert.Equal(t, time.Duration(0), param.Timeout)
})
t.Run("empty", func(t *testing.T) {
conf := KeepAliveConfig{}
_, ok := conf.ToParams()
assert.False(t, ok)
})
}

func TestTlsConfig_LoadTlsOptions(t *testing.T) {
t.Run("valid", func(t *testing.T) {
utils.UseTempFile(`
-----BEGIN CERTIFICATE-----
MIICrzCCAZcCFDnpdKF+Pg1smjtIXrNdIgxGYEJfMA0GCSqGSIb3DQEBCwUAMBQx
EjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0yMzAzMDEyMTA2NThaFw0yNDAyMjkyMTA2
NThaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAOiTDTjfAPvJLDZ2mwNvu0pohSHPRzzfZRc16iVI6+ESl0Dwjdjl
yERFO/ts1GQnhE2ggykvoxH4zUy1OCnjTJ+Mm1ryjy4G5ZIILIF9MfFcyma5/5Xd
oOTcDr3ZDTAwFaabKYKisoVMHAJCphencgoyOToW5/HRHMKOEpTJOQWSyNduXYfY
nsWb3hx7WD9NajliW7/Jjbf7UnDtKY2VM2GZWT3ygIH/7SlBqyuXJNqyZXbqfbrP
6mdZQ5wvYsnSUU4kNMtZg/ns+0H5R7PFmRhIRM0nZvJZTO9oHREdm+e2nnZwHyJF
Z26LxE7Qr1bn8+PQSydyQIqeUdaSX2LuXqECAwEAATANBgkqhkiG9w0BAQsFAAOC
AQEAjRoOTe4W4OQ6YOo5kx5sMAozh0Rg6eifS0s8GuxKwfuBop8FEnM3wAfF6x3J
fsik9MmoM4L11HWjttb46UFq/rP3GsA3DLX8i1yBOES+iyCELd5Ss9q1jfr/Jqo3
cAanE4yl3NNEZoDmMdSj2U11BneKSzHDR+l2hDF9wBifWGI9DQ1ItfA5I6MwnL+0
J03vcwPSwme4bKC/avAT2oDD7jLGLA+kuhMqHvVq7nXRzs46xyFPBBv7fBxXjPPG
c89d0ISafKtZ9kIKaRrzu2HX+b0fzKr0vtHYDLtC1U5oU7GPB12eupERkmWYlhrw
hDL3X7kt3jEZFkzGV1XL1IJx/g==
-----END CERTIFICATE-----`, func(cert string) {
utils.UseTempFile(`-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDokw043wD7ySw2
dpsDb7tKaIUhz0c832UXNeolSOvhEpdA8I3Y5chERTv7bNRkJ4RNoIMpL6MR+M1M
tTgp40yfjJta8o8uBuWSCCyBfTHxXMpmuf+V3aDk3A692Q0wMBWmmymCorKFTBwC
QqYXp3IKMjk6Fufx0RzCjhKUyTkFksjXbl2H2J7Fm94ce1g/TWo5Ylu/yY23+1Jw
7SmNlTNhmVk98oCB/+0pQasrlyTasmV26n26z+pnWUOcL2LJ0lFOJDTLWYP57PtB
+UezxZkYSETNJ2byWUzvaB0RHZvntp52cB8iRWdui8RO0K9W5/Pj0EsnckCKnlHW
kl9i7l6hAgMBAAECggEBAOMWiqeIH5a6BGCdiJhfZZmu2qd7k8xdOIDkVN7ZB/B5
TZTMDUTGgLggfgPubKfqaeW+H7N8XxZyQEtw+wjzduKm0R6JjsJbW5cuQf6htr08
ZCjP3j5/69TrBb3bjGQL32gRQwPaRsOe4A5Y84JPLivEhFoy+YEFNLbHMF905yeH
IaSeqeK0GNm0a/MU68pa1ODIc8B2zqo+f6I9qekezlDR7Or487FqnlLtNf0yvnLD
sbshzj5rzLdLYgA/RNZ4CkuGddxEYjnDB1IG0NX8m9MrHlsi7jqxa7pHt5oDrRsW
ZxBez6Q70dE29sdl5lnce3qjxweB2NK3Q6Cr2eyizwECgYEA/L/WzgY1yDMWzaCr
SRThg9NWO1EYbvz4uxt7rElfZ+NYAaT08E35Ooo9IeBzp3VoFA1PcNQnKB5pgczO
Mu5W/td5zpx1dzguBZAl4IpKkml08i06R7FxxTqtRM/P7Pna+RagtqAo3JZww3bd
ofIPH2OrobqlcFhOsLqKp5ocDNECgYEA65DJsImeBfW1aZ5ABgPr7NErSv2fKj1r
eGsgC5Za1ZiaG5LWkCpuezsvf6ma4EN3CMl5Fo617qaY6mnL2HlfVtFhHYSeLpna
9ZgqZ1zj2HkqiXOPEkb3d3cC61rXiMK97NpshrpzFx+uMCH8MMu9/CVJEHNKGgAq
6zZQ4LhjaNECgYEA3W4UeprmM2bO64d/iJ9Kk3traLw7c8EdCI+jYeVGOHXsfERQ
ctddKfRCapOBv4wUiry+hFLZm0RJmvYbEHPOs6WDiYd5QeFuMGGBTZ7ahjrtwd3t
2TGUQv6NHmQR/cNIHEG+u0DFi7whPp28vkybAx0HGMG0fyBekGZdY0iYmoECgYEA
3mVOlVYHk9ba1AEsrsErDuSXe/AgQa/E8+YnVek4jqnI7LlfyrHUppFFEcDdUFdB
XVFg+ZP4XXx5p+4EHrbP9NYuWsDm2lY1K2Livb0r+ybBqw0niPjpD6eTYQHdtOcu
ihvZFAWZPL6TJCwhvSvNjOziox5FWnDIFFKuXsqWR9ECgYAfiG1izToF+GX3yUPq
CU+ceTbM2uy3hVnQLvCnraN7hkF02Fa9ZwP6nmnsvhfdaIUP5WLm3A+qMWu/PL0i
F/dUCUF6M/DyihQUnOl+MD9Sg89ZHiftqXSY8jGR14uH4woStyUFHiFbtajmnqV7
MK4Li/LGWcksyoF+hbPNXMFCIA==
-----END PRIVATE KEY-----
`, func(key string) {
conf := TlsConfig{
MinVersion: 1.1,
ServerName: "server",
Certificates: []CertConfig{
{Key: key, Cert: cert},
},
}
tlsConf, err := conf.LoadTlsOptions()
assert.NoError(t, err)
assert.Equal(t, uint16(tls.VersionTLS11), tlsConf.MinVersion)
assert.Equal(t, "server", tlsConf.ServerName)
assert.NotEmpty(t, tlsConf.Certificates)
})
})
})
t.Run("invalid", func(t *testing.T) {
conf := TlsConfig{
MinVersion: 1.1,
ServerName: "server",
Certificates: []CertConfig{
{Key: "notexisting", Cert: "notexisting"},
},
}
tlsConf, err := conf.LoadTlsOptions()
assert.ErrorContains(t, err, "failed to load the certificate and key files")
assert.Nil(t, tlsConf)
})
}
90 changes: 89 additions & 1 deletion sdk/store/cache/cache_notify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"github.com/configcat/configcat-proxy/log"
"github.com/configcat/go-sdk/v9/configcatcache"
"github.com/stretchr/testify/assert"
"net/http"
"sync"
"testing"
"time"
)
Expand Down Expand Up @@ -103,7 +105,7 @@ func TestRedisNotify_BadJson(t *testing.T) {
assert.Equal(t, `{"f":null,"s":null,"p":null}`, string(r.LoadEntry().ConfigJson))
}

func TestRedisNotify_MalformedJson(t *testing.T) {
func TestRedisNotify_MalformedCacheEntry(t *testing.T) {
sdkKey := "key"
s := miniredis.RunT(t)
cacheKey := configcatcache.ProduceCacheKey(sdkKey, configcatcache.ConfigJSONName, configcatcache.ConfigJSONCacheVersion)
Expand All @@ -120,6 +122,57 @@ func TestRedisNotify_MalformedJson(t *testing.T) {
assert.Equal(t, `{"f":null,"s":null,"p":null}`, string(r.LoadEntry().ConfigJson))
}

func TestRedisNotify_MalformedJson(t *testing.T) {
sdkKey := "key"
s := miniredis.RunT(t)
cacheKey := configcatcache.ProduceCacheKey(sdkKey, configcatcache.ConfigJSONName, configcatcache.ConfigJSONCacheVersion)
cacheEntry := configcatcache.CacheSegmentsToBytes(time.Now(), "etag", []byte(`{"k":{"flag`))
err := s.Set(cacheKey, string(cacheEntry))
assert.NoError(t, err)
red, err := newRedis(&config.RedisConfig{Addresses: []string{s.Addr()}}, log.NewNullLogger())
assert.NoError(t, err)
r := NewCacheStore(red, status.NewNullReporter())
srv := NewNotifyingCacheStore("test", cacheKey, r, &config.OfflineConfig{CachePollInterval: 1}, status.NewNullReporter(), log.NewNullLogger())
res, err := srv.Get(context.Background(), "")
_, _, j, _ := configcatcache.CacheSegmentsFromBytes(res)
assert.NoError(t, err)
assert.Equal(t, `{"f":null,"s":null,"p":null}`, string(j))
assert.Equal(t, `{"f":null,"s":null,"p":null}`, string(r.LoadEntry().ConfigJson))
}

func TestRedisNotify_Reporter(t *testing.T) {
sdkKey := "key"
s := miniredis.RunT(t)
cacheKey := configcatcache.ProduceCacheKey(sdkKey, configcatcache.ConfigJSONName, configcatcache.ConfigJSONCacheVersion)
cacheEntry := configcatcache.CacheSegmentsToBytes(time.Now(), "etag", []byte(`{"f":{"flag":{"v":{"b":true}}},"p":null}`))
err := s.Set(cacheKey, string(cacheEntry))
assert.NoError(t, err)
reporter := &testReporter{}
red, err := newRedis(&config.RedisConfig{Addresses: []string{s.Addr()}}, log.NewNullLogger())
assert.NoError(t, err)
r := NewCacheStore(red, reporter)
srv := NewNotifyingCacheStore(sdkKey, cacheKey, r, &config.OfflineConfig{CachePollInterval: 1}, reporter, log.NewNullLogger()).(*notifyingCacheStore)

rec := reporter.Records()
assert.Contains(t, rec[len(rec)-1], "reload from cache succeeded")

assert.Equal(t, "etag", srv.LoadEntry().ETag)
assert.False(t, srv.reload())
assert.Equal(t, "etag", srv.LoadEntry().ETag)

rec = reporter.Records()
assert.Contains(t, rec[len(rec)-1], "config from cache not modified")

cacheEntry = configcatcache.CacheSegmentsToBytes(time.Now(), "etag2", []byte(`{"f":{"flag":{"v":`))
err = s.Set(cacheKey, string(cacheEntry))
assert.NoError(t, err)
assert.False(t, srv.reload())
assert.Equal(t, "etag", srv.LoadEntry().ETag)

rec = reporter.Records()
assert.Contains(t, rec[len(rec)-1], "failed to parse JSON from cache")
}

func TestRedisNotify_Unavailable(t *testing.T) {
red, err := newRedis(&config.RedisConfig{Addresses: []string{"nonexisting"}}, log.NewNullLogger())
assert.NoError(t, err)
Expand Down Expand Up @@ -148,3 +201,38 @@ func TestRedisNotify_Close(t *testing.T) {
}
})
}

type testReporter struct {
records []string

mu sync.RWMutex
}

func (r *testReporter) ReportOk(component string, message string) {
r.mu.Lock()
defer r.mu.Unlock()

r.records = append(r.records, component+"[ok] "+message)
}

func (r *testReporter) ReportError(component string, message string) {
r.mu.Lock()
defer r.mu.Unlock()

r.records = append(r.records, component+"[error] "+message)
}

func (r *testReporter) Records() []string {
r.mu.RLock()
defer r.mu.RUnlock()

return r.records
}

func (r *testReporter) HttpHandler() http.HandlerFunc {
return nil
}

func (r *testReporter) GetStatus() status.Status {
return status.Status{}
}
4 changes: 3 additions & 1 deletion sdk/store/cache/dynamodb.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,6 @@ func (d *dynamoDbStore) Set(ctx context.Context, key string, value []byte) error
return err
}

func (d *dynamoDbStore) Shutdown() {}
func (d *dynamoDbStore) Shutdown() {
// nothing to do
}
2 changes: 1 addition & 1 deletion sdk/store/cache/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (r *redisStore) Set(ctx context.Context, key string, value []byte) error {
func (r *redisStore) Shutdown() {
err := r.redisDb.Close()
if err != nil {
r.log.Errorf("shutdown error: %v", err)
r.log.Errorf("shutdown error: %s", err)
}
r.log.Reportf("shutdown complete")
}

0 comments on commit 0070001

Please sign in to comment.