Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions adapters/targetVideo/params_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package targetVideo

import (
"encoding/json"
"testing"

"github.com/prebid/prebid-server/v3/openrtb_ext"
)

func TestValidParams(t *testing.T) {
validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
if err != nil {
t.Fatalf("Failed to fetch the json-schemas. %v", err)
}

for _, validParam := range validParams {
if err := validator.Validate(openrtb_ext.BidderTargetVideo, json.RawMessage(validParam)); err != nil {
t.Errorf("Schema rejected targetVideo params: %s", validParam)
}
}
}

func TestInvalidParams(t *testing.T) {
validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
if err != nil {
t.Fatalf("Failed to fetch the json-schemas. %v", err)
}

for _, invalidParam := range invalidParams {
if err := validator.Validate(openrtb_ext.BidderTargetVideo, json.RawMessage(invalidParam)); err == nil {
t.Errorf("Schema allowed unexpected params: %s", invalidParam)
}
}
}

var validParams = []string{
`{"placementId":846}`,
`{"placementId":"846"}`,
}

var invalidParams = []string{
`null`,
`nil`,
`undefined`,
`{"placementId": "%9"}`,
`{"publisherId": "as9""}`,
`{"placementId": true}`,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add {"placementId": ""} to invalid params to ensure your regex is correct.

`{"placementId": ""}`,
}
140 changes: 140 additions & 0 deletions adapters/targetVideo/targetvideo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package targetVideo

import (
"encoding/json"
"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/errortypes"
"github.com/prebid/prebid-server/v3/openrtb_ext"
"github.com/prebid/prebid-server/v3/util/jsonutil"
)

type adapter struct {
endpoint string
}

type impExtPrebid struct {
Prebid *openrtb_ext.ExtImpPrebid `json:"prebid,omitempty"`
}

func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
totalImps := len(request.Imp)
errors := make([]error, 0)
adapterRequests := make([]*adapters.RequestData, 0, totalImps)

// Split multi-imp request into multiple ad server requests. SRA is currently not recommended.
for i := 0; i < totalImps; i++ {
adapterReq, err := a.makeRequest(*request, request.Imp[i])
if err != nil {
errors = append(errors, err)
continue
}
adapterRequests = append(adapterRequests, adapterReq)
}

return adapterRequests, errors
}

func (a *adapter) makeRequest(request openrtb2.BidRequest, imp openrtb2.Imp) (*adapters.RequestData, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're missing error path test coverage. After you've made the suggested simplifications to this function, please add additional tests to the supplemental folder to cover each of the unmarshal error paths. You can do this by simply sending a mock bid request with the data under consideration malformed or of a mismatched type.


// For now, this adapter sends one imp per request, but we still
// iterate over all imps in the request to perform the required
// imp.ext transformation.
request.Imp = []openrtb2.Imp{imp}

for i := range request.Imp {

var extBidder adapters.ExtImpBidder
if err := jsonutil.Unmarshal(imp.Ext, &extBidder); err != nil {
return nil, &errortypes.BadInput{Message: fmt.Sprintf("Invalid ext.bidder")}
}
var extImpTargetVideo openrtb_ext.ExtImpTargetVideo
if err := jsonutil.Unmarshal(extBidder.Bidder, &extImpTargetVideo); err != nil {
return nil, &errortypes.BadInput{Message: fmt.Sprintf("Placement ID missing")}
}
var prebid *openrtb_ext.ExtImpPrebid
if extBidder.Prebid == nil {
prebid = &openrtb_ext.ExtImpPrebid{}
}
if prebid.StoredRequest == nil {
prebid.StoredRequest = &openrtb_ext.ExtStoredRequest{}
}
prebid.StoredRequest.ID = fmt.Sprintf("%d", extImpTargetVideo.PlacementId)

ext := impExtPrebid{
Prebid: prebid,
}

extRaw, err := jsonutil.Marshal(ext)
if err != nil {
return nil, &errortypes.BadInput{Message: fmt.Sprintf("error building imp.ext, err: %s", err)}
}

request.Imp[i].Ext = extRaw

}

reqJSON, err := json.Marshal(request)
if err != nil {
return nil, err
}

headers := http.Header{}
headers.Add("Content-Type", "application/json;charset=utf-8")
headers.Add("Accept", "application/json")

//fmt.Println("TARGET VIDEO reqJson: ", string(reqJSON))

return &adapters.RequestData{
Method: "POST",
Uri: a.endpoint,
Body: reqJSON,
Headers: headers,
ImpIDs: openrtb_ext.GetImpIDs(request.Imp),
}, nil
}

