istio.io/istio@v0.0.0-20240520182934-d79c90f27776/operator/pkg/util/yaml_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 "reflect" 19 "testing" 20 ) 21 22 func TestToYAML(t *testing.T) { 23 tests := []struct { 24 desc string 25 inVals any 26 expectedOut string 27 }{ 28 { 29 desc: "valid-yaml", 30 inVals: map[string]any{ 31 "foo": "bar", 32 "yo": map[string]any{ 33 "istio": "bar", 34 }, 35 }, 36 expectedOut: `foo: bar 37 yo: 38 istio: bar 39 `, 40 }, 41 { 42 desc: "alphabetical", 43 inVals: map[string]any{ 44 "foo": "yaml", 45 "abc": "f", 46 }, 47 expectedOut: `abc: f 48 foo: yaml 49 `, 50 }, 51 { 52 desc: "expected-err-nil", 53 inVals: nil, 54 expectedOut: "null\n", 55 }, 56 } 57 for _, tt := range tests { 58 t.Run(tt.desc, func(t *testing.T) { 59 if got := ToYAML(tt.inVals); got != tt.expectedOut { 60 t.Errorf("%s: expected out %v got %s", tt.desc, tt.expectedOut, got) 61 } 62 }) 63 } 64 } 65 66 func TestOverlayTrees(t *testing.T) { 67 tests := []struct { 68 desc string 69 inBase map[string]any 70 inOverlays map[string]any 71 expectedOverlay map[string]any 72 expectedErr error 73 }{ 74 { 75 desc: "overlay-valid", 76 inBase: map[string]any{ 77 "foo": "bar", 78 "baz": "naz", 79 }, 80 inOverlays: map[string]any{ 81 "foo": "laz", 82 }, 83 expectedOverlay: map[string]any{ 84 "baz": "naz", 85 "foo": "laz", 86 }, 87 expectedErr: nil, 88 }, 89 { 90 desc: "overlay-key-does-not-exist", 91 inBase: map[string]any{ 92 "foo": "bar", 93 "baz": "naz", 94 }, 95 inOverlays: map[string]any{ 96 "i-dont-exist": "i-really-dont-exist", 97 }, 98 expectedOverlay: map[string]any{ 99 "baz": "naz", 100 "foo": "bar", 101 "i-dont-exist": "i-really-dont-exist", 102 }, 103 expectedErr: nil, 104 }, 105 { 106 desc: "remove-key-val", 107 inBase: map[string]any{ 108 "foo": "bar", 109 }, 110 inOverlays: map[string]any{ 111 "foo": nil, 112 }, 113 expectedOverlay: map[string]any{}, 114 expectedErr: nil, 115 }, 116 } 117 for _, tt := range tests { 118 t.Run(tt.desc, func(t *testing.T) { 119 if gotOverlays, err := OverlayTrees(tt.inBase, tt.inOverlays); !reflect.DeepEqual(gotOverlays, tt.expectedOverlay) || 120 ((err != nil && tt.expectedErr == nil) || (err == nil && tt.expectedErr != nil)) { 121 t.Errorf("%s: expected overlay & err %v %v got %v %v", tt.desc, tt.expectedOverlay, tt.expectedErr, 122 gotOverlays, err) 123 } 124 }) 125 } 126 } 127 128 func TestOverlayYAML(t *testing.T) { 129 tests := []struct { 130 desc string 131 base string 132 overlay string 133 expect string 134 err error 135 }{ 136 { 137 desc: "overlay-yaml", 138 base: `foo: bar 139 yo: lo 140 `, 141 overlay: `yo: go`, 142 expect: `foo: bar 143 yo: go 144 `, 145 err: nil, 146 }, 147 { 148 desc: "combine-yaml", 149 base: `foo: bar`, 150 overlay: `baz: razmatazz`, 151 expect: `baz: razmatazz 152 foo: bar 153 `, 154 err: nil, 155 }, 156 { 157 desc: "blank", 158 base: `R#)*J#FN`, 159 overlay: `FM#)M#F(*#M`, 160 expect: "FM#)M#F(*#M\n", 161 err: nil, 162 }, 163 } 164 for _, tt := range tests { 165 t.Run(tt.desc, func(t *testing.T) { 166 if got, err := OverlayYAML(tt.base, tt.overlay); got != tt.expect || ((tt.err != nil && err == nil) || (tt.err == nil && err != nil)) { 167 t.Errorf("%s: expected overlay&err %v %v got %v %v", tt.desc, tt.expect, tt.err, got, err) 168 } 169 }) 170 } 171 } 172 173 func TestYAMLDiff(t *testing.T) { 174 tests := []struct { 175 desc string 176 diff1 string 177 diff2 string 178 expect string 179 }{ 180 { 181 desc: "1-line-diff", 182 diff1: `hola: yo 183 foo: bar 184 goo: tar 185 `, 186 diff2: `hola: yo 187 foo: bar 188 notgoo: nottar 189 `, 190 expect: ` foo: bar 191 -goo: tar 192 hola: yo 193 +notgoo: nottar 194 `, 195 }, 196 { 197 desc: "no-diff", 198 diff1: `foo: bar`, 199 diff2: `foo: bar`, 200 expect: ``, 201 }, 202 { 203 desc: "invalid-yaml", 204 diff1: `Ij#**#f#`, 205 diff2: `fm*##)n`, 206 expect: "error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go value of type map[string]interface {}", 207 }, 208 } 209 for _, tt := range tests { 210 t.Run(tt.desc, func(t *testing.T) { 211 if got := YAMLDiff(tt.diff1, tt.diff2); got != tt.expect { 212 t.Errorf("%s: expect %v got %v", tt.desc, tt.expect, got) 213 } 214 }) 215 } 216 } 217 218 func TestMultipleYAMLDiff(t *testing.T) { 219 tests := []struct { 220 desc string 221 diff1 string 222 diff2 string 223 expect string 224 }{ 225 { 226 desc: "1-line-diff", 227 diff1: `hola: yo 228 foo: bar 229 goo: tar 230 --- 231 hola: yo1 232 foo: bar1 233 goo: tar1 234 `, 235 diff2: `hola: yo 236 foo: bar 237 notgoo: nottar 238 `, 239 expect: ` foo: bar 240 -goo: tar 241 hola: yo 242 +notgoo: nottar 243 244 -foo: bar1 245 -goo: tar1 246 -hola: yo1 247 +{} 248 `, 249 }, 250 { 251 desc: "no-diff", 252 diff1: `foo: bar 253 --- 254 foo: bar1 255 `, 256 diff2: `foo: bar 257 --- 258 foo: bar1 259 `, 260 expect: ``, 261 }, 262 } 263 for _, tt := range tests { 264 t.Run(tt.desc, func(t *testing.T) { 265 if got := YAMLDiff(tt.diff1, tt.diff2); got != tt.expect { 266 t.Errorf("%s: expect %v got %v", tt.desc, tt.expect, got) 267 } 268 }) 269 } 270 } 271 272 func TestIsYAMLEqual(t *testing.T) { 273 tests := []struct { 274 desc string 275 in1 string 276 in2 string 277 expect bool 278 }{ 279 { 280 desc: "yaml-equal", 281 in1: `foo: bar`, 282 in2: `foo: bar`, 283 expect: true, 284 }, 285 { 286 desc: "bad-yaml-1", 287 in1: "O#JF*()#", 288 in2: `foo: bar`, 289 expect: false, 290 }, 291 { 292 desc: "bad-yaml-2", 293 in1: `foo: bar`, 294 in2: "#OHJ*#()F", 295 expect: false, 296 }, 297 { 298 desc: "yaml-not-equal", 299 in1: `zinc: iron 300 stoichiometry: avagadro 301 `, 302 in2: `i-swear: i-am 303 definitely-not: in1 304 `, 305 expect: false, 306 }, 307 } 308 for _, tt := range tests { 309 t.Run(tt.desc, func(t *testing.T) { 310 if got := IsYAMLEqual(tt.in1, tt.in2); got != tt.expect { 311 t.Errorf("%v: got %v want %v", tt.desc, got, tt.expect) 312 } 313 }) 314 } 315 } 316 317 func TestIsYAMLEmpty(t *testing.T) { 318 tests := []struct { 319 desc string 320 in string 321 expect bool 322 }{ 323 { 324 desc: "completely-empty", 325 in: "", 326 expect: true, 327 }, 328 { 329 desc: "comment-logically-empty", 330 in: `# this is a comment 331 # this is another comment that serves no purpose 332 # (like all comments usually do) 333 `, 334 expect: true, 335 }, 336 { 337 desc: "start-yaml", 338 in: `--- I dont mean anything`, 339 expect: true, 340 }, 341 { 342 desc: "combine-comments-and-yaml", 343 in: `#this is another comment 344 foo: bar 345 # ^ that serves purpose 346 `, 347 expect: false, 348 }, 349 { 350 desc: "yaml-not-empty", 351 in: `foo: bar`, 352 expect: false, 353 }, 354 } 355 for _, tt := range tests { 356 t.Run(tt.desc, func(t *testing.T) { 357 if got := IsYAMLEmpty(tt.in); got != tt.expect { 358 t.Errorf("%v: expect %v got %v", tt.desc, tt.expect, got) 359 } 360 }) 361 } 362 }