From 07dac81d77f83b072346ee3529ff1af65cd36604 Mon Sep 17 00:00:00 2001 From: pm-avinash-kapre <112699665+AvinashKapre@users.noreply.github.com> Date: Thu, 10 Oct 2024 13:03:57 +0530 Subject: [PATCH] UOE-11322: Forward displaymanager and displaymanagerver from app extension to pubmatic ssp (#935) * UOE-11322: Forward displaymanager and displaymanagerver from app extension to pubmatic ssp * test case name update * comment * review comment --- adapters/pubmatic/pubmatic.go | 31 +++- adapters/pubmatic/pubmatic_test.go | 244 ++++++++++++++++++++++++++--- 2 files changed, 255 insertions(+), 20 deletions(-) diff --git a/adapters/pubmatic/pubmatic.go b/adapters/pubmatic/pubmatic.go index eea6babf34e..27ac67255ba 100644 --- a/adapters/pubmatic/pubmatic.go +++ b/adapters/pubmatic/pubmatic.go @@ -113,6 +113,11 @@ func (a *PubmaticAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *ad extractWrapperExtFromImp := true extractPubIDFromImp := true + displayManager, displayManagerVer := "", "" + if request.App != nil && request.App.Ext != nil { + displayManager, displayManagerVer = getDisplayManagerAndVer(request.App) + } + newReqExt, cookies, err := extractPubmaticExtFromRequest(request) if err != nil { return nil, []error{err} @@ -125,7 +130,7 @@ func (a *PubmaticAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *ad impFloorsMap := map[string][]float64{} for i := 0; i < len(request.Imp); i++ { - wrapperExtFromImp, pubIDFromImp, floors, err := parseImpressionObject(&request.Imp[i], extractWrapperExtFromImp, extractPubIDFromImp) + wrapperExtFromImp, pubIDFromImp, floors, err := parseImpressionObject(&request.Imp[i], extractWrapperExtFromImp, extractPubIDFromImp, displayManager, displayManagerVer) // If the parsing is failed, remove imp and add the error. if err != nil { errs = append(errs, err) @@ -383,7 +388,7 @@ func assignBannerWidthAndHeight(banner *openrtb2.Banner, w, h int64) *openrtb2.B } // parseImpressionObject parse the imp to get it ready to send to pubmatic -func parseImpressionObject(imp *openrtb2.Imp, extractWrapperExtFromImp, extractPubIDFromImp bool) (*pubmaticWrapperExt, string, []float64, error) { +func parseImpressionObject(imp *openrtb2.Imp, extractWrapperExtFromImp, extractPubIDFromImp bool, displayManager, displayManagerVer string) (*pubmaticWrapperExt, string, []float64, error) { var wrapExt *pubmaticWrapperExt var pubID string var floors []float64 @@ -397,6 +402,12 @@ func parseImpressionObject(imp *openrtb2.Imp, extractWrapperExtFromImp, extractP imp.Audio = nil } + // Populate imp.displaymanager and imp.displaymanagerver if the SDK failed to do it. + if imp.DisplayManager == "" && imp.DisplayManagerVer == "" && displayManager != "" && displayManagerVer != "" { + imp.DisplayManager = displayManager + imp.DisplayManagerVer = displayManagerVer + } + var bidderExt ExtImpBidderPubmatic if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { return wrapExt, pubID, floors, err @@ -854,3 +865,19 @@ func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server co } return bidder, nil } + +// getDisplayManagerAndVer returns the display manager and version from the request.app.ext or request.app.prebid.ext source and version +func getDisplayManagerAndVer(app *openrtb2.App) (string, string) { + if source, err := jsonparser.GetString(app.Ext, openrtb_ext.PrebidExtKey, "source"); err == nil && source != "" { + if version, err := jsonparser.GetString(app.Ext, openrtb_ext.PrebidExtKey, "version"); err == nil && version != "" { + return source, version + } + } + + if source, err := jsonparser.GetString(app.Ext, "source"); err == nil && source != "" { + if version, err := jsonparser.GetString(app.Ext, "version"); err == nil && version != "" { + return source, version + } + } + return "", "" +} diff --git a/adapters/pubmatic/pubmatic_test.go b/adapters/pubmatic/pubmatic_test.go index 78d495ba983..981a8025dd2 100644 --- a/adapters/pubmatic/pubmatic_test.go +++ b/adapters/pubmatic/pubmatic_test.go @@ -81,15 +81,22 @@ func TestParseImpressionObject(t *testing.T) { imp *openrtb2.Imp extractWrapperExtFromImp bool extractPubIDFromImp bool + displayManager string + displayManagerVer string + } + type want struct { + bidfloor float64 + impExt json.RawMessage + displayManager string + displayManagerVer string } tests := []struct { name string args args expectedWrapperExt *pubmaticWrapperExt expectedPublisherId string + want want wantErr bool - expectedBidfloor float64 - expectedImpExt json.RawMessage }{ { name: "imp.bidfloor empty and kadfloor set", @@ -99,8 +106,10 @@ func TestParseImpressionObject(t *testing.T) { Ext: json.RawMessage(`{"bidder":{"kadfloor":"0.12"}}`), }, }, - expectedBidfloor: 0.12, - expectedImpExt: json.RawMessage(nil), + want: want{ + bidfloor: 0.12, + impExt: json.RawMessage(nil), + }, }, { name: "imp.bidfloor set and kadfloor empty", @@ -111,8 +120,10 @@ func TestParseImpressionObject(t *testing.T) { Ext: json.RawMessage(`{"bidder":{}}`), }, }, - expectedBidfloor: 0.12, - expectedImpExt: json.RawMessage(nil), + want: want{ + bidfloor: 0.12, + impExt: json.RawMessage(nil), + }, }, { name: "imp.bidfloor set and kadfloor invalid", @@ -123,8 +134,10 @@ func TestParseImpressionObject(t *testing.T) { Ext: json.RawMessage(`{"bidder":{"kadfloor":"aaa"}}`), }, }, - expectedBidfloor: 0.12, - expectedImpExt: json.RawMessage(nil), + want: want{ + bidfloor: 0.12, + impExt: json.RawMessage(nil), + }, }, { name: "imp.bidfloor set and kadfloor set, higher imp.bidfloor", @@ -135,7 +148,10 @@ func TestParseImpressionObject(t *testing.T) { Ext: json.RawMessage(`{"bidder":{"kadfloor":"0.11"}}`), }, }, - expectedBidfloor: 0.12, + want: want{ + bidfloor: 0.12, + impExt: json.RawMessage(nil), + }, }, { name: "imp.bidfloor set and kadfloor set, higher kadfloor", @@ -146,8 +162,10 @@ func TestParseImpressionObject(t *testing.T) { Ext: json.RawMessage(`{"bidder":{"kadfloor":"0.13"}}`), }, }, - expectedBidfloor: 0.13, - expectedImpExt: json.RawMessage(nil), + want: want{ + bidfloor: 0.13, + impExt: json.RawMessage(nil), + }, }, { name: "kadfloor string set with whitespace", @@ -158,8 +176,10 @@ func TestParseImpressionObject(t *testing.T) { Ext: json.RawMessage(`{"bidder":{"kadfloor":" \t 0.13 "}}`), }, }, - expectedBidfloor: 0.13, - expectedImpExt: json.RawMessage(nil), + want: want{ + bidfloor: 0.13, + impExt: json.RawMessage(nil), + }, }, { name: "bidViewability Object is set in imp.ext.prebid.pubmatic, pass to imp.ext", @@ -169,7 +189,9 @@ func TestParseImpressionObject(t *testing.T) { Ext: json.RawMessage(`{"bidder":{"bidViewability":{"adSizes":{"728x90":{"createdAt":1679993940011,"rendered":20,"totalViewTime":424413,"viewed":17}},"adUnit":{"createdAt":1679993940011,"rendered":25,"totalViewTime":424413,"viewed":17}}}}`), }, }, - expectedImpExt: json.RawMessage(`{"bidViewability":{"adSizes":{"728x90":{"createdAt":1679993940011,"rendered":20,"totalViewTime":424413,"viewed":17}},"adUnit":{"createdAt":1679993940011,"rendered":25,"totalViewTime":424413,"viewed":17}}}`), + want: want{ + impExt: json.RawMessage(`{"bidViewability":{"adSizes":{"728x90":{"createdAt":1679993940011,"rendered":20,"totalViewTime":424413,"viewed":17}},"adUnit":{"createdAt":1679993940011,"rendered":25,"totalViewTime":424413,"viewed":17}}}`), + }, }, { name: "sendburl set in imp.ext.prebid.pubmatic, pass to imp.ext", @@ -179,17 +201,74 @@ func TestParseImpressionObject(t *testing.T) { Ext: json.RawMessage(`{"bidder":{"sendburl":true}}`), }, }, - expectedImpExt: json.RawMessage(`{"sendburl":true}`), + want: want{ + impExt: json.RawMessage(`{"sendburl":true}`), + }, + }, + { + name: "Populate imp.displaymanager and imp.displaymanagerver if both are empty in imp", + args: args{ + imp: &openrtb2.Imp{ + Video: &openrtb2.Video{}, + Ext: json.RawMessage(`{"bidder":{"kadfloor":"0.12"}}`), + }, + displayManager: "prebid-mobile", + displayManagerVer: "1.0.0", + }, + want: want{ + bidfloor: 0.12, + impExt: json.RawMessage(nil), + displayManager: "prebid-mobile", + displayManagerVer: "1.0.0", + }, + }, + { + name: "do not populate imp.displaymanager and imp.displaymanagerver in imp if only displaymanager or displaymanagerver is present in args", + args: args{ + imp: &openrtb2.Imp{ + Video: &openrtb2.Video{}, + Ext: json.RawMessage(`{"bidder":{"kadfloor":"0.12"}}`), + DisplayManagerVer: "1.0.0", + }, + displayManager: "prebid-mobile", + displayManagerVer: "1.0.0", + }, + want: want{ + bidfloor: 0.12, + impExt: json.RawMessage(nil), + displayManagerVer: "1.0.0", + }, + }, + { + name: "do not populate imp.displaymanager and imp.displaymanagerver if already present in imp", + args: args{ + imp: &openrtb2.Imp{ + Video: &openrtb2.Video{}, + Ext: json.RawMessage(`{"bidder":{"kadfloor":"0.12"}}`), + DisplayManager: "prebid-mobile", + DisplayManagerVer: "1.0.0", + }, + displayManager: "prebid-android", + displayManagerVer: "2.0.0", + }, + want: want{ + bidfloor: 0.12, + impExt: json.RawMessage(nil), + displayManager: "prebid-mobile", + displayManagerVer: "1.0.0", + }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - receivedWrapperExt, receivedPublisherId, _, err := parseImpressionObject(tt.args.imp, tt.args.extractWrapperExtFromImp, tt.args.extractPubIDFromImp) + receivedWrapperExt, receivedPublisherId, _, err := parseImpressionObject(tt.args.imp, tt.args.extractWrapperExtFromImp, tt.args.extractPubIDFromImp, tt.args.displayManager, tt.args.displayManagerVer) assert.Equal(t, tt.wantErr, err != nil) assert.Equal(t, tt.expectedWrapperExt, receivedWrapperExt) assert.Equal(t, tt.expectedPublisherId, receivedPublisherId) - assert.Equal(t, tt.expectedBidfloor, tt.args.imp.BidFloor) - assert.Equal(t, tt.expectedImpExt, tt.args.imp.Ext) + assert.Equal(t, tt.want.bidfloor, tt.args.imp.BidFloor) + assert.Equal(t, tt.want.impExt, tt.args.imp.Ext) + assert.Equal(t, tt.want.displayManager, tt.args.imp.DisplayManager) + assert.Equal(t, tt.want.displayManagerVer, tt.args.imp.DisplayManagerVer) }) } } @@ -1499,3 +1578,132 @@ func TestTrimSuffixWithPattern(t *testing.T) { }) } } + +func TestGetDisplayManagerAndVer(t *testing.T) { + type args struct { + app *openrtb2.App + } + type want struct { + displayManager string + displayManagerVer string + } + tests := []struct { + name string + args args + want want + }{ + { + name: "request app object is not nil but app.ext has no source and version", + args: args{ + + app: &openrtb2.App{ + Name: "AutoScout24", + Ext: json.RawMessage(`{}`), + }, + }, + want: want{ + displayManager: "", + displayManagerVer: "", + }, + }, + { + name: "request app object is not nil and app.ext has source and version", + args: args{ + + app: &openrtb2.App{ + Name: "AutoScout24", + Ext: json.RawMessage(`{"source":"prebid-mobile","version":"1.0.0"}`), + }, + }, + want: want{ + displayManager: "prebid-mobile", + displayManagerVer: "1.0.0", + }, + }, + { + name: "request app object is not nil and app.ext.prebid has source and version", + args: args{ + app: &openrtb2.App{ + Name: "AutoScout24", + Ext: json.RawMessage(`{"prebid":{"source":"prebid-mobile","version":"1.0.0"}}`), + }, + }, + want: want{ + displayManager: "prebid-mobile", + displayManagerVer: "1.0.0", + }, + }, + { + name: "request app object is not nil and app.ext has only version", + args: args{ + app: &openrtb2.App{ + Name: "AutoScout24", + Ext: json.RawMessage(`{"version":"1.0.0"}`), + }, + }, + want: want{ + displayManager: "", + displayManagerVer: "", + }, + }, + { + name: "request app object is not nil and app.ext has only source", + args: args{ + app: &openrtb2.App{ + Name: "AutoScout24", + Ext: json.RawMessage(`{"source":"prebid-mobile"}`), + }, + }, + want: want{ + displayManager: "", + displayManagerVer: "", + }, + }, + { + name: "request app object is not nil and app.ext have empty source but version is present", + args: args{ + app: &openrtb2.App{ + Name: "AutoScout24", + Ext: json.RawMessage(`{"source":"", "version":"1.0.0"}`), + }, + }, + want: want{ + displayManager: "", + displayManagerVer: "", + }, + }, + { + name: "request app object is not nil and app.ext have empty version but source is present", + args: args{ + app: &openrtb2.App{ + Name: "AutoScout24", + Ext: json.RawMessage(`{"source":"prebid-mobile", "version":""}`), + }, + }, + want: want{ + displayManager: "", + displayManagerVer: "", + }, + }, + { + name: "request app object is not nil and both app.ext and app.ext.prebid have source and version", + args: args{ + app: &openrtb2.App{ + Name: "AutoScout24", + Ext: json.RawMessage(`{"source":"prebid-mobile-android","version":"2.0.0","prebid":{"source":"prebid-mobile","version":"1.0.0"}}`), + }, + }, + want: want{ + displayManager: "prebid-mobile", + displayManagerVer: "1.0.0", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + displayManager, displayManagerVer := getDisplayManagerAndVer(tt.args.app) + assert.Equal(t, tt.want.displayManager, displayManager) + assert.Equal(t, tt.want.displayManagerVer, displayManagerVer) + }) + } +}