func (a *adapter) MakeBids(bidReq *openrtb2.BidRequest, unused *adapters.RequestData, httpRes *adapters.ResponseData) (*adapters.BidderResponse, []error) {
if adapters.IsResponseStatusCodeNoContent(httpRes) {
return nil, nil
}
if statusError := adapters.CheckResponseStatusCodeForErrors(httpRes); statusError != nil {
return nil, []error{statusError}
}

bidResp, errResp := prepareBidResponse(httpRes.Body)
if errResp != nil {
return nil, []error{errResp}
}

br := adapters.NewBidderResponse()
errs := []error{}

for _, sb := range bidResp.SeatBid {
for i := range sb.Bid {
bid := sb.Bid[i]
br.Bids = append(br.Bids, &adapters.TypedBid{Bid: &bid, BidType: openrtb_ext.BidTypeVideo})
br.Currency = bidResp.Cur
}
}
return br, errs
}

func prepareBidResponse(body []byte) (openrtb2.BidResponse, error) {
var response openrtb2.BidResponse
if err := jsonutil.Unmarshal(body, &response); err != nil {
return response, err
}
return response, nil
}

func Builder(bidderName openrtb_ext.BidderName, cfg config.Adapter, server config.Server) (adapters.Bidder, error) {
bidder := &adapter{
endpoint: cfg.Endpoint,
}
return bidder, nil
}
20 changes: 20 additions & 0 deletions adapters/targetVideo/targetvideo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package targetVideo

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.BidderTargetVideo, config.Adapter{
Endpoint: "http://localhost/pbs"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})

if buildErr != nil {
t.Fatalf("Builder returned unexpected error %v", buildErr)
}

adapterstest.RunJSONBidderTest(t, "targetvideotest", bidder)
}
116 changes: 116 additions & 0 deletions adapters/targetVideo/targetvideotest/exemplary/app-video.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
{
"mockBidRequest": {
"id": "test-request-id-video",
"app": {
"id": "appID",
"publisher": {
"id": "uniq_pub_id"
}
},
"cur": ["EUR"],
"imp": [
{
"id": "test-imp-id-video",
"video": {
"mimes": ["video/mp4"],
"w": 640,
"h": 360
},
"ext": {
"bidder": {
"placementId": "77777"
}
}
}
],
"device": {
"ua": "test-user-agent"
}
},
"httpCalls": [
{
"expectedRequest": {
"headers": {
"Accept": ["application/json"],
"Content-Type": ["application/json;charset=utf-8"]
},
"uri": "http://localhost/pbs",
"body": {
"id": "test-request-id-video",
"app": {
"id": "appID",
"publisher": {
"id": "uniq_pub_id"
}
},
"imp": [
{
"id": "test-imp-id-video",
"video": {
"mimes": ["video/mp4"],
"w": 640,
"h": 360
},
"ext": {
"prebid": {
"storedrequest": {
"id": "77777"
}
}
}
}
],
"device": {
"ua": "test-user-agent"
},
"cur": ["EUR"]
},
"impIDs":["test-imp-id-video"]
},
"mockResponse": {
"status": 200,
"body": {
"id": "test-request-id-video",
"seatbid": [
{
"seat": "targetVideo",
"bid": [
{
"id": "randomID",
"impid": "test-imp-id-video",
"price": 5.5,
"adid": "12345678",
"adm": "test-imp-id-video",
"cid": "789",
"crid": "12345678",
"h": 360,
"w": 640
}
]
}
],
"cur": "EUR"
}
}
}
],
"expectedBidResponses": [
{
"currency": "EUR",
"bids" : [{
"bid": {
"id": "randomID",
"adid": "12345678",
"impid": "test-imp-id-video",
"price": 5.5,
"adm": "test-imp-id-video",
"crid": "12345678",
"cid": "789",
"h": 360,
"w": 640
},
"type": "video"
}]
}
]
}
Loading
Loading