From b4a4a3f4ba9ffddf91d2b3a8fd0d43b9f4534733 Mon Sep 17 00:00:00 2001 From: harribey Date: Tue, 15 Oct 2024 14:26:04 +0200 Subject: [PATCH 01/11] adapter mediasquare init --- adapters/mediasquare/mediasquare.go | 118 +++++++++ adapters/mediasquare/mediasquare_test.go | 136 ++++++++++ adapters/mediasquare/openrtb.json | 138 ++++++++++ adapters/mediasquare/parsers.go | 86 +++++++ adapters/mediasquare/parsers_test.go | 175 +++++++++++++ adapters/mediasquare/structs.go | 308 +++++++++++++++++++++++ adapters/mediasquare/structs_test.go | 175 +++++++++++++ adapters/mediasquare/utils.go | 101 ++++++++ adapters/mediasquare/utils_test.go | 163 ++++++++++++ exchange/adapter_builders.go | 2 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_mediasquare.go | 6 + static/bidder-info/mediasquare.yaml | 12 + static/bidder-params/mediasquare.json | 19 ++ 14 files changed, 1441 insertions(+) create mode 100644 adapters/mediasquare/mediasquare.go create mode 100644 adapters/mediasquare/mediasquare_test.go create mode 100644 adapters/mediasquare/openrtb.json create mode 100644 adapters/mediasquare/parsers.go create mode 100644 adapters/mediasquare/parsers_test.go create mode 100644 adapters/mediasquare/structs.go create mode 100644 adapters/mediasquare/structs_test.go create mode 100644 adapters/mediasquare/utils.go create mode 100644 adapters/mediasquare/utils_test.go create mode 100644 openrtb_ext/imp_mediasquare.go create mode 100644 static/bidder-info/mediasquare.yaml create mode 100644 static/bidder-params/mediasquare.json diff --git a/adapters/mediasquare/mediasquare.go b/adapters/mediasquare/mediasquare.go new file mode 100644 index 00000000000..1e909a948a5 --- /dev/null +++ b/adapters/mediasquare/mediasquare.go @@ -0,0 +1,118 @@ +package mediasquare + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v2/adapters" + "github.com/prebid/prebid-server/v2/config" + "github.com/prebid/prebid-server/v2/errortypes" + "github.com/prebid/prebid-server/v2/openrtb_ext" +) + +type adapter struct { + endpoint string +} + +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { + return &adapter{ + endpoint: config.Endpoint, + }, nil +} + +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + var ( + requestData []*adapters.RequestData + errs []error + ) + if request == nil { + errs = append(errs, errorWritter(" request", nil, true)) + return nil, errs + } + + msqParams := initMsqParams(request) + for _, imp := range request.Imp { + var ( + bidderExt adapters.ExtImpBidder + msqExt openrtb_ext.ImpExtMediasquare + currentCode = MsqParametersCodes{ + AdUnit: imp.TagID, + AuctionId: request.ID, + BidId: imp.ID, + } + ) + + if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { + errs = append(errs, errorWritter(" imp[ext]", err, len(imp.Ext) == 0)) + continue + } + if err := json.Unmarshal(bidderExt.Bidder, &msqExt); err != nil { + errs = append(errs, errorWritter(" imp-bidder[ext]", err, len(bidderExt.Bidder) == 0)) + continue + } + currentCode.Owner = msqExt.Owner + currentCode.Code = msqExt.Code + + if ok := currentCode.setContent(imp); ok { + msqParams.Codes = append(msqParams.Codes, currentCode) + } + } + + req, err := a.makeRequest(request, &msqParams) + if err != nil { + errs = append(errs, err) + } else if req != nil { + requestData = append(requestData, req) + } + return requestData, errs +} + +func (a *adapter) makeRequest(request *openrtb2.BidRequest, msqParams *MsqParameters) (requestData *adapters.RequestData, err error) { + var requestJsonBytes []byte + if msqParams == nil { + err = errorWritter(" msqParams", nil, true) + return + } + if requestJsonBytes, err = json.Marshal(*msqParams); err == nil { + var headers http.Header = headerList + requestData = &adapters.RequestData{ + Method: "POST", + Uri: a.endpoint, + Body: requestJsonBytes, + Headers: headers, + ImpIDs: openrtb_ext.GetImpIDs(request.Imp), + } + } else { + err = errorWritter(" json.Marshal", err, false) + } + return +} + +func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { + var ( + bidderResponse *adapters.BidderResponse + errs []error + ) + if response.StatusCode != http.StatusOK { + switch response.StatusCode { + case http.StatusBadRequest: + errs = []error{&errortypes.BadInput{Message: fmt.Sprintf(" Unexpected status code: %d.", response.StatusCode)}} + default: + errs = []error{&errortypes.BadServerResponse{ + Message: fmt.Sprintf(" Unexpected status code: %d. Run with request.debug = 1 for more info.", response.StatusCode), + }} + } + return bidderResponse, errs + } + + var msqResponse MsqResponse + if err := json.Unmarshal(response.Body, &msqResponse); err != nil { + errs = []error{&errortypes.BadServerResponse{Message: fmt.Sprintf(" Bad server response: %s.", err.Error())}} + return bidderResponse, errs + } + bidderResponse = adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) + msqResponse.getContent(bidderResponse) + return bidderResponse, errs +} diff --git a/adapters/mediasquare/mediasquare_test.go b/adapters/mediasquare/mediasquare_test.go new file mode 100644 index 00000000000..6c911775dcf --- /dev/null +++ b/adapters/mediasquare/mediasquare_test.go @@ -0,0 +1,136 @@ +package mediasquare + +import ( + "encoding/json" + "errors" + "fmt" + "net/http" + "testing" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v2/adapters" + "github.com/prebid/prebid-server/v2/config" + "github.com/prebid/prebid-server/v2/errortypes" + "github.com/stretchr/testify/assert" +) + +func TestMakeBids(t *testing.T) { + a, _ := Builder("mediasquare", config.Adapter{}, config.Server{}) + tests := []struct { + // tests inputs + request *openrtb2.BidRequest + requestData *adapters.RequestData + // tests expected-results + response *adapters.ResponseData + bidderResponse *adapters.BidderResponse + errs []error + }{ + { + request: &openrtb2.BidRequest{}, + requestData: &adapters.RequestData{}, + + response: &adapters.ResponseData{StatusCode: http.StatusBadRequest}, + bidderResponse: nil, + errs: []error{&errortypes.BadInput{ + Message: fmt.Sprintf(" Unexpected status code: %d.", http.StatusBadRequest), + }}, + }, + { + request: &openrtb2.BidRequest{}, + requestData: &adapters.RequestData{}, + + response: &adapters.ResponseData{StatusCode: 42}, + bidderResponse: nil, + errs: []error{&errortypes.BadServerResponse{ + Message: fmt.Sprintf(" Unexpected status code: %d. Run with request.debug = 1 for more info.", 42), + }}, + }, + { + request: &openrtb2.BidRequest{}, + requestData: &adapters.RequestData{}, + + response: &adapters.ResponseData{StatusCode: http.StatusOK, Body: []byte("")}, + bidderResponse: nil, + errs: []error{&errortypes.BadServerResponse{ + Message: fmt.Sprint(" Bad server response: unexpected end of JSON input."), + }}, + }, + { + request: &openrtb2.BidRequest{Imp: []openrtb2.Imp{{ID: "1"}, {ID: "2"}, {ID: "3"}}}, + requestData: &adapters.RequestData{}, + + response: &adapters.ResponseData{StatusCode: http.StatusOK, Body: []byte(`{"id":"id-ok"}`)}, + bidderResponse: &adapters.BidderResponse{ + Currency: "USD", + Bids: []*adapters.TypedBid{}, + FledgeAuctionConfigs: nil, + }, + errs: nil, + }, + } + + for index, test := range tests { + resp, errs := a.MakeBids(test.request, test.requestData, test.response) + + errsVal, _ := json.Marshal(errs) + errsExp, _ := json.Marshal(test.errs) + assert.Equal(t, test.bidderResponse, resp, fmt.Sprintf("resp >> index: %d", index)) + assert.Equal(t, errsExp, errsVal, fmt.Sprintf("errs >> index: %d", index)) + } +} + +func TestMakeRequest(t *testing.T) { + a, _ := Builder("mediasquare", config.Adapter{Endpoint: "edp-mediasquare"}, config.Server{}) + tests := []struct { + // tests inputs + request *openrtb2.BidRequest + reqInfo *adapters.ExtraRequestInfo + // tests expected-results + result []*adapters.RequestData + errs []error + }{ + { + request: &openrtb2.BidRequest{ID: "id-ok", + Imp: []openrtb2.Imp{ + {ID: "0"}, + {ID: "1", Ext: []byte(`{"id-1":"content-1"}`)}, + {ID: "-42", Ext: []byte(`{"prebid":-42}`)}, + {ID: "-1", Ext: []byte(`{"bidder":{}}`)}, + {ID: "-0", Ext: []byte(`{"bidder":{"owner":"owner-ok","code":0}}`), Native: &openrtb2.Native{}}, + {ID: "42", Ext: []byte(`{"bidder":{"owner":"owner-ok","code":"code-ok"}}`), Native: &openrtb2.Native{}}, + }, + }, + reqInfo: &adapters.ExtraRequestInfo{GlobalPrivacyControlHeader: "global-ok"}, + + result: []*adapters.RequestData{ + {Method: "POST", Uri: "edp-mediasquare", Headers: headerList, ImpIDs: []string{"0", "1", "-42", "-1", "-0", "42"}, + Body: []byte(`{"codes":[{"adunit":"","auctionid":"id-ok","bidid":"42","code":"code-ok","owner":"owner-ok","mediatypes":{"banner":null,"video":null,"native":{"title":null,"icon":null,"image":null,"clickUrl":null,"displayUrl":null,"privacyLink":null,"privacyIcon":null,"cta":null,"rating":null,"downloads":null,"likes":null,"price":null,"saleprice":null,"address":null,"phone":null,"body":null,"body2":null,"sponsoredBy":null,"sizes":null,"type":"native"}},"floor":{"*":{}}}],"gdpr":{"consent_required":false,"consent_string":""},"type":"pbs","dsa":"","tech":{"device":null,"app":null}}`)}, + }, + errs: []error{ + errors.New(" imp[ext]: is empty."), + errors.New(" imp-bidder[ext]: is empty."), + errors.New(" imp[ext]: json: cannot unmarshal number into Go struct field ExtImpBidder.prebid of type openrtb_ext.ExtImpPrebid"), + errors.New(" imp-bidder[ext]: json: cannot unmarshal number into Go struct field ImpExtMediasquare.code of type string"), + }, + }, + } + for index, test := range tests { + result, errs := a.MakeRequests(test.request, test.reqInfo) + + resultBytes, _ := json.Marshal(result) + expectedBytes, _ := json.Marshal(test.result) + assert.Equal(t, string(expectedBytes), string(resultBytes), fmt.Sprintf("result >> index: %d.", index)) + assert.Equal(t, test.errs, errs, fmt.Sprintf("errs >> index: %d.", index)) + } + + // test reference : []error on empty request. + _, errs := a.MakeRequests(nil, nil) + assert.Equal(t, []error{errorWritter(" request", nil, true)}, errs, "[]error") + + var msqAdapter adapter + _, errNil := msqAdapter.makeRequest(nil, nil) + assert.Equal(t, errorWritter(" msqParams", nil, true), errNil, "error errNil") + _, errChan := msqAdapter.makeRequest(nil, &MsqParameters{DSA: make(chan int)}) + assert.Equal(t, errorWritter(" json.Marshal", errors.New("json: unsupported type: chan int"), false), errChan, "error errChan") + +} diff --git a/adapters/mediasquare/openrtb.json b/adapters/mediasquare/openrtb.json new file mode 100644 index 00000000000..38fac739929 --- /dev/null +++ b/adapters/mediasquare/openrtb.json @@ -0,0 +1,138 @@ +{ + "device": { + "ip": "92.154.6.151", + "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36", + "language": "fr", + "geo": { + "country": "FRA", + "ipservice": 3 + } + }, + "ext": { + "prebid": { + "aliases": { + "Magnite": "rubicon", + "msqClassic": "appnexus", + "msqMediagrid": "grid" + }, + "bidadjustmentfactors": { + "msqClassic": 0.8, + "msqMediagrid": 0.8 + }, + "targeting": { + "pricegranularity": {} + }, + "debug": true, + "schains": [ + { + "bidders": ["*"], + "schain": { + "ver": "1.0", + "complete": 1, + "nodes": [ + { + "asi": "mediasquare.fr", + "sid": "1", + "hp": 1 + } + ] + } + }, + { + "bidders": ["msqClassic"], + "schain": { + "ver": "1.0", + "complete": 1, + "nodes": [ + { + "asi": "mediasquare.fr", + "sid": "68", + "hp": 1 + } + ] + } + } + ], + "channel": { + "name": "pbjs", + "version": "9.16.0-pre" + } + } + }, + "id": "70e5672c-515b-406e-967c-fcc2b04de04f", + "imp": [ + { + "banner": { + "format": [ + { + "w": 970, + "h": 250 + } + ], + "pos": 1 + }, + "ext": { + "mediasquare": { + "owner": "owner42", + "code": "code42" + } + }, + "id": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "secure": 1, + "bidfloor": 1, + "bidfloorcur": "USD" + }, + { + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + }, + { + "w": 120, + "h": 600 + } + ], + "pos": 1 + }, + "ext": { + "mediasquare": { + "owner": "owner-42", + "code": "code-42" + } + }, + "id": "2059a3e6-71a3-43ea-8290-b5ceb13d35a8", + "secure": 1, + "bidfloor": 0.01, + "bidfloorcur": "USD" + } + ], + "regs": { + "gdpr": 1, + "ext": { + "gdpr": 1 + } + }, + "site": { + "page": "https://debug.mediasquare.fr/debug/prebid/msq_desktop.html?pbjs_debug=true", + "publisher": { + "id": "MEDIA_SQUARE" + }, + "name": "debug.mediasquare.fr", + "domain": "debug.mediasquare.fr", + "content": {} + }, + "tmax": 1300, + "user": { + "consent": "CQF9-AAQF9-AAAKA1AENDgCsAP_AAEPAAAqIg1NX_H__bW9r8X7_aft0eY1P9_j77sQxBhfJE-4F3LvW_JwXx2E5NF36tqoKmRoEu3ZBIUNlHJHUTVmwaogVryHsakWcoTNKJ6BkkFMRM2dYCF5vm4tjeQKY5_p_d3fx2D-t_dv839zzz8VHn3e5fue0-PCdU5-9Dfn9fRfb-9IP9_78v8v8_l_rk2_eT13_pcvr_D--f_87_XW-9_cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQagCzDQuIAuyJCQm0DCKBACIKwgIoEAAAAJA0QEALgwKdgYBLrCRACBFAAcEAIQAUZAAgAAEgAQiACQIoEAAEAgEAAIAEAgEADAwADgAtBAIAAQHQMUwoAFAsIEiMiIUwIQoEggJbKBBKCoQVwgCLDAigERsFAAgCQEVgACAsXgMASAlYkECXUG0AABAAgFFKFQik_MAQ4Jmy1V4om0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAACAA.f_gAAAAAAAAA", + "ext": { + "consent": "CQF9-AAQF9-AAAKA1AENDgCsAP_AAEPAAAqIg1NX_H__bW9r8X7_aft0eY1P9_j77sQxBhfJE-4F3LvW_JwXx2E5NF36tqoKmRoEu3ZBIUNlHJHUTVmwaogVryHsakWcoTNKJ6BkkFMRM2dYCF5vm4tjeQKY5_p_d3fx2D-t_dv839zzz8VHn3e5fue0-PCdU5-9Dfn9fRfb-9IP9_78v8v8_l_rk2_eT13_pcvr_D--f_87_XW-9_cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQagCzDQuIAuyJCQm0DCKBACIKwgIoEAAAAJA0QEALgwKdgYBLrCRACBFAAcEAIQAUZAAgAAEgAQiACQIoEAAEAgEAAIAEAgEADAwADgAtBAIAAQHQMUwoAFAsIEiMiIUwIQoEggJbKBBKCoQVwgCLDAigERsFAAgCQEVgACAsXgMASAlYkECXUG0AABAAgFFKFQik_MAQ4Jmy1V4om0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAACAA.f_gAAAAAAAAA" + } + }, + "cur": ["USD"] +} diff --git a/adapters/mediasquare/parsers.go b/adapters/mediasquare/parsers.go new file mode 100644 index 00000000000..94b86996ca0 --- /dev/null +++ b/adapters/mediasquare/parsers.go @@ -0,0 +1,86 @@ +package mediasquare + +import ( + "encoding/json" + "fmt" + + "github.com/prebid/openrtb/v20/openrtb2" +) + +// parserDSA: Struct used to extracts dsa content of a json. +type parserDSA struct { + DSA interface{} `json:"dsa,omitempty"` +} + +// setContent: Unmarshal a []byte into the parserDSA struct. +func (parser *parserDSA) setContent(extJsonBytes []byte) error { + if len(extJsonBytes) > 0 { + if err := json.Unmarshal(extJsonBytes, parser); err != nil { + return errorWritter(" extJsonBytes", err, false) + } + return nil + } + return errorWritter(" extJsonBytes", nil, true) +} + +// getValue: Returns the DSA value as a string, defaultly returns empty-string. +func (parser parserDSA) getValue(request *openrtb2.BidRequest) string { + if request == nil || request.Regs == nil { + return "" + } + parser.setContent(request.Regs.Ext) + if parser.DSA != nil { + return fmt.Sprint(parser.DSA) + } + return "" +} + +// parserGDPR: Struct used to extract pair of GDPR/Consent of a json. +type parserGDPR struct { + GDPR interface{} `json:"gdpr,omitempty"` + Consent interface{} `json:"consent,omitempty"` +} + +// setContent: Unmarshal a []byte into the parserGDPR struct. +func (parser *parserGDPR) setContent(extJsonBytes []byte) error { + if len(extJsonBytes) > 0 { + if err := json.Unmarshal(extJsonBytes, parser); err != nil { + return errorWritter(" extJsonBytes", err, false) + } + return nil + } + return errorWritter(" extJsonBytes", nil, true) +} + +// value: Returns the consent or GDPR-string depending of the parserGDPR content, defaulty return empty-string. +func (parser *parserGDPR) value() string { + switch { + case parser.Consent != nil: + return fmt.Sprint(parser.Consent) + case parser.GDPR != nil: + return fmt.Sprint(parser.GDPR) + } + return "" +} + +// getValue: Returns the consent or GDPR-string depending on the openrtb2.User content, defaultly returns empty-string. +func (parser parserGDPR) getValue(field string, request *openrtb2.BidRequest) string { + if request == nil { + return "" + } + switch { + case field == "consent_requirement" && request.Regs != nil: + if ptrInt8ToBool(request.Regs.GDPR) { + return "true" + } + return "false" + case field == "consent_string" && request.User != nil: + if len(request.User.Consent) > 0 { + return request.User.Consent + } + parser.setContent(request.User.Ext) + return parser.value() + default: + return "" + } +} diff --git a/adapters/mediasquare/parsers_test.go b/adapters/mediasquare/parsers_test.go new file mode 100644 index 00000000000..dee536cd8a4 --- /dev/null +++ b/adapters/mediasquare/parsers_test.go @@ -0,0 +1,175 @@ +package mediasquare + +import ( + "encoding/json" + "errors" + "fmt" + "testing" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/stretchr/testify/assert" +) + +func TestParserDSA(t *testing.T) { + tests := []struct { + // tests inputs + parser parserDSA + request openrtb2.BidRequest + // tests expected-results + getValue string + setContent error + expected parserDSA + }{ + { + parser: parserDSA{}, + request: openrtb2.BidRequest{ + Regs: &openrtb2.Regs{ + Ext: []byte(`{"dsa":"dsa-ok"}`), + }, + }, + + getValue: "dsa-ok", + setContent: nil, + expected: parserDSA{DSA: "dsa-ok"}, + }, + { + parser: parserDSA{}, + request: openrtb2.BidRequest{ + Regs: &openrtb2.Regs{ + Ext: []byte(`{"no-dsa":"no-dsa"}`), + }, + }, + + getValue: "", + setContent: nil, + expected: parserDSA{}, + }, + { + parser: parserDSA{}, + request: openrtb2.BidRequest{ + Regs: &openrtb2.Regs{ + Ext: []byte(``), + }, + }, + + getValue: "", + setContent: errorWritter(" extJsonBytes", nil, true), + expected: parserDSA{}, + }, + } + for index, test := range tests { + assert.Equal(t, test.getValue, test.parser.getValue(&test.request), fmt.Sprintf("getValue >> index: %d", index)) + assert.Equal(t, test.setContent, test.parser.setContent(test.request.Regs.Ext), fmt.Sprintf("setContent >> index: %d", index)) + assert.Equal(t, test.expected, test.parser, fmt.Sprintf("exactValue >> index: %d", index)) + } + + var pError parserDSA + assert.Equal(t, pError.setContent([]byte(`{invalid json}`)), + errorWritter(" extJsonBytes", errors.New("invalid character 'i' looking for beginning of object key string"), false)) +} + +func TestParserGDPR(t *testing.T) { + tests := []struct { + //tests inputs + parser parserGDPR + request openrtb2.BidRequest + extJsonBytes []byte + // tests expected-results + getValue struct { + field string + value string + } + setContent error + value string + }{ + { + parser: parserGDPR{}, + request: openrtb2.BidRequest{User: &openrtb2.User{Ext: json.RawMessage(`{"gdpr":"gdpr-ok-user"}`)}}, + extJsonBytes: []byte(`{"gdpr":"gdpr-ok-extjson"}`), + + getValue: struct { + field string + value string + }{field: "consent_string", value: "gdpr-ok-user"}, + setContent: nil, + value: "gdpr-ok-extjson", + }, + { + parser: parserGDPR{}, + request: openrtb2.BidRequest{User: &openrtb2.User{Consent: "consent-ok-user"}}, + extJsonBytes: []byte(`{"gdpr":"gdpr-ok","consent":"consent-ok"}`), + + getValue: struct { + field string + value string + }{field: "consent_string", value: "consent-ok-user"}, + setContent: nil, + value: "consent-ok", + }, + { + parser: parserGDPR{}, + request: openrtb2.BidRequest{}, + extJsonBytes: []byte(""), + + getValue: struct { + field string + value string + }{field: "consent_string", value: ""}, + setContent: errorWritter(" extJsonBytes", nil, true), + value: "", + }, + { + parser: parserGDPR{}, + request: openrtb2.BidRequest{Regs: &openrtb2.Regs{GDPR: IntAsPtrInt8(0)}}, + extJsonBytes: []byte(""), + + getValue: struct { + field string + value string + }{field: "consent_requirement", value: "false"}, + setContent: nil, + value: "", + }, + { + parser: parserGDPR{}, + request: openrtb2.BidRequest{Regs: &openrtb2.Regs{GDPR: IntAsPtrInt8(1)}}, + extJsonBytes: []byte(""), + + getValue: struct { + field string + value string + }{field: "consent_requirement", value: "true"}, + setContent: nil, + value: "", + }, + { + parser: parserGDPR{}, + getValue: struct { + field string + value string + }{field: "null", value: ""}, + }, + } + + for index, test := range tests { + switch test.getValue.field { + case "consent_string": + assert.Equal(t, test.getValue.value, test.parser.getValue("consent_string", &(test.request)), fmt.Sprintf("[consent_string]: getValue >> index: %d", index)) + assert.Equal(t, test.setContent, test.parser.setContent(test.extJsonBytes), fmt.Sprintf("setContent >> index: %d", index)) + assert.Equal(t, test.value, test.parser.value(), fmt.Sprintf("value >> index: %d", index)) + case "consent_requirement": + assert.Equal(t, test.getValue.value, test.parser.getValue("consent_requirement", &(test.request)), fmt.Sprintf("[consent_requirement]: getValue >> index: %d", index)) + case "null": + assert.Equal(t, test.getValue.value, test.parser.getValue("null", nil), fmt.Sprintf("[consent_requirement]: getValue >> index: %d", index)) + } + } + + var pError parserGDPR + assert.Equal(t, pError.setContent([]byte(`{invalid json}`)), + errorWritter(" extJsonBytes", errors.New("invalid character 'i' looking for beginning of object key string"), false)) +} + +func IntAsPtrInt8(i int) *int8 { + val := int8(i) + return &val +} diff --git a/adapters/mediasquare/structs.go b/adapters/mediasquare/structs.go new file mode 100644 index 00000000000..79786d431ea --- /dev/null +++ b/adapters/mediasquare/structs.go @@ -0,0 +1,308 @@ +package mediasquare + +import ( + "encoding/json" + "fmt" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v2/adapters" + "github.com/prebid/prebid-server/v2/openrtb_ext" +) + +// MsqResponse: Bid-Response sent by Mediasquare. +type MsqResponse struct { + Infos struct { + Version string `json:"version"` + Description string `json:"description"` + Hostname string `json:"hostname,omitempty"` + } `json:"infos"` + Responses []MsqResponseBids `json:"responses"` +} + +// MsqParameters: Bid-Request sent to Mediasquare. +type MsqParameters struct { + Codes []MsqParametersCodes `json:"codes"` + Gdpr struct { + ConsentRequired bool `json:"consent_required"` + ConsentString string `json:"consent_string"` + } `json:"gdpr"` + Type string `json:"type"` + DSA interface{} `json:"dsa,omitempty"` + Support MsqSupport `json:"tech"` +} + +type MsqResponseBidsVideo struct { + Xml string `json:"xml"` + Url string `json:"url"` +} + +type NativeResponseImg struct { + Url string `json:"url"` + Width *int `json:"width,omitempty"` + Height *int `json:"height,omitempty"` +} + +type MsqResponseBidsNative struct { + ClickUrl string `json:"clickUrl,omitempty"` + ClickTrackers []string `json:"clickTrackers,omitempty"` + ImpressionTrackers []string `json:"impressionTrackers,omitempty"` + JavascriptTrackers []string `json:"javascriptTrackers,omitempty"` + Privacy *string `json:"privacy,omitempty"` + Title *string `json:"title,omitempty"` + Icon *NativeResponseImg `json:"icon,omitempty"` + Image *NativeResponseImg `json:"image,omitempty"` + Cta *string `json:"cta,omitempty"` + Rating *string `json:"rating,omitempty"` + Downloads *string `json:"downloads,omitempty"` + Likes *string `json:"likes,omitempty"` + Price *string `json:"price,omitempty"` + SalePrice *string `json:"saleprice,omitempty"` + Address *string `json:"address,omitempty"` + Phone *string `json:"phone,omitempty"` + Body *string `json:"body,omitempty"` + Body2 *string `json:"body2,omitempty"` + SponsoredBy *string `json:"sponsoredBy,omitempty"` + DisplayUrl *string `json:"displayUrl,omitempty"` +} + +type MsqResponseBids struct { + ID string `json:"id"` + Ad string `json:"ad,omitempty"` + BidId string `json:"bid_id,omitempty"` + Bidder string `json:"bidder,omitempty"` + //Code string `json:"code,omitempty"` + Cpm float64 `json:"cpm,omitempty"` + //Increment float32 `json:"increment"` + Currency string `json:"currency,omitempty"` + CreativeId string `json:"creative_id,omitempty"` + Height int64 `json:"height,omitempty"` + Width int64 `json:"width,omitempty"` + NetRevenue bool `json:"net_revenue,omitempty"` + TransactionId string `json:"transaction_id,omitempty"` + Ttl int `json:"ttl,omitempty"` + Video *MsqResponseBidsVideo `json:"video,omitempty"` + Native *MsqResponseBidsNative `json:"native,omitempty"` + //Amp *MsqResponseBidsAmp `json:"targeting,omitempty"` + ADomain []string `json:"adomain,omitempty"` + //HasConsent bool `json:"hasConsent,omitempty"` + //Context string `json:"context,omitempty"` + //Ova string `json:"ova,omitempty"` + Dsa interface{} `json:"dsa,omitempty"` + //Match string `json:"match,omitempty"` + BURL string `json:"burl,omitempty"` +} + +type MsqSupport struct { + Device interface{} `json:"device"` + App interface{} `json:"app"` +} + +type MsqParametersCodes struct { + AdUnit string `json:"adunit"` + AuctionId string `json:"auctionid"` + BidId string `json:"bidid"` + Code string `json:"code"` + Owner string `json:"owner"` + Mediatypes MediaTypes `json:"mediatypes,omitempty"` + Floor map[string]MsqFloor `json:"floor,omitempty"` +} + +type MsqFloor struct { + Price float64 `json:"floor,omitempty"` + Currency string `json:"currency,omitempty"` +} + +type MediaTypeNativeBasis struct { + Required bool + Len *int +} + +type MediaTypeNativeImage struct { + Required bool + Sizes []*int + Aspect_ratio *struct { + Min_width *int + Min_height *int + Ratio_width *int + Ratio_height *int + } +} + +type MediaTypeNativeTitle struct { + Required bool + Len int +} + +type MediaTypeNative struct { + Title *MediaTypeNativeTitle `json:"title"` + Icon *MediaTypeNativeImage `json:"icon"` + Image *MediaTypeNativeImage `json:"image"` + Clickurl *MediaTypeNativeBasis `json:"clickUrl"` + Displayurl *MediaTypeNativeBasis `json:"displayUrl"` + Privacylink *MediaTypeNativeBasis `json:"privacyLink"` + Privacyicon *MediaTypeNativeBasis `json:"privacyIcon"` + Cta *MediaTypeNativeBasis `json:"cta"` + Rating *MediaTypeNativeBasis `json:"rating"` + Downloads *MediaTypeNativeBasis `json:"downloads"` + Likes *MediaTypeNativeBasis `json:"likes"` + Price *MediaTypeNativeBasis `json:"price"` + Saleprice *MediaTypeNativeBasis `json:"saleprice"` + Address *MediaTypeNativeBasis `json:"address"` + Phone *MediaTypeNativeBasis `json:"phone"` + Body *MediaTypeNativeBasis `json:"body"` + Body2 *MediaTypeNativeBasis `json:"body2"` + Sponsoredby *MediaTypeNativeBasis `json:"sponsoredBy"` + Sizes [][]int `json:"sizes"` + Type string `json:"type"` +} + +type MediaTypeVideo struct { + Mimes []string `json:"mimes"` + Minduration *int `json:"minduration"` + Maxduration *int `json:"maxduration"` + Protocols []*int `json:"protocols"` + Startdelay *int `json:"startdelay"` + Placement *int `json:"placement"` + Skip *int `json:"skip"` + Skipafter *int `json:"skipafter"` + Minbitrate *int `json:"minbitrate"` + Maxbitrate *int `json:"maxbitrate"` + Delivery []*int `json:"delivery"` + Playbackmethod []*int `json:"playbackmethod"` + Api []*int `json:"api"` + Linearity *int `json:"linearity"` + W *int `json:"w"` + H *int `json:"h"` + Boxingallowed *int `json:"boxingallower"` + PlayerSize [][]int `json:"playersize"` + Context string `json:"context"` + Plcmt *int `json:"plcmt,omitempty"` +} + +type MediaTypes struct { + Banner *MediaTypeBanner `json:"banner"` + Video *MediaTypeVideo `json:"video"` + Native *MediaTypeNative `json:"native"` +} + +type MediaTypeBanner struct { + Sizes [][]*int `json:"sizes"` +} + +func initMsqParams(request *openrtb2.BidRequest) (msqParams MsqParameters) { + msqParams.Type = "pbs" + msqParams.Support = MsqSupport{ + Device: request.Device, + App: request.App, + } + msqParams.Gdpr = struct { + ConsentRequired bool `json:"consent_required"` + ConsentString string `json:"consent_string"` + }{ + ConsentRequired: (parserGDPR{}).getValue("consent_requirement", request) == "true", + ConsentString: (parserGDPR{}).getValue("consent_string", request), + } + msqParams.DSA = parserDSA{}.getValue(request) + + return +} + +// setContent: Loads currentImp into msqParams (*MsqParametersCodes), +// returns (errs []error, ok bool) where `ok` express if mandatory content had been loaded. +func (msqParams *MsqParametersCodes) setContent(currentImp openrtb2.Imp) (ok bool) { + var ( + currentMapFloors = make(map[string]MsqFloor, 0) + currentFloor = MsqFloor{ + Price: currentImp.BidFloor, + Currency: currentImp.BidFloorCur, + } + ) + + if currentImp.Video != nil { + ok = true + var video MediaTypeVideo + currentVideoBytes, _ := json.Marshal(currentImp.Video) + json.Unmarshal(currentVideoBytes, &video) + json.Unmarshal(currentImp.Video.Ext, &video) + + msqParams.Mediatypes.Video = &video + if msqParams.Mediatypes.Video != nil { + if currentImp.Video.W != nil && currentImp.Video.H != nil { + currentMapFloors[fmt.Sprintf("%dx%d", *(currentImp.Video.W), *(currentImp.Video.H))] = currentFloor + } + } + currentMapFloors["*"] = currentFloor + } + + if currentImp.Banner != nil { + ok = true + + json.Unmarshal(currentImp.Banner.Ext, msqParams.Mediatypes.Banner) + switch { + case len(currentImp.Banner.Format) > 0: + for _, bannerFormat := range currentImp.Banner.Format { + currentMapFloors[fmt.Sprintf("%dx%d", bannerFormat.W, bannerFormat.H)] = currentFloor + } + case currentImp.Banner.W != nil && currentImp.Banner.H != nil: + currentMapFloors[fmt.Sprintf("%dx%d", *(currentImp.Banner.W), *(currentImp.Banner.H))] = currentFloor + } + + if msqParams.Mediatypes.Banner != nil { + for _, bannerSizes := range msqParams.Mediatypes.Banner.Sizes { + if len(bannerSizes) == 2 && bannerSizes[0] != nil && bannerSizes[1] != nil { + currentMapFloors[fmt.Sprintf("%dx%d", *(bannerSizes[0]), *(bannerSizes[1]))] = currentFloor + } + } + } + } + + if currentImp.Native != nil { + ok = true + var native = MediaTypeNative{Type: "native"} + json.Unmarshal(currentImp.Native.Ext, &native) + + msqParams.Mediatypes.Native = &native + for _, nativeSizes := range msqParams.Mediatypes.Native.Sizes { + if len(nativeSizes) == 2 { + currentMapFloors[fmt.Sprintf("%dx%d", nativeSizes[0], nativeSizes[1])] = currentFloor + } + } + currentMapFloors["*"] = currentFloor + } + + if len(currentMapFloors) > 0 { + msqParams.Floor = currentMapFloors + } + return +} + +// getContent: Loads msqResp content into the bidderResponse (*adapters.BidderResponse). +func (msqResp *MsqResponse) getContent(bidderResponse *adapters.BidderResponse) { + var tmpBids []*adapters.TypedBid + for _, resp := range msqResp.Responses { + tmpTBid := adapters.TypedBid{ + BidType: resp.bidType(), + Seat: openrtb_ext.BidderName(resp.Bidder), + Bid: &openrtb2.Bid{ + ID: resp.ID, + ImpID: resp.BidId, + Price: resp.Cpm, + AdM: resp.Ad, + ADomain: resp.ADomain, + W: resp.Width, + H: resp.Height, + CrID: resp.CreativeId, + MType: resp.mType(), + BURL: resp.BURL, + Ext: resp.extBid(), + }, + BidMeta: resp.extBidPrebidMeta(), + } + tmpBids = append(tmpBids, &tmpTBid) + bidderResponse.Currency = resp.Currency + } + + if len(tmpBids) > 0 { + bidderResponse.Bids = tmpBids + } +} diff --git a/adapters/mediasquare/structs_test.go b/adapters/mediasquare/structs_test.go new file mode 100644 index 00000000000..48a89bf6231 --- /dev/null +++ b/adapters/mediasquare/structs_test.go @@ -0,0 +1,175 @@ +package mediasquare + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v2/adapters" + "github.com/prebid/prebid-server/v2/openrtb_ext" + "github.com/stretchr/testify/assert" +) + +func TestGetContent(t *testing.T) { + tests := []struct { + resp MsqResponse + value adapters.BidderResponse + expected adapters.BidderResponse + }{ + { + resp: MsqResponse{}, + value: adapters.BidderResponse{Currency: ""}, + expected: adapters.BidderResponse{Currency: ""}, + }, + { + resp: MsqResponse{ + Responses: []MsqResponseBids{ + { + ID: "id-ok", + Ad: "ad-ok", + Cpm: 42.0, + Currency: "currency-ok", + Width: 42, + Height: 42, + Bidder: "bidder-ok", + }, + }, + }, + value: adapters.BidderResponse{Currency: ""}, + expected: adapters.BidderResponse{ + Currency: "currency-ok", + Bids: []*adapters.TypedBid{ + { + Bid: &openrtb2.Bid{ + AdM: "ad-ok", + ID: "id-ok", + Price: 42.0, + W: 42, + H: 42, + MType: openrtb2.MarkupBanner, + }, + BidMeta: &openrtb_ext.ExtBidPrebidMeta{MediaType: "banner"}, + BidType: "banner", + Seat: "bidder-ok", + }, + }, + }, + }, + } + + for index, test := range tests { + test.resp.getContent(&test.value) + expectedBytes, _ := json.Marshal(test.expected) + valueBytes, _ := json.Marshal(test.value) + assert.Equal(t, expectedBytes, valueBytes, + fmt.Sprintf("getContent >> index: %d\nexpect:%s\nvalue:%s", index, string(expectedBytes), string(valueBytes))) + } +} + +func TestSetContent(t *testing.T) { + tests := []struct { + // tests inputs + params MsqParametersCodes + imp openrtb2.Imp + // tests expected-results + ok bool + }{ + { + params: MsqParametersCodes{}, + imp: openrtb2.Imp{}, + ok: false, + }, + { + params: MsqParametersCodes{ + AdUnit: "adunit-ok", + AuctionId: "auctionid-ok", + Code: "code-ok", + BidId: "bidid-ok", + Mediatypes: MediaTypes{ + Banner: &MediaTypeBanner{Sizes: [][]*int{{intAsPtrInt(1), intAsPtrInt(1)}, {intAsPtrInt(42), intAsPtrInt(42)}}}, + }, + }, + imp: openrtb2.Imp{ + ID: "imp-id", + Banner: &openrtb2.Banner{ + Format: []openrtb2.Format{{W: 1, H: 2}, {W: 2, H: 1}}, + Ext: json.RawMessage(`{"type":"raw-message-id"}`), + }, + BidFloor: 0.8, + }, + ok: true, + }, + { + params: MsqParametersCodes{}, + imp: openrtb2.Imp{ + ID: "imp-id", + Video: &openrtb2.Video{ + MIMEs: []string{"MIMEs-ok"}, + W: intAsPtrInt64(42), H: intAsPtrInt64(42), + Ext: json.RawMessage(`{"h":42,"w":42}`), + }, + BidFloor: 0.8, + }, + ok: true, + }, + { + params: MsqParametersCodes{}, + imp: openrtb2.Imp{ + ID: "imp-id", + Native: &openrtb2.Native{ + Ext: json.RawMessage(`{"sizes":[[42,42],[2,1],[1,1]]}`), + }, + BidFloor: 0.8, + }, + + ok: true, + }, + { + params: MsqParametersCodes{}, + imp: openrtb2.Imp{ + ID: "imp-id", + Banner: &openrtb2.Banner{ + W: intAsPtrInt64(42), + H: intAsPtrInt64(42), + }, + BidFloor: 0.8, + }, + ok: true, + }, + } + + for index, test := range tests { + expected := test.params + + ok := test.params.setContent(test.imp) + assert.Equal(t, test.ok, ok, fmt.Sprintf("ok >> index: %d", index)) + + switch index { + case 1: + expected.Floor = map[string]MsqFloor{"1x1": {Price: 0.8}, "1x2": {Price: 0.8}, "2x1": {Price: 0.8}, "42x42": {Price: 0.8}} + case 2: + expected.Floor = map[string]MsqFloor{"42x42": {Price: 0.8}, "*": {Price: 0.8}} + expected.Mediatypes.Video = &MediaTypeVideo{Mimes: []string{"MIMEs-ok"}, H: intAsPtrInt(42), W: intAsPtrInt(42)} + case 3: + expected.Mediatypes.Native = &MediaTypeNative{Type: "native", Sizes: [][]int{{42, 42}, {2, 1}, {1, 1}}} + expected.Floor = map[string]MsqFloor{"1x1": {Price: 0.8}, "42x42": {Price: 0.8}, "2x1": {Price: 0.8}, "*": {Price: 0.8}} + case 4: + expected.Floor = map[string]MsqFloor{"42x42": {Price: 0.8}} + } + + expectedBytes, _ := json.Marshal(expected) + paramsBytes, _ := json.Marshal(test.params) + assert.Equal(t, string(expectedBytes), string(paramsBytes), fmt.Sprintf("assert >> index: %d", index)) + } +} + +func intAsPtrInt(i int) *int { + val := i + return &val +} + +func intAsPtrInt64(i int64) *int64 { + val := i + return &val +} diff --git a/adapters/mediasquare/utils.go b/adapters/mediasquare/utils.go new file mode 100644 index 00000000000..af65d54f90c --- /dev/null +++ b/adapters/mediasquare/utils.go @@ -0,0 +1,101 @@ +package mediasquare + +import ( + "encoding/json" + "fmt" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v2/openrtb_ext" +) + +var headerList = map[string][]string{ + "Content-Type": {"application/json;charset=utf-8"}, + "Accept": {"application/json"}, +} + +var mediaTypeList = map[openrtb_ext.BidType]openrtb2.MarkupType{ + "banner": openrtb2.MarkupBanner, + "video": openrtb2.MarkupVideo, + "audio": openrtb2.MarkupAudio, + "native": openrtb2.MarkupNative, +} + +// mType: Returns the openrtb2.MarkupType from an MsqResponseBids. +func (msqBids *MsqResponseBids) mType() openrtb2.MarkupType { + switch { + case msqBids.Video != nil: + return mediaTypeList["video"] + case msqBids.Native != nil: + return mediaTypeList["native"] + default: + return mediaTypeList["banner"] + } +} + +// bidType: Returns the openrtb_ext.BidType from an MsqResponseBids. +func (msqBids *MsqResponseBids) bidType() openrtb_ext.BidType { + switch { + case msqBids.Video != nil: + return "video" + case msqBids.Native != nil: + return "native" + default: + return "banner" + } +} + +// extBid: Extracts the ExtBid from msqBids formated as (json.RawMessage). +func (msqBids *MsqResponseBids) extBid() (raw json.RawMessage) { + extBid, _ := msqBids.loadExtBid() + if extBid.DSA != nil || extBid.Prebid != nil { + bb, _ := json.Marshal(extBid) + if len(bb) > 0 { + raw = json.RawMessage(bb) + } + } + return +} + +// loadExtBid: Extracts the ExtBid from msqBids as (openrtb_ext.ExtBid, []error). +func (msqBids *MsqResponseBids) loadExtBid() (extBid openrtb_ext.ExtBid, errs []error) { + if msqBids.Dsa != nil { + bb, err := json.Marshal(msqBids.Dsa) + if err != nil { + errs = append(errs, err) + } + if len(bb) > 0 { + var dsa openrtb_ext.ExtBidDSA + if err = json.Unmarshal(bb, &dsa); err != nil { + errs = append(errs, err) + } else { + extBid.DSA = &dsa + } + } + } + return +} + +// extBidPrebidMeta: Extracts the ExtBidPrebidMeta from msqBids. +func (msqBids *MsqResponseBids) extBidPrebidMeta() *openrtb_ext.ExtBidPrebidMeta { + var extBidMeta openrtb_ext.ExtBidPrebidMeta + if msqBids.ADomain != nil { + extBidMeta.AdvertiserDomains = msqBids.ADomain + } + extBidMeta.MediaType = string(msqBids.bidType()) + return &extBidMeta +} + +// ptrInt8ToBool: Return (TRUE) when i equals 1. +func ptrInt8ToBool(i *int8) bool { + if i != nil { + return (*i == int8(1)) + } + return false +} + +func errorWritter(referer string, err error, isEmpty bool) error { + if isEmpty { + return fmt.Errorf("%s: is empty.", referer) + } + return fmt.Errorf("%s: %s", referer, err.Error()) +} diff --git a/adapters/mediasquare/utils_test.go b/adapters/mediasquare/utils_test.go new file mode 100644 index 00000000000..280597e11fd --- /dev/null +++ b/adapters/mediasquare/utils_test.go @@ -0,0 +1,163 @@ +package mediasquare + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v2/openrtb_ext" + "github.com/stretchr/testify/assert" +) + +func TestPtrInt8ToBool(t *testing.T) { + // map[tests-inputs]test-expected-results + tests := map[int8]bool{ + 0: false, + 1: true, + 42: false, + } + for value, expected := range tests { + assert.Equal(t, expected, ptrInt8ToBool(&value), "ptrInt8ToBool >> value:", value) + } + assert.Equal(t, false, ptrInt8ToBool(nil), "ptrInt8ToBool >> value(nil)") +} + +func TestMethodsType(t *testing.T) { + tests := []struct { + // tests inputs + resp MsqResponseBids + // tests expected-results + bidType openrtb_ext.BidType + mType openrtb2.MarkupType + }{ + { + resp: MsqResponseBids{Native: &MsqResponseBidsNative{ClickUrl: "not-nil"}}, + + bidType: "native", + mType: openrtb2.MarkupNative, + }, + { + resp: MsqResponseBids{Video: &MsqResponseBidsVideo{Xml: "not-nil"}}, + + bidType: "video", + mType: openrtb2.MarkupVideo, + }, + { + resp: MsqResponseBids{ID: "not-nil"}, + + bidType: "banner", + mType: openrtb2.MarkupBanner, + }, + } + for testIndex, test := range tests { + assert.Equal(t, test.bidType, test.resp.bidType(), "bidType >> testIndex:", testIndex) + assert.Equal(t, test.mType, test.resp.mType(), "mType >> testIndex:", testIndex) + } +} + +func TestLoadExtBid(t *testing.T) { + tests := []struct { + // tests inputs + resp MsqResponseBids + // tests expected-results + extBid openrtb_ext.ExtBid + isOk bool + }{ + { + resp: MsqResponseBids{}, + + extBid: openrtb_ext.ExtBid{DSA: nil, Prebid: nil}, + isOk: true, + }, + { + resp: MsqResponseBids{Dsa: openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, + + extBid: openrtb_ext.ExtBid{DSA: &openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, + isOk: true, + }, + { + resp: MsqResponseBids{Dsa: "lol"}, + + extBid: openrtb_ext.ExtBid{}, + isOk: false, + }, + { + resp: MsqResponseBids{Dsa: make(chan int)}, + + extBid: openrtb_ext.ExtBid{}, + isOk: false, + }, + } + + for index, test := range tests { + extBid, errs := test.resp.loadExtBid() + assert.Equal(t, test.extBid.DSA, extBid.DSA, fmt.Sprintf("extBid.DSA >> index: %d", index)) + assert.Equal(t, test.isOk, errs == nil, fmt.Sprintf("isOk >> index: %d", index)) + } +} + +func TestExtBidPrebidMeta(t *testing.T) { + tests := []struct { + // tests inputs + resp MsqResponseBids + // tests expected-results + adomains []string + mediatype string + value openrtb_ext.ExtBidPrebidMeta + }{ + { + resp: MsqResponseBids{ADomain: []string{"test-adomain-0", "test-adomain-1"}}, + + adomains: []string{"test-adomain-0", "test-adomain-1"}, + mediatype: "banner", + value: openrtb_ext.ExtBidPrebidMeta{ + AdvertiserDomains: []string{"test-adomain-0", "test-adomain-1"}, + MediaType: "banner", + }, + }, + { + resp: MsqResponseBids{}, + + adomains: nil, + mediatype: "banner", + value: openrtb_ext.ExtBidPrebidMeta{MediaType: "banner"}, + }, + { + resp: MsqResponseBids{Video: &MsqResponseBidsVideo{Xml: "not-nil"}}, + + adomains: nil, + mediatype: "video", + value: openrtb_ext.ExtBidPrebidMeta{MediaType: "video"}, + }, + } + + for index, test := range tests { + result := test.resp.extBidPrebidMeta() + assert.Equal(t, test.adomains, result.AdvertiserDomains, fmt.Sprintf("ADomains >> index: %d", index)) + assert.Equal(t, test.mediatype, result.MediaType, fmt.Sprintf("MediaType >> index: %d", index)) + assert.Equal(t, test.value, *result, fmt.Sprintf("ExactValue >> index: %d", index)) + } +} + +func TestExtBid(t *testing.T) { + tests := []struct { + // tests inputs + resp MsqResponseBids + // tests expected-results + raw json.RawMessage + }{ + { + resp: MsqResponseBids{Dsa: openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, + raw: json.RawMessage([]byte(`{"dsa":{"behalf":"behalf"}}`)), + }, + { + resp: MsqResponseBids{}, + raw: nil, + }, + } + + for index, test := range tests { + assert.Equal(t, test.raw, test.resp.extBid(), fmt.Sprintf("raw >> index: %d", index)) + } +} diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index b05c048ec7c..e247e5e053d 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -132,6 +132,7 @@ import ( "github.com/prebid/prebid-server/v2/adapters/marsmedia" "github.com/prebid/prebid-server/v2/adapters/mediago" "github.com/prebid/prebid-server/v2/adapters/medianet" + "github.com/prebid/prebid-server/v2/adapters/mediasquare" "github.com/prebid/prebid-server/v2/adapters/melozen" "github.com/prebid/prebid-server/v2/adapters/metax" "github.com/prebid/prebid-server/v2/adapters/mgid" @@ -362,6 +363,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderMediafuse: appnexus.Builder, openrtb_ext.BidderMediaGo: mediago.Builder, openrtb_ext.BidderMedianet: medianet.Builder, + openrtb_ext.BidderMediasquare: mediasquare.Builder, openrtb_ext.BidderMeloZen: melozen.Builder, openrtb_ext.BidderMetaX: metax.Builder, openrtb_ext.BidderMgid: mgid.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 0570d8a468d..744787eee53 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -150,6 +150,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderMediafuse, BidderMediaGo, BidderMedianet, + BidderMediasquare, BidderMeloZen, BidderMetaX, BidderMgid, @@ -477,6 +478,7 @@ const ( BidderMediafuse BidderName = "mediafuse" BidderMediaGo BidderName = "mediago" BidderMedianet BidderName = "medianet" + BidderMediasquare BidderName = "mediasquare" BidderMeloZen BidderName = "melozen" BidderMetaX BidderName = "metax" BidderMgid BidderName = "mgid" diff --git a/openrtb_ext/imp_mediasquare.go b/openrtb_ext/imp_mediasquare.go new file mode 100644 index 00000000000..8f1291e6086 --- /dev/null +++ b/openrtb_ext/imp_mediasquare.go @@ -0,0 +1,6 @@ +package openrtb_ext + +type ImpExtMediasquare struct { + Owner string `json:"owner"` + Code string `json:"code"` +} diff --git a/static/bidder-info/mediasquare.yaml b/static/bidder-info/mediasquare.yaml new file mode 100644 index 00000000000..bc8d54de062 --- /dev/null +++ b/static/bidder-info/mediasquare.yaml @@ -0,0 +1,12 @@ +endpoint: "https://pbs-front.mediasquare.fr/msq_prebid" +endpointCompression: gzip +gvlVendorID: 791 +modifyingVastXmlAllowed: true +maintainer: + email: "alexandre.harribey@mediasquare.fr" +capabilities: + app: + mediaTypes: + - banner + - video + - native diff --git a/static/bidder-params/mediasquare.json b/static/bidder-params/mediasquare.json new file mode 100644 index 00000000000..db7d07201f7 --- /dev/null +++ b/static/bidder-params/mediasquare.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Mediasquare Adapter Params", + "description": "A schema which validates params accepted by the Mediasquare adapter", + "type": "object", + "properties": { + "owner": { + "type": "string", + "minLength": 1, + "description": "The owner provided for mediasquare." + }, + "code": { + "type": "string", + "minLength": 1, + "description": "The code provided for mediasquare." + } + }, + "required": ["owner", "code"] +} From 1e3b2257d91ee0ee3414c4d5f63ae104a3acd4cc Mon Sep 17 00:00:00 2001 From: harribey Date: Wed, 16 Oct 2024 15:08:31 +0200 Subject: [PATCH 02/11] mediasquare adapter v0.00 --- adapters/mediasquare/mediasquare.go | 3 +- adapters/mediasquare/mediasquare_test.go | 2 +- adapters/mediasquare/openrtb.json | 138 ----------------------- adapters/mediasquare/structs.go | 11 +- adapters/mediasquare/structs_test.go | 8 +- adapters/mediasquare/utils.go | 5 + static/bidder-info/mediasquare.yaml | 8 +- 7 files changed, 23 insertions(+), 152 deletions(-) delete mode 100644 adapters/mediasquare/openrtb.json diff --git a/adapters/mediasquare/mediasquare.go b/adapters/mediasquare/mediasquare.go index 1e909a948a5..ebf16a1de35 100644 --- a/adapters/mediasquare/mediasquare.go +++ b/adapters/mediasquare/mediasquare.go @@ -33,6 +33,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E } msqParams := initMsqParams(request) + msqParams.Test = (request.Test == int8(1)) for _, imp := range request.Imp { var ( bidderExt adapters.ExtImpBidder @@ -75,7 +76,7 @@ func (a *adapter) makeRequest(request *openrtb2.BidRequest, msqParams *MsqParame err = errorWritter(" msqParams", nil, true) return } - if requestJsonBytes, err = json.Marshal(*msqParams); err == nil { + if requestJsonBytes, err = json.Marshal(msqParams); err == nil { var headers http.Header = headerList requestData = &adapters.RequestData{ Method: "POST", diff --git a/adapters/mediasquare/mediasquare_test.go b/adapters/mediasquare/mediasquare_test.go index 6c911775dcf..1cededcd683 100644 --- a/adapters/mediasquare/mediasquare_test.go +++ b/adapters/mediasquare/mediasquare_test.go @@ -104,7 +104,7 @@ func TestMakeRequest(t *testing.T) { result: []*adapters.RequestData{ {Method: "POST", Uri: "edp-mediasquare", Headers: headerList, ImpIDs: []string{"0", "1", "-42", "-1", "-0", "42"}, - Body: []byte(`{"codes":[{"adunit":"","auctionid":"id-ok","bidid":"42","code":"code-ok","owner":"owner-ok","mediatypes":{"banner":null,"video":null,"native":{"title":null,"icon":null,"image":null,"clickUrl":null,"displayUrl":null,"privacyLink":null,"privacyIcon":null,"cta":null,"rating":null,"downloads":null,"likes":null,"price":null,"saleprice":null,"address":null,"phone":null,"body":null,"body2":null,"sponsoredBy":null,"sizes":null,"type":"native"}},"floor":{"*":{}}}],"gdpr":{"consent_required":false,"consent_string":""},"type":"pbs","dsa":"","tech":{"device":null,"app":null}}`)}, + Body: []byte(`{"codes":[{"adunit":"","auctionid":"id-ok","bidid":"42","code":"code-ok","owner":"owner-ok","mediatypes":{"banner":null,"video":null,"native":{"title":null,"icon":null,"image":null,"clickUrl":null,"displayUrl":null,"privacyLink":null,"privacyIcon":null,"cta":null,"rating":null,"downloads":null,"likes":null,"price":null,"saleprice":null,"address":null,"phone":null,"body":null,"body2":null,"sponsoredBy":null,"sizes":null,"type":"native"}},"floor":{"*":{}}}],"gdpr":{"consent_required":false,"consent_string":""},"type":"pbs","dsa":"","tech":{"device":null,"app":null},"test":false}`)}, }, errs: []error{ errors.New(" imp[ext]: is empty."), diff --git a/adapters/mediasquare/openrtb.json b/adapters/mediasquare/openrtb.json deleted file mode 100644 index 38fac739929..00000000000 --- a/adapters/mediasquare/openrtb.json +++ /dev/null @@ -1,138 +0,0 @@ -{ - "device": { - "ip": "92.154.6.151", - "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36", - "language": "fr", - "geo": { - "country": "FRA", - "ipservice": 3 - } - }, - "ext": { - "prebid": { - "aliases": { - "Magnite": "rubicon", - "msqClassic": "appnexus", - "msqMediagrid": "grid" - }, - "bidadjustmentfactors": { - "msqClassic": 0.8, - "msqMediagrid": 0.8 - }, - "targeting": { - "pricegranularity": {} - }, - "debug": true, - "schains": [ - { - "bidders": ["*"], - "schain": { - "ver": "1.0", - "complete": 1, - "nodes": [ - { - "asi": "mediasquare.fr", - "sid": "1", - "hp": 1 - } - ] - } - }, - { - "bidders": ["msqClassic"], - "schain": { - "ver": "1.0", - "complete": 1, - "nodes": [ - { - "asi": "mediasquare.fr", - "sid": "68", - "hp": 1 - } - ] - } - } - ], - "channel": { - "name": "pbjs", - "version": "9.16.0-pre" - } - } - }, - "id": "70e5672c-515b-406e-967c-fcc2b04de04f", - "imp": [ - { - "banner": { - "format": [ - { - "w": 970, - "h": 250 - } - ], - "pos": 1 - }, - "ext": { - "mediasquare": { - "owner": "owner42", - "code": "code42" - } - }, - "id": "2c35e25e-e7d3-41bf-b810-06a449f456b9", - "secure": 1, - "bidfloor": 1, - "bidfloorcur": "USD" - }, - { - "banner": { - "format": [ - { - "w": 300, - "h": 250 - }, - { - "w": 300, - "h": 600 - }, - { - "w": 120, - "h": 600 - } - ], - "pos": 1 - }, - "ext": { - "mediasquare": { - "owner": "owner-42", - "code": "code-42" - } - }, - "id": "2059a3e6-71a3-43ea-8290-b5ceb13d35a8", - "secure": 1, - "bidfloor": 0.01, - "bidfloorcur": "USD" - } - ], - "regs": { - "gdpr": 1, - "ext": { - "gdpr": 1 - } - }, - "site": { - "page": "https://debug.mediasquare.fr/debug/prebid/msq_desktop.html?pbjs_debug=true", - "publisher": { - "id": "MEDIA_SQUARE" - }, - "name": "debug.mediasquare.fr", - "domain": "debug.mediasquare.fr", - "content": {} - }, - "tmax": 1300, - "user": { - "consent": "CQF9-AAQF9-AAAKA1AENDgCsAP_AAEPAAAqIg1NX_H__bW9r8X7_aft0eY1P9_j77sQxBhfJE-4F3LvW_JwXx2E5NF36tqoKmRoEu3ZBIUNlHJHUTVmwaogVryHsakWcoTNKJ6BkkFMRM2dYCF5vm4tjeQKY5_p_d3fx2D-t_dv839zzz8VHn3e5fue0-PCdU5-9Dfn9fRfb-9IP9_78v8v8_l_rk2_eT13_pcvr_D--f_87_XW-9_cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQagCzDQuIAuyJCQm0DCKBACIKwgIoEAAAAJA0QEALgwKdgYBLrCRACBFAAcEAIQAUZAAgAAEgAQiACQIoEAAEAgEAAIAEAgEADAwADgAtBAIAAQHQMUwoAFAsIEiMiIUwIQoEggJbKBBKCoQVwgCLDAigERsFAAgCQEVgACAsXgMASAlYkECXUG0AABAAgFFKFQik_MAQ4Jmy1V4om0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAACAA.f_gAAAAAAAAA", - "ext": { - "consent": "CQF9-AAQF9-AAAKA1AENDgCsAP_AAEPAAAqIg1NX_H__bW9r8X7_aft0eY1P9_j77sQxBhfJE-4F3LvW_JwXx2E5NF36tqoKmRoEu3ZBIUNlHJHUTVmwaogVryHsakWcoTNKJ6BkkFMRM2dYCF5vm4tjeQKY5_p_d3fx2D-t_dv839zzz8VHn3e5fue0-PCdU5-9Dfn9fRfb-9IP9_78v8v8_l_rk2_eT13_pcvr_D--f_87_XW-9_cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQagCzDQuIAuyJCQm0DCKBACIKwgIoEAAAAJA0QEALgwKdgYBLrCRACBFAAcEAIQAUZAAgAAEgAQiACQIoEAAEAgEAAIAEAgEADAwADgAtBAIAAQHQMUwoAFAsIEiMiIUwIQoEggJbKBBKCoQVwgCLDAigERsFAAgCQEVgACAsXgMASAlYkECXUG0AABAAgFFKFQik_MAQ4Jmy1V4om0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAACAA.f_gAAAAAAAAA" - } - }, - "cur": ["USD"] -} diff --git a/adapters/mediasquare/structs.go b/adapters/mediasquare/structs.go index 79786d431ea..dbb180da0f5 100644 --- a/adapters/mediasquare/structs.go +++ b/adapters/mediasquare/structs.go @@ -6,7 +6,6 @@ import ( "github.com/prebid/openrtb/v20/openrtb2" "github.com/prebid/prebid-server/v2/adapters" - "github.com/prebid/prebid-server/v2/openrtb_ext" ) // MsqResponse: Bid-Response sent by Mediasquare. @@ -29,6 +28,7 @@ type MsqParameters struct { Type string `json:"type"` DSA interface{} `json:"dsa,omitempty"` Support MsqSupport `json:"tech"` + Test bool `json:"test"` } type MsqResponseBidsVideo struct { @@ -236,15 +236,21 @@ func (msqParams *MsqParametersCodes) setContent(currentImp openrtb2.Imp) (ok boo if currentImp.Banner != nil { ok = true + var banner MediaTypeBanner + json.Unmarshal(currentImp.Banner.Ext, &banner) - json.Unmarshal(currentImp.Banner.Ext, msqParams.Mediatypes.Banner) + msqParams.Mediatypes.Banner = &banner switch { case len(currentImp.Banner.Format) > 0: for _, bannerFormat := range currentImp.Banner.Format { currentMapFloors[fmt.Sprintf("%dx%d", bannerFormat.W, bannerFormat.H)] = currentFloor + msqParams.Mediatypes.Banner.Sizes = append(msqParams.Mediatypes.Banner.Sizes, + []*int{intToPtrInt(int(bannerFormat.W)), intToPtrInt(int(bannerFormat.H))}) } case currentImp.Banner.W != nil && currentImp.Banner.H != nil: currentMapFloors[fmt.Sprintf("%dx%d", *(currentImp.Banner.W), *(currentImp.Banner.H))] = currentFloor + msqParams.Mediatypes.Banner.Sizes = append(msqParams.Mediatypes.Banner.Sizes, + []*int{intToPtrInt(int(*currentImp.Banner.W)), intToPtrInt(int(*currentImp.Banner.H))}) } if msqParams.Mediatypes.Banner != nil { @@ -282,7 +288,6 @@ func (msqResp *MsqResponse) getContent(bidderResponse *adapters.BidderResponse) for _, resp := range msqResp.Responses { tmpTBid := adapters.TypedBid{ BidType: resp.bidType(), - Seat: openrtb_ext.BidderName(resp.Bidder), Bid: &openrtb2.Bid{ ID: resp.ID, ImpID: resp.BidId, diff --git a/adapters/mediasquare/structs_test.go b/adapters/mediasquare/structs_test.go index 48a89bf6231..d9084d25db4 100644 --- a/adapters/mediasquare/structs_test.go +++ b/adapters/mediasquare/structs_test.go @@ -51,7 +51,6 @@ func TestGetContent(t *testing.T) { }, BidMeta: &openrtb_ext.ExtBidPrebidMeta{MediaType: "banner"}, BidType: "banner", - Seat: "bidder-ok", }, }, }, @@ -86,9 +85,6 @@ func TestSetContent(t *testing.T) { AuctionId: "auctionid-ok", Code: "code-ok", BidId: "bidid-ok", - Mediatypes: MediaTypes{ - Banner: &MediaTypeBanner{Sizes: [][]*int{{intAsPtrInt(1), intAsPtrInt(1)}, {intAsPtrInt(42), intAsPtrInt(42)}}}, - }, }, imp: openrtb2.Imp{ ID: "imp-id", @@ -147,7 +143,8 @@ func TestSetContent(t *testing.T) { switch index { case 1: - expected.Floor = map[string]MsqFloor{"1x1": {Price: 0.8}, "1x2": {Price: 0.8}, "2x1": {Price: 0.8}, "42x42": {Price: 0.8}} + expected.Mediatypes.Banner = &MediaTypeBanner{Sizes: [][]*int{{intAsPtrInt(1), intAsPtrInt(2)}, {intAsPtrInt(2), intAsPtrInt(1)}}} + expected.Floor = map[string]MsqFloor{"1x2": {Price: 0.8}, "2x1": {Price: 0.8}} case 2: expected.Floor = map[string]MsqFloor{"42x42": {Price: 0.8}, "*": {Price: 0.8}} expected.Mediatypes.Video = &MediaTypeVideo{Mimes: []string{"MIMEs-ok"}, H: intAsPtrInt(42), W: intAsPtrInt(42)} @@ -155,6 +152,7 @@ func TestSetContent(t *testing.T) { expected.Mediatypes.Native = &MediaTypeNative{Type: "native", Sizes: [][]int{{42, 42}, {2, 1}, {1, 1}}} expected.Floor = map[string]MsqFloor{"1x1": {Price: 0.8}, "42x42": {Price: 0.8}, "2x1": {Price: 0.8}, "*": {Price: 0.8}} case 4: + expected.Mediatypes.Banner = &MediaTypeBanner{Sizes: [][]*int{{intAsPtrInt(42), intAsPtrInt(42)}}} expected.Floor = map[string]MsqFloor{"42x42": {Price: 0.8}} } diff --git a/adapters/mediasquare/utils.go b/adapters/mediasquare/utils.go index af65d54f90c..0f022ad1b02 100644 --- a/adapters/mediasquare/utils.go +++ b/adapters/mediasquare/utils.go @@ -93,6 +93,11 @@ func ptrInt8ToBool(i *int8) bool { return false } +func intToPtrInt(i int) *int { + val := int(i) + return &val +} + func errorWritter(referer string, err error, isEmpty bool) error { if isEmpty { return fmt.Errorf("%s: is empty.", referer) diff --git a/static/bidder-info/mediasquare.yaml b/static/bidder-info/mediasquare.yaml index bc8d54de062..05f82862010 100644 --- a/static/bidder-info/mediasquare.yaml +++ b/static/bidder-info/mediasquare.yaml @@ -1,4 +1,4 @@ -endpoint: "https://pbs-front.mediasquare.fr/msq_prebid" +endpoint: "http://pbs-front.mediasquare.fr/msq_prebid" endpointCompression: gzip gvlVendorID: 791 modifyingVastXmlAllowed: true @@ -7,6 +7,6 @@ maintainer: capabilities: app: mediaTypes: - - banner - - video - - native + - banner + - video + - native From 1c8be468a04d015745465472f326ce2768092546 Mon Sep 17 00:00:00 2001 From: harribey Date: Wed, 16 Oct 2024 16:54:58 +0200 Subject: [PATCH 03/11] fix:typo+comments --- adapters/mediasquare/mediasquare_test.go | 5 ++- adapters/mediasquare/structs.go | 25 +++++--------- adapters/mediasquare/utils.go | 9 ++--- adapters/mediasquare/utils_test.go | 44 +++++++++--------------- 4 files changed, 33 insertions(+), 50 deletions(-) diff --git a/adapters/mediasquare/mediasquare_test.go b/adapters/mediasquare/mediasquare_test.go index 1cededcd683..1d79eaf40b9 100644 --- a/adapters/mediasquare/mediasquare_test.go +++ b/adapters/mediasquare/mediasquare_test.go @@ -74,8 +74,8 @@ func TestMakeBids(t *testing.T) { errsVal, _ := json.Marshal(errs) errsExp, _ := json.Marshal(test.errs) - assert.Equal(t, test.bidderResponse, resp, fmt.Sprintf("resp >> index: %d", index)) - assert.Equal(t, errsExp, errsVal, fmt.Sprintf("errs >> index: %d", index)) + assert.Equal(t, test.bidderResponse, resp, fmt.Sprintf("resp >> index: %d.", index)) + assert.Equal(t, errsExp, errsVal, fmt.Sprintf("errs >> index: %d.", index)) } } @@ -132,5 +132,4 @@ func TestMakeRequest(t *testing.T) { assert.Equal(t, errorWritter(" msqParams", nil, true), errNil, "error errNil") _, errChan := msqAdapter.makeRequest(nil, &MsqParameters{DSA: make(chan int)}) assert.Equal(t, errorWritter(" json.Marshal", errors.New("json: unsupported type: chan int"), false), errChan, "error errChan") - } diff --git a/adapters/mediasquare/structs.go b/adapters/mediasquare/structs.go index dbb180da0f5..2ea88fb2fa8 100644 --- a/adapters/mediasquare/structs.go +++ b/adapters/mediasquare/structs.go @@ -66,13 +66,11 @@ type MsqResponseBidsNative struct { } type MsqResponseBids struct { - ID string `json:"id"` - Ad string `json:"ad,omitempty"` - BidId string `json:"bid_id,omitempty"` - Bidder string `json:"bidder,omitempty"` - //Code string `json:"code,omitempty"` - Cpm float64 `json:"cpm,omitempty"` - //Increment float32 `json:"increment"` + ID string `json:"id"` + Ad string `json:"ad,omitempty"` + BidId string `json:"bid_id,omitempty"` + Bidder string `json:"bidder,omitempty"` + Cpm float64 `json:"cpm,omitempty"` Currency string `json:"currency,omitempty"` CreativeId string `json:"creative_id,omitempty"` Height int64 `json:"height,omitempty"` @@ -82,14 +80,9 @@ type MsqResponseBids struct { Ttl int `json:"ttl,omitempty"` Video *MsqResponseBidsVideo `json:"video,omitempty"` Native *MsqResponseBidsNative `json:"native,omitempty"` - //Amp *MsqResponseBidsAmp `json:"targeting,omitempty"` - ADomain []string `json:"adomain,omitempty"` - //HasConsent bool `json:"hasConsent,omitempty"` - //Context string `json:"context,omitempty"` - //Ova string `json:"ova,omitempty"` - Dsa interface{} `json:"dsa,omitempty"` - //Match string `json:"match,omitempty"` - BURL string `json:"burl,omitempty"` + ADomain []string `json:"adomain,omitempty"` + Dsa interface{} `json:"dsa,omitempty"` + BURL string `json:"burl,omitempty"` } type MsqSupport struct { @@ -202,7 +195,7 @@ func initMsqParams(request *openrtb2.BidRequest) (msqParams MsqParameters) { ConsentRequired: (parserGDPR{}).getValue("consent_requirement", request) == "true", ConsentString: (parserGDPR{}).getValue("consent_string", request), } - msqParams.DSA = parserDSA{}.getValue(request) + msqParams.DSA = (parserDSA{}).getValue(request) return } diff --git a/adapters/mediasquare/utils.go b/adapters/mediasquare/utils.go index 0f022ad1b02..012bb5adcc4 100644 --- a/adapters/mediasquare/utils.go +++ b/adapters/mediasquare/utils.go @@ -48,8 +48,7 @@ func (msqBids *MsqResponseBids) bidType() openrtb_ext.BidType { func (msqBids *MsqResponseBids) extBid() (raw json.RawMessage) { extBid, _ := msqBids.loadExtBid() if extBid.DSA != nil || extBid.Prebid != nil { - bb, _ := json.Marshal(extBid) - if len(bb) > 0 { + if bb, _ := json.Marshal(extBid); len(bb) > 0 { raw = json.RawMessage(bb) } } @@ -75,7 +74,7 @@ func (msqBids *MsqResponseBids) loadExtBid() (extBid openrtb_ext.ExtBid, errs [] return } -// extBidPrebidMeta: Extracts the ExtBidPrebidMeta from msqBids. +// extBidPrebidMeta: Extracts the ExtBidPrebidMeta from msqBids as (*openrtb_ext.ExtBidPrebidMeta). func (msqBids *MsqResponseBids) extBidPrebidMeta() *openrtb_ext.ExtBidPrebidMeta { var extBidMeta openrtb_ext.ExtBidPrebidMeta if msqBids.ADomain != nil { @@ -85,7 +84,7 @@ func (msqBids *MsqResponseBids) extBidPrebidMeta() *openrtb_ext.ExtBidPrebidMeta return &extBidMeta } -// ptrInt8ToBool: Return (TRUE) when i equals 1. +// ptrInt8ToBool: Returns (TRUE) when i equals 1. func ptrInt8ToBool(i *int8) bool { if i != nil { return (*i == int8(1)) @@ -93,11 +92,13 @@ func ptrInt8ToBool(i *int8) bool { return false } +// intToPtrInt: Returns a ptr_int(*int) for which *ptr_int = i. func intToPtrInt(i int) *int { val := int(i) return &val } +// errorWritter: Returns a Custom error message. func errorWritter(referer string, err error, isEmpty bool) error { if isEmpty { return fmt.Errorf("%s: is empty.", referer) diff --git a/adapters/mediasquare/utils_test.go b/adapters/mediasquare/utils_test.go index 280597e11fd..21fd7f55d4b 100644 --- a/adapters/mediasquare/utils_test.go +++ b/adapters/mediasquare/utils_test.go @@ -18,7 +18,7 @@ func TestPtrInt8ToBool(t *testing.T) { 42: false, } for value, expected := range tests { - assert.Equal(t, expected, ptrInt8ToBool(&value), "ptrInt8ToBool >> value:", value) + assert.Equal(t, expected, ptrInt8ToBool(&value), fmt.Sprintf("ptrInt8ToBool >> value: (int8)=%d.", value)) } assert.Equal(t, false, ptrInt8ToBool(nil), "ptrInt8ToBool >> value(nil)") } @@ -32,20 +32,17 @@ func TestMethodsType(t *testing.T) { mType openrtb2.MarkupType }{ { - resp: MsqResponseBids{Native: &MsqResponseBidsNative{ClickUrl: "not-nil"}}, - + resp: MsqResponseBids{Native: &MsqResponseBidsNative{ClickUrl: "not-nil"}}, bidType: "native", mType: openrtb2.MarkupNative, }, { - resp: MsqResponseBids{Video: &MsqResponseBidsVideo{Xml: "not-nil"}}, - + resp: MsqResponseBids{Video: &MsqResponseBidsVideo{Xml: "not-nil"}}, bidType: "video", mType: openrtb2.MarkupVideo, }, { - resp: MsqResponseBids{ID: "not-nil"}, - + resp: MsqResponseBids{ID: "not-nil"}, bidType: "banner", mType: openrtb2.MarkupBanner, }, @@ -65,26 +62,22 @@ func TestLoadExtBid(t *testing.T) { isOk bool }{ { - resp: MsqResponseBids{}, - + resp: MsqResponseBids{}, extBid: openrtb_ext.ExtBid{DSA: nil, Prebid: nil}, isOk: true, }, { - resp: MsqResponseBids{Dsa: openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, - + resp: MsqResponseBids{Dsa: openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, extBid: openrtb_ext.ExtBid{DSA: &openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, isOk: true, }, { - resp: MsqResponseBids{Dsa: "lol"}, - + resp: MsqResponseBids{Dsa: "lol"}, extBid: openrtb_ext.ExtBid{}, isOk: false, }, { - resp: MsqResponseBids{Dsa: make(chan int)}, - + resp: MsqResponseBids{Dsa: make(chan int)}, extBid: openrtb_ext.ExtBid{}, isOk: false, }, @@ -92,8 +85,8 @@ func TestLoadExtBid(t *testing.T) { for index, test := range tests { extBid, errs := test.resp.loadExtBid() - assert.Equal(t, test.extBid.DSA, extBid.DSA, fmt.Sprintf("extBid.DSA >> index: %d", index)) - assert.Equal(t, test.isOk, errs == nil, fmt.Sprintf("isOk >> index: %d", index)) + assert.Equal(t, test.extBid.DSA, extBid.DSA, fmt.Sprintf("extBid.DSA >> index: %d.", index)) + assert.Equal(t, test.isOk, errs == nil, fmt.Sprintf("isOk >> index: %d.", index)) } } @@ -107,8 +100,7 @@ func TestExtBidPrebidMeta(t *testing.T) { value openrtb_ext.ExtBidPrebidMeta }{ { - resp: MsqResponseBids{ADomain: []string{"test-adomain-0", "test-adomain-1"}}, - + resp: MsqResponseBids{ADomain: []string{"test-adomain-0", "test-adomain-1"}}, adomains: []string{"test-adomain-0", "test-adomain-1"}, mediatype: "banner", value: openrtb_ext.ExtBidPrebidMeta{ @@ -117,15 +109,13 @@ func TestExtBidPrebidMeta(t *testing.T) { }, }, { - resp: MsqResponseBids{}, - + resp: MsqResponseBids{}, adomains: nil, mediatype: "banner", value: openrtb_ext.ExtBidPrebidMeta{MediaType: "banner"}, }, { - resp: MsqResponseBids{Video: &MsqResponseBidsVideo{Xml: "not-nil"}}, - + resp: MsqResponseBids{Video: &MsqResponseBidsVideo{Xml: "not-nil"}}, adomains: nil, mediatype: "video", value: openrtb_ext.ExtBidPrebidMeta{MediaType: "video"}, @@ -134,9 +124,9 @@ func TestExtBidPrebidMeta(t *testing.T) { for index, test := range tests { result := test.resp.extBidPrebidMeta() - assert.Equal(t, test.adomains, result.AdvertiserDomains, fmt.Sprintf("ADomains >> index: %d", index)) - assert.Equal(t, test.mediatype, result.MediaType, fmt.Sprintf("MediaType >> index: %d", index)) - assert.Equal(t, test.value, *result, fmt.Sprintf("ExactValue >> index: %d", index)) + assert.Equal(t, test.adomains, result.AdvertiserDomains, fmt.Sprintf("ADomains >> index: %d.", index)) + assert.Equal(t, test.mediatype, result.MediaType, fmt.Sprintf("MediaType >> index: %d.", index)) + assert.Equal(t, test.value, *result, fmt.Sprintf("ExactValue >> index: %d.", index)) } } @@ -158,6 +148,6 @@ func TestExtBid(t *testing.T) { } for index, test := range tests { - assert.Equal(t, test.raw, test.resp.extBid(), fmt.Sprintf("raw >> index: %d", index)) + assert.Equal(t, test.raw, test.resp.extBid(), fmt.Sprintf("Raw >> index: %d.", index)) } } From 6051fdbf46cff8e720f44f83e2612e24dc03a936 Mon Sep 17 00:00:00 2001 From: harribey Date: Wed, 16 Oct 2024 17:58:00 +0200 Subject: [PATCH 04/11] ++ --- adapters/mediasquare/structs_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adapters/mediasquare/structs_test.go b/adapters/mediasquare/structs_test.go index d9084d25db4..c11967648de 100644 --- a/adapters/mediasquare/structs_test.go +++ b/adapters/mediasquare/structs_test.go @@ -139,7 +139,7 @@ func TestSetContent(t *testing.T) { expected := test.params ok := test.params.setContent(test.imp) - assert.Equal(t, test.ok, ok, fmt.Sprintf("ok >> index: %d", index)) + assert.Equal(t, test.ok, ok, fmt.Sprintf("ok >> index: %d.", index)) switch index { case 1: @@ -158,7 +158,7 @@ func TestSetContent(t *testing.T) { expectedBytes, _ := json.Marshal(expected) paramsBytes, _ := json.Marshal(test.params) - assert.Equal(t, string(expectedBytes), string(paramsBytes), fmt.Sprintf("assert >> index: %d", index)) + assert.Equal(t, string(expectedBytes), string(paramsBytes), fmt.Sprintf("assert >> index: %d.", index)) } } From 355ddb0c67fd0b9bd88b8221facc59bc37de28eb Mon Sep 17 00:00:00 2001 From: harribey Date: Thu, 24 Oct 2024 19:12:01 +0200 Subject: [PATCH 05/11] fix:structs_privacy --- adapters/mediasquare/mediasquare.go | 10 +- adapters/mediasquare/mediasquare_test.go | 2 +- adapters/mediasquare/structs.go | 116 +++++++++++------------ adapters/mediasquare/structs_test.go | 36 +++---- adapters/mediasquare/utils.go | 14 +-- adapters/mediasquare/utils_test.go | 32 +++---- 6 files changed, 105 insertions(+), 105 deletions(-) diff --git a/adapters/mediasquare/mediasquare.go b/adapters/mediasquare/mediasquare.go index ebf16a1de35..74cecbba009 100644 --- a/adapters/mediasquare/mediasquare.go +++ b/adapters/mediasquare/mediasquare.go @@ -38,7 +38,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E var ( bidderExt adapters.ExtImpBidder msqExt openrtb_ext.ImpExtMediasquare - currentCode = MsqParametersCodes{ + currentCode = msqParametersCodes{ AdUnit: imp.TagID, AuctionId: request.ID, BidId: imp.ID, @@ -70,7 +70,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E return requestData, errs } -func (a *adapter) makeRequest(request *openrtb2.BidRequest, msqParams *MsqParameters) (requestData *adapters.RequestData, err error) { +func (a *adapter) makeRequest(request *openrtb2.BidRequest, msqParams *msqParameters) (requestData *adapters.RequestData, err error) { var requestJsonBytes []byte if msqParams == nil { err = errorWritter(" msqParams", nil, true) @@ -108,12 +108,12 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R return bidderResponse, errs } - var msqResponse MsqResponse - if err := json.Unmarshal(response.Body, &msqResponse); err != nil { + var msqResp msqResponse + if err := json.Unmarshal(response.Body, &msqResp); err != nil { errs = []error{&errortypes.BadServerResponse{Message: fmt.Sprintf(" Bad server response: %s.", err.Error())}} return bidderResponse, errs } bidderResponse = adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) - msqResponse.getContent(bidderResponse) + msqResp.getContent(bidderResponse) return bidderResponse, errs } diff --git a/adapters/mediasquare/mediasquare_test.go b/adapters/mediasquare/mediasquare_test.go index 1d79eaf40b9..ec87b3984d1 100644 --- a/adapters/mediasquare/mediasquare_test.go +++ b/adapters/mediasquare/mediasquare_test.go @@ -130,6 +130,6 @@ func TestMakeRequest(t *testing.T) { var msqAdapter adapter _, errNil := msqAdapter.makeRequest(nil, nil) assert.Equal(t, errorWritter(" msqParams", nil, true), errNil, "error errNil") - _, errChan := msqAdapter.makeRequest(nil, &MsqParameters{DSA: make(chan int)}) + _, errChan := msqAdapter.makeRequest(nil, &msqParameters{DSA: make(chan int)}) assert.Equal(t, errorWritter(" json.Marshal", errors.New("json: unsupported type: chan int"), false), errChan, "error errChan") } diff --git a/adapters/mediasquare/structs.go b/adapters/mediasquare/structs.go index 2ea88fb2fa8..cf367b04214 100644 --- a/adapters/mediasquare/structs.go +++ b/adapters/mediasquare/structs.go @@ -8,49 +8,49 @@ import ( "github.com/prebid/prebid-server/v2/adapters" ) -// MsqResponse: Bid-Response sent by Mediasquare. -type MsqResponse struct { +// msqResponse: Bid-Response sent by mediasquare. +type msqResponse struct { Infos struct { Version string `json:"version"` Description string `json:"description"` Hostname string `json:"hostname,omitempty"` } `json:"infos"` - Responses []MsqResponseBids `json:"responses"` + Responses []msqResponseBids `json:"responses"` } -// MsqParameters: Bid-Request sent to Mediasquare. -type MsqParameters struct { - Codes []MsqParametersCodes `json:"codes"` +// msqParameters: Bid-Request sent to mediasquare. +type msqParameters struct { + Codes []msqParametersCodes `json:"codes"` Gdpr struct { ConsentRequired bool `json:"consent_required"` ConsentString string `json:"consent_string"` } `json:"gdpr"` Type string `json:"type"` DSA interface{} `json:"dsa,omitempty"` - Support MsqSupport `json:"tech"` + Support msqSupport `json:"tech"` Test bool `json:"test"` } -type MsqResponseBidsVideo struct { +type msqResponseBidsVideo struct { Xml string `json:"xml"` Url string `json:"url"` } -type NativeResponseImg struct { +type nativeResponseImg struct { Url string `json:"url"` Width *int `json:"width,omitempty"` Height *int `json:"height,omitempty"` } -type MsqResponseBidsNative struct { +type msqResponseBidsNative struct { ClickUrl string `json:"clickUrl,omitempty"` ClickTrackers []string `json:"clickTrackers,omitempty"` ImpressionTrackers []string `json:"impressionTrackers,omitempty"` JavascriptTrackers []string `json:"javascriptTrackers,omitempty"` Privacy *string `json:"privacy,omitempty"` Title *string `json:"title,omitempty"` - Icon *NativeResponseImg `json:"icon,omitempty"` - Image *NativeResponseImg `json:"image,omitempty"` + Icon *nativeResponseImg `json:"icon,omitempty"` + Image *nativeResponseImg `json:"image,omitempty"` Cta *string `json:"cta,omitempty"` Rating *string `json:"rating,omitempty"` Downloads *string `json:"downloads,omitempty"` @@ -65,7 +65,7 @@ type MsqResponseBidsNative struct { DisplayUrl *string `json:"displayUrl,omitempty"` } -type MsqResponseBids struct { +type msqResponseBids struct { ID string `json:"id"` Ad string `json:"ad,omitempty"` BidId string `json:"bid_id,omitempty"` @@ -78,39 +78,39 @@ type MsqResponseBids struct { NetRevenue bool `json:"net_revenue,omitempty"` TransactionId string `json:"transaction_id,omitempty"` Ttl int `json:"ttl,omitempty"` - Video *MsqResponseBidsVideo `json:"video,omitempty"` - Native *MsqResponseBidsNative `json:"native,omitempty"` + Video *msqResponseBidsVideo `json:"video,omitempty"` + Native *msqResponseBidsNative `json:"native,omitempty"` ADomain []string `json:"adomain,omitempty"` Dsa interface{} `json:"dsa,omitempty"` BURL string `json:"burl,omitempty"` } -type MsqSupport struct { +type msqSupport struct { Device interface{} `json:"device"` App interface{} `json:"app"` } -type MsqParametersCodes struct { +type msqParametersCodes struct { AdUnit string `json:"adunit"` AuctionId string `json:"auctionid"` BidId string `json:"bidid"` Code string `json:"code"` Owner string `json:"owner"` - Mediatypes MediaTypes `json:"mediatypes,omitempty"` - Floor map[string]MsqFloor `json:"floor,omitempty"` + Mediatypes mediaTypes `json:"mediatypes,omitempty"` + Floor map[string]msqFloor `json:"floor,omitempty"` } -type MsqFloor struct { +type msqFloor struct { Price float64 `json:"floor,omitempty"` Currency string `json:"currency,omitempty"` } -type MediaTypeNativeBasis struct { +type mediaTypeNativeBasis struct { Required bool Len *int } -type MediaTypeNativeImage struct { +type mediaTypeNativeImage struct { Required bool Sizes []*int Aspect_ratio *struct { @@ -121,35 +121,35 @@ type MediaTypeNativeImage struct { } } -type MediaTypeNativeTitle struct { +type mediaTypeNativeTitle struct { Required bool Len int } -type MediaTypeNative struct { - Title *MediaTypeNativeTitle `json:"title"` - Icon *MediaTypeNativeImage `json:"icon"` - Image *MediaTypeNativeImage `json:"image"` - Clickurl *MediaTypeNativeBasis `json:"clickUrl"` - Displayurl *MediaTypeNativeBasis `json:"displayUrl"` - Privacylink *MediaTypeNativeBasis `json:"privacyLink"` - Privacyicon *MediaTypeNativeBasis `json:"privacyIcon"` - Cta *MediaTypeNativeBasis `json:"cta"` - Rating *MediaTypeNativeBasis `json:"rating"` - Downloads *MediaTypeNativeBasis `json:"downloads"` - Likes *MediaTypeNativeBasis `json:"likes"` - Price *MediaTypeNativeBasis `json:"price"` - Saleprice *MediaTypeNativeBasis `json:"saleprice"` - Address *MediaTypeNativeBasis `json:"address"` - Phone *MediaTypeNativeBasis `json:"phone"` - Body *MediaTypeNativeBasis `json:"body"` - Body2 *MediaTypeNativeBasis `json:"body2"` - Sponsoredby *MediaTypeNativeBasis `json:"sponsoredBy"` +type mediaTypeNative struct { + Title *mediaTypeNativeTitle `json:"title"` + Icon *mediaTypeNativeImage `json:"icon"` + Image *mediaTypeNativeImage `json:"image"` + Clickurl *mediaTypeNativeBasis `json:"clickUrl"` + Displayurl *mediaTypeNativeBasis `json:"displayUrl"` + Privacylink *mediaTypeNativeBasis `json:"privacyLink"` + Privacyicon *mediaTypeNativeBasis `json:"privacyIcon"` + Cta *mediaTypeNativeBasis `json:"cta"` + Rating *mediaTypeNativeBasis `json:"rating"` + Downloads *mediaTypeNativeBasis `json:"downloads"` + Likes *mediaTypeNativeBasis `json:"likes"` + Price *mediaTypeNativeBasis `json:"price"` + Saleprice *mediaTypeNativeBasis `json:"saleprice"` + Address *mediaTypeNativeBasis `json:"address"` + Phone *mediaTypeNativeBasis `json:"phone"` + Body *mediaTypeNativeBasis `json:"body"` + Body2 *mediaTypeNativeBasis `json:"body2"` + Sponsoredby *mediaTypeNativeBasis `json:"sponsoredBy"` Sizes [][]int `json:"sizes"` Type string `json:"type"` } -type MediaTypeVideo struct { +type mediaTypeVideo struct { Mimes []string `json:"mimes"` Minduration *int `json:"minduration"` Maxduration *int `json:"maxduration"` @@ -172,19 +172,19 @@ type MediaTypeVideo struct { Plcmt *int `json:"plcmt,omitempty"` } -type MediaTypes struct { - Banner *MediaTypeBanner `json:"banner"` - Video *MediaTypeVideo `json:"video"` - Native *MediaTypeNative `json:"native"` +type mediaTypes struct { + Banner *mediaTypeBanner `json:"banner"` + Video *mediaTypeVideo `json:"video"` + Native *mediaTypeNative `json:"native"` } -type MediaTypeBanner struct { +type mediaTypeBanner struct { Sizes [][]*int `json:"sizes"` } -func initMsqParams(request *openrtb2.BidRequest) (msqParams MsqParameters) { +func initMsqParams(request *openrtb2.BidRequest) (msqParams msqParameters) { msqParams.Type = "pbs" - msqParams.Support = MsqSupport{ + msqParams.Support = msqSupport{ Device: request.Device, App: request.App, } @@ -200,12 +200,12 @@ func initMsqParams(request *openrtb2.BidRequest) (msqParams MsqParameters) { return } -// setContent: Loads currentImp into msqParams (*MsqParametersCodes), +// setContent: Loads currentImp into msqParams (*msqParametersCodes), // returns (errs []error, ok bool) where `ok` express if mandatory content had been loaded. -func (msqParams *MsqParametersCodes) setContent(currentImp openrtb2.Imp) (ok bool) { +func (msqParams *msqParametersCodes) setContent(currentImp openrtb2.Imp) (ok bool) { var ( - currentMapFloors = make(map[string]MsqFloor, 0) - currentFloor = MsqFloor{ + currentMapFloors = make(map[string]msqFloor, 0) + currentFloor = msqFloor{ Price: currentImp.BidFloor, Currency: currentImp.BidFloorCur, } @@ -213,7 +213,7 @@ func (msqParams *MsqParametersCodes) setContent(currentImp openrtb2.Imp) (ok boo if currentImp.Video != nil { ok = true - var video MediaTypeVideo + var video mediaTypeVideo currentVideoBytes, _ := json.Marshal(currentImp.Video) json.Unmarshal(currentVideoBytes, &video) json.Unmarshal(currentImp.Video.Ext, &video) @@ -229,7 +229,7 @@ func (msqParams *MsqParametersCodes) setContent(currentImp openrtb2.Imp) (ok boo if currentImp.Banner != nil { ok = true - var banner MediaTypeBanner + var banner mediaTypeBanner json.Unmarshal(currentImp.Banner.Ext, &banner) msqParams.Mediatypes.Banner = &banner @@ -257,7 +257,7 @@ func (msqParams *MsqParametersCodes) setContent(currentImp openrtb2.Imp) (ok boo if currentImp.Native != nil { ok = true - var native = MediaTypeNative{Type: "native"} + var native = mediaTypeNative{Type: "native"} json.Unmarshal(currentImp.Native.Ext, &native) msqParams.Mediatypes.Native = &native @@ -276,7 +276,7 @@ func (msqParams *MsqParametersCodes) setContent(currentImp openrtb2.Imp) (ok boo } // getContent: Loads msqResp content into the bidderResponse (*adapters.BidderResponse). -func (msqResp *MsqResponse) getContent(bidderResponse *adapters.BidderResponse) { +func (msqResp *msqResponse) getContent(bidderResponse *adapters.BidderResponse) { var tmpBids []*adapters.TypedBid for _, resp := range msqResp.Responses { tmpTBid := adapters.TypedBid{ diff --git a/adapters/mediasquare/structs_test.go b/adapters/mediasquare/structs_test.go index c11967648de..e172c5b195a 100644 --- a/adapters/mediasquare/structs_test.go +++ b/adapters/mediasquare/structs_test.go @@ -13,18 +13,18 @@ import ( func TestGetContent(t *testing.T) { tests := []struct { - resp MsqResponse + resp msqResponse value adapters.BidderResponse expected adapters.BidderResponse }{ { - resp: MsqResponse{}, + resp: msqResponse{}, value: adapters.BidderResponse{Currency: ""}, expected: adapters.BidderResponse{Currency: ""}, }, { - resp: MsqResponse{ - Responses: []MsqResponseBids{ + resp: msqResponse{ + Responses: []msqResponseBids{ { ID: "id-ok", Ad: "ad-ok", @@ -69,18 +69,18 @@ func TestGetContent(t *testing.T) { func TestSetContent(t *testing.T) { tests := []struct { // tests inputs - params MsqParametersCodes + params msqParametersCodes imp openrtb2.Imp // tests expected-results ok bool }{ { - params: MsqParametersCodes{}, + params: msqParametersCodes{}, imp: openrtb2.Imp{}, ok: false, }, { - params: MsqParametersCodes{ + params: msqParametersCodes{ AdUnit: "adunit-ok", AuctionId: "auctionid-ok", Code: "code-ok", @@ -97,7 +97,7 @@ func TestSetContent(t *testing.T) { ok: true, }, { - params: MsqParametersCodes{}, + params: msqParametersCodes{}, imp: openrtb2.Imp{ ID: "imp-id", Video: &openrtb2.Video{ @@ -110,7 +110,7 @@ func TestSetContent(t *testing.T) { ok: true, }, { - params: MsqParametersCodes{}, + params: msqParametersCodes{}, imp: openrtb2.Imp{ ID: "imp-id", Native: &openrtb2.Native{ @@ -122,7 +122,7 @@ func TestSetContent(t *testing.T) { ok: true, }, { - params: MsqParametersCodes{}, + params: msqParametersCodes{}, imp: openrtb2.Imp{ ID: "imp-id", Banner: &openrtb2.Banner{ @@ -143,17 +143,17 @@ func TestSetContent(t *testing.T) { switch index { case 1: - expected.Mediatypes.Banner = &MediaTypeBanner{Sizes: [][]*int{{intAsPtrInt(1), intAsPtrInt(2)}, {intAsPtrInt(2), intAsPtrInt(1)}}} - expected.Floor = map[string]MsqFloor{"1x2": {Price: 0.8}, "2x1": {Price: 0.8}} + expected.Mediatypes.Banner = &mediaTypeBanner{Sizes: [][]*int{{intAsPtrInt(1), intAsPtrInt(2)}, {intAsPtrInt(2), intAsPtrInt(1)}}} + expected.Floor = map[string]msqFloor{"1x2": {Price: 0.8}, "2x1": {Price: 0.8}} case 2: - expected.Floor = map[string]MsqFloor{"42x42": {Price: 0.8}, "*": {Price: 0.8}} - expected.Mediatypes.Video = &MediaTypeVideo{Mimes: []string{"MIMEs-ok"}, H: intAsPtrInt(42), W: intAsPtrInt(42)} + expected.Floor = map[string]msqFloor{"42x42": {Price: 0.8}, "*": {Price: 0.8}} + expected.Mediatypes.Video = &mediaTypeVideo{Mimes: []string{"MIMEs-ok"}, H: intAsPtrInt(42), W: intAsPtrInt(42)} case 3: - expected.Mediatypes.Native = &MediaTypeNative{Type: "native", Sizes: [][]int{{42, 42}, {2, 1}, {1, 1}}} - expected.Floor = map[string]MsqFloor{"1x1": {Price: 0.8}, "42x42": {Price: 0.8}, "2x1": {Price: 0.8}, "*": {Price: 0.8}} + expected.Mediatypes.Native = &mediaTypeNative{Type: "native", Sizes: [][]int{{42, 42}, {2, 1}, {1, 1}}} + expected.Floor = map[string]msqFloor{"1x1": {Price: 0.8}, "42x42": {Price: 0.8}, "2x1": {Price: 0.8}, "*": {Price: 0.8}} case 4: - expected.Mediatypes.Banner = &MediaTypeBanner{Sizes: [][]*int{{intAsPtrInt(42), intAsPtrInt(42)}}} - expected.Floor = map[string]MsqFloor{"42x42": {Price: 0.8}} + expected.Mediatypes.Banner = &mediaTypeBanner{Sizes: [][]*int{{intAsPtrInt(42), intAsPtrInt(42)}}} + expected.Floor = map[string]msqFloor{"42x42": {Price: 0.8}} } expectedBytes, _ := json.Marshal(expected) diff --git a/adapters/mediasquare/utils.go b/adapters/mediasquare/utils.go index 012bb5adcc4..1d7f7b0db37 100644 --- a/adapters/mediasquare/utils.go +++ b/adapters/mediasquare/utils.go @@ -20,8 +20,8 @@ var mediaTypeList = map[openrtb_ext.BidType]openrtb2.MarkupType{ "native": openrtb2.MarkupNative, } -// mType: Returns the openrtb2.MarkupType from an MsqResponseBids. -func (msqBids *MsqResponseBids) mType() openrtb2.MarkupType { +// mType: Returns the openrtb2.MarkupType from an msqResponseBids. +func (msqBids *msqResponseBids) mType() openrtb2.MarkupType { switch { case msqBids.Video != nil: return mediaTypeList["video"] @@ -32,8 +32,8 @@ func (msqBids *MsqResponseBids) mType() openrtb2.MarkupType { } } -// bidType: Returns the openrtb_ext.BidType from an MsqResponseBids. -func (msqBids *MsqResponseBids) bidType() openrtb_ext.BidType { +// bidType: Returns the openrtb_ext.BidType from an msqResponseBids. +func (msqBids *msqResponseBids) bidType() openrtb_ext.BidType { switch { case msqBids.Video != nil: return "video" @@ -45,7 +45,7 @@ func (msqBids *MsqResponseBids) bidType() openrtb_ext.BidType { } // extBid: Extracts the ExtBid from msqBids formated as (json.RawMessage). -func (msqBids *MsqResponseBids) extBid() (raw json.RawMessage) { +func (msqBids *msqResponseBids) extBid() (raw json.RawMessage) { extBid, _ := msqBids.loadExtBid() if extBid.DSA != nil || extBid.Prebid != nil { if bb, _ := json.Marshal(extBid); len(bb) > 0 { @@ -56,7 +56,7 @@ func (msqBids *MsqResponseBids) extBid() (raw json.RawMessage) { } // loadExtBid: Extracts the ExtBid from msqBids as (openrtb_ext.ExtBid, []error). -func (msqBids *MsqResponseBids) loadExtBid() (extBid openrtb_ext.ExtBid, errs []error) { +func (msqBids *msqResponseBids) loadExtBid() (extBid openrtb_ext.ExtBid, errs []error) { if msqBids.Dsa != nil { bb, err := json.Marshal(msqBids.Dsa) if err != nil { @@ -75,7 +75,7 @@ func (msqBids *MsqResponseBids) loadExtBid() (extBid openrtb_ext.ExtBid, errs [] } // extBidPrebidMeta: Extracts the ExtBidPrebidMeta from msqBids as (*openrtb_ext.ExtBidPrebidMeta). -func (msqBids *MsqResponseBids) extBidPrebidMeta() *openrtb_ext.ExtBidPrebidMeta { +func (msqBids *msqResponseBids) extBidPrebidMeta() *openrtb_ext.ExtBidPrebidMeta { var extBidMeta openrtb_ext.ExtBidPrebidMeta if msqBids.ADomain != nil { extBidMeta.AdvertiserDomains = msqBids.ADomain diff --git a/adapters/mediasquare/utils_test.go b/adapters/mediasquare/utils_test.go index 21fd7f55d4b..5b32652d771 100644 --- a/adapters/mediasquare/utils_test.go +++ b/adapters/mediasquare/utils_test.go @@ -26,23 +26,23 @@ func TestPtrInt8ToBool(t *testing.T) { func TestMethodsType(t *testing.T) { tests := []struct { // tests inputs - resp MsqResponseBids + resp msqResponseBids // tests expected-results bidType openrtb_ext.BidType mType openrtb2.MarkupType }{ { - resp: MsqResponseBids{Native: &MsqResponseBidsNative{ClickUrl: "not-nil"}}, + resp: msqResponseBids{Native: &msqResponseBidsNative{ClickUrl: "not-nil"}}, bidType: "native", mType: openrtb2.MarkupNative, }, { - resp: MsqResponseBids{Video: &MsqResponseBidsVideo{Xml: "not-nil"}}, + resp: msqResponseBids{Video: &msqResponseBidsVideo{Xml: "not-nil"}}, bidType: "video", mType: openrtb2.MarkupVideo, }, { - resp: MsqResponseBids{ID: "not-nil"}, + resp: msqResponseBids{ID: "not-nil"}, bidType: "banner", mType: openrtb2.MarkupBanner, }, @@ -56,28 +56,28 @@ func TestMethodsType(t *testing.T) { func TestLoadExtBid(t *testing.T) { tests := []struct { // tests inputs - resp MsqResponseBids + resp msqResponseBids // tests expected-results extBid openrtb_ext.ExtBid isOk bool }{ { - resp: MsqResponseBids{}, + resp: msqResponseBids{}, extBid: openrtb_ext.ExtBid{DSA: nil, Prebid: nil}, isOk: true, }, { - resp: MsqResponseBids{Dsa: openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, + resp: msqResponseBids{Dsa: openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, extBid: openrtb_ext.ExtBid{DSA: &openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, isOk: true, }, { - resp: MsqResponseBids{Dsa: "lol"}, + resp: msqResponseBids{Dsa: "lol"}, extBid: openrtb_ext.ExtBid{}, isOk: false, }, { - resp: MsqResponseBids{Dsa: make(chan int)}, + resp: msqResponseBids{Dsa: make(chan int)}, extBid: openrtb_ext.ExtBid{}, isOk: false, }, @@ -93,14 +93,14 @@ func TestLoadExtBid(t *testing.T) { func TestExtBidPrebidMeta(t *testing.T) { tests := []struct { // tests inputs - resp MsqResponseBids + resp msqResponseBids // tests expected-results adomains []string mediatype string value openrtb_ext.ExtBidPrebidMeta }{ { - resp: MsqResponseBids{ADomain: []string{"test-adomain-0", "test-adomain-1"}}, + resp: msqResponseBids{ADomain: []string{"test-adomain-0", "test-adomain-1"}}, adomains: []string{"test-adomain-0", "test-adomain-1"}, mediatype: "banner", value: openrtb_ext.ExtBidPrebidMeta{ @@ -109,13 +109,13 @@ func TestExtBidPrebidMeta(t *testing.T) { }, }, { - resp: MsqResponseBids{}, + resp: msqResponseBids{}, adomains: nil, mediatype: "banner", value: openrtb_ext.ExtBidPrebidMeta{MediaType: "banner"}, }, { - resp: MsqResponseBids{Video: &MsqResponseBidsVideo{Xml: "not-nil"}}, + resp: msqResponseBids{Video: &msqResponseBidsVideo{Xml: "not-nil"}}, adomains: nil, mediatype: "video", value: openrtb_ext.ExtBidPrebidMeta{MediaType: "video"}, @@ -133,16 +133,16 @@ func TestExtBidPrebidMeta(t *testing.T) { func TestExtBid(t *testing.T) { tests := []struct { // tests inputs - resp MsqResponseBids + resp msqResponseBids // tests expected-results raw json.RawMessage }{ { - resp: MsqResponseBids{Dsa: openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, + resp: msqResponseBids{Dsa: openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, raw: json.RawMessage([]byte(`{"dsa":{"behalf":"behalf"}}`)), }, { - resp: MsqResponseBids{}, + resp: msqResponseBids{}, raw: nil, }, } From c7221a2502e38e963155ea6b535810afcbeac6a3 Mon Sep 17 00:00:00 2001 From: Alexandre <101182841+mediasquare-alexandre@users.noreply.github.com> Date: Wed, 30 Oct 2024 14:52:48 +0100 Subject: [PATCH 06/11] fix: mediasquare.yaml - endpoint --- static/bidder-info/mediasquare.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/bidder-info/mediasquare.yaml b/static/bidder-info/mediasquare.yaml index 05f82862010..6056cc30a8d 100644 --- a/static/bidder-info/mediasquare.yaml +++ b/static/bidder-info/mediasquare.yaml @@ -1,4 +1,4 @@ -endpoint: "http://pbs-front.mediasquare.fr/msq_prebid" +endpoint: "https://pbs-front.mediasquare.fr/msq_prebid" endpointCompression: gzip gvlVendorID: 791 modifyingVastXmlAllowed: true From 3a1f90da215bb4e15d05497346f5aa9cd9cc55f6 Mon Sep 17 00:00:00 2001 From: Alexandre <101182841+mediasquare-alexandre@users.noreply.github.com> Date: Mon, 4 Nov 2024 00:16:17 +0100 Subject: [PATCH 07/11] Update adapter_builders.go --- exchange/adapter_builders.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index 767ddc9fa32..a153c70ebc9 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -133,7 +133,7 @@ import ( "github.com/prebid/prebid-server/v3/adapters/marsmedia" "github.com/prebid/prebid-server/v3/adapters/mediago" "github.com/prebid/prebid-server/v3/adapters/medianet" - "github.com/prebid/prebid-server/v2/adapters/mediasquare" + "github.com/prebid/prebid-server/v3/adapters/mediasquare" "github.com/prebid/prebid-server/v3/adapters/melozen" "github.com/prebid/prebid-server/v3/adapters/metax" "github.com/prebid/prebid-server/v3/adapters/mgid" From 747bff30a911aa1117742e7ed80742791f87599a Mon Sep 17 00:00:00 2001 From: harribey Date: Mon, 4 Nov 2024 00:26:53 +0100 Subject: [PATCH 08/11] fix: import -- v2 -> v3 --- adapters/mediasquare/mediasquare.go | 8 ++++---- adapters/mediasquare/mediasquare_test.go | 6 +++--- adapters/mediasquare/structs.go | 2 +- adapters/mediasquare/structs_test.go | 4 ++-- adapters/mediasquare/utils.go | 2 +- adapters/mediasquare/utils_test.go | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/adapters/mediasquare/mediasquare.go b/adapters/mediasquare/mediasquare.go index 74cecbba009..ce630a57ef8 100644 --- a/adapters/mediasquare/mediasquare.go +++ b/adapters/mediasquare/mediasquare.go @@ -6,10 +6,10 @@ import ( "net/http" "github.com/prebid/openrtb/v20/openrtb2" - "github.com/prebid/prebid-server/v2/adapters" - "github.com/prebid/prebid-server/v2/config" - "github.com/prebid/prebid-server/v2/errortypes" - "github.com/prebid/prebid-server/v2/openrtb_ext" + "github.com/prebid/prebid-server/v3/adapters" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/errortypes" + "github.com/prebid/prebid-server/v3/openrtb_ext" ) type adapter struct { diff --git a/adapters/mediasquare/mediasquare_test.go b/adapters/mediasquare/mediasquare_test.go index ec87b3984d1..9e9940de215 100644 --- a/adapters/mediasquare/mediasquare_test.go +++ b/adapters/mediasquare/mediasquare_test.go @@ -8,9 +8,9 @@ import ( "testing" "github.com/prebid/openrtb/v20/openrtb2" - "github.com/prebid/prebid-server/v2/adapters" - "github.com/prebid/prebid-server/v2/config" - "github.com/prebid/prebid-server/v2/errortypes" + "github.com/prebid/prebid-server/v3/adapters" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/errortypes" "github.com/stretchr/testify/assert" ) diff --git a/adapters/mediasquare/structs.go b/adapters/mediasquare/structs.go index cf367b04214..25eb8411e23 100644 --- a/adapters/mediasquare/structs.go +++ b/adapters/mediasquare/structs.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/prebid/openrtb/v20/openrtb2" - "github.com/prebid/prebid-server/v2/adapters" + "github.com/prebid/prebid-server/v3/adapters" ) // msqResponse: Bid-Response sent by mediasquare. diff --git a/adapters/mediasquare/structs_test.go b/adapters/mediasquare/structs_test.go index e172c5b195a..5275dc0742b 100644 --- a/adapters/mediasquare/structs_test.go +++ b/adapters/mediasquare/structs_test.go @@ -6,8 +6,8 @@ import ( "testing" "github.com/prebid/openrtb/v20/openrtb2" - "github.com/prebid/prebid-server/v2/adapters" - "github.com/prebid/prebid-server/v2/openrtb_ext" + "github.com/prebid/prebid-server/v3/adapters" + "github.com/prebid/prebid-server/v3/openrtb_ext" "github.com/stretchr/testify/assert" ) diff --git a/adapters/mediasquare/utils.go b/adapters/mediasquare/utils.go index 1d7f7b0db37..e68b0e7d3b8 100644 --- a/adapters/mediasquare/utils.go +++ b/adapters/mediasquare/utils.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/prebid/openrtb/v20/openrtb2" - "github.com/prebid/prebid-server/v2/openrtb_ext" + "github.com/prebid/prebid-server/v3/openrtb_ext" ) var headerList = map[string][]string{ diff --git a/adapters/mediasquare/utils_test.go b/adapters/mediasquare/utils_test.go index 5b32652d771..d42ab4c2e26 100644 --- a/adapters/mediasquare/utils_test.go +++ b/adapters/mediasquare/utils_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/prebid/openrtb/v20/openrtb2" - "github.com/prebid/prebid-server/v2/openrtb_ext" + "github.com/prebid/prebid-server/v3/openrtb_ext" "github.com/stretchr/testify/assert" ) From 8de23e94eea5645d26d84a7ef7a6ac52af028acd Mon Sep 17 00:00:00 2001 From: harribey Date: Mon, 4 Nov 2024 00:39:53 +0100 Subject: [PATCH 09/11] try-fix: exchange/adapter_builder.go --- exchange/adapter_builders.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index a153c70ebc9..90ae025f4fe 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -133,7 +133,7 @@ import ( "github.com/prebid/prebid-server/v3/adapters/marsmedia" "github.com/prebid/prebid-server/v3/adapters/mediago" "github.com/prebid/prebid-server/v3/adapters/medianet" - "github.com/prebid/prebid-server/v3/adapters/mediasquare" + "github.com/prebid/prebid-server/v3/adapters/mediasquare" "github.com/prebid/prebid-server/v3/adapters/melozen" "github.com/prebid/prebid-server/v3/adapters/metax" "github.com/prebid/prebid-server/v3/adapters/mgid" From 0a0e2b268dc27e070aaa0516ce333694694d89b3 Mon Sep 17 00:00:00 2001 From: mediasquare-alexandre Date: Thu, 28 Nov 2024 11:28:22 +0100 Subject: [PATCH 10/11] mediasquare-adapter: ++mediasquaretest/json-tests --- adapters/mediasquare/mediasquare.go | 14 +- adapters/mediasquare/mediasquare_test.go | 136 +-------- .../exemplary/simple-test-banner.json | 262 ++++++++++++++++++ .../exemplary/simple-test-native.json | 233 ++++++++++++++++ .../exemplary/simple-test-video.json | 202 ++++++++++++++ .../supplemental/some-errors-test-0.json | 128 +++++++++ .../supplemental/some-errors-test-1.json | 153 ++++++++++ .../supplemental/some-errors-test-2.json | 154 ++++++++++ .../supplemental/some-errors-test-3.json | 88 ++++++ adapters/mediasquare/parsers.go | 58 ++-- adapters/mediasquare/parsers_test.go | 175 ------------ adapters/mediasquare/structs.go | 34 +-- adapters/mediasquare/structs_test.go | 173 ------------ adapters/mediasquare/utils.go | 7 +- adapters/mediasquare/utils_test.go | 153 ---------- 15 files changed, 1292 insertions(+), 678 deletions(-) create mode 100644 adapters/mediasquare/mediasquaretest/exemplary/simple-test-banner.json create mode 100644 adapters/mediasquare/mediasquaretest/exemplary/simple-test-native.json create mode 100644 adapters/mediasquare/mediasquaretest/exemplary/simple-test-video.json create mode 100644 adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-0.json create mode 100644 adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-1.json create mode 100644 adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-2.json create mode 100644 adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-3.json delete mode 100644 adapters/mediasquare/parsers_test.go delete mode 100644 adapters/mediasquare/structs_test.go delete mode 100644 adapters/mediasquare/utils_test.go diff --git a/adapters/mediasquare/mediasquare.go b/adapters/mediasquare/mediasquare.go index ce630a57ef8..26a213b3d52 100644 --- a/adapters/mediasquare/mediasquare.go +++ b/adapters/mediasquare/mediasquare.go @@ -1,7 +1,6 @@ package mediasquare import ( - "encoding/json" "fmt" "net/http" @@ -10,6 +9,7 @@ import ( "github.com/prebid/prebid-server/v3/config" "github.com/prebid/prebid-server/v3/errortypes" "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/prebid/prebid-server/v3/util/jsonutil" ) type adapter struct { @@ -45,11 +45,11 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E } ) - if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { + if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { errs = append(errs, errorWritter(" imp[ext]", err, len(imp.Ext) == 0)) continue } - if err := json.Unmarshal(bidderExt.Bidder, &msqExt); err != nil { + if err := jsonutil.Unmarshal(bidderExt.Bidder, &msqExt); err != nil { errs = append(errs, errorWritter(" imp-bidder[ext]", err, len(bidderExt.Bidder) == 0)) continue } @@ -76,7 +76,7 @@ func (a *adapter) makeRequest(request *openrtb2.BidRequest, msqParams *msqParame err = errorWritter(" msqParams", nil, true) return } - if requestJsonBytes, err = json.Marshal(msqParams); err == nil { + if requestJsonBytes, err = jsonutil.Marshal(msqParams); err == nil { var headers http.Header = headerList requestData = &adapters.RequestData{ Method: "POST", @@ -86,8 +86,9 @@ func (a *adapter) makeRequest(request *openrtb2.BidRequest, msqParams *msqParame ImpIDs: openrtb_ext.GetImpIDs(request.Imp), } } else { - err = errorWritter(" json.Marshal", err, false) + err = errorWritter(" jsonutil.Marshal", err, false) } + return } @@ -109,11 +110,12 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R } var msqResp msqResponse - if err := json.Unmarshal(response.Body, &msqResp); err != nil { + if err := jsonutil.Unmarshal(response.Body, &msqResp); err != nil { errs = []error{&errortypes.BadServerResponse{Message: fmt.Sprintf(" Bad server response: %s.", err.Error())}} return bidderResponse, errs } bidderResponse = adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) msqResp.getContent(bidderResponse) + return bidderResponse, errs } diff --git a/adapters/mediasquare/mediasquare_test.go b/adapters/mediasquare/mediasquare_test.go index 9e9940de215..0650ca79155 100644 --- a/adapters/mediasquare/mediasquare_test.go +++ b/adapters/mediasquare/mediasquare_test.go @@ -1,135 +1,29 @@ package mediasquare import ( - "encoding/json" - "errors" - "fmt" - "net/http" "testing" - "github.com/prebid/openrtb/v20/openrtb2" "github.com/prebid/prebid-server/v3/adapters" + "github.com/prebid/prebid-server/v3/adapters/adapterstest" "github.com/prebid/prebid-server/v3/config" - "github.com/prebid/prebid-server/v3/errortypes" + "github.com/prebid/prebid-server/v3/openrtb_ext" "github.com/stretchr/testify/assert" ) -func TestMakeBids(t *testing.T) { - a, _ := Builder("mediasquare", config.Adapter{}, config.Server{}) - tests := []struct { - // tests inputs - request *openrtb2.BidRequest - requestData *adapters.RequestData - // tests expected-results - response *adapters.ResponseData - bidderResponse *adapters.BidderResponse - errs []error - }{ - { - request: &openrtb2.BidRequest{}, - requestData: &adapters.RequestData{}, - - response: &adapters.ResponseData{StatusCode: http.StatusBadRequest}, - bidderResponse: nil, - errs: []error{&errortypes.BadInput{ - Message: fmt.Sprintf(" Unexpected status code: %d.", http.StatusBadRequest), - }}, - }, - { - request: &openrtb2.BidRequest{}, - requestData: &adapters.RequestData{}, - - response: &adapters.ResponseData{StatusCode: 42}, - bidderResponse: nil, - errs: []error{&errortypes.BadServerResponse{ - Message: fmt.Sprintf(" Unexpected status code: %d. Run with request.debug = 1 for more info.", 42), - }}, - }, - { - request: &openrtb2.BidRequest{}, - requestData: &adapters.RequestData{}, - - response: &adapters.ResponseData{StatusCode: http.StatusOK, Body: []byte("")}, - bidderResponse: nil, - errs: []error{&errortypes.BadServerResponse{ - Message: fmt.Sprint(" Bad server response: unexpected end of JSON input."), - }}, - }, - { - request: &openrtb2.BidRequest{Imp: []openrtb2.Imp{{ID: "1"}, {ID: "2"}, {ID: "3"}}}, - requestData: &adapters.RequestData{}, - - response: &adapters.ResponseData{StatusCode: http.StatusOK, Body: []byte(`{"id":"id-ok"}`)}, - bidderResponse: &adapters.BidderResponse{ - Currency: "USD", - Bids: []*adapters.TypedBid{}, - FledgeAuctionConfigs: nil, - }, - errs: nil, - }, - } - - for index, test := range tests { - resp, errs := a.MakeBids(test.request, test.requestData, test.response) - - errsVal, _ := json.Marshal(errs) - errsExp, _ := json.Marshal(test.errs) - assert.Equal(t, test.bidderResponse, resp, fmt.Sprintf("resp >> index: %d.", index)) - assert.Equal(t, errsExp, errsVal, fmt.Sprintf("errs >> index: %d.", index)) - } -} - -func TestMakeRequest(t *testing.T) { - a, _ := Builder("mediasquare", config.Adapter{Endpoint: "edp-mediasquare"}, config.Server{}) - tests := []struct { - // tests inputs - request *openrtb2.BidRequest - reqInfo *adapters.ExtraRequestInfo - // tests expected-results - result []*adapters.RequestData - errs []error - }{ - { - request: &openrtb2.BidRequest{ID: "id-ok", - Imp: []openrtb2.Imp{ - {ID: "0"}, - {ID: "1", Ext: []byte(`{"id-1":"content-1"}`)}, - {ID: "-42", Ext: []byte(`{"prebid":-42}`)}, - {ID: "-1", Ext: []byte(`{"bidder":{}}`)}, - {ID: "-0", Ext: []byte(`{"bidder":{"owner":"owner-ok","code":0}}`), Native: &openrtb2.Native{}}, - {ID: "42", Ext: []byte(`{"bidder":{"owner":"owner-ok","code":"code-ok"}}`), Native: &openrtb2.Native{}}, - }, - }, - reqInfo: &adapters.ExtraRequestInfo{GlobalPrivacyControlHeader: "global-ok"}, - - result: []*adapters.RequestData{ - {Method: "POST", Uri: "edp-mediasquare", Headers: headerList, ImpIDs: []string{"0", "1", "-42", "-1", "-0", "42"}, - Body: []byte(`{"codes":[{"adunit":"","auctionid":"id-ok","bidid":"42","code":"code-ok","owner":"owner-ok","mediatypes":{"banner":null,"video":null,"native":{"title":null,"icon":null,"image":null,"clickUrl":null,"displayUrl":null,"privacyLink":null,"privacyIcon":null,"cta":null,"rating":null,"downloads":null,"likes":null,"price":null,"saleprice":null,"address":null,"phone":null,"body":null,"body2":null,"sponsoredBy":null,"sizes":null,"type":"native"}},"floor":{"*":{}}}],"gdpr":{"consent_required":false,"consent_string":""},"type":"pbs","dsa":"","tech":{"device":null,"app":null},"test":false}`)}, - }, - errs: []error{ - errors.New(" imp[ext]: is empty."), - errors.New(" imp-bidder[ext]: is empty."), - errors.New(" imp[ext]: json: cannot unmarshal number into Go struct field ExtImpBidder.prebid of type openrtb_ext.ExtImpPrebid"), - errors.New(" imp-bidder[ext]: json: cannot unmarshal number into Go struct field ImpExtMediasquare.code of type string"), - }, - }, - } - for index, test := range tests { - result, errs := a.MakeRequests(test.request, test.reqInfo) - - resultBytes, _ := json.Marshal(result) - expectedBytes, _ := json.Marshal(test.result) - assert.Equal(t, string(expectedBytes), string(resultBytes), fmt.Sprintf("result >> index: %d.", index)) - assert.Equal(t, test.errs, errs, fmt.Sprintf("errs >> index: %d.", index)) +func TestBidderMediasquare(t *testing.T) { + bidder, buildErr := Builder(openrtb_ext.BidderMediasquare, config.Adapter{ + Endpoint: "https://pbs-front.mediasquare.fr/msq_prebid"}, + config.Server{ExternalUrl: "https://pbs-front.mediasquare.fr/msq_prebid", GvlID: 1, DataCenter: "2"}) + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) } - // test reference : []error on empty request. - _, errs := a.MakeRequests(nil, nil) - assert.Equal(t, []error{errorWritter(" request", nil, true)}, errs, "[]error") + // MakeRequests : case request is empty. + resp, errs := bidder.MakeRequests(nil, nil) + expectingErrors := []error{errorWritter(" request", nil, true)} + assert.Equal(t, []*adapters.RequestData(nil), resp, "resp, was supposed to be empty result.") + assert.Equal(t, expectingErrors, errs, "errs, was supposed to be :", expectingErrors) - var msqAdapter adapter - _, errNil := msqAdapter.makeRequest(nil, nil) - assert.Equal(t, errorWritter(" msqParams", nil, true), errNil, "error errNil") - _, errChan := msqAdapter.makeRequest(nil, &msqParameters{DSA: make(chan int)}) - assert.Equal(t, errorWritter(" json.Marshal", errors.New("json: unsupported type: chan int"), false), errChan, "error errChan") + // starting json-tests. + adapterstest.RunJSONBidderTest(t, "mediasquaretest", bidder) } diff --git a/adapters/mediasquare/mediasquaretest/exemplary/simple-test-banner.json b/adapters/mediasquare/mediasquaretest/exemplary/simple-test-banner.json new file mode 100644 index 00000000000..4f8030b3ffe --- /dev/null +++ b/adapters/mediasquare/mediasquaretest/exemplary/simple-test-banner.json @@ -0,0 +1,262 @@ +{ + "mockBidRequest": { + "id": "70e5672c-515b-406e-967c-fcc2b04de04f", + "imp": [ + { + "id": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "bidfloor": 1, + "bidfloorcur": "USD", + "banner": { + "w": 970, + "h": 250 + }, + "ext": { + "bidder": { + "owner": "test", + "code": "publishername_atf_desktop_rg_pave" + } + } + }, + { + "id": "2059a3e6-71a3-43ea-8290-b5ceb13d35a8", + "bidfloor": 0.01, + "bidfloorcur": "USD", + "banner": { + "format": [ + { "w": 300, "h": 250 }, + { "w": 300, "h": 600 }, + { "w": 120, "h": 600 } + ] + }, + "ext": { + "bidder": { + "owner": "test", + "code": "publishername_atf_desktop_rg_pave" + } + } + } + ], + "app": { + "content": {}, + "domain": "debug.mediasquare.fr", + "id": "app-id-test", + "name": "debug.mediasquare.fr", + "publisher": { + "id": "MEDIA_SQUARE" + } + }, + "device": { + "devicetype": 1, + "geo": { + "country": "FRA", + "ipservice": 3 + }, + "ip": "92.154.6.0", + "language": "fr", + "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" + }, + "regs": { + "gdpr": 1, + "ext": { + "dsa": "mediasquare-test" + } + }, + "user": { + "consent": "there-is-a-real-cs-in-it" + }, + "test": 1 + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://pbs-front.mediasquare.fr/msq_prebid", + "body": { + "codes": [ + { + "adunit": "", + "auctionid": "70e5672c-515b-406e-967c-fcc2b04de04f", + "bidid": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "code": "publishername_atf_desktop_rg_pave", + "owner": "test", + "mediatypes": { + "banner": { + "sizes": [[970, 250]] + }, + "video": null, + "native": null + }, + "floor": { + "970x250": { + "floor": 1, + "currency": "USD" + } + } + }, + { + "adunit": "", + "auctionid": "70e5672c-515b-406e-967c-fcc2b04de04f", + "bidid": "2059a3e6-71a3-43ea-8290-b5ceb13d35a8", + "code": "publishername_atf_desktop_rg_pave", + "owner": "test", + "mediatypes": { + "banner": { + "sizes": [ + [300, 250], + [300, 600], + [120, 600] + ] + }, + "video": null, + "native": null + }, + "floor": { + "120x600": { + "floor": 0.01, + "currency": "USD" + }, + "300x250": { + "floor": 0.01, + "currency": "USD" + }, + "300x600": { + "floor": 0.01, + "currency": "USD" + } + } + } + ], + "gdpr": { + "consent_required": true, + "consent_string": "there-is-a-real-cs-in-it" + }, + "dsa": "mediasquare-test", + "tech": { + "device": { + "geo": { + "ipservice": 3, + "country": "FRA" + }, + "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36", + "ip": "92.154.6.0", + "devicetype": 1, + "language": "fr" + }, + "app": { + "id": "app-id-test", + "name": "debug.mediasquare.fr", + "domain": "debug.mediasquare.fr", + "publisher": { + "id": "MEDIA_SQUARE" + }, + "content": {} + } + }, + "type": "pbs", + "test": true + }, + "impIDs": [ + "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "2059a3e6-71a3-43ea-8290-b5ceb13d35a8" + ] + }, + + "mockResponse": { + "status": 200, + "body": { + "infos": { + "version": "1.6.1", + "description": "mediasquare prebid client endpoint" + }, + "cookies": null, + "responses": [ + { + "ad": "\u003c!-- This is an example --\u003e", + "bid_id": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "bidder": "fakeBidder", + "code": "test/publishername_atf_desktop_rg_pave", + "cpm": 2, + "increment": 2, + "currency": "USD", + "creative_id": "fakeBidder|fakeCreative", + "width": 250, + "net_revenue": true, + "transaction_id": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "ttl": 20000, + "adomain": ["mediasquare.fr"], + "dsa": "dsa-mediasquare", + "hasConsent": true + }, + { + "ad": "\u003c!-- This is an example --\u003e", + "bid_id": "2059a3e6-71a3-43ea-8290-b5ceb13d35a8", + "bidder": "fakeBidder", + "code": "test/publishername_atf_desktop_rg_pave", + "cpm": 0.02, + "increment": 0.02, + "currency": "USD", + "creative_id": "fakeBidder|fakeCreative", + "width": 250, + "net_revenue": true, + "transaction_id": "2059a3e6-71a3-43ea-8290-b5ceb13d35a8", + "ttl": 20000, + "adomain": ["mediasquare.fr"], + "hasConsent": true + } + ], + "Calc_cpm": { + "2059a3e6-71a3-43ea-8290-b5ceb13d35a8": { + "TmpCpmMax": 0, + "CpmMax": 0.02 + }, + "2c35e25e-e7d3-41bf-b810-06a449f456b9": { + "TmpCpmMax": 0, + "CpmMax": 2 + } + } + } + } + } + ], + "expectedBidResponses": [ + { + "Currency": "USD", + "Bids": [ + { + "Bid": { + "id": "", + "impid": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "price": 2, + "adm": "\u003c!-- This is an example --\u003e", + "adomain": ["mediasquare.fr"], + "crid": "fakeBidder|fakeCreative", + "w": 250, + "mtype": 1 + }, + "BidMeta": { + "advertiserDomains": ["mediasquare.fr"], + "mediaType": "banner" + }, + "type": "banner" + }, + { + "Bid": { + "id": "", + "impid": "2059a3e6-71a3-43ea-8290-b5ceb13d35a8", + "price": 0.02, + "adm": "\u003c!-- This is an example --\u003e", + "adomain": ["mediasquare.fr"], + "crid": "fakeBidder|fakeCreative", + "w": 250, + "mtype": 1 + }, + "BidMeta": { + "advertiserDomains": ["mediasquare.fr"], + "mediaType": "banner" + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/mediasquare/mediasquaretest/exemplary/simple-test-native.json b/adapters/mediasquare/mediasquaretest/exemplary/simple-test-native.json new file mode 100644 index 00000000000..611fb7f96bf --- /dev/null +++ b/adapters/mediasquare/mediasquaretest/exemplary/simple-test-native.json @@ -0,0 +1,233 @@ +{ + "mockBidRequest": { + "id": "70e5672c-515b-406e-967c-fcc2b04de04f", + "imp": [ + { + "id": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "bidfloor": 1, + "bidfloorcur": "USD", + "tagid": "msq_tag_200123_native", + "banner": null, + "video": null, + "native": { + "ext": { + "title": { "required": true, "len": 80 }, + "body": { "required": true }, + "icon": { + "required": false, + "aspect_ratio": { + "min_width": 50, + "min_height": 50, + "ratio_width": 2, + "ratio_height": 3 + } + }, + "image": { + "required": false, + "aspect_ratio": { + "min_width": 300, + "min_height": 200, + "ratio_width": 2, + "ratio_height": 3 + } + }, + "clickUrl": { "required": true }, + "sizes": [ + [970, 250], + [728, 90] + ] + } + }, + "ext": { + "bidder": { + "owner": "test", + "code": "publishername_atf_desktop_rg_pave" + } + } + } + ], + "app": { + "content": {}, + "domain": "debug.mediasquare.fr", + "id": "app-id-test", + "name": "debug.mediasquare.fr", + "publisher": { + "id": "MEDIA_SQUARE" + } + }, + "device": { + "devicetype": 1, + "geo": { + "country": "FRA", + "ipservice": 3 + }, + "ip": "92.154.6.0", + "language": "fr", + "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" + }, + "regs": { + "gdpr": 1, + "ext": { + "dsa": "mediasquare-test" + } + }, + "user": { + "consent": "there-is-a-real-cs-in-it" + }, + "test": 1 + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://pbs-front.mediasquare.fr/msq_prebid", + "body": { + "codes": [ + { + "owner": "test", + "code": "publishername_atf_desktop_rg_pave", + "adunit": "msq_tag_200123_native", + "auctionid": "70e5672c-515b-406e-967c-fcc2b04de04f", + "bidid": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "mediatypes": { + "video": null, + "banner": null, + "native": { + "address": null, + "title": { "required": true, "len": 80 }, + "body": { "required": true }, + "body2": null, + "type": "native", + "cta": null, + "displayUrl": null, + "downloads": null, + "icon": { + "required": false, + "aspect_ratio": { + "min_width": 50, + "min_height": 50, + "ratio_width": 2, + "ratio_height": 3 + } + }, + "image": { + "required": false, + "aspect_ratio": { + "min_width": 300, + "min_height": 200, + "ratio_width": 2, + "ratio_height": 3 + } + }, + "likes": null, + "phone": null, + "price": null, + "privacyIcon": null, + "privacyLink": null, + "rating": null, + "saleprice": null, + "sizes": [ + [970, 250], + [728, 90] + ], + "sponsoredBy": null, + "clickUrl": { "required": true } + } + }, + "floor": { + "*": { "floor": 1, "currency": "USD" }, + "970x250": { "floor": 1, "currency": "USD" }, + "728x90": { "floor": 1, "currency": "USD" } + } + } + ], + "gdpr": { + "consent_string": "there-is-a-real-cs-in-it", + "consent_required": true + }, + "type": "pbs", + "dsa": "mediasquare-test", + "tech": { + "device": { + "geo": { + "ipservice": 3, + "country": "FRA" + }, + "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36", + "ip": "92.154.6.0", + "devicetype": 1, + "language": "fr" + }, + "app": { + "id": "app-id-test", + "name": "debug.mediasquare.fr", + "domain": "debug.mediasquare.fr", + "publisher": { + "id": "MEDIA_SQUARE" + }, + "content": {} + } + }, + "test": true + }, + "impIDs": ["2c35e25e-e7d3-41bf-b810-06a449f456b9"] + }, + + "mockResponse": { + "status": 200, + "body": { + "infos": { + "version": "1.6.1", + "description": "mediasquare prebid client endpoint" + }, + "cookies": null, + "responses": [ + { + "bid_id": "4e2d4580c1da1", + "bidder": "fakeBidder", + "code": "test/publishername_atf_desktop_rg_pave", + "cpm": 1, + "increment": 1, + "currency": "USD", + "creative_id": "fakeBidder|fakeCreative", + "net_revenue": true, + "transaction_id": "4e2d4580c1da1", + "ttl": 20000, + "native": { + "clickUrl": "http: //i.am.a/URL", + "title": "Learn about this awesome thing" + }, + "adomain": ["mediasquare.fr"], + "hasConsent": true + } + ], + "Calc_cpm": { "4e2d4580c1da1": { "TmpCpmMax": 0, "CpmMax": 1 } } + } + } + } + ], + "expectedBidResponses": [ + { + "Currency": "USD", + "Bids": [ + { + "bid": { + "id": "", + "impid": "4e2d4580c1da1", + "price": 1, + "adomain": ["mediasquare.fr"], + "crid": "fakeBidder|fakeCreative", + "mtype": 4 + }, + "bidmeta": { + "advertiserDomains": ["mediasquare.fr"], + "mediaType": "native" + }, + "type": "native", + "bidvideo": null, + "dealpriority": 0 + } + ] + } + ] +} diff --git a/adapters/mediasquare/mediasquaretest/exemplary/simple-test-video.json b/adapters/mediasquare/mediasquaretest/exemplary/simple-test-video.json new file mode 100644 index 00000000000..15a249764af --- /dev/null +++ b/adapters/mediasquare/mediasquaretest/exemplary/simple-test-video.json @@ -0,0 +1,202 @@ +{ + "mockBidRequest": { + "id": "70e5672c-515b-406e-967c-fcc2b04de04f", + "imp": [ + { + "id": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "bidfloor": 1, + "tagid": "msq_tag_200123_native", + "banner": null, + "native": null, + "video": { + "mimes": ["video/mp4"], + "minduration": 10, + "maxduration": 23, + "placement": 1, + "w": 800, + "h": 600, + "plcmt": 1, + "ext": { + "context": "context-test", + "linearity": 0, + "playersize": [[800, 600]] + } + }, + "ext": { + "bidder": { + "owner": "test", + "code": "publishername_atf_desktop_rg_video" + } + } + } + ], + "app": { + "content": {}, + "domain": "debug.mediasquare.fr", + "id": "app-id-test", + "name": "debug.mediasquare.fr", + "publisher": { + "id": "MEDIA_SQUARE" + } + }, + "device": { + "devicetype": 1, + "geo": { + "country": "FRA", + "ipservice": 3 + }, + "ip": "92.154.6.0", + "language": "fr", + "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" + }, + "regs": { + "gdpr": 1, + "ext": { + "dsa": "mediasquare-test" + } + }, + "user": { + "consent": "there-is-a-real-cs-in-it" + }, + "test": 1 + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://pbs-front.mediasquare.fr/msq_prebid", + "body": { + "codes": [ + { + "owner": "test", + "code": "publishername_atf_desktop_rg_video", + "adunit": "msq_tag_200123_native", + "auctionid": "70e5672c-515b-406e-967c-fcc2b04de04f", + "bidid": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "mediatypes": { + "video": { + "mimes": ["video/mp4"], + "minbitrate": null, + "maxbitrate": null, + "minduration": 10, + "maxduration": 23, + "placement": 1, + "linearity": 0, + "w": 800, + "h": 600, + "playbackmethod": null, + "playersize": [[800, 600]], + "api": null, + "boxingallower": null, + "context": "context-test", + "delivery": null, + "plcmt": 1, + "protocols": null, + "skip": null, + "skipafter": null, + "startdelay": null + }, + "banner": null, + "native": null + }, + "floor": { + "*": { "floor": 1 }, + "800x600": { "floor": 1 } + } + } + ], + "gdpr": { + "consent_string": "there-is-a-real-cs-in-it", + "consent_required": true + }, + "type": "pbs", + "dsa": "mediasquare-test", + "tech": { + "device": { + "geo": { + "ipservice": 3, + "country": "FRA" + }, + "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36", + "ip": "92.154.6.0", + "devicetype": 1, + "language": "fr" + }, + "app": { + "id": "app-id-test", + "name": "debug.mediasquare.fr", + "domain": "debug.mediasquare.fr", + "publisher": { + "id": "MEDIA_SQUARE" + }, + "content": {} + } + }, + "test": true + }, + "impIDs": ["2c35e25e-e7d3-41bf-b810-06a449f456b9"] + }, + + "mockResponse": { + "status": 200, + "body": { + "infos": { + "version": "1.6.1", + "description": "mediasquare prebid client endpoint" + }, + "cookies": null, + "responses": [ + { + "bid_id": "4e2d4580c1da1", + "bidder": "fakeBidder", + "code": "test/publishername_atf_desktop_rg_pave", + "cpm": 1, + "increment": 1, + "currency": "USD", + "creative_id": "fakeBidder|fakeCreative", + "net_revenue": true, + "transaction_id": "4e2d4580c1da1", + "ttl": 20000, + "video": { + "xml": "Some Xml Vast", + "url": "https://dummy.domain.tv/some_vast" + }, + "adomain": ["mediasquare.fr"], + "dsa": { + "behalf": "dsa-test-behalf", + "paid": "dsa-test-paid" + }, + "hasConsent": true + } + ], + "Calc_cpm": { "4e2d4580c1da1": { "TmpCpmMax": 0, "CpmMax": 1 } } + } + } + } + ], + "expectedBidResponses": [ + { + "Currency": "USD", + "Bids": [ + { + "bid": { + "id": "", + "impid": "4e2d4580c1da1", + "price": 1, + "adomain": ["mediasquare.fr"], + "crid": "fakeBidder|fakeCreative", + "mtype": 2, + "ext": { + "dsa": { "behalf": "dsa-test-behalf", "paid": "dsa-test-paid" } + } + }, + "meta": { + "advertiserDomains": ["mediasquare.fr"], + "mediaType": "video" + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-0.json b/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-0.json new file mode 100644 index 00000000000..f550121b3ab --- /dev/null +++ b/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-0.json @@ -0,0 +1,128 @@ +{ + "mockBidRequest": { + "id": "id-ok", + "imp": [ + { "id": "0" }, + { "id": "1", "ext": { "id-1": "content-1" } }, + { "id": "-42", "ext": { "prebid": -42 } }, + { "id": "-1", "ext": { "bidder": {} } }, + { + "id": "-0", + "native": { "request": "" }, + "ext": { "bidder": { "owner": "test", "code": 0 } } + }, + { + "id": "42", + "native": { "request": "" }, + "ext": { + "bidder": { + "owner": "test", + "code": "publishername_atf_desktop_rg_pave" + } + } + } + ], + "test": 1 + }, + "expectedMakeRequestsErrors": [ + { + "value": " imp[ext]: is empty.", + "comparison": "literal" + }, + { + "value": " imp-bidder[ext]: is empty.", + "comparison": "literal" + }, + { + "value": " imp[ext]: cannot unmarshal adapters.ExtImpBidder.Prebid: expect { or n, but found -", + "comparison": "literal" + }, + { + "value": " imp-bidder[ext]: cannot unmarshal openrtb_ext.ImpExtMediasquare.Code: expects \" or n, but found 0", + "comparison": "literal" + } + ], + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://pbs-front.mediasquare.fr/msq_prebid", + "body": { + "codes": [ + { + "adunit": "", + "auctionid": "id-ok", + "bidid": "42", + "code": "publishername_atf_desktop_rg_pave", + "owner": "test", + "mediatypes": { + "banner": null, + "video": null, + "native": { + "title": null, + "icon": null, + "image": null, + "clickUrl": null, + "displayUrl": null, + "privacyLink": null, + "privacyIcon": null, + "cta": null, + "rating": null, + "downloads": null, + "likes": null, + "price": null, + "saleprice": null, + "address": null, + "phone": null, + "body": null, + "body2": null, + "sponsoredBy": null, + "sizes": null, + "type": "native" + } + }, + "floor": { "*": {} } + } + ], + "gdpr": { "consent_required": false, "consent_string": "" }, + "type": "pbs", + "dsa": "", + "tech": { "device": null, "app": null }, + "test": true + }, + "impIDs": ["0", "1", "-42", "-1", "-0", "42"] + }, + + "mockResponse": { + "status": 200, + "body": { + "id": "id-ok", + "seatbid": [ + { + "seat": "mediasquare", + "bid": [ + { + "id": "42", + "impid": "1", + "price": 1.5, + "adm": "some-test-ad", + "crid": "test-crid", + "h": 50, + "w": 320, + "mtype": 1 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [] + } + ] +} diff --git a/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-1.json b/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-1.json new file mode 100644 index 00000000000..fca42ab512f --- /dev/null +++ b/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-1.json @@ -0,0 +1,153 @@ +{ + "mockBidRequest": { + "id": "70e5672c-515b-406e-967c-fcc2b04de04f", + "imp": [ + { + "id": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "bidfloor": 1, + "tagid": "msq_tag_200123_native", + "banner": null, + "native": null, + "video": { + "mimes": ["video/mp4"], + "minduration": 10, + "maxduration": 23, + "placement": 1, + "w": 800, + "h": 600, + "plcmt": 1, + "ext": { + "context": "context-test", + "linearity": 0, + "playersize": [[800, 600]] + } + }, + "ext": { + "bidder": { + "owner": "test", + "code": "publishername_atf_desktop_rg_video" + } + } + } + ], + "app": { + "content": {}, + "domain": "debug.mediasquare.fr", + "id": "app-id-test", + "name": "debug.mediasquare.fr", + "publisher": { + "id": "MEDIA_SQUARE" + } + }, + "device": { + "devicetype": 1, + "geo": { + "country": "FRA", + "ipservice": 3 + }, + "ip": "92.154.6.0", + "language": "fr", + "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" + }, + "regs": { + "gdpr": 1, + "ext": { + "dsa": null + } + }, + "user": { + "ext": { + "consent": "consent-covering" + } + }, + "test": 1 + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://pbs-front.mediasquare.fr/msq_prebid", + "body": { + "codes": [ + { + "owner": "test", + "code": "publishername_atf_desktop_rg_video", + "adunit": "msq_tag_200123_native", + "auctionid": "70e5672c-515b-406e-967c-fcc2b04de04f", + "bidid": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "mediatypes": { + "video": { + "mimes": ["video/mp4"], + "minbitrate": null, + "maxbitrate": null, + "minduration": 10, + "maxduration": 23, + "placement": 1, + "linearity": 0, + "w": 800, + "h": 600, + "playbackmethod": null, + "playersize": [[800, 600]], + "api": null, + "boxingallower": null, + "context": "context-test", + "delivery": null, + "plcmt": 1, + "protocols": null, + "skip": null, + "skipafter": null, + "startdelay": null + }, + "banner": null, + "native": null + }, + "floor": { + "*": { "floor": 1 }, + "800x600": { "floor": 1 } + } + } + ], + "gdpr": { + "consent_string": "consent-covering", + "consent_required": true + }, + "type": "pbs", + "dsa": "", + "tech": { + "device": { + "geo": { + "ipservice": 3, + "country": "FRA" + }, + "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36", + "ip": "92.154.6.0", + "devicetype": 1, + "language": "fr" + }, + "app": { + "id": "app-id-test", + "name": "debug.mediasquare.fr", + "domain": "debug.mediasquare.fr", + "publisher": { + "id": "MEDIA_SQUARE" + }, + "content": {} + } + }, + "test": true + }, + "impIDs": ["2c35e25e-e7d3-41bf-b810-06a449f456b9"] + }, + "mockResponse": { + "status": 400, + "body": null + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": " Unexpected status code: 400.", + "comparison": "literal" + } + ] +} diff --git a/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-2.json b/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-2.json new file mode 100644 index 00000000000..b24da988fde --- /dev/null +++ b/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-2.json @@ -0,0 +1,154 @@ +{ + "mockBidRequest": { + "id": "70e5672c-515b-406e-967c-fcc2b04de04f", + "imp": [ + { + "id": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "bidfloor": 1, + "tagid": "msq_tag_200123_native", + "banner": null, + "native": null, + "video": { + "mimes": ["video/mp4"], + "minduration": 10, + "maxduration": 23, + "placement": 1, + "w": 800, + "h": 600, + "plcmt": 1, + "ext": { + "context": "context-test", + "linearity": 0, + "playersize": [[800, 600]] + } + }, + "ext": { + "bidder": { + "owner": "test", + "code": "publishername_atf_desktop_rg_video" + } + } + } + ], + "app": { + "content": {}, + "domain": "debug.mediasquare.fr", + "id": "app-id-test", + "name": "debug.mediasquare.fr", + "publisher": { + "id": "MEDIA_SQUARE" + } + }, + "device": { + "devicetype": 1, + "geo": { + "country": "FRA", + "ipservice": 3 + }, + "ip": "92.154.6.0", + "language": "fr", + "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" + }, + "regs": { + "gdpr": 1, + "ext": { + "dsa": null + } + }, + "user": { + "ext": { + "gdpr": "consent-covering" + } + }, + "test": 1 + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://pbs-front.mediasquare.fr/msq_prebid", + "body": { + "codes": [ + { + "owner": "test", + "code": "publishername_atf_desktop_rg_video", + "adunit": "msq_tag_200123_native", + "auctionid": "70e5672c-515b-406e-967c-fcc2b04de04f", + "bidid": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "mediatypes": { + "video": { + "mimes": ["video/mp4"], + "minbitrate": null, + "maxbitrate": null, + "minduration": 10, + "maxduration": 23, + "placement": 1, + "linearity": 0, + "w": 800, + "h": 600, + "playbackmethod": null, + "playersize": [[800, 600]], + "api": null, + "boxingallower": null, + "context": "context-test", + "delivery": null, + "plcmt": 1, + "protocols": null, + "skip": null, + "skipafter": null, + "startdelay": null + }, + "banner": null, + "native": null + }, + "floor": { + "*": { "floor": 1 }, + "800x600": { "floor": 1 } + } + } + ], + "gdpr": { + "consent_string": "consent-covering", + "consent_required": true + }, + "type": "pbs", + "dsa": "", + "tech": { + "device": { + "geo": { + "ipservice": 3, + "country": "FRA" + }, + "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36", + "ip": "92.154.6.0", + "devicetype": 1, + "language": "fr" + }, + "app": { + "id": "app-id-test", + "name": "debug.mediasquare.fr", + "domain": "debug.mediasquare.fr", + "publisher": { + "id": "MEDIA_SQUARE" + }, + "content": {} + } + }, + "test": true + }, + "impIDs": ["2c35e25e-e7d3-41bf-b810-06a449f456b9"] + }, + + "mockResponse": { + "status": 42, + "body": null + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": " Unexpected status code: 42. Run with request.debug = 1 for more info.", + "comparison": "literal" + } + ] +} diff --git a/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-3.json b/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-3.json new file mode 100644 index 00000000000..d001d19c1da --- /dev/null +++ b/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-3.json @@ -0,0 +1,88 @@ +{ + "mockBidRequest": { + "imp": [ + { + "id": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "bidfloor": 1, + "tagid": "msq_tag_200123_native", + "banner": null, + "native": null, + "video": { + "mimes": ["video/mp4"], + "minduration": 10, + "maxduration": 23, + "placement": 1, + "w": 800, + "h": 600, + "plcmt": 1, + "ext": { + "context": "context-test", + "linearity": 0, + "playersize": [[800, 600]] + } + }, + "ext": null + } + ], + "app": null, + "device": null, + "regs": { + "gdpr": null, + "ext": { + "dsa": null + } + }, + "user": { + "ext": { + "consent": null + } + }, + "test": 1 + }, + "expectedMakeRequestsErrors": [ + { + "value": " imp-bidder[ext]: is empty.", + "comparison": "literal" + } + ], + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://pbs-front.mediasquare.fr/msq_prebid", + "body": { + "codes": null, + "gdpr": { + "consent_string": "", + "consent_required": false + }, + "type": "pbs", + "dsa": "", + "tech": { + "device": null, + "app": null + }, + "test": true + }, + "impIDs": ["2c35e25e-e7d3-41bf-b810-06a449f456b9"] + }, + + "mockResponse": { + "status": 200, + "body": { + "infos": { + "version": "42", + "description": "test-description", + "hostname": null + }, + "responses": "lol" + } + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": " Bad server response: cannot unmarshal mediasquare.msqResponse.Responses: decode slice: expect [ or n, but found \".", + "comparison": "literal" + } + ] +} diff --git a/adapters/mediasquare/parsers.go b/adapters/mediasquare/parsers.go index 94b86996ca0..dd01b73efa8 100644 --- a/adapters/mediasquare/parsers.go +++ b/adapters/mediasquare/parsers.go @@ -1,13 +1,13 @@ package mediasquare import ( - "encoding/json" "fmt" "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v3/util/jsonutil" ) -// parserDSA: Struct used to extracts dsa content of a json. +// parserDSA: Struct used to extracts dsa content of a jsonutil. type parserDSA struct { DSA interface{} `json:"dsa,omitempty"` } @@ -15,7 +15,7 @@ type parserDSA struct { // setContent: Unmarshal a []byte into the parserDSA struct. func (parser *parserDSA) setContent(extJsonBytes []byte) error { if len(extJsonBytes) > 0 { - if err := json.Unmarshal(extJsonBytes, parser); err != nil { + if err := jsonutil.Unmarshal(extJsonBytes, parser); err != nil { return errorWritter(" extJsonBytes", err, false) } return nil @@ -24,18 +24,18 @@ func (parser *parserDSA) setContent(extJsonBytes []byte) error { } // getValue: Returns the DSA value as a string, defaultly returns empty-string. -func (parser parserDSA) getValue(request *openrtb2.BidRequest) string { +func (parser parserDSA) getValue(request *openrtb2.BidRequest) (dsa string) { if request == nil || request.Regs == nil { - return "" + return } parser.setContent(request.Regs.Ext) if parser.DSA != nil { - return fmt.Sprint(parser.DSA) + dsa = fmt.Sprint(parser.DSA) } - return "" + return } -// parserGDPR: Struct used to extract pair of GDPR/Consent of a json. +// parserGDPR: Struct used to extract pair of GDPR/Consent of a jsonutil. type parserGDPR struct { GDPR interface{} `json:"gdpr,omitempty"` Consent interface{} `json:"consent,omitempty"` @@ -44,7 +44,7 @@ type parserGDPR struct { // setContent: Unmarshal a []byte into the parserGDPR struct. func (parser *parserGDPR) setContent(extJsonBytes []byte) error { if len(extJsonBytes) > 0 { - if err := json.Unmarshal(extJsonBytes, parser); err != nil { + if err := jsonutil.Unmarshal(extJsonBytes, parser); err != nil { return errorWritter(" extJsonBytes", err, false) } return nil @@ -53,34 +53,32 @@ func (parser *parserGDPR) setContent(extJsonBytes []byte) error { } // value: Returns the consent or GDPR-string depending of the parserGDPR content, defaulty return empty-string. -func (parser *parserGDPR) value() string { +func (parser *parserGDPR) value() (gdpr string) { switch { case parser.Consent != nil: - return fmt.Sprint(parser.Consent) + gdpr = fmt.Sprint(parser.Consent) case parser.GDPR != nil: - return fmt.Sprint(parser.GDPR) + gdpr = fmt.Sprint(parser.GDPR) } - return "" + return } // getValue: Returns the consent or GDPR-string depending on the openrtb2.User content, defaultly returns empty-string. -func (parser parserGDPR) getValue(field string, request *openrtb2.BidRequest) string { - if request == nil { - return "" - } - switch { - case field == "consent_requirement" && request.Regs != nil: - if ptrInt8ToBool(request.Regs.GDPR) { - return "true" - } - return "false" - case field == "consent_string" && request.User != nil: - if len(request.User.Consent) > 0 { - return request.User.Consent +func (parser parserGDPR) getValue(field string, request *openrtb2.BidRequest) (gdpr string) { + if request != nil { + switch { + case field == "consent_requirement" && request.Regs != nil: + gdpr = "false" + if ptrInt8ToBool(request.Regs.GDPR) { + gdpr = "true" + } + case field == "consent_string" && request.User != nil: + gdpr = request.User.Consent + if len(gdpr) <= 0 { + parser.setContent(request.User.Ext) + gdpr = parser.value() + } } - parser.setContent(request.User.Ext) - return parser.value() - default: - return "" } + return } diff --git a/adapters/mediasquare/parsers_test.go b/adapters/mediasquare/parsers_test.go deleted file mode 100644 index dee536cd8a4..00000000000 --- a/adapters/mediasquare/parsers_test.go +++ /dev/null @@ -1,175 +0,0 @@ -package mediasquare - -import ( - "encoding/json" - "errors" - "fmt" - "testing" - - "github.com/prebid/openrtb/v20/openrtb2" - "github.com/stretchr/testify/assert" -) - -func TestParserDSA(t *testing.T) { - tests := []struct { - // tests inputs - parser parserDSA - request openrtb2.BidRequest - // tests expected-results - getValue string - setContent error - expected parserDSA - }{ - { - parser: parserDSA{}, - request: openrtb2.BidRequest{ - Regs: &openrtb2.Regs{ - Ext: []byte(`{"dsa":"dsa-ok"}`), - }, - }, - - getValue: "dsa-ok", - setContent: nil, - expected: parserDSA{DSA: "dsa-ok"}, - }, - { - parser: parserDSA{}, - request: openrtb2.BidRequest{ - Regs: &openrtb2.Regs{ - Ext: []byte(`{"no-dsa":"no-dsa"}`), - }, - }, - - getValue: "", - setContent: nil, - expected: parserDSA{}, - }, - { - parser: parserDSA{}, - request: openrtb2.BidRequest{ - Regs: &openrtb2.Regs{ - Ext: []byte(``), - }, - }, - - getValue: "", - setContent: errorWritter(" extJsonBytes", nil, true), - expected: parserDSA{}, - }, - } - for index, test := range tests { - assert.Equal(t, test.getValue, test.parser.getValue(&test.request), fmt.Sprintf("getValue >> index: %d", index)) - assert.Equal(t, test.setContent, test.parser.setContent(test.request.Regs.Ext), fmt.Sprintf("setContent >> index: %d", index)) - assert.Equal(t, test.expected, test.parser, fmt.Sprintf("exactValue >> index: %d", index)) - } - - var pError parserDSA - assert.Equal(t, pError.setContent([]byte(`{invalid json}`)), - errorWritter(" extJsonBytes", errors.New("invalid character 'i' looking for beginning of object key string"), false)) -} - -func TestParserGDPR(t *testing.T) { - tests := []struct { - //tests inputs - parser parserGDPR - request openrtb2.BidRequest - extJsonBytes []byte - // tests expected-results - getValue struct { - field string - value string - } - setContent error - value string - }{ - { - parser: parserGDPR{}, - request: openrtb2.BidRequest{User: &openrtb2.User{Ext: json.RawMessage(`{"gdpr":"gdpr-ok-user"}`)}}, - extJsonBytes: []byte(`{"gdpr":"gdpr-ok-extjson"}`), - - getValue: struct { - field string - value string - }{field: "consent_string", value: "gdpr-ok-user"}, - setContent: nil, - value: "gdpr-ok-extjson", - }, - { - parser: parserGDPR{}, - request: openrtb2.BidRequest{User: &openrtb2.User{Consent: "consent-ok-user"}}, - extJsonBytes: []byte(`{"gdpr":"gdpr-ok","consent":"consent-ok"}`), - - getValue: struct { - field string - value string - }{field: "consent_string", value: "consent-ok-user"}, - setContent: nil, - value: "consent-ok", - }, - { - parser: parserGDPR{}, - request: openrtb2.BidRequest{}, - extJsonBytes: []byte(""), - - getValue: struct { - field string - value string - }{field: "consent_string", value: ""}, - setContent: errorWritter(" extJsonBytes", nil, true), - value: "", - }, - { - parser: parserGDPR{}, - request: openrtb2.BidRequest{Regs: &openrtb2.Regs{GDPR: IntAsPtrInt8(0)}}, - extJsonBytes: []byte(""), - - getValue: struct { - field string - value string - }{field: "consent_requirement", value: "false"}, - setContent: nil, - value: "", - }, - { - parser: parserGDPR{}, - request: openrtb2.BidRequest{Regs: &openrtb2.Regs{GDPR: IntAsPtrInt8(1)}}, - extJsonBytes: []byte(""), - - getValue: struct { - field string - value string - }{field: "consent_requirement", value: "true"}, - setContent: nil, - value: "", - }, - { - parser: parserGDPR{}, - getValue: struct { - field string - value string - }{field: "null", value: ""}, - }, - } - - for index, test := range tests { - switch test.getValue.field { - case "consent_string": - assert.Equal(t, test.getValue.value, test.parser.getValue("consent_string", &(test.request)), fmt.Sprintf("[consent_string]: getValue >> index: %d", index)) - assert.Equal(t, test.setContent, test.parser.setContent(test.extJsonBytes), fmt.Sprintf("setContent >> index: %d", index)) - assert.Equal(t, test.value, test.parser.value(), fmt.Sprintf("value >> index: %d", index)) - case "consent_requirement": - assert.Equal(t, test.getValue.value, test.parser.getValue("consent_requirement", &(test.request)), fmt.Sprintf("[consent_requirement]: getValue >> index: %d", index)) - case "null": - assert.Equal(t, test.getValue.value, test.parser.getValue("null", nil), fmt.Sprintf("[consent_requirement]: getValue >> index: %d", index)) - } - } - - var pError parserGDPR - assert.Equal(t, pError.setContent([]byte(`{invalid json}`)), - errorWritter(" extJsonBytes", errors.New("invalid character 'i' looking for beginning of object key string"), false)) -} - -func IntAsPtrInt8(i int) *int8 { - val := int8(i) - return &val -} diff --git a/adapters/mediasquare/structs.go b/adapters/mediasquare/structs.go index 25eb8411e23..93af4d0bb5f 100644 --- a/adapters/mediasquare/structs.go +++ b/adapters/mediasquare/structs.go @@ -1,11 +1,11 @@ package mediasquare import ( - "encoding/json" "fmt" "github.com/prebid/openrtb/v20/openrtb2" "github.com/prebid/prebid-server/v3/adapters" + "github.com/prebid/prebid-server/v3/util/jsonutil" ) // msqResponse: Bid-Response sent by mediasquare. @@ -106,24 +106,24 @@ type msqFloor struct { } type mediaTypeNativeBasis struct { - Required bool - Len *int + Required bool `json:"required,omitempty"` + Len *int `json:"len,omitempty"` } type mediaTypeNativeImage struct { - Required bool - Sizes []*int + Required bool `json:"required"` + Sizes []*int `json:"sizes,omitempty"` Aspect_ratio *struct { - Min_width *int - Min_height *int - Ratio_width *int - Ratio_height *int - } + Min_width *int `json:"min_width,omitempty"` + Min_height *int `json:"min_height,omitempty"` + Ratio_width *int `json:"ratio_width,omitempty"` + Ratio_height *int `json:"ratio_height,omitempty"` + } `json:"aspect_ratio,omitempty"` } type mediaTypeNativeTitle struct { - Required bool - Len int + Required bool `json:"required,omitempty"` + Len int `json:"len,omitempty"` } type mediaTypeNative struct { @@ -214,9 +214,9 @@ func (msqParams *msqParametersCodes) setContent(currentImp openrtb2.Imp) (ok boo if currentImp.Video != nil { ok = true var video mediaTypeVideo - currentVideoBytes, _ := json.Marshal(currentImp.Video) - json.Unmarshal(currentVideoBytes, &video) - json.Unmarshal(currentImp.Video.Ext, &video) + currentVideoBytes, _ := jsonutil.Marshal(currentImp.Video) + jsonutil.Unmarshal(currentVideoBytes, &video) + jsonutil.Unmarshal(currentImp.Video.Ext, &video) msqParams.Mediatypes.Video = &video if msqParams.Mediatypes.Video != nil { @@ -230,7 +230,7 @@ func (msqParams *msqParametersCodes) setContent(currentImp openrtb2.Imp) (ok boo if currentImp.Banner != nil { ok = true var banner mediaTypeBanner - json.Unmarshal(currentImp.Banner.Ext, &banner) + jsonutil.Unmarshal(currentImp.Banner.Ext, &banner) msqParams.Mediatypes.Banner = &banner switch { @@ -258,7 +258,7 @@ func (msqParams *msqParametersCodes) setContent(currentImp openrtb2.Imp) (ok boo if currentImp.Native != nil { ok = true var native = mediaTypeNative{Type: "native"} - json.Unmarshal(currentImp.Native.Ext, &native) + jsonutil.Unmarshal(currentImp.Native.Ext, &native) msqParams.Mediatypes.Native = &native for _, nativeSizes := range msqParams.Mediatypes.Native.Sizes { diff --git a/adapters/mediasquare/structs_test.go b/adapters/mediasquare/structs_test.go deleted file mode 100644 index 5275dc0742b..00000000000 --- a/adapters/mediasquare/structs_test.go +++ /dev/null @@ -1,173 +0,0 @@ -package mediasquare - -import ( - "encoding/json" - "fmt" - "testing" - - "github.com/prebid/openrtb/v20/openrtb2" - "github.com/prebid/prebid-server/v3/adapters" - "github.com/prebid/prebid-server/v3/openrtb_ext" - "github.com/stretchr/testify/assert" -) - -func TestGetContent(t *testing.T) { - tests := []struct { - resp msqResponse - value adapters.BidderResponse - expected adapters.BidderResponse - }{ - { - resp: msqResponse{}, - value: adapters.BidderResponse{Currency: ""}, - expected: adapters.BidderResponse{Currency: ""}, - }, - { - resp: msqResponse{ - Responses: []msqResponseBids{ - { - ID: "id-ok", - Ad: "ad-ok", - Cpm: 42.0, - Currency: "currency-ok", - Width: 42, - Height: 42, - Bidder: "bidder-ok", - }, - }, - }, - value: adapters.BidderResponse{Currency: ""}, - expected: adapters.BidderResponse{ - Currency: "currency-ok", - Bids: []*adapters.TypedBid{ - { - Bid: &openrtb2.Bid{ - AdM: "ad-ok", - ID: "id-ok", - Price: 42.0, - W: 42, - H: 42, - MType: openrtb2.MarkupBanner, - }, - BidMeta: &openrtb_ext.ExtBidPrebidMeta{MediaType: "banner"}, - BidType: "banner", - }, - }, - }, - }, - } - - for index, test := range tests { - test.resp.getContent(&test.value) - expectedBytes, _ := json.Marshal(test.expected) - valueBytes, _ := json.Marshal(test.value) - assert.Equal(t, expectedBytes, valueBytes, - fmt.Sprintf("getContent >> index: %d\nexpect:%s\nvalue:%s", index, string(expectedBytes), string(valueBytes))) - } -} - -func TestSetContent(t *testing.T) { - tests := []struct { - // tests inputs - params msqParametersCodes - imp openrtb2.Imp - // tests expected-results - ok bool - }{ - { - params: msqParametersCodes{}, - imp: openrtb2.Imp{}, - ok: false, - }, - { - params: msqParametersCodes{ - AdUnit: "adunit-ok", - AuctionId: "auctionid-ok", - Code: "code-ok", - BidId: "bidid-ok", - }, - imp: openrtb2.Imp{ - ID: "imp-id", - Banner: &openrtb2.Banner{ - Format: []openrtb2.Format{{W: 1, H: 2}, {W: 2, H: 1}}, - Ext: json.RawMessage(`{"type":"raw-message-id"}`), - }, - BidFloor: 0.8, - }, - ok: true, - }, - { - params: msqParametersCodes{}, - imp: openrtb2.Imp{ - ID: "imp-id", - Video: &openrtb2.Video{ - MIMEs: []string{"MIMEs-ok"}, - W: intAsPtrInt64(42), H: intAsPtrInt64(42), - Ext: json.RawMessage(`{"h":42,"w":42}`), - }, - BidFloor: 0.8, - }, - ok: true, - }, - { - params: msqParametersCodes{}, - imp: openrtb2.Imp{ - ID: "imp-id", - Native: &openrtb2.Native{ - Ext: json.RawMessage(`{"sizes":[[42,42],[2,1],[1,1]]}`), - }, - BidFloor: 0.8, - }, - - ok: true, - }, - { - params: msqParametersCodes{}, - imp: openrtb2.Imp{ - ID: "imp-id", - Banner: &openrtb2.Banner{ - W: intAsPtrInt64(42), - H: intAsPtrInt64(42), - }, - BidFloor: 0.8, - }, - ok: true, - }, - } - - for index, test := range tests { - expected := test.params - - ok := test.params.setContent(test.imp) - assert.Equal(t, test.ok, ok, fmt.Sprintf("ok >> index: %d.", index)) - - switch index { - case 1: - expected.Mediatypes.Banner = &mediaTypeBanner{Sizes: [][]*int{{intAsPtrInt(1), intAsPtrInt(2)}, {intAsPtrInt(2), intAsPtrInt(1)}}} - expected.Floor = map[string]msqFloor{"1x2": {Price: 0.8}, "2x1": {Price: 0.8}} - case 2: - expected.Floor = map[string]msqFloor{"42x42": {Price: 0.8}, "*": {Price: 0.8}} - expected.Mediatypes.Video = &mediaTypeVideo{Mimes: []string{"MIMEs-ok"}, H: intAsPtrInt(42), W: intAsPtrInt(42)} - case 3: - expected.Mediatypes.Native = &mediaTypeNative{Type: "native", Sizes: [][]int{{42, 42}, {2, 1}, {1, 1}}} - expected.Floor = map[string]msqFloor{"1x1": {Price: 0.8}, "42x42": {Price: 0.8}, "2x1": {Price: 0.8}, "*": {Price: 0.8}} - case 4: - expected.Mediatypes.Banner = &mediaTypeBanner{Sizes: [][]*int{{intAsPtrInt(42), intAsPtrInt(42)}}} - expected.Floor = map[string]msqFloor{"42x42": {Price: 0.8}} - } - - expectedBytes, _ := json.Marshal(expected) - paramsBytes, _ := json.Marshal(test.params) - assert.Equal(t, string(expectedBytes), string(paramsBytes), fmt.Sprintf("assert >> index: %d.", index)) - } -} - -func intAsPtrInt(i int) *int { - val := i - return &val -} - -func intAsPtrInt64(i int64) *int64 { - val := i - return &val -} diff --git a/adapters/mediasquare/utils.go b/adapters/mediasquare/utils.go index e68b0e7d3b8..65704369138 100644 --- a/adapters/mediasquare/utils.go +++ b/adapters/mediasquare/utils.go @@ -6,6 +6,7 @@ import ( "github.com/prebid/openrtb/v20/openrtb2" "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/prebid/prebid-server/v3/util/jsonutil" ) var headerList = map[string][]string{ @@ -48,7 +49,7 @@ func (msqBids *msqResponseBids) bidType() openrtb_ext.BidType { func (msqBids *msqResponseBids) extBid() (raw json.RawMessage) { extBid, _ := msqBids.loadExtBid() if extBid.DSA != nil || extBid.Prebid != nil { - if bb, _ := json.Marshal(extBid); len(bb) > 0 { + if bb, _ := jsonutil.Marshal(extBid); len(bb) > 0 { raw = json.RawMessage(bb) } } @@ -58,13 +59,13 @@ func (msqBids *msqResponseBids) extBid() (raw json.RawMessage) { // loadExtBid: Extracts the ExtBid from msqBids as (openrtb_ext.ExtBid, []error). func (msqBids *msqResponseBids) loadExtBid() (extBid openrtb_ext.ExtBid, errs []error) { if msqBids.Dsa != nil { - bb, err := json.Marshal(msqBids.Dsa) + bb, err := jsonutil.Marshal(msqBids.Dsa) if err != nil { errs = append(errs, err) } if len(bb) > 0 { var dsa openrtb_ext.ExtBidDSA - if err = json.Unmarshal(bb, &dsa); err != nil { + if err = jsonutil.Unmarshal(bb, &dsa); err != nil { errs = append(errs, err) } else { extBid.DSA = &dsa diff --git a/adapters/mediasquare/utils_test.go b/adapters/mediasquare/utils_test.go deleted file mode 100644 index d42ab4c2e26..00000000000 --- a/adapters/mediasquare/utils_test.go +++ /dev/null @@ -1,153 +0,0 @@ -package mediasquare - -import ( - "encoding/json" - "fmt" - "testing" - - "github.com/prebid/openrtb/v20/openrtb2" - "github.com/prebid/prebid-server/v3/openrtb_ext" - "github.com/stretchr/testify/assert" -) - -func TestPtrInt8ToBool(t *testing.T) { - // map[tests-inputs]test-expected-results - tests := map[int8]bool{ - 0: false, - 1: true, - 42: false, - } - for value, expected := range tests { - assert.Equal(t, expected, ptrInt8ToBool(&value), fmt.Sprintf("ptrInt8ToBool >> value: (int8)=%d.", value)) - } - assert.Equal(t, false, ptrInt8ToBool(nil), "ptrInt8ToBool >> value(nil)") -} - -func TestMethodsType(t *testing.T) { - tests := []struct { - // tests inputs - resp msqResponseBids - // tests expected-results - bidType openrtb_ext.BidType - mType openrtb2.MarkupType - }{ - { - resp: msqResponseBids{Native: &msqResponseBidsNative{ClickUrl: "not-nil"}}, - bidType: "native", - mType: openrtb2.MarkupNative, - }, - { - resp: msqResponseBids{Video: &msqResponseBidsVideo{Xml: "not-nil"}}, - bidType: "video", - mType: openrtb2.MarkupVideo, - }, - { - resp: msqResponseBids{ID: "not-nil"}, - bidType: "banner", - mType: openrtb2.MarkupBanner, - }, - } - for testIndex, test := range tests { - assert.Equal(t, test.bidType, test.resp.bidType(), "bidType >> testIndex:", testIndex) - assert.Equal(t, test.mType, test.resp.mType(), "mType >> testIndex:", testIndex) - } -} - -func TestLoadExtBid(t *testing.T) { - tests := []struct { - // tests inputs - resp msqResponseBids - // tests expected-results - extBid openrtb_ext.ExtBid - isOk bool - }{ - { - resp: msqResponseBids{}, - extBid: openrtb_ext.ExtBid{DSA: nil, Prebid: nil}, - isOk: true, - }, - { - resp: msqResponseBids{Dsa: openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, - extBid: openrtb_ext.ExtBid{DSA: &openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, - isOk: true, - }, - { - resp: msqResponseBids{Dsa: "lol"}, - extBid: openrtb_ext.ExtBid{}, - isOk: false, - }, - { - resp: msqResponseBids{Dsa: make(chan int)}, - extBid: openrtb_ext.ExtBid{}, - isOk: false, - }, - } - - for index, test := range tests { - extBid, errs := test.resp.loadExtBid() - assert.Equal(t, test.extBid.DSA, extBid.DSA, fmt.Sprintf("extBid.DSA >> index: %d.", index)) - assert.Equal(t, test.isOk, errs == nil, fmt.Sprintf("isOk >> index: %d.", index)) - } -} - -func TestExtBidPrebidMeta(t *testing.T) { - tests := []struct { - // tests inputs - resp msqResponseBids - // tests expected-results - adomains []string - mediatype string - value openrtb_ext.ExtBidPrebidMeta - }{ - { - resp: msqResponseBids{ADomain: []string{"test-adomain-0", "test-adomain-1"}}, - adomains: []string{"test-adomain-0", "test-adomain-1"}, - mediatype: "banner", - value: openrtb_ext.ExtBidPrebidMeta{ - AdvertiserDomains: []string{"test-adomain-0", "test-adomain-1"}, - MediaType: "banner", - }, - }, - { - resp: msqResponseBids{}, - adomains: nil, - mediatype: "banner", - value: openrtb_ext.ExtBidPrebidMeta{MediaType: "banner"}, - }, - { - resp: msqResponseBids{Video: &msqResponseBidsVideo{Xml: "not-nil"}}, - adomains: nil, - mediatype: "video", - value: openrtb_ext.ExtBidPrebidMeta{MediaType: "video"}, - }, - } - - for index, test := range tests { - result := test.resp.extBidPrebidMeta() - assert.Equal(t, test.adomains, result.AdvertiserDomains, fmt.Sprintf("ADomains >> index: %d.", index)) - assert.Equal(t, test.mediatype, result.MediaType, fmt.Sprintf("MediaType >> index: %d.", index)) - assert.Equal(t, test.value, *result, fmt.Sprintf("ExactValue >> index: %d.", index)) - } -} - -func TestExtBid(t *testing.T) { - tests := []struct { - // tests inputs - resp msqResponseBids - // tests expected-results - raw json.RawMessage - }{ - { - resp: msqResponseBids{Dsa: openrtb_ext.ExtBidDSA{Behalf: "behalf"}}, - raw: json.RawMessage([]byte(`{"dsa":{"behalf":"behalf"}}`)), - }, - { - resp: msqResponseBids{}, - raw: nil, - }, - } - - for index, test := range tests { - assert.Equal(t, test.raw, test.resp.extBid(), fmt.Sprintf("Raw >> index: %d.", index)) - } -} From 01c1674efe9d5fe605ddc6a3026ccb4ed8fccd2b Mon Sep 17 00:00:00 2001 From: mediasquare-alexandre Date: Tue, 10 Dec 2024 18:24:26 +0100 Subject: [PATCH 11/11] renamed-files+params_test.go --- adapters/mediasquare/mediasquare.go | 7 +- adapters/mediasquare/mediasquare_test.go | 19 +- .../exemplary/multi-format.json | 501 ++++++++++++++++++ ...le-test-banner.json => simple-banner.json} | 0 ...le-test-native.json => simple-native.json} | 0 ...mple-test-video.json => simple-video.json} | 0 ...rors-test-0.json => no-valid-imp-ext.json} | 0 ...ors-test-3.json => no-valid-response.json} | 2 +- ...ome-errors-test-1.json => status-400.json} | 0 ...errors-test-2.json => status-not-200.json} | 0 adapters/mediasquare/params_test.go | 51 ++ 11 files changed, 575 insertions(+), 5 deletions(-) create mode 100644 adapters/mediasquare/mediasquaretest/exemplary/multi-format.json rename adapters/mediasquare/mediasquaretest/exemplary/{simple-test-banner.json => simple-banner.json} (100%) rename adapters/mediasquare/mediasquaretest/exemplary/{simple-test-native.json => simple-native.json} (100%) rename adapters/mediasquare/mediasquaretest/exemplary/{simple-test-video.json => simple-video.json} (100%) rename adapters/mediasquare/mediasquaretest/supplemental/{some-errors-test-0.json => no-valid-imp-ext.json} (100%) rename adapters/mediasquare/mediasquaretest/supplemental/{some-errors-test-3.json => no-valid-response.json} (91%) rename adapters/mediasquare/mediasquaretest/supplemental/{some-errors-test-1.json => status-400.json} (100%) rename adapters/mediasquare/mediasquaretest/supplemental/{some-errors-test-2.json => status-not-200.json} (100%) create mode 100644 adapters/mediasquare/params_test.go diff --git a/adapters/mediasquare/mediasquare.go b/adapters/mediasquare/mediasquare.go index 26a213b3d52..0c88557caa6 100644 --- a/adapters/mediasquare/mediasquare.go +++ b/adapters/mediasquare/mediasquare.go @@ -27,7 +27,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E requestData []*adapters.RequestData errs []error ) - if request == nil { + if request == nil || request.Imp == nil { errs = append(errs, errorWritter(" request", nil, true)) return nil, errs } @@ -111,7 +111,10 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R var msqResp msqResponse if err := jsonutil.Unmarshal(response.Body, &msqResp); err != nil { - errs = []error{&errortypes.BadServerResponse{Message: fmt.Sprintf(" Bad server response: %s.", err.Error())}} + errs = []error{&errortypes.BadServerResponse{ + Message: fmt.Sprintf(" Unexprected status code: %d. Bad server response: %s.", + http.StatusNotAcceptable, err.Error())}, + } return bidderResponse, errs } bidderResponse = adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) diff --git a/adapters/mediasquare/mediasquare_test.go b/adapters/mediasquare/mediasquare_test.go index 0650ca79155..3b8b8d46661 100644 --- a/adapters/mediasquare/mediasquare_test.go +++ b/adapters/mediasquare/mediasquare_test.go @@ -3,6 +3,7 @@ package mediasquare import ( "testing" + "github.com/prebid/openrtb/v20/openrtb2" "github.com/prebid/prebid-server/v3/adapters" "github.com/prebid/prebid-server/v3/adapters/adapterstest" "github.com/prebid/prebid-server/v3/config" @@ -17,6 +18,16 @@ func TestBidderMediasquare(t *testing.T) { if buildErr != nil { t.Fatalf("Builder returned unexpected error %v", buildErr) } + adapterstest.RunJSONBidderTest(t, "mediasquaretest", bidder) +} + +func TestMakeRequests(t *testing.T) { + bidder, buildErr := Builder(openrtb_ext.BidderMediasquare, config.Adapter{ + Endpoint: "https://pbs-front.mediasquare.fr/msq_prebid"}, + config.Server{ExternalUrl: "https://pbs-front.mediasquare.fr/msq_prebid", GvlID: 1, DataCenter: "2"}) + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) + } // MakeRequests : case request is empty. resp, errs := bidder.MakeRequests(nil, nil) @@ -24,6 +35,10 @@ func TestBidderMediasquare(t *testing.T) { assert.Equal(t, []*adapters.RequestData(nil), resp, "resp, was supposed to be empty result.") assert.Equal(t, expectingErrors, errs, "errs, was supposed to be :", expectingErrors) - // starting json-tests. - adapterstest.RunJSONBidderTest(t, "mediasquaretest", bidder) + // MakeRequests : case request.Imp is empty. + bidResquest := openrtb2.BidRequest{ID: "id-test", Imp: nil} + resp, errs = bidder.MakeRequests(&bidResquest, nil) + expectingErrors = []error{errorWritter(" request", nil, true)} + assert.Equal(t, []*adapters.RequestData(nil), resp, "resp, was supposed to be empty result.") + assert.Equal(t, expectingErrors, errs, "errs, was supposed to be :", expectingErrors) } diff --git a/adapters/mediasquare/mediasquaretest/exemplary/multi-format.json b/adapters/mediasquare/mediasquaretest/exemplary/multi-format.json new file mode 100644 index 00000000000..52b244342eb --- /dev/null +++ b/adapters/mediasquare/mediasquaretest/exemplary/multi-format.json @@ -0,0 +1,501 @@ +{ + "mockBidRequest": { + "id": "70e5672c-515b-406e-967c-fcc2b04de04f", + "imp": [ + { + "id": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "bidfloor": 1, + "bidfloorcur": "USD", + "banner": { + "w": 970, + "h": 250 + }, + "ext": { + "bidder": { + "owner": "test", + "code": "publishername_atf_desktop_rg_pave" + } + } + }, + { + "id": "2059a3e6-71a3-43ea-8290-b5ceb13d35a8", + "bidfloor": 0.01, + "bidfloorcur": "USD", + "banner": { + "format": [ + { "w": 300, "h": 250 }, + { "w": 300, "h": 600 }, + { "w": 120, "h": 600 } + ] + }, + "ext": { + "bidder": { + "owner": "test", + "code": "publishername_atf_desktop_rg_pave" + } + } + }, + { + "id": "2c35e25e-e7d3-41bf-b810-06a449f456c9", + "bidfloor": 1, + "bidfloorcur": "USD", + "tagid": "msq_tag_200123_native", + "banner": null, + "video": null, + "native": { + "ext": { + "title": { "required": true, "len": 80 }, + "body": { "required": true }, + "icon": { + "required": false, + "aspect_ratio": { + "min_width": 50, + "min_height": 50, + "ratio_width": 2, + "ratio_height": 3 + } + }, + "image": { + "required": false, + "aspect_ratio": { + "min_width": 300, + "min_height": 200, + "ratio_width": 2, + "ratio_height": 3 + } + }, + "clickUrl": { "required": true }, + "sizes": [ + [970, 250], + [728, 90] + ] + } + }, + "ext": { + "bidder": { + "owner": "test", + "code": "publishername_atf_desktop_rg_pave" + } + } + }, + { + "id": "2c35e25e-e7d3-41bf-b810-06a449f456d9", + "bidfloor": 1, + "tagid": "msq_tag_200123_native", + "banner": null, + "native": null, + "video": { + "mimes": ["video/mp4"], + "minduration": 10, + "maxduration": 23, + "placement": 1, + "w": 800, + "h": 600, + "plcmt": 1, + "ext": { + "context": "context-test", + "linearity": 0, + "playersize": [[800, 600]] + } + }, + "ext": { + "bidder": { + "owner": "test", + "code": "publishername_atf_desktop_rg_video" + } + } + } + ], + "app": { + "content": {}, + "domain": "debug.mediasquare.fr", + "id": "app-id-test", + "name": "debug.mediasquare.fr", + "publisher": { + "id": "MEDIA_SQUARE" + } + }, + "device": { + "devicetype": 1, + "geo": { + "country": "FRA", + "ipservice": 3 + }, + "ip": "92.154.6.0", + "language": "fr", + "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" + }, + "regs": { + "gdpr": 1, + "ext": { + "dsa": "mediasquare-test" + } + }, + "user": { + "consent": "there-is-a-real-cs-in-it" + }, + "test": 1 + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://pbs-front.mediasquare.fr/msq_prebid", + "body": { + "codes": [ + { + "adunit": "", + "auctionid": "70e5672c-515b-406e-967c-fcc2b04de04f", + "bidid": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "code": "publishername_atf_desktop_rg_pave", + "owner": "test", + "mediatypes": { + "banner": { + "sizes": [[970, 250]] + }, + "video": null, + "native": null + }, + "floor": { + "970x250": { + "floor": 1, + "currency": "USD" + } + } + }, + { + "adunit": "", + "auctionid": "70e5672c-515b-406e-967c-fcc2b04de04f", + "bidid": "2059a3e6-71a3-43ea-8290-b5ceb13d35a8", + "code": "publishername_atf_desktop_rg_pave", + "owner": "test", + "mediatypes": { + "banner": { + "sizes": [ + [300, 250], + [300, 600], + [120, 600] + ] + }, + "video": null, + "native": null + }, + "floor": { + "120x600": { + "floor": 0.01, + "currency": "USD" + }, + "300x250": { + "floor": 0.01, + "currency": "USD" + }, + "300x600": { + "floor": 0.01, + "currency": "USD" + } + } + }, + { + "owner": "test", + "code": "publishername_atf_desktop_rg_pave", + "adunit": "msq_tag_200123_native", + "auctionid": "70e5672c-515b-406e-967c-fcc2b04de04f", + "bidid": "2c35e25e-e7d3-41bf-b810-06a449f456c9", + "mediatypes": { + "video": null, + "banner": null, + "native": { + "address": null, + "title": { "required": true, "len": 80 }, + "body": { "required": true }, + "body2": null, + "type": "native", + "cta": null, + "displayUrl": null, + "downloads": null, + "icon": { + "required": false, + "aspect_ratio": { + "min_width": 50, + "min_height": 50, + "ratio_width": 2, + "ratio_height": 3 + } + }, + "image": { + "required": false, + "aspect_ratio": { + "min_width": 300, + "min_height": 200, + "ratio_width": 2, + "ratio_height": 3 + } + }, + "likes": null, + "phone": null, + "price": null, + "privacyIcon": null, + "privacyLink": null, + "rating": null, + "saleprice": null, + "sizes": [ + [970, 250], + [728, 90] + ], + "sponsoredBy": null, + "clickUrl": { "required": true } + } + }, + "floor": { + "*": { "floor": 1, "currency": "USD" }, + "970x250": { "floor": 1, "currency": "USD" }, + "728x90": { "floor": 1, "currency": "USD" } + } + }, + { + "owner": "test", + "code": "publishername_atf_desktop_rg_video", + "adunit": "msq_tag_200123_native", + "auctionid": "70e5672c-515b-406e-967c-fcc2b04de04f", + "bidid": "2c35e25e-e7d3-41bf-b810-06a449f456d9", + "mediatypes": { + "video": { + "mimes": ["video/mp4"], + "minbitrate": null, + "maxbitrate": null, + "minduration": 10, + "maxduration": 23, + "placement": 1, + "linearity": 0, + "w": 800, + "h": 600, + "playbackmethod": null, + "playersize": [[800, 600]], + "api": null, + "boxingallower": null, + "context": "context-test", + "delivery": null, + "plcmt": 1, + "protocols": null, + "skip": null, + "skipafter": null, + "startdelay": null + }, + "banner": null, + "native": null + }, + "floor": { + "*": { "floor": 1 }, + "800x600": { "floor": 1 } + } + } + ], + "gdpr": { + "consent_required": true, + "consent_string": "there-is-a-real-cs-in-it" + }, + "dsa": "mediasquare-test", + "tech": { + "device": { + "geo": { + "ipservice": 3, + "country": "FRA" + }, + "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36", + "ip": "92.154.6.0", + "devicetype": 1, + "language": "fr" + }, + "app": { + "id": "app-id-test", + "name": "debug.mediasquare.fr", + "domain": "debug.mediasquare.fr", + "publisher": { + "id": "MEDIA_SQUARE" + }, + "content": {} + } + }, + "type": "pbs", + "test": true + }, + "impIDs": [ + "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "2059a3e6-71a3-43ea-8290-b5ceb13d35a8", + "2c35e25e-e7d3-41bf-b810-06a449f456c9", + "2c35e25e-e7d3-41bf-b810-06a449f456d9" + ] + }, + + "mockResponse": { + "status": 200, + "body": { + "infos": { + "version": "1.6.1", + "description": "mediasquare prebid client endpoint" + }, + "cookies": null, + "responses": [ + { + "ad": "\u003c!-- This is an example --\u003e", + "bid_id": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "bidder": "fakeBidder", + "code": "test/publishername_atf_desktop_rg_pave", + "cpm": 2, + "increment": 2, + "currency": "USD", + "creative_id": "fakeBidder|fakeCreative", + "width": 250, + "net_revenue": true, + "transaction_id": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "ttl": 20000, + "adomain": ["mediasquare.fr"], + "hasConsent": true + }, + { + "ad": "\u003c!-- This is an example --\u003e", + "bid_id": "2059a3e6-71a3-43ea-8290-b5ceb13d35a8", + "bidder": "fakeBidder", + "code": "test/publishername_atf_desktop_rg_pave", + "cpm": 0.02, + "increment": 0.02, + "currency": "USD", + "creative_id": "fakeBidder|fakeCreative", + "width": 250, + "net_revenue": true, + "transaction_id": "2059a3e6-71a3-43ea-8290-b5ceb13d35a8", + "ttl": 20000, + "adomain": ["mediasquare.fr"], + "hasConsent": true + }, + { + "bid_id": "2c35e25e-e7d3-41bf-b810-06a449f456c9", + "bidder": "fakeBidder", + "code": "test/publishername_atf_desktop_rg_pave", + "cpm": 2, + "increment": 2, + "currency": "USD", + "creative_id": "fakeBidder|fakeCreative", + "net_revenue": true, + "transaction_id": "2c35e25e-e7d3-41bf-b810-06a449f456c9", + "ttl": 20000, + "native": { + "clickUrl": "http: //i.am.a/URL", + "title": "Learn about this awesome thing" + }, + "adomain": ["mediasquare.fr"], + "hasConsent": true + }, + { + "bid_id": "2c35e25e-e7d3-41bf-b810-06a449f456d9", + "bidder": "fakeBidder", + "code": "test/publishername_atf_desktop_rg_video", + "cpm": 2, + "increment": 2, + "currency": "USD", + "creative_id": "fakeBidder|fakeCreative", + "net_revenue": true, + "transaction_id": "2c35e25e-e7d3-41bf-b810-06a449f456d9", + "ttl": 20000, + "video": { + "xml": "Some Xml Vast", + "url": "https://dummy.domain.tv/some_vast" + }, + "adomain": ["mediasquare.fr"], + "hasConsent": true + } + ], + "Calc_cpm": { + "2059a3e6-71a3-43ea-8290-b5ceb13d35a8": { + "TmpCpmMax": 0, + "CpmMax": 0.02 + }, + "2c35e25e-e7d3-41bf-b810-06a449f456b9": { + "TmpCpmMax": 0, + "CpmMax": 2 + }, + "2c35e25e-e7d3-41bf-b810-06a449f456c9": { + "TmpCpmMax": 0, + "CpmMax": 2 + }, + "2c35e25e-e7d3-41bf-b810-06a449f456d9": { + "TmpCpmMax": 0, + "CpmMax": 2 + } + } + } + } + } + ], + "expectedBidResponses": [ + { + "Currency": "USD", + "Bids": [ + { + "Bid": { + "id": "", + "impid": "2c35e25e-e7d3-41bf-b810-06a449f456b9", + "price": 2, + "adm": "\u003c!-- This is an example --\u003e", + "adomain": ["mediasquare.fr"], + "crid": "fakeBidder|fakeCreative", + "w": 250, + "mtype": 1 + }, + "BidMeta": { + "advertiserDomains": ["mediasquare.fr"], + "mediaType": "banner" + }, + "type": "banner" + }, + { + "Bid": { + "id": "", + "impid": "2059a3e6-71a3-43ea-8290-b5ceb13d35a8", + "price": 0.02, + "adm": "\u003c!-- This is an example --\u003e", + "adomain": ["mediasquare.fr"], + "crid": "fakeBidder|fakeCreative", + "w": 250, + "mtype": 1 + }, + "BidMeta": { + "advertiserDomains": ["mediasquare.fr"], + "mediaType": "banner" + }, + "type": "banner" + }, + { + "Bid": { + "id": "", + "impid": "2c35e25e-e7d3-41bf-b810-06a449f456c9", + "price": 2, + "adomain": ["mediasquare.fr"], + "crid": "fakeBidder|fakeCreative", + "mtype": 4 + }, + "BidMeta": { + "advertiserDomains": ["mediasquare.fr"], + "mediaType": "native" + }, + "type": "native" + }, + { + "Bid": { + "id": "", + "impid": "2c35e25e-e7d3-41bf-b810-06a449f456d9", + "price": 2, + "adomain": ["mediasquare.fr"], + "crid": "fakeBidder|fakeCreative", + "mtype": 2 + }, + "BidMeta": { + "advertiserDomains": ["mediasquare.fr"], + "mediaType": "video" + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/mediasquare/mediasquaretest/exemplary/simple-test-banner.json b/adapters/mediasquare/mediasquaretest/exemplary/simple-banner.json similarity index 100% rename from adapters/mediasquare/mediasquaretest/exemplary/simple-test-banner.json rename to adapters/mediasquare/mediasquaretest/exemplary/simple-banner.json diff --git a/adapters/mediasquare/mediasquaretest/exemplary/simple-test-native.json b/adapters/mediasquare/mediasquaretest/exemplary/simple-native.json similarity index 100% rename from adapters/mediasquare/mediasquaretest/exemplary/simple-test-native.json rename to adapters/mediasquare/mediasquaretest/exemplary/simple-native.json diff --git a/adapters/mediasquare/mediasquaretest/exemplary/simple-test-video.json b/adapters/mediasquare/mediasquaretest/exemplary/simple-video.json similarity index 100% rename from adapters/mediasquare/mediasquaretest/exemplary/simple-test-video.json rename to adapters/mediasquare/mediasquaretest/exemplary/simple-video.json diff --git a/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-0.json b/adapters/mediasquare/mediasquaretest/supplemental/no-valid-imp-ext.json similarity index 100% rename from adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-0.json rename to adapters/mediasquare/mediasquaretest/supplemental/no-valid-imp-ext.json diff --git a/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-3.json b/adapters/mediasquare/mediasquaretest/supplemental/no-valid-response.json similarity index 91% rename from adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-3.json rename to adapters/mediasquare/mediasquaretest/supplemental/no-valid-response.json index d001d19c1da..3273618bd9b 100644 --- a/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-3.json +++ b/adapters/mediasquare/mediasquaretest/supplemental/no-valid-response.json @@ -81,7 +81,7 @@ ], "expectedMakeBidsErrors": [ { - "value": " Bad server response: cannot unmarshal mediasquare.msqResponse.Responses: decode slice: expect [ or n, but found \".", + "value": " Unexprected status code: 406. Bad server response: cannot unmarshal mediasquare.msqResponse.Responses: decode slice: expect [ or n, but found \".", "comparison": "literal" } ] diff --git a/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-1.json b/adapters/mediasquare/mediasquaretest/supplemental/status-400.json similarity index 100% rename from adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-1.json rename to adapters/mediasquare/mediasquaretest/supplemental/status-400.json diff --git a/adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-2.json b/adapters/mediasquare/mediasquaretest/supplemental/status-not-200.json similarity index 100% rename from adapters/mediasquare/mediasquaretest/supplemental/some-errors-test-2.json rename to adapters/mediasquare/mediasquaretest/supplemental/status-not-200.json diff --git a/adapters/mediasquare/params_test.go b/adapters/mediasquare/params_test.go new file mode 100644 index 00000000000..c9d2d5fe01e --- /dev/null +++ b/adapters/mediasquare/params_test.go @@ -0,0 +1,51 @@ +package mediasquare + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func TestValidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json schema. %v", err) + } + + for _, p := range validParams { + if err := validator.Validate(openrtb_ext.BidderMediasquare, json.RawMessage(p)); err != nil { + t.Errorf("Schema rejected valid params: %s", p) + } + } +} + +func TestInvalidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json schema. %v", err) + } + + for _, p := range invalidParams { + if err := validator.Validate(openrtb_ext.BidderMediasquare, json.RawMessage(p)); err == nil { + t.Errorf("Schema allowed invalid params: %s", p) + } + } +} + +var validParams = []string{ + `{"owner":"owner-test", "code": "code-test"}`, +} + +var invalidParams = []string{ + `{"owner":"owner-test", "code": 42}`, + `{"owner":"owner-test", "code": nil}`, + `{"owner":"owner-test", "code": ""}`, + `{"owner": 42, "code": "code-test"}`, + `{"owner": nil, "code": "code-test"}`, + `{"owner": "", "code": "code-test"}`, + `nil`, + ``, + `[]`, + `true`, +}