diff --git a/config/account.go b/config/account.go index 6966261a992..dc78b4858bb 100644 --- a/config/account.go +++ b/config/account.go @@ -42,7 +42,7 @@ type Account struct { DefaultBidLimit int `mapstructure:"default_bid_limit" json:"default_bid_limit"` BidAdjustments *openrtb_ext.ExtRequestPrebidBidAdjustments `mapstructure:"bidadjustments" json:"bidadjustments"` Privacy AccountPrivacy `mapstructure:"privacy" json:"privacy"` - Auction AuctionPrivacy `mapstructure:"auctionprivacy" json:"auctionprivacy"` + Auction Auction `mapstructure:"auction" json:"auction"` } // CookieSync represents the account-level defaults for the cookie sync endpoint. @@ -363,8 +363,3 @@ func (ip *IPv4) Validate(errs []error) []error { } return errs } - -type PrivacySandbox struct { - CookieDeprecation bool `mapstructure:"cookiedeprecation" json:"cookiedeprecation"` - CookieDeprecationExpirationSec int `mapstructure:"cookiedeprecationexpirationsec" json:"cookiedeprecationexpirationsec"` -} diff --git a/config/config.go b/config/config.go index 3eb1d1ca0cb..bdcc806ac58 100644 --- a/config/config.go +++ b/config/config.go @@ -100,6 +100,8 @@ type Configuration struct { Hooks Hooks `mapstructure:"hooks"` Validations Validations `mapstructure:"validations"` PriceFloors PriceFloors `mapstructure:"price_floors"` + + Auction Auction `mapstructure:"auction"` } type PriceFloors struct { @@ -1286,7 +1288,12 @@ type TmaxAdjustments struct { BidderResponseDurationMin uint `mapstructure:"bidder_response_duration_min_ms"` } -type AuctionPrivacy struct { - TopicsDomain string `mapstructure:"topicsdomain"` +type Auction struct { PrivacySandbox PrivacySandbox `mapstructure:"privacysandbox" json:"privacysandbox"` } + +type PrivacySandbox struct { + TopicsDomain string `mapstructure:"topicsdomain"` + CookieDeprecation bool `mapstructure:"cookiedeprecation"` + CookieDeprecationExpirationSec int `mapstructure:"cookiedeprecationexpirationsec"` +} diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go index c136f25b23c..3b877b7774f 100644 --- a/endpoints/openrtb2/auction.go +++ b/endpoints/openrtb2/auction.go @@ -2014,7 +2014,7 @@ func (deps *endpointDeps) setFieldsImplicitly(httpReq *http.Request, r *openrtb_ setAuctionTypeImplicitly(r) - setSecBrowsingTopcisImplicitly(httpReq, r) + setSecBrowsingTopcisImplicitly(httpReq, r, deps.cfg) } // setDeviceImplicitly uses implicit info from httpReq to populate bidReq.Device @@ -2034,11 +2034,16 @@ func setAuctionTypeImplicitly(r *openrtb_ext.RequestWrapper) { } // (100);v=chrome.1:1:20, (200);v=chrome.1:1:40, (300);v=chrome.1:1:60, ();p=P -func setSecBrowsingTopcisImplicitly(httpReq *http.Request, r *openrtb_ext.RequestWrapper) { +func setSecBrowsingTopcisImplicitly(httpReq *http.Request, r *openrtb_ext.RequestWrapper, cfg *config.Configuration) { if r.User == nil { r.User = &openrtb2.User{} } + topicsDomain := "TOPICS_DOMAIN" + if cfg != nil { + topicsDomain = cfg.Auction.PrivacySandbox.TopicsDomain + } + secBrowsingTopics := httpReq.Header.Get("Sec-Browsing-Topics") if secBrowsingTopics == "" { return @@ -2049,7 +2054,7 @@ func setSecBrowsingTopcisImplicitly(httpReq *http.Request, r *openrtb_ext.Reques secBrowsingTopicsArr := strings.Split(secBrowsingTopics, ",") c := 0 for _, seg := range secBrowsingTopicsArr { - if c > 10 { + if c >= 10 { break } @@ -2090,15 +2095,7 @@ func setSecBrowsingTopcisImplicitly(httpReq *http.Request, r *openrtb_ext.Reques } segtax := 600 + (taxanomy - 1) segclass := strings.TrimSpace(taxanomyModel[2]) - // modelVer := strings.TrimSpace(taxanomyModel[2]) - // segclass, err := strconv.Atoi(modelVer) - // if err != nil { - // continue - // } - - // if _, ok := userData["TOPICS_DOMAIN"]; !ok { - // userData["TOPICS_DOMAIN"] = map[int]map[int][]string{} - // } + if _, ok := userData[segtax]; !ok { userData[segtax] = map[string]map[string]map[string]struct{}{} } @@ -2107,14 +2104,14 @@ func setSecBrowsingTopcisImplicitly(httpReq *http.Request, r *openrtb_ext.Reques userData[segtax][segclass] = map[string]map[string]struct{}{} } - if _, ok := userData[segtax][segclass]["TOPICS_DOMAIN"]; !ok { - userData[segtax][segclass]["TOPICS_DOMAIN"] = map[string]struct{}{} + if _, ok := userData[segtax][segclass][topicsDomain]; !ok { + userData[segtax][segclass][topicsDomain] = map[string]struct{}{} } for _, segId := range segmentsIdArr { segId = strings.TrimSpace(segId) if segid, err := strconv.Atoi(segId); err == nil && segid > 0 { - userData[segtax][segclass]["TOPICS_DOMAIN"][segId] = struct{}{} + userData[segtax][segclass][topicsDomain][segId] = struct{}{} } } @@ -2127,12 +2124,10 @@ func setSecBrowsingTopcisImplicitly(httpReq *http.Request, r *openrtb_ext.Reques } requestUserData := map[int]map[string]map[string]map[string]struct{}{} - for _, data := range r.User.Data { + for i, data := range r.User.Data { ext := &extData{} - if err := json.Unmarshal(data.Ext, ext); err != nil { - continue - } + _ = json.Unmarshal(data.Ext, ext) if ext.Segtax == 0 || ext.Segclass == "" { continue } @@ -2160,7 +2155,7 @@ func setSecBrowsingTopcisImplicitly(httpReq *http.Request, r *openrtb_ext.Reques if _, ok := userData[ext.Segtax][ext.Segclass][data.Name]; ok { for segId := range userData[ext.Segtax][ext.Segclass][data.Name] { if _, ok := requestUserData[ext.Segtax][ext.Segclass][data.Name][segId]; !ok { - data.Segment = append(data.Segment, openrtb2.Segment{ + r.User.Data[i].Segment = append(r.User.Data[i].Segment, openrtb2.Segment{ ID: segId, }) } @@ -2174,22 +2169,6 @@ func setSecBrowsingTopcisImplicitly(httpReq *http.Request, r *openrtb_ext.Reques if !merged { continue } - - // if _, ok := userData[ext.Segtax]; !ok { - // userData[ext.Segtax] = map[string]map[string]map[string]struct{}{} - // } - - // if _, ok := userData[ext.Segtax][ext.Segclass]; !ok { - // userData[ext.Segtax][ext.Segclass] = map[string]map[string]struct{}{} - // } - - // if _, ok := userData[ext.Segtax][ext.Segclass][data.Name]; !ok { - // userData[ext.Segtax][ext.Segclass][data.Name] = map[string]struct{}{} - // } - - // for _, segId := range data.Segment { - // userData[ext.Segtax][ext.Segclass][data.Name][segId.ID] = struct{}{} - // } } for segtax, SegclassSegName := range userData { @@ -2207,8 +2186,6 @@ func setSecBrowsingTopcisImplicitly(httpReq *http.Request, r *openrtb_ext.Reques } } } - - // r.User.Ext = json.RawMessage(fmt.Sprintf(`{"consent": "%s"}`, secBrowsingTopic)) } func setSiteImplicitly(httpReq *http.Request, r *openrtb_ext.RequestWrapper) { diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go index 6c9d5376da6..55852f96893 100644 --- a/endpoints/openrtb2/auction_test.go +++ b/endpoints/openrtb2/auction_test.go @@ -6189,6 +6189,7 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { type args struct { httpReq *http.Request r *openrtb_ext.RequestWrapper + cfg *config.Configuration } tests := []struct { name string @@ -6200,6 +6201,7 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { args: args{ httpReq: &http.Request{}, r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{}, }, @@ -6208,10 +6210,11 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { args: args{ httpReq: &http.Request{ Header: http.Header{ - "Sec-Browsing-Topics": []string{""}, + "Sec-Browsing-Topics": []string{" "}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{}, }, @@ -6223,7 +6226,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"some-sec-cookie-value"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{}, }, @@ -6235,7 +6239,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"();p=P0000000000000000000000000000000"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{}, }, @@ -6247,7 +6252,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"(1);v=chrome.1:1:2, ();p=P00000000000"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{ Data: []openrtb2.Data{ @@ -6264,14 +6270,67 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { }, }, { - name: "Sec-Browsing-Topics with one valid field and one invalid field, request.user.data empty, valid field data added to req.user.data", + name: "Sec-Browsing-Topics with more than 10 valid fields, request.user.data empty, only 10 valid fields added to req.user.data", args: args{ httpReq: &http.Request{ Header: http.Header{ - "Sec-Browsing-Topics": []string{"(1);v=chrome.1:1:2, (4);v=chrome.1, ();p=P0000000000"}, + "Sec-Browsing-Topics": []string{"(1);v=chrome.1:1:2, (2);v=chrome.1:1:2, (3);v=chrome.1:1:2, (4);v=chrome.1:1:2, (5);v=chrome.1:1:2, (6);v=chrome.1:1:2, (7);v=chrome.1:1:2, (8);v=chrome.1:1:2, (9);v=chrome.1:1:2, (10);v=chrome.1:1:2, (11);v=chrome.1:1:2, (12);v=chrome.1:1:2, ();p=P00000000000"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, + }, + wantUser: &openrtb2.User{ + Data: []openrtb2.Data{ + { + Name: "TOPICS_DOMAIN", + Segment: []openrtb2.Segment{ + { + ID: "1", + }, + { + ID: "2", + }, + { + ID: "3", + }, + { + ID: "4", + }, + { + ID: "5", + }, + { + ID: "6", + }, + { + ID: "7", + }, + { + ID: "8", + }, + { + ID: "9", + }, + { + ID: "10", + }, + }, + Ext: json.RawMessage(`{"segtax": 600, "segclass": "2"}`), + }, + }, + }, + }, + { + name: "Sec-Browsing-Topics with one valid field and others different invalid scenarios, request.user.data empty, valid field data added to req.user.data", + args: args{ + httpReq: &http.Request{ + Header: http.Header{ + "Sec-Browsing-Topics": []string{"(1);v=chrome.1:1:2, (4);v=chrome.1, 5);v=chrome.1, (6;v=chrome.1, ();v=chrome.1, ( );v=chrome.1, ();p=P0000000000"}, + }, + }, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{ Data: []openrtb2.Data{ @@ -6295,7 +6354,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"(1 2);v=chrome.1:1:2, ();p=P00000000000"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{ Data: []openrtb2.Data{ @@ -6322,7 +6382,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"(1);v=chrome.1:1:2, (1);v=chrome.1:1:1, ();p=P0000000000"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{ Data: []openrtb2.Data{ @@ -6355,7 +6416,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"(1);v=chrome.1:11:2, (1);v=chrome.1:1:4, (1);v=chrome.1:0:2, ();p=P0000000000"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{ Data: []openrtb2.Data{ @@ -6379,7 +6441,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"(100);v=chrome.1:111111111111111111:20, (200);v=chrome.1:2:40, (200 300);v=chrome.1:2:40, ();p=P"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{ Data: []openrtb2.Data{ @@ -6406,7 +6469,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"(1);v=chrome.1:1:2, (1);v=chrome.1:1:2, ();p=P0000000000"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{ Data: []openrtb2.Data{ @@ -6430,7 +6494,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"(1);v=chrome.1:1:2, (2);v=chrome.1:1:2, ();p=P0000000000"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{ Data: []openrtb2.Data{ @@ -6457,7 +6522,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"(1);v=chrome.1:1:2, (2);v=chrome.1:1:2, ();p=P0000000000"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{ Data: []openrtb2.Data{ @@ -6484,7 +6550,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"(1 2 4 6 7 4567 ) ; v=chrome.1: 1 : 2, (1);v=chrome.1, ();p=P0000000000"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{ Data: []openrtb2.Data{ @@ -6523,7 +6590,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"(1 -2 4 6 7 4567 ) ; v=chrome.1: 1 : 2, (1);v=chrome.1, ();p=P0000000000"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{ Data: []openrtb2.Data{ @@ -6559,7 +6627,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"(1);v=chrome.1:1:4,();p=P0000000000,(2);v=chrome.1:1:4,();p=P000000000"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{ Data: []openrtb2.Data{ @@ -6586,7 +6655,8 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { "Sec-Browsing-Topics": []string{"(100);v=chrome.1:2:20"}, }, }, - r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + r: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{}}, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, }, wantUser: &openrtb2.User{ Data: []openrtb2.Data{ @@ -6602,10 +6672,229 @@ func Test_setSecBrowsingTopcisImplicitly(t *testing.T) { }, }, }, + { + name: "Sec-Browsing-Topics with two fields both matching segtax and segclass and different segIds, request.user.data has non matching user data, header data merged and added in req.user.data", + args: args{ + httpReq: &http.Request{ + Header: http.Header{ + "Sec-Browsing-Topics": []string{"(1);v=chrome.1:1:2, (2);v=chrome.1:1:2, ();p=P0000000000"}, + }, + }, + r: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{ + User: &openrtb2.User{ + Data: []openrtb2.Data{ + { + Name: "ABC", + Segment: []openrtb2.Segment{ + { + ID: "1", + }, + { + ID: "2", + }, + }, + Ext: json.RawMessage(`{"segtax": 600, "segclass": "2"}`), + }, + }, + }, + }, + }, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, + }, + wantUser: &openrtb2.User{ + Data: []openrtb2.Data{ + { + Name: "ABC", + Segment: []openrtb2.Segment{ + { + ID: "1", + }, + { + ID: "2", + }, + }, + Ext: json.RawMessage(`{"segtax": 600, "segclass": "2"}`), + }, + { + Name: "TOPICS_DOMAIN", + Segment: []openrtb2.Segment{ + { + ID: "1", + }, + { + ID: "2", + }, + }, + Ext: json.RawMessage(`{"segtax": 600, "segclass": "2"}`), + }, + }, + }, + }, + { + name: "Sec-Browsing-Topics with two fields both matching segtax and segclass and different segIds, request.user.data also with same segclass, segtax and same segIds, duplicate header data not added to req.user.data", + args: args{ + httpReq: &http.Request{ + Header: http.Header{ + "Sec-Browsing-Topics": []string{"(1);v=chrome.1:1:2, (2);v=chrome.1:1:2, ();p=P0000000000"}, + }, + }, + r: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{ + User: &openrtb2.User{ + Data: []openrtb2.Data{ + { + Name: "TOPICS_DOMAIN", + Segment: []openrtb2.Segment{ + { + ID: "1", + }, + { + ID: "2", + }, + }, + Ext: json.RawMessage(`{"segtax": 600, "segclass": "2"}`), + }, + }, + }, + }, + }, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, + }, + wantUser: &openrtb2.User{ + Data: []openrtb2.Data{ + { + Name: "TOPICS_DOMAIN", + Segment: []openrtb2.Segment{ + { + ID: "1", + }, + { + ID: "2", + }, + }, + Ext: json.RawMessage(`{"segtax": 600, "segclass": "2"}`), + }, + }, + }, + }, + { + name: "Sec-Browsing-Topics with two fields both matching segtax and segclass and different segIds, request.user.data also with same segclass, segtax and domain but different segIds, merge header and req.user.data", + args: args{ + httpReq: &http.Request{ + Header: http.Header{ + "Sec-Browsing-Topics": []string{"(1);v=chrome.1:1:2, (2);v=chrome.1:1:2, ();p=P0000000000"}, + }, + }, + r: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{ + User: &openrtb2.User{ + Data: []openrtb2.Data{ + { + Name: "TOPICS_DOMAIN", + Segment: []openrtb2.Segment{ + { + ID: "3", + }, + { + ID: "4", + }, + }, + Ext: json.RawMessage(`{"segtax": 600, "segclass": "2"}`), + }, + }, + }, + }, + }, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, + }, + wantUser: &openrtb2.User{ + Data: []openrtb2.Data{ + { + Name: "TOPICS_DOMAIN", + Segment: []openrtb2.Segment{ + { + ID: "1", + }, + { + ID: "2", + }, + { + ID: "3", + }, + { + ID: "4", + }, + }, + Ext: json.RawMessage(`{"segtax": 600, "segclass": "2"}`), + }, + }, + }, + }, + { + name: "Sec-Browsing-Topics with two fields both matching segtax and segclass and different segIds, request.user.data with invalid segclass, add header data to req.user.data, keep invalid req.user.data as is", + args: args{ + httpReq: &http.Request{ + Header: http.Header{ + "Sec-Browsing-Topics": []string{"(1);v=chrome.1:1:2, (2);v=chrome.1:1:2, ();p=P0000000000"}, + }, + }, + r: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{ + User: &openrtb2.User{ + Data: []openrtb2.Data{ + { + Name: "TOPICS_DOMAIN", + Segment: []openrtb2.Segment{ + { + ID: "3", + }, + { + ID: "4", + }, + }, + Ext: json.RawMessage(`{"segtax": 0, "segclass": "0"}`), + }, + }, + }, + }, + }, + cfg: &config.Configuration{Auction: config.Auction{PrivacySandbox: config.PrivacySandbox{TopicsDomain: "TOPICS_DOMAIN"}}}, + }, + wantUser: &openrtb2.User{ + Data: []openrtb2.Data{ + { + Name: "TOPICS_DOMAIN", + Segment: []openrtb2.Segment{ + { + ID: "3", + }, + { + ID: "4", + }, + }, + Ext: json.RawMessage(`{"segtax": 0, "segclass": "0"}`), + }, + + { + Name: "TOPICS_DOMAIN", + Segment: []openrtb2.Segment{ + { + ID: "1", + }, + { + ID: "2", + }, + }, + Ext: json.RawMessage(`{"segtax": 600, "segclass": "2"}`), + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - setSecBrowsingTopcisImplicitly(tt.args.httpReq, tt.args.r) + setSecBrowsingTopcisImplicitly(tt.args.httpReq, tt.args.r, tt.args.cfg) // sequence is not garunteed in request.user.data as we're using a map if tt.wantUser.Data != nil {