From e4d7e09e37533f5e4e82c1be79fa262e4aa94ff8 Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Wed, 18 Jun 2025 14:48:45 +0530 Subject: [PATCH 01/15] RM 825 : Prebid server adapter for risemediatech --- adapters/risemediatech/params_test.go | 16 ++ adapters/risemediatech/risemediatech.go | 159 ++++++++++++++++++ adapters/risemediatech/risemediatech_test.go | 20 +++ .../exemplary/sample_valid_request.json | 59 +++++++ exchange/adapter_builders.go | 2 + openrtb_ext/bidders.go | 2 + openrtb_ext/imp_risemediatech.go | 12 ++ static/bidder-info/risemediatech.yaml | 14 ++ static/bidder-params/risemediatech.json | 25 +++ 9 files changed, 309 insertions(+) create mode 100644 adapters/risemediatech/params_test.go create mode 100644 adapters/risemediatech/risemediatech.go create mode 100644 adapters/risemediatech/risemediatech_test.go create mode 100644 adapters/risemediatech/risemediatechtest/exemplary/sample_valid_request.json create mode 100644 openrtb_ext/imp_risemediatech.go create mode 100644 static/bidder-info/risemediatech.yaml create mode 100644 static/bidder-params/risemediatech.json diff --git a/adapters/risemediatech/params_test.go b/adapters/risemediatech/params_test.go new file mode 100644 index 00000000000..90cb9d2f159 --- /dev/null +++ b/adapters/risemediatech/params_test.go @@ -0,0 +1,16 @@ +package risemediatech + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func TestValidParams(t *testing.T) { + valid := `{"bidfloor": 1.2, "mimes": ["video/mp4"], "minduration": 5}` + var extImp openrtb_ext.ExtImpRiseMediaTech + if err := json.Unmarshal([]byte(valid), &extImp); err != nil { + t.Errorf("Valid params should not throw error: %v", err) + } +} diff --git a/adapters/risemediatech/risemediatech.go b/adapters/risemediatech/risemediatech.go new file mode 100644 index 00000000000..f8a8cdd3b0b --- /dev/null +++ b/adapters/risemediatech/risemediatech.go @@ -0,0 +1,159 @@ +package risemediatech + +import ( + "encoding/json" + "errors" + "fmt" + "net/http" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v3/adapters" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/prebid/prebid-server/v3/util/jsonutil" +) + +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 errs []error + var adapterRequests []*adapters.RequestData + + for _, imp := range request.Imp { + impExt, err := parseImpExt(imp.Ext) + if err != nil { + errs = append(errs, fmt.Errorf("impID %s: %v", imp.ID, err)) + continue + } + + //Validate banner fields if this is a banner impression + if imp.Banner != nil { + if imp.Banner.W == nil || imp.Banner.H == nil { + errs = append(errs, fmt.Errorf("impID %s: missing banner w or h", imp.ID)) + continue + } + if *imp.Banner.W == 0 || *imp.Banner.H == 0 { + errs = append(errs, fmt.Errorf("impID %s: banner w or h cannot be zero", imp.ID)) + continue + } + } + + // Validate additional video fields if this is a video impression + if imp.Video != nil { + if impExt.MinDuration == 0 { + errs = append(errs, fmt.Errorf("impID %s: missing minDuration", imp.ID)) + continue + } + if impExt.MaxDuration == 0 { + errs = append(errs, fmt.Errorf("impID %s: missing maxDuration", imp.ID)) + continue + } + if impExt.StartDelay == 0 { + errs = append(errs, fmt.Errorf("impID %s: missing startDelay", imp.ID)) + continue + } + if len(impExt.Protocols) == 0 { + errs = append(errs, fmt.Errorf("impID %s: missing protocols", imp.ID)) + continue + } + } + + // Prepare sanitized request for each impression + newImp := imp + newImp.Ext = nil // Remove bidder extension + + // Create individual bid request with single imp + modifiedRequest := *request + modifiedRequest.Imp = []openrtb2.Imp{newImp} + + reqJSON, err := json.Marshal(modifiedRequest) + if err != nil { + errs = append(errs, err) + continue + } + + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + headers.Add("Accept", "application/json") + + adapterRequests = append(adapterRequests, &adapters.RequestData{ + Method: "POST", + Uri: a.endpoint, + Body: reqJSON, + Headers: headers, + ImpIDs: []string{imp.ID}, + }) + } + + if len(adapterRequests) == 0 { + return nil, append(errs, errors.New("no valid impressions")) + } + return adapterRequests, errs +} + +func parseImpExt(ext json.RawMessage) (*openrtb_ext.ExtImpRiseMediaTech, error) { + var bidderExt adapters.ExtImpBidder + if err := jsonutil.Unmarshal(ext, &bidderExt); err != nil { + return nil, err + } + var riseExt openrtb_ext.ExtImpRiseMediaTech + if err := jsonutil.Unmarshal(bidderExt.Bidder, &riseExt); err != nil { + return nil, err + } + return &riseExt, nil +} + +func (a *adapter) MakeBids(request *openrtb2.BidRequest, reqData *adapters.RequestData, respData *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if adapters.IsResponseStatusCodeNoContent(respData) { + return nil, nil + } + if err := adapters.CheckResponseStatusCodeForErrors(respData); err != nil { + return nil, []error{err} + } + + var bidResp openrtb2.BidResponse + if err := jsonutil.Unmarshal(respData.Body, &bidResp); err != nil { + return nil, []error{err} + } + + br := adapters.NewBidderResponseWithBidsCapacity(len(bidResp.SeatBid)) + if bidResp.Cur != "" { + br.Currency = bidResp.Cur + } + + for _, seatBid := range bidResp.SeatBid { + for i := range seatBid.Bid { + bid := &seatBid.Bid[i] + + bidType, err := getBidType(bid) + if err != nil { + return nil, []error{err} + } + + br.Bids = append(br.Bids, &adapters.TypedBid{ + Bid: bid, + BidType: bidType, + }) + } + } + return br, nil +} + +func getBidType(bid *openrtb2.Bid) (openrtb_ext.BidType, error) { + switch bid.MType { + case openrtb2.MarkupBanner: + return openrtb_ext.BidTypeBanner, nil + case openrtb2.MarkupVideo: + return openrtb_ext.BidTypeVideo, nil + case openrtb2.MarkupNative: + return openrtb_ext.BidTypeNative, nil + default: + return "", fmt.Errorf("unknown bid type mtype=%d", bid.MType) + } +} diff --git a/adapters/risemediatech/risemediatech_test.go b/adapters/risemediatech/risemediatech_test.go new file mode 100644 index 00000000000..26e0420cfad --- /dev/null +++ b/adapters/risemediatech/risemediatech_test.go @@ -0,0 +1,20 @@ +package risemediatech + +import ( + "testing" + + "github.com/prebid/prebid-server/v3/adapters/adapterstest" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func TestJsonSamples(t *testing.T) { + bidder, buildErr := Builder(openrtb_ext.BidderRiseMediaTech, config.Adapter{ + Endpoint: "https://example.risemediatech.com/bid"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) + } + + adapterstest.RunJSONBidderTest(t, "risemediatechtest", bidder) +} diff --git a/adapters/risemediatech/risemediatechtest/exemplary/sample_valid_request.json b/adapters/risemediatech/risemediatechtest/exemplary/sample_valid_request.json new file mode 100644 index 00000000000..17229823bb4 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/exemplary/sample_valid_request.json @@ -0,0 +1,59 @@ +{ + "mockRequest": { + "id": "test-request", + "imp": [{ + "id": "imp-1", + "video": { + "w": 640, + "h": 480 + }, + "ext": { + "bidder": { + "bidfloor": 1.5, + "mimes": ["video/mp4"], + "minduration": 5, + "maxduration": 30, + "startdelay": 0, + "maxseq": 1, + "poddur": 60, + "protocols": [2, 3] + } + } + }] + }, + "expectedRequest": { + "uri": "https://example-bidder-endpoint.com/bid", + "method": "POST" + }, + "mockResponse": { + "id": "test-request", + "seatbid": [{ + "bid": [{ + "id": "bid-1", + "impid": "imp-1", + "price": 2.0, + "adm": "", + "crid": "creative-1", + "w": 640, + "h": 480, + "mtype": 2 + }] + }], + "cur": "USD" + }, + "expectedResponse": { + "currency": "USD", + "bids": [{ + "bid": { + "id": "bid-1", + "impid": "imp-1", + "price": 2.0, + "adm": "", + "crid": "creative-1", + "w": 640, + "h": 480 + }, + "type": "video" + }] + } +} diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index 87821fd0c75..fcd55ca6b38 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -184,6 +184,7 @@ import ( "github.com/prebid/prebid-server/v3/adapters/revcontent" "github.com/prebid/prebid-server/v3/adapters/richaudience" "github.com/prebid/prebid-server/v3/adapters/rise" + "github.com/prebid/prebid-server/v3/adapters/risemediatech" "github.com/prebid/prebid-server/v3/adapters/roulax" "github.com/prebid/prebid-server/v3/adapters/rtbhouse" "github.com/prebid/prebid-server/v3/adapters/rubicon" @@ -436,6 +437,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderRevcontent: revcontent.Builder, openrtb_ext.BidderRichaudience: richaudience.Builder, openrtb_ext.BidderRise: rise.Builder, + openrtb_ext.BidderRiseMediaTech: risemediatech.Builder, openrtb_ext.BidderRoulax: roulax.Builder, openrtb_ext.BidderRTBHouse: rtbhouse.Builder, openrtb_ext.BidderRubicon: rubicon.Builder, diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 67cf8e7c15e..2874314e0b5 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -202,6 +202,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderRevcontent, BidderRichaudience, BidderRise, + BidderRiseMediaTech, BidderRoulax, BidderRTBHouse, BidderRubicon, @@ -558,6 +559,7 @@ const ( BidderRevcontent BidderName = "revcontent" BidderRichaudience BidderName = "richaudience" BidderRise BidderName = "rise" + BidderRiseMediaTech BidderName = "risemediatech" BidderRoulax BidderName = "roulax" BidderRTBHouse BidderName = "rtbhouse" BidderRubicon BidderName = "rubicon" diff --git a/openrtb_ext/imp_risemediatech.go b/openrtb_ext/imp_risemediatech.go new file mode 100644 index 00000000000..169fe5be705 --- /dev/null +++ b/openrtb_ext/imp_risemediatech.go @@ -0,0 +1,12 @@ +package openrtb_ext + +type ExtImpRiseMediaTech struct { + BidFloor *float64 `json:"bidfloor,omitempty"` + Mimes []string `json:"mimes,omitempty"` + MinDuration int64 `json:"minduration,omitempty"` + MaxDuration int64 `json:"maxduration,omitempty"` + StartDelay int64 `json:"startdelay,omitempty"` + MaxSeq int64 `json:"maxseq,omitempty"` + PodDur int64 `json:"poddur,omitempty"` + Protocols []int64 `json:"protocols,omitempty"` +} diff --git a/static/bidder-info/risemediatech.yaml b/static/bidder-info/risemediatech.yaml new file mode 100644 index 00000000000..bc30b3faed9 --- /dev/null +++ b/static/bidder-info/risemediatech.yaml @@ -0,0 +1,14 @@ +enabled: true +endpoint: http://localhost:8082/ads/rtb/prebid/server +endpointCompression: gzip +maintainer: + email: prebid@risemediatech.io +capabilities: + app: + mediaTypes: + - banner + - video + site: + mediaTypes: + - banner + - video diff --git a/static/bidder-params/risemediatech.json b/static/bidder-params/risemediatech.json new file mode 100644 index 00000000000..679a0d5cfa5 --- /dev/null +++ b/static/bidder-params/risemediatech.json @@ -0,0 +1,25 @@ +{ + "title": "RiseMediaTech", + "description": "Prebid Server adapter for RiseMediaTech", + "type": "object", + "properties": { + "bidfloor": { + "type": "number", + "description": "Bid Floor Price" + }, + "mimes": { + "type": "array", + "items": { "type": "string" } + }, + "minduration": { "type": "integer" }, + "maxduration": { "type": "integer" }, + "startdelay": { "type": "integer" }, + "maxseq": { "type": "integer" }, + "poddur": { "type": "integer" }, + "protocols": { + "type": "array", + "items": { "type": "integer" } + } + }, + "required": [] +} From ff5d135bfecf1cdffdf40e1ecc0231280fc3fd41 Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Thu, 10 Jul 2025 10:41:02 +0530 Subject: [PATCH 02/15] RM-825 : Modified logic --- adapters/risemediatech/params_test.go | 38 +++++- adapters/risemediatech/risemediatech.go | 100 ++++++++-------- adapters/risemediatech/risemediatech_test.go | 15 ++- .../exemplary/sample_valid_request.json | 59 ---------- .../exemplary/simple_banner.json | 110 ++++++++++++++++++ .../exemplary/simple_video.json | 107 +++++++++++++++++ .../supplementary/bad_media_type.json | 58 +++++++++ .../supplementary/bad_response.json | 44 +++++++ .../supplementary/no_valid_impressions.json | 19 +++ .../supplementary/status_204.json | 39 +++++++ .../supplementary/status_not_200.json | 44 +++++++ openrtb_ext/imp_risemediatech.go | 10 +- static/bidder-info/risemediatech.yaml | 2 +- static/bidder-params/risemediatech.json | 18 +-- 14 files changed, 525 insertions(+), 138 deletions(-) delete mode 100644 adapters/risemediatech/risemediatechtest/exemplary/sample_valid_request.json create mode 100644 adapters/risemediatech/risemediatechtest/exemplary/simple_banner.json create mode 100644 adapters/risemediatech/risemediatechtest/exemplary/simple_video.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/bad_media_type.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/bad_response.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/no_valid_impressions.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/status_204.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/status_not_200.json diff --git a/adapters/risemediatech/params_test.go b/adapters/risemediatech/params_test.go index 90cb9d2f159..528aa38de09 100644 --- a/adapters/risemediatech/params_test.go +++ b/adapters/risemediatech/params_test.go @@ -8,9 +8,39 @@ import ( ) func TestValidParams(t *testing.T) { - valid := `{"bidfloor": 1.2, "mimes": ["video/mp4"], "minduration": 5}` - var extImp openrtb_ext.ExtImpRiseMediaTech - if err := json.Unmarshal([]byte(valid), &extImp); err != nil { - t.Errorf("Valid params should not throw error: %v", err) + 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.BidderRiseMediaTech, json.RawMessage(p)); err != nil { + t.Errorf("Schema rejected valid params: %s — error: %v", p, err) + } + } +} + +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.BidderRiseMediaTech, json.RawMessage(p)); err == nil { + t.Errorf("Schema allowed invalid params: %s", p) + } + } +} + +var validParams = []string{ + `{"bidfloor": 0.01}`, + `{"bidfloor": 2.5, "testMode": 1}`, +} + +var invalidParams = []string{ + `{"bidfloor": "1.2"}`, + `{"testMode": "yes"}`, + `{"bidfloor": -5}`, + `{"testMode": 9999}`, } diff --git a/adapters/risemediatech/risemediatech.go b/adapters/risemediatech/risemediatech.go index f8a8cdd3b0b..15bd6180e12 100644 --- a/adapters/risemediatech/risemediatech.go +++ b/adapters/risemediatech/risemediatech.go @@ -17,13 +17,14 @@ 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 Builder(bidderName openrtb_ext.BidderName, cfg config.Adapter, server config.Server) (adapters.Bidder, error) { + return &adapter{endpoint: cfg.Endpoint}, nil } func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { var errs []error - var adapterRequests []*adapters.RequestData + var validImps []openrtb2.Imp + var setTestMode bool for _, imp := range request.Imp { impExt, err := parseImpExt(imp.Ext) @@ -32,69 +33,66 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E continue } - //Validate banner fields if this is a banner impression + // Validate banner if imp.Banner != nil { - if imp.Banner.W == nil || imp.Banner.H == nil { - errs = append(errs, fmt.Errorf("impID %s: missing banner w or h", imp.ID)) - continue - } - if *imp.Banner.W == 0 || *imp.Banner.H == 0 { - errs = append(errs, fmt.Errorf("impID %s: banner w or h cannot be zero", imp.ID)) + if imp.Banner.W == nil || imp.Banner.H == nil || *imp.Banner.W == 0 || *imp.Banner.H == 0 { + errs = append(errs, fmt.Errorf("impID %s: invalid banner dimensions", imp.ID)) continue } } - // Validate additional video fields if this is a video impression + // Validate video if imp.Video != nil { - if impExt.MinDuration == 0 { - errs = append(errs, fmt.Errorf("impID %s: missing minDuration", imp.ID)) + if len(imp.Video.MIMEs) == 0 { + errs = append(errs, fmt.Errorf("impID %s: missing or empty video.mimes", imp.ID)) continue } - if impExt.MaxDuration == 0 { - errs = append(errs, fmt.Errorf("impID %s: missing maxDuration", imp.ID)) - continue - } - if impExt.StartDelay == 0 { - errs = append(errs, fmt.Errorf("impID %s: missing startDelay", imp.ID)) - continue - } - if len(impExt.Protocols) == 0 { - errs = append(errs, fmt.Errorf("impID %s: missing protocols", imp.ID)) + if imp.Video.W == nil || imp.Video.H == nil || *imp.Video.W == 0 || *imp.Video.H == 0 { + errs = append(errs, fmt.Errorf("impID %s: missing or invalid video width/height", imp.ID)) continue } } - // Prepare sanitized request for each impression - newImp := imp - newImp.Ext = nil // Remove bidder extension - - // Create individual bid request with single imp - modifiedRequest := *request - modifiedRequest.Imp = []openrtb2.Imp{newImp} + // Setting bid floor if present + if impExt.BidFloor != nil && *impExt.BidFloor > 0 { + imp.BidFloor = *impExt.BidFloor + } - reqJSON, err := json.Marshal(modifiedRequest) - if err != nil { - errs = append(errs, err) - continue + // Check test mode + if impExt.TestMode != nil && *impExt.TestMode == 1 { + setTestMode = true } - headers := http.Header{} - headers.Add("Content-Type", "application/json;charset=utf-8") - headers.Add("Accept", "application/json") - - adapterRequests = append(adapterRequests, &adapters.RequestData{ - Method: "POST", - Uri: a.endpoint, - Body: reqJSON, - Headers: headers, - ImpIDs: []string{imp.ID}, - }) + validImps = append(validImps, imp) } - if len(adapterRequests) == 0 { + if len(validImps) == 0 { return nil, append(errs, errors.New("no valid impressions")) } - return adapterRequests, errs + + modifiedRequest := *request + modifiedRequest.Imp = validImps + if setTestMode { + modifiedRequest.Test = 1 + } + + reqJSON, err := json.Marshal(modifiedRequest) + if err != nil { + return nil, append(errs, err) + } + + headers := http.Header{} + headers.Set("Content-Type", "application/json;charset=utf-8") + headers.Set("Accept", "application/json") + headers.Set("User-Agent", "prebid-server") + headers.Set("X-Prebid", "true") + + return []*adapters.RequestData{{ + Method: "POST", + Uri: a.endpoint, + Body: reqJSON, + Headers: headers, + }}, errs } func parseImpExt(ext json.RawMessage) (*openrtb_ext.ExtImpRiseMediaTech, error) { @@ -136,10 +134,12 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, reqData *adapters.Reque return nil, []error{err} } - br.Bids = append(br.Bids, &adapters.TypedBid{ + typedBid := &adapters.TypedBid{ Bid: bid, BidType: bidType, - }) + } + + br.Bids = append(br.Bids, typedBid) } } return br, nil @@ -151,8 +151,6 @@ func getBidType(bid *openrtb2.Bid) (openrtb_ext.BidType, error) { return openrtb_ext.BidTypeBanner, nil case openrtb2.MarkupVideo: return openrtb_ext.BidTypeVideo, nil - case openrtb2.MarkupNative: - return openrtb_ext.BidTypeNative, nil default: return "", fmt.Errorf("unknown bid type mtype=%d", bid.MType) } diff --git a/adapters/risemediatech/risemediatech_test.go b/adapters/risemediatech/risemediatech_test.go index 26e0420cfad..5789ec901e0 100644 --- a/adapters/risemediatech/risemediatech_test.go +++ b/adapters/risemediatech/risemediatech_test.go @@ -9,11 +9,20 @@ import ( ) func TestJsonSamples(t *testing.T) { - bidder, buildErr := Builder(openrtb_ext.BidderRiseMediaTech, config.Adapter{ - Endpoint: "https://example.risemediatech.com/bid"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + bidder, buildErr := Builder( + openrtb_ext.BidderRiseMediaTech, + config.Adapter{ + Endpoint: "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + }, + config.Server{ + ExternalUrl: "http://hosturl.com", + GvlID: 0, + DataCenter: "2", + }, + ) if buildErr != nil { - t.Fatalf("Builder returned unexpected error %v", buildErr) + t.Fatalf("Builder returned unexpected error: %v", buildErr) } adapterstest.RunJSONBidderTest(t, "risemediatechtest", bidder) diff --git a/adapters/risemediatech/risemediatechtest/exemplary/sample_valid_request.json b/adapters/risemediatech/risemediatechtest/exemplary/sample_valid_request.json deleted file mode 100644 index 17229823bb4..00000000000 --- a/adapters/risemediatech/risemediatechtest/exemplary/sample_valid_request.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "mockRequest": { - "id": "test-request", - "imp": [{ - "id": "imp-1", - "video": { - "w": 640, - "h": 480 - }, - "ext": { - "bidder": { - "bidfloor": 1.5, - "mimes": ["video/mp4"], - "minduration": 5, - "maxduration": 30, - "startdelay": 0, - "maxseq": 1, - "poddur": 60, - "protocols": [2, 3] - } - } - }] - }, - "expectedRequest": { - "uri": "https://example-bidder-endpoint.com/bid", - "method": "POST" - }, - "mockResponse": { - "id": "test-request", - "seatbid": [{ - "bid": [{ - "id": "bid-1", - "impid": "imp-1", - "price": 2.0, - "adm": "", - "crid": "creative-1", - "w": 640, - "h": 480, - "mtype": 2 - }] - }], - "cur": "USD" - }, - "expectedResponse": { - "currency": "USD", - "bids": [{ - "bid": { - "id": "bid-1", - "impid": "imp-1", - "price": 2.0, - "adm": "", - "crid": "creative-1", - "w": 640, - "h": 480 - }, - "type": "video" - }] - } -} diff --git a/adapters/risemediatech/risemediatechtest/exemplary/simple_banner.json b/adapters/risemediatech/risemediatechtest/exemplary/simple_banner.json new file mode 100644 index 00000000000..0186decd4c0 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/exemplary/simple_banner.json @@ -0,0 +1,110 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + }, + "app": { + "id": "1", + "bundle": "com.risemediatech.sampleapp" + }, + "imp": [ + { + "id": "test-imp-id", + "tagid": "test-tag", + "banner": { + "format": [ + { "w": 300, "h": 250 }, + { "w": 728, "h": 90 } + ] + }, + "ext": { + "bidder": { + "bidfloor": 1.2, + "testMode": 1 + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "tagid": "test-tag", + "banner": { + "format": [ + { "w": 300, "h": 250 }, + { "w": 728, "h": 90 } + ] + }, + "bidfloor": 1.2 + } + ], + "app": { + "id": "1", + "bundle": "com.risemediatech.sampleapp" + }, + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + } + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "risemediatech", + "bid": [ + { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.65, + "adm": "
Sample Ad Markup
", + "crid": "creative-123", + "cid": "campaign-456", + "dealid": "deal-789", + "w": 300, + "h": 250, + "mtype": 1 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.65, + "adm": "
Sample Ad Markup
", + "crid": "creative-123", + "cid": "campaign-456", + "dealid": "deal-789", + "w": 300, + "h": 250, + "mtype": 1 + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/risemediatech/risemediatechtest/exemplary/simple_video.json b/adapters/risemediatech/risemediatechtest/exemplary/simple_video.json new file mode 100644 index 00000000000..aaf640f1805 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/exemplary/simple_video.json @@ -0,0 +1,107 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + }, + "app": { + "id": "1", + "bundle": "com.risemediatech.videotestapp" + }, + "imp": [ + { + "id": "test-imp-id", + "tagid": "video-tag", + "video": { + "mimes": ["video/mp4"], + "protocols": [2, 5], + "w": 1024, + "h": 576 + }, + "ext": { + "bidder": { + "bidfloor": 0.75, + "testMode": 1 + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "body": { + "id": "test-request-id", + "device": { + "ip": "123.123.123.123", + "ua": "iPad" + }, + "app": { + "id": "1", + "bundle": "com.risemediatech.videotestapp" + }, + "imp": [ + { + "id": "test-imp-id", + "tagid": "video-tag", + "video": { + "mimes": ["video/mp4"], + "protocols": [2, 5], + "w": 1024, + "h": 576 + }, + "bidfloor": 0.75 + } + ] + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "risemediatech", + "bid": [ + { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.88, + "adm": "00:00:30", + "cid": "video-campaign-001", + "crid": "video-creative-abc", + "dealid": "deal-999", + "mtype": 2 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.88, + "adm": "00:00:30", + "cid": "video-campaign-001", + "crid": "video-creative-abc", + "dealid": "deal-999", + "mtype": 2 + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/risemediatech/risemediatechtest/supplementary/bad_media_type.json b/adapters/risemediatech/risemediatechtest/supplementary/bad_media_type.json new file mode 100644 index 00000000000..9fa9dea72d8 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/bad_media_type.json @@ -0,0 +1,58 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "ext": { + "bidder": { + "bidfloor": 1.0 + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.risemediatech.sampleapp" + }, + "device": { + "ip": "123.123.123.123" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-bid-id", + "impid": "test-imp-id", + "price": 0.5, + "adm": "
test
", + "mtype": 9, + "w": 300, + "h": 250 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "unknown bid type mtype=9", + "comparison": "contains" + } + ] +} diff --git a/adapters/risemediatech/risemediatechtest/supplementary/bad_response.json b/adapters/risemediatech/risemediatechtest/supplementary/bad_response.json new file mode 100644 index 00000000000..c1bbb070ef0 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/bad_response.json @@ -0,0 +1,44 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "bidfloor": 1.0 + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.risemediatech.sampleapp" + }, + "device": { + "ip": "123.123.123.123" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": "invalid-json-response" + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "invalid character", + "comparison": "contains" + } + ] +} diff --git a/adapters/risemediatech/risemediatechtest/supplementary/no_valid_impressions.json b/adapters/risemediatech/risemediatechtest/supplementary/no_valid_impressions.json new file mode 100644 index 00000000000..f97d33c3e8c --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/no_valid_impressions.json @@ -0,0 +1,19 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [], + "app": { + "id": "1", + "bundle": "com.risemediatech.sampleapp" + }, + "device": { + "ip": "123.123.123.123" + } + }, + "expectedMakeRequestsErrors": [ + { + "value": "no valid impressions", + "comparison": "contains" + } + ] +} diff --git a/adapters/risemediatech/risemediatechtest/supplementary/status_204.json b/adapters/risemediatech/risemediatechtest/supplementary/status_204.json new file mode 100644 index 00000000000..699f5a1a403 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/status_204.json @@ -0,0 +1,39 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "bidfloor": 1.0 + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.risemediatech.sampleapp" + }, + "device": { + "ip": "123.123.123.123" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + "expectedBidResponses": [] +} diff --git a/adapters/risemediatech/risemediatechtest/supplementary/status_not_200.json b/adapters/risemediatech/risemediatechtest/supplementary/status_not_200.json new file mode 100644 index 00000000000..a7e31d0c231 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/status_not_200.json @@ -0,0 +1,44 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "bidfloor": 1.0 + } + } + } + ], + "app": { + "id": "1", + "bundle": "com.risemediatech.sampleapp" + }, + "device": { + "ip": "123.123.123.123" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 500, + "body": {} + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 500", + "comparison": "contains" + } + ] +} diff --git a/openrtb_ext/imp_risemediatech.go b/openrtb_ext/imp_risemediatech.go index 169fe5be705..f9905dad074 100644 --- a/openrtb_ext/imp_risemediatech.go +++ b/openrtb_ext/imp_risemediatech.go @@ -1,12 +1,6 @@ package openrtb_ext type ExtImpRiseMediaTech struct { - BidFloor *float64 `json:"bidfloor,omitempty"` - Mimes []string `json:"mimes,omitempty"` - MinDuration int64 `json:"minduration,omitempty"` - MaxDuration int64 `json:"maxduration,omitempty"` - StartDelay int64 `json:"startdelay,omitempty"` - MaxSeq int64 `json:"maxseq,omitempty"` - PodDur int64 `json:"poddur,omitempty"` - Protocols []int64 `json:"protocols,omitempty"` + BidFloor *float64 `json:"bidfloor,omitempty"` + TestMode *int `json:"testMode,omitempty"` } diff --git a/static/bidder-info/risemediatech.yaml b/static/bidder-info/risemediatech.yaml index bc30b3faed9..8c56278578f 100644 --- a/static/bidder-info/risemediatech.yaml +++ b/static/bidder-info/risemediatech.yaml @@ -1,5 +1,5 @@ enabled: true -endpoint: http://localhost:8082/ads/rtb/prebid/server +endpoint: https://dev-ads.risemediatech.com/ads/rtb/prebid/server endpointCompression: gzip maintainer: email: prebid@risemediatech.io diff --git a/static/bidder-params/risemediatech.json b/static/bidder-params/risemediatech.json index 679a0d5cfa5..fbbaaf7a693 100644 --- a/static/bidder-params/risemediatech.json +++ b/static/bidder-params/risemediatech.json @@ -5,21 +5,15 @@ "properties": { "bidfloor": { "type": "number", + "minimum": 0, "description": "Bid Floor Price" }, - "mimes": { - "type": "array", - "items": { "type": "string" } - }, - "minduration": { "type": "integer" }, - "maxduration": { "type": "integer" }, - "startdelay": { "type": "integer" }, - "maxseq": { "type": "integer" }, - "poddur": { "type": "integer" }, - "protocols": { - "type": "array", - "items": { "type": "integer" } + "testMode": { + "type": "integer", + "enum": [0, 1], + "description": "Test Mode parameter to indicate test request" } }, + "additionalProperties": false, "required": [] } From f6d165148c9225a73234ce64d6219defb2b67abc Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Tue, 15 Jul 2025 15:39:18 +0530 Subject: [PATCH 03/15] Modified the tests --- adapters/risemediatech/risemediatech.go | 23 ++++++--- .../exemplary/simple_banner.json | 51 +++++++++++-------- .../exemplary/simple_video.json | 11 +++- 3 files changed, 56 insertions(+), 29 deletions(-) diff --git a/adapters/risemediatech/risemediatech.go b/adapters/risemediatech/risemediatech.go index 15bd6180e12..4eefa5eae21 100644 --- a/adapters/risemediatech/risemediatech.go +++ b/adapters/risemediatech/risemediatech.go @@ -87,12 +87,23 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E headers.Set("User-Agent", "prebid-server") headers.Set("X-Prebid", "true") - return []*adapters.RequestData{{ - Method: "POST", - Uri: a.endpoint, - Body: reqJSON, - Headers: headers, - }}, errs + return []*adapters.RequestData{ + { + Method: "POST", + Uri: a.endpoint, + Body: reqJSON, + Headers: headers, + ImpIDs: extractImpIDs(validImps), + }, + }, errs +} + +func extractImpIDs(imps []openrtb2.Imp) []string { + ids := make([]string, 0, len(imps)) + for _, imp := range imps { + ids = append(ids, imp.ID) + } + return ids } func parseImpExt(ext json.RawMessage) (*openrtb_ext.ExtImpRiseMediaTech, error) { diff --git a/adapters/risemediatech/risemediatechtest/exemplary/simple_banner.json b/adapters/risemediatech/risemediatechtest/exemplary/simple_banner.json index 0186decd4c0..e541667ac0f 100644 --- a/adapters/risemediatech/risemediatechtest/exemplary/simple_banner.json +++ b/adapters/risemediatech/risemediatechtest/exemplary/simple_banner.json @@ -12,16 +12,17 @@ "imp": [ { "id": "test-imp-id", - "tagid": "test-tag", + "tagid": "test-banner-slot", "banner": { "format": [ - { "w": 300, "h": 250 }, - { "w": 728, "h": 90 } - ] + { "w": 300, "h": 250 } + ], + "w": 300, + "h": 250 }, "ext": { "bidder": { - "bidfloor": 1.2, + "bidfloor": 0.5, "testMode": 1 } } @@ -37,14 +38,21 @@ "imp": [ { "id": "test-imp-id", - "tagid": "test-tag", + "tagid": "test-banner-slot", "banner": { "format": [ - { "w": 300, "h": 250 }, - { "w": 728, "h": 90 } - ] + { "w": 300, "h": 250 } + ], + "w": 300, + "h": 250 }, - "bidfloor": 1.2 + "bidfloor": 0.5, + "ext": { + "bidder": { + "bidfloor": 0.5, + "testMode": 1 + } + } } ], "app": { @@ -54,7 +62,8 @@ "device": { "ip": "123.123.123.123", "ua": "iPad" - } + }, + "test": 1 }, "impIDs": ["test-imp-id"] }, @@ -69,11 +78,11 @@ { "id": "test_bid_id", "impid": "test-imp-id", - "price": 0.65, - "adm": "
Sample Ad Markup
", - "crid": "creative-123", - "cid": "campaign-456", - "dealid": "deal-789", + "price": 0.85, + "adm": "
Sample Banner Ad
", + "crid": "banner-creative-001", + "cid": "banner-campaign-abc", + "dealid": "deal-123", "w": 300, "h": 250, "mtype": 1 @@ -93,11 +102,11 @@ "bid": { "id": "test_bid_id", "impid": "test-imp-id", - "price": 0.65, - "adm": "
Sample Ad Markup
", - "crid": "creative-123", - "cid": "campaign-456", - "dealid": "deal-789", + "price": 0.85, + "adm": "
Sample Banner Ad
", + "crid": "banner-creative-001", + "cid": "banner-campaign-abc", + "dealid": "deal-123", "w": 300, "h": 250, "mtype": 1 diff --git a/adapters/risemediatech/risemediatechtest/exemplary/simple_video.json b/adapters/risemediatech/risemediatechtest/exemplary/simple_video.json index aaf640f1805..3d0012b9910 100644 --- a/adapters/risemediatech/risemediatechtest/exemplary/simple_video.json +++ b/adapters/risemediatech/risemediatechtest/exemplary/simple_video.json @@ -52,9 +52,16 @@ "w": 1024, "h": 576 }, - "bidfloor": 0.75 + "bidfloor": 0.75, + "ext": { + "bidder": { + "bidfloor": 0.75, + "testMode": 1 + } + } } - ] + ], + "test": 1 }, "impIDs": ["test-imp-id"] }, From 9e92df2030cd80aeb25c88d9712d2a5c5360e767 Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Fri, 25 Jul 2025 16:20:48 +0530 Subject: [PATCH 04/15] Changes as per review comments in upstream repo PR --- adapters/risemediatech/params_test.go | 29 +++++++++------- adapters/risemediatech/risemediatech.go | 35 ++++++++++---------- adapters/risemediatech/risemediatech_test.go | 2 ++ openrtb_ext/imp_risemediatech.go | 4 +-- 4 files changed, 38 insertions(+), 32 deletions(-) diff --git a/adapters/risemediatech/params_test.go b/adapters/risemediatech/params_test.go index 528aa38de09..31c49d377f6 100644 --- a/adapters/risemediatech/params_test.go +++ b/adapters/risemediatech/params_test.go @@ -5,31 +5,36 @@ import ( "testing" "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/stretchr/testify/require" ) 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) - } + require.NoError(t, err, "Failed to fetch the JSON schema") for _, p := range validParams { - if err := validator.Validate(openrtb_ext.BidderRiseMediaTech, json.RawMessage(p)); err != nil { - t.Errorf("Schema rejected valid params: %s — error: %v", p, err) - } + p := p // capture range variable + t.Run(p, func(t *testing.T) { + err := validator.Validate(openrtb_ext.BidderRiseMediaTech, json.RawMessage(p)) + if err != nil { + t.Errorf("Schema rejected valid params: %s — error: %v", p, err) + } + }) } } 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) - } + require.NoError(t, err, "Failed to fetch the JSON schema") for _, p := range invalidParams { - if err := validator.Validate(openrtb_ext.BidderRiseMediaTech, json.RawMessage(p)); err == nil { - t.Errorf("Schema allowed invalid params: %s", p) - } + p := p // capture range variable + t.Run(p, func(t *testing.T) { + err := validator.Validate(openrtb_ext.BidderRiseMediaTech, json.RawMessage(p)) + if err == nil { + t.Errorf("Schema allowed invalid params: %s", p) + } + }) } } diff --git a/adapters/risemediatech/risemediatech.go b/adapters/risemediatech/risemediatech.go index 4eefa5eae21..465bcc715af 100644 --- a/adapters/risemediatech/risemediatech.go +++ b/adapters/risemediatech/risemediatech.go @@ -1,7 +1,6 @@ package risemediatech import ( - "encoding/json" "errors" "fmt" "net/http" @@ -9,7 +8,9 @@ import ( "github.com/prebid/openrtb/v20/openrtb2" "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" + "github.com/prebid/prebid-server/v3/util/iterutil" "github.com/prebid/prebid-server/v3/util/jsonutil" ) @@ -26,17 +27,17 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E var validImps []openrtb2.Imp var setTestMode bool - for _, imp := range request.Imp { + for imp := range iterutil.SlicePointerValues(request.Imp) { impExt, err := parseImpExt(imp.Ext) if err != nil { - errs = append(errs, fmt.Errorf("impID %s: %v", imp.ID, err)) + errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("impID %s: %v", imp.ID, err)}) continue } // Validate banner if imp.Banner != nil { if imp.Banner.W == nil || imp.Banner.H == nil || *imp.Banner.W == 0 || *imp.Banner.H == 0 { - errs = append(errs, fmt.Errorf("impID %s: invalid banner dimensions", imp.ID)) + errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("impID %s: invalid banner dimensions", imp.ID)}) continue } } @@ -44,30 +45,30 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E // Validate video if imp.Video != nil { if len(imp.Video.MIMEs) == 0 { - errs = append(errs, fmt.Errorf("impID %s: missing or empty video.mimes", imp.ID)) + errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("impID %s: missing or empty video.mimes", imp.ID)}) continue } if imp.Video.W == nil || imp.Video.H == nil || *imp.Video.W == 0 || *imp.Video.H == 0 { - errs = append(errs, fmt.Errorf("impID %s: missing or invalid video width/height", imp.ID)) + errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("impID %s: missing or invalid video width/height", imp.ID)}) continue } } // Setting bid floor if present - if impExt.BidFloor != nil && *impExt.BidFloor > 0 { - imp.BidFloor = *impExt.BidFloor + if impExt.BidFloor > 0 { + imp.BidFloor = impExt.BidFloor } // Check test mode - if impExt.TestMode != nil && *impExt.TestMode == 1 { + if impExt.TestMode == 1 { setTestMode = true } - validImps = append(validImps, imp) + validImps = append(validImps, *imp) } if len(validImps) == 0 { - return nil, append(errs, errors.New("no valid impressions")) + return nil, append(errs, &errortypes.BadInput{Message: "no valid impressions"}) } modifiedRequest := *request @@ -76,7 +77,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E modifiedRequest.Test = 1 } - reqJSON, err := json.Marshal(modifiedRequest) + reqJSON, err := jsonutil.Marshal(modifiedRequest) if err != nil { return nil, append(errs, err) } @@ -100,13 +101,13 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E func extractImpIDs(imps []openrtb2.Imp) []string { ids := make([]string, 0, len(imps)) - for _, imp := range imps { + for imp := range iterutil.SlicePointerValues(imps) { ids = append(ids, imp.ID) } return ids } -func parseImpExt(ext json.RawMessage) (*openrtb_ext.ExtImpRiseMediaTech, error) { +func parseImpExt(ext jsonutil.RawMessage) (*openrtb_ext.ExtImpRiseMediaTech, error) { var bidderExt adapters.ExtImpBidder if err := jsonutil.Unmarshal(ext, &bidderExt); err != nil { return nil, err @@ -136,10 +137,8 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, reqData *adapters.Reque br.Currency = bidResp.Cur } - for _, seatBid := range bidResp.SeatBid { - for i := range seatBid.Bid { - bid := &seatBid.Bid[i] - + for seatBid := range iterutil.SlicePointerValues(bidResp.SeatBid) { + for bid := range iterutil.SlicePointerValues(seatBid.Bid) { bidType, err := getBidType(bid) if err != nil { return nil, []error{err} diff --git a/adapters/risemediatech/risemediatech_test.go b/adapters/risemediatech/risemediatech_test.go index 5789ec901e0..98f3d99d758 100644 --- a/adapters/risemediatech/risemediatech_test.go +++ b/adapters/risemediatech/risemediatech_test.go @@ -6,6 +6,7 @@ import ( "github.com/prebid/prebid-server/v3/adapters/adapterstest" "github.com/prebid/prebid-server/v3/config" "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/stretchr/testify/require" ) func TestJsonSamples(t *testing.T) { @@ -24,6 +25,7 @@ func TestJsonSamples(t *testing.T) { if buildErr != nil { t.Fatalf("Builder returned unexpected error: %v", buildErr) } + require.NoError(t, buildErr, "Builder returned unexpected error") adapterstest.RunJSONBidderTest(t, "risemediatechtest", bidder) } diff --git a/openrtb_ext/imp_risemediatech.go b/openrtb_ext/imp_risemediatech.go index f9905dad074..faab784c296 100644 --- a/openrtb_ext/imp_risemediatech.go +++ b/openrtb_ext/imp_risemediatech.go @@ -1,6 +1,6 @@ package openrtb_ext type ExtImpRiseMediaTech struct { - BidFloor *float64 `json:"bidfloor,omitempty"` - TestMode *int `json:"testMode,omitempty"` + BidFloor float64 `json:"bidfloor,omitempty"` + TestMode int `json:"testMode,omitempty"` } From 90590dd0810302bd35756a47ef4639abb38c3c31 Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Fri, 25 Jul 2025 22:41:19 +0530 Subject: [PATCH 05/15] Changes for review comments and improving unit test coverage --- adapters/risemediatech/risemediatech.go | 23 +++++----- .../exemplary/banner_bid_floor_set.json | 36 +++++++++++++++ .../exemplary/test_mode_set.json | 36 +++++++++++++++ .../supplementary/all_imps_invalid.json | 20 ++++++++ .../invalid_banner_missing_width.json | 15 ++++++ .../invalid_banner_zero_height.json | 15 ++++++ .../supplementary/invalid_imp_ext.json | 15 ++++++ .../invalid_video_empty_mimes.json | 15 ++++++ .../invalid_video_missing_width.json | 15 ++++++ .../invalid_video_zero_height.json | 15 ++++++ .../supplementary/no_test_mode.json | 46 +++++++++++++++++++ 11 files changed, 239 insertions(+), 12 deletions(-) create mode 100644 adapters/risemediatech/risemediatechtest/exemplary/banner_bid_floor_set.json create mode 100644 adapters/risemediatech/risemediatechtest/exemplary/test_mode_set.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/all_imps_invalid.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/invalid_banner_missing_width.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/invalid_banner_zero_height.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/invalid_imp_ext.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/invalid_video_empty_mimes.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/invalid_video_missing_width.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/invalid_video_zero_height.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/no_test_mode.json diff --git a/adapters/risemediatech/risemediatech.go b/adapters/risemediatech/risemediatech.go index 465bcc715af..07792901a07 100644 --- a/adapters/risemediatech/risemediatech.go +++ b/adapters/risemediatech/risemediatech.go @@ -1,7 +1,6 @@ package risemediatech import ( - "errors" "fmt" "net/http" @@ -10,8 +9,8 @@ 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/iterutil" - "github.com/prebid/prebid-server/v3/util/jsonutil" + iterators "github.com/prebid/prebid-server/v3/util/iterutil" + jsonutils "github.com/prebid/prebid-server/v3/util/jsonutil" ) type adapter struct { @@ -27,7 +26,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E var validImps []openrtb2.Imp var setTestMode bool - for imp := range iterutil.SlicePointerValues(request.Imp) { + for imp := range iterators.SlicePointerValues(request.Imp) { impExt, err := parseImpExt(imp.Ext) if err != nil { errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("impID %s: %v", imp.ID, err)}) @@ -77,7 +76,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E modifiedRequest.Test = 1 } - reqJSON, err := jsonutil.Marshal(modifiedRequest) + reqJSON, err := jsonutils.Marshal(modifiedRequest) if err != nil { return nil, append(errs, err) } @@ -101,19 +100,19 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E func extractImpIDs(imps []openrtb2.Imp) []string { ids := make([]string, 0, len(imps)) - for imp := range iterutil.SlicePointerValues(imps) { + for imp := range iterators.SlicePointerValues(imps) { ids = append(ids, imp.ID) } return ids } -func parseImpExt(ext jsonutil.RawMessage) (*openrtb_ext.ExtImpRiseMediaTech, error) { +func parseImpExt(ext jsonutils.RawMessage) (*openrtb_ext.ExtImpRiseMediaTech, error) { var bidderExt adapters.ExtImpBidder - if err := jsonutil.Unmarshal(ext, &bidderExt); err != nil { + if err := jsonutils.Unmarshal(ext, &bidderExt); err != nil { return nil, err } var riseExt openrtb_ext.ExtImpRiseMediaTech - if err := jsonutil.Unmarshal(bidderExt.Bidder, &riseExt); err != nil { + if err := jsonutils.Unmarshal(bidderExt.Bidder, &riseExt); err != nil { return nil, err } return &riseExt, nil @@ -128,7 +127,7 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, reqData *adapters.Reque } var bidResp openrtb2.BidResponse - if err := jsonutil.Unmarshal(respData.Body, &bidResp); err != nil { + if err := jsonutils.Unmarshal(respData.Body, &bidResp); err != nil { return nil, []error{err} } @@ -137,8 +136,8 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, reqData *adapters.Reque br.Currency = bidResp.Cur } - for seatBid := range iterutil.SlicePointerValues(bidResp.SeatBid) { - for bid := range iterutil.SlicePointerValues(seatBid.Bid) { + for seatBid := range iterators.SlicePointerValues(bidResp.SeatBid) { + for bid := range iterators.SlicePointerValues(seatBid.Bid) { bidType, err := getBidType(bid) if err != nil { return nil, []error{err} diff --git a/adapters/risemediatech/risemediatechtest/exemplary/banner_bid_floor_set.json b/adapters/risemediatech/risemediatechtest/exemplary/banner_bid_floor_set.json new file mode 100644 index 00000000000..7b1bab68044 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/exemplary/banner_bid_floor_set.json @@ -0,0 +1,36 @@ +{ + "mockBidRequest": { + "id": "test-bid-floor-set", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "ext": { "bidder": { "placementId": "abc", "bidFloor": 1.23 } } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "body": { + "id": "test-bid-floor-set", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "bidfloor": 1.23, + "ext": { "bidder": { "placementId": "abc", "bidFloor": 1.23 } } + } + ] + }, + "impIDs": ["1"] + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + "expectedBidResponses": [] +} \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/exemplary/test_mode_set.json b/adapters/risemediatech/risemediatechtest/exemplary/test_mode_set.json new file mode 100644 index 00000000000..e080642f716 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/exemplary/test_mode_set.json @@ -0,0 +1,36 @@ +{ + "mockBidRequest": { + "id": "test-test-mode-set", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "ext": { "bidder": { "placementId": "abc", "testMode": 1 } } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "body": { + "id": "test-test-mode-set", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "ext": { "bidder": { "placementId": "abc", "testMode": 1 } } + } + ], + "test": 1 + }, + "impIDs": ["1"] + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + "expectedBidResponses": [] +} \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/supplementary/all_imps_invalid.json b/adapters/risemediatech/risemediatechtest/supplementary/all_imps_invalid.json new file mode 100644 index 00000000000..7b5ba3c379c --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/all_imps_invalid.json @@ -0,0 +1,20 @@ +{ + "mockBidRequest": { + "id": "test-all-imps-invalid", + "imp": [ + { + "id": "1", + "banner": { "h": 250 }, + "ext": { "bidder": { "placementId": "abc" } } + }, + { + "id": "2", + "video": { "w": 640, "h": 0, "mimes": ["video/mp4"] }, + "ext": { "bidder": { "placementId": "def" } } + } + ] + }, + "expectedMakeRequestsErrors": [ + { "value": "no valid impressions", "comparison": "contains" } + ] + } \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/supplementary/invalid_banner_missing_width.json b/adapters/risemediatech/risemediatechtest/supplementary/invalid_banner_missing_width.json new file mode 100644 index 00000000000..054c0b9e5ac --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/invalid_banner_missing_width.json @@ -0,0 +1,15 @@ +{ + "mockBidRequest": { + "id": "test-invalid-banner-missing-width", + "imp": [ + { + "id": "1", + "banner": { "h": 250 }, + "ext": { "bidder": { "placementId": "abc" } } + } + ] + }, + "expectedMakeRequestsErrors": [ + { "value": "invalid banner dimensions", "comparison": "contains" } + ] + } \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/supplementary/invalid_banner_zero_height.json b/adapters/risemediatech/risemediatechtest/supplementary/invalid_banner_zero_height.json new file mode 100644 index 00000000000..a767d712b53 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/invalid_banner_zero_height.json @@ -0,0 +1,15 @@ +{ + "mockBidRequest": { + "id": "test-invalid-banner-zero-height", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 0 }, + "ext": { "bidder": { "placementId": "abc" } } + } + ] + }, + "expectedMakeRequestsErrors": [ + { "value": "invalid banner dimensions", "comparison": "contains" } + ] + } \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/supplementary/invalid_imp_ext.json b/adapters/risemediatech/risemediatechtest/supplementary/invalid_imp_ext.json new file mode 100644 index 00000000000..a3651c3d20e --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/invalid_imp_ext.json @@ -0,0 +1,15 @@ +{ + "mockBidRequest": { + "id": "test-invalid-imp-ext", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "ext": "not-a-valid-json" + } + ] + }, + "expectedMakeRequestsErrors": [ + { "value": "impID 1: invalid character", "comparison": "contains" } + ] + } \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/supplementary/invalid_video_empty_mimes.json b/adapters/risemediatech/risemediatechtest/supplementary/invalid_video_empty_mimes.json new file mode 100644 index 00000000000..5fcbc963fb9 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/invalid_video_empty_mimes.json @@ -0,0 +1,15 @@ +{ + "mockBidRequest": { + "id": "test-invalid-video-empty-mimes", + "imp": [ + { + "id": "1", + "video": { "w": 640, "h": 480, "mimes": [] }, + "ext": { "bidder": { "placementId": "abc" } } + } + ] + }, + "expectedMakeRequestsErrors": [ + { "value": "missing or empty video.mimes", "comparison": "contains" } + ] + } \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/supplementary/invalid_video_missing_width.json b/adapters/risemediatech/risemediatechtest/supplementary/invalid_video_missing_width.json new file mode 100644 index 00000000000..beed163e6fe --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/invalid_video_missing_width.json @@ -0,0 +1,15 @@ +{ + "mockBidRequest": { + "id": "test-invalid-video-missing-width", + "imp": [ + { + "id": "1", + "video": { "h": 250, "mimes": ["video/mp4"] }, + "ext": { "bidder": { "placementId": "abc" } } + } + ] + }, + "expectedMakeRequestsErrors": [ + { "value": "missing or invalid video width/height", "comparison": "contains" } + ] + } \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/supplementary/invalid_video_zero_height.json b/adapters/risemediatech/risemediatechtest/supplementary/invalid_video_zero_height.json new file mode 100644 index 00000000000..aa529466da6 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/invalid_video_zero_height.json @@ -0,0 +1,15 @@ +{ + "mockBidRequest": { + "id": "test-invalid-video-zero-height", + "imp": [ + { + "id": "1", + "video": { "w": 640, "h": 0, "mimes": ["video/mp4"] }, + "ext": { "bidder": { "placementId": "abc" } } + } + ] + }, + "expectedMakeRequestsErrors": [ + { "value": "missing or invalid video width/height", "comparison": "contains" } + ] + } \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/supplementary/no_test_mode.json b/adapters/risemediatech/risemediatechtest/supplementary/no_test_mode.json new file mode 100644 index 00000000000..7134afe8e1a --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/no_test_mode.json @@ -0,0 +1,46 @@ +{ + "mockBidRequest": { + "id": "no-test-mode", + "imp": [ + { + "id": "imp-4", + "tagid": "tag-4", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "bidfloor": 0.8 + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "body": { + "id": "no-test-mode", + "imp": [ + { + "id": "imp-4", + "tagid": "tag-4", + "banner": { + "w": 300, + "h": 250 + }, + "bidfloor": 0.8 + } + ] + }, + "impIDs": ["imp-4"] + }, + "mockResponse": { + "status": 204 + } + } + ], + "expectedBidResponses": [] +} From 9579ed95deac99de23604f22f030fff435e360b4 Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Fri, 25 Jul 2025 23:09:48 +0530 Subject: [PATCH 06/15] Review comment changes --- adapters/risemediatech/risemediatech.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/adapters/risemediatech/risemediatech.go b/adapters/risemediatech/risemediatech.go index 07792901a07..9daa062a184 100644 --- a/adapters/risemediatech/risemediatech.go +++ b/adapters/risemediatech/risemediatech.go @@ -29,7 +29,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E for imp := range iterators.SlicePointerValues(request.Imp) { impExt, err := parseImpExt(imp.Ext) if err != nil { - errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("impID %s: %v", imp.ID, err)}) + errs = append(errs, &errortypes.BadInput{Message: fmt.Errorf("impID %s: %w", imp.ID, err).Error()}) continue } @@ -106,16 +106,16 @@ func extractImpIDs(imps []openrtb2.Imp) []string { return ids } -func parseImpExt(ext jsonutils.RawMessage) (*openrtb_ext.ExtImpRiseMediaTech, error) { +func parseImpExt(ext jsonutils.RawMessage) (openrtb_ext.ExtImpRiseMediaTech, error) { var bidderExt adapters.ExtImpBidder if err := jsonutils.Unmarshal(ext, &bidderExt); err != nil { - return nil, err + return openrtb_ext.ExtImpRiseMediaTech{}, err } var riseExt openrtb_ext.ExtImpRiseMediaTech if err := jsonutils.Unmarshal(bidderExt.Bidder, &riseExt); err != nil { - return nil, err + return openrtb_ext.ExtImpRiseMediaTech{}, err } - return &riseExt, nil + return riseExt, nil } func (a *adapter) MakeBids(request *openrtb2.BidRequest, reqData *adapters.RequestData, respData *adapters.ResponseData) (*adapters.BidderResponse, []error) { From 5d6ea8e6353209c1b31f83025d8aea55627383df Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Sat, 26 Jul 2025 00:08:02 +0530 Subject: [PATCH 07/15] Updated test cases to improve code coverage --- adapters/risemediatech/risemediatech_test.go | 138 +++++++++++++++++ .../exemplary/imp_banner_and_video.json | 37 +++++ .../exemplary/multiple_seatbids_bids.json | 145 ++++++++++++++++++ .../supplementary/bidfloor_negative.json | 35 +++++ .../supplementary/bidfloor_zero.json | 35 +++++ .../supplementary/imp_no_banner_no_video.json | 14 ++ .../supplementary/invalid_rise_ext_type.json | 17 ++ .../supplementary/test_mode_zero.json | 35 +++++ 8 files changed, 456 insertions(+) create mode 100644 adapters/risemediatech/risemediatechtest/exemplary/imp_banner_and_video.json create mode 100644 adapters/risemediatech/risemediatechtest/exemplary/multiple_seatbids_bids.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/bidfloor_negative.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/bidfloor_zero.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/imp_no_banner_no_video.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/invalid_rise_ext_type.json create mode 100644 adapters/risemediatech/risemediatechtest/supplementary/test_mode_zero.json diff --git a/adapters/risemediatech/risemediatech_test.go b/adapters/risemediatech/risemediatech_test.go index 98f3d99d758..767ff3d227b 100644 --- a/adapters/risemediatech/risemediatech_test.go +++ b/adapters/risemediatech/risemediatech_test.go @@ -7,6 +7,9 @@ import ( "github.com/prebid/prebid-server/v3/config" "github.com/prebid/prebid-server/v3/openrtb_ext" "github.com/stretchr/testify/require" + "github.com/prebid/prebid-server/v3/util/jsonutil" + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v3/adapters" ) func TestJsonSamples(t *testing.T) { @@ -29,3 +32,138 @@ func TestJsonSamples(t *testing.T) { adapterstest.RunJSONBidderTest(t, "risemediatechtest", bidder) } + +// Table-driven test for parseImpExt +func TestParseImpExt(t *testing.T) { + tests := []struct { + name string + ext jsonutil.RawMessage + wantErr bool + }{ + {"Valid ext", jsonutil.RawMessage(`{"bidder":{"placementId":"abc"}}`), false}, + {"Invalid JSON", jsonutil.RawMessage(`not-json`), true}, + {"Not an object", jsonutil.RawMessage(`"string"`), true}, + {"Bidder not object", jsonutil.RawMessage(`{"bidder":"not-an-object"}`), true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := parseImpExt(tt.ext) + if tt.wantErr && err == nil { + t.Errorf("expected error, got nil") + } + if !tt.wantErr && err != nil { + t.Errorf("did not expect error, got %v", err) + } + }) + } +} + +// Table-driven test for getBidType +func TestGetBidType(t *testing.T) { + tests := []struct { + name string + mtype openrtb2.MarkupType + wantErr bool + wantBidTy openrtb_ext.BidType + }{ + {"Banner", openrtb2.MarkupBanner, false, openrtb_ext.BidTypeBanner}, + {"Video", openrtb2.MarkupVideo, false, openrtb_ext.BidTypeVideo}, + {"Unknown", 99, true, ""}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bid := &openrtb2.Bid{MType: tt.mtype} + bidType, err := getBidType(bid) + if tt.wantErr { + if err == nil { + t.Errorf("expected error for mtype=%d, got nil", tt.mtype) + } + } else { + if err != nil { + t.Errorf("did not expect error for mtype=%d, got %v", tt.mtype, err) + } + if bidType != tt.wantBidTy { + t.Errorf("expected bidType %v, got %v", tt.wantBidTy, bidType) + } + } + }) + } +} + +// Table-driven test for MakeRequests error branches +func TestMakeRequestsErrors(t *testing.T) { + a := &adapter{endpoint: "http://test-endpoint"} + baseImp := openrtb2.Imp{ID: "1", Ext: jsonutil.RawMessage(`{"bidder":{"placementId":"abc"}}`)} + tests := []struct { + name string + imps []openrtb2.Imp + wantErr string + }{ + {"Invalid ext", []openrtb2.Imp{{ID: "1", Ext: jsonutil.RawMessage(`not-json`)}}, "impID 1:"}, + {"Invalid banner dims", []openrtb2.Imp{{ID: "1", Banner: &openrtb2.Banner{} /* nil w/h */, Ext: baseImp.Ext}}, "invalid banner dimensions"}, + {"Empty video mimes", []openrtb2.Imp{{ID: "1", Video: &openrtb2.Video{W: intPtr(640), H: intPtr(480), MIMEs: []string{}}, Ext: baseImp.Ext}}, "missing or empty video.mimes"}, + {"Invalid video dims", []openrtb2.Imp{{ID: "1", Video: &openrtb2.Video{W: intPtr(0), H: intPtr(0), MIMEs: []string{"video/mp4"}}, Ext: baseImp.Ext}}, "missing or invalid video width/height"}, + {"No valid imps", []openrtb2.Imp{}, "no valid impressions"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + req := &openrtb2.BidRequest{Imp: tt.imps} + _, errs := a.MakeRequests(req, nil) + if len(errs) == 0 { + t.Errorf("expected error, got none") + } + found := false + for _, err := range errs { + if err != nil && (tt.wantErr == "" || contains(err.Error(), tt.wantErr)) { + found = true + break + } + } + if !found { + t.Errorf("expected error containing %q, got %v", tt.wantErr, errs) + } + }) + } +} + +// Table-driven test for MakeBids error branches +func TestMakeBidsErrors(t *testing.T) { + a := &adapter{endpoint: "http://test-endpoint"} + validReq := &openrtb2.BidRequest{ID: "1"} + validReqData := &adapters.RequestData{} + tests := []struct { + name string + respData *adapters.ResponseData + wantErr string + }{ + {"Non-200/204 response", &adapters.ResponseData{StatusCode: 500, Body: []byte(`{}`)}, "Unexpected status code"}, + {"Invalid JSON", &adapters.ResponseData{StatusCode: 200, Body: []byte(`not-json`)}, ""}, + {"Unknown mtype", &adapters.ResponseData{StatusCode: 200, Body: []byte(`{"id":"1","seatbid":[{"bid":[{"id":"b1","impid":"1","price":1.0,"adm":"
test
","mtype":99}]}],"cur":"USD"}`)}, "unknown bid type"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, errs := a.MakeBids(validReq, validReqData, tt.respData) + if len(errs) == 0 { + t.Errorf("expected error, got none") + } + found := false + for _, err := range errs { + if err != nil && contains(err.Error(), tt.wantErr) { + found = true + break + } + } + if !found { + t.Errorf("expected error containing %q, got %v", tt.wantErr, errs) + } + }) + } +} + +// Helper for int pointer +func intPtr(i int64) *int64 { return &i } +// Helper for string contains +func contains(s, substr string) bool { return substr == "" || (len(substr) > 0 && len(s) > 0 && (len(s) >= len(substr)) && (stringContains(s, substr))) } +func stringContains(s, substr string) bool { return len(substr) == 0 || (len(s) >= len(substr) && (s == substr || (len(s) > len(substr) && (s[0:len(substr)] == substr || stringContains(s[1:], substr)))) ) } diff --git a/adapters/risemediatech/risemediatechtest/exemplary/imp_banner_and_video.json b/adapters/risemediatech/risemediatechtest/exemplary/imp_banner_and_video.json new file mode 100644 index 00000000000..e5ceb557765 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/exemplary/imp_banner_and_video.json @@ -0,0 +1,37 @@ +{ + "mockBidRequest": { + "id": "test-banner-and-video", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "video": { "w": 640, "h": 480, "mimes": ["video/mp4"] }, + "ext": { "bidder": { "placementId": "abc" } } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "body": { + "id": "test-banner-and-video", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "video": { "w": 640, "h": 480, "mimes": ["video/mp4"] }, + "ext": { "bidder": { "placementId": "abc" } } + } + ] + }, + "impIDs": ["1"] + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + "expectedBidResponses": [] + } \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/exemplary/multiple_seatbids_bids.json b/adapters/risemediatech/risemediatechtest/exemplary/multiple_seatbids_bids.json new file mode 100644 index 00000000000..e1dbabfc477 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/exemplary/multiple_seatbids_bids.json @@ -0,0 +1,145 @@ +{ + "mockBidRequest": { + "id": "test-multiple-seatbids-bids", + "imp": [ + { + "id": "imp-1", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "placementId": "abc" + } + } + }, + { + "id": "imp-2", + "video": { + "w": 640, + "h": 480, + "mimes": [ + "video/mp4" + ] + }, + "ext": { + "bidder": { + "placementId": "def" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "body": { + "id": "test-multiple-seatbids-bids", + "imp": [ + { + "id": "imp-1", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "placementId": "abc" + } + } + }, + { + "id": "imp-2", + "video": { + "w": 640, + "h": 480, + "mimes": [ + "video/mp4" + ] + }, + "ext": { + "bidder": { + "placementId": "def" + } + } + } + ] + }, + "impIDs": [ + "imp-1", + "imp-2" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-multiple-seatbids-bids", + "seatbid": [ + { + "seat": "seat-1", + "bid": [ + { + "id": "bid-1", + "impid": "imp-1", + "price": 1.0, + "adm": "
Banner
", + "mtype": 1, + "w": 300, + "h": 250 + } + ] + }, + { + "seat": "seat-2", + "bid": [ + { + "id": "bid-2", + "impid": "imp-2", + "price": 2.0, + "adm": "", + "mtype": 2, + "w": 640, + "h": 480 + } + ] + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "bid-1", + "impid": "imp-1", + "price": 1.0, + "adm": "
Banner
", + "mtype": 1, + "w": 300, + "h": 250 + }, + "type": "banner" + }, + { + "bid": { + "id": "bid-2", + "impid": "imp-2", + "price": 2.0, + "adm": "", + "mtype": 2, + "w": 640, + "h": 480 + }, + "type": "video" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/supplementary/bidfloor_negative.json b/adapters/risemediatech/risemediatechtest/supplementary/bidfloor_negative.json new file mode 100644 index 00000000000..ded7b647e95 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/bidfloor_negative.json @@ -0,0 +1,35 @@ +{ + "mockBidRequest": { + "id": "test-bidfloor-negative", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "ext": { "bidder": { "placementId": "abc", "bidFloor": -1 } } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "body": { + "id": "test-bidfloor-negative", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "ext": { "bidder": { "placementId": "abc", "bidFloor": -1 } } + } + ] + }, + "impIDs": ["1"] + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + "expectedBidResponses": [] + } \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/supplementary/bidfloor_zero.json b/adapters/risemediatech/risemediatechtest/supplementary/bidfloor_zero.json new file mode 100644 index 00000000000..1a889e49435 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/bidfloor_zero.json @@ -0,0 +1,35 @@ +{ + "mockBidRequest": { + "id": "test-bidfloor-zero", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "ext": { "bidder": { "placementId": "abc", "bidFloor": 0 } } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "body": { + "id": "test-bidfloor-zero", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "ext": { "bidder": { "placementId": "abc", "bidFloor": 0 } } + } + ] + }, + "impIDs": ["1"] + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + "expectedBidResponses": [] + } \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/supplementary/imp_no_banner_no_video.json b/adapters/risemediatech/risemediatechtest/supplementary/imp_no_banner_no_video.json new file mode 100644 index 00000000000..b120c58c221 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/imp_no_banner_no_video.json @@ -0,0 +1,14 @@ +{ + "mockBidRequest": { + "id": "test-no-banner-no-video", + "imp": [ + { + "id": "1", + "ext": { "bidder": { "placementId": "abc" } } + } + ] + }, + "expectedMakeRequestsErrors": [ + { "value": "no valid impressions", "comparison": "contains" } + ] + } \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/supplementary/invalid_rise_ext_type.json b/adapters/risemediatech/risemediatechtest/supplementary/invalid_rise_ext_type.json new file mode 100644 index 00000000000..bff351a595c --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/invalid_rise_ext_type.json @@ -0,0 +1,17 @@ +{ + "mockBidRequest": { + "id": "test-invalid-rise-ext-not-object", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "ext": { + "bidder": "not-an-object" + } + } + ] + }, + "expectedMakeRequestsErrors": [ + { "value": "impID 1:", "comparison": "contains" } + ] + } \ No newline at end of file diff --git a/adapters/risemediatech/risemediatechtest/supplementary/test_mode_zero.json b/adapters/risemediatech/risemediatechtest/supplementary/test_mode_zero.json new file mode 100644 index 00000000000..f908b469589 --- /dev/null +++ b/adapters/risemediatech/risemediatechtest/supplementary/test_mode_zero.json @@ -0,0 +1,35 @@ +{ + "mockBidRequest": { + "id": "test-test-mode-zero", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "ext": { "bidder": { "placementId": "abc", "testMode": 0 } } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://dev-ads.risemediatech.com/ads/rtb/prebid/server", + "body": { + "id": "test-test-mode-zero", + "imp": [ + { + "id": "1", + "banner": { "w": 300, "h": 250 }, + "ext": { "bidder": { "placementId": "abc", "testMode": 0 } } + } + ] + }, + "impIDs": ["1"] + }, + "mockResponse": { + "status": 204, + "body": {} + } + } + ], + "expectedBidResponses": [] + } \ No newline at end of file From ddbb2d83268f5d5465e8617b312bcfc0bfd30236 Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Sat, 26 Jul 2025 18:14:02 +0530 Subject: [PATCH 08/15] Changes as per review comments. --- adapters/risemediatech/params_test.go | 36 ++++++++++++++------ adapters/risemediatech/risemediatech.go | 22 ++++++------ adapters/risemediatech/risemediatech_test.go | 27 ++++++--------- 3 files changed, 47 insertions(+), 38 deletions(-) diff --git a/adapters/risemediatech/params_test.go b/adapters/risemediatech/params_test.go index 31c49d377f6..404552ff805 100644 --- a/adapters/risemediatech/params_test.go +++ b/adapters/risemediatech/params_test.go @@ -12,12 +12,19 @@ func TestValidParams(t *testing.T) { validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") require.NoError(t, err, "Failed to fetch the JSON schema") - for _, p := range validParams { - p := p // capture range variable - t.Run(p, func(t *testing.T) { - err := validator.Validate(openrtb_ext.BidderRiseMediaTech, json.RawMessage(p)) + tests := []struct { + name string + input string + }{ + {"Valid bidfloor only", `{"bidfloor": 0.01}`}, + {"Valid bidfloor with testMode", `{"bidfloor": 2.5, "testMode": 1}`}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := validator.Validate(openrtb_ext.BidderRiseMediaTech, json.RawMessage(tt.input)) if err != nil { - t.Errorf("Schema rejected valid params: %s — error: %v", p, err) + t.Errorf("Schema rejected valid params: %s — error: %v", tt.input, err) } }) } @@ -27,12 +34,21 @@ func TestInvalidParams(t *testing.T) { validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") require.NoError(t, err, "Failed to fetch the JSON schema") - for _, p := range invalidParams { - p := p // capture range variable - t.Run(p, func(t *testing.T) { - err := validator.Validate(openrtb_ext.BidderRiseMediaTech, json.RawMessage(p)) + tests := []struct { + name string + input string + }{ + {"Invalid bidfloor type", `{"bidfloor": "1.2"}`}, + {"Invalid testMode type", `{"testMode": "yes"}`}, + {"Negative bidfloor", `{"bidfloor": -5}`}, + {"Invalid testMode value", `{"testMode": 9999}`}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := validator.Validate(openrtb_ext.BidderRiseMediaTech, json.RawMessage(tt.input)) if err == nil { - t.Errorf("Schema allowed invalid params: %s", p) + t.Errorf("Schema allowed invalid params: %s", tt.input) } }) } diff --git a/adapters/risemediatech/risemediatech.go b/adapters/risemediatech/risemediatech.go index 9daa062a184..69835c9955a 100644 --- a/adapters/risemediatech/risemediatech.go +++ b/adapters/risemediatech/risemediatech.go @@ -9,8 +9,8 @@ import ( "github.com/prebid/prebid-server/v3/config" "github.com/prebid/prebid-server/v3/errortypes" "github.com/prebid/prebid-server/v3/openrtb_ext" - iterators "github.com/prebid/prebid-server/v3/util/iterutil" - jsonutils "github.com/prebid/prebid-server/v3/util/jsonutil" + "github.com/prebid/prebid-server/v3/util/iterutil" + "github.com/prebid/prebid-server/v3/util/jsonutil" ) type adapter struct { @@ -26,7 +26,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E var validImps []openrtb2.Imp var setTestMode bool - for imp := range iterators.SlicePointerValues(request.Imp) { + for imp := range iterutil.SlicePointerValues(request.Imp) { impExt, err := parseImpExt(imp.Ext) if err != nil { errs = append(errs, &errortypes.BadInput{Message: fmt.Errorf("impID %s: %w", imp.ID, err).Error()}) @@ -76,7 +76,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E modifiedRequest.Test = 1 } - reqJSON, err := jsonutils.Marshal(modifiedRequest) + reqJSON, err := jsonutil.Marshal(modifiedRequest) if err != nil { return nil, append(errs, err) } @@ -100,19 +100,19 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E func extractImpIDs(imps []openrtb2.Imp) []string { ids := make([]string, 0, len(imps)) - for imp := range iterators.SlicePointerValues(imps) { + for imp := range iterutil.SlicePointerValues(imps) { ids = append(ids, imp.ID) } return ids } -func parseImpExt(ext jsonutils.RawMessage) (openrtb_ext.ExtImpRiseMediaTech, error) { +func parseImpExt(ext jsonutil.RawMessage) (openrtb_ext.ExtImpRiseMediaTech, error) { var bidderExt adapters.ExtImpBidder - if err := jsonutils.Unmarshal(ext, &bidderExt); err != nil { + if err := jsonutil.Unmarshal(ext, &bidderExt); err != nil { return openrtb_ext.ExtImpRiseMediaTech{}, err } var riseExt openrtb_ext.ExtImpRiseMediaTech - if err := jsonutils.Unmarshal(bidderExt.Bidder, &riseExt); err != nil { + if err := jsonutil.Unmarshal(bidderExt.Bidder, &riseExt); err != nil { return openrtb_ext.ExtImpRiseMediaTech{}, err } return riseExt, nil @@ -127,7 +127,7 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, reqData *adapters.Reque } var bidResp openrtb2.BidResponse - if err := jsonutils.Unmarshal(respData.Body, &bidResp); err != nil { + if err := jsonutil.Unmarshal(respData.Body, &bidResp); err != nil { return nil, []error{err} } @@ -136,8 +136,8 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, reqData *adapters.Reque br.Currency = bidResp.Cur } - for seatBid := range iterators.SlicePointerValues(bidResp.SeatBid) { - for bid := range iterators.SlicePointerValues(seatBid.Bid) { + for seatBid := range iterutil.SlicePointerValues(bidResp.SeatBid) { + for bid := range iterutil.SlicePointerValues(seatBid.Bid) { bidType, err := getBidType(bid) if err != nil { return nil, []error{err} diff --git a/adapters/risemediatech/risemediatech_test.go b/adapters/risemediatech/risemediatech_test.go index 767ff3d227b..f84d76989f3 100644 --- a/adapters/risemediatech/risemediatech_test.go +++ b/adapters/risemediatech/risemediatech_test.go @@ -1,15 +1,18 @@ package risemediatech import ( + "strings" "testing" "github.com/prebid/prebid-server/v3/adapters/adapterstest" "github.com/prebid/prebid-server/v3/config" "github.com/prebid/prebid-server/v3/openrtb_ext" - "github.com/stretchr/testify/require" "github.com/prebid/prebid-server/v3/util/jsonutil" + "github.com/prebid/prebid-server/v3/util/ptrutil" "github.com/prebid/openrtb/v20/openrtb2" "github.com/prebid/prebid-server/v3/adapters" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestJsonSamples(t *testing.T) { @@ -103,20 +106,18 @@ func TestMakeRequestsErrors(t *testing.T) { }{ {"Invalid ext", []openrtb2.Imp{{ID: "1", Ext: jsonutil.RawMessage(`not-json`)}}, "impID 1:"}, {"Invalid banner dims", []openrtb2.Imp{{ID: "1", Banner: &openrtb2.Banner{} /* nil w/h */, Ext: baseImp.Ext}}, "invalid banner dimensions"}, - {"Empty video mimes", []openrtb2.Imp{{ID: "1", Video: &openrtb2.Video{W: intPtr(640), H: intPtr(480), MIMEs: []string{}}, Ext: baseImp.Ext}}, "missing or empty video.mimes"}, - {"Invalid video dims", []openrtb2.Imp{{ID: "1", Video: &openrtb2.Video{W: intPtr(0), H: intPtr(0), MIMEs: []string{"video/mp4"}}, Ext: baseImp.Ext}}, "missing or invalid video width/height"}, + {"Empty video mimes", []openrtb2.Imp{{ID: "1", Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](640), H: ptrutil.ToPtr[int64](480), MIMEs: []string{}}, Ext: baseImp.Ext}}, "missing or empty video.mimes"}, + {"Invalid video dims", []openrtb2.Imp{{ID: "1", Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](0), H: ptrutil.ToPtr[int64](0), MIMEs: []string{"video/mp4"}}, Ext: baseImp.Ext}}, "missing or invalid video width/height"}, {"No valid imps", []openrtb2.Imp{}, "no valid impressions"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { req := &openrtb2.BidRequest{Imp: tt.imps} _, errs := a.MakeRequests(req, nil) - if len(errs) == 0 { - t.Errorf("expected error, got none") - } + assert.NotEmpty(t, errs, "expected error, got none") found := false for _, err := range errs { - if err != nil && (tt.wantErr == "" || contains(err.Error(), tt.wantErr)) { + if err != nil && (tt.wantErr == "" || strings.Contains(err.Error(), tt.wantErr)) { found = true break } @@ -145,12 +146,10 @@ func TestMakeBidsErrors(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { _, errs := a.MakeBids(validReq, validReqData, tt.respData) - if len(errs) == 0 { - t.Errorf("expected error, got none") - } + assert.NotEmpty(t, errs, "expected error, got none") found := false for _, err := range errs { - if err != nil && contains(err.Error(), tt.wantErr) { + if err != nil && strings.Contains(err.Error(), tt.wantErr) { found = true break } @@ -161,9 +160,3 @@ func TestMakeBidsErrors(t *testing.T) { }) } } - -// Helper for int pointer -func intPtr(i int64) *int64 { return &i } -// Helper for string contains -func contains(s, substr string) bool { return substr == "" || (len(substr) > 0 && len(s) > 0 && (len(s) >= len(substr)) && (stringContains(s, substr))) } -func stringContains(s, substr string) bool { return len(substr) == 0 || (len(s) >= len(substr) && (s == substr || (len(s) > len(substr) && (s[0:len(substr)] == substr || stringContains(s[1:], substr)))) ) } From efe1f598bff2bb42b3318244fcfd84e4d595305b Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Mon, 28 Jul 2025 19:23:04 +0530 Subject: [PATCH 09/15] Additional PR Review comment handled --- adapters/risemediatech/params_test.go | 22 +++----------------- adapters/risemediatech/risemediatech.go | 6 +++--- adapters/risemediatech/risemediatech_test.go | 14 ++++++------- 3 files changed, 13 insertions(+), 29 deletions(-) diff --git a/adapters/risemediatech/params_test.go b/adapters/risemediatech/params_test.go index 404552ff805..3671ba15cce 100644 --- a/adapters/risemediatech/params_test.go +++ b/adapters/risemediatech/params_test.go @@ -6,6 +6,7 @@ import ( "github.com/prebid/prebid-server/v3/openrtb_ext" "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" ) func TestValidParams(t *testing.T) { @@ -22,10 +23,7 @@ func TestValidParams(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := validator.Validate(openrtb_ext.BidderRiseMediaTech, json.RawMessage(tt.input)) - if err != nil { - t.Errorf("Schema rejected valid params: %s — error: %v", tt.input, err) - } + assert.NoError(t, validator.Validate(openrtb_ext.BidderRiseMediaTech, json.RawMessage(tt.input))) }) } } @@ -46,22 +44,8 @@ func TestInvalidParams(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := validator.Validate(openrtb_ext.BidderRiseMediaTech, json.RawMessage(tt.input)) - if err == nil { - t.Errorf("Schema allowed invalid params: %s", tt.input) - } + assert.Error(t, validator.Validate(openrtb_ext.BidderRiseMediaTech, json.RawMessage(tt.input))) }) } } -var validParams = []string{ - `{"bidfloor": 0.01}`, - `{"bidfloor": 2.5, "testMode": 1}`, -} - -var invalidParams = []string{ - `{"bidfloor": "1.2"}`, - `{"testMode": "yes"}`, - `{"bidfloor": -5}`, - `{"testMode": 9999}`, -} diff --git a/adapters/risemediatech/risemediatech.go b/adapters/risemediatech/risemediatech.go index 69835c9955a..362eaf8209e 100644 --- a/adapters/risemediatech/risemediatech.go +++ b/adapters/risemediatech/risemediatech.go @@ -99,9 +99,9 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E } func extractImpIDs(imps []openrtb2.Imp) []string { - ids := make([]string, 0, len(imps)) - for imp := range iterutil.SlicePointerValues(imps) { - ids = append(ids, imp.ID) + ids := make([]string, len(imps)) + for i := range imps { + ids[i] = imps[i].ID } return ids } diff --git a/adapters/risemediatech/risemediatech_test.go b/adapters/risemediatech/risemediatech_test.go index f84d76989f3..6bac205dd53 100644 --- a/adapters/risemediatech/risemediatech_test.go +++ b/adapters/risemediatech/risemediatech_test.go @@ -53,10 +53,10 @@ func TestParseImpExt(t *testing.T) { t.Run(tt.name, func(t *testing.T) { _, err := parseImpExt(tt.ext) if tt.wantErr && err == nil { - t.Errorf("expected error, got nil") + assert.Error(t, err) } if !tt.wantErr && err != nil { - t.Errorf("did not expect error, got %v", err) + assert.NoError(t, err) } }) } @@ -81,14 +81,14 @@ func TestGetBidType(t *testing.T) { bidType, err := getBidType(bid) if tt.wantErr { if err == nil { - t.Errorf("expected error for mtype=%d, got nil", tt.mtype) + assert.Error(t, err) } } else { if err != nil { - t.Errorf("did not expect error for mtype=%d, got %v", tt.mtype, err) + assert.NoError(t, err) } if bidType != tt.wantBidTy { - t.Errorf("expected bidType %v, got %v", tt.wantBidTy, bidType) + assert.Equal(t, tt.wantBidTy, bidType) } } }) @@ -123,7 +123,7 @@ func TestMakeRequestsErrors(t *testing.T) { } } if !found { - t.Errorf("expected error containing %q, got %v", tt.wantErr, errs) + assert.True(t, found, "expected error containing %q, got %v", tt.wantErr, errs) } }) } @@ -155,7 +155,7 @@ func TestMakeBidsErrors(t *testing.T) { } } if !found { - t.Errorf("expected error containing %q, got %v", tt.wantErr, errs) + assert.True(t, found, "expected error containing %q, got %v", tt.wantErr, errs) } }) } From 43073e0a1f65dd59fadfd9bb9e441697608fcbf0 Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Tue, 29 Jul 2025 16:16:13 +0530 Subject: [PATCH 10/15] Modified error string as per review comments --- adapters/risemediatech/risemediatech.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adapters/risemediatech/risemediatech.go b/adapters/risemediatech/risemediatech.go index 362eaf8209e..02cc2427aaf 100644 --- a/adapters/risemediatech/risemediatech.go +++ b/adapters/risemediatech/risemediatech.go @@ -29,7 +29,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E for imp := range iterutil.SlicePointerValues(request.Imp) { impExt, err := parseImpExt(imp.Ext) if err != nil { - errs = append(errs, &errortypes.BadInput{Message: fmt.Errorf("impID %s: %w", imp.ID, err).Error()}) + errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("impID %s: %v", imp.ID, err)}) continue } From ed0afaed914c4efc573ca9926bece16a4b1b93d5 Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Wed, 6 Aug 2025 12:33:25 +0530 Subject: [PATCH 11/15] Modifications as per reviewer comments --- adapters/risemediatech/risemediatech_test.go | 39 +++++++------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/adapters/risemediatech/risemediatech_test.go b/adapters/risemediatech/risemediatech_test.go index 6bac205dd53..f2ebc6379bd 100644 --- a/adapters/risemediatech/risemediatech_test.go +++ b/adapters/risemediatech/risemediatech_test.go @@ -4,13 +4,13 @@ import ( "strings" "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/openrtb_ext" "github.com/prebid/prebid-server/v3/util/jsonutil" "github.com/prebid/prebid-server/v3/util/ptrutil" - "github.com/prebid/openrtb/v20/openrtb2" - "github.com/prebid/prebid-server/v3/adapters" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -52,12 +52,11 @@ func TestParseImpExt(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { _, err := parseImpExt(tt.ext) - if tt.wantErr && err == nil { - assert.Error(t, err) - } - if !tt.wantErr && err != nil { - assert.NoError(t, err) + if tt.wantErr { + require.Error(t, err) + return } + require.NoError(t, err) }) } } @@ -80,17 +79,11 @@ func TestGetBidType(t *testing.T) { bid := &openrtb2.Bid{MType: tt.mtype} bidType, err := getBidType(bid) if tt.wantErr { - if err == nil { - assert.Error(t, err) - } - } else { - if err != nil { - assert.NoError(t, err) - } - if bidType != tt.wantBidTy { - assert.Equal(t, tt.wantBidTy, bidType) - } + require.Error(t, err) + return } + require.NoError(t, err) + assert.Equal(t, tt.wantBidTy, bidType) }) } } @@ -114,7 +107,7 @@ func TestMakeRequestsErrors(t *testing.T) { t.Run(tt.name, func(t *testing.T) { req := &openrtb2.BidRequest{Imp: tt.imps} _, errs := a.MakeRequests(req, nil) - assert.NotEmpty(t, errs, "expected error, got none") + require.NotEmpty(t, errs, "expected error, got none") found := false for _, err := range errs { if err != nil && (tt.wantErr == "" || strings.Contains(err.Error(), tt.wantErr)) { @@ -122,9 +115,7 @@ func TestMakeRequestsErrors(t *testing.T) { break } } - if !found { - assert.True(t, found, "expected error containing %q, got %v", tt.wantErr, errs) - } + assert.True(t, found, "expected error containing %q, got %v", tt.wantErr, errs) }) } } @@ -146,7 +137,7 @@ func TestMakeBidsErrors(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { _, errs := a.MakeBids(validReq, validReqData, tt.respData) - assert.NotEmpty(t, errs, "expected error, got none") + require.NotEmpty(t, errs, "expected error, got none") found := false for _, err := range errs { if err != nil && strings.Contains(err.Error(), tt.wantErr) { @@ -154,9 +145,7 @@ func TestMakeBidsErrors(t *testing.T) { break } } - if !found { - assert.True(t, found, "expected error containing %q, got %v", tt.wantErr, errs) - } + assert.True(t, found, "expected error containing %q, got %v", tt.wantErr, errs) }) } } From 6b46abfa7106c1b14d3ed74290c5b8c4b924b553 Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Wed, 20 Aug 2025 15:46:29 +0530 Subject: [PATCH 12/15] Changes as per review comments --- adapters/risemediatech/risemediatech.go | 4 ---- adapters/risemediatech/risemediatech_test.go | 4 ---- 2 files changed, 8 deletions(-) diff --git a/adapters/risemediatech/risemediatech.go b/adapters/risemediatech/risemediatech.go index 02cc2427aaf..dfd8b39b6f2 100644 --- a/adapters/risemediatech/risemediatech.go +++ b/adapters/risemediatech/risemediatech.go @@ -33,7 +33,6 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E continue } - // Validate banner if imp.Banner != nil { if imp.Banner.W == nil || imp.Banner.H == nil || *imp.Banner.W == 0 || *imp.Banner.H == 0 { errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("impID %s: invalid banner dimensions", imp.ID)}) @@ -41,7 +40,6 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E } } - // Validate video if imp.Video != nil { if len(imp.Video.MIMEs) == 0 { errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("impID %s: missing or empty video.mimes", imp.ID)}) @@ -53,12 +51,10 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E } } - // Setting bid floor if present if impExt.BidFloor > 0 { imp.BidFloor = impExt.BidFloor } - // Check test mode if impExt.TestMode == 1 { setTestMode = true } diff --git a/adapters/risemediatech/risemediatech_test.go b/adapters/risemediatech/risemediatech_test.go index f2ebc6379bd..e49a4ff03fe 100644 --- a/adapters/risemediatech/risemediatech_test.go +++ b/adapters/risemediatech/risemediatech_test.go @@ -36,7 +36,6 @@ func TestJsonSamples(t *testing.T) { adapterstest.RunJSONBidderTest(t, "risemediatechtest", bidder) } -// Table-driven test for parseImpExt func TestParseImpExt(t *testing.T) { tests := []struct { name string @@ -61,7 +60,6 @@ func TestParseImpExt(t *testing.T) { } } -// Table-driven test for getBidType func TestGetBidType(t *testing.T) { tests := []struct { name string @@ -88,7 +86,6 @@ func TestGetBidType(t *testing.T) { } } -// Table-driven test for MakeRequests error branches func TestMakeRequestsErrors(t *testing.T) { a := &adapter{endpoint: "http://test-endpoint"} baseImp := openrtb2.Imp{ID: "1", Ext: jsonutil.RawMessage(`{"bidder":{"placementId":"abc"}}`)} @@ -120,7 +117,6 @@ func TestMakeRequestsErrors(t *testing.T) { } } -// Table-driven test for MakeBids error branches func TestMakeBidsErrors(t *testing.T) { a := &adapter{endpoint: "http://test-endpoint"} validReq := &openrtb2.BidRequest{ID: "1"} From 92e43bde8773c4b19a9934f87cc017249748fbae Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Tue, 9 Sep 2025 22:51:54 +0530 Subject: [PATCH 13/15] Executed go fmt as per review comments --- adapters/risemediatech/params_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/adapters/risemediatech/params_test.go b/adapters/risemediatech/params_test.go index 3671ba15cce..588c6fcfb38 100644 --- a/adapters/risemediatech/params_test.go +++ b/adapters/risemediatech/params_test.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/prebid/prebid-server/v3/openrtb_ext" - "github.com/stretchr/testify/require" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestValidParams(t *testing.T) { @@ -48,4 +48,3 @@ func TestInvalidParams(t *testing.T) { }) } } - From 8a36c57c87064b2f209b624ab7c9078dc69cb718 Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Tue, 7 Oct 2025 00:53:58 +0530 Subject: [PATCH 14/15] Handled review comments --- adapters/risemediatech/risemediatech.go | 37 +++----------------- adapters/risemediatech/risemediatech_test.go | 5 --- 2 files changed, 4 insertions(+), 38 deletions(-) diff --git a/adapters/risemediatech/risemediatech.go b/adapters/risemediatech/risemediatech.go index dfd8b39b6f2..549d8d51476 100644 --- a/adapters/risemediatech/risemediatech.go +++ b/adapters/risemediatech/risemediatech.go @@ -33,24 +33,6 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E continue } - if imp.Banner != nil { - if imp.Banner.W == nil || imp.Banner.H == nil || *imp.Banner.W == 0 || *imp.Banner.H == 0 { - errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("impID %s: invalid banner dimensions", imp.ID)}) - continue - } - } - - if imp.Video != nil { - if len(imp.Video.MIMEs) == 0 { - errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("impID %s: missing or empty video.mimes", imp.ID)}) - continue - } - if imp.Video.W == nil || imp.Video.H == nil || *imp.Video.W == 0 || *imp.Video.H == 0 { - errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("impID %s: missing or invalid video width/height", imp.ID)}) - continue - } - } - if impExt.BidFloor > 0 { imp.BidFloor = impExt.BidFloor } @@ -66,13 +48,12 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E return nil, append(errs, &errortypes.BadInput{Message: "no valid impressions"}) } - modifiedRequest := *request - modifiedRequest.Imp = validImps + request.Imp = validImps if setTestMode { - modifiedRequest.Test = 1 + request.Test = 1 } - reqJSON, err := jsonutil.Marshal(modifiedRequest) + reqJSON, err := jsonutil.Marshal(request) if err != nil { return nil, append(errs, err) } @@ -80,8 +61,6 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E headers := http.Header{} headers.Set("Content-Type", "application/json;charset=utf-8") headers.Set("Accept", "application/json") - headers.Set("User-Agent", "prebid-server") - headers.Set("X-Prebid", "true") return []*adapters.RequestData{ { @@ -89,19 +68,11 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E Uri: a.endpoint, Body: reqJSON, Headers: headers, - ImpIDs: extractImpIDs(validImps), + ImpIDs: openrtb_ext.GetImpIDs(validImps), }, }, errs } -func extractImpIDs(imps []openrtb2.Imp) []string { - ids := make([]string, len(imps)) - for i := range imps { - ids[i] = imps[i].ID - } - return ids -} - func parseImpExt(ext jsonutil.RawMessage) (openrtb_ext.ExtImpRiseMediaTech, error) { var bidderExt adapters.ExtImpBidder if err := jsonutil.Unmarshal(ext, &bidderExt); err != nil { diff --git a/adapters/risemediatech/risemediatech_test.go b/adapters/risemediatech/risemediatech_test.go index e49a4ff03fe..8ab8022c615 100644 --- a/adapters/risemediatech/risemediatech_test.go +++ b/adapters/risemediatech/risemediatech_test.go @@ -10,7 +10,6 @@ import ( "github.com/prebid/prebid-server/v3/config" "github.com/prebid/prebid-server/v3/openrtb_ext" "github.com/prebid/prebid-server/v3/util/jsonutil" - "github.com/prebid/prebid-server/v3/util/ptrutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -88,16 +87,12 @@ func TestGetBidType(t *testing.T) { func TestMakeRequestsErrors(t *testing.T) { a := &adapter{endpoint: "http://test-endpoint"} - baseImp := openrtb2.Imp{ID: "1", Ext: jsonutil.RawMessage(`{"bidder":{"placementId":"abc"}}`)} tests := []struct { name string imps []openrtb2.Imp wantErr string }{ {"Invalid ext", []openrtb2.Imp{{ID: "1", Ext: jsonutil.RawMessage(`not-json`)}}, "impID 1:"}, - {"Invalid banner dims", []openrtb2.Imp{{ID: "1", Banner: &openrtb2.Banner{} /* nil w/h */, Ext: baseImp.Ext}}, "invalid banner dimensions"}, - {"Empty video mimes", []openrtb2.Imp{{ID: "1", Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](640), H: ptrutil.ToPtr[int64](480), MIMEs: []string{}}, Ext: baseImp.Ext}}, "missing or empty video.mimes"}, - {"Invalid video dims", []openrtb2.Imp{{ID: "1", Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](0), H: ptrutil.ToPtr[int64](0), MIMEs: []string{"video/mp4"}}, Ext: baseImp.Ext}}, "missing or invalid video width/height"}, {"No valid imps", []openrtb2.Imp{}, "no valid impressions"}, } for _, tt := range tests { From 4cdb024d329641ed82813f5b46aa75afd35a07b9 Mon Sep 17 00:00:00 2001 From: pritishmd-talentica Date: Tue, 28 Oct 2025 16:03:31 +0530 Subject: [PATCH 15/15] Handled PR Review comments by reviwer in upstream PR on 27-10-2025 --- adapters/risemediatech/risemediatech.go | 14 +++++++++++--- adapters/risemediatech/risemediatech_test.go | 1 + .../supplementary/imp_no_banner_no_video.json | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/adapters/risemediatech/risemediatech.go b/adapters/risemediatech/risemediatech.go index 549d8d51476..93a50f62a5a 100644 --- a/adapters/risemediatech/risemediatech.go +++ b/adapters/risemediatech/risemediatech.go @@ -17,13 +17,14 @@ type adapter struct { endpoint string } -func Builder(bidderName openrtb_ext.BidderName, cfg config.Adapter, server config.Server) (adapters.Bidder, error) { +func Builder(_ openrtb_ext.BidderName, cfg config.Adapter, _ config.Server) (adapters.Bidder, error) { return &adapter{endpoint: cfg.Endpoint}, nil } func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { var errs []error - var validImps []openrtb2.Imp + validImps := make([]openrtb2.Imp, 0, len(request.Imp)) + // Note: If ANY impression has testMode=1, the entire request is marked as test var setTestMode bool for imp := range iterutil.SlicePointerValues(request.Imp) { @@ -33,7 +34,14 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E continue } - if impExt.BidFloor > 0 { + if imp.Banner == nil && imp.Video == nil { + errs = append(errs, &errortypes.BadInput{ + Message: fmt.Sprintf("impID %s: no banner or video object specified", imp.ID), + }) + continue + } + + if imp.BidFloor == 0 && impExt.BidFloor > 0 { imp.BidFloor = impExt.BidFloor } diff --git a/adapters/risemediatech/risemediatech_test.go b/adapters/risemediatech/risemediatech_test.go index 8ab8022c615..eb4afdfc97f 100644 --- a/adapters/risemediatech/risemediatech_test.go +++ b/adapters/risemediatech/risemediatech_test.go @@ -94,6 +94,7 @@ func TestMakeRequestsErrors(t *testing.T) { }{ {"Invalid ext", []openrtb2.Imp{{ID: "1", Ext: jsonutil.RawMessage(`not-json`)}}, "impID 1:"}, {"No valid imps", []openrtb2.Imp{}, "no valid impressions"}, + {"No banner or video", []openrtb2.Imp{{ID: "1", Ext: jsonutil.RawMessage(`{"bidder":{"bidfloor": 0.5}}`)}}, "no banner or video object specified"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/adapters/risemediatech/risemediatechtest/supplementary/imp_no_banner_no_video.json b/adapters/risemediatech/risemediatechtest/supplementary/imp_no_banner_no_video.json index b120c58c221..2132e3203a8 100644 --- a/adapters/risemediatech/risemediatechtest/supplementary/imp_no_banner_no_video.json +++ b/adapters/risemediatech/risemediatechtest/supplementary/imp_no_banner_no_video.json @@ -9,6 +9,6 @@ ] }, "expectedMakeRequestsErrors": [ - { "value": "no valid impressions", "comparison": "contains" } + { "value": "impID 1: no banner or video object specified", "comparison": "literal" } ] } \ No newline at end of file