github.com/khulnasoft/cli@v0.0.0-20240402070845-01bcad7beefa/cli/compose/interpolation/interpolation_test.go (about) 1 // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: 2 //go:build go1.19 3 4 package interpolation 5 6 import ( 7 "strconv" 8 "testing" 9 10 "gotest.tools/v3/assert" 11 is "gotest.tools/v3/assert/cmp" 12 ) 13 14 var defaults = map[string]string{ 15 "USER": "jenny", 16 "FOO": "bar", 17 "count": "5", 18 } 19 20 func defaultMapping(name string) (string, bool) { 21 val, ok := defaults[name] 22 return val, ok 23 } 24 25 func TestInterpolate(t *testing.T) { 26 services := map[string]any{ 27 "servicea": map[string]any{ 28 "image": "example:${USER}", 29 "volumes": []any{"$FOO:/target"}, 30 "logging": map[string]any{ 31 "driver": "${FOO}", 32 "options": map[string]any{ 33 "user": "$USER", 34 }, 35 }, 36 }, 37 } 38 expected := map[string]any{ 39 "servicea": map[string]any{ 40 "image": "example:jenny", 41 "volumes": []any{"bar:/target"}, 42 "logging": map[string]any{ 43 "driver": "bar", 44 "options": map[string]any{ 45 "user": "jenny", 46 }, 47 }, 48 }, 49 } 50 result, err := Interpolate(services, Options{LookupValue: defaultMapping}) 51 assert.NilError(t, err) 52 assert.Check(t, is.DeepEqual(expected, result)) 53 } 54 55 func TestInvalidInterpolation(t *testing.T) { 56 services := map[string]any{ 57 "servicea": map[string]any{ 58 "image": "${", 59 }, 60 } 61 _, err := Interpolate(services, Options{LookupValue: defaultMapping}) 62 assert.Error(t, err, `invalid interpolation format for servicea.image: "${"; you may need to escape any $ with another $`) 63 } 64 65 func TestInterpolateWithDefaults(t *testing.T) { 66 t.Setenv("FOO", "BARZ") 67 68 config := map[string]any{ 69 "networks": map[string]any{ 70 "foo": "thing_${FOO}", 71 }, 72 } 73 expected := map[string]any{ 74 "networks": map[string]any{ 75 "foo": "thing_BARZ", 76 }, 77 } 78 result, err := Interpolate(config, Options{}) 79 assert.NilError(t, err) 80 assert.Check(t, is.DeepEqual(expected, result)) 81 } 82 83 func TestInterpolateWithCast(t *testing.T) { 84 config := map[string]any{ 85 "foo": map[string]any{ 86 "replicas": "$count", 87 }, 88 } 89 toInt := func(value string) (any, error) { 90 return strconv.Atoi(value) 91 } 92 result, err := Interpolate(config, Options{ 93 LookupValue: defaultMapping, 94 TypeCastMapping: map[Path]Cast{NewPath(PathMatchAll, "replicas"): toInt}, 95 }) 96 assert.NilError(t, err) 97 expected := map[string]any{ 98 "foo": map[string]any{ 99 "replicas": 5, 100 }, 101 } 102 assert.Check(t, is.DeepEqual(expected, result)) 103 } 104 105 func TestPathMatches(t *testing.T) { 106 testcases := []struct { 107 doc string 108 path Path 109 pattern Path 110 expected bool 111 }{ 112 { 113 doc: "pattern too short", 114 path: NewPath("one", "two", "three"), 115 pattern: NewPath("one", "two"), 116 }, 117 { 118 doc: "pattern too long", 119 path: NewPath("one", "two"), 120 pattern: NewPath("one", "two", "three"), 121 }, 122 { 123 doc: "pattern mismatch", 124 path: NewPath("one", "three", "two"), 125 pattern: NewPath("one", "two", "three"), 126 }, 127 { 128 doc: "pattern mismatch with match-all part", 129 path: NewPath("one", "three", "two"), 130 pattern: NewPath(PathMatchAll, "two", "three"), 131 }, 132 { 133 doc: "pattern match with match-all part", 134 path: NewPath("one", "two", "three"), 135 pattern: NewPath("one", "*", "three"), 136 expected: true, 137 }, 138 { 139 doc: "pattern match", 140 path: NewPath("one", "two", "three"), 141 pattern: NewPath("one", "two", "three"), 142 expected: true, 143 }, 144 } 145 for _, testcase := range testcases { 146 assert.Check(t, is.Equal(testcase.expected, testcase.path.matches(testcase.pattern))) 147 } 148 }