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