github.com/kubeshop/testkube@v1.17.23/pkg/tcl/expressionstcl/generic_test.go (about)

     1  // Copyright 2024 Testkube.
     2  //
     3  // Licensed as a Testkube Pro file under the Testkube Community
     4  // License (the "License"); you may not use this file except in compliance with
     5  // the License. You may obtain a copy of the License at
     6  //
     7  //     https://github.com/kubeshop/testkube/blob/main/licenses/TCL.txt
     8  
     9  package expressionstcl
    10  
    11  import (
    12  	"fmt"
    13  	"testing"
    14  
    15  	"github.com/stretchr/testify/assert"
    16  	corev1 "k8s.io/api/core/v1"
    17  	"k8s.io/apimachinery/pkg/util/intstr"
    18  
    19  	"github.com/kubeshop/testkube/internal/common"
    20  )
    21  
    22  type testObj2 struct {
    23  	Expr  string `expr:"expression"`
    24  	Dummy string
    25  }
    26  
    27  type testObj struct {
    28  	Expr            string                        `expr:"expression"`
    29  	Tmpl            string                        `expr:"template"`
    30  	ExprPtr         *string                       `expr:"expression"`
    31  	TmplPtr         *string                       `expr:"template"`
    32  	IntExpr         intstr.IntOrString            `expr:"expression"`
    33  	IntTmpl         intstr.IntOrString            `expr:"template"`
    34  	IntExprPtr      *intstr.IntOrString           `expr:"expression"`
    35  	IntTmplPtr      *intstr.IntOrString           `expr:"template"`
    36  	Obj             testObj2                      `expr:"include"`
    37  	ObjPtr          *testObj2                     `expr:"include"`
    38  	SliceExprStr    []string                      `expr:"expression"`
    39  	SliceExprStrPtr *[]string                     `expr:"expression"`
    40  	SliceExprObj    []testObj2                    `expr:"include"`
    41  	MapKeyVal       map[string]string             `expr:"template,template"`
    42  	MapValIntTmpl   map[string]intstr.IntOrString `expr:"template"`
    43  	MapKeyTmpl      map[string]string             `expr:"template,"`
    44  	MapValTmpl      map[string]string             `expr:"template"`
    45  	MapTmplExpr     map[string]string             `expr:"template,expression"`
    46  	Dummy           string
    47  	DummyPtr        *string
    48  	DummyObj        testObj2
    49  	DummyObjPtr     *testObj2
    50  }
    51  
    52  type testObjNested struct {
    53  	Value corev1.Volume `expr:"force"`
    54  	Dummy corev1.Volume
    55  }
    56  
    57  type testEnum string
    58  
    59  type testObjWithStringEnums struct {
    60  	Value testEnum `expr:"force"`
    61  	Dummy testEnum
    62  }
    63  
    64  type testObjWithStringEnumPointers struct {
    65  	Value *testEnum `expr:"force"`
    66  	Dummy *testEnum
    67  }
    68  
    69  var testMachine = NewMachine().
    70  	Register("dummy", "test").
    71  	Register("ten", 10)
    72  
    73  func TestGenericString(t *testing.T) {
    74  	obj := testObj{
    75  		Expr:     "5 + 3 + ten",
    76  		Tmpl:     "{{ 10 + 3 }}{{ ten }}",
    77  		ExprPtr:  common.Ptr("1 + 2 + ten"),
    78  		TmplPtr:  common.Ptr("{{ 4 + 3 }}{{ ten }}"),
    79  		Dummy:    "5 + 3 + ten",
    80  		DummyPtr: common.Ptr("5 + 3 + ten"),
    81  	}
    82  	err := Simplify(&obj, testMachine)
    83  	assert.NoError(t, err)
    84  	assert.Equal(t, "18", obj.Expr)
    85  	assert.Equal(t, "1310", obj.Tmpl)
    86  	assert.Equal(t, common.Ptr("13"), obj.ExprPtr)
    87  	assert.Equal(t, common.Ptr("710"), obj.TmplPtr)
    88  	assert.Equal(t, "5 + 3 + ten", obj.Dummy)
    89  	assert.Equal(t, common.Ptr("5 + 3 + ten"), obj.DummyPtr)
    90  }
    91  
    92  func TestGenericIntOrString(t *testing.T) {
    93  	obj := testObj{
    94  		IntExpr:    intstr.IntOrString{Type: intstr.String, StrVal: "5 + 3 + ten"},
    95  		IntTmpl:    intstr.IntOrString{Type: intstr.String, StrVal: "{{ 10 + 3 }}{{ ten }}"},
    96  		IntExprPtr: &intstr.IntOrString{Type: intstr.String, StrVal: "1 + 2 + ten"},
    97  		IntTmplPtr: &intstr.IntOrString{Type: intstr.String, StrVal: "{{ 4 + 3 }}{{ ten }}"},
    98  	}
    99  	err := Simplify(&obj, testMachine)
   100  	assert.NoError(t, err)
   101  	assert.Equal(t, "18", obj.IntExpr.String())
   102  	assert.Equal(t, "1310", obj.IntTmpl.String())
   103  	assert.Equal(t, "13", obj.IntExprPtr.String())
   104  	assert.Equal(t, "710", obj.IntTmplPtr.String())
   105  }
   106  
   107  func TestGenericSlice(t *testing.T) {
   108  	obj := testObj{
   109  		SliceExprStr:    []string{"200 + 100", "100 + 200", "ten", "abc"},
   110  		SliceExprStrPtr: &[]string{"200 + 100", "100 + 200", "ten", "abc"},
   111  		SliceExprObj:    []testObj2{{Expr: "10 + 5", Dummy: "3 + 2"}},
   112  	}
   113  	err := Simplify(&obj, testMachine)
   114  	assert.NoError(t, err)
   115  	assert.Equal(t, []string{"300", "300", "10", "abc"}, obj.SliceExprStr)
   116  	assert.Equal(t, &[]string{"300", "300", "10", "abc"}, obj.SliceExprStrPtr)
   117  	assert.Equal(t, []testObj2{{Expr: "15", Dummy: "3 + 2"}}, obj.SliceExprObj)
   118  }
   119  
   120  func TestGenericMap(t *testing.T) {
   121  	obj := testObj{
   122  		MapKeyVal:     map[string]string{"{{ 10 + 3 }}2": "{{ 3 + 5 }}"},
   123  		MapKeyTmpl:    map[string]string{"{{ 10 + 3 }}2": "{{ 3 + 5 }}"},
   124  		MapValTmpl:    map[string]string{"{{ 10 + 3 }}2": "{{ 3 + 5 }}"},
   125  		MapValIntTmpl: map[string]intstr.IntOrString{"{{ 10 + 3 }}2": {Type: intstr.String, StrVal: "{{ 3 + 5 }}"}},
   126  		MapTmplExpr:   map[string]string{"{{ 10 + 3 }}2": "3 + 5"},
   127  	}
   128  	err := Simplify(&obj, testMachine)
   129  	assert.NoError(t, err)
   130  	assert.Equal(t, map[string]string{"132": "8"}, obj.MapKeyVal)
   131  	assert.Equal(t, map[string]string{"132": "{{ 3 + 5 }}"}, obj.MapKeyTmpl)
   132  	assert.Equal(t, map[string]string{"{{ 10 + 3 }}2": "8"}, obj.MapValTmpl)
   133  	assert.Equal(t, map[string]intstr.IntOrString{"{{ 10 + 3 }}2": {Type: intstr.String, StrVal: "8"}}, obj.MapValIntTmpl)
   134  	assert.Equal(t, map[string]string{"132": "8"}, obj.MapTmplExpr)
   135  }
   136  
   137  func TestNestedObject(t *testing.T) {
   138  	obj := testObj{
   139  		Obj:         testObj2{Expr: "10 + 5", Dummy: "3 + 2"},
   140  		ObjPtr:      &testObj2{Expr: "10 + 8", Dummy: "33 + 2"},
   141  		DummyObj:    testObj2{Expr: "10 + 8", Dummy: "333 + 2"},
   142  		DummyObjPtr: &testObj2{Expr: "10 + 8", Dummy: "3333 + 2"},
   143  	}
   144  	err := Simplify(&obj, testMachine)
   145  	assert.NoError(t, err)
   146  	assert.Equal(t, testObj2{Expr: "15", Dummy: "3 + 2"}, obj.Obj)
   147  	assert.Equal(t, &testObj2{Expr: "18", Dummy: "33 + 2"}, obj.ObjPtr)
   148  	assert.Equal(t, testObj2{Expr: "10 + 8", Dummy: "333 + 2"}, obj.DummyObj)
   149  	assert.Equal(t, &testObj2{Expr: "10 + 8", Dummy: "3333 + 2"}, obj.DummyObjPtr)
   150  }
   151  
   152  func TestGenericNotMutateStringPointer(t *testing.T) {
   153  	ptr := common.Ptr("200 + 10")
   154  	obj := testObj{
   155  		ExprPtr: ptr,
   156  	}
   157  	_ = Simplify(&obj, testMachine)
   158  	assert.Equal(t, common.Ptr("200 + 10"), ptr)
   159  }
   160  
   161  func TestGenericCompileError(t *testing.T) {
   162  	got := testObj{
   163  		Tmpl: "{{ 1 + 2 }}{{ 3",
   164  	}
   165  	err := Simplify(&got)
   166  
   167  	assert.Contains(t, fmt.Sprintf("%v", err), "Tmpl: template error")
   168  }
   169  
   170  func TestGenericForceSimplify(t *testing.T) {
   171  	got := corev1.Volume{
   172  		Name: "{{ 3 + 2 }}{{ 5 }}",
   173  		VolumeSource: corev1.VolumeSource{
   174  			ConfigMap: &corev1.ConfigMapVolumeSource{
   175  				LocalObjectReference: corev1.LocalObjectReference{Name: "{{ 4433 }}"},
   176  			},
   177  		},
   178  	}
   179  	err := SimplifyForce(&got)
   180  
   181  	want := corev1.Volume{
   182  		Name: "55",
   183  		VolumeSource: corev1.VolumeSource{
   184  			ConfigMap: &corev1.ConfigMapVolumeSource{
   185  				LocalObjectReference: corev1.LocalObjectReference{Name: "4433"},
   186  			},
   187  		},
   188  	}
   189  
   190  	assert.NoError(t, err)
   191  	assert.Equal(t, want, got)
   192  }
   193  
   194  func TestGenericForceSimplifyNested(t *testing.T) {
   195  	got := testObjNested{
   196  		Value: corev1.Volume{
   197  			Name: "{{ 3 + 2 }}{{ 5 }}",
   198  			VolumeSource: corev1.VolumeSource{
   199  				ConfigMap: &corev1.ConfigMapVolumeSource{
   200  					LocalObjectReference: corev1.LocalObjectReference{Name: "{{ 4433 }}"},
   201  				},
   202  			},
   203  		},
   204  		Dummy: corev1.Volume{
   205  			Name: "{{ 3 + 2 }}{{ 5 }}",
   206  			VolumeSource: corev1.VolumeSource{
   207  				ConfigMap: &corev1.ConfigMapVolumeSource{
   208  					LocalObjectReference: corev1.LocalObjectReference{Name: "{{ 4433 }}"},
   209  				},
   210  			},
   211  		},
   212  	}
   213  	err := Simplify(&got)
   214  
   215  	want := testObjNested{
   216  		Value: corev1.Volume{
   217  			Name: "55",
   218  			VolumeSource: corev1.VolumeSource{
   219  				ConfigMap: &corev1.ConfigMapVolumeSource{
   220  					LocalObjectReference: corev1.LocalObjectReference{Name: "4433"},
   221  				},
   222  			},
   223  		},
   224  		Dummy: corev1.Volume{
   225  			Name: "{{ 3 + 2 }}{{ 5 }}",
   226  			VolumeSource: corev1.VolumeSource{
   227  				ConfigMap: &corev1.ConfigMapVolumeSource{
   228  					LocalObjectReference: corev1.LocalObjectReference{Name: "{{ 4433 }}"},
   229  				},
   230  			},
   231  		},
   232  	}
   233  
   234  	assert.NoError(t, err)
   235  	assert.Equal(t, want, got)
   236  }
   237  
   238  func TestGenericSimplifyWithStringEnums(t *testing.T) {
   239  	got := testObjWithStringEnums{
   240  		Value: "{{ 3 + 2 }}{{ 5 }}",
   241  		Dummy: "{{ 4433 }}",
   242  	}
   243  	err := Simplify(&got)
   244  
   245  	want := testObjWithStringEnums{
   246  		Value: "55",
   247  		Dummy: "{{ 4433 }}",
   248  	}
   249  
   250  	assert.NoError(t, err)
   251  	assert.Equal(t, want, got)
   252  }
   253  
   254  func TestGenericSimplifyWithStringEnumPointers(t *testing.T) {
   255  	got := testObjWithStringEnumPointers{
   256  		Value: common.Ptr[testEnum]("{{ 3 + 2 }}{{ 5 }}"),
   257  		Dummy: common.Ptr[testEnum]("{{ 4433 }}"),
   258  	}
   259  	err := Simplify(&got)
   260  
   261  	want := testObjWithStringEnumPointers{
   262  		Value: common.Ptr[testEnum]("55"),
   263  		Dummy: common.Ptr[testEnum]("{{ 4433 }}"),
   264  	}
   265  
   266  	assert.NoError(t, err)
   267  	assert.Equal(t, want, got)
   268  }