138 lines
3.7 KiB
Go
138 lines
3.7 KiB
Go
|
|
package config
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"net/http"
|
||
|
|
"net/http/httptest"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/stretchr/testify/require"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestEnvironmentSubstitution(t *testing.T) {
|
||
|
|
tests := []struct {
|
||
|
|
name string
|
||
|
|
setEnv func(*testing.T)
|
||
|
|
contents string
|
||
|
|
expected string
|
||
|
|
wantErr bool
|
||
|
|
errSubstring string
|
||
|
|
}{
|
||
|
|
{
|
||
|
|
name: "Legacy with ${} and without {}",
|
||
|
|
setEnv: func(t *testing.T) {
|
||
|
|
t.Setenv("TEST_ENV1", "VALUE1")
|
||
|
|
t.Setenv("TEST_ENV2", "VALUE2")
|
||
|
|
},
|
||
|
|
contents: "A string with ${TEST_ENV1}, $TEST_ENV2 and $TEST_ENV1 as repeated",
|
||
|
|
expected: "A string with VALUE1, VALUE2 and VALUE1 as repeated",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "Env not set",
|
||
|
|
contents: "Env variable ${NOT_SET} will be empty",
|
||
|
|
expected: "Env variable will be empty", // Two spaces present
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "Env not set, fallback to default",
|
||
|
|
contents: "Env variable ${THIS_IS_ABSENT:-Fallback}",
|
||
|
|
expected: "Env variable Fallback",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "No fallback",
|
||
|
|
setEnv: func(t *testing.T) {
|
||
|
|
t.Setenv("MY_ENV1", "VALUE1")
|
||
|
|
},
|
||
|
|
contents: "Env variable ${MY_ENV1:-Fallback}",
|
||
|
|
expected: "Env variable VALUE1",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "Mix and match",
|
||
|
|
setEnv: func(t *testing.T) {
|
||
|
|
t.Setenv("MY_VAR", "VALUE")
|
||
|
|
t.Setenv("MY_VAR2", "VALUE2")
|
||
|
|
},
|
||
|
|
contents: "Env var ${MY_VAR} is set, with $MY_VAR syntax and default on this ${MY_VAR1:-Substituted}, no default on this ${MY_VAR2:-NoDefault}",
|
||
|
|
expected: "Env var VALUE is set, with VALUE syntax and default on this Substituted, no default on this VALUE2",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "Default has special chars",
|
||
|
|
contents: `Not recommended but supported ${MY_VAR:-Default with special chars Supported#$\"}`,
|
||
|
|
expected: `Not recommended but supported Default with special chars Supported#$\"`, // values are escaped
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "unset error",
|
||
|
|
contents: "Contains ${THIS_IS_NOT_SET?unset-error}",
|
||
|
|
wantErr: true,
|
||
|
|
errSubstring: "unset-error",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "env empty error",
|
||
|
|
setEnv: func(t *testing.T) {
|
||
|
|
t.Setenv("ENV_EMPTY", "")
|
||
|
|
},
|
||
|
|
contents: "Contains ${ENV_EMPTY:?empty-error}",
|
||
|
|
wantErr: true,
|
||
|
|
errSubstring: "empty-error",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "Fallback as env variable",
|
||
|
|
setEnv: func(t *testing.T) {
|
||
|
|
t.Setenv("FALLBACK", "my-fallback")
|
||
|
|
},
|
||
|
|
contents: "Should output ${NOT_SET:-${FALLBACK}}",
|
||
|
|
expected: "Should output my-fallback",
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, tt := range tests {
|
||
|
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
|
if tt.setEnv != nil {
|
||
|
|
tt.setEnv(t)
|
||
|
|
}
|
||
|
|
actual, err := substituteEnvironment([]byte(tt.contents))
|
||
|
|
if tt.wantErr {
|
||
|
|
require.ErrorContains(t, err, tt.errSubstring)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
require.EqualValues(t, tt.expected, string(actual))
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestURLRetries3Fails(t *testing.T) {
|
||
|
|
httpLoadConfigRetryInterval = 0 * time.Second
|
||
|
|
responseCounter := 0
|
||
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
w.WriteHeader(http.StatusNotFound)
|
||
|
|
responseCounter++
|
||
|
|
}))
|
||
|
|
defer ts.Close()
|
||
|
|
|
||
|
|
expected := fmt.Sprintf("error loading config file %s: retry 3 of 3 failed to retrieve remote config: 404 Not Found", ts.URL)
|
||
|
|
|
||
|
|
c := NewConfig()
|
||
|
|
err := c.LoadConfig(ts.URL)
|
||
|
|
require.Error(t, err)
|
||
|
|
require.Equal(t, expected, err.Error())
|
||
|
|
require.Equal(t, 4, responseCounter)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestURLRetries3FailsThenPasses(t *testing.T) {
|
||
|
|
httpLoadConfigRetryInterval = 0 * time.Second
|
||
|
|
responseCounter := 0
|
||
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
if responseCounter <= 2 {
|
||
|
|
w.WriteHeader(http.StatusNotFound)
|
||
|
|
} else {
|
||
|
|
w.WriteHeader(http.StatusOK)
|
||
|
|
}
|
||
|
|
responseCounter++
|
||
|
|
}))
|
||
|
|
defer ts.Close()
|
||
|
|
|
||
|
|
c := NewConfig()
|
||
|
|
require.NoError(t, c.LoadConfig(ts.URL))
|
||
|
|
require.Equal(t, 4, responseCounter)
|
||
|
|
}
|