github.com/prebid/prebid-server/v2@v2.18.0/floors/rule_test.go (about)

     1  package floors
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"testing"
     7  
     8  	"github.com/prebid/openrtb/v20/openrtb2"
     9  	"github.com/prebid/prebid-server/v2/currency"
    10  	"github.com/prebid/prebid-server/v2/openrtb_ext"
    11  	"github.com/prebid/prebid-server/v2/util/ptrutil"
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  func TestPrepareRuleCombinations(t *testing.T) {
    16  	testCases := []struct {
    17  		name string
    18  		in   []string
    19  		del  string
    20  		exp  []string
    21  	}{
    22  		{
    23  			name: "Schema items, n = 1",
    24  			in:   []string{"A"},
    25  			del:  "|",
    26  			exp: []string{
    27  				"a",
    28  				"*",
    29  			},
    30  		},
    31  		{
    32  			name: "Schema items, n = 2",
    33  			in:   []string{"A", "B"},
    34  			del:  "|",
    35  			exp: []string{
    36  				"a|b",
    37  				"a|*",
    38  				"*|b",
    39  				"*|*",
    40  			},
    41  		},
    42  		{
    43  			name: "Schema items, n = 3",
    44  			in:   []string{"A", "B", "C"},
    45  			del:  "|",
    46  			exp: []string{
    47  				"a|b|c",
    48  				"a|b|*",
    49  				"a|*|c",
    50  				"*|b|c",
    51  				"a|*|*",
    52  				"*|b|*",
    53  				"*|*|c",
    54  				"*|*|*",
    55  			},
    56  		},
    57  		{
    58  			name: "Schema items, n = 4",
    59  			in:   []string{"A", "B", "C", "D"},
    60  			del:  "|",
    61  			exp: []string{
    62  				"a|b|c|d",
    63  				"a|b|c|*",
    64  				"a|b|*|d",
    65  				"a|*|c|d",
    66  				"*|b|c|d",
    67  				"a|b|*|*",
    68  				"a|*|c|*",
    69  				"a|*|*|d",
    70  				"*|b|c|*",
    71  				"*|b|*|d",
    72  				"*|*|c|d",
    73  				"a|*|*|*",
    74  				"*|b|*|*",
    75  				"*|*|c|*",
    76  				"*|*|*|d",
    77  				"*|*|*|*",
    78  			},
    79  		},
    80  		{
    81  			name: "Schema items, n = 1 with wildcards",
    82  			in:   []string{"*"},
    83  			del:  "|",
    84  			exp: []string{
    85  				"*",
    86  			},
    87  		},
    88  		{
    89  			name: "Schema items, n = 2 with wildcard at index = 0",
    90  			in:   []string{"*", "B"},
    91  			del:  "|",
    92  			exp: []string{
    93  				"*|b",
    94  				"*|*",
    95  			},
    96  		},
    97  		{
    98  			name: "Schema items, n = 2 with wildcards at index = 1",
    99  			in:   []string{"A", "*"},
   100  			del:  "|",
   101  			exp: []string{
   102  				"a|*",
   103  				"*|*",
   104  			},
   105  		},
   106  
   107  		{
   108  			name: "Schema items, n = 2 wildcards at index = 0,1",
   109  			in:   []string{"*", "*"},
   110  			del:  "|",
   111  			exp: []string{
   112  				"*|*",
   113  			},
   114  		},
   115  
   116  		{
   117  			name: "Schema items, n = 3 wildcard at index = 0",
   118  			in:   []string{"*", "B", "C"},
   119  			del:  "|",
   120  			exp: []string{
   121  				"*|b|c",
   122  				"*|b|*",
   123  				"*|*|c",
   124  				"*|*|*",
   125  			},
   126  		},
   127  		{
   128  			name: "Schema items, n = 3 wildcard at index = 1",
   129  			in:   []string{"A", "*", "C"},
   130  			del:  "|",
   131  			exp: []string{
   132  				"a|*|c",
   133  				"a|*|*",
   134  				"*|*|c",
   135  				"*|*|*",
   136  			},
   137  		},
   138  		{
   139  			name: "Schema items, n = 3 with wildcard at index = 2",
   140  			in:   []string{"A", "B", "*"},
   141  			del:  "|",
   142  			exp: []string{
   143  				"a|b|*",
   144  				"a|*|*",
   145  				"*|b|*",
   146  				"*|*|*",
   147  			},
   148  		},
   149  		{
   150  			name: "Schema items, n = 3 with wildcard at index = 0,2",
   151  			in:   []string{"*", "B", "*"},
   152  			del:  "|",
   153  			exp: []string{
   154  				"*|b|*",
   155  				"*|*|*",
   156  			},
   157  		},
   158  		{
   159  			name: "Schema items, n = 3 with wildcard at index = 0,1",
   160  			in:   []string{"*", "*", "C"},
   161  			del:  "|",
   162  			exp: []string{
   163  				"*|*|c",
   164  				"*|*|*",
   165  			},
   166  		},
   167  		{
   168  			name: "Schema items, n = 3 with wildcard at index = 1,2",
   169  			in:   []string{"A", "*", "*"},
   170  			del:  "|",
   171  			exp: []string{
   172  				"a|*|*",
   173  				"*|*|*",
   174  			},
   175  		},
   176  	}
   177  	for _, tc := range testCases {
   178  		t.Run(tc.name, func(t *testing.T) {
   179  			act := prepareRuleCombinations(tc.in, tc.del)
   180  			assert.Equal(t, tc.exp, act, tc.name)
   181  		})
   182  	}
   183  }
   184  
   185  func TestUpdateImpExtWithFloorDetails(t *testing.T) {
   186  	testCases := []struct {
   187  		name         string
   188  		matchedRule  string
   189  		floorRuleVal float64
   190  		floorVal     float64
   191  		imp          *openrtb_ext.ImpWrapper
   192  		expected     json.RawMessage
   193  	}{
   194  		{
   195  			name:         "Nil ImpExt",
   196  			matchedRule:  "test|123|xyz",
   197  			floorRuleVal: 5.5,
   198  			floorVal:     5.5,
   199  			imp:          &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{ID: "1234", Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](300), H: ptrutil.ToPtr[int64](250)}}},
   200  			expected:     []byte(`{"prebid":{"floors":{"floorrule":"test|123|xyz","floorrulevalue":5.5,"floorvalue":5.5}}}`),
   201  		},
   202  		{
   203  			name:         "Empty ImpExt",
   204  			matchedRule:  "test|123|xyz",
   205  			floorRuleVal: 5.5,
   206  			floorVal:     5.5,
   207  			imp:          &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{ID: "1234", Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](300), H: ptrutil.ToPtr[int64](250)}, Ext: json.RawMessage{}}},
   208  			expected:     []byte(`{"prebid":{"floors":{"floorrule":"test|123|xyz","floorrulevalue":5.5,"floorvalue":5.5}}}`),
   209  		},
   210  		{
   211  			name:         "With prebid Ext",
   212  			matchedRule:  "banner|www.test.com|*",
   213  			floorRuleVal: 5.5,
   214  			floorVal:     15.5,
   215  			imp:          &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{ID: "1234", Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](300), H: ptrutil.ToPtr[int64](250)}, Ext: []byte(`{"prebid": {"test": true}}`)}},
   216  			expected:     []byte(`{"prebid":{"floors":{"floorrule":"banner|www.test.com|*","floorrulevalue":5.5,"floorvalue":15.5}}}`),
   217  		},
   218  	}
   219  	for _, tc := range testCases {
   220  		t.Run(tc.name, func(t *testing.T) {
   221  			updateImpExtWithFloorDetails(tc.imp, tc.matchedRule, tc.floorRuleVal, tc.floorVal)
   222  			_ = tc.imp.RebuildImp()
   223  			if tc.imp.Ext != nil {
   224  				assert.Equal(t, tc.imp.Ext, tc.expected, tc.name)
   225  			}
   226  		})
   227  	}
   228  }
   229  
   230  func TestCreateRuleKeys(t *testing.T) {
   231  	testCases := []struct {
   232  		name        string
   233  		floorSchema openrtb_ext.PriceFloorSchema
   234  		request     *openrtb2.BidRequest
   235  		out         []string
   236  	}{
   237  		{
   238  			name: "CreateRule with banner mediatype, size and domain",
   239  			request: &openrtb2.BidRequest{
   240  				Site: &openrtb2.Site{
   241  					Domain: "www.test.com",
   242  				},
   243  				Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
   244  				Ext: json.RawMessage(`{"prebid": { "floors": {"data": {"currency": "USD","skipRate": 0,"schema": {"fields": [ "mediaType", "size", "domain" ] },"values": {  "banner|300x250|www.website.com": 1.01, "banner|300x250|*": 2.01, "banner|300x600|www.website.com": 3.01,  "banner|300x600|*": 4.01, "banner|728x90|www.website.com": 5.01, "banner|728x90|*": 6.01, "banner|*|www.website.com": 7.01, "banner|*|*": 8.01, "*|300x250|www.website.com": 9.01, "*|300x250|*": 10.01, "*|300x600|www.website.com": 11.01,  "*|300x600|*": 12.01,  "*|728x90|www.website.com": 13.01, "*|728x90|*": 14.01,  "*|*|www.website.com": 15.01, "*|*|*": 16.01  }, "default": 1}}}}`),
   245  			},
   246  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "size", "domain"}},
   247  			out:         []string{"banner", "300x250", "www.test.com"},
   248  		},
   249  		{
   250  			name: "CreateRule with video mediatype, size and domain",
   251  			request: &openrtb2.BidRequest{
   252  				Site: &openrtb2.Site{
   253  					Domain: "www.test.com",
   254  				},
   255  				Imp: []openrtb2.Imp{{ID: "1234", Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](640), H: ptrutil.ToPtr[int64](480), Placement: 1}}},
   256  			},
   257  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "size", "domain"}},
   258  			out:         []string{"video", "640x480", "www.test.com"},
   259  		},
   260  		{
   261  			name: "CreateRule with video mediatype, size and domain",
   262  			request: &openrtb2.BidRequest{
   263  				Site: &openrtb2.Site{
   264  					Domain: "www.test.com",
   265  				},
   266  				Imp: []openrtb2.Imp{{ID: "1234", Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](300), H: ptrutil.ToPtr[int64](250), Placement: 2}}},
   267  			},
   268  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "size", "domain"}},
   269  			out:         []string{"video-outstream", "300x250", "www.test.com"},
   270  		},
   271  		{
   272  			name: "CreateRule with audio mediatype, adUnitCode and domain",
   273  			request: &openrtb2.BidRequest{
   274  				Site: &openrtb2.Site{
   275  					Domain: "www.test.com",
   276  				},
   277  				Imp: []openrtb2.Imp{{ID: "1234", TagID: "tag123", Audio: &openrtb2.Audio{MaxDuration: 300}}},
   278  			},
   279  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "adUnitCode", "siteDomain"}},
   280  			out:         []string{"audio", "tag123", "www.test.com"},
   281  		},
   282  		{
   283  			name: "CreateRule with audio mediatype, adUnitCode=* and domain",
   284  			request: &openrtb2.BidRequest{
   285  				Site: &openrtb2.Site{
   286  					Domain: "www.test.com",
   287  				},
   288  				Imp: []openrtb2.Imp{{ID: "1234", Audio: &openrtb2.Audio{MaxDuration: 300}}},
   289  			},
   290  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "adUnitCode", "siteDomain"}},
   291  			out:         []string{"audio", "*", "www.test.com"},
   292  		},
   293  		{
   294  			name: "CreateRule with native mediatype, bundle and domain",
   295  			request: &openrtb2.BidRequest{
   296  				App: &openrtb2.App{
   297  					Domain: "www.test.com",
   298  					Bundle: "bundle123",
   299  				},
   300  				Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}}},
   301  			},
   302  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "bundle", "siteDomain"}},
   303  			out:         []string{"native", "bundle123", "www.test.com"},
   304  		},
   305  		{
   306  			name: "CreateRule with native, banner mediatype, bundle and domain",
   307  			request: &openrtb2.BidRequest{
   308  				App: &openrtb2.App{
   309  					Domain: "www.test.com",
   310  					Bundle: "bundle123",
   311  				},
   312  				Imp: []openrtb2.Imp{{ID: "1234", Audio: &openrtb2.Audio{MaxDuration: 300}, Native: &openrtb2.Native{Request: "Test"}}},
   313  			},
   314  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "bundle", "siteDomain"}},
   315  			out:         []string{"*", "bundle123", "www.test.com"},
   316  		},
   317  		{
   318  			name: "CreateRule with channel, country, deviceType",
   319  			request: &openrtb2.BidRequest{
   320  				App: &openrtb2.App{
   321  					Publisher: &openrtb2.Publisher{
   322  						Domain: "www.test.com",
   323  					},
   324  					Bundle: "bundle123",
   325  				},
   326  				Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}, UA: "tablet"},
   327  				Imp:    []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}}},
   328  				Ext:    json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`),
   329  			},
   330  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"channel", "country", "deviceType"}},
   331  			out:         []string{"chName", "USA", "tablet"},
   332  		},
   333  		{
   334  			name: "CreateRule with channel, country, deviceType=tablet",
   335  			request: &openrtb2.BidRequest{
   336  				App: &openrtb2.App{
   337  					Publisher: &openrtb2.Publisher{
   338  						Domain: "www.test.com",
   339  					},
   340  					Bundle: "bundle123",
   341  				},
   342  				Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}, UA: "Windows NT touch"},
   343  				Imp:    []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}}},
   344  				Ext:    json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`),
   345  			},
   346  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"channel", "country", "deviceType"}},
   347  			out:         []string{"chName", "USA", "tablet"},
   348  		},
   349  		{
   350  			name: "CreateRule with channel, country, deviceType=desktop",
   351  			request: &openrtb2.BidRequest{
   352  				App: &openrtb2.App{
   353  					Publisher: &openrtb2.Publisher{
   354  						Domain: "www.test.com",
   355  					},
   356  					Bundle: "bundle123",
   357  				},
   358  				Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}, UA: "Windows NT"},
   359  				Imp:    []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}}},
   360  				Ext:    json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`),
   361  			},
   362  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"channel", "country", "deviceType"}},
   363  			out:         []string{"chName", "USA", "desktop"},
   364  		},
   365  		{
   366  			name: "CreateRule with channel, country, deviceType=desktop",
   367  			request: &openrtb2.BidRequest{
   368  				App: &openrtb2.App{
   369  					Publisher: &openrtb2.Publisher{
   370  						Domain: "www.test.com",
   371  					},
   372  					Bundle: "bundle123",
   373  				},
   374  				Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}, UA: "Windows NT"},
   375  				Imp:    []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}}},
   376  				Ext:    json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`),
   377  			},
   378  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"channel", "country", "deviceType"}},
   379  			out:         []string{"chName", "USA", "desktop"},
   380  		},
   381  		{
   382  			name: "CreateRule with channel, size, deviceType=desktop",
   383  			request: &openrtb2.BidRequest{
   384  				App: &openrtb2.App{
   385  					Publisher: &openrtb2.Publisher{
   386  						Domain: "www.test.com",
   387  					},
   388  					Bundle: "bundle123",
   389  				},
   390  				Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}, UA: "SomeDevice"},
   391  				Imp:    []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 100, H: 200}, {W: 200, H: 300}}}}},
   392  				Ext:    json.RawMessage(`{"prebid": {"test": "1}}`),
   393  			},
   394  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"channel", "size", "deviceType"}},
   395  			out:         []string{"*", "*", "desktop"},
   396  		},
   397  		{
   398  			name: "CreateRule with pubDomain, country, deviceType",
   399  			request: &openrtb2.BidRequest{
   400  				App: &openrtb2.App{
   401  					Publisher: &openrtb2.Publisher{
   402  						Domain: "www.test.com",
   403  					},
   404  					Bundle: "bundle123",
   405  				},
   406  				Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}, UA: "Phone"},
   407  				Imp:    []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}}},
   408  				Ext:    json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`),
   409  			},
   410  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"pubDomain", "country", "deviceType"}},
   411  			out:         []string{"www.test.com", "USA", "phone"},
   412  		},
   413  		{
   414  			name: "CreateRule with pubDomain, gptSlot, deviceType",
   415  			request: &openrtb2.BidRequest{
   416  				Site: &openrtb2.Site{
   417  					Publisher: &openrtb2.Publisher{
   418  						Domain: "www.test.com",
   419  					},
   420  				},
   421  				Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}},
   422  				Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"},
   423  					Ext: json.RawMessage(`{"data": {"adserver": {"name": "gam","adslot": "adslot123"}, "pbadslot": "pbadslot123"}}`),
   424  				}},
   425  				Ext: json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`),
   426  			},
   427  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"pubDomain", "gptSlot", "deviceType"}},
   428  			out:         []string{"www.test.com", "adslot123", "*"},
   429  		},
   430  		{
   431  			name: "CreateRule with pubDomain, gptSlot, deviceType",
   432  			request: &openrtb2.BidRequest{
   433  				Site: &openrtb2.Site{
   434  					Publisher: &openrtb2.Publisher{
   435  						Domain: "www.test.com",
   436  					},
   437  				},
   438  				Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}},
   439  				Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"},
   440  					Ext: json.RawMessage(`{"data": {"adserver": {"name": "test","adslot": "adslot123"}, "pbadslot": "pbadslot123"}}`),
   441  				}},
   442  				Ext: json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`),
   443  			},
   444  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"pubDomain", "gptSlot", "deviceType"}},
   445  			out:         []string{"www.test.com", "pbadslot123", "*"},
   446  		},
   447  		{
   448  			name: "CreateRule with domain, adUnitCode, channel",
   449  			request: &openrtb2.BidRequest{
   450  				App: &openrtb2.App{
   451  					Publisher: &openrtb2.Publisher{
   452  						Domain: "www.test.com",
   453  					},
   454  				},
   455  				Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}},
   456  				Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"},
   457  					Ext: json.RawMessage(`{"data": {"adserver": {"name": "test","adslot": "adslot123"}, "pbadslot": "pbadslot123"}}`),
   458  				}},
   459  			},
   460  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"domain", "adUnitCode", "channel"}},
   461  			out:         []string{"www.test.com", "pbadslot123", "*"},
   462  		},
   463  		{
   464  			name: "CreateRule with domain, adUnitCode, channel",
   465  			request: &openrtb2.BidRequest{
   466  				App: &openrtb2.App{
   467  					Publisher: &openrtb2.Publisher{
   468  						Domain: "www.test.com",
   469  					},
   470  				},
   471  				Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}},
   472  				Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"},
   473  					Ext: json.RawMessage(`{"gpid":  "gpid_134"}`),
   474  				}},
   475  			},
   476  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"domain", "adUnitCode", "channel"}},
   477  			out:         []string{"www.test.com", "gpid_134", "*"},
   478  		},
   479  		{
   480  			name: "CreateRule with domain, adUnitCode, channel",
   481  			request: &openrtb2.BidRequest{
   482  				App: &openrtb2.App{
   483  					Publisher: &openrtb2.Publisher{
   484  						Domain: "www.test.com",
   485  					},
   486  				},
   487  				Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}},
   488  				Imp:    []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{}, Ext: json.RawMessage(`{"prebid": {"storedrequest": {"id": "storedid_123"}}}`)}},
   489  			},
   490  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"domain", "adUnitCode", "channel"}},
   491  			out:         []string{"www.test.com", "storedid_123", "*"},
   492  		},
   493  		{
   494  			name: "CreateRule with domain, adUnitCode, channel",
   495  			request: &openrtb2.BidRequest{
   496  				App: &openrtb2.App{
   497  					Publisher: &openrtb2.Publisher{
   498  						Domain: "www.test.com",
   499  					},
   500  				},
   501  				Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}},
   502  				Imp:    []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{}, Ext: json.RawMessage(`{"prebid": {"storedrequest": {"id": "storedid_123"}}}`)}},
   503  			},
   504  			floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"domain", "adUnitCode", "channel"}},
   505  			out:         []string{"www.test.com", "storedid_123", "*"},
   506  		},
   507  	}
   508  	for _, tc := range testCases {
   509  		t.Run(tc.name, func(t *testing.T) {
   510  			out := createRuleKey(tc.floorSchema, &openrtb_ext.RequestWrapper{BidRequest: tc.request}, &openrtb_ext.ImpWrapper{Imp: &tc.request.Imp[0]})
   511  			assert.Equal(t, out, tc.out, tc.name)
   512  		})
   513  	}
   514  }
   515  
   516  func TestShouldSkipFloors(t *testing.T) {
   517  
   518  	testCases := []struct {
   519  		name                string
   520  		ModelGroupsSkipRate int
   521  		DataSkipRate        int
   522  		RootSkipRate        int
   523  		out                 bool
   524  		randomGen           func(int) int
   525  	}{
   526  		{
   527  			name:                "ModelGroupsSkipRate=10 with skip = true",
   528  			ModelGroupsSkipRate: 10,
   529  			DataSkipRate:        0,
   530  			RootSkipRate:        0,
   531  			randomGen:           func(i int) int { return 5 },
   532  			out:                 true,
   533  		},
   534  		{
   535  			name:                "ModelGroupsSkipRate=100 with skip = true",
   536  			ModelGroupsSkipRate: 100,
   537  			DataSkipRate:        0,
   538  			RootSkipRate:        0,
   539  			randomGen:           func(i int) int { return 5 },
   540  			out:                 true,
   541  		},
   542  		{
   543  			name:                "ModelGroupsSkipRate=0 with skip = false",
   544  			ModelGroupsSkipRate: 0,
   545  			DataSkipRate:        0,
   546  			RootSkipRate:        0,
   547  			randomGen:           func(i int) int { return 0 },
   548  			out:                 false,
   549  		},
   550  		{
   551  			name:                "DataSkipRate=50  with with skip = true",
   552  			ModelGroupsSkipRate: 0,
   553  			DataSkipRate:        50,
   554  			RootSkipRate:        0,
   555  			randomGen:           func(i int) int { return 40 },
   556  			out:                 true,
   557  		},
   558  		{
   559  			name:                "RootSkipRate=50  with with skip = true",
   560  			ModelGroupsSkipRate: 0,
   561  			DataSkipRate:        0,
   562  			RootSkipRate:        60,
   563  			randomGen:           func(i int) int { return 40 },
   564  			out:                 true,
   565  		},
   566  		{
   567  			name:                "RootSkipRate=50  with with skip = false",
   568  			ModelGroupsSkipRate: 0,
   569  			DataSkipRate:        0,
   570  			RootSkipRate:        60,
   571  			randomGen:           func(i int) int { return 70 },
   572  			out:                 false,
   573  		},
   574  		{
   575  			name:                "RootSkipRate=100  with with skip = true",
   576  			ModelGroupsSkipRate: 0,
   577  			DataSkipRate:        0,
   578  			RootSkipRate:        100,
   579  			randomGen:           func(i int) int { return 100 },
   580  			out:                 true,
   581  		},
   582  	}
   583  	for _, tc := range testCases {
   584  		t.Run(tc.name, func(t *testing.T) {
   585  			out := shouldSkipFloors(tc.ModelGroupsSkipRate, tc.DataSkipRate, tc.RootSkipRate, tc.randomGen)
   586  			assert.Equal(t, out, tc.out, tc.name)
   587  		})
   588  	}
   589  
   590  }
   591  
   592  func TestSelectFloorModelGroup(t *testing.T) {
   593  	weightNilModelGroup := openrtb_ext.PriceFloorModelGroup{ModelWeight: nil}
   594  	weight01ModelGroup := openrtb_ext.PriceFloorModelGroup{ModelWeight: getIntPtr(1)}
   595  	weight25ModelGroup := openrtb_ext.PriceFloorModelGroup{ModelWeight: getIntPtr(25)}
   596  	weight50ModelGroup := openrtb_ext.PriceFloorModelGroup{ModelWeight: getIntPtr(50)}
   597  
   598  	testCases := []struct {
   599  		name               string
   600  		ModelGroup         []openrtb_ext.PriceFloorModelGroup
   601  		fn                 func(int) int
   602  		expectedModelGroup []openrtb_ext.PriceFloorModelGroup
   603  	}{
   604  		{
   605  			name: "ModelGroup with default weight selection",
   606  			ModelGroup: []openrtb_ext.PriceFloorModelGroup{
   607  				weightNilModelGroup,
   608  			},
   609  			fn: func(i int) int { return 0 },
   610  			expectedModelGroup: []openrtb_ext.PriceFloorModelGroup{
   611  				weight01ModelGroup,
   612  			},
   613  		},
   614  		{
   615  			name: "ModelGroup with weight = 25 selection",
   616  			ModelGroup: []openrtb_ext.PriceFloorModelGroup{
   617  				weight25ModelGroup,
   618  				weight50ModelGroup,
   619  			},
   620  			fn: func(i int) int { return 5 },
   621  			expectedModelGroup: []openrtb_ext.PriceFloorModelGroup{
   622  				weight25ModelGroup,
   623  			},
   624  		},
   625  		{
   626  			name: "ModelGroup with weight = 50 selection",
   627  			ModelGroup: []openrtb_ext.PriceFloorModelGroup{
   628  				weight50ModelGroup,
   629  			},
   630  			fn: func(i int) int { return 55 },
   631  			expectedModelGroup: []openrtb_ext.PriceFloorModelGroup{
   632  				weight50ModelGroup,
   633  			},
   634  		},
   635  		{
   636  			name: "ModelGroup with weight = 25 selection",
   637  			ModelGroup: []openrtb_ext.PriceFloorModelGroup{
   638  				weight25ModelGroup,
   639  				weight50ModelGroup,
   640  			},
   641  			fn: func(i int) int { return 80 },
   642  			expectedModelGroup: []openrtb_ext.PriceFloorModelGroup{
   643  				weight25ModelGroup,
   644  			},
   645  		},
   646  	}
   647  
   648  	for _, tc := range testCases {
   649  		t.Run(tc.name, func(t *testing.T) {
   650  			resp := selectFloorModelGroup(tc.ModelGroup, tc.fn)
   651  			assert.Equal(t, resp, tc.expectedModelGroup)
   652  		})
   653  	}
   654  }
   655  
   656  func TestGetMinFloorValue(t *testing.T) {
   657  	rates := map[string]map[string]float64{
   658  		"USD": {
   659  			"INR": 81.17,
   660  		},
   661  	}
   662  
   663  	type args struct {
   664  		floorExt    *openrtb_ext.PriceFloorRules
   665  		imp         openrtb2.Imp
   666  		conversions currency.Conversions
   667  	}
   668  	testCases := []struct {
   669  		name    string
   670  		args    args
   671  		want    float64
   672  		want1   string
   673  		wantErr error
   674  	}{
   675  		{
   676  			name: "Floor min is available in imp and floor ext",
   677  			args: args{
   678  				floorExt: &openrtb_ext.PriceFloorRules{FloorMin: 2.0, FloorMinCur: "INR", Data: &openrtb_ext.PriceFloorData{Currency: "INR"}},
   679  				imp:      openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "INR","floorMin":1.0}}}`)},
   680  			},
   681  			want:  1,
   682  			want1: "INR",
   683  		},
   684  		{
   685  			name: "Floor min and floor min currency is available in imp ext only",
   686  			args: args{
   687  				floorExt: &openrtb_ext.PriceFloorRules{},
   688  				imp:      openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "INR", "floorMin": 1.0}}}`)},
   689  			},
   690  			want:  0.0123,
   691  			want1: "USD",
   692  		},
   693  		{
   694  			name: "Floor min is available in floor ext only",
   695  			args: args{
   696  				floorExt: &openrtb_ext.PriceFloorRules{FloorMin: 1.0, FloorMinCur: "EUR", Data: &openrtb_ext.PriceFloorData{Currency: "EUR"}},
   697  				imp:      openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{}}}`)},
   698  			},
   699  			want:  1.0,
   700  			want1: "EUR",
   701  		},
   702  		{
   703  			name: "Floor min is available in floorExt and currency is available in imp",
   704  			args: args{
   705  				floorExt: &openrtb_ext.PriceFloorRules{FloorMin: 2.0, Data: &openrtb_ext.PriceFloorData{Currency: "INR"}},
   706  				imp:      openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "INR"}}}`)},
   707  			},
   708  			want:  2,
   709  			want1: "INR",
   710  		},
   711  		{
   712  			name: "Floor min is available in ImpExt and currency is available in floorExt",
   713  			args: args{
   714  				floorExt: &openrtb_ext.PriceFloorRules{FloorMinCur: "USD", Data: &openrtb_ext.PriceFloorData{Currency: "INR"}},
   715  				imp:      openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"FloorMin": 2.0}}}`)},
   716  			},
   717  			want:  162.34,
   718  			want1: "INR",
   719  		},
   720  		{
   721  			name: "Floor Min and floor Currency are in Imp and only floor currency is available in floor ext",
   722  			args: args{
   723  				floorExt: &openrtb_ext.PriceFloorRules{FloorMinCur: "USD"},
   724  				imp:      openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "USD","floorMin":1.0}}}`)},
   725  			},
   726  			want:  1,
   727  			want1: "USD",
   728  		},
   729  		{
   730  			name: "Currency are different in floor ext and imp",
   731  			args: args{
   732  				floorExt: &openrtb_ext.PriceFloorRules{FloorMin: 0.0, FloorMinCur: "EUR", Data: &openrtb_ext.PriceFloorData{Currency: "INR"}},
   733  				imp:      openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "USD","floorMin":1.0}}}`)},
   734  			},
   735  			want:  81.17,
   736  			want1: "INR",
   737  		},
   738  		{
   739  			name: "Floor min is 0 in imp ",
   740  			args: args{
   741  				floorExt: &openrtb_ext.PriceFloorRules{FloorMin: 2.0, FloorMinCur: "JPY", Data: &openrtb_ext.PriceFloorData{Currency: "INR"}},
   742  				imp:      openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "USD","floorMin":0.0}}}`)},
   743  			},
   744  			want:  162.34,
   745  			want1: "INR",
   746  		},
   747  		{
   748  			name: "Floor Currency is empty in imp",
   749  			args: args{
   750  				floorExt: &openrtb_ext.PriceFloorRules{FloorMin: 1.0, FloorMinCur: "EUR", Data: &openrtb_ext.PriceFloorData{Currency: "EUR"}},
   751  				imp:      openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "","floorMin":-1.0}}}`)},
   752  			},
   753  			want:  1.0,
   754  			want1: "EUR",
   755  		},
   756  		{
   757  			name: "Invalid input",
   758  			args: args{
   759  				floorExt: &openrtb_ext.PriceFloorRules{FloorMinCur: "EUR", Data: &openrtb_ext.PriceFloorData{}},
   760  				imp:      openrtb2.Imp{Ext: json.RawMessage(`{`)},
   761  			},
   762  			want:    0.0,
   763  			want1:   "",
   764  			wantErr: errors.New("Error in getting FloorMin value : 'expects \" or n, but found \x00'"),
   765  		},
   766  	}
   767  	for _, tc := range testCases {
   768  		t.Run(tc.name, func(t *testing.T) {
   769  			got, got1, err := getMinFloorValue(tc.args.floorExt, &openrtb_ext.ImpWrapper{Imp: &tc.args.imp}, getCurrencyRates(rates))
   770  			assert.Equal(t, tc.wantErr, err, tc.name)
   771  			assert.Equal(t, tc.want, got, tc.name)
   772  			assert.Equal(t, tc.want1, got1, tc.name)
   773  		})
   774  	}
   775  }
   776  
   777  func TestSortCombinations(t *testing.T) {
   778  	type args struct {
   779  		comb            [][]int
   780  		numSchemaFields int
   781  	}
   782  	tests := []struct {
   783  		name    string
   784  		args    args
   785  		expComb [][]int
   786  	}{
   787  		{
   788  			name: "With schema fields = 3",
   789  			args: args{
   790  				comb:            [][]int{{0}, {1}, {2}},
   791  				numSchemaFields: 3,
   792  			},
   793  			expComb: [][]int{{2}, {1}, {0}},
   794  		},
   795  		{
   796  			name: "With schema fields = 3",
   797  			args: args{
   798  				comb:            [][]int{{0, 1}, {1, 2}, {0, 2}},
   799  				numSchemaFields: 3,
   800  			},
   801  			expComb: [][]int{{1, 2}, {0, 2}, {0, 1}},
   802  		},
   803  		{
   804  			name: "With schema fields = 4",
   805  			args: args{
   806  				comb:            [][]int{{0, 1, 2}, {1, 2, 3}, {0, 2, 3}, {0, 1, 3}},
   807  				numSchemaFields: 3,
   808  			},
   809  			expComb: [][]int{{1, 2, 3}, {0, 2, 3}, {0, 1, 3}, {0, 1, 2}},
   810  		},
   811  	}
   812  	for _, tt := range tests {
   813  		t.Run(tt.name, func(t *testing.T) {
   814  			sortCombinations(tt.args.comb, tt.args.numSchemaFields)
   815  			assert.Equal(t, tt.expComb, tt.args.comb)
   816  		})
   817  	}
   818  }
   819  
   820  func TestGenerateCombinations(t *testing.T) {
   821  
   822  	tests := []struct {
   823  		name            string
   824  		numSchemaFields int
   825  		numWildCard     int
   826  		expComb         [][]int
   827  	}{
   828  		{
   829  			name:            "With schema fields = 3, wildcard = 1",
   830  			numSchemaFields: 3,
   831  			numWildCard:     1,
   832  			expComb:         [][]int{{0}, {1}, {2}},
   833  		},
   834  		{
   835  			name:            "With schema fields = 3, wildcard = 2",
   836  			numSchemaFields: 3,
   837  			numWildCard:     2,
   838  			expComb:         [][]int{{0, 1}, {0, 2}, {1, 2}},
   839  		},
   840  		{
   841  			name:            "With schema fields = 3, wildcard = 3",
   842  			numSchemaFields: 3,
   843  			numWildCard:     3,
   844  			expComb:         [][]int{{0, 1, 2}},
   845  		},
   846  	}
   847  	for _, tt := range tests {
   848  		t.Run(tt.name, func(t *testing.T) {
   849  			gotComb := generateCombinations(tt.numSchemaFields, tt.numWildCard)
   850  			assert.Equal(t, tt.expComb, gotComb)
   851  		})
   852  	}
   853  }
   854  
   855  func TestGetDeviceType(t *testing.T) {
   856  	tests := []struct {
   857  		name    string
   858  		request *openrtb2.BidRequest
   859  		want    string
   860  	}{
   861  		{
   862  			name:    "user agent contains Phone",
   863  			request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Phone Samsung Mobile; Win64; x64)"}},
   864  			want:    "phone",
   865  		},
   866  		{
   867  			name:    "user agent contains iPhone",
   868  			request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Safari(iPhone Apple Mobile)"}},
   869  			want:    "phone",
   870  		},
   871  		{
   872  			name:    "user agent contains Mobile.*Android",
   873  			request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Mobile Android; Win64; x64)"}},
   874  			want:    "phone",
   875  		},
   876  		{
   877  			name:    "user agent contains Android.*Mobile",
   878  			request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Android Redmi Mobile; Win64; x64)"}},
   879  			want:    "phone",
   880  		},
   881  		{
   882  			name:    "user agent contains Mobile.*Android",
   883  			request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Mobile pixel Android; Win64; x64)"}},
   884  			want:    "phone",
   885  		},
   886  		{
   887  			name:    "user agent contains Windows NT touch",
   888  			request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Windows NT touch 10.0; Win64; x64)"}},
   889  			want:    "tablet",
   890  		},
   891  		{
   892  			name:    "user agent contains ipad",
   893  			request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (ipad 13.10; Win64; x64)"}},
   894  			want:    "tablet",
   895  		},
   896  		{
   897  			name:    "user agent contains Window NT.*touch",
   898  			request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0; Touch)"}},
   899  			want:    "tablet",
   900  		},
   901  		{
   902  			name:    "user agent contains touch.* Window NT",
   903  			request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (touch realme Windows NT Win64; x64)"}},
   904  			want:    "tablet",
   905  		},
   906  		{
   907  			name:    "user agent contains Android",
   908  			request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Android; Win64; x64)"}},
   909  			want:    "tablet",
   910  		},
   911  		{
   912  			name:    "user agent not matching phone or tablet",
   913  			request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}},
   914  			want:    "desktop",
   915  		},
   916  		{
   917  			name:    "empty user agent",
   918  			request: &openrtb2.BidRequest{Device: &openrtb2.Device{}},
   919  			want:    "*",
   920  		},
   921  	}
   922  	for _, tt := range tests {
   923  		t.Run(tt.name, func(t *testing.T) {
   924  			got := getDeviceType(&openrtb_ext.RequestWrapper{BidRequest: tt.request})
   925  			assert.Equal(t, tt.want, got)
   926  		})
   927  	}
   928  }
   929  
   930  func TestGetAdUnitCode(t *testing.T) {
   931  	tests := []struct {
   932  		name string
   933  		imp  *openrtb_ext.ImpWrapper
   934  		want string
   935  	}{
   936  		{
   937  			name: "imp.ext.gpid",
   938  			imp:  &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{Ext: json.RawMessage(`{"gpid":"test_gpid"}`)}},
   939  			want: "test_gpid",
   940  		},
   941  		{
   942  			name: "imp.TagID",
   943  			imp:  &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{TagID: "tag_1"}},
   944  			want: "tag_1",
   945  		},
   946  		{
   947  			name: "imp.ext.data.pbadslot",
   948  			imp:  &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{Ext: json.RawMessage(`{"data":{"pbadslot":"pbslot_1"}}`)}},
   949  			want: "pbslot_1",
   950  		},
   951  		{
   952  			name: "imp.ext.prebid.storedrequest.id",
   953  			imp:  &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{Ext: json.RawMessage(`{"prebid": {"storedrequest":{"id":"123"}}}`)}},
   954  			want: "123",
   955  		},
   956  		{
   957  			name: "empty adUnitCode",
   958  			imp:  &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{}},
   959  			want: "*",
   960  		},
   961  	}
   962  
   963  	for _, tt := range tests {
   964  		t.Run(tt.name, func(t *testing.T) {
   965  			got := getAdUnitCode(tt.imp)
   966  			assert.Equal(t, tt.want, got)
   967  		})
   968  	}
   969  }
   970  
   971  func TestGetGptSlot(t *testing.T) {
   972  	tests := []struct {
   973  		name string
   974  		imp  *openrtb_ext.ImpWrapper
   975  		want string
   976  	}{
   977  		{
   978  			name: "imp.ext.data.adserver.adslot",
   979  			imp:  &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{Ext: json.RawMessage(`{"data":{"adserver": {"name": "gam", "adslot": "slot_1"}}}`)}},
   980  			want: "slot_1",
   981  		},
   982  		{
   983  			name: "gptSlot = imp.ext.data.pbadslot",
   984  			imp:  &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{Ext: json.RawMessage(`{"data":{"pbadslot":"pbslot_1"}}`)}},
   985  			want: "pbslot_1",
   986  		},
   987  		{
   988  			name: "empty gptSlot",
   989  			imp:  &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{}},
   990  			want: "*",
   991  		},
   992  	}
   993  	for _, tt := range tests {
   994  		t.Run(tt.name, func(t *testing.T) {
   995  			got := getGptSlot(tt.imp)
   996  			assert.Equal(t, tt.want, got)
   997  		})
   998  	}
   999  }
  1000  
  1001  func TestGetSizeValue(t *testing.T) {
  1002  	tests := []struct {
  1003  		name string
  1004  		imp  *openrtb2.Imp
  1005  		want string
  1006  	}{
  1007  		{
  1008  			name: "banner: only one size exists in imp.banner.format",
  1009  			imp:  &openrtb2.Imp{Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}},
  1010  			want: "300x250",
  1011  		},
  1012  		{
  1013  			name: "banner: no imp.banner.format",
  1014  			imp:  &openrtb2.Imp{Banner: &openrtb2.Banner{W: getInt64Ptr(320), H: getInt64Ptr(240)}},
  1015  			want: "320x240",
  1016  		},
  1017  		{
  1018  			name: "video:  imp.video.w and  imp.video.h present",
  1019  			imp:  &openrtb2.Imp{Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](120), H: ptrutil.ToPtr[int64](240)}},
  1020  			want: "120x240",
  1021  		},
  1022  		{
  1023  			name: "banner: more than one size exists in imp.banner.format",
  1024  			imp:  &openrtb2.Imp{Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}, {W: 200, H: 300}}}},
  1025  			want: "*",
  1026  		},
  1027  		{
  1028  			name: "Audo creative",
  1029  			imp:  &openrtb2.Imp{Audio: &openrtb2.Audio{}},
  1030  			want: "*",
  1031  		},
  1032  	}
  1033  	for _, tt := range tests {
  1034  		t.Run(tt.name, func(t *testing.T) {
  1035  			got := getSizeValue(tt.imp)
  1036  			assert.Equal(t, tt.want, got)
  1037  		})
  1038  	}
  1039  }
  1040  
  1041  func TestGetMediaType(t *testing.T) {
  1042  	tests := []struct {
  1043  		name string
  1044  		imp  *openrtb2.Imp
  1045  		want string
  1046  	}{
  1047  		{
  1048  			name: "more than one of these: imp.banner, imp.video, imp.native, imp.audio present",
  1049  			imp:  &openrtb2.Imp{Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](120), H: ptrutil.ToPtr[int64](240)}, Banner: &openrtb2.Banner{W: getInt64Ptr(320), H: getInt64Ptr(240)}},
  1050  			want: "*",
  1051  		},
  1052  		{
  1053  			name: "only banner present",
  1054  			imp:  &openrtb2.Imp{Banner: &openrtb2.Banner{W: getInt64Ptr(320), H: getInt64Ptr(240)}},
  1055  			want: "banner",
  1056  		},
  1057  		{
  1058  			name: "video-outstream present",
  1059  			imp:  &openrtb2.Imp{Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](120), H: ptrutil.ToPtr[int64](240), Placement: 2}},
  1060  			want: "video-outstream",
  1061  		},
  1062  		{
  1063  			name: "video-instream present",
  1064  			imp:  &openrtb2.Imp{Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](120), H: ptrutil.ToPtr[int64](240), Placement: 1}},
  1065  			want: "video",
  1066  		},
  1067  		{
  1068  			name: "only audio",
  1069  			imp:  &openrtb2.Imp{Audio: &openrtb2.Audio{MinDuration: 10}},
  1070  			want: "audio",
  1071  		},
  1072  		{
  1073  			name: "only native",
  1074  			imp:  &openrtb2.Imp{Native: &openrtb2.Native{Request: "test_req"}},
  1075  			want: "native",
  1076  		},
  1077  	}
  1078  
  1079  	for _, tt := range tests {
  1080  		t.Run(tt.name, func(t *testing.T) {
  1081  			got := getMediaType(tt.imp)
  1082  			assert.Equal(t, tt.want, got)
  1083  		})
  1084  	}
  1085  }
  1086  
  1087  func TestGetSiteDomain(t *testing.T) {
  1088  	type args struct {
  1089  		request *openrtb_ext.RequestWrapper
  1090  	}
  1091  	tests := []struct {
  1092  		name    string
  1093  		request *openrtb_ext.RequestWrapper
  1094  		want    string
  1095  	}{
  1096  		{
  1097  			name:    "Site Domain present",
  1098  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{Domain: "abc.xyz.com"}}},
  1099  			want:    "abc.xyz.com",
  1100  		},
  1101  		{
  1102  			name:    "Site Domain not present",
  1103  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{}}},
  1104  			want:    "*",
  1105  		},
  1106  		{
  1107  			name:    "App Domain present",
  1108  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{Domain: "cde.rtu.com"}}},
  1109  			want:    "cde.rtu.com",
  1110  		},
  1111  		{
  1112  			name:    "App Domain not present",
  1113  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{}}},
  1114  			want:    "*",
  1115  		},
  1116  	}
  1117  	for _, tt := range tests {
  1118  		t.Run(tt.name, func(t *testing.T) {
  1119  			got := getSiteDomain(tt.request)
  1120  			assert.Equal(t, tt.want, got)
  1121  		})
  1122  	}
  1123  }
  1124  
  1125  func TestGetPublisherDomain(t *testing.T) {
  1126  	type args struct {
  1127  	}
  1128  	tests := []struct {
  1129  		name    string
  1130  		request *openrtb_ext.RequestWrapper
  1131  		want    string
  1132  	}{
  1133  		{
  1134  			name:    "Site publisher domain present",
  1135  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{Publisher: &openrtb2.Publisher{Domain: "qwe.xyz.com"}}}},
  1136  			want:    "qwe.xyz.com",
  1137  		},
  1138  		{
  1139  			name:    "Site publisher domain not present",
  1140  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{Publisher: &openrtb2.Publisher{}}}},
  1141  			want:    "*",
  1142  		},
  1143  		{
  1144  			name:    "App publisher domain present",
  1145  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{Publisher: &openrtb2.Publisher{Domain: "xyz.com"}}}},
  1146  			want:    "xyz.com",
  1147  		},
  1148  		{
  1149  			name:    "App publisher domain not present",
  1150  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{}}},
  1151  			want:    "*",
  1152  		},
  1153  	}
  1154  	for _, tt := range tests {
  1155  		t.Run(tt.name, func(t *testing.T) {
  1156  			got := getPublisherDomain(tt.request)
  1157  			assert.Equal(t, tt.want, got)
  1158  		})
  1159  	}
  1160  }
  1161  
  1162  func TestGetDomain(t *testing.T) {
  1163  	type args struct {
  1164  	}
  1165  	tests := []struct {
  1166  		name    string
  1167  		request *openrtb_ext.RequestWrapper
  1168  		want    string
  1169  	}{
  1170  		{
  1171  			name:    "Site domain present",
  1172  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{Domain: "qwe.xyz.com", Publisher: &openrtb2.Publisher{Domain: "abc.xyz.com"}}}},
  1173  			want:    "qwe.xyz.com",
  1174  		},
  1175  		{
  1176  			name:    "Site publisher domain present",
  1177  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{Publisher: &openrtb2.Publisher{Domain: "abc.xyz.com"}}}},
  1178  			want:    "abc.xyz.com",
  1179  		},
  1180  		{
  1181  			name:    "Site domain not present",
  1182  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{Publisher: &openrtb2.Publisher{}}}},
  1183  			want:    "*",
  1184  		},
  1185  		{
  1186  			name:    "App publisher domain present",
  1187  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{Domain: "abc.com", Publisher: &openrtb2.Publisher{Domain: "xyz.com"}}}},
  1188  			want:    "abc.com",
  1189  		},
  1190  		{
  1191  			name:    "App domain present",
  1192  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{Publisher: &openrtb2.Publisher{Domain: "xyz.com"}}}},
  1193  			want:    "xyz.com",
  1194  		},
  1195  		{
  1196  			name:    "App domain not present",
  1197  			request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{}}},
  1198  			want:    "*",
  1199  		},
  1200  	}
  1201  	for _, tt := range tests {
  1202  		t.Run(tt.name, func(t *testing.T) {
  1203  			got := getDomain(tt.request)
  1204  			assert.Equal(t, tt.want, got)
  1205  		})
  1206  	}
  1207  }
  1208  
  1209  func getIntPtr(v int) *int {
  1210  	return &v
  1211  }
  1212  
  1213  func getInt64Ptr(v int64) *int64 {
  1214  	return &v
  1215  }