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