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  }