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  }