istio.io/istio@v0.0.0-20240520182934-d79c90f27776/operator/pkg/util/util_test.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package util 16 17 import ( 18 "errors" 19 "testing" 20 ) 21 22 func TestParseValue(t *testing.T) { 23 tests := []struct { 24 desc string 25 in string 26 want any 27 }{ 28 { 29 desc: "empty", 30 in: "", 31 want: "", 32 }, 33 { 34 desc: "true", 35 in: "true", 36 want: true, 37 }, 38 { 39 desc: "false", 40 in: "false", 41 want: false, 42 }, 43 { 44 desc: "numeric-one", 45 in: "1", 46 want: 1, 47 }, 48 { 49 desc: "numeric-zero", 50 in: "0", 51 want: 0, 52 }, 53 { 54 desc: "numeric-large", 55 in: "12345678", 56 want: 12345678, 57 }, 58 { 59 desc: "numeric-negative", 60 in: "-12345678", 61 want: -12345678, 62 }, 63 { 64 desc: "float", 65 in: "1.23456", 66 want: 1.23456, 67 }, 68 { 69 desc: "float-zero", 70 in: "0.00", 71 want: 0.00, 72 }, 73 { 74 desc: "float-negative", 75 in: "-6.54321", 76 want: -6.54321, 77 }, 78 { 79 desc: "string", 80 in: "foobar", 81 want: "foobar", 82 }, 83 { 84 desc: "string-number-prefix", 85 in: "123foobar", 86 want: "123foobar", 87 }, 88 } 89 for _, tt := range tests { 90 t.Run(tt.desc, func(t *testing.T) { 91 if got, want := ParseValue(tt.in), tt.want; !(got == want) { 92 t.Errorf("%s: got:%v, want:%v", tt.desc, got, want) 93 } 94 }) 95 } 96 } 97 98 func TestConsolidateLog(t *testing.T) { 99 tests := []struct { 100 desc string 101 in string 102 want string 103 }{ 104 { 105 desc: "empty", 106 in: "", 107 want: "", 108 }, 109 { 110 desc: "2 errors once", 111 in: "err1\nerr2\n", 112 want: "err1 (repeated 1 times)\nerr2 (repeated 1 times)\n", 113 }, 114 { 115 desc: "3 errors multiple times", 116 in: "err1\nerr2\nerr3\nerr1\nerr2\nerr3\nerr3\nerr3\n", 117 want: "err1 (repeated 2 times)\nerr2 (repeated 2 times)\nerr3 (repeated 4 times)\n", 118 }, 119 } 120 for _, tt := range tests { 121 t.Run(tt.desc, func(t *testing.T) { 122 if got, want := ConsolidateLog(tt.in), tt.want; !(got == want) { 123 t.Errorf("%s: got:%s, want:%s", tt.desc, got, want) 124 } 125 }) 126 } 127 } 128 129 func TestStringBoolMapToSlice(t *testing.T) { 130 tests := []struct { 131 desc string 132 in map[string]bool 133 want []string 134 }{ 135 { 136 desc: "empty", 137 in: make(map[string]bool), 138 want: make([]string, 0), 139 }, 140 { 141 desc: "", 142 in: map[string]bool{ 143 "yo": true, 144 "yolo": false, 145 "test1": true, 146 "water bottle": false, 147 "baseball hat": true, 148 }, 149 want: []string{ 150 "yo", 151 "test1", 152 "baseball hat", 153 }, 154 }, 155 } 156 for _, tt := range tests { 157 t.Run(tt.desc, func(t *testing.T) { 158 if got, want := StringBoolMapToSlice(tt.in), tt.want; !(sameStringSlice(got, want)) { 159 t.Errorf("%s: got:%s, want: %s", tt.desc, got, want) 160 } 161 }) 162 } 163 } 164 165 // Helper function to check if values in 2 slices are the same, 166 // no correspondence to order 167 func sameStringSlice(x, y []string) bool { 168 if len(x) != len(y) { 169 return false 170 } 171 diff := make(map[string]int, len(x)) 172 for _, _x := range x { 173 diff[_x]++ 174 } 175 for _, _y := range y { 176 if _, ok := diff[_y]; !ok { 177 return false 178 } 179 diff[_y]-- 180 if diff[_y] == 0 { 181 delete(diff, _y) 182 } 183 } 184 return len(diff) == 0 185 } 186 187 func TestRenderTemplate(t *testing.T) { 188 type tmplValue struct { 189 Name string 190 Proxy string 191 } 192 tests := []struct { 193 desc string 194 template string 195 in tmplValue 196 want string 197 err error 198 }{ 199 { 200 desc: "valid-template", 201 template: "{{.Name}} uses {{.Proxy}} as sidecar", 202 in: tmplValue{ 203 Name: "istio", 204 Proxy: "envoy", 205 }, 206 want: "istio uses envoy as sidecar", 207 err: nil, 208 }, 209 { 210 desc: "empty-template", 211 template: "", 212 in: tmplValue{ 213 Name: "istio", 214 Proxy: "envoy", 215 }, 216 want: "", 217 err: nil, 218 }, 219 { 220 desc: "template with no template strings", 221 template: "this template is without handlebar expressions", 222 in: tmplValue{ 223 Name: "istio", 224 Proxy: "envoy", 225 }, 226 want: "this template is without handlebar expressions", 227 err: nil, 228 }, 229 { 230 desc: "template with missing variable", 231 template: "{{ .Name }} has replaced its control plane with {{ .Istiod }} component", 232 in: tmplValue{ 233 Name: "istio", 234 Proxy: "envoy", 235 }, 236 want: "", 237 err: errors.New(""), 238 }, 239 } 240 for _, tt := range tests { 241 t.Run(tt.desc, func(t *testing.T) { 242 got, err := RenderTemplate(tt.template, tt.in) 243 if got != tt.want { 244 t.Errorf("%s: got :%v, wanted output: %v", tt.desc, got, tt.want) 245 } 246 247 if (err == nil && tt.err != nil) || (err != nil && tt.err == nil) { 248 t.Errorf("%s: got error :%v, wanted error: %v", tt.desc, err, tt.err) 249 } 250 }) 251 } 252 }