github.com/prebid/prebid-server@v0.275.0/openrtb_ext/request_test.go (about)

     1  package openrtb_ext
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/prebid/openrtb/v19/openrtb2"
     9  	"github.com/prebid/prebid-server/util/ptrutil"
    10  	"github.com/stretchr/testify/assert"
    11  )
    12  
    13  type granularityTestData struct {
    14  	json   []byte
    15  	target PriceGranularity
    16  }
    17  
    18  func TestGranularityUnmarshal(t *testing.T) {
    19  	testGroups := []struct {
    20  		desc        string
    21  		in          []granularityTestData
    22  		expectError bool
    23  	}{
    24  		{
    25  			desc:        "Unmarshal without error",
    26  			in:          validGranularityTests,
    27  			expectError: false,
    28  		},
    29  		{
    30  			desc: "Malformed json. Expect unmarshall error",
    31  			in: []granularityTestData{
    32  				{json: []byte(`[]`)},
    33  			},
    34  			expectError: true,
    35  		},
    36  	}
    37  	for _, tg := range testGroups {
    38  		for i, tc := range tg.in {
    39  			var resolved PriceGranularity
    40  			err := json.Unmarshal(tc.json, &resolved)
    41  
    42  			// Assert validation error
    43  			if tg.expectError && !assert.Errorf(t, err, "%s test case %d", tg.desc, i) {
    44  				continue
    45  			}
    46  
    47  			// Assert Targeting.Precision
    48  			assert.Equal(t, tc.target.Precision, resolved.Precision, "%s test case %d", tg.desc, i)
    49  
    50  			// Assert Targeting.Ranges
    51  			if assert.Len(t, resolved.Ranges, len(tc.target.Ranges), "%s test case %d", tg.desc, i) {
    52  				expected := make(map[string]struct{}, len(tc.target.Ranges))
    53  				for _, r := range tc.target.Ranges {
    54  					expected[fmt.Sprintf("%2.2f-%2.2f-%2.2f", r.Min, r.Max, r.Increment)] = struct{}{}
    55  				}
    56  				for _, actualRange := range resolved.Ranges {
    57  					targetRange := fmt.Sprintf("%2.2f-%2.2f-%2.2f", actualRange.Min, actualRange.Max, actualRange.Increment)
    58  					_, exists := expected[targetRange]
    59  					assert.True(t, exists, "%s test case %d target.range %s not found", tg.desc, i, targetRange)
    60  				}
    61  			}
    62  		}
    63  	}
    64  }
    65  
    66  var validGranularityTests []granularityTestData = []granularityTestData{
    67  	{
    68  		json: []byte(`{"precision": 4, "ranges": [{"min": 0, "max": 5, "increment": 0.1}, {"min": 5, "max":10, "increment":0.5}, {"min":10, "max":20, "increment":1}]}`),
    69  		target: PriceGranularity{
    70  			Precision: ptrutil.ToPtr(4),
    71  			Ranges: []GranularityRange{
    72  				{Min: 0.0, Max: 5.0, Increment: 0.1},
    73  				{Min: 5.0, Max: 10.0, Increment: 0.5},
    74  				{Min: 10.0, Max: 20.0, Increment: 1.0},
    75  			},
    76  		},
    77  	},
    78  	{
    79  		json: []byte(`{"ranges":[{ "max":5, "increment": 0.05}, {"max": 10, "increment": 0.25}, {"max": 20, "increment": 0.5}]}`),
    80  		target: PriceGranularity{
    81  			Ranges: []GranularityRange{
    82  				{Min: 0.0, Max: 5.0, Increment: 0.05},
    83  				{Min: 0.0, Max: 10.0, Increment: 0.25},
    84  				{Min: 0.0, Max: 20.0, Increment: 0.5},
    85  			},
    86  		},
    87  	},
    88  	{
    89  		json: []byte(`"medium"`),
    90  		target: PriceGranularity{
    91  			Precision: ptrutil.ToPtr(2),
    92  			Ranges: []GranularityRange{{
    93  				Min:       0,
    94  				Max:       20,
    95  				Increment: 0.1}},
    96  		},
    97  	},
    98  	{
    99  		json: []byte(`{ "precision": 3, "ranges": [{"max":20, "increment":0.005}]}`),
   100  		target: PriceGranularity{
   101  			Precision: ptrutil.ToPtr(3),
   102  			Ranges:    []GranularityRange{{Min: 0.0, Max: 20.0, Increment: 0.005}},
   103  		},
   104  	},
   105  	{
   106  		json: []byte(`{"precision": 0, "ranges": [{"max":5, "increment": 1}, {"max": 10, "increment": 2}, {"max": 20, "increment": 5}]}`),
   107  		target: PriceGranularity{
   108  			Precision: ptrutil.ToPtr(0),
   109  			Ranges: []GranularityRange{
   110  				{Min: 0.0, Max: 5.0, Increment: 1.0},
   111  				{Min: 0.0, Max: 10.0, Increment: 2.0},
   112  				{Min: 0.0, Max: 20.0, Increment: 5.0},
   113  			},
   114  		},
   115  	},
   116  	{
   117  		json: []byte(`{"precision": 2, "ranges": [{"min": 0.5, "max":5, "increment": 0.1}, {"min": 54, "max": 10, "increment": 1}, {"min": -42, "max": 20, "increment": 5}]}`),
   118  		target: PriceGranularity{
   119  			Precision: ptrutil.ToPtr(2),
   120  			Ranges: []GranularityRange{
   121  				{Min: 0.5, Max: 5.0, Increment: 0.1},
   122  				{Min: 54.0, Max: 10.0, Increment: 1.0},
   123  				{Min: -42.0, Max: 20.0, Increment: 5.0},
   124  			},
   125  		},
   126  	},
   127  	{
   128  		json:   []byte(`{}`),
   129  		target: PriceGranularity{},
   130  	},
   131  	{
   132  		json: []byte(`{"precision": 2}`),
   133  		target: PriceGranularity{
   134  			Precision: ptrutil.ToPtr(2),
   135  		},
   136  	},
   137  	{
   138  		json: []byte(`{"precision": 2, "ranges":[]}`),
   139  		target: PriceGranularity{
   140  			Precision: ptrutil.ToPtr(2),
   141  			Ranges:    []GranularityRange{},
   142  		},
   143  	},
   144  }
   145  
   146  func TestCloneExtRequestPrebid(t *testing.T) {
   147  	testCases := []struct {
   148  		name       string
   149  		prebid     *ExtRequestPrebid
   150  		prebidCopy *ExtRequestPrebid                            // manual copy of above prebid object to verify against
   151  		mutator    func(t *testing.T, prebid *ExtRequestPrebid) // function to modify the prebid object
   152  	}{
   153  		{
   154  			name:       "Nil", // Verify the nil case
   155  			prebid:     nil,
   156  			prebidCopy: nil,
   157  			mutator:    func(t *testing.T, prebid *ExtRequestPrebid) {},
   158  		},
   159  		{
   160  			name: "NoMutateTest",
   161  			prebid: &ExtRequestPrebid{
   162  				Aliases:              map[string]string{"alias1": "bidder1"},
   163  				BidAdjustmentFactors: map[string]float64{"bidder5": 1.2},
   164  				BidderParams:         json.RawMessage(`{}`),
   165  				Channel: &ExtRequestPrebidChannel{
   166  					Name:    "ABC",
   167  					Version: "1.0",
   168  				},
   169  				Debug: true,
   170  				Experiment: &Experiment{
   171  					AdsCert: &AdsCert{
   172  						Enabled: false,
   173  					},
   174  				},
   175  				Server: &ExtRequestPrebidServer{
   176  					ExternalUrl: "http://www.example.com",
   177  					GvlID:       5,
   178  					DataCenter:  "Universe Central",
   179  				},
   180  				SupportDeals: true,
   181  			},
   182  			prebidCopy: &ExtRequestPrebid{
   183  				Aliases:              map[string]string{"alias1": "bidder1"},
   184  				BidAdjustmentFactors: map[string]float64{"bidder5": 1.2},
   185  				BidderParams:         json.RawMessage(`{}`),
   186  				Channel: &ExtRequestPrebidChannel{
   187  					Name:    "ABC",
   188  					Version: "1.0",
   189  				},
   190  				Debug: true,
   191  				Experiment: &Experiment{
   192  					AdsCert: &AdsCert{
   193  						Enabled: false,
   194  					},
   195  				},
   196  				Server: &ExtRequestPrebidServer{
   197  					ExternalUrl: "http://www.example.com",
   198  					GvlID:       5,
   199  					DataCenter:  "Universe Central",
   200  				},
   201  				SupportDeals: true,
   202  			},
   203  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {},
   204  		},
   205  		{
   206  			name: "GeneralTest",
   207  			prebid: &ExtRequestPrebid{
   208  				Aliases:              map[string]string{"alias1": "bidder1"},
   209  				BidAdjustmentFactors: map[string]float64{"bidder5": 1.2},
   210  				BidderParams:         json.RawMessage(`{}`),
   211  				Channel: &ExtRequestPrebidChannel{
   212  					Name:    "ABC",
   213  					Version: "1.0",
   214  				},
   215  				Debug: true,
   216  				Experiment: &Experiment{
   217  					AdsCert: &AdsCert{
   218  						Enabled: false,
   219  					},
   220  				},
   221  				Server: &ExtRequestPrebidServer{
   222  					ExternalUrl: "http://www.example.com",
   223  					GvlID:       5,
   224  					DataCenter:  "Universe Central",
   225  				},
   226  				SupportDeals: true,
   227  			},
   228  			prebidCopy: &ExtRequestPrebid{
   229  				Aliases:              map[string]string{"alias1": "bidder1"},
   230  				BidAdjustmentFactors: map[string]float64{"bidder5": 1.2},
   231  				BidderParams:         json.RawMessage(`{}`),
   232  				Channel: &ExtRequestPrebidChannel{
   233  					Name:    "ABC",
   234  					Version: "1.0",
   235  				},
   236  				Debug: true,
   237  				Experiment: &Experiment{
   238  					AdsCert: &AdsCert{
   239  						Enabled: false,
   240  					},
   241  				},
   242  				Server: &ExtRequestPrebidServer{
   243  					ExternalUrl: "http://www.example.com",
   244  					GvlID:       5,
   245  					DataCenter:  "Universe Central",
   246  				},
   247  				SupportDeals: true,
   248  			},
   249  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   250  				prebid.Aliases["alias2"] = "bidder52"
   251  				prebid.Aliases["alias1"] = "some other"
   252  				prebid.AliasGVLIDs = map[string]uint16{"alias2": 42}
   253  				prebid.BidAdjustmentFactors["alias2"] = 1.1
   254  				delete(prebid.BidAdjustmentFactors, "bidder5")
   255  				prebid.BidderParams = json.RawMessage(`{"someJSON": true}`)
   256  				prebid.Channel = nil
   257  				prebid.Data = &ExtRequestPrebidData{
   258  					EidPermissions: []ExtRequestPrebidDataEidPermission{{Source: "mySource", Bidders: []string{"sauceBidder"}}},
   259  				}
   260  				prebid.Events = json.RawMessage(`{}`)
   261  				prebid.Server.GvlID = 7
   262  				prebid.SupportDeals = false
   263  			},
   264  		},
   265  		{
   266  			name: "BidderConfig",
   267  			prebid: &ExtRequestPrebid{
   268  				BidderConfigs: []BidderConfig{
   269  					{
   270  						Bidders: []string{"Bidder1", "bidder2"},
   271  						Config:  &Config{&ORTB2{Site: json.RawMessage(`{"value":"config1"}`)}},
   272  					},
   273  					{
   274  						Bidders: []string{"Bidder5", "bidder17"},
   275  						Config:  &Config{&ORTB2{App: json.RawMessage(`{"value":"config2"}`)}},
   276  					},
   277  					{
   278  						Bidders: []string{"foo"},
   279  						Config:  &Config{&ORTB2{User: json.RawMessage(`{"value":"config3"}`)}},
   280  					},
   281  				},
   282  			},
   283  			prebidCopy: &ExtRequestPrebid{
   284  				BidderConfigs: []BidderConfig{
   285  					{
   286  						Bidders: []string{"Bidder1", "bidder2"},
   287  						Config:  &Config{&ORTB2{Site: json.RawMessage(`{"value":"config1"}`)}},
   288  					},
   289  					{
   290  						Bidders: []string{"Bidder5", "bidder17"},
   291  						Config:  &Config{&ORTB2{App: json.RawMessage(`{"value":"config2"}`)}},
   292  					},
   293  					{
   294  						Bidders: []string{"foo"},
   295  						Config:  &Config{&ORTB2{User: json.RawMessage(`{"value":"config3"}`)}},
   296  					},
   297  				},
   298  			},
   299  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   300  				prebid.BidderConfigs[0].Bidders = append(prebid.BidderConfigs[0].Bidders, "bidder4")
   301  				prebid.BidderConfigs[1] = BidderConfig{
   302  					Bidders: []string{"george"},
   303  					Config:  &Config{nil},
   304  				}
   305  				prebid.BidderConfigs[2].Config.ORTB2.User = json.RawMessage(`{"id": 345}`)
   306  				prebid.BidderConfigs = append(prebid.BidderConfigs, BidderConfig{
   307  					Bidders: []string{"bidder2"},
   308  					Config:  &Config{&ORTB2{}},
   309  				})
   310  			},
   311  		},
   312  		{
   313  			name: "Cache",
   314  			prebid: &ExtRequestPrebid{
   315  				Cache: &ExtRequestPrebidCache{
   316  					Bids: &ExtRequestPrebidCacheBids{
   317  						ReturnCreative: ptrutil.ToPtr(true),
   318  					},
   319  					VastXML: &ExtRequestPrebidCacheVAST{
   320  						ReturnCreative: ptrutil.ToPtr(false),
   321  					},
   322  				},
   323  			},
   324  			prebidCopy: &ExtRequestPrebid{
   325  				Cache: &ExtRequestPrebidCache{
   326  					Bids: &ExtRequestPrebidCacheBids{
   327  						ReturnCreative: ptrutil.ToPtr(true),
   328  					},
   329  					VastXML: &ExtRequestPrebidCacheVAST{
   330  						ReturnCreative: ptrutil.ToPtr(false),
   331  					},
   332  				},
   333  			},
   334  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   335  				prebid.Cache.Bids.ReturnCreative = ptrutil.ToPtr(false)
   336  				prebid.Cache.Bids = nil
   337  				prebid.Cache.VastXML = &ExtRequestPrebidCacheVAST{
   338  					ReturnCreative: ptrutil.ToPtr(true),
   339  				}
   340  			},
   341  		},
   342  		{
   343  			name: "Currency",
   344  			prebid: &ExtRequestPrebid{
   345  				CurrencyConversions: &ExtRequestCurrency{
   346  					ConversionRates: map[string]map[string]float64{"A": {"X": 5.4}},
   347  					UsePBSRates:     ptrutil.ToPtr(false),
   348  				},
   349  			},
   350  			prebidCopy: &ExtRequestPrebid{
   351  				CurrencyConversions: &ExtRequestCurrency{
   352  					ConversionRates: map[string]map[string]float64{"A": {"X": 5.4}},
   353  					UsePBSRates:     ptrutil.ToPtr(false),
   354  				},
   355  			},
   356  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   357  				prebid.CurrencyConversions.ConversionRates["A"]["X"] = 3.4
   358  				prebid.CurrencyConversions.ConversionRates["B"] = make(map[string]float64)
   359  				prebid.CurrencyConversions.ConversionRates["B"]["Y"] = 0.76
   360  				prebid.CurrencyConversions.UsePBSRates = ptrutil.ToPtr(true)
   361  			},
   362  		},
   363  		{
   364  			name: "Data",
   365  			prebid: &ExtRequestPrebid{
   366  				Data: &ExtRequestPrebidData{
   367  					EidPermissions: []ExtRequestPrebidDataEidPermission{
   368  						{
   369  							Source:  "Sauce",
   370  							Bidders: []string{"G", "H"},
   371  						},
   372  						{
   373  							Source:  "Black Hole",
   374  							Bidders: []string{"Q", "P"},
   375  						},
   376  					},
   377  					Bidders: []string{"A", "B", "C"},
   378  				},
   379  			},
   380  			prebidCopy: &ExtRequestPrebid{
   381  				Data: &ExtRequestPrebidData{
   382  					EidPermissions: []ExtRequestPrebidDataEidPermission{
   383  						{
   384  							Source:  "Sauce",
   385  							Bidders: []string{"G", "H"},
   386  						},
   387  						{
   388  							Source:  "Black Hole",
   389  							Bidders: []string{"Q", "P"},
   390  						},
   391  					},
   392  					Bidders: []string{"A", "B", "C"},
   393  				},
   394  			},
   395  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   396  				prebid.Data.EidPermissions[0].Source = "Fuzzy Bunnies"
   397  				prebid.Data.EidPermissions[1].Bidders[0] = "X"
   398  				prebid.Data.EidPermissions[0].Bidders = append(prebid.Data.EidPermissions[0].Bidders, "R")
   399  				prebid.Data.EidPermissions = append(prebid.Data.EidPermissions, ExtRequestPrebidDataEidPermission{Source: "Harry"})
   400  				prebid.Data.Bidders[1] = "D"
   401  				prebid.Data.Bidders = append(prebid.Data.Bidders, "E")
   402  			},
   403  		},
   404  		{
   405  			name: "Multibid",
   406  			prebid: &ExtRequestPrebid{
   407  				MultiBid: []*ExtMultiBid{
   408  					{Bidder: "somebidder", MaxBids: ptrutil.ToPtr(3), TargetBidderCodePrefix: "SB"},
   409  					{Bidders: []string{"A", "B", "C"}, MaxBids: ptrutil.ToPtr(4)},
   410  				},
   411  			},
   412  			prebidCopy: &ExtRequestPrebid{
   413  				MultiBid: []*ExtMultiBid{
   414  					{Bidder: "somebidder", MaxBids: ptrutil.ToPtr(3), TargetBidderCodePrefix: "SB"},
   415  					{Bidders: []string{"A", "B", "C"}, MaxBids: ptrutil.ToPtr(4)},
   416  				},
   417  			},
   418  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   419  				prebid.MultiBid[0].MaxBids = ptrutil.ToPtr(2)
   420  				prebid.MultiBid[1].Bidders = []string{"C", "D", "E", "F"}
   421  				prebid.MultiBid = []*ExtMultiBid{
   422  					{Bidder: "otherbid"},
   423  				}
   424  			},
   425  		},
   426  		{
   427  			name: "PassthroughSChains",
   428  			prebid: &ExtRequestPrebid{
   429  				SChains: []*ExtRequestPrebidSChain{
   430  					{
   431  						Bidders: []string{"A", "B", "C"},
   432  						SChain: openrtb2.SupplyChain{
   433  							Complete: 1,
   434  							Ver:      "2.2",
   435  							Ext:      json.RawMessage(`{"foo": "bar"}`),
   436  							Nodes: []openrtb2.SupplyChainNode{
   437  								{
   438  									ASI:    "something",
   439  									Domain: "example.com",
   440  									HP:     openrtb2.Int8Ptr(1),
   441  								},
   442  							},
   443  						},
   444  					},
   445  				},
   446  			},
   447  			prebidCopy: &ExtRequestPrebid{
   448  				SChains: []*ExtRequestPrebidSChain{
   449  					{
   450  						Bidders: []string{"A", "B", "C"},
   451  						SChain: openrtb2.SupplyChain{
   452  							Complete: 1,
   453  							Ver:      "2.2",
   454  							Ext:      json.RawMessage(`{"foo": "bar"}`),
   455  							Nodes: []openrtb2.SupplyChainNode{
   456  								{
   457  									ASI:    "something",
   458  									Domain: "example.com",
   459  									HP:     openrtb2.Int8Ptr(1),
   460  								},
   461  							},
   462  						},
   463  					},
   464  				},
   465  			},
   466  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   467  				prebid.Passthrough = json.RawMessage(`{"bar": "foo"}`)
   468  				prebid.SChains[0].Bidders = append(prebid.SChains[0].Bidders, "D")
   469  				prebid.SChains[0].SChain.Ver = "2.3"
   470  				prebid.SChains[0].SChain.Complete = 0
   471  				prebid.SChains[0].SChain.Nodes[0].Name = "Alice"
   472  				prebid.SChains[0].SChain.Nodes[0].ASI = "New ASI"
   473  				prebid.SChains[0].SChain.Nodes[0].HP = openrtb2.Int8Ptr(0)
   474  				prebid.SChains[0].SChain.Nodes = append(prebid.SChains[0].SChain.Nodes, prebid.SChains[0].SChain.Nodes[0])
   475  				prebid.SChains = append(prebid.SChains, prebid.SChains[0])
   476  			},
   477  		},
   478  		{
   479  			name: "StoredRequest",
   480  			prebid: &ExtRequestPrebid{
   481  				StoredRequest: &ExtStoredRequest{
   482  					ID: "abc123",
   483  				},
   484  			},
   485  			prebidCopy: &ExtRequestPrebid{
   486  				StoredRequest: &ExtStoredRequest{
   487  					ID: "abc123",
   488  				},
   489  			},
   490  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   491  				prebid.StoredRequest.ID = "nada"
   492  				prebid.StoredRequest = &ExtStoredRequest{ID: "ID"}
   493  			},
   494  		},
   495  		{
   496  			name: "Targeting",
   497  			prebid: &ExtRequestPrebid{
   498  				Targeting: &ExtRequestTargeting{
   499  					PriceGranularity: &PriceGranularity{
   500  						Precision: ptrutil.ToPtr(2),
   501  						Ranges: []GranularityRange{
   502  							{Max: 2.0, Increment: 0.1},
   503  							{Max: 10.0, Increment: 0.5},
   504  							{Max: 20.0, Increment: 1.0},
   505  						},
   506  					},
   507  					IncludeWinners: ptrutil.ToPtr(true),
   508  					IncludeBrandCategory: &ExtIncludeBrandCategory{
   509  						PrimaryAdServer:     1,
   510  						Publisher:           "Bob",
   511  						TranslateCategories: ptrutil.ToPtr(true),
   512  					},
   513  					DurationRangeSec: []int{1, 2, 3},
   514  				},
   515  			},
   516  			prebidCopy: &ExtRequestPrebid{
   517  				Targeting: &ExtRequestTargeting{
   518  					PriceGranularity: &PriceGranularity{
   519  						Precision: ptrutil.ToPtr(2),
   520  						Ranges: []GranularityRange{
   521  							{Max: 2.0, Increment: 0.1},
   522  							{Max: 10.0, Increment: 0.5},
   523  							{Max: 20.0, Increment: 1.0},
   524  						},
   525  					},
   526  					IncludeWinners: ptrutil.ToPtr(true),
   527  					IncludeBrandCategory: &ExtIncludeBrandCategory{
   528  						PrimaryAdServer:     1,
   529  						Publisher:           "Bob",
   530  						TranslateCategories: ptrutil.ToPtr(true),
   531  					},
   532  					DurationRangeSec: []int{1, 2, 3},
   533  				},
   534  			},
   535  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   536  				prebid.Targeting.PriceGranularity.Ranges[1].Max = 12
   537  				prebid.Targeting.PriceGranularity.Ranges[1].Min = 2.0
   538  				prebid.Targeting.PriceGranularity.Ranges = append(prebid.Targeting.PriceGranularity.Ranges, GranularityRange{Max: 50, Increment: 2.0})
   539  				prebid.Targeting.IncludeWinners = nil
   540  				prebid.Targeting.IncludeBidderKeys = ptrutil.ToPtr(true)
   541  				prebid.Targeting.IncludeBrandCategory.TranslateCategories = ptrutil.ToPtr(false)
   542  				prebid.Targeting.IncludeBrandCategory = nil
   543  				prebid.Targeting.DurationRangeSec[1] = 5
   544  				prebid.Targeting.DurationRangeSec = append(prebid.Targeting.DurationRangeSec, 1)
   545  				prebid.Targeting.AppendBidderNames = true
   546  			},
   547  		},
   548  		{
   549  			name: "NoSale",
   550  			prebid: &ExtRequestPrebid{
   551  				NoSale: []string{"A", "B", "C"},
   552  			},
   553  			prebidCopy: &ExtRequestPrebid{
   554  				NoSale: []string{"A", "B", "C"},
   555  			},
   556  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   557  				prebid.NoSale[1] = "G"
   558  				prebid.NoSale = append(prebid.NoSale, "D")
   559  			},
   560  		},
   561  		{
   562  			name: "AlternateBidderCodes",
   563  			prebid: &ExtRequestPrebid{
   564  				AlternateBidderCodes: &ExtAlternateBidderCodes{
   565  					Enabled: true,
   566  					Bidders: map[string]ExtAdapterAlternateBidderCodes{
   567  						"X": {Enabled: true, AllowedBidderCodes: []string{"A", "B", "C"}},
   568  						"Y": {Enabled: false, AllowedBidderCodes: []string{"C", "B", "G"}},
   569  					},
   570  				},
   571  			},
   572  			prebidCopy: &ExtRequestPrebid{
   573  				AlternateBidderCodes: &ExtAlternateBidderCodes{
   574  					Enabled: true,
   575  					Bidders: map[string]ExtAdapterAlternateBidderCodes{
   576  						"X": {Enabled: true, AllowedBidderCodes: []string{"A", "B", "C"}},
   577  						"Y": {Enabled: false, AllowedBidderCodes: []string{"C", "B", "G"}},
   578  					},
   579  				},
   580  			},
   581  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   582  				newAABC := prebid.AlternateBidderCodes.Bidders["X"]
   583  				newAABC.Enabled = false
   584  				newAABC.AllowedBidderCodes[1] = "F"
   585  				newAABC.AllowedBidderCodes = append(newAABC.AllowedBidderCodes, "Z")
   586  				prebid.AlternateBidderCodes.Bidders["X"] = newAABC
   587  				prebid.AlternateBidderCodes.Bidders["Z"] = ExtAdapterAlternateBidderCodes{Enabled: true, AllowedBidderCodes: []string{"G", "Z"}}
   588  				prebid.AlternateBidderCodes.Enabled = false
   589  				prebid.AlternateBidderCodes = nil
   590  			},
   591  		},
   592  		{
   593  			name: "Floors",
   594  			prebid: &ExtRequestPrebid{
   595  				Floors: &PriceFloorRules{
   596  					FloorMin:    0.25,
   597  					FloorMinCur: "EUR",
   598  					Location: &PriceFloorEndpoint{
   599  						URL: "http://www.example.com",
   600  					},
   601  					Data: &PriceFloorData{
   602  						Currency: "USD",
   603  						SkipRate: 3,
   604  						ModelGroups: []PriceFloorModelGroup{
   605  							{
   606  								Currency:    "USD",
   607  								ModelWeight: ptrutil.ToPtr(0),
   608  								SkipRate:    2,
   609  								Schema: PriceFloorSchema{
   610  									Fields:    []string{"A", "B"},
   611  									Delimiter: "^",
   612  								},
   613  								Values: map[string]float64{"A": 2, "B": 1},
   614  							},
   615  						},
   616  					},
   617  					Enforcement: &PriceFloorEnforcement{
   618  						EnforceJS:   ptrutil.ToPtr(true),
   619  						FloorDeals:  ptrutil.ToPtr(false),
   620  						EnforceRate: 5,
   621  					},
   622  					Enabled:       ptrutil.ToPtr(true),
   623  					FloorProvider: "Someone",
   624  				},
   625  			},
   626  			prebidCopy: &ExtRequestPrebid{
   627  				Floors: &PriceFloorRules{
   628  					FloorMin:    0.25,
   629  					FloorMinCur: "EUR",
   630  					Location: &PriceFloorEndpoint{
   631  						URL: "http://www.example.com",
   632  					},
   633  					Data: &PriceFloorData{
   634  						Currency: "USD",
   635  						SkipRate: 3,
   636  						ModelGroups: []PriceFloorModelGroup{
   637  							{
   638  								Currency:    "USD",
   639  								ModelWeight: ptrutil.ToPtr(0),
   640  								SkipRate:    2,
   641  								Schema: PriceFloorSchema{
   642  									Fields:    []string{"A", "B"},
   643  									Delimiter: "^",
   644  								},
   645  								Values: map[string]float64{"A": 2, "B": 1},
   646  							},
   647  						},
   648  					},
   649  					Enforcement: &PriceFloorEnforcement{
   650  						EnforceJS:   ptrutil.ToPtr(true),
   651  						FloorDeals:  ptrutil.ToPtr(false),
   652  						EnforceRate: 5,
   653  					},
   654  					Enabled:       ptrutil.ToPtr(true),
   655  					FloorProvider: "Someone",
   656  				},
   657  			},
   658  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   659  				prebid.Floors.Data.ModelGroups[0].Schema.Fields[1] = "C"
   660  				prebid.Floors.Data.ModelGroups[0].Schema.Fields = append(prebid.Floors.Data.ModelGroups[0].Schema.Fields, "D")
   661  				prebid.Floors.Data.ModelGroups[0].Schema.Delimiter = ","
   662  				prebid.Floors.Data.ModelGroups[0].Currency = "CRO"
   663  				prebid.Floors.Data.ModelGroups[0].ModelWeight = ptrutil.ToPtr(8)
   664  				prebid.Floors.Data.ModelGroups[0].Values["A"] = 0
   665  				prebid.Floors.Data.ModelGroups[0].Values["C"] = 7
   666  				prebid.Floors.Data.ModelGroups = append(prebid.Floors.Data.ModelGroups, PriceFloorModelGroup{})
   667  				prebid.Floors.FloorMin = 0.3
   668  				prebid.Floors.FetchStatus = "arf"
   669  				prebid.Floors.Location.URL = "www.nothere.com"
   670  				prebid.Floors.Location = nil
   671  				prebid.Floors.Enabled = nil
   672  				prebid.Floors.Skipped = ptrutil.ToPtr(true)
   673  				prebid.Floors.Enforcement.BidAdjustment = ptrutil.ToPtr(true)
   674  				prebid.Floors.Enforcement.EnforceJS = ptrutil.ToPtr(false)
   675  				prebid.Floors.Enforcement.FloorDeals = nil
   676  				prebid.Floors.FloorProvider = ""
   677  			},
   678  		},
   679  		{
   680  			name: "MultiBidMap",
   681  			prebid: &ExtRequestPrebid{
   682  				MultiBidMap: map[string]ExtMultiBid{
   683  					"A": {
   684  						Bidder:                 "J",
   685  						Bidders:                []string{"X", "Y", "Z"},
   686  						MaxBids:                ptrutil.ToPtr(5),
   687  						TargetBidderCodePrefix: ">>",
   688  					},
   689  					"B": {
   690  						Bidder:  "J",
   691  						Bidders: []string{"One", "Two", "Three"},
   692  					},
   693  				},
   694  			},
   695  			prebidCopy: &ExtRequestPrebid{
   696  				MultiBidMap: map[string]ExtMultiBid{
   697  					"A": {
   698  						Bidder:                 "J",
   699  						Bidders:                []string{"X", "Y", "Z"},
   700  						MaxBids:                ptrutil.ToPtr(5),
   701  						TargetBidderCodePrefix: ">>",
   702  					},
   703  					"B": {
   704  						Bidder:  "J",
   705  						Bidders: []string{"One", "Two", "Three"},
   706  					},
   707  				},
   708  			},
   709  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   710  				mulbidB := prebid.MultiBidMap["B"]
   711  				mulbidB.TargetBidderCodePrefix = "|"
   712  				mulbidB.Bidders[1] = "Five"
   713  				mulbidB.Bidders = append(mulbidB.Bidders, "Six")
   714  				mulbidB.MaxBids = ptrutil.ToPtr(2)
   715  				prebid.MultiBidMap["B"] = mulbidB
   716  				prebid.MultiBidMap["C"] = ExtMultiBid{Bidder: "alpha", MaxBids: ptrutil.ToPtr(3)}
   717  			},
   718  		},
   719  		{
   720  			name: "MultiBidMap",
   721  			prebid: &ExtRequestPrebid{
   722  				AdServerTargeting: []AdServerTarget{
   723  					{
   724  						Key:    "A",
   725  						Source: "Sauce",
   726  						Value:  "Gold",
   727  					},
   728  					{
   729  						Key:    "B",
   730  						Source: "Omega",
   731  						Value:  "Dirt",
   732  					},
   733  				},
   734  			},
   735  			prebidCopy: &ExtRequestPrebid{
   736  				AdServerTargeting: []AdServerTarget{
   737  					{
   738  						Key:    "A",
   739  						Source: "Sauce",
   740  						Value:  "Gold",
   741  					},
   742  					{
   743  						Key:    "B",
   744  						Source: "Omega",
   745  						Value:  "Dirt",
   746  					},
   747  				},
   748  			},
   749  			mutator: func(t *testing.T, prebid *ExtRequestPrebid) {
   750  				prebid.AdServerTargeting[0].Key = "Five"
   751  				prebid.AdServerTargeting[1].Value = "Dust"
   752  				prebid.AdServerTargeting = append(prebid.AdServerTargeting, AdServerTarget{Key: "Val"})
   753  				prebid.AdServerTargeting = nil
   754  			},
   755  		},
   756  	}
   757  
   758  	for _, test := range testCases {
   759  		t.Run(test.name, func(t *testing.T) {
   760  			clone := test.prebid.Clone()
   761  			if test.prebid != nil {
   762  				assert.NotSame(t, test.prebid, clone)
   763  			}
   764  			test.mutator(t, test.prebid)
   765  			assert.Equal(t, test.prebidCopy, clone)
   766  		})
   767  	}
   768  
   769  }