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 }