github.com/prebid/prebid-server@v0.275.0/ortb/clone_test.go (about) 1 package ortb 2 3 import ( 4 "encoding/json" 5 "reflect" 6 "testing" 7 8 "github.com/prebid/openrtb/v19/adcom1" 9 "github.com/prebid/openrtb/v19/openrtb2" 10 "github.com/prebid/prebid-server/util/ptrutil" 11 "github.com/stretchr/testify/assert" 12 ) 13 14 func TestCloneApp(t *testing.T) { 15 t.Run("nil", func(t *testing.T) { 16 result := CloneApp(nil) 17 assert.Nil(t, result) 18 }) 19 20 t.Run("empty", func(t *testing.T) { 21 given := &openrtb2.App{} 22 result := CloneApp(given) 23 assert.Equal(t, given, result) 24 assert.NotSame(t, given, result) 25 }) 26 27 t.Run("populated", func(t *testing.T) { 28 given := &openrtb2.App{ 29 ID: "anyID", 30 Name: "anyName", 31 Bundle: "anyBundle", 32 Domain: "anyDomain", 33 StoreURL: "anyStoreURL", 34 CatTax: adcom1.CatTaxIABContent10, 35 Cat: []string{"cat1"}, 36 SectionCat: []string{"sectionCat1"}, 37 PageCat: []string{"pageCat1"}, 38 Ver: "anyVer", 39 PrivacyPolicy: 1, 40 Paid: 2, 41 Publisher: &openrtb2.Publisher{ID: "anyPublisher", Ext: json.RawMessage(`{"publisher":1}`)}, 42 Content: &openrtb2.Content{ID: "anyContent", Ext: json.RawMessage(`{"content":1}`)}, 43 Keywords: "anyKeywords", 44 KwArray: []string{"key1"}, 45 InventoryPartnerDomain: "anyInventoryPartnerDomain", 46 Ext: json.RawMessage(`{"anyField":1}`), 47 } 48 result := CloneApp(given) 49 assert.Equal(t, given, result, "equality") 50 assert.NotSame(t, given, result, "pointer") 51 assert.NotSame(t, given.Cat, result.Cat, "cat") 52 assert.NotSame(t, given.SectionCat, result.SectionCat, "sectioncat") 53 assert.NotSame(t, given.PageCat, result.PageCat, "pagecat") 54 assert.NotSame(t, given.Publisher, result.Publisher, "publisher") 55 assert.NotSame(t, given.Publisher.Ext, result.Publisher.Ext, "publisher-ext") 56 assert.NotSame(t, given.Content, result.Content, "content") 57 assert.NotSame(t, given.Content.Ext, result.Content.Ext, "content-ext") 58 assert.NotSame(t, given.KwArray, result.KwArray, "kwarray") 59 assert.NotSame(t, given.Ext, result.Ext, "ext") 60 }) 61 62 t.Run("assumptions", func(t *testing.T) { 63 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.App{})), 64 []string{ 65 "Cat", 66 "SectionCat", 67 "PageCat", 68 "Publisher", 69 "Content", 70 "KwArray", 71 "Ext", 72 }) 73 }) 74 } 75 76 func TestClonePublisher(t *testing.T) { 77 t.Run("nil", func(t *testing.T) { 78 result := ClonePublisher(nil) 79 assert.Nil(t, result) 80 }) 81 82 t.Run("empty", func(t *testing.T) { 83 given := &openrtb2.Publisher{} 84 result := ClonePublisher(given) 85 assert.Equal(t, given, result) 86 assert.NotSame(t, given, result) 87 }) 88 89 t.Run("populated", func(t *testing.T) { 90 given := &openrtb2.Publisher{ 91 ID: "anyID", 92 Name: "anyName", 93 CatTax: adcom1.CatTaxIABContent20, 94 Cat: []string{"cat1"}, 95 Domain: "anyDomain", 96 Ext: json.RawMessage(`{"anyField":1}`), 97 } 98 result := ClonePublisher(given) 99 assert.Equal(t, given, result, "equality") 100 assert.NotSame(t, given, result, "pointer") 101 assert.NotSame(t, given.Cat, result.Cat, "cat") 102 assert.NotSame(t, given.Ext, result.Ext, "ext") 103 }) 104 105 t.Run("assumptions", func(t *testing.T) { 106 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.Publisher{})), 107 []string{ 108 "Cat", 109 "Ext", 110 }) 111 }) 112 } 113 114 func TestCloneContent(t *testing.T) { 115 t.Run("nil", func(t *testing.T) { 116 result := CloneContent(nil) 117 assert.Nil(t, result) 118 }) 119 120 t.Run("empty", func(t *testing.T) { 121 given := &openrtb2.Content{} 122 result := CloneContent(given) 123 assert.Equal(t, given, result) 124 assert.NotSame(t, given, result) 125 }) 126 127 t.Run("populated", func(t *testing.T) { 128 given := &openrtb2.Content{ 129 ID: "anyID", 130 Episode: 1, 131 Title: "anyTitle", 132 Series: "anySeries", 133 Season: "anySeason", 134 Artist: "anyArtist", 135 Genre: "anyGenre", 136 Album: "anyAlbum", 137 ISRC: "anyIsrc", 138 Producer: &openrtb2.Producer{ID: "anyID", Cat: []string{"anyCat"}}, 139 URL: "anyUrl", 140 CatTax: adcom1.CatTaxIABContent10, 141 Cat: []string{"cat1"}, 142 ProdQ: ptrutil.ToPtr(adcom1.ProductionProsumer), 143 VideoQuality: ptrutil.ToPtr(adcom1.ProductionProfessional), 144 Context: adcom1.ContentApp, 145 ContentRating: "anyContentRating", 146 UserRating: "anyUserRating", 147 QAGMediaRating: adcom1.MediaRatingAll, 148 Keywords: "anyKeywords", 149 KwArray: []string{"key1"}, 150 LiveStream: 2, 151 SourceRelationship: 3, 152 Len: 4, 153 Language: "anyLanguage", 154 LangB: "anyLangB", 155 Embeddable: 5, 156 Data: []openrtb2.Data{{ID: "1", Ext: json.RawMessage(`{"data":1}`)}}, 157 Network: &openrtb2.Network{ID: "anyNetwork", Ext: json.RawMessage(`{"network":1}`)}, 158 Channel: &openrtb2.Channel{ID: "anyChannel", Ext: json.RawMessage(`{"channel":1}`)}, 159 Ext: json.RawMessage(`{"anyField":1}`), 160 } 161 result := CloneContent(given) 162 assert.Equal(t, given, result, "equality") 163 assert.NotSame(t, given, result, "pointer") 164 assert.NotSame(t, given.Producer, result.Producer, "producer") 165 assert.NotSame(t, given.Producer.Cat, result.Producer.Cat, "producer-cat") 166 assert.NotSame(t, given.Cat, result.Cat, "cat") 167 assert.NotSame(t, given.ProdQ, result.ProdQ, "prodq") 168 assert.NotSame(t, given.VideoQuality, result.VideoQuality, "videoquality") 169 assert.NotSame(t, given.KwArray, result.KwArray, "kwarray") 170 assert.NotSame(t, given.Data, result.Data, "data") 171 assert.NotSame(t, given.Data[0], result.Data[0], "data-item") 172 assert.NotSame(t, given.Data[0].Ext, result.Data[0].Ext, "data-item-ext") 173 assert.NotSame(t, given.Network, result.Network, "network") 174 assert.NotSame(t, given.Network.Ext, result.Network.Ext, "network-ext") 175 assert.NotSame(t, given.Channel, result.Channel, "channel") 176 assert.NotSame(t, given.Channel.Ext, result.Channel.Ext, "channel-ext") 177 assert.NotSame(t, given.Ext, result.Ext, "ext") 178 }) 179 180 t.Run("assumptions", func(t *testing.T) { 181 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.Content{})), 182 []string{ 183 "Producer", 184 "Cat", 185 "ProdQ", 186 "VideoQuality", 187 "KwArray", 188 "Data", 189 "Network", 190 "Channel", 191 "Ext", 192 }) 193 }) 194 } 195 196 func TestCloneProducer(t *testing.T) { 197 t.Run("nil", func(t *testing.T) { 198 result := CloneProducer(nil) 199 assert.Nil(t, result) 200 }) 201 202 t.Run("empty", func(t *testing.T) { 203 given := &openrtb2.Producer{} 204 result := CloneProducer(given) 205 assert.Equal(t, given, result) 206 assert.NotSame(t, given, result) 207 }) 208 209 t.Run("populated", func(t *testing.T) { 210 given := &openrtb2.Producer{ 211 ID: "anyID", 212 Name: "anyName", 213 CatTax: adcom1.CatTaxIABContent20, 214 Cat: []string{"cat1"}, 215 Domain: "anyDomain", 216 Ext: json.RawMessage(`{"anyField":1}`), 217 } 218 result := CloneProducer(given) 219 assert.Equal(t, given, result, "equality") 220 assert.NotSame(t, given, result, "pointer") 221 assert.NotSame(t, given.Cat, result.Cat, "cat") 222 assert.NotSame(t, given.Ext, result.Ext, "ext") 223 }) 224 225 t.Run("assumptions", func(t *testing.T) { 226 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.Producer{})), 227 []string{ 228 "Cat", 229 "Ext", 230 }) 231 }) 232 } 233 234 func TestCloneDataSlice(t *testing.T) { 235 t.Run("nil", func(t *testing.T) { 236 result := CloneDataSlice(nil) 237 assert.Nil(t, result) 238 }) 239 240 t.Run("empty", func(t *testing.T) { 241 given := []openrtb2.Data{} 242 result := CloneDataSlice(given) 243 assert.Empty(t, result) 244 assert.NotSame(t, given, result) 245 }) 246 247 t.Run("one", func(t *testing.T) { 248 given := []openrtb2.Data{ 249 {ID: "1", Ext: json.RawMessage(`{"anyField":1}`)}, 250 } 251 result := CloneDataSlice(given) 252 assert.Equal(t, given, result, "equality") 253 assert.NotSame(t, given[0], result[0], "item-pointer") 254 assert.NotSame(t, given[0].Ext, result[0].Ext, "item-pointer-ext") 255 }) 256 257 t.Run("many", func(t *testing.T) { 258 given := []openrtb2.Data{ 259 {ID: "1", Ext: json.RawMessage(`{"anyField":1}`)}, 260 {ID: "2", Ext: json.RawMessage(`{"anyField":2}`)}, 261 } 262 result := CloneDataSlice(given) 263 assert.Equal(t, given, result, "equality") 264 assert.NotSame(t, given[0], result[0], "item0-pointer") 265 assert.NotSame(t, given[0].Ext, result[0].Ext, "item0-pointer-ext") 266 assert.NotSame(t, given[1], result[1], "item1-pointer") 267 assert.NotSame(t, given[1].Ext, result[1].Ext, "item1-pointer-ext") 268 }) 269 } 270 271 func TestCloneData(t *testing.T) { 272 t.Run("populated", func(t *testing.T) { 273 given := openrtb2.Data{ 274 ID: "anyID", 275 Name: "anyName", 276 Segment: []openrtb2.Segment{{ID: "1", Ext: json.RawMessage(`{"anyField":1}`)}}, 277 Ext: json.RawMessage(`{"anyField":1}`), 278 } 279 result := CloneData(given) 280 assert.Equal(t, given, result, "equality") 281 assert.NotSame(t, given, result, "pointer") 282 assert.NotSame(t, given.Segment, result.Segment, "segment") 283 assert.NotSame(t, given.Segment[0], result.Segment[0], "segment-item") 284 assert.NotSame(t, given.Segment[0].Ext, result.Segment[0].Ext, "segment-item-ext") 285 assert.NotSame(t, given.Ext, result.Ext, "ext") 286 }) 287 288 t.Run("assumptions", func(t *testing.T) { 289 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.Data{})), 290 []string{ 291 "Segment", 292 "Ext", 293 }) 294 }) 295 } 296 297 func TestCloneSegmentSlice(t *testing.T) { 298 t.Run("nil", func(t *testing.T) { 299 result := CloneSegmentSlice(nil) 300 assert.Nil(t, result) 301 }) 302 303 t.Run("empty", func(t *testing.T) { 304 given := []openrtb2.Segment{} 305 result := CloneSegmentSlice(given) 306 assert.Empty(t, result) 307 assert.NotSame(t, given, result) 308 }) 309 310 t.Run("one", func(t *testing.T) { 311 given := []openrtb2.Segment{ 312 {ID: "1", Ext: json.RawMessage(`{"anyField":1}`)}, 313 } 314 result := CloneSegmentSlice(given) 315 assert.Equal(t, given, result, "equality") 316 assert.NotSame(t, given[0], result[0], "item-pointer") 317 assert.NotSame(t, given[0].Ext, result[0].Ext, "item-pointer-ext") 318 }) 319 320 t.Run("many", func(t *testing.T) { 321 given := []openrtb2.Segment{ 322 {Ext: json.RawMessage(`{"anyField":1}`)}, 323 {Ext: json.RawMessage(`{"anyField":2}`)}, 324 } 325 result := CloneSegmentSlice(given) 326 assert.Equal(t, given, result, "equality") 327 assert.NotSame(t, given[0], result[0], "item0-pointer") 328 assert.NotSame(t, given[0].Ext, result[0].Ext, "item0-pointer-ext") 329 assert.NotSame(t, given[1], result[1], "item1-pointer") 330 assert.NotSame(t, given[1].Ext, result[1].Ext, "item1-pointer-ext") 331 }) 332 } 333 334 func TestCloneSegment(t *testing.T) { 335 t.Run("populated", func(t *testing.T) { 336 given := openrtb2.Segment{ 337 ID: "anyID", 338 Name: "anyName", 339 Value: "anyValue", 340 Ext: json.RawMessage(`{"anyField":1}`), 341 } 342 result := CloneSegment(given) 343 assert.Equal(t, given, result, "equality") 344 assert.NotSame(t, given, result, "pointer") 345 assert.NotSame(t, given.Ext, result.Ext, "ext") 346 }) 347 348 t.Run("assumptions", func(t *testing.T) { 349 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.Segment{})), 350 []string{ 351 "Ext", 352 }) 353 }) 354 } 355 356 func TestCloneNetwork(t *testing.T) { 357 t.Run("nil", func(t *testing.T) { 358 result := CloneNetwork(nil) 359 assert.Nil(t, result) 360 }) 361 362 t.Run("empty", func(t *testing.T) { 363 given := &openrtb2.Network{} 364 result := CloneNetwork(given) 365 assert.Empty(t, result) 366 assert.NotSame(t, given, result) 367 }) 368 369 t.Run("populated", func(t *testing.T) { 370 given := &openrtb2.Network{ 371 ID: "anyID", 372 Name: "anyName", 373 Domain: "anyDomain", 374 Ext: json.RawMessage(`{"anyField":1}`), 375 } 376 result := CloneNetwork(given) 377 assert.Equal(t, given, result, "equality") 378 assert.NotSame(t, given, result, "pointer") 379 assert.NotSame(t, given.Ext, result.Ext, "ext") 380 }) 381 382 t.Run("assumptions", func(t *testing.T) { 383 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.Network{})), 384 []string{ 385 "Ext", 386 }) 387 }) 388 } 389 390 func TestCloneChannel(t *testing.T) { 391 t.Run("nil", func(t *testing.T) { 392 result := CloneChannel(nil) 393 assert.Nil(t, result) 394 }) 395 396 t.Run("empty", func(t *testing.T) { 397 given := &openrtb2.Channel{} 398 result := CloneChannel(given) 399 assert.Empty(t, result) 400 assert.NotSame(t, given, result) 401 }) 402 403 t.Run("populated", func(t *testing.T) { 404 given := &openrtb2.Channel{ 405 ID: "anyID", 406 Name: "anyName", 407 Domain: "anyDomain", 408 Ext: json.RawMessage(`{"anyField":1}`), 409 } 410 result := CloneChannel(given) 411 assert.Equal(t, given, result, "equality") 412 assert.NotSame(t, given, result, "pointer") 413 assert.NotSame(t, given.Ext, result.Ext, "ext") 414 }) 415 416 t.Run("assumptions", func(t *testing.T) { 417 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.Channel{})), 418 []string{ 419 "Ext", 420 }) 421 }) 422 } 423 424 func TestCloneSite(t *testing.T) { 425 t.Run("nil", func(t *testing.T) { 426 result := CloneSite(nil) 427 assert.Nil(t, result) 428 }) 429 430 t.Run("empty", func(t *testing.T) { 431 given := &openrtb2.Site{} 432 result := CloneSite(given) 433 assert.Empty(t, result) 434 assert.NotSame(t, given, result) 435 }) 436 437 t.Run("populated", func(t *testing.T) { 438 given := &openrtb2.Site{ 439 ID: "anyID", 440 Name: "anyName", 441 Domain: "anyDomain", 442 CatTax: adcom1.CatTaxIABContent10, 443 Cat: []string{"cat1"}, 444 SectionCat: []string{"sectionCat1"}, 445 PageCat: []string{"pageCat1"}, 446 Page: "anyPage", 447 Ref: "anyRef", 448 Search: "anySearch", 449 Mobile: 1, 450 PrivacyPolicy: 2, 451 Publisher: &openrtb2.Publisher{ID: "anyPublisher", Ext: json.RawMessage(`{"publisher":1}`)}, 452 Content: &openrtb2.Content{ID: "anyContent", Ext: json.RawMessage(`{"content":1}`)}, 453 Keywords: "anyKeywords", 454 KwArray: []string{"key1"}, 455 InventoryPartnerDomain: "anyInventoryPartnerDomain", 456 Ext: json.RawMessage(`{"anyField":1}`), 457 } 458 result := CloneSite(given) 459 assert.Equal(t, given, result, "equality") 460 assert.NotSame(t, given, result, "pointer") 461 assert.NotSame(t, given.Cat, result.Cat, "cat") 462 assert.NotSame(t, given.SectionCat, result.SectionCat, "sectioncat") 463 assert.NotSame(t, given.PageCat, result.PageCat, "pagecat") 464 assert.NotSame(t, given.Publisher, result.Publisher, "publisher") 465 assert.NotSame(t, given.Publisher.Ext, result.Publisher.Ext, "publisher-ext") 466 assert.NotSame(t, given.Content, result.Content, "content") 467 assert.NotSame(t, given.Content.Ext, result.Content.Ext, "content-ext") 468 assert.NotSame(t, given.KwArray, result.KwArray, "kwarray") 469 assert.NotSame(t, given.Ext, result.Ext, "ext") 470 }) 471 472 t.Run("assumptions", func(t *testing.T) { 473 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.Site{})), 474 []string{ 475 "Cat", 476 "SectionCat", 477 "PageCat", 478 "Publisher", 479 "Content", 480 "KwArray", 481 "Ext", 482 }) 483 }) 484 } 485 486 func TestCloneUser(t *testing.T) { 487 t.Run("nil", func(t *testing.T) { 488 result := CloneUser(nil) 489 assert.Nil(t, result) 490 }) 491 492 t.Run("empty", func(t *testing.T) { 493 given := &openrtb2.User{} 494 result := CloneUser(given) 495 assert.Empty(t, result) 496 assert.NotSame(t, given, result) 497 }) 498 499 t.Run("populated", func(t *testing.T) { 500 given := &openrtb2.User{ 501 ID: "anyID", 502 BuyerUID: "anyBuyerUID", 503 Yob: 1, 504 Gender: "anyGender", 505 Keywords: "anyKeywords", 506 KwArray: []string{"key1"}, 507 CustomData: "anyCustomData", 508 Geo: &openrtb2.Geo{Lat: 1.2, Lon: 2.3, Ext: json.RawMessage(`{"geo":1}`)}, 509 Data: []openrtb2.Data{{ID: "1", Ext: json.RawMessage(`{"data":1}`)}}, 510 Consent: "anyConsent", 511 EIDs: []openrtb2.EID{{Source: "1", Ext: json.RawMessage(`{"eid":1}`)}}, 512 Ext: json.RawMessage(`{"anyField":1}`), 513 } 514 result := CloneUser(given) 515 assert.Equal(t, given, result, "equality") 516 assert.NotSame(t, given, result, "pointer") 517 assert.NotSame(t, given.KwArray, result.KwArray, "cat") 518 assert.NotSame(t, given.Geo, result.Geo, "geo") 519 assert.NotSame(t, given.Geo.Ext, result.Geo.Ext, "geo-ext") 520 assert.NotSame(t, given.Data[0], result.Data[0], "data-item") 521 assert.NotSame(t, given.Data[0].Ext, result.Data[0].Ext, "data-item-ext") 522 assert.NotSame(t, given.EIDs[0], result.EIDs[0], "eids-item") 523 assert.NotSame(t, given.EIDs[0].Ext, result.EIDs[0].Ext, "eids-item-ext") 524 assert.NotSame(t, given.Ext, result.Ext, "ext") 525 }) 526 527 t.Run("assumptions", func(t *testing.T) { 528 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.User{})), 529 []string{ 530 "KwArray", 531 "Geo", 532 "Data", 533 "EIDs", 534 "Ext", 535 }) 536 }) 537 } 538 539 func TestCloneGeo(t *testing.T) { 540 t.Run("nil", func(t *testing.T) { 541 result := CloneGeo(nil) 542 assert.Nil(t, result) 543 }) 544 545 t.Run("empty", func(t *testing.T) { 546 given := &openrtb2.Geo{} 547 result := CloneGeo(given) 548 assert.Empty(t, result) 549 assert.NotSame(t, given, result) 550 }) 551 552 t.Run("populated", func(t *testing.T) { 553 given := &openrtb2.Geo{ 554 Lat: 1.234, 555 Lon: 5.678, 556 Type: adcom1.LocationGPS, 557 Accuracy: 1, 558 LastFix: 2, 559 IPService: adcom1.LocationServiceIP2Location, 560 Country: "anyCountry", 561 Region: "anyRegion", 562 RegionFIPS104: "anyRegionFIPS104", 563 Metro: "anyMetro", 564 City: "anyCity", 565 ZIP: "anyZIP", 566 UTCOffset: 3, 567 Ext: json.RawMessage(`{"anyField":1}`), 568 } 569 result := CloneGeo(given) 570 assert.Equal(t, given, result, "equality") 571 assert.NotSame(t, given, result, "pointer") 572 assert.NotSame(t, given.Ext, result.Ext, "ext") 573 }) 574 575 t.Run("assumptions", func(t *testing.T) { 576 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.Geo{})), 577 []string{ 578 "Ext", 579 }) 580 }) 581 } 582 583 func TestCloneEIDSlice(t *testing.T) { 584 t.Run("nil", func(t *testing.T) { 585 result := CloneEIDSlice(nil) 586 assert.Nil(t, result) 587 }) 588 589 t.Run("empty", func(t *testing.T) { 590 given := []openrtb2.EID{} 591 result := CloneEIDSlice(given) 592 assert.Empty(t, result) 593 assert.NotSame(t, given, result) 594 }) 595 596 t.Run("one", func(t *testing.T) { 597 given := []openrtb2.EID{ 598 {Source: "1", Ext: json.RawMessage(`{"anyField":1}`)}, 599 } 600 result := CloneEIDSlice(given) 601 assert.Equal(t, given, result, "equality") 602 assert.NotSame(t, given[0], result[0], "item-pointer") 603 assert.NotSame(t, given[0].Ext, result[0].Ext, "item-pointer-ext") 604 }) 605 606 t.Run("many", func(t *testing.T) { 607 given := []openrtb2.EID{ 608 {Source: "1", Ext: json.RawMessage(`{"anyField":1}`)}, 609 {Source: "2", Ext: json.RawMessage(`{"anyField":2}`)}, 610 } 611 result := CloneEIDSlice(given) 612 assert.Equal(t, given, result, "equality") 613 assert.NotSame(t, given[0], result[0], "item0-pointer") 614 assert.NotSame(t, given[0].Ext, result[0].Ext, "item0-pointer-ext") 615 assert.NotSame(t, given[1], result[1], "item1-pointer") 616 assert.NotSame(t, given[1].Ext, result[1].Ext, "item1-pointer-ext") 617 }) 618 } 619 620 func TestCloneEID(t *testing.T) { 621 t.Run("populated", func(t *testing.T) { 622 given := openrtb2.EID{ 623 Source: "anySource", 624 UIDs: []openrtb2.UID{{ID: "1", Ext: json.RawMessage(`{"uid":1}`)}}, 625 Ext: json.RawMessage(`{"anyField":1}`), 626 } 627 result := CloneEID(given) 628 assert.Equal(t, given, result, "equality") 629 assert.NotSame(t, given, result, "pointer") 630 assert.NotSame(t, given.UIDs, result.UIDs, "uids") 631 assert.NotSame(t, given.UIDs[0], result.UIDs[0], "uids-item") 632 assert.NotSame(t, given.UIDs[0].Ext, result.UIDs[0].Ext, "uids-item-ext") 633 assert.NotSame(t, given.Ext, result.Ext, "ext") 634 }) 635 636 t.Run("assumptions", func(t *testing.T) { 637 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.EID{})), 638 []string{ 639 "UIDs", 640 "Ext", 641 }) 642 }) 643 } 644 645 func TestCloneUIDSlice(t *testing.T) { 646 t.Run("nil", func(t *testing.T) { 647 result := CloneUIDSlice(nil) 648 assert.Nil(t, result) 649 }) 650 651 t.Run("empty", func(t *testing.T) { 652 given := []openrtb2.UID{} 653 result := CloneUIDSlice(given) 654 assert.Empty(t, result) 655 assert.NotSame(t, given, result) 656 }) 657 658 t.Run("one", func(t *testing.T) { 659 given := []openrtb2.UID{ 660 {ID: "1", Ext: json.RawMessage(`{"anyField":1}`)}, 661 } 662 result := CloneUIDSlice(given) 663 assert.Equal(t, given, result, "equality") 664 assert.NotSame(t, given[0], result[0], "item-pointer") 665 assert.NotSame(t, given[0].Ext, result[0].Ext, "item-pointer-ext") 666 }) 667 668 t.Run("many", func(t *testing.T) { 669 given := []openrtb2.UID{ 670 {ID: "1", Ext: json.RawMessage(`{"anyField":1}`)}, 671 {ID: "2", Ext: json.RawMessage(`{"anyField":2}`)}, 672 } 673 result := CloneUIDSlice(given) 674 assert.Equal(t, given, result, "equality") 675 assert.NotSame(t, given[0], result[0], "item0-pointer") 676 assert.NotSame(t, given[0].Ext, result[0].Ext, "item0-pointer-ext") 677 assert.NotSame(t, given[1], result[1], "item1-pointer") 678 assert.NotSame(t, given[1].Ext, result[1].Ext, "item1-pointer-ext") 679 }) 680 } 681 682 func TestCloneUID(t *testing.T) { 683 t.Run("populated", func(t *testing.T) { 684 given := openrtb2.UID{ 685 ID: "anyID", 686 AType: adcom1.AgentTypePerson, 687 Ext: json.RawMessage(`{"anyField":1}`), 688 } 689 result := CloneUID(given) 690 assert.Equal(t, given, result, "equality") 691 assert.NotSame(t, given, result, "pointer") 692 assert.NotSame(t, given.Ext, result.Ext, "ext") 693 }) 694 695 t.Run("assumptions", func(t *testing.T) { 696 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.UID{})), 697 []string{ 698 "Ext", 699 }) 700 }) 701 } 702 703 func TestCloneDOOH(t *testing.T) { 704 t.Run("nil", func(t *testing.T) { 705 result := CloneDOOH(nil) 706 assert.Nil(t, result) 707 }) 708 709 t.Run("empty", func(t *testing.T) { 710 given := &openrtb2.DOOH{} 711 result := CloneDOOH(given) 712 assert.Empty(t, result) 713 assert.NotSame(t, given, result) 714 }) 715 716 t.Run("populated", func(t *testing.T) { 717 given := &openrtb2.DOOH{ 718 ID: "anyID", 719 Name: "anyName", 720 VenueType: []string{"venue1"}, 721 VenueTypeTax: ptrutil.ToPtr(adcom1.VenueTaxonomyAdCom), 722 Publisher: &openrtb2.Publisher{ID: "anyPublisher", Ext: json.RawMessage(`{"publisher":1}`)}, 723 Domain: "anyDomain", 724 Keywords: "anyKeywords", 725 Content: &openrtb2.Content{ID: "anyContent", Ext: json.RawMessage(`{"content":1}`)}, 726 Ext: json.RawMessage(`{"anyField":1}`), 727 } 728 result := CloneDOOH(given) 729 assert.Equal(t, given, result, "equality") 730 assert.NotSame(t, given, result, "pointer") 731 assert.NotSame(t, given.VenueType, result.VenueType, "venuetype") 732 assert.NotSame(t, given.VenueTypeTax, result.VenueTypeTax, "venuetypetax") 733 assert.NotSame(t, given.Publisher, result.Publisher, "publisher") 734 assert.NotSame(t, given.Publisher.Ext, result.Publisher.Ext, "publisher-ext") 735 assert.NotSame(t, given.Content, result.Content, "content") 736 assert.NotSame(t, given.Content.Ext, result.Content.Ext, "content-ext") 737 assert.NotSame(t, given.Ext, result.Ext, "ext") 738 }) 739 740 t.Run("assumptions", func(t *testing.T) { 741 assert.ElementsMatch(t, discoverPointerFields(reflect.TypeOf(openrtb2.DOOH{})), 742 []string{ 743 "VenueType", 744 "VenueTypeTax", 745 "Publisher", 746 "Content", 747 "Ext", 748 }) 749 }) 750 } 751 752 // discoverPointerFields returns the names of all fields of an object that are 753 // pointers and would need to be cloned. This method is specific to types which can 754 // appear within an OpenRTB data model object. 755 func discoverPointerFields(t reflect.Type) []string { 756 var fields []string 757 for _, f := range reflect.VisibleFields(t) { 758 if f.Type.Kind() == reflect.Slice || f.Type.Kind() == reflect.Pointer { 759 fields = append(fields, f.Name) 760 } 761 } 762 return fields 763 }