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