github.com/prebid/prebid-server@v0.275.0/floors/floors_test.go (about)

     1  package floors
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"testing"
     7  
     8  	"github.com/prebid/openrtb/v19/openrtb2"
     9  	"github.com/prebid/prebid-server/config"
    10  	"github.com/prebid/prebid-server/currency"
    11  	"github.com/prebid/prebid-server/openrtb_ext"
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  func TestIsRequestEnabledWithFloor(t *testing.T) {
    16  	FalseFlag := false
    17  	TrueFlag := true
    18  
    19  	testCases := []struct {
    20  		name string
    21  		in   *openrtb_ext.ExtRequest
    22  		out  bool
    23  	}{
    24  		{
    25  			name: "Request With Nil Floors",
    26  			in:   &openrtb_ext.ExtRequest{},
    27  			out:  true,
    28  		},
    29  		{
    30  			name: "Request With Floors Disabled",
    31  			in:   &openrtb_ext.ExtRequest{Prebid: openrtb_ext.ExtRequestPrebid{Floors: &openrtb_ext.PriceFloorRules{Enabled: &FalseFlag}}},
    32  			out:  false,
    33  		},
    34  		{
    35  			name: "Request With Floors Enabled",
    36  			in:   &openrtb_ext.ExtRequest{Prebid: openrtb_ext.ExtRequestPrebid{Floors: &openrtb_ext.PriceFloorRules{Enabled: &TrueFlag}}},
    37  			out:  true,
    38  		},
    39  	}
    40  	for _, tc := range testCases {
    41  		t.Run(tc.name, func(t *testing.T) {
    42  			out := tc.in.Prebid.Floors.GetEnabled()
    43  			assert.Equal(t, out, tc.out, tc.name)
    44  		})
    45  	}
    46  }
    47  
    48  func getCurrencyRates(rates map[string]map[string]float64) currency.Conversions {
    49  	return currency.NewRates(rates)
    50  }
    51  
    52  func TestEnrichWithPriceFloors(t *testing.T) {
    53  	rates := map[string]map[string]float64{
    54  		"USD": {
    55  			"INR": 70,
    56  			"EUR": 0.9,
    57  			"JPY": 5.09,
    58  		},
    59  	}
    60  
    61  	testAccountConfig := config.Account{
    62  		PriceFloors: config.AccountPriceFloors{
    63  			Enabled:        true,
    64  			UseDynamicData: false,
    65  			MaxRule:        100,
    66  			MaxSchemaDims:  5,
    67  		},
    68  	}
    69  
    70  	width := int64(300)
    71  	height := int64(600)
    72  
    73  	testCases := []struct {
    74  		name              string
    75  		bidRequestWrapper *openrtb_ext.RequestWrapper
    76  		account           config.Account
    77  		conversions       currency.Conversions
    78  		Skipped           bool
    79  		err               string
    80  		expFloorVal       float64
    81  		expFloorCur       string
    82  		expPriceFlrLoc    string
    83  		expSchemaVersion  string
    84  	}{
    85  		{
    86  			name: "Floors disabled in account config",
    87  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
    88  				BidRequest: &openrtb2.BidRequest{
    89  					Site: &openrtb2.Site{
    90  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
    91  					},
    92  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
    93  					Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x600|www.website5.com":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
    94  				},
    95  			},
    96  			account: config.Account{
    97  				PriceFloors: config.AccountPriceFloors{
    98  					Enabled: false,
    99  				},
   100  			},
   101  			err: "Floors feature is disabled at account or in the request",
   102  		},
   103  		{
   104  			name: "Floors disabled in req.ext.prebid.floors.Enabled=false config",
   105  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   106  				BidRequest: &openrtb2.BidRequest{
   107  					Site: &openrtb2.Site{
   108  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   109  					},
   110  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   111  					Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x600|www.website.com":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":false,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   112  				},
   113  			},
   114  			account: testAccountConfig,
   115  			err:     "Floors feature is disabled at account or in the request",
   116  		},
   117  		{
   118  			name: "Floors enabled in req.ext.prebid.floors.Enabled and enabled account config",
   119  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   120  				BidRequest: &openrtb2.BidRequest{
   121  					Site: &openrtb2.Site{
   122  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   123  					},
   124  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   125  					Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 2 from req","currency":"USD","values":{"banner|300x250|www.website.com":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}},{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x250|www.website.com":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   126  				},
   127  			},
   128  			account:        testAccountConfig,
   129  			expFloorVal:    5,
   130  			expFloorCur:    "USD",
   131  			expPriceFlrLoc: openrtb_ext.RequestLocation,
   132  		},
   133  		{
   134  			name: "Skiprate = 100, Floors enabled in  req.ext.prebid.floors.Enabled and account config: Floors singalling skipped ",
   135  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   136  				BidRequest: &openrtb2.BidRequest{
   137  					Site: &openrtb2.Site{
   138  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   139  					},
   140  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   141  					Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x250|www.website.com":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"skiprate": 100,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   142  				},
   143  			},
   144  			account: testAccountConfig,
   145  			Skipped: true,
   146  		},
   147  		{
   148  			name: "Single ModelGroup, Invalid Skiprate = 110: Floors singalling skipped",
   149  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   150  				BidRequest: &openrtb2.BidRequest{
   151  					Site: &openrtb2.Site{
   152  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   153  					},
   154  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   155  					Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x250|www.website.com":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"skiprate": 110,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   156  				},
   157  			},
   158  			account:        testAccountConfig,
   159  			err:            "Invalid SkipRate = '110' at ext.prebid.floors.skiprate",
   160  			expPriceFlrLoc: openrtb_ext.RequestLocation,
   161  		},
   162  		{
   163  			name: "Multiple ModelGroups, Invalid Skiprate = 110: in one group, Floors singalling done using second ModelGroup",
   164  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   165  				BidRequest: &openrtb2.BidRequest{
   166  					Site: &openrtb2.Site{
   167  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   168  					},
   169  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   170  					Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":11,"floormincur":"USD","data":{"currency":"USD","floorsschemaversion":"2","modelgroups":[{"modelweight":50,"modelversion":"version2","schema":{"fields":["mediaType","size","domain"],"delimiter":"|"},"values":{"*|*|*":11.01,"*|*|www.website1.com":17.01},"default":21},{"modelweight":50,"modelversion":"version11","skiprate":110,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"},"values":{"*|300x250|*":11.01,"*|300x250|www.website1.com":100.01},"default":21}]},"enforcement":{"enforcepbs":true,"floordeals":true},"enabled":true}}}`),
   171  				},
   172  			},
   173  			account:          testAccountConfig,
   174  			err:              "Invalid Floor Model = 'version11' due to SkipRate = '110' is out of range (1-100)",
   175  			expFloorVal:      11.01,
   176  			expFloorCur:      "USD",
   177  			expPriceFlrLoc:   openrtb_ext.RequestLocation,
   178  			expSchemaVersion: "2",
   179  		},
   180  		{
   181  			name: "Rule selection with Site object, banner|300x600|www.website.com",
   182  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   183  				BidRequest: &openrtb2.BidRequest{
   184  					Site: &openrtb2.Site{
   185  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   186  					},
   187  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{W: &width, H: &height}}},
   188  					Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"BANNER|300x600|WWW.WEBSITE.COM":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   189  				},
   190  			},
   191  			account:        testAccountConfig,
   192  			expFloorVal:    5,
   193  			expFloorCur:    "USD",
   194  			expPriceFlrLoc: openrtb_ext.RequestLocation,
   195  		},
   196  		{
   197  			name: "Rule selection with App object, *|*|www.test.com",
   198  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   199  				BidRequest: &openrtb2.BidRequest{
   200  					App: &openrtb2.App{
   201  						Domain: "www.test.com",
   202  					},
   203  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{W: &width, H: &height}}},
   204  					Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x600|www.website.com":5,"*|*|www.test.com":15,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   205  				},
   206  			},
   207  			account:        testAccountConfig,
   208  			expFloorVal:    15,
   209  			expFloorCur:    "USD",
   210  			expPriceFlrLoc: openrtb_ext.RequestLocation,
   211  		},
   212  		{
   213  			name: "Floors Signalling not done as req.ext.prebid.floors not provided",
   214  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   215  				BidRequest: &openrtb2.BidRequest{
   216  					App: &openrtb2.App{
   217  						Domain: "www.test.com",
   218  					},
   219  					Imp: []openrtb2.Imp{{ID: "1234", BidFloor: 10, BidFloorCur: "EUR", Banner: &openrtb2.Banner{W: &width, H: &height}}},
   220  					Ext: json.RawMessage(`{"prebid":{}}`),
   221  				},
   222  			},
   223  			account:        testAccountConfig,
   224  			expFloorVal:    10,
   225  			expFloorCur:    "EUR",
   226  			expPriceFlrLoc: openrtb_ext.NoDataLocation,
   227  			err:            "Empty Floors data",
   228  		},
   229  		{
   230  			name: "BidFloor(USD) Less than MinBidFloor(INR) with different currency",
   231  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   232  				BidRequest: &openrtb2.BidRequest{
   233  					Site: &openrtb2.Site{
   234  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   235  					},
   236  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   237  					Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":80,"floormincur":"INR","data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x250|www.website.com":1,"*|*|www.test.com":15,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   238  				},
   239  			},
   240  			account:        testAccountConfig,
   241  			expFloorVal:    1.1429,
   242  			expFloorCur:    "USD",
   243  			expPriceFlrLoc: openrtb_ext.RequestLocation,
   244  		},
   245  		{
   246  			name: "BidFloor(INR) Less than MinBidFloor(USD) with different currency",
   247  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   248  				BidRequest: &openrtb2.BidRequest{
   249  					Site: &openrtb2.Site{
   250  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   251  					},
   252  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   253  					Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":1,"floormincur":"USD","data":{"currency":"INR","modelgroups":[{"modelversion":"model 1 from req","values":{"banner|300x250|www.website.com":60,"*|*|www.test.com":65,"*|*|*":67},"Default":50,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   254  				},
   255  			},
   256  			account:        testAccountConfig,
   257  			expFloorVal:    70,
   258  			expFloorCur:    "INR",
   259  			expPriceFlrLoc: openrtb_ext.RequestLocation,
   260  		},
   261  		{
   262  			name: "BidFloor is greater than MinBidFloor with same currency",
   263  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   264  				BidRequest: &openrtb2.BidRequest{
   265  					Site: &openrtb2.Site{
   266  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   267  					},
   268  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   269  					Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":1,"floormincur":"USD","data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","values":{"banner|300x250|www.website.com":2,"*|*|www.test.com":1.5,"*|*|*":1.7},"Default":5,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   270  				},
   271  			},
   272  			account:        testAccountConfig,
   273  			expFloorVal:    2,
   274  			expFloorCur:    "USD",
   275  			expPriceFlrLoc: openrtb_ext.RequestLocation,
   276  		},
   277  		{
   278  			name: "BidFloor Less than MinBidFloor with same currency",
   279  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   280  				BidRequest: &openrtb2.BidRequest{
   281  					Site: &openrtb2.Site{
   282  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   283  					},
   284  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   285  					Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":3,"floormincur":"USD","data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","values":{"banner|300x250|www.website.com":2,"*|*|www.test.com":1.5,"*|*|*":1.7},"Default":5,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   286  				},
   287  			},
   288  			account:        testAccountConfig,
   289  			expFloorVal:    3,
   290  			expFloorCur:    "USD",
   291  			expPriceFlrLoc: openrtb_ext.RequestLocation,
   292  		},
   293  		{
   294  			name: "No Rule matching, default value provided",
   295  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   296  				BidRequest: &openrtb2.BidRequest{
   297  					Site: &openrtb2.Site{
   298  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   299  					},
   300  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   301  					Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","values":{"banner|300x250|www.website.com1":2,"*|*|www.test2.com":1.5},"schema":{"fields":["mediaType","size","domain"]}, "default": 20}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   302  				},
   303  			},
   304  			account:        testAccountConfig,
   305  			expFloorVal:    20,
   306  			expFloorCur:    "USD",
   307  			expPriceFlrLoc: openrtb_ext.RequestLocation,
   308  		},
   309  		{
   310  			name: "No Rule matching, default value less than floorMin",
   311  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   312  				BidRequest: &openrtb2.BidRequest{
   313  					Site: &openrtb2.Site{
   314  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   315  					},
   316  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   317  					Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":15,"floormincur":"USD","data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","values":{"banner|300x250|www.website.com1":2,"*|*|www.test2.com":1.5},"schema":{"fields":["mediaType","size","domain"]}, "default": 5}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   318  				},
   319  			},
   320  			account:        testAccountConfig,
   321  			expFloorVal:    15,
   322  			expFloorCur:    "USD",
   323  			expPriceFlrLoc: openrtb_ext.RequestLocation,
   324  		},
   325  		{
   326  			name: "imp.bidfloor provided, No Rule matching, MinBidFloor provided",
   327  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   328  				BidRequest: &openrtb2.BidRequest{
   329  					Site: &openrtb2.Site{
   330  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   331  					},
   332  					Imp: []openrtb2.Imp{{ID: "1234", BidFloor: 100, BidFloorCur: "INR", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   333  					Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":2,"floormincur":"USD","data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","values":{"banner|300x250|www.website.com1":2,"*|*|www.test2.com":1.5},"schema":{"fields":["mediaType","size","domain"]}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   334  				},
   335  			},
   336  			account:        testAccountConfig,
   337  			expFloorVal:    100,
   338  			expFloorCur:    "INR",
   339  			expPriceFlrLoc: openrtb_ext.RequestLocation,
   340  		},
   341  		{
   342  			name:              "Empty RequestWrapper ",
   343  			bidRequestWrapper: nil,
   344  			account:           testAccountConfig,
   345  			err:               "Empty bidrequest",
   346  		},
   347  		{
   348  			name: "Invalid Floor Min Currency",
   349  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   350  				BidRequest: &openrtb2.BidRequest{
   351  					Site: &openrtb2.Site{
   352  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   353  					},
   354  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   355  					Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":80,"floormincur":"ABCD","data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x250|www.website.com":1,"*|*|www.test.com":15,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   356  				},
   357  			},
   358  			account:        testAccountConfig,
   359  			err:            "Error in getting FloorMin value : 'currency: tag is not well-formed'",
   360  			expPriceFlrLoc: openrtb_ext.RequestLocation,
   361  		},
   362  	}
   363  
   364  	for _, tc := range testCases {
   365  		t.Run(tc.name, func(t *testing.T) {
   366  
   367  			ErrList := EnrichWithPriceFloors(tc.bidRequestWrapper, tc.account, getCurrencyRates(rates))
   368  			if tc.bidRequestWrapper != nil {
   369  				assert.Equal(t, tc.bidRequestWrapper.Imp[0].BidFloor, tc.expFloorVal, tc.name)
   370  				assert.Equal(t, tc.bidRequestWrapper.Imp[0].BidFloorCur, tc.expFloorCur, tc.name)
   371  				requestExt, err := tc.bidRequestWrapper.GetRequestExt()
   372  				if err == nil {
   373  					if tc.Skipped {
   374  						assert.Equal(t, *requestExt.GetPrebid().Floors.Skipped, tc.Skipped, tc.name)
   375  					} else {
   376  						assert.Equal(t, requestExt.GetPrebid().Floors.PriceFloorLocation, tc.expPriceFlrLoc, tc.name)
   377  						if tc.expSchemaVersion != "" {
   378  							assert.Equal(t, requestExt.GetPrebid().Floors.Data.FloorsSchemaVersion, tc.expSchemaVersion, tc.name)
   379  						}
   380  					}
   381  				}
   382  			}
   383  			if len(ErrList) > 0 {
   384  				assert.Equal(t, ErrList[0].Error(), tc.err, tc.name)
   385  			}
   386  		})
   387  	}
   388  }
   389  
   390  func getTrue() *bool {
   391  	trueFlag := true
   392  	return &trueFlag
   393  }
   394  
   395  func TestResolveFloors(t *testing.T) {
   396  	rates := map[string]map[string]float64{
   397  		"USD": {
   398  			"INR": 70,
   399  			"EUR": 0.9,
   400  			"JPY": 5.09,
   401  		},
   402  	}
   403  
   404  	testCases := []struct {
   405  		name              string
   406  		bidRequestWrapper *openrtb_ext.RequestWrapper
   407  		account           config.Account
   408  		conversions       currency.Conversions
   409  		expErr            []error
   410  		expFloors         *openrtb_ext.PriceFloorRules
   411  	}{
   412  		{
   413  			name: "Dynamic fetch disabled, only enforcement object present in req.ext",
   414  			bidRequestWrapper: &openrtb_ext.RequestWrapper{
   415  				BidRequest: &openrtb2.BidRequest{
   416  					Site: &openrtb2.Site{
   417  						Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
   418  					},
   419  					Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   420  					Ext: json.RawMessage(`{"prebid":{"floors":{"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
   421  				},
   422  			},
   423  			account: config.Account{
   424  				PriceFloors: config.AccountPriceFloors{
   425  					Enabled:        true,
   426  					UseDynamicData: false,
   427  				},
   428  			},
   429  			expFloors: &openrtb_ext.PriceFloorRules{
   430  				Enforcement: &openrtb_ext.PriceFloorEnforcement{
   431  					EnforcePBS:  getTrue(),
   432  					EnforceRate: 100,
   433  					FloorDeals:  getTrue(),
   434  				},
   435  				FetchStatus:        openrtb_ext.FetchNone,
   436  				PriceFloorLocation: openrtb_ext.RequestLocation,
   437  			},
   438  		},
   439  	}
   440  
   441  	for _, tc := range testCases {
   442  		t.Run(tc.name, func(t *testing.T) {
   443  			resolvedFloors, _ := resolveFloors(tc.account, tc.bidRequestWrapper, getCurrencyRates(rates))
   444  			assert.Equal(t, resolvedFloors, tc.expFloors, tc.name)
   445  		})
   446  	}
   447  }
   448  
   449  func printFloors(floors *openrtb_ext.PriceFloorRules) string {
   450  	fbytes, _ := json.Marshal(floors)
   451  	return string(fbytes)
   452  }
   453  
   454  func TestCreateFloorsFrom(t *testing.T) {
   455  
   456  	testAccountConfig := config.Account{
   457  		PriceFloors: config.AccountPriceFloors{
   458  			Enabled:        true,
   459  			UseDynamicData: false,
   460  			MaxRule:        100,
   461  			MaxSchemaDims:  5,
   462  		},
   463  	}
   464  
   465  	type args struct {
   466  		floors        *openrtb_ext.PriceFloorRules
   467  		account       config.Account
   468  		fetchStatus   string
   469  		floorLocation string
   470  	}
   471  	testCases := []struct {
   472  		name  string
   473  		args  args
   474  		want  *openrtb_ext.PriceFloorRules
   475  		want1 []error
   476  	}{
   477  		{
   478  			name: "floor provider should be selected from floor json",
   479  			args: args{
   480  				account: testAccountConfig,
   481  				floors: &openrtb_ext.PriceFloorRules{
   482  					Enabled:     getTrue(),
   483  					FloorMin:    10.11,
   484  					FloorMinCur: "EUR",
   485  					Enforcement: &openrtb_ext.PriceFloorEnforcement{
   486  						EnforcePBS:  getTrue(),
   487  						EnforceRate: 100,
   488  						FloorDeals:  getTrue(),
   489  					},
   490  					Data: &openrtb_ext.PriceFloorData{
   491  						Currency: "USD",
   492  						ModelGroups: []openrtb_ext.PriceFloorModelGroup{
   493  							{
   494  								ModelVersion: "model from fetched",
   495  								Currency:     "USD",
   496  								Values: map[string]float64{
   497  									"banner|300x600|www.website5.com": 15,
   498  									"*|*|*":                           25,
   499  								},
   500  								Schema: openrtb_ext.PriceFloorSchema{
   501  									Fields: []string{"mediaType", "size", "domain"},
   502  								},
   503  							},
   504  						},
   505  						FloorProvider: "PM",
   506  					},
   507  				},
   508  				fetchStatus:   openrtb_ext.FetchSuccess,
   509  				floorLocation: openrtb_ext.FetchLocation,
   510  			},
   511  			want: &openrtb_ext.PriceFloorRules{
   512  				Enabled:            getTrue(),
   513  				FloorMin:           10.11,
   514  				FloorMinCur:        "EUR",
   515  				FetchStatus:        openrtb_ext.FetchSuccess,
   516  				PriceFloorLocation: openrtb_ext.FetchLocation,
   517  				Enforcement: &openrtb_ext.PriceFloorEnforcement{
   518  					EnforcePBS:  getTrue(),
   519  					EnforceRate: 100,
   520  					FloorDeals:  getTrue(),
   521  				},
   522  				Data: &openrtb_ext.PriceFloorData{
   523  					Currency: "USD",
   524  					ModelGroups: []openrtb_ext.PriceFloorModelGroup{
   525  						{
   526  							ModelVersion: "model from fetched",
   527  							Currency:     "USD",
   528  							Values: map[string]float64{
   529  								"banner|300x600|www.website5.com": 15,
   530  								"*|*|*":                           25,
   531  							},
   532  							Schema: openrtb_ext.PriceFloorSchema{
   533  								Fields: []string{"mediaType", "size", "domain"},
   534  							},
   535  						},
   536  					},
   537  					FloorProvider: "PM",
   538  				},
   539  			},
   540  		},
   541  		{
   542  			name: "floor provider will be empty if no value provided in floor json",
   543  			args: args{
   544  				account: testAccountConfig,
   545  				floors: &openrtb_ext.PriceFloorRules{
   546  					Enabled:     getTrue(),
   547  					FloorMin:    10.11,
   548  					FloorMinCur: "EUR",
   549  					Enforcement: &openrtb_ext.PriceFloorEnforcement{
   550  						EnforcePBS:  getTrue(),
   551  						EnforceRate: 100,
   552  						FloorDeals:  getTrue(),
   553  					},
   554  					Data: &openrtb_ext.PriceFloorData{
   555  						Currency: "USD",
   556  						ModelGroups: []openrtb_ext.PriceFloorModelGroup{
   557  							{
   558  								ModelVersion: "model from request",
   559  								Currency:     "USD",
   560  								Values: map[string]float64{
   561  									"banner|300x600|www.website5.com": 15,
   562  									"*|*|*":                           25,
   563  								},
   564  								Schema: openrtb_ext.PriceFloorSchema{
   565  									Fields: []string{"mediaType", "size", "domain"},
   566  								},
   567  							},
   568  						},
   569  						FloorProvider: "",
   570  					},
   571  				},
   572  				fetchStatus:   openrtb_ext.FetchSuccess,
   573  				floorLocation: openrtb_ext.FetchLocation,
   574  			},
   575  			want: &openrtb_ext.PriceFloorRules{
   576  				Enabled:            getTrue(),
   577  				FloorMin:           10.11,
   578  				FloorMinCur:        "EUR",
   579  				FetchStatus:        openrtb_ext.FetchSuccess,
   580  				PriceFloorLocation: openrtb_ext.FetchLocation,
   581  				Enforcement: &openrtb_ext.PriceFloorEnforcement{
   582  					EnforcePBS:  getTrue(),
   583  					EnforceRate: 100,
   584  					FloorDeals:  getTrue(),
   585  				},
   586  				Data: &openrtb_ext.PriceFloorData{
   587  					Currency: "USD",
   588  					ModelGroups: []openrtb_ext.PriceFloorModelGroup{
   589  						{
   590  							ModelVersion: "model from request",
   591  							Currency:     "USD",
   592  							Values: map[string]float64{
   593  								"banner|300x600|www.website5.com": 15,
   594  								"*|*|*":                           25,
   595  							},
   596  							Schema: openrtb_ext.PriceFloorSchema{
   597  								Fields: []string{"mediaType", "size", "domain"},
   598  							},
   599  						},
   600  					},
   601  					FloorProvider: "",
   602  				},
   603  			},
   604  		},
   605  		{
   606  			name: "only floor enforcement object present",
   607  			args: args{
   608  				account: testAccountConfig,
   609  				floors: &openrtb_ext.PriceFloorRules{
   610  					Enabled: getTrue(),
   611  					Enforcement: &openrtb_ext.PriceFloorEnforcement{
   612  						EnforcePBS:  getTrue(),
   613  						EnforceRate: 100,
   614  						FloorDeals:  getTrue(),
   615  					},
   616  				},
   617  				fetchStatus:   openrtb_ext.FetchNone,
   618  				floorLocation: openrtb_ext.RequestLocation,
   619  			},
   620  			want: &openrtb_ext.PriceFloorRules{
   621  				FetchStatus:        openrtb_ext.FetchNone,
   622  				PriceFloorLocation: openrtb_ext.RequestLocation,
   623  				Enforcement: &openrtb_ext.PriceFloorEnforcement{
   624  					EnforcePBS:  getTrue(),
   625  					EnforceRate: 100,
   626  					FloorDeals:  getTrue(),
   627  				},
   628  			},
   629  		},
   630  		{
   631  			name: "Invalid modelGroup with skipRate = 110",
   632  			args: args{
   633  				account: testAccountConfig,
   634  				floors: &openrtb_ext.PriceFloorRules{
   635  					Enabled: getTrue(),
   636  					Data: &openrtb_ext.PriceFloorData{
   637  						Currency: "USD",
   638  						ModelGroups: []openrtb_ext.PriceFloorModelGroup{
   639  							{
   640  								ModelVersion: "model from fetched",
   641  								Currency:     "USD",
   642  								SkipRate:     110,
   643  								Values: map[string]float64{
   644  									"banner|300x600|www.website5.com": 15,
   645  									"*|*|*":                           25,
   646  								},
   647  								Schema: openrtb_ext.PriceFloorSchema{
   648  									Fields: []string{"mediaType", "size", "domain"},
   649  								},
   650  							},
   651  						},
   652  					},
   653  				},
   654  				fetchStatus:   openrtb_ext.FetchNone,
   655  				floorLocation: openrtb_ext.RequestLocation,
   656  			},
   657  			want: &openrtb_ext.PriceFloorRules{
   658  				FetchStatus:        openrtb_ext.FetchNone,
   659  				PriceFloorLocation: openrtb_ext.RequestLocation,
   660  			},
   661  			want1: []error{
   662  				errors.New("Invalid Floor Model = 'model from fetched' due to SkipRate = '110' is out of range (1-100)"),
   663  			},
   664  		},
   665  	}
   666  	for _, tc := range testCases {
   667  		t.Run(tc.name, func(t *testing.T) {
   668  			got, got1 := createFloorsFrom(tc.args.floors, tc.args.account, tc.args.fetchStatus, tc.args.floorLocation)
   669  			assert.Equal(t, got1, tc.want1, tc.name)
   670  			assert.Equal(t, got, tc.want, tc.name)
   671  		})
   672  	}
   673  }
   674  
   675  func TestIsPriceFloorsEnabled(t *testing.T) {
   676  	type args struct {
   677  		account           config.Account
   678  		bidRequestWrapper *openrtb_ext.RequestWrapper
   679  	}
   680  	tests := []struct {
   681  		name string
   682  		args args
   683  		want bool
   684  	}{
   685  		{
   686  			name: "Disabled in account and req",
   687  			args: args{
   688  				account: config.Account{PriceFloors: config.AccountPriceFloors{Enabled: false}},
   689  				bidRequestWrapper: &openrtb_ext.RequestWrapper{
   690  					BidRequest: &openrtb2.BidRequest{
   691  						Ext: json.RawMessage(`{"prebid":{"floors":{"enabled": false} }}`),
   692  					},
   693  				},
   694  			},
   695  			want: false,
   696  		},
   697  		{
   698  			name: "Enabled  in account and req",
   699  			args: args{
   700  				account: config.Account{PriceFloors: config.AccountPriceFloors{Enabled: true}},
   701  				bidRequestWrapper: &openrtb_ext.RequestWrapper{
   702  					BidRequest: &openrtb2.BidRequest{
   703  						Ext: json.RawMessage(`{"prebid":{"floors":{"enabled": true} }}`),
   704  					},
   705  				},
   706  			},
   707  			want: true,
   708  		},
   709  		{
   710  			name: "disabled  in account and enabled req",
   711  			args: args{
   712  				account: config.Account{PriceFloors: config.AccountPriceFloors{Enabled: false}},
   713  				bidRequestWrapper: &openrtb_ext.RequestWrapper{
   714  					BidRequest: &openrtb2.BidRequest{
   715  						Ext: json.RawMessage(`{"prebid":{"floors":{"enabled": true} }}`),
   716  					},
   717  				},
   718  			},
   719  			want: false,
   720  		},
   721  		{
   722  			name: "Enabled  in account and disabled in req",
   723  			args: args{
   724  				account: config.Account{PriceFloors: config.AccountPriceFloors{Enabled: true}},
   725  				bidRequestWrapper: &openrtb_ext.RequestWrapper{
   726  					BidRequest: &openrtb2.BidRequest{
   727  						Ext: json.RawMessage(`{"prebid":{"floors":{"enabled": false} }}`)},
   728  				},
   729  			},
   730  			want: false,
   731  		},
   732  	}
   733  	for _, tt := range tests {
   734  		t.Run(tt.name, func(t *testing.T) {
   735  			got := isPriceFloorsEnabled(tt.args.account, tt.args.bidRequestWrapper)
   736  			assert.Equal(t, got, tt.want, tt.name)
   737  		})
   738  	}
   739  }