-
Notifications
You must be signed in to change notification settings - Fork 749
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f03dfa5
commit 8686f03
Showing
16 changed files
with
559 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package ucfunnel | ||
|
||
import ( | ||
"encoding/json" | ||
"github.com/prebid/prebid-server/openrtb_ext" | ||
"testing" | ||
) | ||
|
||
// This file actually intends to test static/bidder-params/ucfunnel.json | ||
// | ||
// These also validate the format of the external API: request.imp[i].ext.ucfunnel | ||
|
||
// TestValidParams makes sure that the ucfunnel schema accepts all imp.ext fields which we intend to support. | ||
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.BidderUcfunnel, json.RawMessage(validParam)); err != nil { | ||
t.Errorf("Schema rejected ucfunnel params: %s", validParam) | ||
} | ||
} | ||
} | ||
|
||
// TestInvalidParams makes sure that the ucfunnel schema rejects all the imp.ext fields we don't support. | ||
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.BidderUcfunnel, json.RawMessage(invalidParam)); err != nil { | ||
t.Errorf("Schema allowed unexpected params: %s", invalidParam) | ||
} | ||
} | ||
} | ||
|
||
var validParams = []string{ | ||
`{"adunitid": "ad-83444226E44368D1E32E49EEBE6D29","partnerid": "par-2EDDB423AA24474188B843EE4842932"}`, | ||
} | ||
|
||
var invalidParams = []string{ | ||
`{"adunitid": "","partnerid": ""}`, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
package ucfunnel | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"github.com/mxmCherry/openrtb" | ||
"github.com/prebid/prebid-server/adapters" | ||
"github.com/prebid/prebid-server/errortypes" | ||
"github.com/prebid/prebid-server/openrtb_ext" | ||
"net/http" | ||
"net/url" | ||
) | ||
|
||
type UcfunnelAdapter struct { | ||
URI string | ||
} | ||
|
||
func NewUcfunnelBidder(endpoint string) *UcfunnelAdapter { | ||
return &UcfunnelAdapter{ | ||
URI: endpoint} | ||
} | ||
|
||
func (a *UcfunnelAdapter) Name() string { | ||
return "ucfunnel" | ||
} | ||
|
||
func (a *UcfunnelAdapter) SkipNoCookies() bool { | ||
return false | ||
} | ||
|
||
func (a *UcfunnelAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { | ||
if response.StatusCode == http.StatusNoContent { | ||
return nil, nil | ||
} | ||
|
||
if response.StatusCode == http.StatusBadRequest { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), | ||
}} | ||
} | ||
|
||
if response.StatusCode != http.StatusOK { | ||
return nil, []error{&errortypes.BadServerResponse{ | ||
Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), | ||
}} | ||
} | ||
|
||
var errs []error | ||
var bidResp openrtb.BidResponse | ||
if err := json.Unmarshal(response.Body, &bidResp); err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
var bidReq openrtb.BidRequest | ||
if err := json.Unmarshal(externalRequest.Body, &bidReq); err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(bidResp.SeatBid[0].Bid)) | ||
for _, sb := range bidResp.SeatBid { | ||
for i := range sb.Bid { | ||
bidType := getBidType(bidReq, sb.Bid[i].ImpID) | ||
if (bidType == openrtb_ext.BidTypeBanner) || (bidType == openrtb_ext.BidTypeVideo) { | ||
b := &adapters.TypedBid{ | ||
Bid: &sb.Bid[i], | ||
BidType: bidType, | ||
} | ||
bidResponse.Bids = append(bidResponse.Bids, b) | ||
} | ||
} | ||
} | ||
return bidResponse, errs | ||
} | ||
|
||
func (a *UcfunnelAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { | ||
errs := make([]error, 0, len(request.Imp)) | ||
|
||
// If all the requests were malformed, don't bother making a server call with no impressions. | ||
if len(request.Imp) == 0 { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: fmt.Sprintf("No impression in the bid request\n"), | ||
}} | ||
} | ||
|
||
partnerId, partnerErr := getPartnerId(request) | ||
if partnerErr != nil { | ||
return nil, partnerErr | ||
} | ||
|
||
reqJSON, err := json.Marshal(request) | ||
if err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
headers := http.Header{} | ||
headers.Add("Content-Type", "application/json") | ||
|
||
uri := a.URI + "/" + url.PathEscape(partnerId) + "/request" | ||
return []*adapters.RequestData{{ | ||
Method: "POST", | ||
Uri: uri, | ||
Body: reqJSON, | ||
Headers: headers, | ||
}}, errs | ||
} | ||
|
||
func getPartnerId(request *openrtb.BidRequest) (string, []error) { | ||
var ext ExtBidderUcfunnel | ||
var errs = []error{} | ||
err := json.Unmarshal(request.Imp[0].Ext, &ext) | ||
if err != nil { | ||
errs = append(errs, err) | ||
return "", errs | ||
} | ||
errs = checkBidderParameter(ext) | ||
if errs != nil { | ||
return "", errs | ||
} | ||
return ext.Bidder.PartnerId, nil | ||
} | ||
|
||
func checkBidderParameter(ext ExtBidderUcfunnel) []error { | ||
var errs = []error{} | ||
if len(ext.Bidder.PartnerId) == 0 || len(ext.Bidder.AdUnitId) == 0 { | ||
errs = append(errs, fmt.Errorf("No PartnerId or AdUnitId in the bid request\n")) | ||
return errs | ||
} | ||
return nil | ||
} | ||
|
||
func getBidType(bidReq openrtb.BidRequest, impid string) openrtb_ext.BidType { | ||
for i := range bidReq.Imp { | ||
if bidReq.Imp[i].ID == impid { | ||
if bidReq.Imp[i].Banner != nil { | ||
return openrtb_ext.BidTypeBanner | ||
} else if bidReq.Imp[i].Video != nil { | ||
return openrtb_ext.BidTypeVideo | ||
} else if bidReq.Imp[i].Audio != nil { | ||
return openrtb_ext.BidTypeAudio | ||
} else if bidReq.Imp[i].Native != nil { | ||
return openrtb_ext.BidTypeNative | ||
} | ||
} | ||
} | ||
return openrtb_ext.BidTypeNative | ||
} | ||
|
||
type ExtBidderUcfunnel struct { | ||
Bidder openrtb_ext.ExtImpUcfunnel `json:"bidder"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
package ucfunnel | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/mxmCherry/openrtb" | ||
"github.com/prebid/prebid-server/adapters" | ||
"github.com/prebid/prebid-server/adapters/adapterstest" | ||
) | ||
|
||
func TestUcfunnelAdapterNames(t *testing.T) { | ||
adapter := NewUcfunnelBidder("http://localhost/bid") | ||
adapterstest.VerifyStringValue(adapter.Name(), "ucfunnel", t) | ||
} | ||
|
||
func TestSkipNoCookies(t *testing.T) { | ||
adapter := NewUcfunnelBidder("http://localhost/bid") | ||
status := adapter.SkipNoCookies() | ||
if status != false { | ||
t.Errorf("actual = %t expected != %t", status, false) | ||
} | ||
} | ||
|
||
func TestMakeRequests(t *testing.T) { | ||
|
||
imp := openrtb.Imp{ | ||
ID: "1234", | ||
Banner: &openrtb.Banner{}, | ||
} | ||
imp2 := openrtb.Imp{ | ||
ID: "1235", | ||
Video: &openrtb.Video{}, | ||
} | ||
|
||
imp3 := openrtb.Imp{ | ||
ID: "1236", | ||
Audio: &openrtb.Audio{}, | ||
} | ||
|
||
imp4 := openrtb.Imp{ | ||
ID: "1237", | ||
Native: &openrtb.Native{}, | ||
} | ||
imp5 := openrtb.Imp{ | ||
ID: "1237", | ||
Native: &openrtb.Native{}, | ||
} | ||
|
||
internalRequest01 := openrtb.BidRequest{Imp: []openrtb.Imp{}} | ||
internalRequest02 := openrtb.BidRequest{Imp: []openrtb.Imp{imp, imp2, imp3, imp4, imp5}} | ||
internalRequest03 := openrtb.BidRequest{Imp: []openrtb.Imp{imp, imp2, imp3, imp4, imp5}} | ||
|
||
internalRequest03.Imp[0].Ext = []byte(`{"bidder": {"adunitid": "ad-488663D474E44841E8A293379892348","partnerid": "par-7E6D2DB9A8922AB07B44A444D2BA67"}}`) | ||
internalRequest03.Imp[1].Ext = []byte(`{"bidder": {"adunitid": "ad-488663D474E44841E8A293379892348","partnerid": "par-7E6D2DB9A8922AB07B44A444D2BA67"}}`) | ||
internalRequest03.Imp[2].Ext = []byte(`{"bidder": {"adunitid": "ad-488663D474E44841E8A293379892348","partnerid": "par-7E6D2DB9A8922AB07B44A444D2BA67"}}`) | ||
internalRequest03.Imp[3].Ext = []byte(`{"bidder": {"adunitid": "ad-488663D474E44841E8A293379892348","partnerid": "par-7E6D2DB9A8922AB07B44A444D2BA67"}}`) | ||
internalRequest03.Imp[4].Ext = []byte(`{"bidder": {"adunitid": "aa","partnerid": ""}}`) | ||
|
||
adapter := NewUcfunnelBidder("http://localhost/bid") | ||
|
||
var testCases = []struct { | ||
in []openrtb.BidRequest | ||
out1 [](int) | ||
out2 [](bool) | ||
}{ | ||
{ | ||
in: []openrtb.BidRequest{internalRequest01, internalRequest02, internalRequest03}, | ||
out1: [](int){1, 1, 0}, | ||
out2: [](bool){false, false, true}, | ||
}, | ||
} | ||
|
||
for idx := range testCases { | ||
for i := range testCases[idx].in { | ||
RequestData, err := adapter.MakeRequests(&testCases[idx].in[i], nil) | ||
if ((RequestData == nil) == testCases[idx].out2[i]) && (len(err) == testCases[idx].out1[i]) { | ||
t.Errorf("actual = %v expected = %v", len(err), testCases[idx].out1[i]) | ||
} | ||
} | ||
} | ||
} | ||
|
||
func TestMakeBids(t *testing.T) { | ||
imp := openrtb.Imp{ | ||
ID: "1234", | ||
Banner: &openrtb.Banner{}, | ||
} | ||
imp2 := openrtb.Imp{ | ||
ID: "1235", | ||
Video: &openrtb.Video{}, | ||
} | ||
|
||
imp3 := openrtb.Imp{ | ||
ID: "1236", | ||
Audio: &openrtb.Audio{}, | ||
} | ||
|
||
imp4 := openrtb.Imp{ | ||
ID: "1237", | ||
Native: &openrtb.Native{}, | ||
} | ||
imp5 := openrtb.Imp{ | ||
ID: "1237", | ||
Native: &openrtb.Native{}, | ||
} | ||
|
||
internalRequest03 := openrtb.BidRequest{Imp: []openrtb.Imp{imp, imp2, imp3, imp4, imp5}} | ||
internalRequest04 := openrtb.BidRequest{Imp: []openrtb.Imp{imp}} | ||
|
||
internalRequest03.Imp[0].Ext = []byte(`{"bidder": {"adunitid": "ad-488663D474E44841E8A293379892348","partnerid": "par-7E6D2DB9A8922AB07B44A444D2BA67"}}`) | ||
internalRequest03.Imp[1].Ext = []byte(`{"bidder": {"adunitid": "ad-488663D474E44841E8A293379892348","partnerid": "par-7E6D2DB9A8922AB07B44A444D2BA67"}}`) | ||
internalRequest03.Imp[2].Ext = []byte(`{"bidder": {"adunitid": "ad-488663D474E44841E8A293379892348","partnerid": "par-7E6D2DB9A8922AB07B44A444D2BA67"}}`) | ||
internalRequest03.Imp[3].Ext = []byte(`{"bidder": {"adunitid": "ad-488663D474E44841E8A293379892348","partnerid": "par-7E6D2DB9A8922AB07B44A444D2BA67"}}`) | ||
internalRequest03.Imp[4].Ext = []byte(`{"bidder": {"adunitid": "aa","partnerid": ""}}`) | ||
internalRequest04.Imp[0].Ext = []byte(`{"bidder": {"adunitid": "0"}}`) | ||
|
||
mockResponse200 := adapters.ResponseData{StatusCode: 200, Body: json.RawMessage(`{"seatbid": [{"bid": [{"impid": "1234"}]},{"bid": [{"impid": "1235"}]},{"bid": [{"impid": "1236"}]},{"bid": [{"impid": "1237"}]}]}`)} | ||
mockResponse203 := adapters.ResponseData{StatusCode: 203, Body: json.RawMessage(`{"seatbid":[{"bid":[{"impid":"1234"}]},{"bid":[{"impid":"1235"}]}]}`)} | ||
mockResponse204 := adapters.ResponseData{StatusCode: 204, Body: json.RawMessage(`{"seatbid":[{"bid":[{"impid":"1234"}]},{"bid":[{"impid":"1235"}]}]}`)} | ||
mockResponse400 := adapters.ResponseData{StatusCode: 400, Body: json.RawMessage(`{"seatbid":[{"bid":[{"impid":"1234"}]},{"bid":[{"impid":"1235"}]}]}`)} | ||
mockResponseError := adapters.ResponseData{StatusCode: 200, Body: json.RawMessage(`{"seatbid":[{"bid":[{"im236"}],{"bid":[{"impid":"1237}]}`)} | ||
|
||
RequestData01 := adapters.RequestData{Method: "POST", Body: []byte(`{"imp":[{"id":"1234","banner":{}},{"id":"1235","video":{}},{"id":"1236","audio":{}},{"id":"1237","native":{}}]}`)} | ||
RequestData02 := adapters.RequestData{Method: "POST", Body: []byte(`{"imp":[{"id":"1234","banne"1235","video":{}},{"id":"1236","audio":{}},{"id":"1237","native":{}}]}`)} | ||
|
||
adapter := NewUcfunnelBidder("http://localhost/bid") | ||
|
||
var testCases = []struct { | ||
in1 []openrtb.BidRequest | ||
in2 []adapters.RequestData | ||
in3 []adapters.ResponseData | ||
out1 [](bool) | ||
out2 [](bool) | ||
}{ | ||
{ | ||
in1: []openrtb.BidRequest{internalRequest03, internalRequest03, internalRequest03, internalRequest03, internalRequest03, internalRequest04}, | ||
in2: []adapters.RequestData{RequestData01, RequestData01, RequestData01, RequestData01, RequestData01, RequestData02}, | ||
in3: []adapters.ResponseData{mockResponse200, mockResponse203, mockResponse204, mockResponse400, mockResponseError, mockResponse200}, | ||
out1: [](bool){true, false, false, false, false, false}, | ||
out2: [](bool){false, true, false, true, true, true}, | ||
}, | ||
} | ||
|
||
for idx := range testCases { | ||
for i := range testCases[idx].in1 { | ||
BidderResponse, err := adapter.MakeBids(&testCases[idx].in1[i], &testCases[idx].in2[i], &testCases[idx].in3[i]) | ||
|
||
if (BidderResponse == nil) == testCases[idx].out1[i] { | ||
fmt.Println(i) | ||
fmt.Println("BidderResponse") | ||
t.Errorf("actual = %t expected == %v", (BidderResponse == nil), testCases[idx].out1[i]) | ||
} | ||
|
||
if (err == nil) == testCases[idx].out2[i] { | ||
fmt.Println(i) | ||
fmt.Println("error") | ||
t.Errorf("actual = %t expected == %v", err, testCases[idx].out2[i]) | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.