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  }