github.com/prebid/prebid-server/v2@v2.18.0/bidadjustment/build_rules_test.go (about)

     1  package bidadjustment
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/prebid/openrtb/v20/openrtb2"
     7  	"github.com/prebid/prebid-server/v2/config"
     8  	"github.com/prebid/prebid-server/v2/openrtb_ext"
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  func TestBuildRules(t *testing.T) {
    13  	testCases := []struct {
    14  		name                string
    15  		givenBidAdjustments *openrtb_ext.ExtRequestPrebidBidAdjustments
    16  		expectedRules       map[string][]openrtb_ext.Adjustment
    17  	}{
    18  		{
    19  			name: "OneAdjustment",
    20  			givenBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
    21  				MediaType: openrtb_ext.MediaType{
    22  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
    23  						"bidderA": {
    24  							"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}},
    25  						},
    26  					},
    27  				},
    28  			},
    29  			expectedRules: map[string][]openrtb_ext.Adjustment{
    30  				"banner|bidderA|dealId": {
    31  					{
    32  						Type:  AdjustmentTypeMultiplier,
    33  						Value: 1.1,
    34  					},
    35  				},
    36  			},
    37  		},
    38  		{
    39  			name: "MultipleAdjustments",
    40  			givenBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
    41  				MediaType: openrtb_ext.MediaType{
    42  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
    43  						"bidderA": {
    44  							"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}},
    45  						},
    46  						"*": {
    47  							"diffDealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 1.1, Currency: "USD"}},
    48  							"*":          []openrtb_ext.Adjustment{{Type: AdjustmentTypeStatic, Value: 5.0, Currency: "USD"}},
    49  						},
    50  					},
    51  					VideoInstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
    52  						"*": {
    53  							"*": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}, {Type: AdjustmentTypeCPM, Value: 0.18, Currency: "USD"}},
    54  						},
    55  					},
    56  					VideoOutstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
    57  						"bidderB": {
    58  							"*": []openrtb_ext.Adjustment{{Type: AdjustmentTypeStatic, Value: 0.25, Currency: "USD"}},
    59  						},
    60  					},
    61  				},
    62  			},
    63  			expectedRules: map[string][]openrtb_ext.Adjustment{
    64  				"banner|bidderA|dealId": {
    65  					{
    66  						Type:  AdjustmentTypeMultiplier,
    67  						Value: 1.1,
    68  					},
    69  				},
    70  				"banner|*|diffDealId": {
    71  					{
    72  						Type:     AdjustmentTypeCPM,
    73  						Value:    1.1,
    74  						Currency: "USD",
    75  					},
    76  				},
    77  				"banner|*|*": {
    78  					{
    79  						Type:     AdjustmentTypeStatic,
    80  						Value:    5.0,
    81  						Currency: "USD",
    82  					},
    83  				},
    84  				"video-instream|*|*": {
    85  					{
    86  						Type:  AdjustmentTypeMultiplier,
    87  						Value: 1.1,
    88  					},
    89  					{
    90  						Type:     AdjustmentTypeCPM,
    91  						Value:    0.18,
    92  						Currency: "USD",
    93  					},
    94  				},
    95  				"video-outstream|bidderB|*": {
    96  					{
    97  						Type:     AdjustmentTypeStatic,
    98  						Value:    0.25,
    99  						Currency: "USD",
   100  					},
   101  				},
   102  			},
   103  		},
   104  		{
   105  			name:                "NilAdjustments",
   106  			givenBidAdjustments: nil,
   107  			expectedRules:       nil,
   108  		},
   109  	}
   110  
   111  	for _, test := range testCases {
   112  		t.Run(test.name, func(t *testing.T) {
   113  			rules := BuildRules(test.givenBidAdjustments)
   114  			assert.Equal(t, test.expectedRules, rules)
   115  		})
   116  	}
   117  }
   118  
   119  func TestMergeAndValidate(t *testing.T) {
   120  	testCases := []struct {
   121  		name                   string
   122  		givenRequestWrapper    *openrtb_ext.RequestWrapper
   123  		givenAccount           *config.Account
   124  		expectError            bool
   125  		expectedBidAdjustments *openrtb_ext.ExtRequestPrebidBidAdjustments
   126  	}{
   127  		{
   128  			name: "ValidReqAndAcctAdjustments",
   129  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   130  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"banner":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)},
   131  			},
   132  			givenAccount: &config.Account{
   133  				BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   134  					MediaType: openrtb_ext.MediaType{
   135  						Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   136  							"bidderB": {
   137  								"dealId": []openrtb_ext.Adjustment{{Type: "multiplier", Value: 1.5}},
   138  							},
   139  						},
   140  					},
   141  				},
   142  			},
   143  			expectError: false,
   144  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   145  				MediaType: openrtb_ext.MediaType{
   146  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   147  						"bidderA": {
   148  							"dealId": []openrtb_ext.Adjustment{{Type: "multiplier", Value: 1.1}},
   149  						},
   150  						"bidderB": {
   151  							"dealId": []openrtb_ext.Adjustment{{Type: "multiplier", Value: 1.5}},
   152  						},
   153  					},
   154  				},
   155  			},
   156  		},
   157  		{
   158  			name: "InvalidReqAdjustment",
   159  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   160  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"banner":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 200}]}}}}}}`)},
   161  			},
   162  			givenAccount: &config.Account{
   163  				BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   164  					MediaType: openrtb_ext.MediaType{
   165  						Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   166  							"bidderB": {
   167  								"dealId": []openrtb_ext.Adjustment{{Type: "multiplier", Value: 1.5}},
   168  							},
   169  						},
   170  					},
   171  				},
   172  			},
   173  			expectError:            true,
   174  			expectedBidAdjustments: nil,
   175  		},
   176  		{
   177  			name: "InvalidAcctAdjustment",
   178  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   179  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"banner":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)},
   180  			},
   181  			givenAccount: &config.Account{
   182  				BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   183  					MediaType: openrtb_ext.MediaType{
   184  						Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   185  							"bidderB": {
   186  								"dealId": []openrtb_ext.Adjustment{{Type: "multiplier", Value: -1.5}},
   187  							},
   188  						},
   189  					},
   190  				},
   191  			},
   192  			expectError:            true,
   193  			expectedBidAdjustments: nil,
   194  		},
   195  		{
   196  			name: "InvalidJSON",
   197  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   198  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{}}`)},
   199  			},
   200  			givenAccount:           &config.Account{},
   201  			expectError:            true,
   202  			expectedBidAdjustments: nil,
   203  		},
   204  	}
   205  
   206  	for _, test := range testCases {
   207  		t.Run(test.name, func(t *testing.T) {
   208  			mergedBidAdj, err := Merge(test.givenRequestWrapper, test.givenAccount.BidAdjustments)
   209  			if !test.expectError {
   210  				assert.NoError(t, err)
   211  			} else {
   212  				assert.Error(t, err)
   213  			}
   214  			assert.Equal(t, test.expectedBidAdjustments, mergedBidAdj)
   215  		})
   216  	}
   217  }
   218  
   219  func TestMerge(t *testing.T) {
   220  	testCases := []struct {
   221  		name                   string
   222  		givenRequestWrapper    *openrtb_ext.RequestWrapper
   223  		acctBidAdjustments     *openrtb_ext.ExtRequestPrebidBidAdjustments
   224  		expectedBidAdjustments *openrtb_ext.ExtRequestPrebidBidAdjustments
   225  	}{
   226  		{
   227  			name: "DiffBidderNames",
   228  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   229  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"banner":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)},
   230  			},
   231  			acctBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   232  				MediaType: openrtb_ext.MediaType{
   233  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   234  						"bidderB": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}},
   235  					},
   236  				},
   237  			},
   238  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   239  				MediaType: openrtb_ext.MediaType{
   240  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   241  						"bidderA": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}},
   242  						"bidderB": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}},
   243  					},
   244  				},
   245  			},
   246  		},
   247  		{
   248  			name: "RequestTakesPrecedence",
   249  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   250  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"audio":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)},
   251  			},
   252  			acctBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   253  				MediaType: openrtb_ext.MediaType{
   254  					Audio: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   255  						"bidderA": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}},
   256  					},
   257  				},
   258  			},
   259  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   260  				MediaType: openrtb_ext.MediaType{
   261  					Audio: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   262  						"bidderA": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}},
   263  					},
   264  				},
   265  			},
   266  		},
   267  		{
   268  			name: "DiffDealIds",
   269  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   270  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"video-instream":{"bidderA":{"dealId":[{ "adjtype": "static", "value": 3.00, "currency": "USD"}]}}}}}}`)},
   271  			},
   272  			acctBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   273  				MediaType: openrtb_ext.MediaType{
   274  					VideoInstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   275  						"bidderA": {"diffDealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}},
   276  					},
   277  				},
   278  			},
   279  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   280  				MediaType: openrtb_ext.MediaType{
   281  					VideoInstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   282  						"bidderA": {
   283  							"dealId":     []openrtb_ext.Adjustment{{Type: AdjustmentTypeStatic, Value: 3.00, Currency: "USD"}},
   284  							"diffDealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   285  						},
   286  					},
   287  				},
   288  			},
   289  		},
   290  		{
   291  			name: "DiffBidderNamesCpm",
   292  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   293  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"native":{"bidderA":{"dealId":[{"adjtype": "cpm", "value": 0.18, "currency": "USD"}]}}}}}}`)},
   294  			},
   295  			acctBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   296  				MediaType: openrtb_ext.MediaType{
   297  					Native: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   298  						"bidderB": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}},
   299  					},
   300  				},
   301  			},
   302  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   303  				MediaType: openrtb_ext.MediaType{
   304  					Native: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   305  						"bidderA": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 0.18, Currency: "USD"}}},
   306  						"bidderB": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}},
   307  					},
   308  				},
   309  			},
   310  		},
   311  		{
   312  			name: "ReqAdjVideoAcctAdjBanner",
   313  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   314  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"video-outstream":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)},
   315  			},
   316  			acctBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   317  				MediaType: openrtb_ext.MediaType{
   318  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   319  						"bidderB": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}},
   320  					},
   321  				},
   322  			},
   323  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   324  				MediaType: openrtb_ext.MediaType{
   325  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   326  						"bidderB": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}},
   327  					},
   328  					VideoOutstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   329  						"bidderA": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}},
   330  					},
   331  				},
   332  			},
   333  		},
   334  		{
   335  			name: "RequestNilPrebid",
   336  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   337  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"ext":{"bidder": {}}}`)},
   338  			},
   339  			acctBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   340  				MediaType: openrtb_ext.MediaType{
   341  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   342  						"bidderB": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}},
   343  					},
   344  				},
   345  			},
   346  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   347  				MediaType: openrtb_ext.MediaType{
   348  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   349  						"bidderB": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}},
   350  					},
   351  				},
   352  			},
   353  		},
   354  		{
   355  			name: "AcctWildCardRequestVideo",
   356  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   357  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"video-instream":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)},
   358  			},
   359  			acctBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   360  				MediaType: openrtb_ext.MediaType{
   361  					WildCard: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   362  						"bidderB": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}},
   363  					},
   364  				},
   365  			},
   366  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   367  				MediaType: openrtb_ext.MediaType{
   368  					WildCard: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   369  						"bidderB": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}},
   370  					},
   371  					VideoInstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   372  						"bidderA": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}},
   373  					},
   374  				},
   375  			},
   376  		},
   377  		{
   378  			name: "NilReqExtPrebidAndAcctBidAdj",
   379  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   380  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"ext":{"bidder": {}}}`)},
   381  			},
   382  			acctBidAdjustments:     nil,
   383  			expectedBidAdjustments: nil,
   384  		},
   385  		{
   386  			name: "NilAcctBidAdj",
   387  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   388  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"banner":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)},
   389  			},
   390  			acctBidAdjustments: nil,
   391  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   392  				MediaType: openrtb_ext.MediaType{
   393  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   394  						"bidderA": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}},
   395  					},
   396  				},
   397  			},
   398  		},
   399  
   400  		{
   401  			name: "NilExtPrebid-NilExtPrebidBidAdj_NilAcct",
   402  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   403  				BidRequest: &openrtb2.BidRequest{},
   404  			},
   405  			acctBidAdjustments:     nil,
   406  			expectedBidAdjustments: nil,
   407  		},
   408  		{
   409  			name: "NilExtPrebid-NilExtPrebidBidAdj-Acct",
   410  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   411  				BidRequest: &openrtb2.BidRequest{},
   412  			},
   413  			acctBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   414  				MediaType: openrtb_ext.MediaType{
   415  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   416  						"bidderA": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}},
   417  					},
   418  				},
   419  			},
   420  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   421  				MediaType: openrtb_ext.MediaType{
   422  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   423  						"bidderA": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}},
   424  					},
   425  				},
   426  			},
   427  		},
   428  		{
   429  			name: "NotNilExtPrebid-NilExtBidAdj-NilAcct",
   430  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   431  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{}}`)},
   432  			},
   433  			acctBidAdjustments:     nil,
   434  			expectedBidAdjustments: nil,
   435  		},
   436  		{
   437  			name: "NotNilExtPrebid_NilExtBidAdj_NotNilAcct",
   438  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   439  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{}}`)},
   440  			},
   441  			acctBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   442  				MediaType: openrtb_ext.MediaType{
   443  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   444  						"bidderA": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}},
   445  					},
   446  				},
   447  			},
   448  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   449  				MediaType: openrtb_ext.MediaType{
   450  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   451  						"bidderA": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}},
   452  					},
   453  				},
   454  			},
   455  		},
   456  		{
   457  			name: "NotNilExtPrebid-NotNilExtBidAdj-NilAcct",
   458  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   459  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"banner":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)},
   460  			},
   461  			acctBidAdjustments: nil,
   462  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   463  				MediaType: openrtb_ext.MediaType{
   464  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   465  						"bidderA": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}},
   466  					},
   467  				},
   468  			},
   469  		},
   470  		{
   471  			name: "NotNilExtPrebid-NotNilExtBidAdj-NotNilAcct",
   472  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   473  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"banner":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)},
   474  			},
   475  			acctBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   476  				MediaType: openrtb_ext.MediaType{
   477  					VideoInstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   478  						"bidderB": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 3}}},
   479  					},
   480  					VideoOutstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   481  						"bidderC": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 3}}},
   482  					},
   483  					Audio: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   484  						"bidderD": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 3}}},
   485  					},
   486  					Native: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   487  						"bidderE": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 3}}},
   488  					},
   489  					WildCard: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   490  						"bidderF": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 3}}},
   491  					},
   492  				},
   493  			},
   494  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   495  				MediaType: openrtb_ext.MediaType{
   496  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   497  						"bidderA": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}},
   498  					},
   499  					VideoInstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   500  						"bidderB": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 3}}},
   501  					},
   502  					VideoOutstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   503  						"bidderC": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 3}}},
   504  					},
   505  					Audio: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   506  						"bidderD": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 3}}},
   507  					},
   508  					Native: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   509  						"bidderE": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 3}}},
   510  					},
   511  					WildCard: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   512  						"bidderF": {"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 3}}},
   513  					},
   514  				},
   515  			},
   516  		},
   517  	}
   518  
   519  	for _, test := range testCases {
   520  		t.Run(test.name, func(t *testing.T) {
   521  			mergedBidAdj, err := merge(test.givenRequestWrapper, test.acctBidAdjustments)
   522  			assert.NoError(t, err)
   523  			assert.Equal(t, test.expectedBidAdjustments, mergedBidAdj)
   524  		})
   525  	}
   526  }