github.com/prebid/prebid-server@v0.275.0/bidadjustment/build_rules_test.go (about)

     1  package bidadjustment
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/prebid/openrtb/v19/openrtb2"
     7  	"github.com/prebid/prebid-server/config"
     8  	"github.com/prebid/prebid-server/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  		givenAccount           *config.Account
   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  			givenAccount: &config.Account{
   232  				BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   233  					MediaType: openrtb_ext.MediaType{
   234  						Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   235  							"bidderB": {
   236  								"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   237  							},
   238  						},
   239  					},
   240  				},
   241  			},
   242  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   243  				MediaType: openrtb_ext.MediaType{
   244  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   245  						"bidderA": {
   246  							"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}},
   247  						},
   248  						"bidderB": {
   249  							"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   250  						},
   251  					},
   252  				},
   253  			},
   254  		},
   255  		{
   256  			name: "RequestTakesPrecedence",
   257  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   258  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"audio":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)},
   259  			},
   260  			givenAccount: &config.Account{
   261  				BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   262  					MediaType: openrtb_ext.MediaType{
   263  						Audio: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   264  							"bidderA": {
   265  								"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   266  							},
   267  						},
   268  					},
   269  				},
   270  			},
   271  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   272  				MediaType: openrtb_ext.MediaType{
   273  					Audio: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   274  						"bidderA": {
   275  							"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}},
   276  						},
   277  					},
   278  				},
   279  			},
   280  		},
   281  		{
   282  			name: "DiffDealIds",
   283  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   284  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"video-instream":{"bidderA":{"dealId":[{ "adjtype": "static", "value": 3.00, "currency": "USD"}]}}}}}}`)},
   285  			},
   286  			givenAccount: &config.Account{
   287  				BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   288  					MediaType: openrtb_ext.MediaType{
   289  						VideoInstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   290  							"bidderA": {
   291  								"diffDealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   292  							},
   293  						},
   294  					},
   295  				},
   296  			},
   297  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   298  				MediaType: openrtb_ext.MediaType{
   299  					VideoInstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   300  						"bidderA": {
   301  							"dealId":     []openrtb_ext.Adjustment{{Type: AdjustmentTypeStatic, Value: 3.00, Currency: "USD"}},
   302  							"diffDealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   303  						},
   304  					},
   305  				},
   306  			},
   307  		},
   308  		{
   309  			name: "DiffBidderNamesCpm",
   310  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   311  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"native":{"bidderA":{"dealId":[{"adjtype": "cpm", "value": 0.18, "currency": "USD"}]}}}}}}`)},
   312  			},
   313  			givenAccount: &config.Account{
   314  				BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   315  					MediaType: openrtb_ext.MediaType{
   316  						Native: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   317  							"bidderB": {
   318  								"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   319  							},
   320  						},
   321  					},
   322  				},
   323  			},
   324  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   325  				MediaType: openrtb_ext.MediaType{
   326  					Native: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   327  						"bidderA": {
   328  							"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 0.18, Currency: "USD"}},
   329  						},
   330  						"bidderB": {
   331  							"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   332  						},
   333  					},
   334  				},
   335  			},
   336  		},
   337  		{
   338  			name: "ReqAdjVideoAcctAdjBanner",
   339  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   340  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"video-outstream":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)},
   341  			},
   342  			givenAccount: &config.Account{
   343  				BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   344  					MediaType: openrtb_ext.MediaType{
   345  						Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   346  							"bidderB": {
   347  								"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   348  							},
   349  						},
   350  					},
   351  				},
   352  			},
   353  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   354  				MediaType: openrtb_ext.MediaType{
   355  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   356  						"bidderB": {
   357  							"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   358  						},
   359  					},
   360  					VideoOutstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   361  						"bidderA": {
   362  							"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}},
   363  						},
   364  					},
   365  				},
   366  			},
   367  		},
   368  		{
   369  			name: "RequestNilPrebid",
   370  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   371  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"ext":{"bidder": {}}}`)},
   372  			},
   373  			givenAccount: &config.Account{
   374  				BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   375  					MediaType: openrtb_ext.MediaType{
   376  						Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   377  							"bidderB": {
   378  								"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   379  							},
   380  						},
   381  					},
   382  				},
   383  			},
   384  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   385  				MediaType: openrtb_ext.MediaType{
   386  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   387  						"bidderB": {
   388  							"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   389  						},
   390  					},
   391  				},
   392  			},
   393  		},
   394  		{
   395  			name: "AcctWildCardRequestVideo",
   396  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   397  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"video-instream":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)},
   398  			},
   399  			givenAccount: &config.Account{
   400  				BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   401  					MediaType: openrtb_ext.MediaType{
   402  						WildCard: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   403  							"bidderB": {
   404  								"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   405  							},
   406  						},
   407  					},
   408  				},
   409  			},
   410  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   411  				MediaType: openrtb_ext.MediaType{
   412  					WildCard: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   413  						"bidderB": {
   414  							"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}},
   415  						},
   416  					},
   417  					VideoInstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   418  						"bidderA": {
   419  							"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}},
   420  						},
   421  					},
   422  				},
   423  			},
   424  		},
   425  		{
   426  			name: "NilReqExtPrebidAndAcctBidAdj",
   427  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   428  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"ext":{"bidder": {}}}`)},
   429  			},
   430  			givenAccount:           &config.Account{},
   431  			expectedBidAdjustments: nil,
   432  		},
   433  		{
   434  			name: "NilAcctBidAdj",
   435  			givenRequestWrapper: &openrtb_ext.RequestWrapper{
   436  				BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"banner":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)},
   437  			},
   438  			givenAccount: &config.Account{},
   439  			expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{
   440  				MediaType: openrtb_ext.MediaType{
   441  					Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{
   442  						"bidderA": {
   443  							"dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}},
   444  						},
   445  					},
   446  				},
   447  			},
   448  		},
   449  	}
   450  
   451  	for _, test := range testCases {
   452  		t.Run(test.name, func(t *testing.T) {
   453  			mergedBidAdj, err := merge(test.givenRequestWrapper, test.givenAccount.BidAdjustments)
   454  			assert.NoError(t, err)
   455  			assert.Equal(t, test.expectedBidAdjustments, mergedBidAdj)
   456  		})
   457  	}
   458  }