github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/utils/merge_test.go (about) 1 package utils_test 2 3 import ( 4 "fmt" 5 "reflect" 6 "testing" 7 8 "github.com/masterhung0112/hk_server/v5/utils" 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 ) 12 13 // Test merging maps alone. This isolates the complexity of merging maps from merging maps recursively in 14 // a struct/ptr/etc. 15 // Remember that for our purposes, "merging" means replacing base with patch if patch is /anything/ other than nil. 16 func TestMergeWithMaps(t *testing.T) { 17 t.Run("merge maps where patch is longer", func(t *testing.T) { 18 m1 := map[string]int{"this": 1, "is": 2, "a map": 3} 19 m2 := map[string]int{"this": 1, "is": 3, "a second map": 3, "another key": 4} 20 21 expected := map[string]int{"this": 1, "is": 3, "a second map": 3, "another key": 4} 22 merged, err := mergeStringIntMap(m1, m2) 23 require.NoError(t, err) 24 25 assert.Equal(t, expected, merged) 26 }) 27 28 t.Run("merge maps where base is longer", func(t *testing.T) { 29 m1 := map[string]int{"this": 1, "is": 2, "a map": 3, "with": 4, "more keys": -12} 30 m2 := map[string]int{"this": 1, "is": 3, "a second map": 3} 31 expected := map[string]int{"this": 1, "is": 3, "a second map": 3} 32 33 merged, err := mergeStringIntMap(m1, m2) 34 require.NoError(t, err) 35 36 assert.Equal(t, expected, merged) 37 }) 38 39 t.Run("merge maps where base is empty", func(t *testing.T) { 40 m1 := make(map[string]int) 41 m2 := map[string]int{"this": 1, "is": 3, "a second map": 3, "another key": 4} 42 43 expected := map[string]int{"this": 1, "is": 3, "a second map": 3, "another key": 4} 44 merged, err := mergeStringIntMap(m1, m2) 45 require.NoError(t, err) 46 47 assert.Equal(t, expected, merged) 48 }) 49 50 t.Run("merge maps where patch is empty", func(t *testing.T) { 51 m1 := map[string]int{"this": 1, "is": 3, "a map": 3, "another key": 4} 52 var m2 map[string]int 53 expected := map[string]int{"this": 1, "is": 3, "a map": 3, "another key": 4} 54 55 merged, err := mergeStringIntMap(m1, m2) 56 require.NoError(t, err) 57 58 assert.Equal(t, expected, merged) 59 }) 60 61 t.Run("merge map[string]*int patch with different keys and values", func(t *testing.T) { 62 m1 := map[string]*int{"this": newInt(1), "is": newInt(3), "a key": newInt(3)} 63 m2 := map[string]*int{"this": newInt(2), "is": newInt(3), "a key": newInt(4)} 64 expected := map[string]*int{"this": newInt(2), "is": newInt(3), "a key": newInt(4)} 65 66 merged, err := mergeStringPtrIntMap(m1, m2) 67 require.NoError(t, err) 68 69 assert.Equal(t, expected, merged) 70 }) 71 72 t.Run("merge map[string]*int patch has nil keys -- doesn't matter, maps overwrite completely", func(t *testing.T) { 73 m1 := map[string]*int{"this": newInt(1), "is": newInt(3), "a key": newInt(3)} 74 m2 := map[string]*int{"this": newInt(1), "is": nil, "a key": newInt(3)} 75 expected := map[string]*int{"this": newInt(1), "is": nil, "a key": newInt(3)} 76 77 merged, err := mergeStringPtrIntMap(m1, m2) 78 require.NoError(t, err) 79 80 assert.Equal(t, expected, merged) 81 }) 82 83 t.Run("merge map[string]*int base has nil vals -- overwrite base with patch", func(t *testing.T) { 84 m1 := map[string]*int{"this": newInt(1), "is": nil, "base key": newInt(4)} 85 m2 := map[string]*int{"this": newInt(1), "is": newInt(3), "a key": newInt(3)} 86 expected := map[string]*int{"this": newInt(1), "is": newInt(3), "a key": newInt(3)} 87 88 merged, err := mergeStringPtrIntMap(m1, m2) 89 require.NoError(t, err) 90 91 assert.Equal(t, expected, merged) 92 }) 93 94 t.Run("merge map[string]*int base has nil vals -- but patch is nil, so keep base", func(t *testing.T) { 95 m1 := map[string]*int{"this": newInt(1), "is": nil, "base key": newInt(4)} 96 var m2 map[string]*int 97 expected := map[string]*int{"this": newInt(1), "is": nil, "base key": newInt(4)} 98 99 merged, err := mergeStringPtrIntMap(m1, m2) 100 require.NoError(t, err) 101 102 assert.Equal(t, expected, merged) 103 }) 104 105 t.Run("merge map[string]*int pointers are not copied - change in base do not affect merged", func(t *testing.T) { 106 // that should never happen, since patch overwrites completely 107 m1 := map[string]*int{"this": newInt(1), "is": newInt(3), "a key": newInt(4)} 108 m2 := map[string]*int{"this": newInt(1), "a key": newInt(5)} 109 expected := map[string]*int{"this": newInt(1), "a key": newInt(5)} 110 111 merged, err := mergeStringPtrIntMap(m1, m2) 112 require.NoError(t, err) 113 114 assert.Equal(t, expected, merged) 115 *m1["this"] = 6 116 assert.Equal(t, 1, *merged["this"]) 117 }) 118 119 t.Run("merge map[string]*int pointers are not copied - change in patched do not affect merged", func(t *testing.T) { 120 m1 := map[string]*int{"this": newInt(1), "is": newInt(3), "a key": newInt(4)} 121 m2 := map[string]*int{"this": newInt(2), "a key": newInt(5)} 122 expected := map[string]*int{"this": newInt(2), "a key": newInt(5)} 123 124 merged, err := mergeStringPtrIntMap(m1, m2) 125 require.NoError(t, err) 126 127 assert.Equal(t, expected, merged) 128 *m2["this"] = 6 129 assert.Equal(t, 2, *merged["this"]) 130 }) 131 132 t.Run("merge map[string][]int overwrite base with patch", func(t *testing.T) { 133 m1 := map[string][]int{"this": {1, 2, 3}, "is": {4, 5, 6}} 134 m2 := map[string][]int{"this": {1, 2, 3}, "new": {7, 8, 9}} 135 expected := map[string][]int{"this": {1, 2, 3}, "new": {7, 8, 9}} 136 137 merged, err := mergeStringSliceIntMap(m1, m2) 138 require.NoError(t, err) 139 140 assert.Equal(t, expected, merged) 141 }) 142 143 t.Run("merge map[string][]int nil in patch /does/ overwrite base", func(t *testing.T) { 144 m1 := map[string][]int{"this": {1, 2, 3}, "is": {4, 5, 6}} 145 m2 := map[string][]int{"this": {1, 2, 3}, "is": nil} 146 expected := map[string][]int{"this": {1, 2, 3}, "is": nil} 147 148 merged, err := mergeStringSliceIntMap(m1, m2) 149 require.NoError(t, err) 150 151 assert.Equal(t, expected, merged) 152 }) 153 154 t.Run("merge map[string][]int nil in base is overwritten", func(t *testing.T) { 155 m1 := map[string][]int{"this": {1, 2, 3}, "is": nil} 156 m2 := map[string][]int{"this": {1, 2, 3}, "is": {4, 5, 6}} 157 expected := map[string][]int{"this": {1, 2, 3}, "is": {4, 5, 6}} 158 merged, err := mergeStringSliceIntMap(m1, m2) 159 require.NoError(t, err) 160 161 assert.Equal(t, expected, merged) 162 }) 163 164 t.Run("merge map[string][]int nil in base is overwritten even without matching key", func(t *testing.T) { 165 m1 := map[string][]int{"this": {1, 2, 3}, "is": nil} 166 m2 := map[string][]int{"this": {1, 2, 3}, "new": {4, 5, 6}} 167 expected := map[string][]int{"this": {1, 2, 3}, "new": {4, 5, 6}} 168 169 merged, err := mergeStringSliceIntMap(m1, m2) 170 require.NoError(t, err) 171 172 assert.Equal(t, expected, merged) 173 }) 174 175 t.Run("merge map[string][]int slice is cloned - change in base does not affect merged", func(t *testing.T) { 176 // shouldn't, is patch clobbers 177 m1 := map[string][]int{"this": {1, 2, 3}, "is": {4, 5, 6}} 178 m2 := map[string][]int{"this": {1, 2, 3}, "new": {7, 8, 9}} 179 expected := map[string][]int{"this": {1, 2, 3}, "new": {7, 8, 9}} 180 181 merged, err := mergeStringSliceIntMap(m1, m2) 182 require.NoError(t, err) 183 184 assert.Equal(t, expected, merged) 185 m1["this"][0] = 99 186 assert.Equal(t, 1, merged["this"][0]) 187 }) 188 189 t.Run("merge map[string][]int slice is cloned - change in patch does not affect merged", func(t *testing.T) { 190 m1 := map[string][]int{"this": {1, 2, 3}, "is": {4, 5, 6}} 191 m2 := map[string][]int{"this": {1, 2, 3}, "new": {7, 8, 9}} 192 expected := map[string][]int{"this": {1, 2, 3}, "new": {7, 8, 9}} 193 194 merged, err := mergeStringSliceIntMap(m1, m2) 195 require.NoError(t, err) 196 197 assert.Equal(t, expected, merged) 198 m2["new"][1] = 0 199 assert.Equal(t, 8, merged["new"][1]) 200 }) 201 202 t.Run("merge map[string]map[string]*int", func(t *testing.T) { 203 m1 := map[string]map[string]*int{"this": {"second": newInt(99)}, "base": {"level": newInt(10)}} 204 m2 := map[string]map[string]*int{"this": {"second": newInt(77)}, "patch": {"level": newInt(15)}} 205 expected := map[string]map[string]*int{"this": {"second": newInt(77)}, "patch": {"level": newInt(15)}} 206 207 merged, err := mergeMapOfMap(m1, m2) 208 require.NoError(t, err) 209 210 assert.Equal(t, expected, merged) 211 }) 212 213 t.Run("merge map[string]map[string]*int, patch has nil keys -- /do/ overwrite base with nil", func(t *testing.T) { 214 m1 := map[string]map[string]*int{"this": {"second": newInt(99)}, "base": {"level": newInt(10)}} 215 m2 := map[string]map[string]*int{"this": {"second": nil}, "base": nil, "patch": {"level": newInt(15)}} 216 expected := map[string]map[string]*int{"this": {"second": nil}, "base": nil, "patch": {"level": newInt(15)}} 217 218 merged, err := mergeMapOfMap(m1, m2) 219 require.NoError(t, err) 220 221 assert.Equal(t, expected, merged) 222 }) 223 224 t.Run("merge map[string]map[string]*int, base has nil vals -- overwrite base with patch", func(t *testing.T) { 225 m1 := map[string]map[string]*int{"this": {"second": nil}, "base": nil} 226 m2 := map[string]map[string]*int{"this": {"second": newInt(77)}, "base": {"level": newInt(10)}, "patch": {"level": newInt(15)}} 227 expected := map[string]map[string]*int{"this": {"second": newInt(77)}, "base": {"level": newInt(10)}, "patch": {"level": newInt(15)}} 228 229 merged, err := mergeMapOfMap(m1, m2) 230 require.NoError(t, err) 231 232 assert.Equal(t, expected, merged) 233 }) 234 235 t.Run("merge map[string]map[string]*int, pointers are not copied - change in base does not affect merged", func(t *testing.T) { 236 // shouldn't, if we're overwriting completely 237 m1 := map[string]map[string]*int{"this": {"second": newInt(99)}, "base": {"level": newInt(10)}, "are belong": {"to us": newInt(23)}} 238 m2 := map[string]map[string]*int{"base": {"level": newInt(10)}} 239 expected := map[string]map[string]*int{"base": {"level": newInt(10)}} 240 241 merged, err := mergeMapOfMap(m1, m2) 242 require.NoError(t, err) 243 244 assert.Equal(t, expected, merged) 245 246 // test changing the map entry's referenced value 247 *m1["base"]["level"] = 347 248 assert.Equal(t, 10, *merged["base"]["level"]) 249 250 // test replacing map entry 251 m1["base"]["level"] = newInt(12) 252 assert.Equal(t, 10, *merged["base"]["level"]) 253 254 // test replacing a referenced map 255 m1["base"] = map[string]*int{"third": newInt(777)} 256 assert.Equal(t, 10, *merged["base"]["level"]) 257 258 }) 259 260 t.Run("merge map[string]map[string]*int, pointers are not copied - change in patch do not affect merged", func(t *testing.T) { 261 m1 := map[string]map[string]*int{"base": {"level": newInt(15)}} 262 m2 := map[string]map[string]*int{"this": {"second": newInt(99)}, "patch": {"level": newInt(10)}, 263 "are belong": {"to us": newInt(23)}} 264 expected := map[string]map[string]*int{"this": {"second": newInt(99)}, "patch": {"level": newInt(10)}, 265 "are belong": {"to us": newInt(23)}} 266 267 merged, err := mergeMapOfMap(m1, m2) 268 require.NoError(t, err) 269 270 assert.Equal(t, expected, merged) 271 272 // test replacing a referenced map 273 m2["this"] = map[string]*int{"third": newInt(777)} 274 assert.Equal(t, 99, *merged["this"]["second"]) 275 276 // test replacing map entry 277 m2["patch"]["level"] = newInt(12) 278 assert.Equal(t, 10, *merged["patch"]["level"]) 279 280 // test changing the map entry's referenced value 281 *m2["are belong"]["to us"] = 347 282 assert.Equal(t, 23, *merged["are belong"]["to us"]) 283 }) 284 285 t.Run("merge map[string]interface{}", func(t *testing.T) { 286 m1 := map[string]interface{}{"this": map[string]*int{"second": newInt(99)}, 287 "base": map[string]*int{"level": newInt(10)}} 288 m2 := map[string]interface{}{"this": map[string]*int{"second": newInt(77)}, 289 "patch": map[string]*int{"level": newInt(15)}} 290 expected := map[string]interface{}{"this": map[string]*int{"second": newInt(77)}, 291 "patch": map[string]*int{"level": newInt(15)}} 292 293 merged, err := mergeInterfaceMap(m1, m2) 294 require.NoError(t, err) 295 296 assert.Equal(t, expected, merged) 297 }) 298 299 t.Run("merge map[string]interface{}, patch has nil keys -- /do/ overwrite base with nil", func(t *testing.T) { 300 m1 := map[string]interface{}{"this": map[string]*int{"second": newInt(99)}} 301 m2 := map[string]interface{}{"this": map[string]*int{"second": nil}} 302 expected := map[string]interface{}{"this": map[string]*int{"second": nil}} 303 304 merged, err := mergeInterfaceMap(m1, m2) 305 require.NoError(t, err) 306 307 assert.Equal(t, expected, merged) 308 }) 309 310 t.Run("merge map[string]interface{}, patch has nil keys -- /do/ overwrite base with nil (more complex)", func(t *testing.T) { 311 m1 := map[string]interface{}{"this": map[string]*int{"second": newInt(99)}, 312 "base": map[string]*int{"level": newInt(10)}} 313 m2 := map[string]interface{}{"this": map[string]*int{"second": nil}, 314 "base": nil, "patch": map[string]*int{"level": newInt(15)}} 315 expected := map[string]interface{}{"this": map[string]*int{"second": nil}, 316 "base": nil, "patch": map[string]*int{"level": newInt(15)}} 317 318 merged, err := mergeInterfaceMap(m1, m2) 319 require.NoError(t, err) 320 321 assert.Equal(t, expected, merged) 322 }) 323 324 t.Run("merge map[string]map[string]*int, base has nil vals -- overwrite base with patch", func(t *testing.T) { 325 m1 := map[string]interface{}{"base": nil} 326 m2 := map[string]interface{}{"base": map[string]*int{"level": newInt(10)}} 327 expected := map[string]interface{}{"base": map[string]*int{"level": newInt(10)}} 328 329 merged, err := mergeInterfaceMap(m1, m2) 330 require.NoError(t, err) 331 332 assert.Equal(t, expected, merged) 333 }) 334 335 t.Run("merge map[string]map[string]*int, base has nil vals -- overwrite base with patch (more complex)", func(t *testing.T) { 336 m1 := map[string]interface{}{"this": map[string]*int{"second": nil}, "base": nil} 337 m2 := map[string]interface{}{"this": map[string]*int{"second": newInt(77)}, 338 "base": map[string]*int{"level": newInt(10)}, "patch": map[string]*int{"level": newInt(15)}} 339 expected := map[string]interface{}{"this": map[string]*int{"second": newInt(77)}, 340 "base": map[string]*int{"level": newInt(10)}, "patch": map[string]*int{"level": newInt(15)}} 341 342 merged, err := mergeInterfaceMap(m1, m2) 343 require.NoError(t, err) 344 345 assert.Equal(t, expected, merged) 346 }) 347 348 t.Run("merge map[string]interface{}, pointers are not copied - changes in base do not affect merged", func(t *testing.T) { 349 m1 := map[string]interface{}{"this": map[string]*int{"second": newInt(99)}, 350 "base": map[string]*int{"level": newInt(10)}, "are belong": map[string]*int{"to us": newInt(23)}} 351 m2 := map[string]interface{}{"this": map[string]*int{"second": newInt(99)}, 352 "base": map[string]*int{"level": newInt(10)}, "are belong": map[string]*int{"to us": newInt(23)}} 353 expected := map[string]interface{}{"this": map[string]*int{"second": newInt(99)}, 354 "base": map[string]*int{"level": newInt(10)}, "are belong": map[string]*int{"to us": newInt(23)}} 355 356 merged, err := mergeInterfaceMap(m1, m2) 357 require.NoError(t, err) 358 359 assert.Equal(t, expected, merged) 360 361 // test replacing a referenced map 362 m1["this"] = map[string]*int{"third": newInt(777)} 363 assert.Equal(t, 99, *merged["this"].(map[string]*int)["second"]) 364 365 // test replacing map entry 366 m1["base"].(map[string]*int)["level"] = newInt(12) 367 assert.Equal(t, 10, *merged["base"].(map[string]*int)["level"]) 368 369 // test changing the map entry's referenced value 370 *m1["are belong"].(map[string]*int)["to us"] = 347 371 assert.Equal(t, 23, *merged["are belong"].(map[string]*int)["to us"]) 372 }) 373 374 t.Run("merge map[string]interface{}, pointers are not copied - change in patch do not affect merged", func(t *testing.T) { 375 m1 := map[string]interface{}{"base": map[string]*int{"level": newInt(15)}} 376 m2 := map[string]interface{}{"this": map[string]*int{"second": newInt(99)}, 377 "patch": map[string]*int{"level": newInt(10)}, "are belong": map[string]*int{"to us": newInt(23)}} 378 expected := map[string]interface{}{"this": map[string]*int{"second": newInt(99)}, 379 "patch": map[string]*int{"level": newInt(10)}, "are belong": map[string]*int{"to us": newInt(23)}} 380 381 merged, err := mergeInterfaceMap(m1, m2) 382 require.NoError(t, err) 383 384 assert.Equal(t, expected, merged) 385 386 // test replacing a referenced map 387 m2["this"] = map[string]*int{"third": newInt(777)} 388 assert.Equal(t, 99, *merged["this"].(map[string]*int)["second"]) 389 390 // test replacing map entry 391 m2["patch"].(map[string]*int)["level"] = newInt(12) 392 assert.Equal(t, 10, *merged["patch"].(map[string]*int)["level"]) 393 394 // test changing the map entry's referenced value 395 *m2["are belong"].(map[string]*int)["to us"] = 347 396 assert.Equal(t, 23, *merged["are belong"].(map[string]*int)["to us"]) 397 }) 398 } 399 400 // Test merging slices alone. This isolates the complexity of merging slices from merging slices 401 // recursively in a struct/ptr/etc. 402 func TestMergeWithSlices(t *testing.T) { 403 t.Run("patch overwrites base slice", func(t *testing.T) { 404 m1 := []string{"this", "will", "be", "overwritten"} 405 m2 := []string{"this one", "will", "replace the other", "one", "and", "is", "longer"} 406 expected := []string{"this one", "will", "replace the other", "one", "and", "is", "longer"} 407 408 merged, err := mergeStringSlices(m1, m2) 409 require.NoError(t, err) 410 411 assert.Equal(t, expected, merged) 412 }) 413 414 t.Run("patch overwrites base even when base is longer", func(t *testing.T) { 415 m1 := []string{"this", "will", "be", "overwritten", "but", "not", "this"} 416 m2 := []string{"this one", "will", "replace the other", "one"} 417 expected := []string{"this one", "will", "replace the other", "one"} 418 419 merged, err := mergeStringSlices(m1, m2) 420 require.NoError(t, err) 421 422 assert.Equal(t, expected, merged) 423 }) 424 425 t.Run("patch overwrites when base is empty slice", func(t *testing.T) { 426 m1 := []string{} 427 m2 := []string{"this one", "will", "replace the other", "one"} 428 expected := []string{"this one", "will", "replace the other", "one"} 429 430 merged, err := mergeStringSlices(m1, m2) 431 require.NoError(t, err) 432 433 assert.Equal(t, expected, merged) 434 }) 435 436 t.Run("patch overwrites when base is nil", func(t *testing.T) { 437 var m1 []string 438 m2 := []string{"this one", "will", "replace the other", "one"} 439 expected := []string{"this one", "will", "replace the other", "one"} 440 441 merged, err := mergeStringSlices(m1, m2) 442 require.NoError(t, err) 443 444 assert.Equal(t, expected, merged) 445 }) 446 447 t.Run("patch overwites when patch is empty struct", func(t *testing.T) { 448 m1 := []string{"this", "will", "be", "overwritten"} 449 m2 := []string{} 450 expected := []string{} 451 452 merged, err := mergeStringSlices(m1, m2) 453 require.NoError(t, err) 454 455 assert.Equal(t, expected, merged) 456 }) 457 458 t.Run("use base where patch is nil", func(t *testing.T) { 459 m1 := []string{"this", "will", "not", "be", "overwritten"} 460 var m2 []string 461 expected := []string{"this", "will", "not", "be", "overwritten"} 462 463 merged, err := mergeStringSlices(m1, m2) 464 require.NoError(t, err) 465 466 assert.Equal(t, expected, merged) 467 }) 468 469 t.Run("return nil where both are nil", func(t *testing.T) { 470 var m1 []string 471 var m2 []string 472 expected := []string(nil) 473 474 merged, err := mergeStringSlices(m1, m2) 475 require.NoError(t, err) 476 477 assert.Equal(t, expected, merged) 478 }) 479 480 t.Run("return empty struct where both are empty", func(t *testing.T) { 481 m1 := []string{} 482 m2 := []string{} 483 expected := []string{} 484 485 merged, err := mergeStringSlices(m1, m2) 486 require.NoError(t, err) 487 488 assert.Equal(t, expected, merged) 489 }) 490 491 t.Run("patch is nil, slice is not copied. change in base will not affect merged", func(t *testing.T) { 492 m1 := []string{"this", "will", "not", "be", "overwritten"} 493 var m2 []string 494 expected := []string{"this", "will", "not", "be", "overwritten"} 495 496 merged, err := mergeStringSlices(m1, m2) 497 require.NoError(t, err) 498 499 assert.Equal(t, expected, merged) 500 m1[0] = "THAT" 501 assert.Equal(t, "this", merged[0]) 502 }) 503 504 t.Run("patch empty, slice is not copied. change in patch will not affect merged", func(t *testing.T) { 505 m1 := []string{"this", "will", "not", "be", "overwritten"} 506 m2 := []string{} 507 expected := []string{} 508 509 merged, err := mergeStringSlices(m1, m2) 510 require.NoError(t, err) 511 512 assert.Equal(t, expected, merged) 513 // of course this won't change merged, even if it did copy... but just in case. 514 m2 = append(m2, "test") 515 assert.Len(t, m2, 1) 516 assert.Empty(t, merged) 517 }) 518 519 t.Run("slice is not copied. change in patch will not affect merged", func(t *testing.T) { 520 var m1 []string 521 m2 := []string{"this", "will", "not", "be", "overwritten"} 522 expected := []string{"this", "will", "not", "be", "overwritten"} 523 524 merged, err := mergeStringSlices(m1, m2) 525 require.NoError(t, err) 526 527 assert.Equal(t, expected, merged) 528 m2[0] = "THAT" 529 assert.Equal(t, "this", merged[0]) 530 }) 531 532 t.Run("base overwritten, slice is not copied. change in patch will not affect merged", func(t *testing.T) { 533 m1 := []string{"this", "will", "be", "overwritten"} 534 m2 := []string{"that", "overwrote", "it"} 535 expected := []string{"that", "overwrote", "it"} 536 537 merged, err := mergeStringSlices(m1, m2) 538 require.NoError(t, err) 539 540 assert.Equal(t, expected, merged) 541 m2[0] = "THAT!!" 542 assert.Equal(t, "that", merged[0]) 543 }) 544 } 545 546 type evenSimpler struct { 547 B *bool 548 ES2 *evenSimpler2 549 } 550 551 func (e *evenSimpler) String() string { 552 if e == nil { 553 return "nil" 554 } 555 sb := "nil" 556 if e.B != nil { 557 sb = fmt.Sprintf("%t", *e.B) 558 } 559 return fmt.Sprintf("ES{B: %s, ES2: %s}", sb, e.ES2.String()) 560 } 561 562 type evenSimpler2 struct { 563 S *string 564 } 565 566 func (e *evenSimpler2) String() string { 567 if e == nil { 568 return "nil" 569 } 570 var s string 571 if e.S == nil { 572 s = "nil" 573 } else { 574 s = *e.S 575 } 576 return fmt.Sprintf("ES2{S: %s}", s) 577 } 578 579 func TestMergeWithEvenSimpler(t *testing.T) { 580 t.Run("evenSimplerStruct: base nils are overwritten by patch", func(t *testing.T) { 581 t1 := evenSimpler{newBool(true), &evenSimpler2{nil}} 582 t2 := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}} 583 expected := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}} 584 585 merged, err := mergeEvenSimpler(t1, t2) 586 require.NoError(t, err) 587 588 assert.Equal(t, expected, *merged) 589 }) 590 591 t.Run("evenSimplerStruct: patch nils are ignored", func(t *testing.T) { 592 t1 := evenSimpler{newBool(true), &evenSimpler2{newString("base")}} 593 t2 := evenSimpler{nil, &evenSimpler2{nil}} 594 expected := evenSimpler{newBool(true), &evenSimpler2{newString("base")}} 595 596 merged, err := mergeEvenSimpler(t1, t2) 597 require.NoError(t, err) 598 599 assert.Equal(t, expected, *merged) 600 }) 601 602 t.Run("evenSimplerStruct: can handle both nils, merged will have nil (not zero value)", func(t *testing.T) { 603 t1 := evenSimpler{nil, &evenSimpler2{nil}} 604 t2 := evenSimpler{nil, &evenSimpler2{nil}} 605 expected := evenSimpler{nil, &evenSimpler2{nil}} 606 607 merged, err := mergeEvenSimpler(t1, t2) 608 require.NoError(t, err) 609 610 assert.Equal(t, expected, *merged) 611 }) 612 613 t.Run("evenSimplerStruct: can handle both nils (ptr to ptr), merged will have nil (not zero value)", func(t *testing.T) { 614 t1 := evenSimpler{newBool(true), nil} 615 t2 := evenSimpler{newBool(true), nil} 616 expected := evenSimpler{newBool(true), nil} 617 618 merged, err := mergeEvenSimpler(t1, t2) 619 require.NoError(t, err) 620 621 assert.Equal(t, expected, *merged) 622 }) 623 624 t.Run("evenSimplerStruct: base nils (ptr to ptr) are overwritten by patch", func(t *testing.T) { 625 t1 := evenSimpler{newBool(true), nil} 626 t2 := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}} 627 expected := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}} 628 629 merged, err := mergeEvenSimpler(t1, t2) 630 require.NoError(t, err) 631 632 assert.Equal(t, expected, *merged) 633 }) 634 635 t.Run("evenSimplerStruct: base nils (ptr to ptr) are overwritten by patch, and not copied - changes in patch don't affect merged", func(t *testing.T) { 636 t1 := evenSimpler{newBool(true), nil} 637 t2 := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}} 638 expected := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}} 639 640 merged, err := mergeEvenSimpler(t1, t2) 641 require.NoError(t, err) 642 643 assert.Equal(t, expected, *merged) 644 *t2.ES2.S = "new patch" 645 assert.Equal(t, "patch", *merged.ES2.S) 646 }) 647 648 t.Run("evenSimplerStruct: patch nils (ptr to ptr) do not overwrite base, and are not copied - changes in base don't affect merged", func(t *testing.T) { 649 t1 := evenSimpler{newBool(true), &evenSimpler2{newString("base")}} 650 t2 := evenSimpler{newBool(false), nil} 651 expected := evenSimpler{newBool(false), &evenSimpler2{newString("base")}} 652 653 merged, err := mergeEvenSimpler(t1, t2) 654 require.NoError(t, err) 655 656 assert.Equal(t, expected, *merged) 657 *t1.ES2.S = "new base" 658 assert.Equal(t, "base", *merged.ES2.S) 659 }) 660 661 } 662 663 type sliceStruct struct { 664 Sls []string 665 } 666 667 func TestMergeWithSliceStruct(t *testing.T) { 668 t.Run("patch nils are ignored - sliceStruct", func(t *testing.T) { 669 t1 := sliceStruct{[]string{"this", "is", "base"}} 670 t2 := sliceStruct{nil} 671 expected := sliceStruct{[]string{"this", "is", "base"}} 672 673 merged, err := mergeSliceStruct(t1, t2) 674 require.NoError(t, err) 675 676 assert.Equal(t, expected, *merged) 677 }) 678 679 t.Run("base nils are overwritten by patch - sliceStruct", func(t *testing.T) { 680 t1 := sliceStruct{nil} 681 t2 := sliceStruct{[]string{"this", "is", "patch"}} 682 expected := sliceStruct{[]string{"this", "is", "patch"}} 683 684 merged, err := mergeSliceStruct(t1, t2) 685 require.NoError(t, err) 686 687 assert.Equal(t, expected, *merged) 688 }) 689 690 t.Run("slices are not being copied or modified", func(t *testing.T) { 691 t1 := sliceStruct{[]string{"this", "is", "base"}} 692 t2 := sliceStruct{nil} 693 expected := sliceStruct{[]string{"this", "is", "base"}} 694 695 merged, err := mergeSliceStruct(t1, t2) 696 require.NoError(t, err) 697 698 assert.Equal(t, expected, *merged) 699 700 // changes in base do not affect merged 701 t1.Sls[0] = "test0" 702 assert.Equal(t, "this", merged.Sls[0]) 703 704 // changes in merged (on slice that was cloned from base) do not affect base 705 merged.Sls[1] = "test222" 706 assert.Equal(t, "is", t1.Sls[1]) 707 }) 708 709 t.Run("slices are not being copied or modified", func(t *testing.T) { 710 t1 := sliceStruct{nil} 711 t2 := sliceStruct{[]string{"this", "is", "patch"}} 712 expected := sliceStruct{[]string{"this", "is", "patch"}} 713 714 merged, err := mergeSliceStruct(t1, t2) 715 require.NoError(t, err) 716 717 assert.Equal(t, expected, *merged) 718 719 // changes in patch do not affect merged 720 t2.Sls[0] = "test0" 721 assert.Equal(t, "this", merged.Sls[0]) 722 723 // changes in merged (on slice that was cloned from patch) do not affect patch 724 merged.Sls[1] = "test222" 725 assert.Equal(t, "is", t2.Sls[1]) 726 }) 727 } 728 729 type mapPtr struct { 730 MP map[string]*evenSimpler2 731 } 732 733 func TestMergeWithMapPtr(t *testing.T) { 734 t.Run("patch nils overwrite - mapPtr - maps overwrite completely", func(t *testing.T) { 735 t1 := mapPtr{map[string]*evenSimpler2{"base key": {newString("base")}}} 736 t2 := mapPtr{map[string]*evenSimpler2{"base key": {nil}}} 737 expected := mapPtr{map[string]*evenSimpler2{"base key": {nil}}} 738 739 merged, err := mergeMapPtr(t1, t2) 740 require.NoError(t, err) 741 742 assert.Equal(t, expected, *merged) 743 }) 744 745 t.Run("patch nil structs are ignored - mapPtr - maps overwrite ", func(t *testing.T) { 746 t1 := mapPtr{map[string]*evenSimpler2{"base key": {newString("base")}}} 747 t2 := mapPtr{map[string]*evenSimpler2{"base key": nil}} 748 expected := mapPtr{map[string]*evenSimpler2{"base key": nil}} 749 750 merged, err := mergeMapPtr(t1, t2) 751 require.NoError(t, err) 752 753 assert.Equal(t, expected, *merged) 754 }) 755 } 756 757 type mapPtrState struct { 758 MP map[string]*state 759 } 760 type state struct { 761 Enable bool 762 } 763 764 func TestMergeWithMapPtrState(t *testing.T) { 765 t.Run("inside structs, patch map overwrites completely - mapPtrState", func(t *testing.T) { 766 t1 := mapPtrState{map[string]*state{"base key": {true}}} 767 t2 := mapPtrState{map[string]*state{"base key": nil}} 768 expected := mapPtrState{map[string]*state{"base key": nil}} 769 770 merged, err := mergeMapPtrState(t1, t2) 771 require.NoError(t, err) 772 773 assert.Equal(t, expected, *merged) 774 }) 775 776 t.Run("merge identical structs - simple", func(t *testing.T) { 777 t1 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true), 778 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 779 simple2{30, newString("test"), []string{"test1", "test2"}}, 780 &simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}} 781 t2 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true), 782 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 783 simple2{30, newString("test"), []string{"test1", "test2"}}, 784 &simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}} 785 expected := simple{42, 0, nil, newInt(45), newBool(true), 786 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 787 simple2{30, newString("test"), []string{"test1", "test2"}}, 788 &simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}} 789 790 merged, err := mergeSimple(t1, t2) 791 require.NoError(t, err) 792 793 assert.Equal(t, expected, *merged) 794 }) 795 796 t.Run("base nils are overwritten by patch", func(t *testing.T) { 797 t1 := simple{42, 42.2, newFloat64(932.2), newInt(45), nil, 798 []int{1, 2, 3}, nil, 799 simple2{30, nil, nil}, 800 nil} 801 t2 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true), 802 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 803 simple2{30, newString("test"), []string{"test1", "test2"}}, 804 &simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}} 805 expected := simple{42, 0, nil, newInt(45), newBool(true), 806 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 807 simple2{30, newString("test"), []string{"test1", "test2"}}, 808 &simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}} 809 810 merged, err := mergeSimple(t1, t2) 811 require.NoError(t, err) 812 813 assert.Equal(t, expected, *merged) 814 }) 815 } 816 817 type mapPtrState2 struct { 818 MP map[string]*state2 819 } 820 type state2 struct { 821 Enable bool 822 EPtr *bool 823 } 824 825 func TestMergeWithMapPtrState2(t *testing.T) { 826 t.Run("inside structs, maps overwrite completely - mapPtrState2", func(t *testing.T) { 827 t1 := mapPtrState2{map[string]*state2{"base key": {true, newBool(true)}}} 828 t2 := mapPtrState2{map[string]*state2{"base key": {false, nil}}} 829 expected := mapPtrState2{map[string]*state2{"base key": {false, nil}}} 830 831 merged, err := mergeMapPtrState2(t1, t2) 832 require.NoError(t, err) 833 834 assert.Equal(t, expected, *merged) 835 }) 836 837 t.Run("inside structs, maps overwrite completely - mapPtrState2 2", func(t *testing.T) { 838 t1 := mapPtrState2{map[string]*state2{"base key": {true, newBool(true)}}} // 839 t2 := mapPtrState2{map[string]*state2{"base key": nil}} 840 expected := mapPtrState2{map[string]*state2{"base key": nil}} 841 842 merged, err := mergeMapPtrState2(t1, t2) 843 require.NoError(t, err) 844 845 assert.Equal(t, expected, *merged) 846 }) 847 } 848 849 type simple struct { 850 I int 851 f float64 852 fp *float64 853 IP *int 854 B *bool 855 Sli []int 856 Msi map[string]int 857 S2 simple2 858 S3 *simple2 859 } 860 861 type simple2 struct { 862 I int 863 S *string 864 Sls []string 865 } 866 867 func TestMergeWithSimpleStruct(t *testing.T) { 868 t.Run("patch nils are ignored", func(t *testing.T) { 869 t1 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true), 870 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 871 simple2{30, newString("test base"), []string{"test1", "test2"}}, 872 &simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}} 873 t2 := simple{42, 42.2, newFloat64(932.2), nil, nil, 874 nil, nil, 875 simple2{30, nil, nil}, 876 &simple2{42, nil, nil}} 877 expected := simple{42, 0, nil, newInt(45), newBool(true), 878 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 879 simple2{30, newString("test base"), []string{"test1", "test2"}}, 880 &simple2{42, newString("test2"), []string{"test3", "test4", "test5"}}} 881 882 merged, err := mergeSimple(t1, t2) 883 require.NoError(t, err) 884 885 assert.Equal(t, expected, *merged) 886 }) 887 888 t.Run("patch nilled structs are ignored", func(t *testing.T) { 889 t1 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true), 890 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 891 simple2{30, newString("test base"), []string{"test1", "test2"}}, 892 &simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}} 893 t2 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true), 894 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 895 simple2{30, newString("test base"), []string{"test1", "test2"}}, 896 nil} 897 expected := simple{42, 0, nil, newInt(45), newBool(true), 898 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 899 simple2{30, newString("test base"), []string{"test1", "test2"}}, 900 &simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}} 901 902 merged, err := mergeSimple(t1, t2) 903 require.NoError(t, err) 904 905 assert.Equal(t, expected, *merged) 906 }) 907 908 t.Run("can handle both nils", func(t *testing.T) { 909 t1 := simple{42, 42.2, newFloat64(932.2), newInt(45), nil, 910 []int{1, 2, 3}, nil, 911 simple2{30, nil, nil}, 912 nil} 913 t2 := simple{42, 42.2, newFloat64(932.2), newInt(45), nil, 914 []int{1, 2, 3}, nil, 915 simple2{30, nil, nil}, 916 nil} 917 expected := simple{42, 0, nil, newInt(45), nil, 918 []int{1, 2, 3}, nil, 919 simple2{30, nil, nil}, 920 nil} 921 922 merged, err := mergeSimple(t1, t2) 923 require.NoError(t, err) 924 925 assert.Equal(t, expected, *merged) 926 }) 927 928 t.Run("different base vals are overwritten by patch, and unexported fields are ignored", func(t *testing.T) { 929 t1 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true), 930 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 931 simple2{30, newString("test"), []string{"test1", "test2"}}, 932 &simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}} 933 t2 := simple{13, 53.1, newFloat64(932.2), newInt(46), newBool(false), 934 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 935 simple2{30, newString("testpatch"), []string{"test1", "test99"}}, 936 &simple2{45, nil, []string{"test3", "test123", "test5"}}} 937 expected := simple{13, 0, nil, newInt(46), newBool(false), 938 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 939 simple2{30, newString("testpatch"), []string{"test1", "test99"}}, 940 &simple2{45, newString("test2"), []string{"test3", "test123", "test5"}}} 941 942 merged, err := mergeSimple(t1, t2) 943 require.NoError(t, err) 944 945 assert.NotEqual(t, t1, *merged) 946 assert.Equal(t, expected, *merged) 947 }) 948 949 t.Run("pointers are not being copied or modified", func(t *testing.T) { 950 t1 := simple{42, 42.2, newFloat64(932.2), newInt(99), newBool(true), 951 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 952 simple2{30, newString("test"), []string{"test1", "test2"}}, 953 &simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}} 954 t2 := simple{13, 53.1, newFloat64(932.2), nil, newBool(false), 955 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 956 simple2{30, newString("testpatch"), []string{"test1", "test2"}}, 957 &simple2{45, nil, []string{"test3", "test4", "test5"}}} 958 expected := simple{13, 0, nil, newInt(99), newBool(false), 959 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 960 simple2{30, newString("testpatch"), []string{"test1", "test2"}}, 961 &simple2{45, newString("test2"), []string{"test3", "test4", "test5"}}} 962 963 merged, err := mergeSimple(t1, t2) 964 require.NoError(t, err) 965 966 assert.NotEqual(t, t1, *merged) 967 assert.Equal(t, expected, *merged) 968 969 // changes in originals do not affect merged 970 *t1.S3.S = "testBASE" 971 assert.Equal(t, "test2", *merged.S3.S) 972 *t2.B = true 973 assert.Equal(t, false, *merged.B) 974 975 // changes in base do not affect patched 976 *t1.S2.S = "test from base" 977 assert.NotEqual(t, *t1.S2.S, *t2.S2.S) 978 979 // changes in merged (on pointers that were cloned from base or patch) do not affect base or patch 980 *merged.IP = 0 981 assert.Equal(t, 99, *t1.IP) 982 *merged.S2.S = "testMERGED" 983 assert.NotEqual(t, *t2.S2.S, *merged.S2.S) 984 }) 985 986 t.Run("slices are not being copied or modified", func(t *testing.T) { 987 t1 := simple{42, 42.2, newFloat64(932.2), newInt(99), newBool(true), 988 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 989 simple2{30, newString("test"), []string{"test1", "test2"}}, 990 &simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}} 991 t2 := simple{13, 53.1, newFloat64(932.2), nil, newBool(false), 992 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 993 simple2{30, newString("testpatch"), nil}, 994 &simple2{45, nil, []string{"test3", "test4", "test99"}}} 995 expected := simple{13, 0, nil, newInt(99), newBool(false), 996 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 997 simple2{30, newString("testpatch"), []string{"test1", "test2"}}, 998 &simple2{45, newString("test2"), []string{"test3", "test4", "test99"}}} 999 1000 merged, err := mergeSimple(t1, t2) 1001 require.NoError(t, err) 1002 1003 assert.NotEqual(t, t1, *merged) 1004 assert.Equal(t, expected, *merged) 1005 1006 // changes in base do not affect merged 1007 t1.S2.Sls[0] = "test0" 1008 assert.Equal(t, "test1", merged.S2.Sls[0]) 1009 1010 // changes in patch do not affect merged 1011 t2.S3.Sls[0] = "test0" 1012 assert.Equal(t, "test3", merged.S3.Sls[0]) 1013 1014 // changes in merged (on slice that was cloned from base) do not affect base 1015 merged.S2.Sls[1] = "test222" 1016 assert.Equal(t, "test2", t1.S2.Sls[1]) 1017 }) 1018 1019 t.Run("maps are not being copied or modified: base -> merged", func(t *testing.T) { 1020 t1 := simple{42, 42.2, newFloat64(932.2), newInt(99), newBool(true), 1021 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 1022 simple2{30, newString("test"), []string{"test1", "test2"}}, 1023 &simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}} 1024 t2 := simple{13, 53.1, newFloat64(932.2), nil, newBool(false), 1025 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 1026 simple2{30, newString("testpatch"), []string{"test1", "test2"}}, 1027 &simple2{45, nil, []string{"test3", "test4", "test99"}}} 1028 expected := simple{13, 0, nil, newInt(99), newBool(false), 1029 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2}, 1030 simple2{30, newString("testpatch"), []string{"test1", "test2"}}, 1031 &simple2{45, newString("test2"), []string{"test3", "test4", "test99"}}} 1032 1033 merged, err := mergeSimple(t1, t2) 1034 require.NoError(t, err) 1035 1036 assert.NotEqual(t, t1, *merged) 1037 assert.Equal(t, expected, *merged) 1038 1039 // changes in originals do not affect merged 1040 t1.Msi["key1"] = 3 1041 assert.Equal(t, 1, merged.Msi["key1"]) 1042 t2.Msi["key5"] = 5 1043 _, ok := merged.Msi["key5"] 1044 assert.False(t, ok) 1045 }) 1046 1047 t.Run("patch map overwrites", func(t *testing.T) { 1048 t1 := simple{42, 42.2, newFloat64(932.2), newInt(99), newBool(true), 1049 []int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2, "key4": 4}, 1050 simple2{30, newString("test"), []string{"test1", "test2"}}, 1051 &simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}} 1052 t2 := simple{13, 53.1, newFloat64(932.2), nil, newBool(false), 1053 []int{1, 2, 3}, map[string]int{"key1": 11, "key2": 2, "key3": 3}, 1054 simple2{30, newString("testpatch"), []string{"test1", "test2"}}, 1055 &simple2{45, nil, []string{"test3", "test4", "test99"}}} 1056 expected := simple{13, 0, nil, newInt(99), newBool(false), 1057 []int{1, 2, 3}, map[string]int{"key1": 11, "key2": 2, "key3": 3}, 1058 simple2{30, newString("testpatch"), []string{"test1", "test2"}}, 1059 &simple2{45, newString("test2"), []string{"test3", "test4", "test99"}}} 1060 1061 merged, err := mergeSimple(t1, t2) 1062 require.NoError(t, err) 1063 1064 assert.Equal(t, expected, *merged) 1065 }) 1066 } 1067 1068 // The following are tests to see if multiply nested structs/maps/slice and pointers to structs/maps/slices 1069 // will merge. Probably overkill, but if anything goes wrong here, it is best to isolate the problem and 1070 // make a simplified test (like many of the above tests). 1071 func TestMergeWithVeryComplexStruct(t *testing.T) { 1072 t.Run("merge identical structs", func(t *testing.T) { 1073 setupStructs(t) 1074 1075 merged, err := mergeTestStructs(base, patch) 1076 require.NoError(t, err) 1077 1078 assert.Equal(t, expectedMerged, *merged) 1079 }) 1080 1081 t.Run("merge identical structs as pointers", func(t *testing.T) { 1082 setupStructs(t) 1083 1084 merged, err := mergeTestStructsPtrs(&base, &patch) 1085 require.NoError(t, err) 1086 1087 assert.Equal(t, expectedMerged, *merged) 1088 }) 1089 1090 t.Run("different base vals are overwritten by patch", func(t *testing.T) { 1091 setupStructs(t) 1092 1093 base.F = 1342.12 1094 base.Struct1.Pi = newInt(937) 1095 base.Struct1p.UI = 734 1096 base.Struct1.Struct2.Sli = []int{123123, 1243123} 1097 1098 merged, err := mergeTestStructs(base, patch) 1099 require.NoError(t, err) 1100 1101 assert.NotEqual(t, base, *merged) 1102 assert.Equal(t, patch, *merged) 1103 }) 1104 1105 t.Run("nil values in patch are ignored", func(t *testing.T) { 1106 setupStructs(t) 1107 1108 patch.Pi = nil 1109 patch.Struct1.Pi16 = nil 1110 1111 merged, err := mergeTestStructs(base, patch) 1112 require.NoError(t, err) 1113 1114 assert.NotEqual(t, patch, *merged) 1115 assert.Equal(t, expectedMerged, *merged) 1116 }) 1117 1118 t.Run("nil structs in patch are ignored", func(t *testing.T) { 1119 setupStructs(t) 1120 1121 patch.Struct1p = nil 1122 patch.Struct1.Struct2p = nil 1123 1124 merged, err := mergeTestStructs(base, patch) 1125 require.NoError(t, err) 1126 1127 assert.NotEqual(t, patch, *merged) 1128 assert.Equal(t, expectedMerged, *merged) 1129 }) 1130 1131 t.Run("nil slices in patch are ignored", func(t *testing.T) { 1132 setupStructs(t) 1133 1134 patch.Sls = nil 1135 patch.Struct1.Sli = nil 1136 patch.Struct1.Struct2p.Slf = nil 1137 1138 merged, err := mergeTestStructs(base, patch) 1139 require.NoError(t, err) 1140 1141 assert.NotEqual(t, patch, *merged) 1142 assert.Equal(t, expectedMerged, *merged) 1143 }) 1144 1145 t.Run("nil maps in patch are ignored", func(t *testing.T) { 1146 setupStructs(t) 1147 1148 patch.Msi = nil 1149 patch.Mspi = nil 1150 patch.Struct1.Mis = nil 1151 patch.Struct1.Struct2p.Mspi = nil 1152 1153 merged, err := mergeTestStructs(base, patch) 1154 require.NoError(t, err) 1155 1156 assert.NotEqual(t, patch, *merged) 1157 assert.Equal(t, expectedMerged, *merged) 1158 }) 1159 } 1160 1161 func TestMergeWithStructFieldFilter(t *testing.T) { 1162 t.Run("filter skips merging from patch", func(t *testing.T) { 1163 t1 := evenSimpler{newBool(true), &evenSimpler2{newString("base")}} 1164 t2 := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}} 1165 expected := evenSimpler{newBool(true), &evenSimpler2{newString("base")}} 1166 1167 merged, err := mergeEvenSimplerWithConfig(t1, t2, &utils.MergeConfig{ 1168 StructFieldFilter: func(structField reflect.StructField, base, patch reflect.Value) bool { 1169 return false 1170 }, 1171 }) 1172 require.NoError(t, err) 1173 1174 assert.Equal(t, expected, *merged) 1175 }) 1176 1177 t.Run("filter skips merging configured fields from patch", func(t *testing.T) { 1178 t1 := evenSimpler{newBool(true), &evenSimpler2{newString("base")}} 1179 t2 := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}} 1180 expected := evenSimpler{newBool(false), &evenSimpler2{newString("base")}} 1181 1182 merged, err := mergeEvenSimplerWithConfig(t1, t2, &utils.MergeConfig{ 1183 StructFieldFilter: func(structField reflect.StructField, base, patch reflect.Value) bool { 1184 return structField.Name == "B" 1185 }, 1186 }) 1187 require.NoError(t, err) 1188 1189 assert.Equal(t, expected, *merged) 1190 }) 1191 } 1192 1193 type testStruct struct { 1194 I int 1195 I8 int8 1196 I16 int16 1197 I32 int32 1198 I64 int64 1199 F float64 1200 F32 float32 1201 S string 1202 UI uint 1203 UI8 uint8 1204 UI16 uint32 1205 UI32 uint32 1206 UI64 uint64 1207 Pi *int 1208 Pi8 *int8 1209 Pi16 *int16 1210 Pi32 *int32 1211 Pi64 *int64 1212 Pf *float64 1213 Pf32 *float32 1214 Ps *string 1215 Pui *uint 1216 Pui8 *uint8 1217 Pui16 *uint16 1218 Pui32 *uint32 1219 Pui64 *uint64 1220 Sls []string 1221 Sli []int 1222 Slf []float64 1223 Msi map[string]int 1224 Mis map[int]string 1225 Mspi map[string]*int 1226 Mips map[int]*string 1227 Struct1 testStructEmbed 1228 Struct1p *testStructEmbed 1229 } 1230 1231 type testStructEmbed struct { 1232 I int 1233 I8 int8 1234 I16 int16 1235 I32 int32 1236 I64 int64 1237 F float64 1238 F32 float32 1239 S string 1240 UI uint 1241 UI8 uint8 1242 UI16 uint32 1243 UI32 uint32 1244 UI64 uint64 1245 Pi *int 1246 Pi8 *int8 1247 Pi16 *int16 1248 Pi32 *int32 1249 Pi64 *int64 1250 Pf *float64 1251 Pf32 *float32 1252 Ps *string 1253 Pui *uint 1254 Pui8 *uint8 1255 Pui16 *uint16 1256 Pui32 *uint32 1257 Pui64 *uint64 1258 Sls []string 1259 Sli []int 1260 Slf []float64 1261 Msi map[string]int 1262 Mis map[int]string 1263 Mspi map[string]*int 1264 Mips map[int]*string 1265 Struct2 testStructEmbed2 1266 Struct2p *testStructEmbed2 1267 } 1268 1269 type testStructEmbed2 struct { 1270 I int 1271 I8 int8 1272 I16 int16 1273 I32 int32 1274 I64 int64 1275 F float64 1276 F32 float32 1277 S string 1278 UI uint 1279 UI8 uint8 1280 UI16 uint32 1281 UI32 uint32 1282 UI64 uint64 1283 Pi *int 1284 Pi8 *int8 1285 Pi16 *int16 1286 Pi32 *int32 1287 Pi64 *int64 1288 Pf *float64 1289 Pf32 *float32 1290 Ps *string 1291 Pui *uint 1292 Pui8 *uint8 1293 Pui16 *uint16 1294 Pui32 *uint32 1295 Pui64 *uint64 1296 Sls []string 1297 Sli []int 1298 Slf []float64 1299 Msi map[string]int 1300 Mis map[int]string 1301 Mspi map[string]*int 1302 Mips map[int]*string 1303 } 1304 1305 // the base structs 1306 var baseStructEmbed2A, baseStructEmbed2B, baseStructEmbed2C, baseStructEmbed2D testStructEmbed2 1307 var baseStructEmbedBaseA, baseStructEmbedBaseB testStructEmbed 1308 var base testStruct 1309 1310 // the patch structs 1311 var patchStructEmbed2A, patchStructEmbed2B, patchStructEmbed2C, patchStructEmbed2D testStructEmbed2 1312 var patchStructEmbedBaseA, patchStructEmbedBaseB testStructEmbed 1313 var patch testStruct 1314 1315 // The merged structs 1316 var mergeStructEmbed2A, mergeStructEmbed2B, mergeStructEmbed2C, mergeStructEmbed2D testStructEmbed2 1317 var mergeStructEmbedBaseA, mergeStructEmbedBaseB testStructEmbed 1318 var expectedMerged testStruct 1319 1320 func setupStructs(t *testing.T) { 1321 t.Helper() 1322 1323 baseStructEmbed2A = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1324 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1325 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1326 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1327 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1328 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1329 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1330 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1331 } 1332 1333 baseStructEmbed2B = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1334 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1335 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1336 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1337 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1338 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1339 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1340 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1341 } 1342 1343 baseStructEmbed2C = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1344 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1345 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1346 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1347 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1348 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1349 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1350 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1351 } 1352 1353 baseStructEmbed2D = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1354 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1355 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1356 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1357 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1358 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1359 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1360 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1361 } 1362 1363 baseStructEmbedBaseA = testStructEmbed{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1364 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1365 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1366 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1367 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1368 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1369 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1370 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1371 baseStructEmbed2A, &baseStructEmbed2B, 1372 } 1373 1374 baseStructEmbedBaseB = testStructEmbed{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1375 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1376 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1377 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1378 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1379 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1380 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1381 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1382 baseStructEmbed2C, &baseStructEmbed2D, 1383 } 1384 1385 base = testStruct{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1386 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1387 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1388 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1389 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1390 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1391 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1392 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1393 baseStructEmbedBaseA, &baseStructEmbedBaseB, 1394 } 1395 1396 patchStructEmbed2A = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1397 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1398 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1399 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1400 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1401 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1402 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1403 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1404 } 1405 1406 patchStructEmbed2B = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1407 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1408 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1409 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1410 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1411 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1412 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1413 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1414 } 1415 1416 patchStructEmbed2C = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1417 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1418 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1419 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1420 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1421 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1422 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1423 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1424 } 1425 1426 patchStructEmbed2D = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1427 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1428 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1429 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1430 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1431 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1432 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1433 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1434 } 1435 1436 patchStructEmbedBaseA = testStructEmbed{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1437 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1438 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1439 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1440 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1441 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1442 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1443 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1444 patchStructEmbed2A, &patchStructEmbed2B, 1445 } 1446 1447 patchStructEmbedBaseB = testStructEmbed{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1448 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1449 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1450 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1451 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1452 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1453 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1454 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1455 patchStructEmbed2C, &patchStructEmbed2D, 1456 } 1457 1458 patch = testStruct{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1459 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1460 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1461 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1462 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1463 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1464 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1465 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1466 patchStructEmbedBaseA, &patchStructEmbedBaseB, 1467 } 1468 1469 mergeStructEmbed2A = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1470 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1471 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1472 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1473 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1474 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1475 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1476 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1477 } 1478 1479 mergeStructEmbed2B = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1480 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1481 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1482 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1483 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1484 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1485 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1486 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1487 } 1488 1489 mergeStructEmbed2C = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1490 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1491 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1492 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1493 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1494 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1495 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1496 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1497 } 1498 1499 mergeStructEmbed2D = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1500 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1501 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1502 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1503 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1504 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1505 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1506 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1507 } 1508 1509 mergeStructEmbedBaseA = testStructEmbed{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1510 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1511 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1512 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1513 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1514 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1515 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1516 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1517 mergeStructEmbed2A, &mergeStructEmbed2B, 1518 } 1519 1520 mergeStructEmbedBaseB = testStructEmbed{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1521 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1522 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1523 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1524 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1525 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1526 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1527 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1528 mergeStructEmbed2C, &mergeStructEmbed2D, 1529 } 1530 1531 expectedMerged = testStruct{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13, 1532 newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18), 1533 newFloat64(19.9), newFloat32(20.1), newString("test pointer"), 1534 newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25), 1535 []string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3}, 1536 map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"}, 1537 map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)}, 1538 map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")}, 1539 mergeStructEmbedBaseA, &mergeStructEmbedBaseB, 1540 } 1541 } 1542 1543 func mergeSimple(base, patch simple) (*simple, error) { 1544 ret, err := utils.Merge(base, patch, nil) 1545 if err != nil { 1546 return nil, err 1547 } 1548 retS := ret.(simple) 1549 return &retS, nil 1550 } 1551 1552 func mergeEvenSimpler(base, patch evenSimpler) (*evenSimpler, error) { 1553 ret, err := utils.Merge(base, patch, nil) 1554 if err != nil { 1555 return nil, err 1556 } 1557 retTS := ret.(evenSimpler) 1558 return &retTS, nil 1559 } 1560 1561 func mergeEvenSimplerWithConfig(base, patch evenSimpler, mergeConfig *utils.MergeConfig) (*evenSimpler, error) { 1562 ret, err := utils.Merge(base, patch, mergeConfig) 1563 if err != nil { 1564 return nil, err 1565 } 1566 retTS := ret.(evenSimpler) 1567 return &retTS, nil 1568 } 1569 1570 func mergeSliceStruct(base, patch sliceStruct) (*sliceStruct, error) { 1571 ret, err := utils.Merge(base, patch, nil) 1572 if err != nil { 1573 return nil, err 1574 } 1575 retTS := ret.(sliceStruct) 1576 return &retTS, nil 1577 } 1578 1579 func mergeMapPtr(base, patch mapPtr) (*mapPtr, error) { 1580 ret, err := utils.Merge(base, patch, nil) 1581 if err != nil { 1582 return nil, err 1583 } 1584 retTS := ret.(mapPtr) 1585 return &retTS, nil 1586 } 1587 1588 func mergeMapPtrState(base, patch mapPtrState) (*mapPtrState, error) { 1589 ret, err := utils.Merge(base, patch, nil) 1590 if err != nil { 1591 return nil, err 1592 } 1593 retTS := ret.(mapPtrState) 1594 return &retTS, nil 1595 } 1596 1597 func mergeMapPtrState2(base, patch mapPtrState2) (*mapPtrState2, error) { 1598 ret, err := utils.Merge(base, patch, nil) 1599 if err != nil { 1600 return nil, err 1601 } 1602 retTS := ret.(mapPtrState2) 1603 return &retTS, nil 1604 } 1605 1606 func mergeTestStructs(base, patch testStruct) (*testStruct, error) { 1607 ret, err := utils.Merge(base, patch, nil) 1608 if err != nil { 1609 return nil, err 1610 } 1611 retTS := ret.(testStruct) 1612 return &retTS, nil 1613 } 1614 1615 func mergeStringIntMap(base, patch map[string]int) (map[string]int, error) { 1616 ret, err := utils.Merge(base, patch, nil) 1617 if err != nil { 1618 return nil, err 1619 } 1620 retTS := ret.(map[string]int) 1621 return retTS, nil 1622 } 1623 1624 func mergeStringPtrIntMap(base, patch map[string]*int) (map[string]*int, error) { 1625 ret, err := utils.Merge(base, patch, nil) 1626 if err != nil { 1627 return nil, err 1628 } 1629 retTS := ret.(map[string]*int) 1630 return retTS, nil 1631 } 1632 1633 func mergeStringSliceIntMap(base, patch map[string][]int) (map[string][]int, error) { 1634 ret, err := utils.Merge(base, patch, nil) 1635 if err != nil { 1636 return nil, err 1637 } 1638 retTS := ret.(map[string][]int) 1639 return retTS, nil 1640 } 1641 1642 func mergeMapOfMap(base, patch map[string]map[string]*int) (map[string]map[string]*int, error) { 1643 ret, err := utils.Merge(base, patch, nil) 1644 if err != nil { 1645 return nil, err 1646 } 1647 retTS := ret.(map[string]map[string]*int) 1648 return retTS, nil 1649 } 1650 1651 func mergeInterfaceMap(base, patch map[string]interface{}) (map[string]interface{}, error) { 1652 ret, err := utils.Merge(base, patch, nil) 1653 if err != nil { 1654 return nil, err 1655 } 1656 retTS := ret.(map[string]interface{}) 1657 return retTS, nil 1658 } 1659 1660 func mergeStringSlices(base, patch []string) ([]string, error) { 1661 ret, err := utils.Merge(base, patch, nil) 1662 if err != nil { 1663 return nil, err 1664 } 1665 retTS := ret.([]string) 1666 return retTS, nil 1667 } 1668 1669 func mergeTestStructsPtrs(base, patch *testStruct) (*testStruct, error) { 1670 ret, err := utils.Merge(base, patch, nil) 1671 if err != nil { 1672 return nil, err 1673 } 1674 retTS := ret.(testStruct) 1675 return &retTS, nil 1676 } 1677 1678 func newBool(b bool) *bool { return &b } 1679 func newInt(n int) *int { return &n } 1680 func newInt64(n int64) *int64 { return &n } 1681 func newString(s string) *string { return &s } 1682 func newInt8(n int8) *int8 { return &n } 1683 func newInt16(n int16) *int16 { return &n } 1684 func newInt32(n int32) *int32 { return &n } 1685 func newFloat64(f float64) *float64 { return &f } 1686 func newFloat32(f float32) *float32 { return &f } 1687 func newUint(n uint) *uint { return &n } 1688 func newUint8(n uint8) *uint8 { return &n } 1689 func newUint16(n uint16) *uint16 { return &n } 1690 func newUint32(n uint32) *uint32 { return &n } 1691 func newUint64(n uint64) *uint64 { return &n }