diff --git a/.gitignore b/.gitignore
index 51200f7c41d..b6f85c4f5f7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,4 +59,4 @@ analytics/filesystem/testFiles/
*.swp
*.swo
pbsimage
-manual_build
+manual_build
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 73faa5fa2fa..1019e9e973b 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ all: deps test build-modules build
# deps will clean out the vendor directory and use go mod for a fresh install
deps:
GOPROXY="https://proxy.golang.org" go mod vendor -v && go mod tidy -v
-
+
# test will ensure that all of our dependencies are available and run validate.sh
test: deps
# If there is no indentation, Make will treat it as a directive for itself; otherwise, it's regarded as a shell script.
@@ -37,10 +37,10 @@ format:
# formatcheck runs format for diagnostics, without modifying the code
formatcheck:
./scripts/format.sh -f false
-
+
mockgen: mockgeninstall mockgendb mockgencache mockgenmetrics mockgenlogger mockgenpublisherfeature
-# export GOPATH=~/go ; GOBIN=~/go/bin; export PATH=$PATH:$GOBIN
+# export GOPATH=~/go ; GOBIN=~/go/bin; export PATH=$PATH:$GOBIN
mockgeninstall:
go install github.com/golang/mock/mockgen@v1.6.0
diff --git a/analytics/pubmatic/logger.go b/analytics/pubmatic/logger.go
index 67fb1562265..c0a1f577c77 100644
--- a/analytics/pubmatic/logger.go
+++ b/analytics/pubmatic/logger.go
@@ -35,6 +35,8 @@ func GetLogAuctionObjectAsURL(ao analytics.AuctionObject, rCtx *models.RequestCt
if ao.RequestWrapper == nil || ao.RequestWrapper.BidRequest == nil || rCtx == nil || rCtx.PubID == 0 || rCtx.LoggerDisabled {
return "", nil
}
+ // Get Updated Floor values using floor rules from updated request
+ getFloorValueFromUpdatedRequest(ao.RequestWrapper, rCtx)
wlog := WloggerRecord{
record: record{
@@ -191,6 +193,19 @@ func GetRequestCtx(hookExecutionOutcome []hookexecution.StageOutcome) *models.Re
return nil
}
+// getFloorValueFromUpdatedRequest gets updated floor values by floor module
+func getFloorValueFromUpdatedRequest(reqWrapper *openrtb_ext.RequestWrapper, rCtx *models.RequestCtx) {
+ for _, imp := range reqWrapper.BidRequest.Imp {
+ if impCtx, ok := rCtx.ImpBidCtx[imp.ID]; ok {
+ if imp.BidFloor > 0 && impCtx.BidFloor != imp.BidFloor {
+ impCtx.BidFloor = imp.BidFloor
+ impCtx.BidFloorCur = imp.BidFloorCur
+ rCtx.ImpBidCtx[imp.ID] = impCtx
+ }
+ }
+ }
+}
+
func convertNonBidToBidWrapper(nonBid *openrtb_ext.NonBid) (bid bidWrapper) {
bid.Bid = &openrtb2.Bid{
Price: nonBid.Ext.Prebid.Bid.Price,
diff --git a/analytics/pubmatic/logger_test.go b/analytics/pubmatic/logger_test.go
index 82328929f36..06aa005f336 100644
--- a/analytics/pubmatic/logger_test.go
+++ b/analytics/pubmatic/logger_test.go
@@ -7,6 +7,7 @@ import (
"testing"
"github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/prebid/openrtb/v20/openrtb3"
"github.com/prebid/prebid-server/v2/analytics"
"github.com/prebid/prebid-server/v2/exchange"
"github.com/prebid/prebid-server/v2/hooks/hookanalytics"
@@ -114,9 +115,9 @@ func TestConvertNonBidToBid(t *testing.T) {
nonBid: openrtb_ext.NonBid{
StatusCode: int(exchange.ResponseRejectedBelowFloor),
ImpId: "imp1",
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
Price: 10,
ADomain: []string{"abc.com"},
DealID: "d1",
@@ -1059,9 +1060,9 @@ func TestGetPartnerRecordsByImpForDefaultBids(t *testing.T) {
{
ImpId: "imp1",
StatusCode: int(exchange.ResponseRejectedBelowFloor),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
ID: "bid-id-2",
},
},
@@ -1141,9 +1142,9 @@ func TestGetPartnerRecordsByImpForDefaultBids(t *testing.T) {
{
ImpId: "imp1",
StatusCode: int(exchange.ResponseRejectedBelowFloor),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
ID: "bid-id-1",
},
},
@@ -1313,9 +1314,9 @@ func TestGetPartnerRecordsByImpForSeatNonBid(t *testing.T) {
{
ImpId: "imp1",
StatusCode: int(exchange.ResponseRejectedBelowDealFloor),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
Price: 10,
},
},
@@ -1343,9 +1344,9 @@ func TestGetPartnerRecordsByImpForSeatNonBid(t *testing.T) {
{
ImpId: "imp1",
StatusCode: int(exchange.ResponseRejectedBelowFloor),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
Price: 10,
ID: "bid-id-1",
W: 10,
@@ -1444,9 +1445,9 @@ func TestGetPartnerRecordsByImpForSeatNonBidForFloors(t *testing.T) {
{
ImpId: "imp1",
StatusCode: int(exchange.ResponseRejectedBelowFloor),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
Price: 10,
ID: "bid-id-1",
Floors: &openrtb_ext.ExtBidPrebidFloors{
@@ -1509,10 +1510,10 @@ func TestGetPartnerRecordsByImpForSeatNonBidForFloors(t *testing.T) {
NonBid: []openrtb_ext.NonBid{
{
ImpId: "imp1",
- StatusCode: int((exchange.ResponseRejectedBelowFloor)),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
+ StatusCode: int(exchange.ResponseRejectedBelowFloor),
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
Price: 10,
ID: "bid-id-1",
Floors: &openrtb_ext.ExtBidPrebidFloors{
@@ -1575,10 +1576,10 @@ func TestGetPartnerRecordsByImpForSeatNonBidForFloors(t *testing.T) {
NonBid: []openrtb_ext.NonBid{
{
ImpId: "imp1",
- StatusCode: int((exchange.ResponseRejectedBelowFloor)),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
+ StatusCode: int(exchange.ResponseRejectedBelowFloor),
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
Price: 10,
ID: "bid-id-1",
Floors: &openrtb_ext.ExtBidPrebidFloors{
@@ -1642,9 +1643,9 @@ func TestGetPartnerRecordsByImpForSeatNonBidForFloors(t *testing.T) {
{
ImpId: "imp1",
StatusCode: int(exchange.ResponseRejectedBelowFloor),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
Price: 10,
ID: "bid-id-1",
},
@@ -1702,9 +1703,9 @@ func TestGetPartnerRecordsByImpForSeatNonBidForFloors(t *testing.T) {
{
ImpId: "imp1",
StatusCode: int(exchange.ResponseRejectedBelowFloor),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
Price: 10,
ID: "bid-id-1",
},
@@ -1765,9 +1766,9 @@ func TestGetPartnerRecordsByImpForSeatNonBidForFloors(t *testing.T) {
{
ImpId: "imp1",
StatusCode: int(exchange.ResponseRejectedBelowFloor),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
Price: 10,
ID: "bid-id-1",
Floors: &openrtb_ext.ExtBidPrebidFloors{
@@ -2186,9 +2187,9 @@ func TestGetPartnerRecordsByImpForBidIDCollisions(t *testing.T) {
{
ImpId: "imp1",
StatusCode: int(nbr.LossBidLostToDealBid),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
+ Ext: openrtb_ext.ExtNonBid{
+ Prebid: openrtb_ext.ExtNonBidPrebid{
+ Bid: openrtb_ext.ExtNonBidPrebidBid{
Price: 10,
ID: "bid-id-1",
BidId: "uuid",
@@ -2485,8 +2486,8 @@ func TestGetPartnerRecordsByImpForBidExtFailure(t *testing.T) {
NonBid: []openrtb_ext.NonBid{
{
ImpId: "imp1",
- StatusCode: int(nbr.LossBidLostToDealBid),
- Ext: openrtb_ext.NonBidExt{},
+ StatusCode: int(exchange.ResponseRejectedBelowDealFloor),
+ Ext: openrtb_ext.ExtNonBid{},
},
},
},
@@ -2511,7 +2512,10 @@ func TestGetPartnerRecordsByImpForBidExtFailure(t *testing.T) {
NetECPM: 0,
GrossECPM: 0,
OriginalCur: models.USD,
- Nbr: nbr.LossBidLostToDealBid.Ptr(),
+ Nbr: func() *openrtb3.NoBidReason {
+ a := exchange.ResponseRejectedBelowDealFloor
+ return &a
+ }(),
},
},
},
@@ -4192,6 +4196,79 @@ func TestGetLogAuctionObjectAsURLForFloorDetailsAndCDS(t *testing.T) {
},
},
},
+ {
+ name: "set floor value from updated impression if tracker details are absent",
+ args: args{
+ ao: analytics.AuctionObject{
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp-1",
+ BidFloor: 10.10,
+ BidFloorCur: "USD",
+ },
+ },
+ },
+ },
+ Response: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp-1",
+ },
+ },
+ },
+ },
+ },
+ },
+ rCtx: &models.RequestCtx{
+ PubID: 5890,
+ NewReqExt: &models.RequestExt{
+ ExtRequest: openrtb_ext.ExtRequest{},
+ },
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp-1": {
+ AdUnitName: "au",
+ SlotName: "sn",
+ BidFloor: 2.0,
+ BidFloorCur: "USD",
+ },
+ },
+ ResponseExt: openrtb_ext.ExtBidResponse{
+ Prebid: &openrtb_ext.ExtResponsePrebid{
+ Floors: &openrtb_ext.PriceFloorRules{
+ FetchStatus: openrtb_ext.FetchError,
+ Data: &openrtb_ext.PriceFloorData{
+ ModelGroups: []openrtb_ext.PriceFloorModelGroup{
+ {
+ ModelVersion: "model-version",
+ },
+ },
+ FloorProvider: "provider1",
+ },
+ PriceFloorLocation: openrtb_ext.FetchLocation,
+ Enforcement: &openrtb_ext.PriceFloorEnforcement{
+ EnforcePBS: ptrutil.ToPtr(true),
+ },
+ },
+ },
+ },
+ },
+ logInfo: false,
+ forRespExt: true,
+ },
+ want: want{
+ logger: ow.cfg.Endpoint + `?json={"pubid":5890,"pid":"0","pdvid":"0","sl":1,"s":[{"sid":"uuid","sn":"sn","au":"au","ps":[{"pn":"pubmatic","bc":"pubmatic","kgpv":"","kgpsv":"","psz":"0x0","af":"","eg":0,"en":0,"l1":0,"l2":0,"t":0,"wb":0,"bidid":"bid-id-1","origbidid":"bid-id-1","di":"-1","dc":"","db":0,"ss":1,"mi":0,"ocpm":0,"ocry":"USD","fv":10.1,"frv":10.1}]}],"dvc":{},"fmv":"model-version","fsrc":2,"ft":1,"ffs":2,"fp":"provider1"}&pubid=5890`,
+ header: http.Header{
+ models.USER_AGENT_HEADER: []string{""},
+ models.IP_HEADER: []string{""},
+ },
+ },
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -4425,3 +4502,133 @@ func TestSlotRecordsInGetLogAuctionObjectAsURL(t *testing.T) {
})
}
}
+
+func Test_getFloorValueFromUpdatedRequest(t *testing.T) {
+ type args struct {
+ reqWrapper *openrtb_ext.RequestWrapper
+ rCtx *models.RequestCtx
+ }
+ tests := []struct {
+ name string
+ args args
+ want *models.RequestCtx
+ }{
+ {
+ name: "No floor present in request and in rctx",
+ args: args{
+ reqWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp_1",
+ TagID: "tagid_1",
+ },
+ },
+ },
+ },
+ rCtx: &models.RequestCtx{
+ PubID: 5890,
+ Endpoint: models.EndpointV25,
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp_1": {
+ AdUnitName: "tagid_1",
+ },
+ },
+ },
+ },
+ want: &models.RequestCtx{
+ PubID: 5890,
+ Endpoint: models.EndpointV25,
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp_1": {
+ AdUnitName: "tagid_1",
+ },
+ },
+ },
+ },
+ {
+ name: "No floor change in request and in rctx",
+ args: args{
+ reqWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp_1",
+ TagID: "tagid_1",
+ BidFloor: 10,
+ BidFloorCur: "USD",
+ },
+ },
+ },
+ },
+ rCtx: &models.RequestCtx{
+ PubID: 5890,
+ Endpoint: models.EndpointV25,
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp_1": {
+ AdUnitName: "tagid_1",
+ BidFloor: 10,
+ BidFloorCur: "USD",
+ },
+ },
+ },
+ },
+ want: &models.RequestCtx{
+ PubID: 5890,
+ Endpoint: models.EndpointV25,
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp_1": {
+ AdUnitName: "tagid_1",
+ BidFloor: 10,
+ BidFloorCur: "USD",
+ },
+ },
+ },
+ },
+ {
+ name: "floor updated in request",
+ args: args{
+ reqWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp_1",
+ TagID: "tagid_1",
+ BidFloor: 20,
+ BidFloorCur: "EUR",
+ },
+ },
+ },
+ },
+ rCtx: &models.RequestCtx{
+ PubID: 5890,
+ Endpoint: models.EndpointV25,
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp_1": {
+ AdUnitName: "tagid_1",
+ BidFloor: 10,
+ BidFloorCur: "USD",
+ },
+ },
+ },
+ },
+ want: &models.RequestCtx{
+ PubID: 5890,
+ Endpoint: models.EndpointV25,
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp_1": {
+ AdUnitName: "tagid_1",
+ BidFloor: 20,
+ BidFloorCur: "EUR",
+ },
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ getFloorValueFromUpdatedRequest(tt.args.reqWrapper, tt.args.rCtx)
+ assert.Equal(t, tt.want, tt.args.rCtx, tt.name)
+ })
+ }
+}
diff --git a/analytics/pubstack/pubstack_module_test.go b/analytics/pubstack/pubstack_module_test.go
index 911de4c6959..55d2ab19248 100644
--- a/analytics/pubstack/pubstack_module_test.go
+++ b/analytics/pubstack/pubstack_module_test.go
@@ -99,7 +99,7 @@ func TestNewModuleSuccess(t *testing.T) {
{
ImpId: "123",
StatusCode: 34,
- Ext: openrtb_ext.NonBidExt{Prebid: openrtb_ext.ExtResponseNonBidPrebid{Bid: openrtb_ext.NonBidObject{}}},
+ Ext: openrtb_ext.ExtNonBid{Prebid: openrtb_ext.ExtNonBidPrebid{Bid: openrtb_ext.ExtNonBidPrebidBid{}}},
},
},
},
diff --git a/endpoints/openrtb2/amp_auction.go b/endpoints/openrtb2/amp_auction.go
index bf8661c0a8c..17cb6beb2e6 100644
--- a/endpoints/openrtb2/amp_auction.go
+++ b/endpoints/openrtb2/amp_auction.go
@@ -117,6 +117,7 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
// We can respect timeouts more accurately if we note the *real* start time, and use it
// to compute the auction timeout.
start := time.Now()
+ seatNonBid := &openrtb_ext.NonBidCollection{}
hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAmp, deps.metricsEngine)
@@ -137,6 +138,12 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
activityControl := privacy.ActivityControl{}
defer func() {
+ // if AmpObject.AuctionResponse is nil then collect nonbids from all stage outcomes and set it in the AmpObject.SeatNonBid
+ // Nil AmpObject.AuctionResponse indicates the occurrence of a fatal error.
+ if ao.AuctionResponse == nil {
+ seatNonBid.Append(getNonBidsFromStageOutcomes(hookExecutor.GetOutcomes()))
+ ao.SeatNonBid = seatNonBid.Get()
+ }
deps.metricsEngine.RecordRequest(labels)
deps.metricsEngine.RecordRequestTime(labels, time.Since(start))
deps.analytics.LogAmpObject(&ao, activityControl)
@@ -163,7 +170,7 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
// Process reject after parsing amp request, so we can use reqWrapper.
// There is no body for AMP requests, so we pass a nil body and ignore the return value.
if rejectErr != nil {
- labels, ao = rejectAmpRequest(*rejectErr, w, hookExecutor, reqWrapper, nil, labels, ao, nil)
+ labels, ao = rejectAmpRequest(*rejectErr, w, hookExecutor, reqWrapper, nil, labels, ao, nil, *seatNonBid)
return
}
@@ -279,8 +286,8 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
var response *openrtb2.BidResponse
if auctionResponse != nil {
response = auctionResponse.BidResponse
+ seatNonBid.Append(auctionResponse.SeatNonBid)
}
- ao.SeatNonBid = auctionResponse.GetSeatNonBid()
ao.AuctionResponse = response
rejectErr, isRejectErr := hookexecution.CastRejectErr(err)
if err != nil && !isRejectErr {
@@ -300,15 +307,21 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
glog.Errorf("/openrtb2/amp Critical error: %v", err)
ao.Status = http.StatusInternalServerError
ao.Errors = append(ao.Errors, err)
+ if ao.AuctionResponse != nil {
+ // this check ensures that we collect nonBids from stageOutcomes only once.
+ // there could be a case where ao.AuctionResponse nil and reqWrapper.RebuildRequest returns error
+ seatNonBid.Append(getNonBidsFromStageOutcomes(hookExecutor.GetOutcomes()))
+ ao.SeatNonBid = seatNonBid.Get()
+ }
return
}
if isRejectErr {
- labels, ao = rejectAmpRequest(*rejectErr, w, hookExecutor, reqWrapper, account, labels, ao, errL)
+ labels, ao = rejectAmpRequest(*rejectErr, w, hookExecutor, reqWrapper, account, labels, ao, errL, *seatNonBid)
return
}
- labels, ao = sendAmpResponse(w, hookExecutor, auctionResponse, reqWrapper, account, labels, ao, errL)
+ labels, ao = sendAmpResponse(w, hookExecutor, auctionResponse, reqWrapper, account, labels, ao, errL, *seatNonBid)
}
func rejectAmpRequest(
@@ -320,12 +333,13 @@ func rejectAmpRequest(
labels metrics.Labels,
ao analytics.AmpObject,
errs []error,
+ seatNonBid openrtb_ext.NonBidCollection,
) (metrics.Labels, analytics.AmpObject) {
response := &openrtb2.BidResponse{NBR: openrtb3.NoBidReason(rejectErr.NBR).Ptr()}
ao.AuctionResponse = response
ao.Errors = append(ao.Errors, rejectErr)
- return sendAmpResponse(w, hookExecutor, &exchange.AuctionResponse{BidResponse: response}, reqWrapper, account, labels, ao, errs)
+ return sendAmpResponse(w, hookExecutor, &exchange.AuctionResponse{BidResponse: response}, reqWrapper, account, labels, ao, errs, seatNonBid)
}
func sendAmpResponse(
@@ -337,6 +351,7 @@ func sendAmpResponse(
labels metrics.Labels,
ao analytics.AmpObject,
errs []error,
+ seatNonBid openrtb_ext.NonBidCollection,
) (metrics.Labels, analytics.AmpObject) {
var response *openrtb2.BidResponse
if auctionResponse != nil {
@@ -364,6 +379,8 @@ func sendAmpResponse(
glog.Errorf("/openrtb2/amp Critical error unpacking targets: %v", err)
ao.Errors = append(ao.Errors, fmt.Errorf("Critical error while unpacking AMP targets: %v", err))
ao.Status = http.StatusInternalServerError
+ seatNonBid.Append(getNonBidsFromStageOutcomes(hookExecutor.GetOutcomes()))
+ ao.SeatNonBid = seatNonBid.Get()
return labels, ao
}
for key, value := range bidExt.Prebid.Targeting {
@@ -392,7 +409,7 @@ func sendAmpResponse(
}
// Now JSONify the targets for the AMP response.
ampResponse := AmpResponse{Targeting: targets}
- ao, ampResponse.ORTB2.Ext = getExtBidResponse(hookExecutor, auctionResponse, reqWrapper, account, ao, errs)
+ ao, ampResponse.ORTB2.Ext = getExtBidResponse(hookExecutor, auctionResponse, reqWrapper, account, ao, errs, seatNonBid)
ao.AmpTargetingValues = targets
@@ -418,6 +435,7 @@ func getExtBidResponse(
account *config.Account,
ao analytics.AmpObject,
errs []error,
+ seatNonBid openrtb_ext.NonBidCollection,
) (analytics.AmpObject, openrtb_ext.ExtBidResponse) {
var response *openrtb2.BidResponse
if auctionResponse != nil {
@@ -447,6 +465,7 @@ func getExtBidResponse(
Warnings: warnings,
}
+ stageOutcomes := hookExecutor.GetOutcomes()
// add debug information if requested
if reqWrapper != nil {
if reqWrapper.Test == 1 && eRErr == nil {
@@ -458,7 +477,6 @@ func getExtBidResponse(
}
}
- stageOutcomes := hookExecutor.GetOutcomes()
ao.HookExecutionOutcome = stageOutcomes
modules, warns, err := hookexecution.GetModulesJSON(stageOutcomes, reqWrapper.BidRequest, account)
if err != nil {
@@ -474,8 +492,12 @@ func getExtBidResponse(
}
}
- setSeatNonBid(&extBidResponse, reqWrapper, auctionResponse)
-
+ // collect seatNonBid from all stage-outcomes and set in the response.ext.prebid
+ seatNonBid.Append(getNonBidsFromStageOutcomes(stageOutcomes))
+ ao.SeatNonBid = seatNonBid.Get()
+ if returnAllBidStatus(reqWrapper) {
+ setSeatNonBid(&extBidResponse, ao.SeatNonBid)
+ }
return ao, extBidResponse
}
@@ -851,23 +873,3 @@ func setTrace(req *openrtb2.BidRequest, value string) error {
return nil
}
-
-// setSeatNonBid populates bidresponse.ext.prebid.seatnonbid if bidrequest.ext.prebid.returnallbidstatus is true
-func setSeatNonBid(finalExtBidResponse *openrtb_ext.ExtBidResponse, request *openrtb_ext.RequestWrapper, auctionResponse *exchange.AuctionResponse) bool {
- if finalExtBidResponse == nil || auctionResponse == nil || request == nil {
- return false
- }
- reqExt, err := request.GetRequestExt()
- if err != nil {
- return false
- }
- prebid := reqExt.GetPrebid()
- if prebid == nil || !prebid.ReturnAllBidStatus {
- return false
- }
- if finalExtBidResponse.Prebid == nil {
- finalExtBidResponse.Prebid = &openrtb_ext.ExtResponsePrebid{}
- }
- finalExtBidResponse.Prebid.SeatNonBid = auctionResponse.GetSeatNonBid()
- return true
-}
diff --git a/endpoints/openrtb2/amp_auction_test.go b/endpoints/openrtb2/amp_auction_test.go
index 340f1f0d999..40ae577ffaa 100644
--- a/endpoints/openrtb2/amp_auction_test.go
+++ b/endpoints/openrtb2/amp_auction_test.go
@@ -1413,8 +1413,11 @@ func (s formatOverrideSpec) execute(t *testing.T) {
}
type mockAmpExchange struct {
- lastRequest *openrtb2.BidRequest
- requestExt json.RawMessage
+ lastRequest *openrtb2.BidRequest
+ requestExt json.RawMessage
+ returnError bool
+ setBidRequestToNil bool
+ seatNonBid openrtb_ext.NonBidCollection
}
var expectedErrorsFromHoldAuction map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage = map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage{
@@ -1427,6 +1430,13 @@ var expectedErrorsFromHoldAuction map[openrtb_ext.BidderName][]openrtb_ext.ExtBi
}
func (m *mockAmpExchange) HoldAuction(ctx context.Context, auctionRequest *exchange.AuctionRequest, debugLog *exchange.DebugLog) (*exchange.AuctionResponse, error) {
+ if m.returnError {
+ return nil, hookexecution.RejectError{
+ NBR: 1,
+ Stage: hooks.StageBidderRequest.String(),
+ Hook: hookexecution.HookID{ModuleCode: "foobar", HookImplCode: "foo"},
+ }
+ }
r := auctionRequest.BidRequestWrapper
m.lastRequest = r.BidRequest
@@ -1460,7 +1470,11 @@ func (m *mockAmpExchange) HoldAuction(ctx context.Context, auctionRequest *excha
response.Ext = json.RawMessage(fmt.Sprintf(`{"debug": {"httpcalls": {}, "resolvedrequest": %s}}`, resolvedRequest))
}
- return &exchange.AuctionResponse{BidResponse: response}, nil
+ if m.setBidRequestToNil {
+ auctionRequest.BidRequestWrapper.BidRequest = nil
+ }
+
+ return &exchange.AuctionResponse{BidResponse: response, SeatNonBid: m.seatNonBid}, nil
}
type mockAmpExchangeWarnings struct{}
@@ -1660,16 +1674,21 @@ func (logger mockLogger) LogAmpObject(ao *analytics.AmpObject, _ privacy.Activit
func TestBuildAmpObject(t *testing.T) {
testCases := []struct {
- description string
- inTagId string
- exchange *mockAmpExchange
- inStoredRequest json.RawMessage
- expectedAmpObject *analytics.AmpObject
+ description string
+ inTagId string
+ exchange *mockAmpExchange
+ inStoredRequest json.RawMessage
+ planBuilder hooks.ExecutionPlanBuilder
+ returnErrorFromHoldAuction bool
+ setRequestToNil bool
+ seatNonBidFromHoldAuction openrtb_ext.NonBidCollection
+ expectedAmpObject *analytics.AmpObject
}{
{
description: "Stored Amp request with nil body. Only the error gets logged",
inTagId: "test",
inStoredRequest: nil,
+ planBuilder: hooks.EmptyPlanBuilder{},
expectedAmpObject: &analytics.AmpObject{
Status: http.StatusOK,
Errors: []error{fmt.Errorf("unexpected end of JSON input")},
@@ -1679,24 +1698,163 @@ func TestBuildAmpObject(t *testing.T) {
description: "Stored Amp request with no imps that should return error. Only the error gets logged",
inTagId: "test",
inStoredRequest: json.RawMessage(`{"id":"some-request-id","site":{"page":"prebid.org"},"imp":[],"tmax":500}`),
+ planBuilder: hooks.EmptyPlanBuilder{},
expectedAmpObject: &analytics.AmpObject{
Status: http.StatusOK,
Errors: []error{fmt.Errorf("data for tag_id='test' does not define the required imp array")},
},
},
{
- description: "Wrong tag_id, error gets logged",
+ description: "Wrong tag_id, error and seatnonbid gets logged",
inTagId: "unknown",
inStoredRequest: json.RawMessage(`{"id":"some-request-id","site":{"page":"prebid.org"},"imp":[{"id":"some-impression-id","banner":{"format":[{"w":300,"h":250}]},"ext":{"prebid":{"bidder":{"appnexus":{"placementId":12883451}}}}}],"tmax":500}`),
+ planBuilder: mockPlanBuilder{entrypointPlan: makePlan[hookstage.Entrypoint](mockSeatNonBidHook{})},
expectedAmpObject: &analytics.AmpObject{
Status: http.StatusOK,
Errors: []error{fmt.Errorf("unexpected end of JSON input")},
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "pubmatic",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp",
+ StatusCode: 100,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ description: "AmpObject should contain seatNonBid when holdAuction returns error",
+ inTagId: "test",
+ inStoredRequest: json.RawMessage(`{"id":"some-request-id","site":{"page":"prebid.org"},"imp":[{"id":"some-impression-id","banner":{"format":[{"w":300,"h":250}]},"ext":{"prebid":{"bidder":{"appnexus":{"placementId":12883451}}}}}],"tmax":500}`),
+ planBuilder: mockPlanBuilder{entrypointPlan: makePlan[hookstage.Entrypoint](mockSeatNonBidHook{})},
+ returnErrorFromHoldAuction: true,
+ expectedAmpObject: &analytics.AmpObject{
+ Status: http.StatusInternalServerError,
+ Errors: []error{
+ fmt.Errorf("[Module foobar (hook: foo) rejected request with code 1 at bidder_request stage]"),
+ },
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ ID: "some-request-id",
+ Device: &openrtb2.Device{
+ IP: "192.0.2.1",
+ },
+ Site: &openrtb2.Site{
+ Page: "prebid.org",
+ Ext: json.RawMessage(`{"amp":1}`),
+ },
+ Imp: []openrtb2.Imp{
+ {
+ ID: "some-impression-id",
+ Banner: &openrtb2.Banner{
+ Format: []openrtb2.Format{
+ {
+ W: 300,
+ H: 250,
+ },
+ },
+ },
+ Secure: func(val int8) *int8 { return &val }(1), //(*int8)(1),
+ Ext: json.RawMessage(`{"prebid":{"bidder":{"appnexus":{"placementId":12883451}}}}`),
+ },
+ },
+ AT: 1,
+ TMax: 500,
+ Ext: json.RawMessage(`{"prebid":{"cache":{"bids":{}},"channel":{"name":"amp","version":""},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":20,"increment":0.1}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true}}}`),
+ },
+ },
+ Origin: "",
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "pubmatic",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp",
+ StatusCode: 100,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ description: "AmpObject should contain seatNonBid when RebuildRequest returns error after holdAuction",
+ inTagId: "test",
+ inStoredRequest: json.RawMessage(`{"id":"some-request-id","site":{"page":"prebid.org"},"imp":[{"id":"some-impression-id","banner":{"format":[{"w":300,"h":250}]},"ext":{"prebid":{"bidder":{"appnexus":{"placementId":12883451}}}}}],"tmax":500}`),
+ planBuilder: mockPlanBuilder{entrypointPlan: makePlan[hookstage.Entrypoint](mockSeatNonBidHook{})},
+ setRequestToNil: true,
+ seatNonBidFromHoldAuction: getNonBids(map[string][]openrtb_ext.NonBidParams{"pubmatic": {{Bid: &openrtb2.Bid{ImpID: "imp1"}, NonBidReason: 100}}}),
+ expectedAmpObject: &analytics.AmpObject{
+ Status: http.StatusInternalServerError,
+ Errors: []error{
+ fmt.Errorf("[Module foobar (hook: foo) rejected request with code 1 at bidder_request stage]"),
+ },
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ ID: "some-request-id",
+ Device: &openrtb2.Device{
+ IP: "192.0.2.1",
+ },
+ Site: &openrtb2.Site{
+ Page: "prebid.org",
+ Ext: json.RawMessage(`{"amp":1}`),
+ },
+ Imp: []openrtb2.Imp{
+ {
+ ID: "some-impression-id",
+ Banner: &openrtb2.Banner{
+ Format: []openrtb2.Format{
+ {
+ W: 300,
+ H: 250,
+ },
+ },
+ },
+ Secure: func(val int8) *int8 { return &val }(1),
+ Ext: json.RawMessage(`{"prebid":{"bidder":{"appnexus":{"placementId":12883451}}}}`),
+ },
+ },
+ AT: 1,
+ TMax: 500,
+ Ext: json.RawMessage(`{"prebid":{"cache":{"bids":{}},"channel":{"name":"amp","version":""},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":20,"increment":0.1}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true}}}`),
+ },
+ },
+ AuctionResponse: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{{
+ Bid: []openrtb2.Bid{{
+ AdM: "",
+ Ext: json.RawMessage(`{ "prebid": {"targeting": { "hb_pb": "1.20", "hb_appnexus_pb": "1.20", "hb_cache_id": "some_id"}}}`),
+ }},
+ Seat: "",
+ }},
+ Ext: json.RawMessage(`{ "errors": {"openx":[ { "code": 1, "message": "The request exceeded the timeout allocated" } ] } }`),
+ },
+ Origin: "",
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "pubmatic",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: 100,
+ },
+ {
+ ImpId: "imp",
+ StatusCode: 100,
+ },
+ },
+ },
+ },
},
},
{
description: "Valid stored Amp request, correct tag_id, a valid response should be logged",
inTagId: "test",
inStoredRequest: json.RawMessage(`{"id":"some-request-id","site":{"page":"prebid.org"},"imp":[{"id":"some-impression-id","banner":{"format":[{"w":300,"h":250}]},"ext":{"prebid":{"bidder":{"appnexus":{"placementId":12883451}}}}}],"tmax":500}`),
+ planBuilder: hooks.EmptyPlanBuilder{},
expectedAmpObject: &analytics.AmpObject{
Status: http.StatusOK,
Errors: nil,
@@ -1753,6 +1911,7 @@ func TestBuildAmpObject(t *testing.T) {
inTagId: "test",
inStoredRequest: json.RawMessage(`{"id":"some-request-id","site":{"page":"prebid.org"},"imp":[{"id":"some-impression-id","banner":{"format":[{"w":300,"h":250}]},"ext":{"prebid":{"bidder":{"appnexus":{"placementId":12883451}}}}}],"tmax":500}`),
exchange: &mockAmpExchange{requestExt: json.RawMessage(`{ "prebid": {"targeting": { "test_key": "test_value", "hb_appnexus_pb": "9999" } }, "errors": {"openx":[ { "code": 1, "message": "The request exceeded the timeout allocated" } ] } }`)},
+ planBuilder: hooks.EmptyPlanBuilder{},
expectedAmpObject: &analytics.AmpObject{
Status: http.StatusOK,
Errors: nil,
@@ -1814,9 +1973,13 @@ func TestBuildAmpObject(t *testing.T) {
// Set up test, declare a new mock logger every time
exchange := test.exchange
if exchange == nil {
- exchange = &mockAmpExchange{}
+ exchange = &mockAmpExchange{
+ returnError: test.returnErrorFromHoldAuction,
+ setBidRequestToNil: test.setRequestToNil,
+ seatNonBid: test.seatNonBidFromHoldAuction,
+ }
}
- actualAmpObject, endpoint := ampObjectTestSetup(t, test.inTagId, test.inStoredRequest, false, exchange)
+ actualAmpObject, endpoint := ampObjectTestSetup(t, test.inTagId, test.inStoredRequest, false, exchange, test.planBuilder)
// Run test
endpoint(recorder, request, nil)
@@ -1835,6 +1998,7 @@ func TestBuildAmpObject(t *testing.T) {
assert.Equalf(t, test.expectedAmpObject.AuctionResponse, actualAmpObject.AuctionResponse, "Amp Object BidResponse doesn't match expected: %s\n", test.description)
assert.Equalf(t, test.expectedAmpObject.AmpTargetingValues, actualAmpObject.AmpTargetingValues, "Amp Object AmpTargetingValues doesn't match expected: %s\n", test.description)
assert.Equalf(t, test.expectedAmpObject.Origin, actualAmpObject.Origin, "Amp Object Origin field doesn't match expected: %s\n", test.description)
+ assert.Equalf(t, test.expectedAmpObject.SeatNonBid, actualAmpObject.SeatNonBid, "Amp Object SeatNonBid field doesn't match expected: %s\n", test.description)
}
}
@@ -1890,13 +2054,13 @@ func TestIdGeneration(t *testing.T) {
for _, test := range testCases {
// Set up and run test
- actualAmpObject, endpoint := ampObjectTestSetup(t, "test", test.givenInStoredRequest, test.givenGenerateRequestID, &mockAmpExchange{})
+ actualAmpObject, endpoint := ampObjectTestSetup(t, "test", test.givenInStoredRequest, test.givenGenerateRequestID, &mockAmpExchange{}, hooks.EmptyPlanBuilder{})
endpoint(recorder, request, nil)
assert.Equalf(t, test.expectedID, actualAmpObject.RequestWrapper.ID, "Bid Request ID is incorrect: %s\n", test.description)
}
}
-func ampObjectTestSetup(t *testing.T, inTagId string, inStoredRequest json.RawMessage, generateRequestID bool, exchange *mockAmpExchange) (*analytics.AmpObject, httprouter.Handle) {
+func ampObjectTestSetup(t *testing.T, inTagId string, inStoredRequest json.RawMessage, generateRequestID bool, exchange *mockAmpExchange, planBuilder hooks.ExecutionPlanBuilder) (*analytics.AmpObject, httprouter.Handle) {
actualAmpObject := analytics.AmpObject{}
logger := newMockLogger(&actualAmpObject, nil)
@@ -1919,7 +2083,7 @@ func ampObjectTestSetup(t *testing.T, inTagId string, inStoredRequest json.RawMe
[]byte{},
openrtb_ext.BuildBidderMap(),
empty_fetcher.EmptyFetcher{},
- hooks.EmptyPlanBuilder{},
+ planBuilder,
nil,
)
return &actualAmpObject, endpoint
@@ -2324,7 +2488,7 @@ func TestSendAmpResponse_LogsErrors(t *testing.T) {
account := &config.Account{DebugAllow: true}
reqWrapper := openrtb_ext.RequestWrapper{BidRequest: test.request}
- _, ao = sendAmpResponse(test.writer, test.hookExecutor, &exchange.AuctionResponse{BidResponse: test.response}, &reqWrapper, account, labels, ao, nil)
+ labels, ao = sendAmpResponse(test.writer, test.hookExecutor, &exchange.AuctionResponse{BidResponse: test.response}, &reqWrapper, account, labels, ao, nil, openrtb_ext.NonBidCollection{})
assert.Equal(t, test.expectedErrors, ao.Errors, "Invalid errors.")
assert.Equal(t, test.expectedStatus, ao.Status, "Invalid HTTP response status.")
@@ -2344,63 +2508,205 @@ func (e errorResponseWriter) Write(bytes []byte) (int, error) {
func (e errorResponseWriter) WriteHeader(statusCode int) {}
-func TestSetSeatNonBid(t *testing.T) {
+func TestGetExtBidResponse(t *testing.T) {
type args struct {
- finalExtBidResponse *openrtb_ext.ExtBidResponse
- request *openrtb_ext.RequestWrapper
- auctionResponse *exchange.AuctionResponse
+ hookExecutor hookexecution.HookStageExecutor
+ auctionResponse *exchange.AuctionResponse
+ reqWrapper *openrtb_ext.RequestWrapper
+ account *config.Account
+ ao analytics.AmpObject
+ errs []error
+ seatNonBid openrtb_ext.NonBidCollection
+ }
+ type want struct {
+ respExt openrtb_ext.ExtBidResponse
+ ao analytics.AmpObject
}
tests := []struct {
name string
args args
- want bool
+ want want
}{
{
- name: "nil-auctionResponse",
- args: args{auctionResponse: nil},
- want: false,
- },
- {
- name: "nil-request",
- args: args{auctionResponse: &exchange.AuctionResponse{}, request: nil},
- want: false,
- },
- {
- name: "invalid-req-ext",
- args: args{auctionResponse: &exchange.AuctionResponse{}, request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Ext: []byte(`invalid json`)}}},
- want: false,
- },
- {
- name: "nil-prebid",
- args: args{auctionResponse: &exchange.AuctionResponse{}, request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Ext: nil}}},
- want: false,
- },
- {
- name: "returnallbidstatus-is-false",
- args: args{auctionResponse: &exchange.AuctionResponse{}, request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid" : {"returnallbidstatus" : false}}`)}}},
- want: false,
+ name: "seatNonBid: returnallbidstatus is true and nonBids is empty",
+ args: args{
+ hookExecutor: mockStageExecutor{
+ outcomes: []hookexecution.StageOutcome{},
+ },
+ auctionResponse: &exchange.AuctionResponse{
+ BidResponse: &openrtb2.BidResponse{
+ Ext: json.RawMessage(`{}`),
+ },
+ },
+ reqWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Ext: json.RawMessage(`{"prebid":{"returnallbidstatus": true}}`),
+ },
+ },
+ },
+ want: want{
+ respExt: openrtb_ext.ExtBidResponse{
+ Warnings: make(map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage),
+ },
+ ao: analytics.AmpObject{
+ SeatNonBid: nil,
+ },
+ },
},
{
- name: "finalExtBidResponse-is-nil",
- args: args{finalExtBidResponse: nil},
- want: false,
+ name: "seatNonBid: returnallbidstatus is true and nonBids is present",
+ args: args{
+ hookExecutor: mockStageExecutor{
+ outcomes: []hookexecution.StageOutcome{
+ {
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ Status: hookexecution.StatusSuccess,
+ SeatNonBid: getNonBids(map[string][]openrtb_ext.NonBidParams{"pubmatic": {{Bid: &openrtb2.Bid{ImpID: "imp"}, NonBidReason: 100}}}),
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ auctionResponse: &exchange.AuctionResponse{
+ BidResponse: &openrtb2.BidResponse{
+ Ext: json.RawMessage(`{}`),
+ },
+ },
+ reqWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Ext: json.RawMessage(`{"prebid":{"returnallbidstatus": true}}`),
+ },
+ },
+ ao: analytics.AmpObject{},
+ seatNonBid: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {{Bid: &openrtb2.Bid{ImpID: "imp1"}, NonBidReason: 100}},
+ }),
+ },
+ want: want{
+ respExt: openrtb_ext.ExtBidResponse{
+ Warnings: make(map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage),
+ Prebid: &openrtb_ext.ExtResponsePrebid{
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: 100,
+ },
+ {
+ ImpId: "imp",
+ StatusCode: 100,
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ },
+ },
+ ao: analytics.AmpObject{
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: 100,
+ },
+ {
+ ImpId: "imp",
+ StatusCode: 100,
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ },
+ },
},
{
- name: "returnallbidstatus-is-true-and-responseExt.Prebid-is-nil",
- args: args{finalExtBidResponse: &openrtb_ext.ExtBidResponse{Prebid: nil}, auctionResponse: &exchange.AuctionResponse{}, request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid" : {"returnallbidstatus" : true}}`)}}},
- want: true,
+ name: "seatNonBid: returnallbidstatus is false and nonBids is present",
+ args: args{
+ hookExecutor: mockStageExecutor{},
+ auctionResponse: &exchange.AuctionResponse{
+ BidResponse: &openrtb2.BidResponse{
+ Ext: json.RawMessage(`{}`),
+ },
+ },
+ reqWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Ext: json.RawMessage(`{"prebid":{"returnallbidstatus": false}}`),
+ },
+ },
+ ao: analytics.AmpObject{},
+ seatNonBid: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {{Bid: &openrtb2.Bid{ImpID: "imp1"}, NonBidReason: 100}},
+ }),
+ },
+ want: want{
+ respExt: openrtb_ext.ExtBidResponse{
+ Warnings: make(map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage),
+ },
+ ao: analytics.AmpObject{
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: 100,
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ },
+ },
},
{
- name: "returnallbidstatus-is-true-and-responseExt.Prebid-is-not-nil",
- args: args{finalExtBidResponse: &openrtb_ext.ExtBidResponse{Prebid: nil}, auctionResponse: &exchange.AuctionResponse{}, request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid" : {"returnallbidstatus" : true}}`)}}},
- want: true,
+ name: "seatNonBid: reqWrapper is nil and nonBids is present then AmpObject should contain seatnonbid",
+ args: args{
+ hookExecutor: mockStageExecutor{
+ outcomes: []hookexecution.StageOutcome{},
+ },
+ auctionResponse: &exchange.AuctionResponse{
+ BidResponse: &openrtb2.BidResponse{
+ Ext: json.RawMessage(`{}`),
+ },
+ },
+ reqWrapper: nil,
+ seatNonBid: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {{Bid: &openrtb2.Bid{ImpID: "imp1"}, NonBidReason: 100}},
+ }),
+ ao: analytics.AmpObject{},
+ },
+ want: want{
+ respExt: openrtb_ext.ExtBidResponse{
+ Warnings: make(map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage),
+ },
+ ao: analytics.AmpObject{
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: 100,
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ },
+ },
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- if got := setSeatNonBid(tt.args.finalExtBidResponse, tt.args.request, tt.args.auctionResponse); got != tt.want {
- t.Errorf("setSeatNonBid() = %v, want %v", got, tt.want)
- }
+ ao, ext := getExtBidResponse(tt.args.hookExecutor, tt.args.auctionResponse, tt.args.reqWrapper, tt.args.account, tt.args.ao, tt.args.errs, tt.args.seatNonBid)
+ assert.Equal(t, tt.want.respExt, ext, "Found invalid bidResponseExt")
+ assert.Equal(t, tt.want.ao.SeatNonBid, ao.SeatNonBid, "Found invalid seatNonBid in ampObject")
})
}
}
diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go
index 4e0b096dd81..4434876fbd0 100644
--- a/endpoints/openrtb2/auction.go
+++ b/endpoints/openrtb2/auction.go
@@ -165,6 +165,7 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
// We can respect timeouts more accurately if we note the *real* start time, and use it
// to compute the auction timeout.
start := time.Now()
+ seatNonBid := &openrtb_ext.NonBidCollection{}
hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAuction, deps.metricsEngine)
@@ -184,6 +185,12 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
activityControl := privacy.ActivityControl{}
defer func() {
+ // if AuctionObject.Response is nil then collect nonbids from all stage outcomes and set it in the AuctionObject.
+ // Nil AuctionObject.Response indicates the occurrence of a fatal error.
+ if ao.Response == nil {
+ seatNonBid.Append(getNonBidsFromStageOutcomes(hookExecutor.GetOutcomes()))
+ ao.SeatNonBid = seatNonBid.Get()
+ }
deps.metricsEngine.RecordRequest(labels)
recordRejectedBids(labels.PubID, ao.SeatNonBid, deps.metricsEngine)
deps.metricsEngine.RecordRequestTime(labels, time.Since(start))
@@ -199,7 +206,7 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
if rejectErr := hookexecution.FindFirstRejectOrNil(errL); rejectErr != nil {
ao.RequestWrapper = req
- labels, ao = rejectAuctionRequest(*rejectErr, w, hookExecutor, req.BidRequest, account, labels, ao)
+ labels, ao = rejectAuctionRequest(*rejectErr, w, hookExecutor, req.BidRequest, account, labels, ao, seatNonBid)
return
}
@@ -272,9 +279,9 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
var response *openrtb2.BidResponse
if auctionResponse != nil {
response = auctionResponse.BidResponse
+ seatNonBid.Append(auctionResponse.SeatNonBid)
}
ao.Response = response
- ao.SeatNonBid = auctionResponse.GetSeatNonBid()
rejectErr, isRejectErr := hookexecution.CastRejectErr(err)
if err != nil && !isRejectErr {
if errortypes.ReadCode(err) == errortypes.BadInputErrorCode {
@@ -289,15 +296,11 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
ao.Errors = append(ao.Errors, err)
return
} else if isRejectErr {
- labels, ao = rejectAuctionRequest(*rejectErr, w, hookExecutor, req.BidRequest, account, labels, ao)
+ labels, ao = rejectAuctionRequest(*rejectErr, w, hookExecutor, req.BidRequest, account, labels, ao, seatNonBid)
return
}
- err = setSeatNonBidRaw(req, auctionResponse)
- if err != nil {
- glog.Errorf("Error setting seat non-bid: %v", err)
- }
- labels, ao = sendAuctionResponse(w, hookExecutor, response, req.BidRequest, account, labels, ao)
+ labels, ao = sendAuctionResponse(w, hookExecutor, response, req.BidRequest, account, labels, ao, seatNonBid)
}
// setSeatNonBidRaw is transitional function for setting SeatNonBid inside bidResponse.Ext
@@ -305,18 +308,20 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
// 1. today exchange.HoldAuction prepares and marshals some piece of response.Ext which is then used by auction.go, amp_auction.go and video_auction.go
// 2. As per discussion with Prebid Team we are planning to move away from - HoldAuction building openrtb2.BidResponse. instead respective auction modules will build this object
// 3. So, we will need this method to do first, unmarshalling of response.Ext
-func setSeatNonBidRaw(request *openrtb_ext.RequestWrapper, auctionResponse *exchange.AuctionResponse) error {
- if auctionResponse == nil || auctionResponse.BidResponse == nil {
+func setSeatNonBidRaw(request *openrtb_ext.RequestWrapper, response *openrtb2.BidResponse, nonBids []openrtb_ext.SeatNonBid) error {
+ if response == nil || !returnAllBidStatus(request) {
return nil
}
+ if response.Ext == nil {
+ response.Ext = json.RawMessage(`{}`)
+ }
// unmarshalling is required here, until we are moving away from bidResponse.Ext, which is populated
// by HoldAuction
- response := auctionResponse.BidResponse
respExt := &openrtb_ext.ExtBidResponse{}
if err := jsonutil.Unmarshal(response.Ext, &respExt); err != nil {
return err
}
- if setSeatNonBid(respExt, request, auctionResponse) {
+ if setSeatNonBid(respExt, nonBids) {
if respExtJson, err := json.Marshal(respExt); err == nil {
response.Ext = respExtJson
return nil
@@ -335,6 +340,7 @@ func rejectAuctionRequest(
account *config.Account,
labels metrics.Labels,
ao analytics.AuctionObject,
+ seatNonBid *openrtb_ext.NonBidCollection,
) (metrics.Labels, analytics.AuctionObject) {
response := &openrtb2.BidResponse{NBR: openrtb3.NoBidReason(rejectErr.NBR).Ptr()}
if request != nil {
@@ -349,7 +355,21 @@ func rejectAuctionRequest(
ao.Response = response
ao.Errors = append(ao.Errors, rejectErr)
- return sendAuctionResponse(w, hookExecutor, response, request, account, labels, ao)
+ return sendAuctionResponse(w, hookExecutor, response, request, account, labels, ao, seatNonBid)
+}
+
+func getNonBidsFromStageOutcomes(stageOutcomes []hookexecution.StageOutcome) openrtb_ext.NonBidCollection {
+ seatNonBid := openrtb_ext.NonBidCollection{}
+ for _, stageOutcome := range stageOutcomes {
+ for _, groups := range stageOutcome.Groups {
+ for _, result := range groups.InvocationResults {
+ if result.Status == hookexecution.StatusSuccess {
+ seatNonBid.Append(result.SeatNonBid)
+ }
+ }
+ }
+ }
+ return seatNonBid
}
func sendAuctionResponse(
@@ -360,13 +380,21 @@ func sendAuctionResponse(
account *config.Account,
labels metrics.Labels,
ao analytics.AuctionObject,
+ seatNonBid *openrtb_ext.NonBidCollection,
) (metrics.Labels, analytics.AuctionObject) {
hookExecutor.ExecuteAuctionResponseStage(response)
+ stageOutcomes := hookExecutor.GetOutcomes()
+ seatNonBid.Append(getNonBidsFromStageOutcomes(stageOutcomes))
+ ao.SeatNonBid = seatNonBid.Get()
+
if response != nil {
- stageOutcomes := hookExecutor.GetOutcomes()
ao.HookExecutionOutcome = stageOutcomes
UpdateResponseExtOW(w, response, ao)
+ err := setSeatNonBidRaw(ao.RequestWrapper, response, ao.SeatNonBid)
+ if err != nil {
+ glog.Errorf("Error setting seatNonBid in responseExt: %v", err)
+ }
ext, warns, err := hookexecution.EnrichExtBidResponse(response.Ext, stageOutcomes, request, account)
if err != nil {
@@ -2581,3 +2609,31 @@ func (deps *endpointDeps) validateStoredBidRespAndImpExtBidders(prebid *openrtb_
func generateStoredBidResponseValidationError(impID string) error {
return fmt.Errorf("request validation failed. Stored bid responses are specified for imp %s. Bidders specified in imp.ext should match with bidders specified in imp.ext.prebid.storedbidresponse", impID)
}
+
+// setSeatNonBid populates bidresponse.ext.prebid.seatnonbid
+func setSeatNonBid(finalExtBidResponse *openrtb_ext.ExtBidResponse, seatNonBid []openrtb_ext.SeatNonBid) bool {
+ if finalExtBidResponse == nil || len(seatNonBid) == 0 {
+ return false
+ }
+ if finalExtBidResponse.Prebid == nil {
+ finalExtBidResponse.Prebid = &openrtb_ext.ExtResponsePrebid{}
+ }
+ finalExtBidResponse.Prebid.SeatNonBid = seatNonBid
+ return true
+}
+
+// returnAllBidStatus function returns the value of bidrequest.ext.prebid.returnallbidstatus flag
+func returnAllBidStatus(request *openrtb_ext.RequestWrapper) bool {
+ if request == nil {
+ return false
+ }
+ reqExt, err := request.GetRequestExt()
+ if err != nil {
+ return false
+ }
+ prebid := reqExt.GetPrebid()
+ if prebid == nil {
+ return false
+ }
+ return prebid.ReturnAllBidStatus
+}
diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go
index c008a819512..a22b6ee5c65 100644
--- a/endpoints/openrtb2/auction_test.go
+++ b/endpoints/openrtb2/auction_test.go
@@ -5807,7 +5807,7 @@ func TestValidResponseAfterExecutingStages(t *testing.T) {
}
}
-func TestSendAuctionResponse_LogsErrors(t *testing.T) {
+func TestSendAuctionResponse(t *testing.T) {
hookExecutor := &mockStageExecutor{
outcomes: []hookexecution.StageOutcome{
{
@@ -5824,6 +5824,14 @@ func TestSendAuctionResponse_LogsErrors(t *testing.T) {
Status: hookexecution.StatusSuccess,
Action: hookexecution.ActionNone,
Warnings: []string{"warning message"},
+ SeatNonBid: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp1"},
+ NonBidReason: int(exchange.ResponseRejectedCategoryMappingInvalid),
+ },
+ },
+ }),
},
},
},
@@ -5831,50 +5839,134 @@ func TestSendAuctionResponse_LogsErrors(t *testing.T) {
},
},
}
-
testCases := []struct {
- description string
- expectedErrors []error
- expectedStatus int
- request *openrtb2.BidRequest
- response *openrtb2.BidResponse
- hookExecutor hookexecution.HookStageExecutor
+ description string
+ expectedAuctionObject analytics.AuctionObject
+ expectedResponseBody string
+ request *openrtb2.BidRequest
+ response *openrtb2.BidResponse
+ hookExecutor hookexecution.HookStageExecutor
+ auctionObject analytics.AuctionObject
}{
{
description: "Error logged if hook enrichment fails",
- expectedErrors: []error{
- errors.New("Failed to enrich Bid Response with hook debug information: Invalid JSON Document"),
- errors.New("/openrtb2/auction Failed to send response: json: error calling MarshalJSON for type json.RawMessage: invalid character '.' looking for beginning of value"),
+ expectedAuctionObject: analytics.AuctionObject{
+ Errors: []error{
+ errors.New("Failed to enrich Bid Response with hook debug information: Invalid JSON Document"),
+ errors.New("/openrtb2/auction Failed to send response: json: error calling MarshalJSON for type json.RawMessage: invalid character '.' looking for beginning of value"),
+ },
+ Status: 0,
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: int(exchange.ResponseRejectedCategoryMappingInvalid),
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
},
- expectedStatus: 0,
- request: &openrtb2.BidRequest{ID: "some-id", Test: 1},
- response: &openrtb2.BidResponse{ID: "some-id", Ext: json.RawMessage("...")},
- hookExecutor: hookExecutor,
+ expectedResponseBody: "",
+ request: &openrtb2.BidRequest{ID: "some-id", Test: 1},
+ response: &openrtb2.BidResponse{ID: "some-id", Ext: json.RawMessage("...")},
+ hookExecutor: hookExecutor,
+ auctionObject: analytics.AuctionObject{},
},
{
description: "Error logged if hook enrichment returns warnings",
- expectedErrors: []error{
- errors.New("Value is not a string: 1"),
- errors.New("Value is not a boolean: active"),
+ expectedAuctionObject: analytics.AuctionObject{
+ Errors: []error{
+ errors.New("Value is not a string: 1"),
+ errors.New("Value is not a boolean: active"),
+ },
+ Status: 0,
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: int(exchange.ResponseRejectedCategoryMappingInvalid),
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ },
+ expectedResponseBody: "{\"id\":\"some-id\",\"ext\":{\"prebid\":{\"modules\":{\"warnings\":{\"foobar\":{\"foo\":[\"warning message\"]}}}}}}\n",
+ request: &openrtb2.BidRequest{ID: "some-id", Test: 1, Ext: json.RawMessage(`{"prebid": {"debug": "active", "trace": 1}}`)},
+ response: &openrtb2.BidResponse{ID: "some-id", Ext: json.RawMessage("{}")},
+ hookExecutor: hookExecutor,
+ auctionObject: analytics.AuctionObject{},
+ },
+ {
+ description: "Response should contain seatNonBid if returnallbidstatus is true",
+ expectedAuctionObject: analytics.AuctionObject{
+ Errors: nil,
+ Status: 0,
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: int(exchange.ResponseRejectedCategoryMappingInvalid),
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ },
+ expectedResponseBody: "{\"id\":\"some-id\",\"ext\":{\"prebid\":{\"modules\":{\"warnings\":{\"foobar\":{\"foo\":[\"warning message\"]}}}," +
+ "\"seatnonbid\":[{\"nonbid\":[{\"impid\":\"imp1\",\"statuscode\":303,\"ext\":{\"prebid\":{\"bid\":{}}}}],\"seat\":\"pubmatic\",\"ext\":null}]}}}\n",
+ request: &openrtb2.BidRequest{ID: "some-id", Test: 1, Ext: json.RawMessage(`"returnallbidstatus": true}}`)},
+ response: &openrtb2.BidResponse{ID: "some-id", Ext: json.RawMessage("{}")},
+ hookExecutor: hookExecutor,
+ auctionObject: analytics.AuctionObject{
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Ext: json.RawMessage(`{"prebid": {"returnallbidstatus": true}}`),
+ },
+ },
},
- expectedStatus: 0,
- request: &openrtb2.BidRequest{ID: "some-id", Test: 1, Ext: json.RawMessage(`{"prebid": {"debug": "active", "trace": 1}}`)},
- response: &openrtb2.BidResponse{ID: "some-id", Ext: json.RawMessage("{}")},
- hookExecutor: hookExecutor,
+ },
+ {
+ description: "Expect seatNonBid in auctionObject even if response is nil",
+ expectedAuctionObject: analytics.AuctionObject{
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: int(exchange.ResponseRejectedCategoryMappingInvalid),
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ },
+ expectedResponseBody: "null\n",
+ request: &openrtb2.BidRequest{ID: "some-id", Test: 1, Ext: json.RawMessage(`{"prebid": {"debug": true, "trace":" 1"}}`)},
+ response: nil,
+ hookExecutor: hookExecutor,
+ auctionObject: analytics.AuctionObject{},
},
}
-
for _, test := range testCases {
t.Run(test.description, func(t *testing.T) {
writer := httptest.NewRecorder()
labels := metrics.Labels{}
- ao := analytics.AuctionObject{}
account := &config.Account{DebugAllow: true}
+ if test.auctionObject.RequestWrapper != nil {
+ test.auctionObject.RequestWrapper.RebuildRequest()
+ }
- _, ao = sendAuctionResponse(writer, test.hookExecutor, test.response, test.request, account, labels, ao)
+ _, ao := sendAuctionResponse(writer, test.hookExecutor, test.response, test.request, account, labels, test.auctionObject, &openrtb_ext.NonBidCollection{})
- assert.Equal(t, ao.Errors, test.expectedErrors, "Invalid errors.")
- assert.Equal(t, test.expectedStatus, ao.Status, "Invalid HTTP response status.")
+ assert.Equal(t, test.expectedAuctionObject.Errors, ao.Errors, "Invalid errors.")
+ assert.Equal(t, test.expectedAuctionObject.Status, ao.Status, "Invalid HTTP response status.")
+ assert.Equal(t, test.expectedResponseBody, writer.Body.String(), "Invalid response body.")
+ assert.Equal(t, test.expectedAuctionObject.SeatNonBid, ao.SeatNonBid, "Invalid seatNonBid present in auctionObject.")
})
}
}
@@ -6015,46 +6107,112 @@ func (e mockStageExecutor) GetOutcomes() []hookexecution.StageOutcome {
func TestSetSeatNonBidRaw(t *testing.T) {
type args struct {
- request *openrtb_ext.RequestWrapper
- auctionResponse *exchange.AuctionResponse
+ request *openrtb_ext.RequestWrapper
+ response *openrtb2.BidResponse
+ nonBids []openrtb_ext.SeatNonBid
+ }
+ type want struct {
+ error bool
+ response *openrtb2.BidResponse
}
tests := []struct {
- name string
- args args
- wantErr bool
+ name string
+ args args
+ want want
}{
{
- name: "nil-auctionResponse",
- args: args{auctionResponse: nil},
- wantErr: false,
+ name: "nil response",
+ args: args{response: nil},
+ want: want{
+ error: false,
+ response: nil,
+ },
},
{
- name: "nil-bidResponse",
- args: args{auctionResponse: &exchange.AuctionResponse{BidResponse: nil}},
- wantErr: false,
+ name: "returnallbidstatus false",
+ args: args{response: &openrtb2.BidResponse{},
+ request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid": { "returnallbidstatus" : false }}`)}}},
+ want: want{
+ error: false,
+ response: &openrtb2.BidResponse{},
+ },
},
{
- name: "invalid-response.Ext",
- args: args{auctionResponse: &exchange.AuctionResponse{BidResponse: &openrtb2.BidResponse{Ext: []byte(`invalid_json`)}}},
- wantErr: true,
+ name: "invalid responseExt",
+ args: args{
+ request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid": { "returnallbidstatus" : true }}`)}},
+ response: &openrtb2.BidResponse{Ext: []byte(`{invalid}`)},
+ nonBids: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "pubmatic",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp",
+ StatusCode: 1,
+ },
+ },
+ },
+ },
+ },
+ want: want{
+ error: true,
+ response: &openrtb2.BidResponse{Ext: []byte(`{invalid}`)},
+ },
},
{
- name: "update-seatnonbid-in-ext",
+ name: "returnallbistatus is true, update seatnonbid in nil responseExt",
args: args{
- request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid": { "returnallbidstatus" : true }}`)}},
- auctionResponse: &exchange.AuctionResponse{
- ExtBidResponse: &openrtb_ext.ExtBidResponse{Prebid: &openrtb_ext.ExtResponsePrebid{SeatNonBid: []openrtb_ext.SeatNonBid{}}},
- BidResponse: &openrtb2.BidResponse{Ext: []byte(`{}`)},
+ request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid": { "returnallbidstatus" : true }}`)}},
+ response: &openrtb2.BidResponse{Ext: nil},
+ nonBids: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "pubmatic",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp",
+ StatusCode: 1,
+ },
+ },
+ },
+ },
+ },
+ want: want{
+ error: false,
+ response: &openrtb2.BidResponse{
+ Ext: json.RawMessage(`{"prebid":{"seatnonbid":[{"nonbid":[{"impid":"imp","statuscode":1,"ext":{"prebid":{"bid":{}}}}],"seat":"pubmatic","ext":null}]}}`),
+ },
+ },
+ },
+ {
+ name: "returnallbidstatus is true, update seatnonbid in non-nil responseExt",
+ args: args{
+ request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid": { "returnallbidstatus" : true }}`)}},
+ response: &openrtb2.BidResponse{Ext: []byte(`{}`)},
+ nonBids: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "pubmatic",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp",
+ StatusCode: 1,
+ },
+ },
+ },
+ },
+ },
+ want: want{
+ error: false,
+ response: &openrtb2.BidResponse{
+ Ext: json.RawMessage(`{"prebid":{"seatnonbid":[{"nonbid":[{"impid":"imp","statuscode":1,"ext":{"prebid":{"bid":{}}}}],"seat":"pubmatic","ext":null}]}}`),
},
},
- wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- if err := setSeatNonBidRaw(tt.args.request, tt.args.auctionResponse); (err != nil) != tt.wantErr {
- t.Errorf("setSeatNonBidRaw() error = %v, wantErr %v", err, tt.wantErr)
- }
+ err := setSeatNonBidRaw(tt.args.request, tt.args.response, tt.args.nonBids)
+ assert.Equal(t, err != nil, tt.want.error, "mismatched error.")
+ assert.Equal(t, tt.args.response, tt.want.response, "mismatched bidResponse.")
})
}
}
@@ -6507,3 +6665,654 @@ func TestValidateRequestCookieDeprecation(t *testing.T) {
assert.Equal(t, test.wantCDep, deviceExt.GetCDep())
}
}
+
+func TestGetNonBidsFromStageOutcomes(t *testing.T) {
+ tests := []struct {
+ name string
+ stageOutcomes []hookexecution.StageOutcome
+ expectedNonBids openrtb_ext.NonBidCollection
+ }{
+ {
+ name: "nil groups",
+ stageOutcomes: []hookexecution.StageOutcome{
+ {
+ Groups: nil,
+ },
+ },
+ expectedNonBids: getNonBids(map[string][]openrtb_ext.NonBidParams{}),
+ },
+ {
+ name: "nil and empty invocation results",
+ stageOutcomes: []hookexecution.StageOutcome{
+ {
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: nil,
+ },
+ {
+ InvocationResults: []hookexecution.HookOutcome{},
+ },
+ },
+ },
+ },
+ expectedNonBids: getNonBids(map[string][]openrtb_ext.NonBidParams{}),
+ },
+ {
+ name: "single nonbid with failure hookoutcome status",
+ stageOutcomes: []hookexecution.StageOutcome{
+ {
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ Status: hookexecution.StatusExecutionFailure,
+ SeatNonBid: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp1"},
+ NonBidReason: 100,
+ },
+ },
+ }),
+ },
+ },
+ },
+ },
+ },
+ },
+ expectedNonBids: getNonBids(map[string][]openrtb_ext.NonBidParams{}),
+ },
+ {
+ name: "single nonbid with success hookoutcome status",
+ stageOutcomes: []hookexecution.StageOutcome{
+ {
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ Status: hookexecution.StatusSuccess,
+ SeatNonBid: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp1"},
+ NonBidReason: 100,
+ },
+ },
+ }),
+ },
+ },
+ },
+ },
+ },
+ },
+ expectedNonBids: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp1"},
+ NonBidReason: 100,
+ },
+ },
+ }),
+ },
+ {
+ name: "seatNonBid from multi stage outcomes",
+ stageOutcomes: []hookexecution.StageOutcome{
+ {
+ Stage: hooks.StageAllProcessedBidResponses.String(),
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ Status: hookexecution.StatusSuccess,
+ SeatNonBid: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp1"},
+ NonBidReason: 100,
+ },
+ },
+ }),
+ },
+ },
+ },
+ },
+ },
+ {
+ Stage: hooks.StageBidderRequest.String(),
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ Status: hookexecution.StatusSuccess,
+ SeatNonBid: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "appnexus": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp1"},
+ NonBidReason: 100,
+ },
+ },
+ }),
+ },
+ },
+ },
+ },
+ },
+ },
+ expectedNonBids: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "appnexus": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp1"},
+ NonBidReason: 100,
+ },
+ },
+ "pubmatic": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp1"},
+ NonBidReason: 100,
+ },
+ },
+ }),
+ },
+ {
+ name: "seatNonBid for same seat from multi stage outcomes",
+ stageOutcomes: []hookexecution.StageOutcome{
+ {
+ Stage: hooks.StageAllProcessedBidResponses.String(),
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ Status: hookexecution.StatusSuccess,
+ SeatNonBid: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp1"},
+ NonBidReason: 100,
+ },
+ },
+ }),
+ },
+ },
+ },
+ },
+ },
+ {
+ Stage: hooks.StageBidderRequest.String(),
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ Status: hookexecution.StatusSuccess,
+ SeatNonBid: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp2"},
+ NonBidReason: 100,
+ },
+ },
+ }),
+ },
+ },
+ },
+ },
+ },
+ },
+ expectedNonBids: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp1"},
+ NonBidReason: 100,
+ },
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp2"},
+ NonBidReason: 100,
+ },
+ },
+ }),
+ },
+ {
+ name: "multi group outcomes with empty nonbids",
+ stageOutcomes: []hookexecution.StageOutcome{
+ {
+ Stage: hooks.StageAllProcessedBidResponses.String(),
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ Status: hookexecution.StatusSuccess,
+ SeatNonBid: openrtb_ext.NonBidCollection{},
+ },
+ },
+ },
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ Status: hookexecution.StatusSuccess,
+ SeatNonBid: openrtb_ext.NonBidCollection{},
+ },
+ },
+ },
+ },
+ },
+ },
+ expectedNonBids: openrtb_ext.NonBidCollection{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ nonBids := getNonBidsFromStageOutcomes(tt.stageOutcomes)
+ assert.Equal(t, nonBids, tt.expectedNonBids, "getNonBidsFromStageOutcomes returned incorrect nonBids")
+ })
+ }
+}
+
+// getNonBids is utility function which forms NonBidCollection from NonBidParams input
+func getNonBids(bidParamsMap map[string][]openrtb_ext.NonBidParams) openrtb_ext.NonBidCollection {
+ nonBids := openrtb_ext.NonBidCollection{}
+ for bidder, bidParams := range bidParamsMap {
+ for _, bidParam := range bidParams {
+ nonBid := openrtb_ext.NewNonBid(bidParam)
+ nonBids.AddBid(nonBid, bidder)
+ }
+ }
+ return nonBids
+}
+
+func TestSeatNonBidInAuction(t *testing.T) {
+ type args struct {
+ bidRequest openrtb2.BidRequest
+ seatNonBidFromHoldAuction openrtb_ext.NonBidCollection
+ errorFromHoldAuction error
+ rejectRawAuctionHook bool
+ errorFromHook error
+ }
+ type want struct {
+ statusCode int
+ body string
+ seatNonBid []openrtb_ext.SeatNonBid
+ }
+ testCases := []struct {
+ description string
+ args args
+ want want
+ }{
+ {
+ description: "request parsing failed, auctionObject should contain seatNonBid",
+ args: args{
+ bidRequest: openrtb2.BidRequest{
+ ID: "id",
+ Site: &openrtb2.Site{
+ ID: "site-1",
+ },
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp1",
+ Banner: &openrtb2.Banner{
+ W: openrtb2.Int64Ptr(100),
+ H: openrtb2.Int64Ptr(100),
+ },
+ },
+ },
+ },
+ },
+ want: want{
+ body: "Invalid request: request.imp[0].ext is required\n",
+ statusCode: 400,
+ seatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "pubmatic",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp",
+ StatusCode: 100,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ description: "auctionObject and bidResponseExt should contain seatNonBid when returnallbidstatus is true",
+ args: args{
+ bidRequest: openrtb2.BidRequest{
+ ID: "id",
+ Site: &openrtb2.Site{
+ ID: "site-1",
+ },
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp1",
+ Banner: &openrtb2.Banner{
+ W: openrtb2.Int64Ptr(100),
+ H: openrtb2.Int64Ptr(100),
+ },
+ Ext: json.RawMessage(`{"prebid": {"bidder":{"pubmatic":{"publisherid":1234}}}}`),
+ },
+ },
+ Ext: json.RawMessage(`{"prebid": {"returnallbidstatus": true}}`),
+ },
+ },
+ want: want{
+ statusCode: 200,
+ body: `{"id":"","seatbid":[{"bid":[{"id":"","impid":"","price":0,"adm":""}]}],"ext":{"prebid":` +
+ `{"seatnonbid":[{"nonbid":[{"impid":"imp","statuscode":100,"ext":{"prebid":{"bid":{}}}}],"seat":"pubmatic","ext":null}]}}}` + "\n",
+ seatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "pubmatic",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp",
+ StatusCode: 100,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ description: "auctionObject should contain seatNonBid from both holdAuction and hookOutcomes",
+ args: args{
+ seatNonBidFromHoldAuction: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "appnexus": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp"},
+ NonBidReason: 100,
+ },
+ },
+ }),
+ bidRequest: openrtb2.BidRequest{
+ ID: "id",
+ Site: &openrtb2.Site{
+ ID: "site-1",
+ },
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp1",
+ Banner: &openrtb2.Banner{
+ W: openrtb2.Int64Ptr(100),
+ H: openrtb2.Int64Ptr(100),
+ },
+ Ext: json.RawMessage(`{"prebid": {"bidder":{"pubmatic":{"publisherid":1234}}}}`),
+ },
+ },
+ Ext: json.RawMessage(`{"prebid": {"returnallbidstatus": false}}`),
+ },
+ },
+ want: want{
+ statusCode: 200,
+ body: `{"id":"","seatbid":[{"bid":[{"id":"","impid":"","price":0,"adm":""}]}]}` + "\n",
+ seatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "pubmatic",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp",
+ StatusCode: 100,
+ },
+ },
+ },
+ {
+ Seat: "appnexus",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp",
+ StatusCode: 100,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ description: "hookexecutor returns hook-reject error after parseRequest, seatNonBid should be present in auctionObject and bidResponseExt",
+ args: args{
+ rejectRawAuctionHook: true,
+ errorFromHook: &hookexecution.RejectError{Stage: hooks.StageEntrypoint.String(), NBR: 5},
+ bidRequest: openrtb2.BidRequest{
+ ID: "id",
+ Site: &openrtb2.Site{
+ ID: "site-1",
+ },
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp1",
+ Banner: &openrtb2.Banner{
+ W: openrtb2.Int64Ptr(100),
+ H: openrtb2.Int64Ptr(100),
+ },
+ Ext: json.RawMessage(`{"prebid": {"bidder":{"pubmatic":{"publisherid":1234}}}}`),
+ },
+ },
+ Ext: json.RawMessage(`{"prebid": {"returnallbidstatus": true}}`),
+ },
+ },
+ want: want{
+ statusCode: 200,
+ body: `{"id":"id","nbr":10,"ext":{"prebid":{"seatnonbid":[{"nonbid":[{"impid":"imp","statuscode":100,` +
+ `"ext":{"prebid":{"bid":{}}}}],"seat":"pubmatic","ext":null}]}}}` + "\n",
+ seatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "pubmatic",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp",
+ StatusCode: 100,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ description: "holdAuction returns hookRejection error, seatNonBid should be present in auctionObject and bidResponseExt",
+ args: args{
+ errorFromHoldAuction: &hookexecution.RejectError{Stage: hooks.StageAllProcessedBidResponses.String(), NBR: 5},
+ bidRequest: openrtb2.BidRequest{
+ ID: "id",
+ Site: &openrtb2.Site{
+ ID: "site-1",
+ },
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp1",
+ Banner: &openrtb2.Banner{
+ W: openrtb2.Int64Ptr(100),
+ H: openrtb2.Int64Ptr(100),
+ },
+ Ext: json.RawMessage(`{"prebid": {"bidder":{"pubmatic":{"publisherid":1234}}}}`),
+ },
+ },
+ Ext: json.RawMessage(`{"prebid": {"returnallbidstatus": true}}`),
+ },
+ },
+ want: want{
+ statusCode: 200,
+ body: `{"id":"id","nbr":5,"ext":{"prebid":{"seatnonbid":[{"nonbid":[{"impid":"imp","statuscode":100,"ext":{"prebid":{"bid":{}}}}],"seat":"pubmatic","ext":null}]}}}` + "\n",
+ seatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "pubmatic",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp",
+ StatusCode: 100,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ description: "holdAuction returns non-hookRejection error, seatNonBid should be present in auctionObject",
+ args: args{
+ errorFromHoldAuction: errors.New("any-error"),
+ bidRequest: openrtb2.BidRequest{
+ ID: "id",
+ Site: &openrtb2.Site{
+ ID: "site-1",
+ },
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp1",
+ Banner: &openrtb2.Banner{
+ W: openrtb2.Int64Ptr(100),
+ H: openrtb2.Int64Ptr(100),
+ },
+ Ext: json.RawMessage(`{"prebid": {"bidder":{"pubmatic":{"publisherid":1234}}}}`),
+ },
+ },
+ Ext: json.RawMessage(`{"prebid": {"returnallbidstatus": true}}`),
+ },
+ },
+ want: want{
+ statusCode: 500,
+ body: `Critical error while running the auction: any-error`,
+ seatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "pubmatic",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp",
+ StatusCode: 100,
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+ for _, test := range testCases {
+ t.Run(test.description, func(t *testing.T) {
+ reqBody, _ := json.Marshal(test.args.bidRequest)
+ mockAnalytics := mockAnalyticsModule{}
+ deps := &endpointDeps{
+ fakeUUIDGenerator{},
+ &mockExchange{seatNonBid: test.args.seatNonBidFromHoldAuction, returnError: test.args.errorFromHoldAuction},
+ mockBidderParamValidator{},
+ &mockStoredReqFetcher{},
+ empty_fetcher.EmptyFetcher{},
+ empty_fetcher.EmptyFetcher{},
+ &config.Configuration{MaxRequestSize: int64(len(reqBody))},
+ &metricsConfig.NilMetricsEngine{},
+ &mockAnalytics,
+ map[string]string{},
+ false,
+ []byte{},
+ openrtb_ext.BuildBidderMap(),
+ nil,
+ nil,
+ hardcodedResponseIPValidator{response: true},
+ empty_fetcher.EmptyFetcher{},
+ mockPlanBuilder{
+ entrypointPlan: makePlan[hookstage.Entrypoint](mockSeatNonBidHook{}),
+ rawAuctionPlan: makePlan[hookstage.RawAuctionRequest](
+ mockSeatNonBidHook{
+ rejectRawAuctionHook: test.args.rejectRawAuctionHook,
+ returnError: test.args.errorFromHook,
+ },
+ ),
+ },
+ nil,
+ openrtb_ext.NormalizeBidderName,
+ }
+
+ req := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(string(reqBody)))
+ recorder := httptest.NewRecorder()
+
+ deps.Auction(recorder, req, nil)
+
+ assert.Equal(t, test.want.statusCode, recorder.Result().StatusCode, "mismatched status code.")
+ assert.Equal(t, test.want.body, recorder.Body.String(), "mismatched response body.")
+ assert.ElementsMatch(t, test.want.seatNonBid, mockAnalytics.auctionObjects[0].SeatNonBid, "mismatched seat-non-bids.")
+ })
+ }
+}
+
+func TestSetSeatNonBid(t *testing.T) {
+ type args struct {
+ finalExtBidResponse *openrtb_ext.ExtBidResponse
+ seatNonBid []openrtb_ext.SeatNonBid
+ }
+ type want struct {
+ setSeatNonBid bool
+ finalExtBidResponse *openrtb_ext.ExtBidResponse
+ }
+ tests := []struct {
+ name string
+ args args
+ want want
+ }{
+ {
+ name: "nil seatNonBid",
+ args: args{seatNonBid: nil, finalExtBidResponse: &openrtb_ext.ExtBidResponse{}},
+ want: want{
+ setSeatNonBid: false,
+ finalExtBidResponse: &openrtb_ext.ExtBidResponse{},
+ },
+ },
+ {
+ name: "empty seatNonBid",
+ args: args{seatNonBid: []openrtb_ext.SeatNonBid{}, finalExtBidResponse: &openrtb_ext.ExtBidResponse{}},
+ want: want{
+ setSeatNonBid: false,
+ finalExtBidResponse: &openrtb_ext.ExtBidResponse{},
+ },
+ },
+ {
+ name: "finalExtBidResponse is nil",
+ args: args{finalExtBidResponse: nil},
+ want: want{
+ setSeatNonBid: false,
+ finalExtBidResponse: nil,
+ },
+ },
+ {
+ name: "finalExtBidResponse prebid is non-nil",
+ args: args{seatNonBid: []openrtb_ext.SeatNonBid{{Seat: "pubmatic", NonBid: []openrtb_ext.NonBid{{ImpId: "imp1", StatusCode: 100}}}},
+ finalExtBidResponse: &openrtb_ext.ExtBidResponse{Prebid: &openrtb_ext.ExtResponsePrebid{}}},
+ want: want{
+ setSeatNonBid: true,
+ finalExtBidResponse: &openrtb_ext.ExtBidResponse{Prebid: &openrtb_ext.ExtResponsePrebid{
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: 100,
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ }},
+ },
+ },
+ {
+ name: "finalExtBidResponse prebid is nil",
+ args: args{finalExtBidResponse: &openrtb_ext.ExtBidResponse{Prebid: nil}, seatNonBid: []openrtb_ext.SeatNonBid{{Seat: "pubmatic", NonBid: []openrtb_ext.NonBid{{ImpId: "imp1", StatusCode: 100}}}}},
+ want: want{
+ setSeatNonBid: true,
+ finalExtBidResponse: &openrtb_ext.ExtBidResponse{Prebid: &openrtb_ext.ExtResponsePrebid{
+ SeatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp1",
+ StatusCode: 100,
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ }},
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := setSeatNonBid(tt.args.finalExtBidResponse, tt.args.seatNonBid)
+ assert.Equal(t, tt.want.setSeatNonBid, got, "setSeatNonBid returned invalid value")
+ assert.Equal(t, tt.want.finalExtBidResponse, tt.args.finalExtBidResponse, "setSeatNonBid incorrectly updated finalExtBidResponse")
+ })
+ }
+}
diff --git a/endpoints/openrtb2/ctv_auction.go b/endpoints/openrtb2/ctv_auction.go
index 06bd47cda7f..b4ac7212e30 100644
--- a/endpoints/openrtb2/ctv_auction.go
+++ b/endpoints/openrtb2/ctv_auction.go
@@ -121,6 +121,7 @@ func (deps *ctvEndpointDeps) CTVAuctionEndpoint(w http.ResponseWriter, r *http.R
var response *openrtb2.BidResponse
var err error
var errL []error
+ seatNonBid := &openrtb_ext.NonBidCollection{}
ao := analytics.AuctionObject{
Status: http.StatusOK,
@@ -252,12 +253,16 @@ func (deps *ctvEndpointDeps) CTVAuctionEndpoint(w http.ResponseWriter, r *http.R
ao.Errors = append(ao.Errors, err)
return
}
- ao.SeatNonBid = auctionResponse.GetSeatNonBid()
- err = setSeatNonBidRaw(ao.RequestWrapper, auctionResponse)
+
+ response = auctionResponse.BidResponse
+ seatNonBid.Append(auctionResponse.SeatNonBid)
+ seatNonBid.Append(getNonBidsFromStageOutcomes(hookExecutor.GetOutcomes())) // append seatNonBids available in hook-stage-outcomes
+ ao.SeatNonBid = seatNonBid.Get()
+ // add seatNonBids in response.Ext based on 'returnallbidstatus' flag
+ err = setSeatNonBidRaw(ao.RequestWrapper, response, ao.SeatNonBid)
if err != nil {
- glog.Errorf("Error setting seat non-bid: %v", err)
+ util.JLogf("Error setting seatNonBid in responseExt: %v", err) //TODO: REMOVE LOG
}
- response = auctionResponse.BidResponse
util.JLogf("BidResponse", response) //TODO: REMOVE LOG
if deps.isAdPodRequest {
diff --git a/endpoints/openrtb2/test_utils.go b/endpoints/openrtb2/test_utils.go
index 9ad0cf83fe2..00f365ec3bc 100644
--- a/endpoints/openrtb2/test_utils.go
+++ b/endpoints/openrtb2/test_utils.go
@@ -847,9 +847,15 @@ func (cf mockStoredReqFetcher) FetchResponses(ctx context.Context, ids []string)
// mockExchange implements the Exchange interface
type mockExchange struct {
lastRequest *openrtb2.BidRequest
+ seatNonBid openrtb_ext.NonBidCollection
+ returnError error
}
func (m *mockExchange) HoldAuction(ctx context.Context, auctionRequest *exchange.AuctionRequest, debugLog *exchange.DebugLog) (*exchange.AuctionResponse, error) {
+ if m.returnError != nil {
+ return nil, m.returnError
+ }
+
r := auctionRequest.BidRequestWrapper
m.lastRequest = r.BidRequest
return &exchange.AuctionResponse{
@@ -860,6 +866,7 @@ func (m *mockExchange) HoldAuction(ctx context.Context, auctionRequest *exchange
}},
}},
},
+ SeatNonBid: m.seatNonBid,
}, nil
}
@@ -1530,6 +1537,76 @@ func (m mockRejectionHook) HandleRawBidderResponseHook(
return result, nil
}
+// mockSeatNonBidHook can be used to return seatNonBid from hook stage
+type mockSeatNonBidHook struct {
+ rejectEntrypointHook bool
+ rejectRawAuctionHook bool
+ rejectProcessedAuctionHook bool
+ rejectBidderRequestHook bool
+ rejectRawBidderResponseHook bool
+ returnError error
+}
+
+func (m mockSeatNonBidHook) HandleEntrypointHook(
+ _ context.Context,
+ _ hookstage.ModuleInvocationContext,
+ _ hookstage.EntrypointPayload,
+) (hookstage.HookResult[hookstage.EntrypointPayload], error) {
+ if m.rejectEntrypointHook {
+ return hookstage.HookResult[hookstage.EntrypointPayload]{NbrCode: 10, Reject: true}, m.returnError
+ }
+ result := hookstage.HookResult[hookstage.EntrypointPayload]{}
+ result.SeatNonBid = openrtb_ext.NonBidCollection{}
+ nonBid := openrtb_ext.NewNonBid(openrtb_ext.NonBidParams{Bid: &openrtb2.Bid{ImpID: "imp"}, NonBidReason: 100})
+ result.SeatNonBid.AddBid(nonBid, "pubmatic")
+
+ return result, m.returnError
+}
+
+func (m mockSeatNonBidHook) HandleRawAuctionHook(
+ _ context.Context,
+ _ hookstage.ModuleInvocationContext,
+ _ hookstage.RawAuctionRequestPayload,
+) (hookstage.HookResult[hookstage.RawAuctionRequestPayload], error) {
+ if m.rejectRawAuctionHook {
+ return hookstage.HookResult[hookstage.RawAuctionRequestPayload]{NbrCode: 10, Reject: true}, m.returnError
+ }
+ return hookstage.HookResult[hookstage.RawAuctionRequestPayload]{Reject: false, NbrCode: 0}, m.returnError
+}
+
+func (m mockSeatNonBidHook) HandleProcessedAuctionHook(
+ _ context.Context,
+ _ hookstage.ModuleInvocationContext,
+ _ hookstage.ProcessedAuctionRequestPayload,
+) (hookstage.HookResult[hookstage.ProcessedAuctionRequestPayload], error) {
+ if m.rejectProcessedAuctionHook {
+ return hookstage.HookResult[hookstage.ProcessedAuctionRequestPayload]{NbrCode: 10, Reject: true}, m.returnError
+ }
+ return hookstage.HookResult[hookstage.ProcessedAuctionRequestPayload]{Reject: true, NbrCode: 0}, m.returnError
+}
+
+func (m mockSeatNonBidHook) HandleBidderRequestHook(
+ _ context.Context,
+ _ hookstage.ModuleInvocationContext,
+ payload hookstage.BidderRequestPayload,
+) (hookstage.HookResult[hookstage.BidderRequestPayload], error) {
+ if m.rejectBidderRequestHook {
+ return hookstage.HookResult[hookstage.BidderRequestPayload]{NbrCode: 10, Reject: true}, m.returnError
+ }
+ return hookstage.HookResult[hookstage.BidderRequestPayload]{}, m.returnError
+}
+
+func (m mockSeatNonBidHook) HandleRawBidderResponseHook(
+ _ context.Context,
+ _ hookstage.ModuleInvocationContext,
+ payload hookstage.RawBidderResponsePayload,
+) (hookstage.HookResult[hookstage.RawBidderResponsePayload], error) {
+ if m.rejectRawBidderResponseHook {
+ return hookstage.HookResult[hookstage.RawBidderResponsePayload]{NbrCode: 10, Reject: true}, m.returnError
+ }
+ return hookstage.HookResult[hookstage.RawBidderResponsePayload]{}, m.returnError
+}
+
var entryPointHookUpdateWithErrors = hooks.HookWrapper[hookstage.Entrypoint]{
Module: "foobar",
Code: "foo",
diff --git a/endpoints/openrtb2/video_auction.go b/endpoints/openrtb2/video_auction.go
index fed79dd4a5d..c245e3fc2c1 100644
--- a/endpoints/openrtb2/video_auction.go
+++ b/endpoints/openrtb2/video_auction.go
@@ -122,6 +122,7 @@ func NewVideoEndpoint(
func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
start := time.Now()
+ seatNonBid := &openrtb_ext.NonBidCollection{}
vo := analytics.VideoObject{
Status: http.StatusOK,
Errors: make([]error, 0),
@@ -333,9 +334,10 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re
var response *openrtb2.BidResponse
if auctionResponse != nil {
response = auctionResponse.BidResponse
+ seatNonBid.Append(auctionResponse.SeatNonBid)
}
vo.Response = response
- vo.SeatNonBid = auctionResponse.GetSeatNonBid()
+ vo.SeatNonBid = seatNonBid.Get()
if err != nil {
errL := []error{err}
handleError(&labels, w, errL, &vo, &debugLog)
@@ -350,7 +352,7 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re
return
}
if bidReq.Test == 1 {
- err = setSeatNonBidRaw(bidReqWrapper, auctionResponse)
+ err = setSeatNonBidRaw(bidReqWrapper, response, vo.SeatNonBid)
if err != nil {
glog.Errorf("Error setting seat non-bid: %v", err)
}
diff --git a/endpoints/openrtb2/video_auction_test.go b/endpoints/openrtb2/video_auction_test.go
index caa152c1f99..56f56075bf4 100644
--- a/endpoints/openrtb2/video_auction_test.go
+++ b/endpoints/openrtb2/video_auction_test.go
@@ -1363,6 +1363,7 @@ func (cf mockVideoStoredReqFetcher) FetchResponses(ctx context.Context, ids []st
type mockExchangeVideo struct {
lastRequest *openrtb2.BidRequest
cache *mockCacheClient
+ seatNonBid openrtb_ext.NonBidCollection
}
func (m *mockExchangeVideo) HoldAuction(ctx context.Context, r *exchange.AuctionRequest, debugLog *exchange.DebugLog) (*exchange.AuctionResponse, error) {
@@ -1397,7 +1398,9 @@ func (m *mockExchangeVideo) HoldAuction(ctx context.Context, r *exchange.Auction
{ID: "16", ImpID: "5_2", Ext: ext},
},
}},
- }}, nil
+ },
+ SeatNonBid: m.seatNonBid}, nil
+
}
type mockExchangeAppendBidderNames struct {
@@ -1472,3 +1475,105 @@ func readVideoTestFile(t *testing.T, filename string) string {
return string(getRequestPayload(t, requestData))
}
+
+func TestSeatNonBidInVideoAuction(t *testing.T) {
+ bidRequest := openrtb_ext.BidRequestVideo{
+ Test: 1,
+ StoredRequestId: "80ce30c53c16e6ede735f123ef6e32361bfc7b22",
+ PodConfig: openrtb_ext.PodConfig{
+ DurationRangeSec: []int{30, 50},
+ RequireExactDuration: true,
+ Pods: []openrtb_ext.Pod{
+ {PodId: 1, AdPodDurationSec: 30, ConfigId: "fba10607-0c12-43d1-ad07-b8a513bc75d6"},
+ },
+ },
+ App: &openrtb2.App{Bundle: "pbs.com"},
+ Video: &openrtb2.Video{
+ MIMEs: []string{"mp4"},
+ Protocols: []adcom1.MediaCreativeSubtype{1},
+ },
+ }
+
+ type args struct {
+ nonBidsFromHoldAuction openrtb_ext.NonBidCollection
+ }
+ type want struct {
+ seatNonBid []openrtb_ext.SeatNonBid
+ }
+ testCases := []struct {
+ description string
+ args args
+ want want
+ }{
+ {
+ description: "holdAuction returns seatNonBid",
+ args: args{
+ nonBidsFromHoldAuction: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp"},
+ NonBidReason: 100,
+ },
+ },
+ }),
+ },
+ want: want{
+ seatNonBid: []openrtb_ext.SeatNonBid{
+ {
+ Seat: "pubmatic",
+ NonBid: []openrtb_ext.NonBid{
+ {
+ ImpId: "imp",
+ StatusCode: 100,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ description: "holdAuction does not return seatNonBid",
+ args: args{
+ nonBidsFromHoldAuction: openrtb_ext.NonBidCollection{},
+ },
+ want: want{
+ seatNonBid: nil,
+ },
+ },
+ }
+ for _, test := range testCases {
+ t.Run(test.description, func(t *testing.T) {
+ ex := &mockExchangeVideo{seatNonBid: test.args.nonBidsFromHoldAuction}
+ analyticsModule := mockAnalyticsModule{}
+ deps := &endpointDeps{
+ fakeUUIDGenerator{},
+ ex,
+ mockBidderParamValidator{},
+ &mockVideoStoredReqFetcher{},
+ &mockVideoStoredReqFetcher{},
+ &mockAccountFetcher{data: mockVideoAccountData},
+ &config.Configuration{MaxRequestSize: maxSize},
+ &metricsConfig.NilMetricsEngine{},
+ &analyticsModule,
+ map[string]string{},
+ false,
+ []byte{},
+ openrtb_ext.BuildBidderMap(),
+ ex.cache,
+ regexp.MustCompile(`[<>]`),
+ hardcodedResponseIPValidator{response: true},
+ empty_fetcher.EmptyFetcher{},
+ hooks.EmptyPlanBuilder{},
+ nil,
+ openrtb_ext.NormalizeBidderName,
+ }
+
+ reqBody, _ := json.Marshal(bidRequest)
+ req := httptest.NewRequest("POST", "/openrtb2/video", strings.NewReader(string(reqBody)))
+ recorder := httptest.NewRecorder()
+ deps.VideoAuctionEndpoint(recorder, req, nil)
+
+ assert.Equal(t, test.want.seatNonBid, analyticsModule.videoObjects[0].SeatNonBid, "mismatched seatnonbid.")
+ })
+ }
+}
diff --git a/exchange/auction_response.go b/exchange/auction_response.go
index 1d0747b0fe5..b38318a75e4 100644
--- a/exchange/auction_response.go
+++ b/exchange/auction_response.go
@@ -9,12 +9,5 @@ import (
type AuctionResponse struct {
*openrtb2.BidResponse
ExtBidResponse *openrtb_ext.ExtBidResponse
-}
-
-// GetSeatNonBid returns array of seat non-bid if present. nil otherwise
-func (ar *AuctionResponse) GetSeatNonBid() []openrtb_ext.SeatNonBid {
- if ar != nil && ar.ExtBidResponse != nil && ar.ExtBidResponse.Prebid != nil {
- return ar.ExtBidResponse.Prebid.SeatNonBid
- }
- return nil
+ SeatNonBid openrtb_ext.NonBidCollection
}
diff --git a/exchange/entities/entities_ow.go b/exchange/entities/entities_ow.go
new file mode 100644
index 00000000000..1a8d9645fa2
--- /dev/null
+++ b/exchange/entities/entities_ow.go
@@ -0,0 +1,31 @@
+package entities
+
+import "github.com/prebid/prebid-server/v2/openrtb_ext"
+
+// GetNonBidParamsFromPbsOrtbBid function returns NonBidParams from PbsOrtbBid
+func GetNonBidParamsFromPbsOrtbBid(bid *PbsOrtbBid, seat string) openrtb_ext.NonBidParams {
+ adapterCode := seat
+ if bid.AlternateBidderCode != "" {
+ adapterCode = string(openrtb_ext.BidderName(bid.AlternateBidderCode))
+ }
+ if bid.BidMeta == nil {
+ bid.BidMeta = &openrtb_ext.ExtBidPrebidMeta{}
+ }
+ bid.BidMeta.AdapterCode = adapterCode
+ return openrtb_ext.NonBidParams{
+ Bid: bid.Bid,
+ OriginalBidCPM: bid.OriginalBidCPM,
+ OriginalBidCur: bid.OriginalBidCur,
+ DealPriority: bid.DealPriority,
+ DealTierSatisfied: bid.DealTierSatisfied,
+ GeneratedBidID: bid.GeneratedBidID,
+ TargetBidderCode: bid.TargetBidderCode,
+ OriginalBidCPMUSD: bid.OriginalBidCPMUSD,
+ BidMeta: bid.BidMeta,
+ BidType: bid.BidType,
+ BidTargets: bid.BidTargets,
+ BidVideo: bid.BidVideo,
+ BidEvents: bid.BidEvents,
+ BidFloors: bid.BidFloors,
+ }
+}
diff --git a/exchange/exchange.go b/exchange/exchange.go
index 7ba55544945..02afe83a620 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -250,6 +250,9 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog
return nil, err
}
+ // seatNonBid will store nonbids collected inside HoldAuction function, it will not contain the nonbids from stageOutcomes
+ seatNonBid := openrtb_ext.NonBidCollection{}
+
// ensure prebid object always exists
requestExtPrebid := requestExt.GetPrebid()
if requestExtPrebid == nil {
@@ -276,7 +279,7 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog
var floorErrs []error
if e.priceFloorEnabled {
- floorErrs = floors.EnrichWithPriceFloors(r.BidRequestWrapper, r.Account, conversions, e.priceFloorFetcher)
+ floorErrs = floors.EnrichWithPriceFloors(r.BidRequestWrapper, r.Account, conversions, e.priceFloorFetcher, e.me)
if floors.RequestHasFloors(r.BidRequestWrapper.BidRequest) {
// Record request count with non-zero imp.bidfloor value
e.me.RecordFloorsRequestForAccount(r.PubID)
@@ -389,13 +392,11 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog
r.BidderResponseStartTime = extraRespInfo.bidderResponseStartTime
}
- var seatNonBids = nonBids{}
-
if anyBidsReturned {
var rejectedBids []*entities.PbsOrtbSeatBid
adapterBids, rejectedBids = applyBidPriceThreshold(adapterBids, r.Account, conversions)
if len(rejectedBids) > 0 {
- e.updateSeatNonBidsPriceThreshold(&seatNonBids, rejectedBids)
+ e.updateSeatNonBidsPriceThreshold(&seatNonBid, rejectedBids)
}
}
@@ -423,7 +424,7 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog
if len(rejectedBids) > 0 {
// Record rejected bid count at account level
e.me.RecordRejectedBidsForAccount(r.PubID)
- updateSeatNonBidsFloors(&seatNonBids, rejectedBids)
+ updateSeatNonBidsFloors(&seatNonBid, rejectedBids)
}
if responseDebugAllow {
@@ -438,7 +439,7 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog
}
}
- adapterBids, rejections := applyAdvertiserBlocking(r, adapterBids, &seatNonBids)
+ adapterBids, rejections := applyAdvertiserBlocking(r, adapterBids, &seatNonBid)
// add advertiser blocking specific errors
for _, message := range rejections {
errs = append(errs, errors.New(message))
@@ -447,7 +448,7 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog
//If includebrandcategory is present in ext then CE feature is on.
if requestExtPrebid.Targeting != nil && requestExtPrebid.Targeting.IncludeBrandCategory != nil {
var rejections []string
- bidCategory, adapterBids, rejections, err = applyCategoryMapping(ctx, r, *requestExtPrebid.Targeting, adapterBids, e.categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &seatNonBids)
+ bidCategory, adapterBids, rejections, err = applyCategoryMapping(ctx, r, *requestExtPrebid.Targeting, adapterBids, e.categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &seatNonBid)
if err != nil {
return nil, fmt.Errorf("Error in category mapping : %s", err.Error())
}
@@ -545,18 +546,18 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog
e.bidValidationEnforcement.SetBannerCreativeMaxSize(r.Account.Validations)
// Build the response
- bidResponse := e.buildBidResponse(ctx, liveAdapters, adapterBids, r.BidRequestWrapper, adapterExtra, auc, bidResponseExt, cacheInstructions.returnCreative, r.ImpExtInfoMap, r.PubID, errs, &seatNonBids)
+ bidResponse := e.buildBidResponse(ctx, liveAdapters, adapterBids, r.BidRequestWrapper, adapterExtra, auc, bidResponseExt, cacheInstructions.returnCreative, r.ImpExtInfoMap, r.PubID, errs, &seatNonBid)
bidResponse = adservertargeting.Apply(r.BidRequestWrapper, r.ResolvedBidRequest, bidResponse, r.QueryParams, bidResponseExt, r.Account.TruncateTargetAttribute)
bidResponse.Ext, err = encodeBidResponseExt(bidResponseExt)
if err != nil {
return nil, err
}
- bidResponseExt = setSeatNonBid(bidResponseExt, seatNonBids)
return &AuctionResponse{
BidResponse: bidResponse,
ExtBidResponse: bidResponseExt,
+ SeatNonBid: seatNonBid,
}, nil
}
@@ -985,7 +986,7 @@ func errsToBidderWarnings(errs []error) []openrtb_ext.ExtBidderMessage {
}
// This piece takes all the bids supplied by the adapters and crafts an openRTB response to send back to the requester
-func (e *exchange) buildBidResponse(ctx context.Context, liveAdapters []openrtb_ext.BidderName, adapterSeatBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid, bidRequest *openrtb_ext.RequestWrapper, adapterExtra map[openrtb_ext.BidderName]*seatResponseExtra, auc *auction, bidResponseExt *openrtb_ext.ExtBidResponse, returnCreative bool, impExtInfoMap map[string]ImpExtInfo, pubID string, errList []error, seatNonBids *nonBids) *openrtb2.BidResponse {
+func (e *exchange) buildBidResponse(ctx context.Context, liveAdapters []openrtb_ext.BidderName, adapterSeatBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid, bidRequest *openrtb_ext.RequestWrapper, adapterExtra map[openrtb_ext.BidderName]*seatResponseExtra, auc *auction, bidResponseExt *openrtb_ext.ExtBidResponse, returnCreative bool, impExtInfoMap map[string]ImpExtInfo, pubID string, errList []error, seatNonBids *openrtb_ext.NonBidCollection) *openrtb2.BidResponse {
bidResponse := new(openrtb2.BidResponse)
bidResponse.ID = bidRequest.ID
@@ -1020,7 +1021,7 @@ func encodeBidResponseExt(bidResponseExt *openrtb_ext.ExtBidResponse) ([]byte, e
return buffer.Bytes(), err
}
-func applyCategoryMapping(ctx context.Context, r *AuctionRequest, targeting openrtb_ext.ExtRequestTargeting, seatBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid, categoriesFetcher stored_requests.CategoryFetcher, targData *targetData, booleanGenerator deduplicateChanceGenerator, seatNonBids *nonBids) (map[string]string, map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid, []string, error) {
+func applyCategoryMapping(ctx context.Context, r *AuctionRequest, targeting openrtb_ext.ExtRequestTargeting, seatBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid, categoriesFetcher stored_requests.CategoryFetcher, targData *targetData, booleanGenerator deduplicateChanceGenerator, seatNonBids *openrtb_ext.NonBidCollection) (map[string]string, map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid, []string, error) {
bidRequest := r.BidRequestWrapper.BidRequest
res := make(map[string]string)
@@ -1083,6 +1084,8 @@ func applyCategoryMapping(ctx context.Context, r *AuctionRequest, targeting open
duration = bid.BidVideo.Duration
category = bid.BidVideo.PrimaryCategory
}
+ nonBidParams := entities.GetNonBidParamsFromPbsOrtbBid(bid, seatBid.Seat)
+ nonBidParams.NonBidReason = int(ResponseRejectedCategoryMappingInvalid)
if brandCatExt.WithCategory && category == "" {
bidIabCat := bid.Bid.Cat
@@ -1091,7 +1094,8 @@ func applyCategoryMapping(ctx context.Context, r *AuctionRequest, targeting open
//on receiving bids from adapters if no unique IAB category is returned or if no ad server category is returned discard the bid
bidsToRemove = append(bidsToRemove, bidInd)
rejections = updateRejections(rejections, bidID, "Bid did not contain a category")
- seatNonBids.addBid(bid, int(ResponseRejectedInvalidCategoryMapping), string(bidderName))
+ nonBid := openrtb_ext.NewNonBid(nonBidParams)
+ seatNonBids.AddBid(nonBid, string(bidderName))
continue
}
if translateCategories {
@@ -1101,7 +1105,10 @@ func applyCategoryMapping(ctx context.Context, r *AuctionRequest, targeting open
//TODO: add metrics
//if mapping required but no mapping file is found then discard the bid
bidsToRemove = append(bidsToRemove, bidInd)
- seatNonBids.addBid(bid, int(ResponseRejectedInvalidCategoryMapping), string(seatBid.Seat))
+ nonBidParams.NonBidReason = int(ResponseRejectedCategoryMappingInvalid)
+ nonBid := openrtb_ext.NewNonBid(nonBidParams)
+ seatNonBids.AddBid(nonBid, string(seatBid.Seat))
+
reason := fmt.Sprintf("Category mapping file for primary ad server: '%s', publisher: '%s' not found", primaryAdServer, publisher)
rejections = updateRejections(rejections, bidID, reason)
continue
@@ -1119,7 +1126,9 @@ func applyCategoryMapping(ctx context.Context, r *AuctionRequest, targeting open
newDur, err := findDurationRange(duration, targeting.DurationRangeSec)
if err != nil {
bidsToRemove = append(bidsToRemove, bidInd)
- seatNonBids.addBid(bid, int(ResponseRejectedInvalidCategoryMapping), string(seatBid.Seat))
+ nonBidParams.NonBidReason = int(ResponseRejectedCategoryMappingInvalid)
+ nonBid := openrtb_ext.NewNonBid(nonBidParams)
+ seatNonBids.AddBid(nonBid, string(seatBid.Seat))
rejections = updateRejections(rejections, bidID, err.Error())
continue
}
@@ -1171,7 +1180,8 @@ func applyCategoryMapping(ctx context.Context, r *AuctionRequest, targeting open
if dupe.bidderName == bidderName {
// An older bid from the current bidder
bidsToRemove = append(bidsToRemove, dupe.bidIndex)
- seatNonBids.addBid(bid, int(ResponseRejectedInvalidCategoryMapping), string(seatBid.Seat))
+ nonBid := openrtb_ext.NewNonBid(nonBidParams)
+ seatNonBids.AddBid(nonBid, string(seatBid.Seat))
rejections = updateRejections(rejections, dupe.bidID, "Bid was deduplicated")
} else {
// An older bid from a different seatBid we've already finished with
@@ -1192,7 +1202,9 @@ func applyCategoryMapping(ctx context.Context, r *AuctionRequest, targeting open
} else {
// Remove this bid
bidsToRemove = append(bidsToRemove, bidInd)
- seatNonBids.addBid(bid, int(ResponseRejectedInvalidCategoryMapping), string(seatBid.Seat))
+ nonBid := openrtb_ext.NewNonBid(nonBidParams)
+
+ seatNonBids.AddBid(nonBid, string(seatBid.Seat))
rejections = updateRejections(rejections, bidID, "Bid was deduplicated")
continue
}
@@ -1221,7 +1233,6 @@ func applyCategoryMapping(ctx context.Context, r *AuctionRequest, targeting open
for _, seatBidInd := range seatBidsToRemove {
seatBids[seatBidInd].Bids = nil
}
-
return res, seatBids, rejections, nil
}
@@ -1344,7 +1355,7 @@ func (e *exchange) makeExtBidResponse(adapterBids map[openrtb_ext.BidderName]*en
// Return an openrtb seatBid for a bidder
// buildBidResponse is responsible for ensuring nil bid seatbids are not included
-func (e *exchange) makeSeatBid(adapterBid *entities.PbsOrtbSeatBid, adapter openrtb_ext.BidderName, adapterExtra map[openrtb_ext.BidderName]*seatResponseExtra, auc *auction, returnCreative bool, impExtInfoMap map[string]ImpExtInfo, bidRequest *openrtb_ext.RequestWrapper, bidResponseExt *openrtb_ext.ExtBidResponse, pubID string, seatNonBids *nonBids) *openrtb2.SeatBid {
+func (e *exchange) makeSeatBid(adapterBid *entities.PbsOrtbSeatBid, adapter openrtb_ext.BidderName, adapterExtra map[openrtb_ext.BidderName]*seatResponseExtra, auc *auction, returnCreative bool, impExtInfoMap map[string]ImpExtInfo, bidRequest *openrtb_ext.RequestWrapper, bidResponseExt *openrtb_ext.ExtBidResponse, pubID string, seatNonBids *openrtb_ext.NonBidCollection) *openrtb2.SeatBid {
seatBid := &openrtb2.SeatBid{
Seat: adapter.String(),
Group: 0, // Prebid cannot support roadblocking
@@ -1359,7 +1370,7 @@ func (e *exchange) makeSeatBid(adapterBid *entities.PbsOrtbSeatBid, adapter open
return seatBid
}
-func (e *exchange) makeBid(bids []*entities.PbsOrtbBid, auc *auction, returnCreative bool, impExtInfoMap map[string]ImpExtInfo, bidRequest *openrtb_ext.RequestWrapper, bidResponseExt *openrtb_ext.ExtBidResponse, adapter openrtb_ext.BidderName, pubID string, seatNonBids *nonBids) ([]openrtb2.Bid, []error) {
+func (e *exchange) makeBid(bids []*entities.PbsOrtbBid, auc *auction, returnCreative bool, impExtInfoMap map[string]ImpExtInfo, bidRequest *openrtb_ext.RequestWrapper, bidResponseExt *openrtb_ext.ExtBidResponse, adapter openrtb_ext.BidderName, pubID string, seatNonBids *openrtb_ext.NonBidCollection) ([]openrtb2.Bid, []error) {
result := make([]openrtb2.Bid, 0, len(bids))
errs := make([]error, 0, 1)
@@ -1370,13 +1381,16 @@ func (e *exchange) makeBid(bids []*entities.PbsOrtbBid, auc *auction, returnCrea
Message: fmt.Sprintf("bid rejected: %s", err.Error()),
}
bidResponseExt.Warnings[adapter] = append(bidResponseExt.Warnings[adapter], dsaMessage)
-
- seatNonBids.addBid(bid, int(ResponseRejectedGeneral), adapter.String())
+ nonBidParams := entities.GetNonBidParamsFromPbsOrtbBid(bid, adapter.String())
+ nonBidParams.NonBidReason = int(ResponseRejectedGeneral)
+ seatNonBids.AddBid(openrtb_ext.NewNonBid(nonBidParams), adapter.String())
continue // Don't add bid to result
}
if e.bidValidationEnforcement.BannerCreativeMaxSize == config.ValidationEnforce && bid.BidType == openrtb_ext.BidTypeBanner {
if !e.validateBannerCreativeSize(bid, bidResponseExt, adapter, pubID, e.bidValidationEnforcement.BannerCreativeMaxSize) {
- seatNonBids.addBid(bid, int(ResponseRejectedCreativeSizeNotAllowed), adapter.String())
+ nonBidParams := entities.GetNonBidParamsFromPbsOrtbBid(bid, adapter.String())
+ nonBidParams.NonBidReason = int(ResponseRejectedCreativeSizeNotAllowed)
+ seatNonBids.AddBid(openrtb_ext.NewNonBid(nonBidParams), adapter.String())
continue // Don't add bid to result
}
} else if e.bidValidationEnforcement.BannerCreativeMaxSize == config.ValidationWarn && bid.BidType == openrtb_ext.BidTypeBanner {
@@ -1385,7 +1399,9 @@ func (e *exchange) makeBid(bids []*entities.PbsOrtbBid, auc *auction, returnCrea
if _, ok := impExtInfoMap[bid.Bid.ImpID]; ok {
if e.bidValidationEnforcement.SecureMarkup == config.ValidationEnforce && (bid.BidType == openrtb_ext.BidTypeBanner || bid.BidType == openrtb_ext.BidTypeVideo) {
if !e.validateBidAdM(bid, bidResponseExt, adapter, pubID, e.bidValidationEnforcement.SecureMarkup) {
- seatNonBids.addBid(bid, int(ResponseRejectedCreativeNotSecure), adapter.String())
+ nonBidParams := entities.GetNonBidParamsFromPbsOrtbBid(bid, adapter.String())
+ nonBidParams.NonBidReason = int(ResponseRejectedCreativeNotSecure)
+ seatNonBids.AddBid(openrtb_ext.NewNonBid(nonBidParams), adapter.String())
continue // Don't add bid to result
}
} else if e.bidValidationEnforcement.SecureMarkup == config.ValidationWarn && (bid.BidType == openrtb_ext.BidTypeBanner || bid.BidType == openrtb_ext.BidTypeVideo) {
@@ -1693,19 +1709,3 @@ func setErrorMessageSecureMarkup(validationType string) string {
}
return ""
}
-
-// setSeatNonBid adds SeatNonBids within bidResponse.Ext.Prebid.SeatNonBid
-func setSeatNonBid(bidResponseExt *openrtb_ext.ExtBidResponse, seatNonBids nonBids) *openrtb_ext.ExtBidResponse {
- if len(seatNonBids.seatNonBidsMap) == 0 {
- return bidResponseExt
- }
- if bidResponseExt == nil {
- bidResponseExt = &openrtb_ext.ExtBidResponse{}
- }
- if bidResponseExt.Prebid == nil {
- bidResponseExt.Prebid = &openrtb_ext.ExtResponsePrebid{}
- }
-
- bidResponseExt.Prebid.SeatNonBid = seatNonBids.get()
- return bidResponseExt
-}
diff --git a/exchange/exchange_ow.go b/exchange/exchange_ow.go
index d316b1b8de3..9e9023d1cb7 100644
--- a/exchange/exchange_ow.go
+++ b/exchange/exchange_ow.go
@@ -97,7 +97,7 @@ func normalizeDomain(domain string) (string, error) {
// applyAdvertiserBlocking rejects the bids of blocked advertisers mentioned in req.badv
// the rejection is currently only applicable to vast tag bidders. i.e. not for ortb bidders
// it returns seatbids containing valid bids and rejections containing rejected bid.id with reason
-func applyAdvertiserBlocking(r *AuctionRequest, seatBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid, seatNonBids *nonBids) (map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid, []string) {
+func applyAdvertiserBlocking(r *AuctionRequest, seatBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid, seatNonBids *openrtb_ext.NonBidCollection) (map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid, []string) {
bidRequest := r.BidRequestWrapper.BidRequest
rejections := []string{}
nBadvs := []string{}
@@ -141,7 +141,10 @@ func applyAdvertiserBlocking(r *AuctionRequest, seatBids map[openrtb_ext.BidderN
}
if rejectBid {
// Add rejected bid in seatNonBid.
- seatNonBids.addBid(bid, int(ResponseRejectedCreativeAdvertiserBlocking), seatBid.Seat)
+ nonBidParams := entities.GetNonBidParamsFromPbsOrtbBid(bid, seatBid.Seat)
+ nonBidParams.NonBidReason = int(ResponseRejectedCreativeAdvertiserBlocking)
+ seatNonBids.AddBid(openrtb_ext.NewNonBid(nonBidParams), seatBid.Seat)
+
// reject the bid. bid belongs to blocked advertisers list
seatBid.Bids = append(seatBid.Bids[:bidIndex], seatBid.Bids[bidIndex+1:]...)
rejections = updateRejections(rejections, bid.Bid.ID, fmt.Sprintf("Bid (From '%s') belongs to blocked advertiser '%s'", bidderName, bAdv))
@@ -223,14 +226,16 @@ func recordPartnerTimeout(ctx context.Context, pubID, aliasBidder string) {
}
// updateSeatNonBidsFloors updates seatnonbid with rejectedBids due to floors
-func updateSeatNonBidsFloors(seatNonBids *nonBids, rejectedBids []*entities.PbsOrtbSeatBid) {
+func updateSeatNonBidsFloors(seatNonBids *openrtb_ext.NonBidCollection, rejectedBids []*entities.PbsOrtbSeatBid) {
for _, pbsRejSeatBid := range rejectedBids {
for _, pbsRejBid := range pbsRejSeatBid.Bids {
var rejectionReason = ResponseRejectedBelowFloor
if pbsRejBid.Bid.DealID != "" {
rejectionReason = ResponseRejectedBelowDealFloor
}
- seatNonBids.addBid(pbsRejBid, int(rejectionReason), pbsRejSeatBid.Seat)
+ nonBidParams := entities.GetNonBidParamsFromPbsOrtbBid(pbsRejBid, pbsRejSeatBid.Seat)
+ nonBidParams.NonBidReason = int(rejectionReason)
+ seatNonBids.AddBid(openrtb_ext.NewNonBid(nonBidParams), pbsRejSeatBid.Seat)
}
}
}
@@ -342,10 +347,12 @@ func logBidsAbovePriceThreshold(rejectedBids []*entities.PbsOrtbSeatBid) {
}
}
-func (e exchange) updateSeatNonBidsPriceThreshold(seatNonBids *nonBids, rejectedBids []*entities.PbsOrtbSeatBid) {
+func (e exchange) updateSeatNonBidsPriceThreshold(seatNonBids *openrtb_ext.NonBidCollection, rejectedBids []*entities.PbsOrtbSeatBid) {
for _, pbsRejSeatBid := range rejectedBids {
for _, pbsRejBid := range pbsRejSeatBid.Bids {
- seatNonBids.addBid(pbsRejBid, int(ResponseRejectedBidPriceTooHigh), pbsRejSeatBid.Seat)
+ nonBidParams := entities.GetNonBidParamsFromPbsOrtbBid(pbsRejBid, pbsRejSeatBid.Seat)
+ nonBidParams.NonBidReason = int(ResponseRejectedBidPriceTooHigh)
+ seatNonBids.AddBid(openrtb_ext.NewNonBid(nonBidParams), pbsRejSeatBid.Seat)
}
}
}
diff --git a/exchange/exchange_ow_test.go b/exchange/exchange_ow_test.go
index 3ec5637ba1b..1593e96e647 100644
--- a/exchange/exchange_ow_test.go
+++ b/exchange/exchange_ow_test.go
@@ -33,7 +33,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
type want struct {
rejectedBidIds []string
validBidCountPerSeat map[string]int
- expectedseatNonBids nonBids
+ expectedseatNonBids openrtb_ext.NonBidCollection
}
tests := []struct {
name string
@@ -89,36 +89,28 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
},
},
want: want{
- expectedseatNonBids: nonBids{
- seatNonBidsMap: map[string][]openrtb_ext.NonBid{
+ expectedseatNonBids: getNonBids(
+ map[string][]openrtb_ext.NonBidParams{
"": {
{
- StatusCode: int(ResponseRejectedCreativeAdvertiserBlocking),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- ID: "reject_b.a.com.a.com.b.c.d.a.com",
- ADomain: []string{"b.a.com.a.com.b.c.d.a.com"},
- Meta: &openrtb_ext.ExtBidPrebidMeta{},
- },
- },
+ NonBidReason: int(ResponseRejectedCreativeAdvertiserBlocking),
+ Bid: &openrtb2.Bid{
+ ID: "reject_b.a.com.a.com.b.c.d.a.com",
+ ADomain: []string{"b.a.com.a.com.b.c.d.a.com"},
},
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{},
},
{
- StatusCode: int(ResponseRejectedCreativeAdvertiserBlocking),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- ID: "a.com_bid",
- ADomain: []string{"a.com"},
- Meta: &openrtb_ext.ExtBidPrebidMeta{},
- },
- },
+ NonBidReason: int(ResponseRejectedCreativeAdvertiserBlocking),
+ Bid: &openrtb2.Bid{
+ ID: "a.com_bid",
+ ADomain: []string{"a.com"},
},
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{},
},
},
},
- },
+ ),
rejectedBidIds: []string{"a.com_bid", "reject_b.a.com.a.com.b.c.d.a.com"},
validBidCountPerSeat: map[string]int{
"vast_tag_bidder": 3,
@@ -147,7 +139,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
validBidCountPerSeat: map[string]int{
"tab_bidder_1": 2,
},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
},
{
@@ -179,7 +171,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
"tag_bidder_1": 0, // expect 0 bids. i.e. all bids are rejected
"rtb_bidder_1": 2, // no bid must be rejected
},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
},
{
@@ -203,7 +195,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
validBidCountPerSeat: map[string]int{
"tag_adaptor_1": 1,
},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
},
{
@@ -235,7 +227,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
"tag_bidder_1": 2,
"rtb_bidder_1": 2,
},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
},
{
@@ -267,7 +259,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
"tag_bidder_1": 2,
"rtb_bidder_1": 2,
},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
},
{
@@ -292,7 +284,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
want: want{
rejectedBidIds: []string{"bid_1_of_blocked_adv", "bid_2_of_blocked_adv"},
validBidCountPerSeat: map[string]int{"my_adapter": 1},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
}, {
name: "multiple_badv",
@@ -334,7 +326,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
"tag_adapter_2": 0,
"rtb_adapter_1": 1,
},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
}, {
name: "multiple_adomain",
@@ -376,7 +368,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
"tag_adapter_2": 0,
"rtb_adapter_1": 1,
},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
}, {
name: "case_insensitive_badv", // case of domain not matters
@@ -400,7 +392,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
validBidCountPerSeat: map[string]int{
"tag_adapter_1": 0, // expect all bids are rejected as belongs to blocked advertiser
},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
},
{
@@ -425,7 +417,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
validBidCountPerSeat: map[string]int{
"tag_adapter_1": 0, // expect all bids are rejected as belongs to blocked advertiser
},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
},
{
@@ -461,7 +453,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
"block_bidder": 0,
"rtb_non_block_bidder": 4,
},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
},
{
@@ -488,7 +480,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
validBidCountPerSeat: map[string]int{
"block_bidder": 1,
},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
}, {
name: "only_domain_test", // do not expect bid rejection. edu is valid domain
@@ -514,7 +506,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
validBidCountPerSeat: map[string]int{
"tag_bidder": 3,
},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
},
{
@@ -540,7 +532,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
validBidCountPerSeat: map[string]int{
"tag_bidder": 2,
},
- expectedseatNonBids: nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
},
}
@@ -560,7 +552,7 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
seatBids[adaptor.BidderName] = sbids
}
- seatNonBids := nonBids{}
+ seatNonBids := openrtb_ext.NonBidCollection{}
// applyAdvertiserBlocking internally uses tagBidders from (adapter_map.go)
// not testing alias here
@@ -594,13 +586,17 @@ func TestApplyAdvertiserBlocking(t *testing.T) {
continue // advertiser blocking is currently enabled only for tag bidders
}
- sort.Slice(seatNonBids.seatNonBidsMap[sBid.Seat], func(i, j int) bool {
- return seatNonBids.seatNonBidsMap[sBid.Seat][i].Ext.Prebid.Bid.ID > seatNonBids.seatNonBidsMap[sBid.Seat][j].Ext.Prebid.Bid.ID
+ seatNonBidsMap := seatNonBids.GetSeatNonBidMap()
+
+ sort.Slice(seatNonBidsMap[sBid.Seat], func(i, j int) bool {
+ return seatNonBidsMap[sBid.Seat][i].Ext.Prebid.Bid.ID > seatNonBidsMap[sBid.Seat][j].Ext.Prebid.Bid.ID
})
- sort.Slice(tt.want.expectedseatNonBids.seatNonBidsMap[sBid.Seat], func(i, j int) bool {
- return tt.want.expectedseatNonBids.seatNonBidsMap[sBid.Seat][i].Ext.Prebid.Bid.ID > tt.want.expectedseatNonBids.seatNonBidsMap[sBid.Seat][j].Ext.Prebid.Bid.ID
+
+ expectedSeatNonBids := tt.want.expectedseatNonBids.GetSeatNonBidMap()
+ sort.Slice(expectedSeatNonBids[sBid.Seat], func(i, j int) bool {
+ return expectedSeatNonBids[sBid.Seat][i].Ext.Prebid.Bid.ID > expectedSeatNonBids[sBid.Seat][j].Ext.Prebid.Bid.ID
})
- assert.Equal(t, tt.want.expectedseatNonBids.seatNonBidsMap, seatNonBids.seatNonBidsMap, "SeatNonBids not matching")
+ assert.Equal(t, expectedSeatNonBids, seatNonBidsMap, "SeatNonBids not matching")
for _, bid := range sBid.Bids {
if nil != bid.Bid.ADomain {
@@ -1453,21 +1449,21 @@ func TestGetPriceBucketStringOW(t *testing.T) {
func Test_updateSeatNonBidsFloors(t *testing.T) {
type args struct {
- seatNonBids *nonBids
+ seatNonBids *openrtb_ext.NonBidCollection
rejectedBids []*entities.PbsOrtbSeatBid
}
tests := []struct {
name string
args args
- expectedseatNonBids *nonBids
+ expectedseatNonBids openrtb_ext.NonBidCollection
}{
{
name: "nil rejectedBids",
args: args{
rejectedBids: nil,
- seatNonBids: &nonBids{},
+ seatNonBids: &openrtb_ext.NonBidCollection{},
},
- expectedseatNonBids: &nonBids{},
+ expectedseatNonBids: openrtb_ext.NonBidCollection{},
},
{
name: "floors one rejectedBids in seatnonbid",
@@ -1490,37 +1486,31 @@ func Test_updateSeatNonBidsFloors(t *testing.T) {
Seat: "pubmatic",
},
},
- seatNonBids: &nonBids{},
+ seatNonBids: &openrtb_ext.NonBidCollection{},
},
- expectedseatNonBids: &nonBids{
- seatNonBidsMap: map[string][]openrtb_ext.NonBid{
- "pubmatic": {
- {
- StatusCode: 301,
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- ID: "bid1",
- Meta: &openrtb_ext.ExtBidPrebidMeta{AdapterCode: "pubmatic"},
- },
- },
- },
+ expectedseatNonBids: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {
+ {
+ Bid: &openrtb2.Bid{
+ ID: "bid1",
},
- {
- StatusCode: 304,
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- ID: "bid2",
- DealID: "deal1",
- Meta: &openrtb_ext.ExtBidPrebidMeta{AdapterCode: "pubmatic"},
- },
- },
- },
+ NonBidReason: 301,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{
+ AdapterCode: "pubmatic",
+ },
+ },
+ {
+ Bid: &openrtb2.Bid{
+ ID: "bid2",
+ DealID: "deal1",
+ },
+ NonBidReason: 304,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{
+ AdapterCode: "pubmatic",
},
},
},
- },
+ }),
},
{
name: "floors two rejectedBids in seatnonbid",
@@ -1559,68 +1549,58 @@ func Test_updateSeatNonBidsFloors(t *testing.T) {
Seat: "appnexus",
},
},
- seatNonBids: &nonBids{},
+ seatNonBids: &openrtb_ext.NonBidCollection{},
},
- expectedseatNonBids: &nonBids{
- seatNonBidsMap: map[string][]openrtb_ext.NonBid{
- "pubmatic": {
- {
- StatusCode: 301,
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- ID: "bid1",
- Meta: &openrtb_ext.ExtBidPrebidMeta{AdapterCode: "pubmatic"},
- },
- },
- },
+ expectedseatNonBids: getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "pubmatic": {
+ {
+ Bid: &openrtb2.Bid{
+ ID: "bid1",
},
- {
- StatusCode: 304,
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- ID: "bid2",
- DealID: "deal1",
- Meta: &openrtb_ext.ExtBidPrebidMeta{AdapterCode: "pubmatic"},
- },
- },
- },
+ NonBidReason: 301,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{
+ AdapterCode: "pubmatic",
},
},
- "appnexus": {
- {
- StatusCode: 301,
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- ID: "bid1",
- Meta: &openrtb_ext.ExtBidPrebidMeta{AdapterCode: "appnexus"},
- },
- },
- },
+ {
+ Bid: &openrtb2.Bid{
+ ID: "bid2",
+ DealID: "deal1",
},
- {
- StatusCode: 304,
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- ID: "bid2",
- DealID: "deal1",
- Meta: &openrtb_ext.ExtBidPrebidMeta{AdapterCode: "appnexus"},
- },
- },
- },
+ NonBidReason: 304,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{
+ AdapterCode: "pubmatic",
},
},
},
- },
+ "appnexus": {
+ {
+ Bid: &openrtb2.Bid{
+ ID: "bid1",
+ },
+ NonBidReason: 301,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{
+ AdapterCode: "appnexus",
+ },
+ },
+ {
+ Bid: &openrtb2.Bid{
+ ID: "bid2",
+ DealID: "deal1",
+ },
+ NonBidReason: 304,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{
+ AdapterCode: "appnexus",
+ },
+ },
+ },
+ }),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
updateSeatNonBidsFloors(tt.args.seatNonBids, tt.args.rejectedBids)
- assert.Equal(t, tt.expectedseatNonBids, tt.args.seatNonBids)
+ assert.Equal(t, tt.expectedseatNonBids, *tt.args.seatNonBids)
})
}
}
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index 5449086936a..cd3ef3ea078 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -170,7 +170,7 @@ func TestCharacterEscape(t *testing.T) {
var errList []error
// 4) Build bid response
- bidResp := e.buildBidResponse(context.Background(), liveAdapters, adapterBids, bidRequest, adapterExtra, nil, nil, true, nil, "", errList, &nonBids{})
+ bidResp := e.buildBidResponse(context.Background(), liveAdapters, adapterBids, bidRequest, adapterExtra, nil, nil, true, nil, "", errList, &openrtb_ext.NonBidCollection{})
// 5) Assert we have no errors and one '&' character as we are supposed to
if len(errList) > 0 {
@@ -1343,7 +1343,7 @@ func TestGetBidCacheInfoEndToEnd(t *testing.T) {
var errList []error
// 4) Build bid response
- bid_resp := e.buildBidResponse(context.Background(), liveAdapters, adapterBids, bidRequest, adapterExtra, auc, nil, true, nil, "", errList, &nonBids{})
+ bid_resp := e.buildBidResponse(context.Background(), liveAdapters, adapterBids, bidRequest, adapterExtra, auc, nil, true, nil, "", errList, &openrtb_ext.NonBidCollection{})
expectedBidResponse := &openrtb2.BidResponse{
SeatBid: []openrtb2.SeatBid{
@@ -1433,7 +1433,7 @@ func TestBidReturnsCreative(t *testing.T) {
//Run tests
for _, test := range testCases {
- resultingBids, resultingErrs := e.makeBid(sampleBids, sampleAuction, test.inReturnCreative, nil, &openrtb_ext.RequestWrapper{}, nil, "", "", &nonBids{})
+ resultingBids, resultingErrs := e.makeBid(sampleBids, sampleAuction, test.inReturnCreative, nil, &openrtb_ext.RequestWrapper{}, nil, "", "", &openrtb_ext.NonBidCollection{})
assert.Equal(t, 0, len(resultingErrs), "%s. Test should not return errors \n", test.description)
assert.Equal(t, test.expectedCreativeMarkup, resultingBids[0].AdM, "%s. Ad markup string doesn't match expected \n", test.description)
@@ -1718,7 +1718,7 @@ func TestBidResponseCurrency(t *testing.T) {
}
// Run tests
for i := range testCases {
- actualBidResp := e.buildBidResponse(context.Background(), liveAdapters, testCases[i].adapterBids, bidRequest, adapterExtra, nil, bidResponseExt, true, nil, "", errList, &nonBids{})
+ actualBidResp := e.buildBidResponse(context.Background(), liveAdapters, testCases[i].adapterBids, bidRequest, adapterExtra, nil, bidResponseExt, true, nil, "", errList, &openrtb_ext.NonBidCollection{})
assert.Equalf(t, testCases[i].expectedBidResponse, actualBidResp, fmt.Sprintf("[TEST_FAILED] Objects must be equal for test: %s \n Expected: >>%s<< \n Actual: >>%s<< ", testCases[i].description, testCases[i].expectedBidResponse.Ext, actualBidResp.Ext))
}
}
@@ -1785,7 +1785,7 @@ func TestBidResponseImpExtInfo(t *testing.T) {
json.RawMessage(`{"imp_passthrough_val":1}`)}
expectedBidResponseExt := `{"origbidcpm":0,"prebid":{"meta":{"adaptercode":"appnexus"},"type":"video","passthrough":{"imp_passthrough_val":1}},"storedrequestattributes":{"h":480,"mimes":["video/mp4"]}}`
- actualBidResp := e.buildBidResponse(context.Background(), liveAdapters, adapterBids, bidRequest, nil, nil, nil, true, impExtInfo, "", errList, &nonBids{})
+ actualBidResp := e.buildBidResponse(context.Background(), liveAdapters, adapterBids, bidRequest, nil, nil, nil, true, impExtInfo, "", errList, &openrtb_ext.NonBidCollection{})
resBidExt := string(actualBidResp.SeatBid[0].Bid[0].Ext)
assert.Equalf(t, expectedBidResponseExt, resBidExt, "Expected bid response extension is incorrect")
@@ -2223,10 +2223,10 @@ func runSpec(t *testing.T, filename string, spec *exchangeSpec) {
aucResponse, err := ex.HoldAuction(ctx, auctionRequest, debugLog)
var bid *openrtb2.BidResponse
- var bidExt *openrtb_ext.ExtBidResponse
+ var seatnonbid *openrtb_ext.NonBidCollection
if aucResponse != nil {
bid = aucResponse.BidResponse
- bidExt = aucResponse.ExtBidResponse
+ seatnonbid = &aucResponse.SeatNonBid
}
if len(spec.Response.Error) > 0 && spec.Response.Bids == nil {
if err.Error() != spec.Response.Error {
@@ -2324,8 +2324,8 @@ func runSpec(t *testing.T, filename string, spec *exchangeSpec) {
}
assert.Equal(t, expectedBidRespExt.Errors, actualBidRespExt.Errors, "Expected errors from response ext do not match")
}
- if expectedBidRespExt.Prebid != nil {
- assert.ElementsMatch(t, expectedBidRespExt.Prebid.SeatNonBid, bidExt.Prebid.SeatNonBid, "Expected seatNonBids from response ext do not match")
+ if len(spec.Response.SeatNonBids) > 0 {
+ assert.ElementsMatch(t, seatnonbid.Get(), spec.Response.SeatNonBids, "Expected seatNonBids from response ext do not match")
}
}
@@ -2594,37 +2594,28 @@ func TestCategoryMapping(t *testing.T) {
bidderName1 := openrtb_ext.BidderName("appnexus")
adapterBids[bidderName1] = &seatBid
- expectedseatNonBids := nonBids{
- seatNonBidsMap: map[string][]openrtb_ext.NonBid{
- "": {
- {
- ImpId: "imp_id4",
- StatusCode: int(ResponseRejectedInvalidCategoryMapping),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- Price: 40.0000,
- Cat: cats4,
- W: 1,
- H: 1,
- OriginalBidCPM: 40,
- OriginalBidCur: "USD",
- OriginalBidCPMUSD: 40,
-
- ID: "bid_id4",
- Type: openrtb_ext.BidTypeVideo,
- Video: &openrtb_ext.ExtBidPrebidVideo{
- Duration: 30,
- },
- Meta: &openrtb_ext.ExtBidPrebidMeta{},
- },
- },
- },
- },
+ expectedseatNonBids := getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp_id4",
+ ID: "bid_id4",
+ Price: 40.0000,
+ Cat: cats4,
+ W: 1,
+ H: 1,
+ },
+ NonBidReason: int(ResponseRejectedCategoryMappingInvalid),
+ OriginalBidCPM: 40,
+ OriginalBidCur: "USD",
+ BidType: "video",
+ BidVideo: &openrtb_ext.ExtBidPrebidVideo{Duration: 30, PrimaryCategory: "", VASTTagID: ""},
+ OriginalBidCPMUSD: 40,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{},
},
},
- }
- seatNonBids := nonBids{}
+ })
+ seatNonBids := openrtb_ext.NonBidCollection{}
+
bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &seatNonBids)
assert.Equal(t, nil, err, "Category mapping error should be empty")
@@ -2684,8 +2675,9 @@ func TestCategoryMappingNoIncludeBrandCategory(t *testing.T) {
bidderName1 := openrtb_ext.BidderName("appnexus")
adapterBids[bidderName1] = &seatBid
- expectedseatNonBids := nonBids{}
- seatNonBids := nonBids{}
+ expectedseatNonBids := openrtb_ext.NonBidCollection{}
+ seatNonBids := openrtb_ext.NonBidCollection{}
+
bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &seatNonBids)
assert.Equal(t, nil, err, "Category mapping error should be empty")
@@ -2706,7 +2698,7 @@ func TestCategoryMappingTranslateCategoriesNil(t *testing.T) {
t.Errorf("Failed to create a category Fetcher: %v", error)
}
- r := AuctionRequest{
+ r := &AuctionRequest{
BidRequestWrapper: &openrtb_ext.RequestWrapper{
BidRequest: &openrtb2.BidRequest{},
},
@@ -2745,39 +2737,29 @@ func TestCategoryMappingTranslateCategoriesNil(t *testing.T) {
adapterBids[bidderName1] = &seatBid
- expectedseatNonBids := nonBids{
- seatNonBidsMap: map[string][]openrtb_ext.NonBid{
- "": {
- {
- ImpId: "imp_id3",
- StatusCode: int(ResponseRejectedInvalidCategoryMapping),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- Price: 30.0000,
- Cat: cats3,
- W: 1,
- H: 1,
- OriginalBidCPM: 30,
- OriginalBidCur: "USD",
- OriginalBidCPMUSD: 30,
-
- ID: "bid_id3",
- Type: openrtb_ext.BidTypeVideo,
- Video: &openrtb_ext.ExtBidPrebidVideo{
- Duration: 30,
- },
- Meta: &openrtb_ext.ExtBidPrebidMeta{},
- },
- },
- },
- },
+ expectedseatNonBids := getNonBids(map[string][]openrtb_ext.NonBidParams{
+ "": {
+ {
+ Bid: &openrtb2.Bid{ImpID: "imp_id3",
+ ID: "bid_id3",
+ Price: 30.0000,
+ Cat: cats3,
+ W: 1,
+ H: 1,
+ },
+ NonBidReason: int(ResponseRejectedCategoryMappingInvalid),
+ OriginalBidCPM: 30,
+ OriginalBidCur: "USD",
+ BidType: "video",
+ BidVideo: &openrtb_ext.ExtBidPrebidVideo{Duration: 30, PrimaryCategory: "", VASTTagID: ""},
+ OriginalBidCPMUSD: 30,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{},
},
},
- }
+ })
+ seatNonBids := openrtb_ext.NonBidCollection{}
- seatNonBids := nonBids{}
- bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, &r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &seatNonBids)
+ bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &seatNonBids)
assert.Equal(t, nil, err, "Category mapping error should be empty")
assert.Equal(t, 1, len(rejections), "There should be 1 bid rejection message")
@@ -2863,8 +2845,9 @@ func TestCategoryMappingTranslateCategoriesFalse(t *testing.T) {
bidderName1 := openrtb_ext.BidderName("appnexus")
adapterBids[bidderName1] = &seatBid
- expectedseatNonBids := nonBids{}
- seatNonbids := nonBids{}
+ expectedseatNonBids := openrtb_ext.NonBidCollection{}
+ seatNonbids := openrtb_ext.NonBidCollection{}
+
bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &seatNonbids)
assert.Equal(t, nil, err, "Category mapping error should be empty")
@@ -2949,7 +2932,7 @@ func TestCategoryDedupe(t *testing.T) {
},
}
deduplicateGenerator := fakeBooleanGenerator{value: tt.dedupeGeneratorValue}
- bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &deduplicateGenerator, &nonBids{})
+ bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &deduplicateGenerator, &openrtb_ext.NonBidCollection{})
assert.Nil(t, err)
assert.Equal(t, 3, len(rejections))
@@ -3023,7 +3006,7 @@ func TestNoCategoryDedupe(t *testing.T) {
adapterBids[bidderName1] = &seatBid
- bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &nonBids{})
+ bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &openrtb_ext.NonBidCollection{})
assert.Equal(t, nil, err, "Category mapping error should be empty")
assert.Equal(t, 2, len(rejections), "There should be 2 bid rejection messages")
@@ -3092,8 +3075,10 @@ func TestCategoryMappingBidderName(t *testing.T) {
adapterBids[bidderName1] = &seatBid1
adapterBids[bidderName2] = &seatBid2
- expectedseatNonBids := nonBids{}
- seatNonBids := nonBids{}
+ expectedseatNonBids := openrtb_ext.NonBidCollection{}
+
+ seatNonBids := openrtb_ext.NonBidCollection{}
+
bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &seatNonBids)
assert.NoError(t, err, "Category mapping error should be empty")
@@ -3153,9 +3138,9 @@ func TestCategoryMappingBidderNameNoCategories(t *testing.T) {
adapterBids[bidderName1] = &seatBid1
adapterBids[bidderName2] = &seatBid2
+ expectedseatNonBids := openrtb_ext.NonBidCollection{}
+ seatNonBids := openrtb_ext.NonBidCollection{}
- expectedseatNonBids := nonBids{}
- seatNonBids := nonBids{}
bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &seatNonBids)
assert.NoError(t, err, "Category mapping error should be empty")
@@ -3191,13 +3176,13 @@ func TestBidRejectionErrors(t *testing.T) {
bidderName := openrtb_ext.BidderName("appnexus")
testCases := []struct {
- description string
- reqExt openrtb_ext.ExtRequest
- bids []*openrtb2.Bid
- duration int
- expectedRejections []string
- expectedCatDur string
- expectedseatNonBids nonBids
+ description string
+ reqExt openrtb_ext.ExtRequest
+ bids []*openrtb2.Bid
+ duration int
+ expectedRejections []string
+ expectedCatDur string
+ expectedSeatNonBid openrtb_ext.NonBidCollection
}{
{
description: "Bid should be rejected due to not containing a category",
@@ -3209,36 +3194,25 @@ func TestBidRejectionErrors(t *testing.T) {
expectedRejections: []string{
"bid rejected [bid ID: bid_id1] reason: Bid did not contain a category",
},
- expectedseatNonBids: nonBids{
- seatNonBidsMap: map[string][]openrtb_ext.NonBid{
- "appnexus": {
- {
- ImpId: "imp_id1",
- StatusCode: int(ResponseRejectedInvalidCategoryMapping),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- Price: 10.0000,
- Cat: []string{},
- W: 1,
- H: 1,
- OriginalBidCPM: 10,
- OriginalBidCur: "USD",
- OriginalBidCPMUSD: 10,
-
- ID: "bid_id1",
- Type: openrtb_ext.BidTypeVideo,
- Video: &openrtb_ext.ExtBidPrebidVideo{
- Duration: 30,
- },
- Meta: &openrtb_ext.ExtBidPrebidMeta{AdapterCode: "appnexus"},
- },
- },
- },
- },
+ expectedSeatNonBid: func() openrtb_ext.NonBidCollection {
+ seatNonBid := openrtb_ext.NonBidCollection{}
+ nonBid := openrtb_ext.NewNonBid(openrtb_ext.NonBidParams{
+ Bid: &openrtb2.Bid{ID: "bid_id1", ImpID: "imp_id1", Price: 10, W: 1, H: 1, Cat: []string{}},
+ NonBidReason: 303,
+ OriginalBidCPM: 10,
+ OriginalBidCur: "USD",
+ BidType: "video",
+ BidVideo: &openrtb_ext.ExtBidPrebidVideo{
+ Duration: 30,
+ PrimaryCategory: "",
+ VASTTagID: "",
},
- },
- },
+ OriginalBidCPMUSD: 10,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{},
+ })
+ seatNonBid.AddBid(nonBid, "appnexus")
+ return seatNonBid
+ }(),
},
{
description: "Bid should be rejected due to missing category mapping file",
@@ -3250,36 +3224,25 @@ func TestBidRejectionErrors(t *testing.T) {
expectedRejections: []string{
"bid rejected [bid ID: bid_id1] reason: Category mapping file for primary ad server: 'dfp', publisher: 'some_publisher' not found",
},
- expectedseatNonBids: nonBids{
- seatNonBidsMap: map[string][]openrtb_ext.NonBid{
- "": {
- {
- ImpId: "imp_id1",
- StatusCode: int(ResponseRejectedInvalidCategoryMapping),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- Price: 10.0000,
- Cat: []string{"IAB1-1"},
- W: 1,
- H: 1,
- OriginalBidCPM: 10,
- OriginalBidCur: "USD",
- OriginalBidCPMUSD: 10,
-
- ID: "bid_id1",
- Type: openrtb_ext.BidTypeVideo,
- Video: &openrtb_ext.ExtBidPrebidVideo{
- Duration: 30,
- },
- Meta: &openrtb_ext.ExtBidPrebidMeta{},
- },
- },
- },
- },
+ expectedSeatNonBid: func() openrtb_ext.NonBidCollection {
+ seatNonBid := openrtb_ext.NonBidCollection{}
+ nonBid := openrtb_ext.NewNonBid(openrtb_ext.NonBidParams{
+ Bid: &openrtb2.Bid{ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, W: 1, H: 1, Cat: []string{"IAB1-1"}},
+ NonBidReason: 303,
+ OriginalBidCPM: 10,
+ OriginalBidCur: "USD",
+ BidType: "video",
+ BidVideo: &openrtb_ext.ExtBidPrebidVideo{
+ Duration: 30,
+ PrimaryCategory: "",
+ VASTTagID: "",
},
- },
- },
+ OriginalBidCPMUSD: 10,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{},
+ })
+ seatNonBid.AddBid(nonBid, "")
+ return seatNonBid
+ }(),
},
{
description: "Bid should be rejected due to duration exceeding maximum",
@@ -3291,36 +3254,25 @@ func TestBidRejectionErrors(t *testing.T) {
expectedRejections: []string{
"bid rejected [bid ID: bid_id1] reason: bid duration exceeds maximum allowed",
},
- expectedseatNonBids: nonBids{
- seatNonBidsMap: map[string][]openrtb_ext.NonBid{
- "": {
- {
- ImpId: "imp_id1",
- StatusCode: int(ResponseRejectedInvalidCategoryMapping),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- Price: 10.0000,
- Cat: []string{"IAB1-1"},
- W: 1,
- H: 1,
- OriginalBidCPM: 10,
- OriginalBidCur: "USD",
- OriginalBidCPMUSD: 10,
-
- ID: "bid_id1",
- Type: openrtb_ext.BidTypeVideo,
- Video: &openrtb_ext.ExtBidPrebidVideo{
- Duration: 70,
- },
- Meta: &openrtb_ext.ExtBidPrebidMeta{},
- },
- },
- },
- },
+ expectedSeatNonBid: func() openrtb_ext.NonBidCollection {
+ seatNonBid := openrtb_ext.NonBidCollection{}
+ nonBid := openrtb_ext.NewNonBid(openrtb_ext.NonBidParams{
+ Bid: &openrtb2.Bid{ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, W: 1, H: 1, Cat: []string{"IAB1-1"}},
+ NonBidReason: 303,
+ OriginalBidCPM: 10,
+ OriginalBidCur: "USD",
+ BidType: "video",
+ BidVideo: &openrtb_ext.ExtBidPrebidVideo{
+ Duration: 70,
+ PrimaryCategory: "",
+ VASTTagID: "",
},
- },
- },
+ OriginalBidCPMUSD: 10,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{},
+ })
+ seatNonBid.AddBid(nonBid, "")
+ return seatNonBid
+ }(),
},
{
description: "Bid should be rejected due to duplicate bid",
@@ -3334,36 +3286,25 @@ func TestBidRejectionErrors(t *testing.T) {
"bid rejected [bid ID: bid_id1] reason: Bid was deduplicated",
},
expectedCatDur: "10.00_VideoGames_30s",
- expectedseatNonBids: nonBids{
- seatNonBidsMap: map[string][]openrtb_ext.NonBid{
- "": {
- {
- ImpId: "imp_id1",
- StatusCode: int(ResponseRejectedInvalidCategoryMapping),
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- Price: 10.0000,
- Cat: []string{"IAB1-1"},
- W: 1,
- H: 1,
- OriginalBidCPM: 10,
- OriginalBidCur: "USD",
- OriginalBidCPMUSD: 10,
-
- ID: "bid_id1",
- Type: openrtb_ext.BidTypeVideo,
- Video: &openrtb_ext.ExtBidPrebidVideo{
- Duration: 30,
- },
- Meta: &openrtb_ext.ExtBidPrebidMeta{},
- },
- },
- },
- },
+ expectedSeatNonBid: func() openrtb_ext.NonBidCollection {
+ seatNonBid := openrtb_ext.NonBidCollection{}
+ nonBid := openrtb_ext.NewNonBid(openrtb_ext.NonBidParams{
+ Bid: &openrtb2.Bid{ID: "bid_id1", ImpID: "imp_id1", Price: 10.0000, W: 1, H: 1, Cat: []string{"IAB1-1"}},
+ NonBidReason: 303,
+ OriginalBidCPM: 10,
+ OriginalBidCur: "USD",
+ BidType: "video",
+ BidVideo: &openrtb_ext.ExtBidPrebidVideo{
+ Duration: 30,
+ PrimaryCategory: "",
+ VASTTagID: "",
},
- },
- },
+ OriginalBidCPMUSD: 10,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{},
+ })
+ seatNonBid.AddBid(nonBid, "")
+ return seatNonBid
+ }(),
},
}
@@ -3374,16 +3315,15 @@ func TestBidRejectionErrors(t *testing.T) {
Bid: bid, BidMeta: nil, BidType: "video", BidTargets: nil, BidVideo: &openrtb_ext.ExtBidPrebidVideo{Duration: test.duration}, BidEvents: nil, BidFloors: nil, DealPriority: 0, DealTierSatisfied: false, GeneratedBidID: "", OriginalBidCPM: 10.0000, OriginalBidCur: "USD", TargetBidderCode: "", OriginalBidCPMUSD: 10.0000}
innerBids = append(innerBids, ¤tBid)
}
-
- seatBid := entities.PbsOrtbSeatBid{Bids: innerBids, Currency: "USD"}
-
- adapterBids[bidderName] = &seatBid
r := &AuctionRequest{
BidRequestWrapper: &openrtb_ext.RequestWrapper{
BidRequest: &openrtb2.BidRequest{},
},
}
- seatNonBids := nonBids{}
+ seatBid := entities.PbsOrtbSeatBid{Bids: innerBids, Currency: "USD"}
+
+ adapterBids[bidderName] = &seatBid
+ seatNonBids := openrtb_ext.NonBidCollection{}
bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, r, *test.reqExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &seatNonBids)
if len(test.expectedCatDur) > 0 {
@@ -3398,7 +3338,7 @@ func TestBidRejectionErrors(t *testing.T) {
assert.Empty(t, err, "Category mapping error should be empty")
assert.Equal(t, test.expectedRejections, rejections, test.description)
- assert.Equal(t, test.expectedseatNonBids, seatNonBids, "Rejected Bids did not match for %v", test.description)
+ assert.Equal(t, test.expectedSeatNonBid, seatNonBids, "SeatNonBid doesn't match")
}
}
@@ -3454,7 +3394,7 @@ func TestCategoryMappingTwoBiddersOneBidEachNoCategorySamePrice(t *testing.T) {
adapterBids[bidderNameApn1] = &seatBidApn1
adapterBids[bidderNameApn2] = &seatBidApn2
- bidCategory, adapterBids, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &nonBids{})
+ bidCategory, _, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &randomDeduplicateBidBooleanGenerator{}, &openrtb_ext.NonBidCollection{})
assert.NoError(t, err, "Category mapping error should be empty")
assert.Len(t, rejections, 1, "There should be 1 bid rejection message")
@@ -3543,9 +3483,10 @@ func TestCategoryMappingTwoBiddersManyBidsEachNoCategorySamePrice(t *testing.T)
adapterBids[bidderNameApn1] = &seatBidApn1
adapterBids[bidderNameApn2] = &seatBidApn2
- expectedseatNonBids := nonBids{}
- seatNonbids := nonBids{}
- _, adapterBids, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &fakeBooleanGenerator{value: true}, &seatNonbids)
+ expectedseatNonBids := openrtb_ext.NonBidCollection{}
+ seatNonBids := openrtb_ext.NonBidCollection{}
+
+ _, adapterBids, rejections, err := applyCategoryMapping(nil, r, *requestExt.Prebid.Targeting, adapterBids, categoriesFetcher, targData, &fakeBooleanGenerator{value: true}, &seatNonBids)
assert.NoError(t, err, "Category mapping error should be empty")
@@ -3569,7 +3510,7 @@ func TestCategoryMappingTwoBiddersManyBidsEachNoCategorySamePrice(t *testing.T)
assert.Equal(t, 2, totalNumberOfbids, "2 bids total should be returned")
assert.Len(t, rejections, 2, "2 bids should be de-duplicated")
- assert.Equal(t, expectedseatNonBids, seatNonbids, "Bid Rejections not matching")
+ assert.Equal(t, expectedseatNonBids, seatNonBids, "Bid Rejections not matching")
if firstBidderIndicator {
assert.Len(t, adapterBids[bidderNameApn1].Bids, 2)
assert.Len(t, adapterBids[bidderNameApn2].Bids, 0)
@@ -5008,7 +4949,7 @@ func TestMakeBidWithValidation(t *testing.T) {
givenBids []*entities.PbsOrtbBid
givenSeat openrtb_ext.BidderName
expectedNumOfBids int
- expectedNonBids *nonBids
+ expectedNonBids *openrtb_ext.NonBidCollection
expectedNumDebugErrors int
expectedNumDebugWarnings int
}{
@@ -5019,22 +4960,18 @@ func TestMakeBidWithValidation(t *testing.T) {
givenBids: []*entities.PbsOrtbBid{{Bid: &openrtb2.Bid{Ext: json.RawMessage(`{"dsa": {"adrender":1}}`)}}, {Bid: &openrtb2.Bid{}}},
givenSeat: "pubmatic",
expectedNumOfBids: 1,
- expectedNonBids: &nonBids{
- seatNonBidsMap: map[string][]openrtb_ext.NonBid{
- "pubmatic": {
- {
- StatusCode: 300,
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- Meta: &openrtb_ext.ExtBidPrebidMeta{AdapterCode: "pubmatic"},
- },
- },
- },
- },
+ expectedNonBids: func() *openrtb_ext.NonBidCollection {
+ seatNonBid := openrtb_ext.NonBidCollection{}
+ nonBid := openrtb_ext.NewNonBid(openrtb_ext.NonBidParams{
+ Bid: &openrtb2.Bid{},
+ NonBidReason: 300,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{
+ AdapterCode: "pubmatic",
},
- },
- },
+ })
+ seatNonBid.AddBid(nonBid, "pubmatic")
+ return &seatNonBid
+ }(),
expectedNumDebugWarnings: 1,
},
{
@@ -5043,25 +4980,19 @@ func TestMakeBidWithValidation(t *testing.T) {
givenBids: []*entities.PbsOrtbBid{{Bid: &openrtb2.Bid{W: 200, H: 200}, BidType: openrtb_ext.BidTypeBanner}, {Bid: &openrtb2.Bid{W: 50, H: 50}, BidType: openrtb_ext.BidTypeBanner}},
givenSeat: "pubmatic",
expectedNumOfBids: 1,
- expectedNonBids: &nonBids{
- seatNonBidsMap: map[string][]openrtb_ext.NonBid{
- "pubmatic": {
- {
- StatusCode: 351,
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- W: 200,
- H: 200,
- Type: "banner",
- Meta: &openrtb_ext.ExtBidPrebidMeta{AdapterCode: "pubmatic"},
- },
- },
- },
- },
+ expectedNonBids: func() *openrtb_ext.NonBidCollection {
+ seatNonBid := openrtb_ext.NonBidCollection{}
+ nonBid := openrtb_ext.NewNonBid(openrtb_ext.NonBidParams{
+ Bid: &openrtb2.Bid{W: 200, H: 200},
+ NonBidReason: 351,
+ BidType: openrtb_ext.BidTypeBanner,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{
+ AdapterCode: "pubmatic",
},
- },
- },
+ })
+ seatNonBid.AddBid(nonBid, "pubmatic")
+ return &seatNonBid
+ }(),
expectedNumDebugErrors: 1,
},
{
@@ -5070,7 +5001,7 @@ func TestMakeBidWithValidation(t *testing.T) {
givenBids: []*entities.PbsOrtbBid{{Bid: &openrtb2.Bid{W: 200, H: 200}, BidType: openrtb_ext.BidTypeBanner}, {Bid: &openrtb2.Bid{W: 50, H: 50}, BidType: openrtb_ext.BidTypeBanner}},
givenSeat: "pubmatic",
expectedNumOfBids: 2,
- expectedNonBids: &nonBids{},
+ expectedNonBids: &openrtb_ext.NonBidCollection{},
expectedNumDebugErrors: 1,
},
{
@@ -5079,24 +5010,19 @@ func TestMakeBidWithValidation(t *testing.T) {
givenBids: []*entities.PbsOrtbBid{{Bid: &openrtb2.Bid{AdM: "http://domain.com/invalid", ImpID: "1"}, BidType: openrtb_ext.BidTypeBanner}, {Bid: &openrtb2.Bid{AdM: "https://domain.com/valid", ImpID: "2"}, BidType: openrtb_ext.BidTypeBanner}},
givenSeat: "pubmatic",
expectedNumOfBids: 1,
- expectedNonBids: &nonBids{
- seatNonBidsMap: map[string][]openrtb_ext.NonBid{
- "pubmatic": {
- {
- ImpId: "1",
- StatusCode: 352,
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{
- Bid: openrtb_ext.NonBidObject{
- Type: "banner",
- Meta: &openrtb_ext.ExtBidPrebidMeta{AdapterCode: "pubmatic"},
- },
- },
- },
- },
+ expectedNonBids: func() *openrtb_ext.NonBidCollection {
+ seatNonBid := openrtb_ext.NonBidCollection{}
+ nonBid := openrtb_ext.NewNonBid(openrtb_ext.NonBidParams{
+ Bid: &openrtb2.Bid{ImpID: "1"},
+ NonBidReason: 352,
+ BidType: openrtb_ext.BidTypeBanner,
+ BidMeta: &openrtb_ext.ExtBidPrebidMeta{
+ AdapterCode: "pubmatic",
},
- },
- },
+ })
+ seatNonBid.AddBid(nonBid, "pubmatic")
+ return &seatNonBid
+ }(),
expectedNumDebugErrors: 1,
},
{
@@ -5105,7 +5031,7 @@ func TestMakeBidWithValidation(t *testing.T) {
givenBids: []*entities.PbsOrtbBid{{Bid: &openrtb2.Bid{AdM: "http://domain.com/invalid", ImpID: "1"}, BidType: openrtb_ext.BidTypeBanner}, {Bid: &openrtb2.Bid{AdM: "https://domain.com/valid", ImpID: "2"}, BidType: openrtb_ext.BidTypeBanner}},
givenSeat: "pubmatic",
expectedNumOfBids: 2,
- expectedNonBids: &nonBids{},
+ expectedNonBids: &openrtb_ext.NonBidCollection{},
expectedNumDebugErrors: 1,
},
{
@@ -5114,7 +5040,7 @@ func TestMakeBidWithValidation(t *testing.T) {
givenBids: []*entities.PbsOrtbBid{{Bid: &openrtb2.Bid{AdM: "http://domain.com/invalid"}, BidType: openrtb_ext.BidTypeBanner}, {Bid: &openrtb2.Bid{AdM: "https://domain.com/valid"}, BidType: openrtb_ext.BidTypeBanner}},
givenSeat: "pubmatic",
expectedNumOfBids: 2,
- expectedNonBids: &nonBids{},
+ expectedNonBids: &openrtb_ext.NonBidCollection{},
},
{
name: "Creative_size_validation_skipped,_Adm_Validation_enforced,_one_of_two_bids_has_invalid_dimensions",
@@ -5122,7 +5048,7 @@ func TestMakeBidWithValidation(t *testing.T) {
givenBids: []*entities.PbsOrtbBid{{Bid: &openrtb2.Bid{W: 200, H: 200}, BidType: openrtb_ext.BidTypeBanner}, {Bid: &openrtb2.Bid{W: 50, H: 50}, BidType: openrtb_ext.BidTypeBanner}},
givenSeat: "pubmatic",
expectedNumOfBids: 2,
- expectedNonBids: &nonBids{},
+ expectedNonBids: &openrtb_ext.NonBidCollection{},
},
}
@@ -5171,7 +5097,7 @@ func TestMakeBidWithValidation(t *testing.T) {
}
e.bidValidationEnforcement = test.givenValidations
sampleBids := test.givenBids
- nonBids := &nonBids{}
+ nonBids := &openrtb_ext.NonBidCollection{}
resultingBids, resultingErrs := e.makeBid(sampleBids, sampleAuction, true, ImpExtInfoMap, bidRequest, bidExtResponse, test.givenSeat, "", nonBids)
assert.Equal(t, 0, len(resultingErrs))
@@ -5776,9 +5702,10 @@ type exchangeRequest struct {
}
type exchangeResponse struct {
- Bids *openrtb2.BidResponse `json:"bids"`
- Error string `json:"error,omitempty"`
- Ext json.RawMessage `json:"ext,omitempty"`
+ Bids *openrtb2.BidResponse `json:"bids"`
+ Error string `json:"error,omitempty"`
+ Ext json.RawMessage `json:"ext,omitempty"`
+ SeatNonBids []openrtb_ext.SeatNonBid `json:"seatnonbids,omitempty"`
}
type exchangeServer struct {
@@ -6273,42 +6200,80 @@ func TestSelectNewDuration(t *testing.T) {
}
}
-func TestSetSeatNonBid(t *testing.T) {
- type args struct {
- bidResponseExt *openrtb_ext.ExtBidResponse
- seatNonBids nonBids
+func TestBidsToUpdate(t *testing.T) {
+ type testInput struct {
+ multiBid map[string]openrtb_ext.ExtMultiBid
+ bidder string
}
- tests := []struct {
- name string
- args args
- want *openrtb_ext.ExtBidResponse
+ testCases := []struct {
+ desc string
+ in testInput
+ expected int
}{
{
- name: "empty-seatNonBidsMap",
- args: args{seatNonBids: nonBids{}, bidResponseExt: nil},
- want: nil,
+ desc: "Empty multibid map. Expect openrtb_ext.DefaultBidLimit",
+ in: testInput{},
+ expected: openrtb_ext.DefaultBidLimit,
+ },
+ {
+ desc: "Empty bidder. Expect openrtb_ext.DefaultBidLimit",
+ in: testInput{
+ multiBid: map[string]openrtb_ext.ExtMultiBid{
+ "appnexus": {
+ Bidder: "appnexus",
+ MaxBids: ptrutil.ToPtr(2),
+ },
+ },
+ },
+ expected: openrtb_ext.DefaultBidLimit,
},
{
- name: "nil-bidResponseExt",
- args: args{seatNonBids: nonBids{seatNonBidsMap: map[string][]openrtb_ext.NonBid{"key": nil}}, bidResponseExt: nil},
- want: &openrtb_ext.ExtBidResponse{
- Prebid: &openrtb_ext.ExtResponsePrebid{
- SeatNonBid: []openrtb_ext.SeatNonBid{{
- Seat: "key",
- }},
+ desc: "bidder finds a match in multibid map but TargetBidderCodePrefix is empty. Expect openrtb_ext.DefaultBidLimit",
+ in: testInput{
+ multiBid: map[string]openrtb_ext.ExtMultiBid{
+ "appnexus": {
+ Bidder: "appnexus",
+ MaxBids: ptrutil.ToPtr(2),
+ },
},
+ bidder: "appnexus",
},
+ expected: openrtb_ext.DefaultBidLimit,
+ },
+ {
+ desc: "multibid element with non-empty TargetBidderCodePrefix matches bidder. Expect MaxBids value",
+ in: testInput{
+ multiBid: map[string]openrtb_ext.ExtMultiBid{
+ "appnexus": {
+ Bidder: "appnexus",
+ MaxBids: ptrutil.ToPtr(2),
+ TargetBidderCodePrefix: "aPrefix",
+ },
+ },
+ bidder: "appnexus",
+ },
+ expected: 2,
},
}
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- if got := setSeatNonBid(tt.args.bidResponseExt, tt.args.seatNonBids); !reflect.DeepEqual(got, tt.want) {
- t.Errorf("setSeatNonBid() = %v, want %v", got, tt.want)
- }
+ for _, tc := range testCases {
+ t.Run(tc.desc, func(t *testing.T) {
+ assert.Equal(t, tc.expected, bidsToUpdate(tc.in.multiBid, tc.in.bidder), tc.desc)
})
}
}
+// getNonBids is utility function which forms NonBidCollection from NonBidParams input
+func getNonBids(bidParamsMap map[string][]openrtb_ext.NonBidParams) openrtb_ext.NonBidCollection {
+ nonBids := openrtb_ext.NonBidCollection{}
+ for bidder, bidParams := range bidParamsMap {
+ for _, bidParam := range bidParams {
+ nonBid := openrtb_ext.NewNonBid(bidParam)
+ nonBids.AddBid(nonBid, bidder)
+ }
+ }
+ return nonBids
+}
+
func TestBuildMultiBidMap(t *testing.T) {
type testCase struct {
desc string
@@ -6500,65 +6465,3 @@ func TestBuildMultiBidMap(t *testing.T) {
}
}
}
-
-func TestBidsToUpdate(t *testing.T) {
- type testInput struct {
- multiBid map[string]openrtb_ext.ExtMultiBid
- bidder string
- }
- testCases := []struct {
- desc string
- in testInput
- expected int
- }{
- {
- desc: "Empty multibid map. Expect openrtb_ext.DefaultBidLimit",
- in: testInput{},
- expected: openrtb_ext.DefaultBidLimit,
- },
- {
- desc: "Empty bidder. Expect openrtb_ext.DefaultBidLimit",
- in: testInput{
- multiBid: map[string]openrtb_ext.ExtMultiBid{
- "appnexus": {
- Bidder: "appnexus",
- MaxBids: ptrutil.ToPtr(2),
- },
- },
- },
- expected: openrtb_ext.DefaultBidLimit,
- },
- {
- desc: "bidder finds a match in multibid map but TargetBidderCodePrefix is empty. Expect openrtb_ext.DefaultBidLimit",
- in: testInput{
- multiBid: map[string]openrtb_ext.ExtMultiBid{
- "appnexus": {
- Bidder: "appnexus",
- MaxBids: ptrutil.ToPtr(2),
- },
- },
- bidder: "appnexus",
- },
- expected: openrtb_ext.DefaultBidLimit,
- },
- {
- desc: "multibid element with non-empty TargetBidderCodePrefix matches bidder. Expect MaxBids value",
- in: testInput{
- multiBid: map[string]openrtb_ext.ExtMultiBid{
- "appnexus": {
- Bidder: "appnexus",
- MaxBids: ptrutil.ToPtr(2),
- TargetBidderCodePrefix: "aPrefix",
- },
- },
- bidder: "appnexus",
- },
- expected: 2,
- },
- }
- for _, tc := range testCases {
- t.Run(tc.desc, func(t *testing.T) {
- assert.Equal(t, tc.expected, bidsToUpdate(tc.in.multiBid, tc.in.bidder), tc.desc)
- })
- }
-}
diff --git a/exchange/exchangetest/bid_response_validation_enforce_one_bid_rejected.json b/exchange/exchangetest/bid_response_validation_enforce_one_bid_rejected.json
index f82b7a56c0f..f86cbbde377 100644
--- a/exchange/exchangetest/bid_response_validation_enforce_one_bid_rejected.json
+++ b/exchange/exchangetest/bid_response_validation_enforce_one_bid_rejected.json
@@ -211,7 +211,7 @@
"type": "banner",
"meta": {
"adaptercode":"appnexus"
- }
+ }
}
}
}
diff --git a/exchange/seat_non_bids.go b/exchange/seat_non_bids.go
deleted file mode 100644
index ee990105c1d..00000000000
--- a/exchange/seat_non_bids.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package exchange
-
-import (
- "github.com/prebid/prebid-server/v2/exchange/entities"
- "github.com/prebid/prebid-server/v2/openrtb_ext"
-)
-
-type nonBids struct {
- seatNonBidsMap map[string][]openrtb_ext.NonBid
-}
-
-// addBid is not thread safe as we are initializing and writing to map
-func (snb *nonBids) addBid(bid *entities.PbsOrtbBid, nonBidReason int, seat string) {
- if bid == nil || bid.Bid == nil {
- return
- }
- if snb.seatNonBidsMap == nil {
- snb.seatNonBidsMap = make(map[string][]openrtb_ext.NonBid)
- }
- if bid.BidMeta == nil {
- bid.BidMeta = &openrtb_ext.ExtBidPrebidMeta{}
- }
- adapterCode := seat
- if bid.AlternateBidderCode != "" {
- adapterCode = string(openrtb_ext.BidderName(bid.AlternateBidderCode))
- }
- bid.BidMeta.AdapterCode = adapterCode
-
- nonBid := openrtb_ext.NonBid{
- ImpId: bid.Bid.ImpID,
- StatusCode: nonBidReason,
- Ext: openrtb_ext.NonBidExt{
- Prebid: openrtb_ext.ExtResponseNonBidPrebid{Bid: openrtb_ext.NonBidObject{
- Price: bid.Bid.Price,
- ADomain: bid.Bid.ADomain,
- CatTax: bid.Bid.CatTax,
- Cat: bid.Bid.Cat,
- DealID: bid.Bid.DealID,
- W: bid.Bid.W,
- H: bid.Bid.H,
- Dur: bid.Bid.Dur,
- MType: bid.Bid.MType,
- OriginalBidCPM: bid.OriginalBidCPM,
- OriginalBidCur: bid.OriginalBidCur,
-
- //OW specific
- ID: bid.Bid.ID,
- DealPriority: bid.DealPriority,
- DealTierSatisfied: bid.DealTierSatisfied,
- Meta: bid.BidMeta,
- Targeting: bid.BidTargets,
- Type: bid.BidType,
- Video: bid.BidVideo,
- BidId: bid.GeneratedBidID,
- Floors: bid.BidFloors,
- OriginalBidCPMUSD: bid.OriginalBidCPMUSD,
- }},
- },
- }
-
- snb.seatNonBidsMap[seat] = append(snb.seatNonBidsMap[seat], nonBid)
-}
-
-func (snb *nonBids) get() []openrtb_ext.SeatNonBid {
- if snb == nil {
- return nil
- }
- var seatNonBid []openrtb_ext.SeatNonBid
- for seat, nonBids := range snb.seatNonBidsMap {
- seatNonBid = append(seatNonBid, openrtb_ext.SeatNonBid{
- Seat: seat,
- NonBid: nonBids,
- })
- }
- return seatNonBid
-}
diff --git a/exchange/seat_non_bids_test.go b/exchange/seat_non_bids_test.go
deleted file mode 100644
index 4436716ce42..00000000000
--- a/exchange/seat_non_bids_test.go
+++ /dev/null
@@ -1,116 +0,0 @@
-package exchange
-
-import (
- "testing"
-
- "github.com/prebid/openrtb/v20/openrtb2"
- "github.com/prebid/prebid-server/v2/exchange/entities"
- "github.com/prebid/prebid-server/v2/openrtb_ext"
- "github.com/stretchr/testify/assert"
-)
-
-func TestSeatNonBidsAdd(t *testing.T) {
- type fields struct {
- seatNonBidsMap map[string][]openrtb_ext.NonBid
- }
- type args struct {
- bid *entities.PbsOrtbBid
- nonBidReason int
- seat string
- }
- tests := []struct {
- name string
- fields fields
- args args
- want map[string][]openrtb_ext.NonBid
- }{
- {
- name: "nil-seatNonBidsMap",
- fields: fields{seatNonBidsMap: nil},
- args: args{},
- want: nil,
- },
- {
- name: "nil-seatNonBidsMap-with-bid-object",
- fields: fields{seatNonBidsMap: nil},
- args: args{bid: &entities.PbsOrtbBid{Bid: &openrtb2.Bid{}}, seat: "bidder1"},
- want: sampleSeatNonBidMap("bidder1", 1),
- },
- {
- name: "multiple-nonbids-for-same-seat",
- fields: fields{seatNonBidsMap: sampleSeatNonBidMap("bidder2", 1)},
- args: args{bid: &entities.PbsOrtbBid{Bid: &openrtb2.Bid{}}, seat: "bidder2"},
- want: sampleSeatNonBidMap("bidder2", 2),
- },
- {
- name: "multiple-nonbids-without-meta",
- fields: fields{seatNonBidsMap: sampleSeatNonBidMap("bidder2", 1)},
- args: args{bid: &entities.PbsOrtbBid{Bid: &openrtb2.Bid{}}, seat: "bidder2"},
- want: sampleSeatNonBidMap("bidder2", 2),
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- snb := &nonBids{
- seatNonBidsMap: tt.fields.seatNonBidsMap,
- }
- snb.addBid(tt.args.bid, tt.args.nonBidReason, tt.args.seat)
- assert.Equalf(t, tt.want, snb.seatNonBidsMap, "expected seatNonBidsMap not nil")
- })
- }
-}
-
-func TestSeatNonBidsGet(t *testing.T) {
- type fields struct {
- snb *nonBids
- }
- tests := []struct {
- name string
- fields fields
- want []openrtb_ext.SeatNonBid
- }{
- {
- name: "get-seat-nonbids",
- fields: fields{&nonBids{sampleSeatNonBidMap("bidder1", 2)}},
- want: sampleSeatBids("bidder1", 2),
- },
- {
- name: "nil-seat-nonbids",
- fields: fields{nil},
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- if got := tt.fields.snb.get(); !assert.Equal(t, tt.want, got) {
- t.Errorf("seatNonBids.get() = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-var sampleSeatNonBidMap = func(seat string, nonBidCount int) map[string][]openrtb_ext.NonBid {
- nonBids := make([]openrtb_ext.NonBid, 0)
- for i := 0; i < nonBidCount; i++ {
- nonBids = append(nonBids, openrtb_ext.NonBid{
- Ext: openrtb_ext.NonBidExt{Prebid: openrtb_ext.ExtResponseNonBidPrebid{Bid: openrtb_ext.NonBidObject{Meta: &openrtb_ext.ExtBidPrebidMeta{AdapterCode: seat}}}},
- })
- }
- return map[string][]openrtb_ext.NonBid{
- seat: nonBids,
- }
-}
-
-var sampleSeatBids = func(seat string, nonBidCount int) []openrtb_ext.SeatNonBid {
- seatNonBids := make([]openrtb_ext.SeatNonBid, 0)
- seatNonBid := openrtb_ext.SeatNonBid{
- Seat: seat,
- NonBid: make([]openrtb_ext.NonBid, 0),
- }
- for i := 0; i < nonBidCount; i++ {
- seatNonBid.NonBid = append(seatNonBid.NonBid, openrtb_ext.NonBid{
- Ext: openrtb_ext.NonBidExt{Prebid: openrtb_ext.ExtResponseNonBidPrebid{Bid: openrtb_ext.NonBidObject{Meta: &openrtb_ext.ExtBidPrebidMeta{AdapterCode: seat}}}},
- })
- }
- seatNonBids = append(seatNonBids, seatNonBid)
- return seatNonBids
-}
diff --git a/floors/fetcher.go b/floors/fetcher.go
index 5ed96b9ec36..1c87f095777 100644
--- a/floors/fetcher.go
+++ b/floors/fetcher.go
@@ -233,6 +233,7 @@ func (f *PriceFloorFetcher) Fetcher() {
func (f *PriceFloorFetcher) fetchAndValidate(config config.AccountFloorFetch) (*openrtb_ext.PriceFloorRules, int) {
floorResp, maxAge, err := f.fetchFloorRulesFromURL(config)
if floorResp == nil || err != nil {
+ f.metricEngine.RecordFloorStatus(config.AccountID, openrtb_ext.FetchLocation, fetchFailure)
glog.Errorf("Error while fetching floor data from URL: %s, reason : %s", config.URL, err.Error())
return nil, 0
}
@@ -244,11 +245,13 @@ func (f *PriceFloorFetcher) fetchAndValidate(config config.AccountFloorFetch) (*
var priceFloors openrtb_ext.PriceFloorRules
if err = json.Unmarshal(floorResp, &priceFloors.Data); err != nil {
+ f.metricEngine.RecordFloorStatus(config.AccountID, openrtb_ext.FetchLocation, unmarshalFailure)
glog.Errorf("Recieved invalid price floor json from URL: %s", config.URL)
return nil, 0
}
if err := validateRules(config, &priceFloors); err != nil {
+ f.metricEngine.RecordFloorStatus(config.AccountID, openrtb_ext.FetchLocation, invalidFloors)
glog.Errorf("Validation failed for floor JSON from URL: %s, reason: %s", config.URL, err.Error())
return nil, 0
}
diff --git a/floors/fetcher_test.go b/floors/fetcher_test.go
index cdf0537c9ed..ce29e905e14 100644
--- a/floors/fetcher_test.go
+++ b/floors/fetcher_test.go
@@ -12,8 +12,10 @@ import (
"github.com/alitto/pond"
"github.com/coocood/freecache"
+ "github.com/golang/mock/gomock"
"github.com/prebid/prebid-server/v2/config"
"github.com/prebid/prebid-server/v2/metrics"
+
metricsConf "github.com/prebid/prebid-server/v2/metrics/config"
"github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/prebid/prebid-server/v2/util/ptrutil"
@@ -628,6 +630,11 @@ func TestFetchFloorRulesFromURLInvalidMaxAge(t *testing.T) {
}
func TestFetchAndValidate(t *testing.T) {
+
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+ me := &metrics.MetricsEngineMock{}
+
mockHandler := func(mockResponse []byte, mockStatus int) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Add(MaxAge, "30")
@@ -646,6 +653,7 @@ func TestFetchAndValidate(t *testing.T) {
responseStatus int
want *openrtb_ext.PriceFloorRules
want1 int
+ setup func()
}{
{
name: "Recieved valid price floor rules response",
@@ -676,6 +684,7 @@ func TestFetchAndValidate(t *testing.T) {
name: "No response from server",
args: args{
configs: config.AccountFloorFetch{
+ AccountID: "5890",
Enabled: true,
Timeout: 30,
MaxFileSizeKB: 700,
@@ -688,6 +697,9 @@ func TestFetchAndValidate(t *testing.T) {
responseStatus: 500,
want: nil,
want1: 0,
+ setup: func() {
+ me.On("RecordFloorStatus", "5890", "fetch", "1").Return()
+ },
},
{
name: "File is greater than MaxFileSize",
@@ -713,6 +725,7 @@ func TestFetchAndValidate(t *testing.T) {
name: "Malformed response : json unmarshalling failed",
args: args{
configs: config.AccountFloorFetch{
+ AccountID: "5890",
Enabled: true,
Timeout: 30,
MaxFileSizeKB: 800,
@@ -728,11 +741,15 @@ func TestFetchAndValidate(t *testing.T) {
responseStatus: 200,
want: nil,
want1: 0,
+ setup: func() {
+ me.On("RecordFloorStatus", "5890", "fetch", "2").Return()
+ },
},
{
name: "Validations failed for price floor rules response",
args: args{
configs: config.AccountFloorFetch{
+ AccountID: "5890",
Enabled: true,
Timeout: 30,
MaxFileSizeKB: 700,
@@ -748,14 +765,21 @@ func TestFetchAndValidate(t *testing.T) {
responseStatus: 200,
want: nil,
want1: 0,
+ setup: func() {
+ me.On("RecordFloorStatus", "5890", "fetch", "3").Return()
+ },
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
+ if tt.setup != nil {
+ tt.setup()
+ }
mockHttpServer := httptest.NewServer(mockHandler(tt.response, tt.responseStatus))
defer mockHttpServer.Close()
ppf := PriceFloorFetcher{
- httpClient: mockHttpServer.Client(),
+ httpClient: mockHttpServer.Client(),
+ metricEngine: &metricsConf.NilMetricsEngine{},
}
tt.args.configs.URL = mockHttpServer.URL
got, got1 := ppf.fetchAndValidate(tt.args.configs)
diff --git a/floors/floors.go b/floors/floors.go
index 12642d6917f..bce6ddcef6d 100644
--- a/floors/floors.go
+++ b/floors/floors.go
@@ -8,6 +8,7 @@ import (
"github.com/prebid/prebid-server/v2/config"
"github.com/prebid/prebid-server/v2/currency"
+ "github.com/prebid/prebid-server/v2/metrics"
"github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/prebid/prebid-server/v2/util/ptrutil"
)
@@ -32,9 +33,20 @@ const (
floorPrecision float64 = 0.01
)
+const (
+ fetchFailure = "1"
+ unmarshalFailure = "2"
+ invalidFloors = "3"
+ floorsSkipped = "4"
+ zeroFloorValue = "5"
+ highFloorValue = "6"
+ ZERO_FLOOR_VALUE = 0
+ HIGH_FLOOR_VALUE = 200
+)
+
// EnrichWithPriceFloors checks for floors enabled in account and request and selects floors data from dynamic fetched if present
// else selects floors data from req.ext.prebid.floors and update request with selected floors details
-func EnrichWithPriceFloors(bidRequestWrapper *openrtb_ext.RequestWrapper, account config.Account, conversions currency.Conversions, priceFloorFetcher FloorFetcher) []error {
+func EnrichWithPriceFloors(bidRequestWrapper *openrtb_ext.RequestWrapper, account config.Account, conversions currency.Conversions, priceFloorFetcher FloorFetcher, metricsEngine metrics.MetricsEngine) []error {
if bidRequestWrapper == nil || bidRequestWrapper.BidRequest == nil {
return []error{errors.New("Empty bidrequest")}
}
@@ -42,16 +54,15 @@ func EnrichWithPriceFloors(bidRequestWrapper *openrtb_ext.RequestWrapper, accoun
if !isPriceFloorsEnabled(account, bidRequestWrapper) {
return []error{errors.New("Floors feature is disabled at account or in the request")}
}
+ floors, err := resolveFloors(account, bidRequestWrapper, conversions, priceFloorFetcher, metricsEngine)
- floors, err := resolveFloors(account, bidRequestWrapper, conversions, priceFloorFetcher)
-
- updateReqErrs := updateBidRequestWithFloors(floors, bidRequestWrapper, conversions)
+ updateReqErrs := updateBidRequestWithFloors(floors, bidRequestWrapper, conversions, metricsEngine, account.ID)
updateFloorsInRequest(bidRequestWrapper, floors)
return append(err, updateReqErrs...)
}
// updateBidRequestWithFloors will update imp.bidfloor and imp.bidfloorcur based on rules matching
-func updateBidRequestWithFloors(extFloorRules *openrtb_ext.PriceFloorRules, request *openrtb_ext.RequestWrapper, conversions currency.Conversions) []error {
+func updateBidRequestWithFloors(extFloorRules *openrtb_ext.PriceFloorRules, request *openrtb_ext.RequestWrapper, conversions currency.Conversions, metricEngine metrics.MetricsEngine, accountID string) []error {
var (
floorErrList []error
floorVal float64
@@ -69,6 +80,7 @@ func updateBidRequestWithFloors(extFloorRules *openrtb_ext.PriceFloorRules, requ
extFloorRules.Skipped = new(bool)
if shouldSkipFloors(modelGroup.SkipRate, extFloorRules.Data.SkipRate, extFloorRules.SkipRate, rand.Intn) {
*extFloorRules.Skipped = true
+ metricEngine.RecordFloorStatus(accountID, extFloorRules.PriceFloorLocation, floorsSkipped)
return []error{}
}
@@ -94,7 +106,12 @@ func updateBidRequestWithFloors(extFloorRules *openrtb_ext.PriceFloorRules, requ
if floorMinVal > 0.0 && floorVal < floorMinVal {
bidFloor = floorMinVal
}
-
+ if bidFloor < ZERO_FLOOR_VALUE {
+ metricEngine.RecordFloorStatus(accountID, extFloorRules.PriceFloorLocation, zeroFloorValue)
+ }
+ if bidFloor > HIGH_FLOOR_VALUE {
+ metricEngine.RecordFloorStatus(accountID, extFloorRules.PriceFloorLocation, highFloorValue)
+ }
imp.BidFloor = bidFloor
imp.BidFloorCur = floorCur
@@ -146,7 +163,7 @@ func useFetchedData(rate *int) bool {
}
// resolveFloors does selection of floors fields from request data and dynamic fetched data if dynamic fetch is enabled
-func resolveFloors(account config.Account, bidRequestWrapper *openrtb_ext.RequestWrapper, conversions currency.Conversions, priceFloorFetcher FloorFetcher) (*openrtb_ext.PriceFloorRules, []error) {
+func resolveFloors(account config.Account, bidRequestWrapper *openrtb_ext.RequestWrapper, conversions currency.Conversions, priceFloorFetcher FloorFetcher, metricsEngine metrics.MetricsEngine) (*openrtb_ext.PriceFloorRules, []error) {
var (
errList []error
floorRules *openrtb_ext.PriceFloorRules
@@ -166,17 +183,17 @@ func resolveFloors(account config.Account, bidRequestWrapper *openrtb_ext.Reques
if fetchResult != nil && fetchStatus == openrtb_ext.FetchSuccess && useFetchedData(fetchResult.Data.FetchRate) {
mergedFloor := mergeFloors(reqFloor, fetchResult, conversions)
- floorRules, errList = createFloorsFrom(mergedFloor, account, fetchStatus, openrtb_ext.FetchLocation)
+ floorRules, errList = createFloorsFrom(mergedFloor, account, fetchStatus, openrtb_ext.FetchLocation, metricsEngine)
} else if reqFloor != nil {
- floorRules, errList = createFloorsFrom(reqFloor, account, fetchStatus, openrtb_ext.RequestLocation)
+ floorRules, errList = createFloorsFrom(reqFloor, account, fetchStatus, openrtb_ext.RequestLocation, metricsEngine)
} else {
- floorRules, errList = createFloorsFrom(nil, account, fetchStatus, openrtb_ext.NoDataLocation)
+ floorRules, errList = createFloorsFrom(nil, account, fetchStatus, openrtb_ext.NoDataLocation, metricsEngine)
}
return floorRules, errList
}
// createFloorsFrom does preparation of floors data which shall be used for further processing
-func createFloorsFrom(floors *openrtb_ext.PriceFloorRules, account config.Account, fetchStatus, floorLocation string) (*openrtb_ext.PriceFloorRules, []error) {
+func createFloorsFrom(floors *openrtb_ext.PriceFloorRules, account config.Account, fetchStatus, floorLocation string, metricsEngine metrics.MetricsEngine) (*openrtb_ext.PriceFloorRules, []error) {
var floorModelErrList []error
finalFloors := &openrtb_ext.PriceFloorRules{
FetchStatus: fetchStatus,
@@ -186,12 +203,16 @@ func createFloorsFrom(floors *openrtb_ext.PriceFloorRules, account config.Accoun
if floors != nil {
floorValidationErr := validateFloorParams(floors)
if floorValidationErr != nil {
+ metricsEngine.RecordFloorStatus(account.ID, floorLocation, invalidFloors)
return finalFloors, append(floorModelErrList, floorValidationErr)
}
finalFloors.Enforcement = floors.Enforcement
if floors.Data != nil {
validModelGroups, floorModelErrList := selectValidFloorModelGroups(floors.Data.ModelGroups, account)
+ if len(floorModelErrList) > 0 {
+ metricsEngine.RecordFloorStatus(account.ID, floorLocation, invalidFloors)
+ }
if len(validModelGroups) == 0 {
return finalFloors, floorModelErrList
} else {
diff --git a/floors/floors_test.go b/floors/floors_test.go
index f065d2ac84e..4d8786a555f 100644
--- a/floors/floors_test.go
+++ b/floors/floors_test.go
@@ -6,9 +6,12 @@ import (
"reflect"
"testing"
+ "github.com/golang/mock/gomock"
"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/config"
"github.com/prebid/prebid-server/v2/currency"
+ "github.com/prebid/prebid-server/v2/metrics"
+ metricsConf "github.com/prebid/prebid-server/v2/metrics/config"
"github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/prebid/prebid-server/v2/util/jsonutil"
"github.com/prebid/prebid-server/v2/util/ptrutil"
@@ -375,7 +378,7 @@ func TestEnrichWithPriceFloors(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
- ErrList := EnrichWithPriceFloors(tc.bidRequestWrapper, tc.account, getCurrencyRates(rates), &mockPriceFloorFetcher{})
+ ErrList := EnrichWithPriceFloors(tc.bidRequestWrapper, tc.account, getCurrencyRates(rates), &mockPriceFloorFetcher{}, &metricsConf.NilMetricsEngine{})
if tc.bidRequestWrapper != nil {
assert.Equal(t, tc.bidRequestWrapper.Imp[0].BidFloor, tc.expFloorVal, tc.name)
assert.Equal(t, tc.bidRequestWrapper.Imp[0].BidFloorCur, tc.expFloorCur, tc.name)
@@ -635,7 +638,7 @@ func TestResolveFloors(t *testing.T) {
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
- resolvedFloors, _ := resolveFloors(tc.account, tc.bidRequestWrapper, getCurrencyRates(rates), &MockFetch{})
+ resolvedFloors, _ := resolveFloors(tc.account, tc.bidRequestWrapper, getCurrencyRates(rates), &MockFetch{}, &metricsConf.NilMetricsEngine{})
if !reflect.DeepEqual(resolvedFloors, tc.expFloors) {
t.Errorf("resolveFloors error: \nreturn:\t%v\nwant:\t%v", printFloors(resolvedFloors), printFloors(tc.expFloors))
}
@@ -872,7 +875,7 @@ func TestResolveFloorsWithUseDataRate(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
- resolvedFloors, _ := resolveFloors(tc.account, tc.bidRequestWrapper, getCurrencyRates(rates), tc.fetcher)
+ resolvedFloors, _ := resolveFloors(tc.account, tc.bidRequestWrapper, getCurrencyRates(rates), tc.fetcher, &metricsConf.NilMetricsEngine{})
assert.Equal(t, resolvedFloors, tc.expFloors, tc.name)
})
}
@@ -1004,7 +1007,12 @@ func printFloors(floors *openrtb_ext.PriceFloorRules) string {
func TestCreateFloorsFrom(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+ me := &metrics.MetricsEngineMock{}
+
testAccountConfig := config.Account{
+ ID: "5890",
PriceFloors: config.AccountPriceFloors{
Enabled: true,
UseDynamicData: false,
@@ -1024,6 +1032,7 @@ func TestCreateFloorsFrom(t *testing.T) {
args args
want *openrtb_ext.PriceFloorRules
want1 []error
+ setup func()
}{
{
name: "floor provider should be selected from floor json",
@@ -1212,11 +1221,55 @@ func TestCreateFloorsFrom(t *testing.T) {
want1: []error{
errors.New("Invalid Floor Model = 'model from fetched' due to SkipRate = '110' is out of range (1-100)"),
},
+ setup: func() {
+ me.On("RecordFloorStatus", "5890", "request", "3").Return()
+ },
+ },
+ {
+ name: "Invalid floors",
+ args: args{
+ account: testAccountConfig,
+ floors: &openrtb_ext.PriceFloorRules{
+ FloorMin: -1,
+ Enabled: getTrue(),
+ Data: &openrtb_ext.PriceFloorData{
+ Currency: "USD",
+ ModelGroups: []openrtb_ext.PriceFloorModelGroup{
+ {
+ ModelVersion: "model from fetched",
+ Currency: "USD",
+ Values: map[string]float64{
+ "banner|300x600|www.website5.com": 15,
+ "*|*|*": 25,
+ },
+ Schema: openrtb_ext.PriceFloorSchema{
+ Fields: []string{"mediaType", "size", "domain"},
+ },
+ },
+ },
+ },
+ },
+ fetchStatus: openrtb_ext.FetchNone,
+ floorLocation: openrtb_ext.RequestLocation,
+ },
+ want: &openrtb_ext.PriceFloorRules{
+ FetchStatus: openrtb_ext.FetchNone,
+ PriceFloorLocation: openrtb_ext.RequestLocation,
+ },
+ want1: []error{
+ errors.New("Invalid FloorMin = '-1', value should be >= 0"),
+ },
+ setup: func() {
+ me.On("RecordFloorStatus", "5890", "request", "3").Return()
+ },
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
- got, got1 := createFloorsFrom(tc.args.floors, tc.args.account, tc.args.fetchStatus, tc.args.floorLocation)
+ if tc.setup != nil {
+ tc.setup()
+ }
+ got, got1 := createFloorsFrom(tc.args.floors, tc.args.account, tc.args.fetchStatus, tc.args.floorLocation, me)
assert.Equal(t, got1, tc.want1, tc.name)
assert.Equal(t, got, tc.want, tc.name)
})
@@ -1890,3 +1943,259 @@ func TestMergeFloors(t *testing.T) {
})
}
}
+
+func TestUpdateBidRequestWithFloors(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+ me := &metrics.MetricsEngineMock{}
+
+ type args struct {
+ extFloorRules *openrtb_ext.PriceFloorRules
+ request *openrtb_ext.RequestWrapper
+ conversions currency.Conversions
+ metricEngine metrics.MetricsEngine
+ accountID string
+ }
+
+ tests := []struct {
+ name string
+ args args
+ setup func()
+ }{
+
+ {
+ name: "test record floor status with no failures",
+ args: args{
+ extFloorRules: &openrtb_ext.PriceFloorRules{
+ Enabled: getTrue(),
+ FloorMin: 5,
+ FloorMinCur: "USD",
+ PriceFloorLocation: openrtb_ext.RequestLocation,
+ Enforcement: &openrtb_ext.PriceFloorEnforcement{
+ EnforcePBS: getTrue(),
+ EnforceRate: 100,
+ FloorDeals: getTrue(),
+ },
+
+ Data: &openrtb_ext.PriceFloorData{
+ Currency: "USD",
+ ModelGroups: []openrtb_ext.PriceFloorModelGroup{
+ {
+ ModelVersion: "model 1 from req",
+ Currency: "USD",
+ Values: map[string]float64{
+ "banner|300x600|www.website5.com": 5,
+ "*|*|*": 7,
+ },
+ Schema: openrtb_ext.PriceFloorSchema{
+ Fields: []string{"mediaType", "size", "domain"},
+ Delimiter: "|",
+ },
+ },
+ },
+ }},
+ request: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Site: &openrtb2.Site{
+ Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
+ },
+ Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
+ Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x600|www.website5.com":5,"*|*|*":0},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
+ },
+ },
+ accountID: "5890",
+ },
+ },
+ {
+ name: "test record floor status with skiprate 100",
+ args: args{
+ extFloorRules: &openrtb_ext.PriceFloorRules{
+ Enabled: getTrue(),
+ FloorMin: 5,
+ FloorMinCur: "USD",
+ SkipRate: 100,
+ PriceFloorLocation: openrtb_ext.RequestLocation,
+ Enforcement: &openrtb_ext.PriceFloorEnforcement{
+ EnforcePBS: getTrue(),
+ EnforceRate: 100,
+ FloorDeals: getTrue(),
+ },
+
+ Data: &openrtb_ext.PriceFloorData{
+ Currency: "USD",
+ ModelGroups: []openrtb_ext.PriceFloorModelGroup{
+ {
+ ModelVersion: "model 1 from req",
+ Currency: "USD",
+ Values: map[string]float64{
+ "banner|300x600|www.website5.com": 5,
+ "*|*|*": 7,
+ },
+ Schema: openrtb_ext.PriceFloorSchema{
+ Fields: []string{"mediaType", "size", "domain"},
+ Delimiter: "|",
+ },
+ },
+ },
+ }},
+ request: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Site: &openrtb2.Site{
+ Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
+ },
+ Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
+ Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x600|www.website5.com":5,"*|*|*":0},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
+ },
+ },
+ accountID: "5890",
+ },
+ setup: func() {
+ me.On("RecordFloorStatus", "5890", "request", "4").Return()
+ },
+ },
+ {
+ name: "test record floor status with negative floor value, rule matched",
+ args: args{
+ extFloorRules: &openrtb_ext.PriceFloorRules{
+ Enabled: getTrue(),
+ FloorMinCur: "USD",
+ PriceFloorLocation: openrtb_ext.RequestLocation,
+ Enforcement: &openrtb_ext.PriceFloorEnforcement{
+ EnforcePBS: getTrue(),
+ EnforceRate: 100,
+ FloorDeals: getTrue(),
+ },
+
+ Data: &openrtb_ext.PriceFloorData{
+ Currency: "USD",
+ ModelGroups: []openrtb_ext.PriceFloorModelGroup{
+ {
+ ModelVersion: "model 1 from req",
+ Currency: "USD",
+ Values: map[string]float64{
+ "banner|300x600|www.website5.com": 5,
+ "*|*|*": -7,
+ },
+ Schema: openrtb_ext.PriceFloorSchema{
+ Fields: []string{"mediaType", "size", "domain"},
+ Delimiter: "|",
+ },
+ },
+ },
+ }},
+ request: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Site: &openrtb2.Site{
+ Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
+ },
+ Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
+ Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x600|www.website5.com":5,"*|*|*":0},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
+ },
+ },
+ accountID: "5890",
+ },
+
+ setup: func() {
+ me.On("RecordFloorStatus", "5890", "request", "5").Return()
+ },
+ },
+ {
+ name: "test record floor status with high floor value, rule matched",
+ args: args{
+ extFloorRules: &openrtb_ext.PriceFloorRules{
+ Enabled: getTrue(),
+ FloorMinCur: "USD",
+ PriceFloorLocation: openrtb_ext.RequestLocation,
+ Enforcement: &openrtb_ext.PriceFloorEnforcement{
+ EnforcePBS: getTrue(),
+ EnforceRate: 100,
+ FloorDeals: getTrue(),
+ },
+
+ Data: &openrtb_ext.PriceFloorData{
+ Currency: "USD",
+ ModelGroups: []openrtb_ext.PriceFloorModelGroup{
+ {
+ ModelVersion: "model 1 from req",
+ Currency: "USD",
+ Values: map[string]float64{
+ "banner|300x600|www.website5.com": 5,
+ "*|*|*": 201,
+ },
+ Schema: openrtb_ext.PriceFloorSchema{
+ Fields: []string{"mediaType", "size", "domain"},
+ Delimiter: "|",
+ },
+ },
+ },
+ }},
+ request: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Site: &openrtb2.Site{
+ Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
+ },
+ Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
+ Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x600|www.website5.com":5,"*|*|*":0},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
+ },
+ },
+ accountID: "5890",
+ },
+
+ setup: func() {
+ me.On("RecordFloorStatus", "5890", "request", "6").Return()
+ },
+ },
+ {
+ name: "test record floor status with high floor value ih the request, rule not matched",
+ args: args{
+ extFloorRules: &openrtb_ext.PriceFloorRules{
+ Enabled: getTrue(),
+ FloorMin: 201,
+ FloorMinCur: "USD",
+ PriceFloorLocation: openrtb_ext.RequestLocation,
+ Enforcement: &openrtb_ext.PriceFloorEnforcement{
+ EnforcePBS: getTrue(),
+ EnforceRate: 100,
+ FloorDeals: getTrue(),
+ },
+
+ Data: &openrtb_ext.PriceFloorData{
+ Currency: "USD",
+ ModelGroups: []openrtb_ext.PriceFloorModelGroup{
+ {
+ ModelVersion: "model 1 from req",
+ Currency: "USD",
+ Values: map[string]float64{
+ "banner|300x600|www.website5.com": 5,
+ "*|*|*": 201,
+ },
+ Schema: openrtb_ext.PriceFloorSchema{
+ Fields: []string{"mediaType", "size", "domain"},
+ Delimiter: "|",
+ },
+ },
+ },
+ }},
+ request: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Site: &openrtb2.Site{
+ Publisher: &openrtb2.Publisher{Domain: "www.website.com"},
+ },
+ Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}},
+ Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x600|www.website5.com":5,"*|*|*":0},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`),
+ },
+ },
+ accountID: "5890",
+ },
+ setup: func() {
+ me.On("RecordFloorStatus", "5890", "request", "6").Return()
+ },
+ },
+ }
+ for _, test := range tests {
+ if test.setup != nil {
+ test.setup()
+ }
+ updateBidRequestWithFloors(test.args.extFloorRules, test.args.request, test.args.conversions, me, test.args.accountID)
+ }
+}
diff --git a/hooks/hookexecution/enricher_test.go b/hooks/hookexecution/enricher_test.go
index 4f962dea279..95da909c1f7 100644
--- a/hooks/hookexecution/enricher_test.go
+++ b/hooks/hookexecution/enricher_test.go
@@ -31,14 +31,15 @@ type GroupOutcomeTest struct {
type HookOutcomeTest struct {
ExecutionTime
- AnalyticsTags hookanalytics.Analytics `json:"analytics_tags"`
- HookID HookID `json:"hook_id"`
- Status Status `json:"status"`
- Action Action `json:"action"`
- Message string `json:"message"`
- DebugMessages []string `json:"debug_messages"`
- Errors []string `json:"errors"`
- Warnings []string `json:"warnings"`
+ AnalyticsTags hookanalytics.Analytics `json:"analytics_tags"`
+ HookID HookID `json:"hook_id"`
+ Status Status `json:"status"`
+ Action Action `json:"action"`
+ Message string `json:"message"`
+ DebugMessages []string `json:"debug_messages"`
+ Errors []string `json:"errors"`
+ Warnings []string `json:"warnings"`
+ SeatNonBid openrtb_ext.NonBidCollection `json:"seatnonbid"`
}
func TestEnrichBidResponse(t *testing.T) {
diff --git a/hooks/hookexecution/execution.go b/hooks/hookexecution/execution.go
index 03500bb5f0e..6bdc2d09816 100644
--- a/hooks/hookexecution/execution.go
+++ b/hooks/hookexecution/execution.go
@@ -193,6 +193,7 @@ func handleHookResponse[P any](
Warnings: hr.Result.Warnings,
DebugMessages: hr.Result.DebugMessages,
AnalyticsTags: hr.Result.AnalyticsTags,
+ SeatNonBid: hr.Result.SeatNonBid,
ExecutionTime: ExecutionTime{ExecutionTimeMillis: hr.ExecutionTime},
}
diff --git a/hooks/hookexecution/executor.go b/hooks/hookexecution/executor.go
index a353e9000dc..0ba466acc8d 100644
--- a/hooks/hookexecution/executor.go
+++ b/hooks/hookexecution/executor.go
@@ -386,6 +386,6 @@ func (executor EmptyHookExecutor) ExecuteAllProcessedBidResponsesStage(_ map[ope
func (executor EmptyHookExecutor) ExecuteAuctionResponseStage(_ *openrtb2.BidResponse) {}
-func (executor *EmptyHookExecutor) ExecuteBeforeRequestValidationStage(_ *openrtb2.BidRequest) *RejectError {
+func (executor EmptyHookExecutor) ExecuteBeforeRequestValidationStage(_ *openrtb2.BidRequest) *RejectError {
return nil
}
diff --git a/hooks/hookexecution/outcome.go b/hooks/hookexecution/outcome.go
index ff8bf1e973e..fbfc03c5ac5 100644
--- a/hooks/hookexecution/outcome.go
+++ b/hooks/hookexecution/outcome.go
@@ -4,6 +4,7 @@ import (
"time"
"github.com/prebid/prebid-server/v2/hooks/hookanalytics"
+ "github.com/prebid/prebid-server/v2/openrtb_ext"
)
// Status indicates the result of hook execution.
@@ -77,14 +78,15 @@ type GroupOutcome struct {
type HookOutcome struct {
// ExecutionTime is the execution time of a specific hook without applying its result.
ExecutionTime
- AnalyticsTags hookanalytics.Analytics `json:"analytics_tags"`
- HookID HookID `json:"hook_id"`
- Status Status `json:"status"`
- Action Action `json:"action"`
- Message string `json:"message"` // arbitrary string value returned from hook execution
- DebugMessages []string `json:"debug_messages,omitempty"`
- Errors []string `json:"-"`
- Warnings []string `json:"-"`
+ AnalyticsTags hookanalytics.Analytics `json:"analytics_tags"`
+ HookID HookID `json:"hook_id"`
+ Status Status `json:"status"`
+ Action Action `json:"action"`
+ Message string `json:"message"` // arbitrary string value returned from hook execution
+ DebugMessages []string `json:"debug_messages,omitempty"`
+ Errors []string `json:"-"`
+ Warnings []string `json:"-"`
+ SeatNonBid openrtb_ext.NonBidCollection `json:"-"`
}
// HookID points to the specific hook defined by the hook execution plan.
diff --git a/hooks/hookstage/invocation.go b/hooks/hookstage/invocation.go
index d6adb506066..5254cfbae36 100644
--- a/hooks/hookstage/invocation.go
+++ b/hooks/hookstage/invocation.go
@@ -4,6 +4,7 @@ import (
"encoding/json"
"github.com/prebid/prebid-server/v2/hooks/hookanalytics"
+ "github.com/prebid/prebid-server/v2/openrtb_ext"
)
// HookResult represents the result of execution the concrete hook instance.
@@ -16,7 +17,8 @@ type HookResult[T any] struct {
Warnings []string
DebugMessages []string
AnalyticsTags hookanalytics.Analytics
- ModuleContext ModuleContext // holds values that the module wants to pass to itself at later stages
+ ModuleContext ModuleContext // holds values that the module wants to pass to itself at later stages
+ SeatNonBid openrtb_ext.NonBidCollection // holds list of seatnonbid rejected by hook
}
// ModuleInvocationContext holds data passed to the module hook during invocation.
diff --git a/metrics/config/metrics_ow.go b/metrics/config/metrics_ow.go
index 62a950438cd..558530a4aa3 100644
--- a/metrics/config/metrics_ow.go
+++ b/metrics/config/metrics_ow.go
@@ -39,8 +39,6 @@ func (me *MultiMetricsEngine) RecordBids(pubid, profileid, biddder, deal string)
thisME.RecordBids(pubid, profileid, biddder, deal)
}
}
-func (me *MultiMetricsEngine) RecordHttpCounter() {
-}
func (me *MultiMetricsEngine) RecordVastVersion(biddder, vastVersion string) {
for _, thisME := range *me {
@@ -55,10 +53,10 @@ func (me *MultiMetricsEngine) RecordRejectedBidsForBidder(bidder openrtb_ext.Bid
}
}
-// RecordDynamicFetchFailure across all engines
-func (me *MultiMetricsEngine) RecordDynamicFetchFailure(pubId, code string) {
+// RecordFloorStatus across all engines
+func (me *MultiMetricsEngine) RecordFloorStatus(pubId, source, code string) {
for _, thisME := range *me {
- thisME.RecordDynamicFetchFailure(pubId, code)
+ thisME.RecordFloorStatus(pubId, source, code)
}
}
@@ -66,8 +64,8 @@ func (me *MultiMetricsEngine) RecordDynamicFetchFailure(pubId, code string) {
func (me *NilMetricsEngine) RecordVASTTagType(biddder, vastTag string) {
}
-// RecordDynamicFetchFailure as a noop
-func (me *NilMetricsEngine) RecordDynamicFetchFailure(pubId, code string) {
+// RecordFloorStatus as a noop
+func (me *NilMetricsEngine) RecordFloorStatus(pubId, source, code string) {
}
// RecordRejectedBids as a noop
@@ -82,9 +80,6 @@ func (me *NilMetricsEngine) RecordBids(pubid, profileid, biddder, deal string) {
func (me *NilMetricsEngine) RecordVastVersion(biddder, vastVersion string) {
}
-func (m *NilMetricsEngine) RecordHttpCounter() {
-}
-
// RecordRejectedBidsForBidder as a noop
func (me *NilMetricsEngine) RecordRejectedBidsForBidder(bidder openrtb_ext.BidderName) {
}
diff --git a/metrics/go_metrics.go b/metrics/go_metrics.go
index e216c58bcb4..c104cc91cc1 100644
--- a/metrics/go_metrics.go
+++ b/metrics/go_metrics.go
@@ -650,8 +650,8 @@ func (me *Metrics) RecordRejectedBidsForAccount(pubId string) {
}
}
-// RecordDynamicFetchFailure implements a part of the MetricsEngine interface. Records dynamic fetch failure
-func (me *Metrics) RecordDynamicFetchFailure(pubId, code string) {
+// RecordFloorStatus implements a part of the MetricsEngine interface. Records dynamic fetch failure
+func (me *Metrics) RecordFloorStatus(pubId, source, code string) {
if pubId != PublisherUnknown {
me.getAccountMetrics(pubId).dynamicFetchFailureMeter.Mark(1)
}
diff --git a/metrics/go_metrics_ow.go b/metrics/go_metrics_ow.go
index e03a402ee7a..d3c04a7f2f2 100644
--- a/metrics/go_metrics_ow.go
+++ b/metrics/go_metrics_ow.go
@@ -38,9 +38,6 @@ func (me *Metrics) RecordBids(pubid, profileid, biddder, deal string) {
func (me *Metrics) RecordVastVersion(biddder, vastVersion string) {
}
-func (me *Metrics) RecordHttpCounter() {
-}
-
// RecordVASTTagType as a noop
func (me *Metrics) RecordVASTTagType(biddder, vastTag string) {
}
diff --git a/metrics/metrics.go b/metrics/metrics.go
index 682589f8e88..0a6be2cb0ef 100644
--- a/metrics/metrics.go
+++ b/metrics/metrics.go
@@ -519,8 +519,8 @@ type MetricsEngine interface {
//RecordAdapterVideoBidDuration records actual ad duration returned by the bidder
RecordAdapterVideoBidDuration(labels AdapterLabels, videoBidDuration int)
- //RecordDynamicFetchFailure records the dynamic fetch failure labeled by pubid and reason code
- RecordDynamicFetchFailure(pubId, code string)
+ //RecordFloorStatus records the floor validation status labeled by pubid, source and reason code
+ RecordFloorStatus(pubId, source, code string)
//RecordRejectedBids records the rejected bids labeled by pubid, bidder and reason code
RecordRejectedBids(pubid, bidder, code string)
diff --git a/metrics/metrics_mock.go b/metrics/metrics_mock.go
index 07e09db5f0a..0e5682a0ba2 100644
--- a/metrics/metrics_mock.go
+++ b/metrics/metrics_mock.go
@@ -238,9 +238,6 @@ func (me *MetricsEngineMock) RecordRejectedBids(pubid, bidder, code string) {
me.Called(pubid, bidder, code)
}
-func (me *MetricsEngineMock) RecordDynamicFetchFailure(pubId, code string) {
- me.Called(pubId, code)
-}
-
-func (me *MetricsEngineMock) RecordHttpCounter() {
+func (me *MetricsEngineMock) RecordFloorStatus(pubId, source, code string) {
+ me.Called(pubId, source, code)
}
diff --git a/metrics/metrics_ow.go b/metrics/metrics_ow.go
index 958394dd03d..2daa9d086df 100644
--- a/metrics/metrics_ow.go
+++ b/metrics/metrics_ow.go
@@ -1,7 +1,6 @@
package metrics
type OWMetricsEngine interface {
- RecordHttpCounter()
//RecordBids records the bidder deal bids labeled by pubid, profile, bidder and deal
RecordBids(pubid, profileid, bidder, deal string)
//RecordVastVersion record the count of vast version labelled by bidder and vast version
diff --git a/metrics/prometheus/prometheus_ow.go b/metrics/prometheus/prometheus_ow.go
index 789788a93ce..60211b3fd3a 100644
--- a/metrics/prometheus/prometheus_ow.go
+++ b/metrics/prometheus/prometheus_ow.go
@@ -45,16 +45,6 @@ type OWMetrics struct {
// podCompExclTimer indicates time taken by compititve exclusion
// algorithm to generate final pod response based on bid response and ad pod request
podCompExclTimer *prometheus.HistogramVec
- httpCounter prometheus.Counter
-}
-
-func newHttpCounter(cfg config.PrometheusMetrics, registry *prometheus.Registry) prometheus.Counter {
- httpCounter := prometheus.NewCounter(prometheus.CounterOpts{
- Name: "http_requests_total",
- Help: "Number of http requests.",
- })
- registry.MustRegister(httpCounter)
- return httpCounter
}
// RecordAdapterDuplicateBidID captures the bid.ID collisions when adaptor
@@ -170,21 +160,17 @@ func (m *Metrics) RecordFloorsRequestForAccount(pubId string) {
}).Inc()
}
}
-func (m *Metrics) RecordDynamicFetchFailure(pubId, code string) {
+func (m *Metrics) RecordFloorStatus(pubId, source, code string) {
if pubId != metrics.PublisherUnknown {
m.dynamicFetchFailure.With(prometheus.Labels{
accountLabel: pubId,
+ sourceLabel: source,
codeLabel: code,
}).Inc()
}
}
-func (m *Metrics) RecordHttpCounter() {
- m.httpCounter.Inc()
-}
-
func (m *OWMetrics) init(cfg config.PrometheusMetrics, reg *prometheus.Registry) {
- m.httpCounter = newHttpCounter(cfg, reg)
m.rejectedBids = newCounter(cfg, reg,
"rejected_bids",
"Count of rejected bids by publisher id, bidder and rejection reason code",
@@ -201,9 +187,9 @@ func (m *OWMetrics) init(cfg config.PrometheusMetrics, reg *prometheus.Registry)
[]string{bidderLabel, vastTagTypeLabel})
m.dynamicFetchFailure = newCounter(cfg, reg,
- "floors_account_fetch_err",
- "Count of failures in case of dynamic fetch labeled by account",
- []string{codeLabel, accountLabel})
+ "floors_account_status",
+ "Count of floor validation status labeled by account, source and reason code",
+ []string{accountLabel, codeLabel, sourceLabel})
m.adapterDuplicateBidIDCounter = newCounter(cfg, reg,
"duplicate_bid_ids",
diff --git a/metrics/prometheus/prometheus_ow_test.go b/metrics/prometheus/prometheus_ow_test.go
index 35a8c9d05b8..81916c7b8a8 100644
--- a/metrics/prometheus/prometheus_ow_test.go
+++ b/metrics/prometheus/prometheus_ow_test.go
@@ -3,6 +3,7 @@ package prometheusmetrics
import (
"testing"
+ "github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/prometheus/client_golang/prometheus"
)
@@ -168,3 +169,46 @@ func TestRecordVASTTagType(t *testing.T) {
})
}
}
+
+func TestRecordFloorStatus(t *testing.T) {
+ type args struct {
+ code, account, source string
+ }
+ type want struct {
+ expCount int
+ }
+ tests := []struct {
+ name string
+ args args
+ want want
+ }{
+ {
+ name: "record_floor_status",
+ args: args{
+ account: "5890",
+ code: "1",
+ source: openrtb_ext.FetchLocation,
+ },
+ want: want{
+ expCount: 1,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+
+ pm := createMetricsForTesting()
+ pm.RecordFloorStatus(tt.args.account, tt.args.source, tt.args.code)
+ assertCounterVecValue(t,
+ "",
+ "record dynamic fetch failure",
+ pm.dynamicFetchFailure,
+ float64(tt.want.expCount),
+ prometheus.Labels{
+ accountLabel: tt.args.account,
+ sourceLabel: tt.args.source,
+ codeLabel: tt.args.code,
+ })
+ })
+ }
+}
diff --git a/modules/pubmatic/openwrap/auctionresponsehook.go b/modules/pubmatic/openwrap/auctionresponsehook.go
index 7c546a11b9b..1cf613c2289 100644
--- a/modules/pubmatic/openwrap/auctionresponsehook.go
+++ b/modules/pubmatic/openwrap/auctionresponsehook.go
@@ -269,11 +269,7 @@ func (m OpenWrap) handleAuctionResponseHook(
}
}
- // add seat-non-bids in the bidresponse only request.ext.prebid.returnallbidstatus is true
- if rctx.ReturnAllBidStatus {
- rctx.SeatNonBids = prepareSeatNonBids(rctx)
- addSeatNonBidsInResponseExt(rctx, &responseExt)
- }
+ result.SeatNonBid = prepareSeatNonBids(rctx)
if rctx.Debug {
rCtxBytes, _ := json.Marshal(rctx)
@@ -327,7 +323,6 @@ func (m OpenWrap) handleAuctionResponseHook(
// TODO: move debug here
// result.ChangeSet.AddMutation(func(ap hookstage.AuctionResponsePayload) (hookstage.AuctionResponsePayload, error) {
// }, hookstage.MutationUpdate, "response-body-with-sshb-format")
-
return result, nil
}
diff --git a/modules/pubmatic/openwrap/auctionresponsehook_test.go b/modules/pubmatic/openwrap/auctionresponsehook_test.go
index 5f75bf056b8..c61e8f8dd82 100644
--- a/modules/pubmatic/openwrap/auctionresponsehook_test.go
+++ b/modules/pubmatic/openwrap/auctionresponsehook_test.go
@@ -20,117 +20,6 @@ import (
"github.com/stretchr/testify/assert"
)
-func TestSeatNonBidsInHandleAuctionResponseHook(t *testing.T) {
- ctrl := gomock.NewController(t)
- defer ctrl.Finish()
-
- type args struct {
- ctx context.Context
- moduleCtx hookstage.ModuleInvocationContext
- payload hookstage.AuctionResponsePayload
- }
-
- type want struct {
- bidResponseExt json.RawMessage
- err error
- }
-
- tests := []struct {
- name string
- args args
- want want
- getMetricsEngine func() *mock_metrics.MockMetricsEngine
- }{
- {
- name: "returnallbidstatus_true",
- args: args{
- ctx: nil,
- moduleCtx: hookstage.ModuleInvocationContext{
- ModuleContext: hookstage.ModuleContext{
- "rctx": models.RequestCtx{
- StartTime: time.Now().UnixMilli(),
- ReturnAllBidStatus: true,
- ImpBidCtx: map[string]models.ImpCtx{
- "imp1": {},
- },
- AdapterThrottleMap: map[string]struct{}{
- "pubmatic": {},
- },
- PubIDStr: "5890",
- },
- },
- },
- payload: hookstage.AuctionResponsePayload{
- BidResponse: &openrtb2.BidResponse{
- SeatBid: []openrtb2.SeatBid{},
- },
- },
- },
- getMetricsEngine: func() (me *mock_metrics.MockMetricsEngine) {
- mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
- mockEngine.EXPECT().RecordPublisherResponseTimeStats("5890", gomock.Any())
- mockEngine.EXPECT().RecordNobidErrPrebidServerResponse("5890")
- return mockEngine
- },
- want: want{
- bidResponseExt: json.RawMessage(`{"prebid":{"seatnonbid":[{"nonbid":[{"impid":"imp1","statuscode":504,"ext":{"prebid":{"bid":{"id":""}}}}],"seat":"pubmatic","ext":null}]},"matchedimpression":{}}`),
- },
- },
- {
- name: "returnallbidstatus_false",
- args: args{
- ctx: nil,
- moduleCtx: hookstage.ModuleInvocationContext{
- ModuleContext: hookstage.ModuleContext{
- "rctx": models.RequestCtx{
- StartTime: time.Now().UnixMilli(),
- ReturnAllBidStatus: false,
- ImpBidCtx: map[string]models.ImpCtx{
- "imp1": {},
- },
- AdapterThrottleMap: map[string]struct{}{
- "pubmatic": {},
- },
- PubIDStr: "5890",
- },
- },
- },
- payload: hookstage.AuctionResponsePayload{
- BidResponse: &openrtb2.BidResponse{
- SeatBid: []openrtb2.SeatBid{},
- },
- },
- },
- getMetricsEngine: func() (me *mock_metrics.MockMetricsEngine) {
- mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
- mockEngine.EXPECT().RecordPublisherResponseTimeStats("5890", gomock.Any())
- mockEngine.EXPECT().RecordNobidErrPrebidServerResponse("5890")
- return mockEngine
- },
- want: want{
- bidResponseExt: json.RawMessage(`{"matchedimpression":{}}`),
- },
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- o := OpenWrap{
- metricEngine: tt.getMetricsEngine(),
- }
- hookResult, err := o.handleAuctionResponseHook(tt.args.ctx, tt.args.moduleCtx, tt.args.payload)
- assert.Equal(t, tt.want.err, err, tt.name)
- mutations := hookResult.ChangeSet.Mutations()
- assert.NotEmpty(t, mutations, tt.name)
- for _, mut := range mutations {
- result, err := mut.Apply(tt.args.payload)
- assert.Nil(t, err, tt.name)
- assert.Equal(t, tt.want.bidResponseExt, result.BidResponse.Ext, tt.name)
- }
- })
- }
-}
-
func TestNonBRCodesInHandleAuctionResponseHook(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
diff --git a/modules/pubmatic/openwrap/beforevalidationhook.go b/modules/pubmatic/openwrap/beforevalidationhook.go
index 095850b2e50..50d8c457338 100644
--- a/modules/pubmatic/openwrap/beforevalidationhook.go
+++ b/modules/pubmatic/openwrap/beforevalidationhook.go
@@ -165,6 +165,7 @@ func (m OpenWrap) handleBeforeValidationHook(
var allPartnersThrottledFlag bool
rCtx.AdapterThrottleMap, allPartnersThrottledFlag = GetAdapterThrottleMap(rCtx.PartnerConfigMap)
+
if allPartnersThrottledFlag {
result.NbrCode = int(nbr.AllPartnerThrottled)
result.Errors = append(result.Errors, "All adapters throttled")
diff --git a/modules/pubmatic/openwrap/beforevalidationhook_test.go b/modules/pubmatic/openwrap/beforevalidationhook_test.go
index e9506cac09b..3671c92de62 100644
--- a/modules/pubmatic/openwrap/beforevalidationhook_test.go
+++ b/modules/pubmatic/openwrap/beforevalidationhook_test.go
@@ -3247,6 +3247,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
assert.Equal(t, tt.wantErr, err != nil)
assert.Equal(t, tt.want.Reject, got.Reject)
assert.Equal(t, tt.want.NbrCode, got.NbrCode)
+ assert.Equal(t, tt.want.SeatNonBid, got.SeatNonBid)
for i := 0; i < len(got.DebugMessages); i++ {
gotDebugMessage, _ := json.Marshal(got.DebugMessages[i])
wantDebugMessage, _ := json.Marshal(tt.want.DebugMessages[i])
@@ -4031,6 +4032,7 @@ func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) {
},
}, nil)
mockCache.EXPECT().GetAdunitConfigFromCache(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&adunitconfig.AdUnitConfig{})
+
//prometheus metrics
mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234")
mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.InternalError))
diff --git a/modules/pubmatic/openwrap/bidderparams/others.go b/modules/pubmatic/openwrap/bidderparams/others.go
index eaaa2b1058c..9b693281947 100644
--- a/modules/pubmatic/openwrap/bidderparams/others.go
+++ b/modules/pubmatic/openwrap/bidderparams/others.go
@@ -16,10 +16,12 @@ func PrepareAdapterParamsV25(rctx models.RequestCtx, cache cache.Cache, bidReque
return "", "", false, nil, errors.New("ErrBidderParamsValidationError")
}
- var isRegexSlot bool
+ var isRegexSlot, isRegexKGP bool
var matchedSlot, matchedPattern string
- isRegexKGP := rctx.PartnerConfigMap[partnerID][models.KEY_GEN_PATTERN] == models.REGEX_KGP
+ if kgp := rctx.PartnerConfigMap[partnerID][models.KEY_GEN_PATTERN]; kgp == models.REGEX_KGP || kgp == models.ADUNIT_SIZE_REGEX_KGP {
+ isRegexKGP = true
+ }
slots, slotMap, slotMappingInfo, hw := getSlotMeta(rctx, cache, bidRequest, imp, impExt, partnerID)
for i, slot := range slots {
diff --git a/modules/pubmatic/openwrap/bidderparams/others_test.go b/modules/pubmatic/openwrap/bidderparams/others_test.go
new file mode 100644
index 00000000000..1eb42fa6189
--- /dev/null
+++ b/modules/pubmatic/openwrap/bidderparams/others_test.go
@@ -0,0 +1,302 @@
+package bidderparams
+
+import (
+ "testing"
+
+ "github.com/golang/mock/gomock"
+ "github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/adapters"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/cache"
+ mock_cache "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/cache/mock"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
+ "github.com/prebid/prebid-server/v2/openrtb_ext"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestPrepareAdapterParamsV25(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+ mockCache := mock_cache.NewMockCache(ctrl)
+ type args struct {
+ rctx models.RequestCtx
+ cache cache.Cache
+ bidRequest openrtb2.BidRequest
+ imp openrtb2.Imp
+ impExt models.ImpExtension
+ partnerID int
+ }
+ type want struct {
+ matchedSlot string
+ matchedPattern string
+ isRegexSlot bool
+ params []byte
+ wantErr bool
+ }
+ tests := []struct {
+ name string
+ args args
+ setup func()
+ want want
+ }{
+ {
+ name: "AdUnit,Size slot matched",
+ args: args{
+ rctx: models.RequestCtx{
+ PubID: 5890,
+ ProfileID: 123,
+ DisplayID: 1,
+ PartnerConfigMap: map[int]map[string]string{
+ 19323: {
+ models.PREBID_PARTNER_NAME: "appnexus",
+ models.BidderCode: "appnexus",
+ models.TIMEOUT: "200",
+ models.KEY_GEN_PATTERN: "_AU_@_W_x_H_",
+ models.SERVER_SIDE_FLAG: "1",
+ },
+ },
+ },
+ cache: mockCache,
+ impExt: models.ImpExtension{
+ Data: openrtb_ext.ExtImpData{
+ PbAdslot: "/43743431/DMDEMO1",
+ },
+ },
+ imp: getTestImp("/43743431/DMDEMO1", true, false),
+ partnerID: 19323,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ "/43743431/dmdemo1@200x300": {
+ PartnerId: 19323,
+ AdapterId: 2,
+ VersionId: 92588,
+ SlotName: "/43743431/DMDemo1@200x300",
+ MappingJson: "{\"placementId\":\"9880618\"}",
+ SlotMappings: map[string]interface{}{
+ "placementId": "9880618",
+ },
+ OrderID: 1,
+ Hash: "",
+ },
+ })
+ mockCache.EXPECT().GetSlotToHashValueMapFromCacheV25(gomock.Any(), gomock.Any()).Return(models.SlotMappingInfo{
+ OrderedSlotList: []string{"/43743431/DMDemo1@200x300"},
+ HashValueMap: map[string]string{"/43743431/DMDemo1@200x300": ""},
+ })
+ },
+ want: want{
+ matchedSlot: "/43743431/DMDEMO1@200x300",
+ matchedPattern: "",
+ isRegexSlot: false,
+ params: []byte("{\"placementId\":9880618}"),
+ wantErr: false,
+ },
+ },
+ {
+ name: "partnerconfig not found for partnerId",
+ args: args{
+ rctx: models.RequestCtx{
+ PubID: 5890,
+ ProfileID: 123,
+ DisplayID: 1,
+ PartnerConfigMap: nil,
+ },
+ cache: mockCache,
+ partnerID: 1,
+ },
+ setup: func() {},
+ want: want{
+ matchedSlot: "",
+ matchedPattern: "",
+ isRegexSlot: false,
+ params: nil,
+ wantErr: true,
+ },
+ },
+ {
+ name: "slots not founds",
+ args: args{
+ rctx: models.RequestCtx{
+ IsTestRequest: 1,
+ PubID: 5890,
+ ProfileID: 123,
+ DisplayID: 1,
+ PartnerConfigMap: map[int]map[string]string{
+ 256: {
+ models.PREBID_PARTNER_NAME: "appnexus",
+ models.BidderCode: "appnexus",
+ models.TIMEOUT: "200",
+ models.KEY_GEN_PATTERN: "_AU_@_W_x_H_",
+ models.SERVER_SIDE_FLAG: "1",
+ },
+ },
+ },
+ cache: mockCache,
+ impExt: models.ImpExtension{
+ Bidder: map[string]*models.BidderExtension{
+ "appnexus": {
+ KeyWords: []models.KeyVal{
+ {
+ Key: "test_key1",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ {
+ Key: "test_key2",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ },
+ },
+ },
+ Wrapper: &models.ExtImpWrapper{
+ Div: "Div1",
+ },
+ },
+ imp: getTestImp("/Test_Adunit1234", true, false),
+ partnerID: 256,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(nil)
+ },
+ want: want{
+ matchedSlot: "",
+ matchedPattern: "",
+ isRegexSlot: false,
+ params: nil,
+ wantErr: false,
+ },
+ },
+ {
+ name: "regex mapping slot found",
+ args: args{
+ rctx: models.RequestCtx{
+ PubID: 5890,
+ ProfileID: 123,
+ DisplayID: 1,
+ PartnerConfigMap: map[int]map[string]string{
+ 19323: {
+ models.PREBID_PARTNER_NAME: "appnexus",
+ models.BidderCode: "appnexus",
+ models.TIMEOUT: "200",
+ models.KEY_GEN_PATTERN: "_AU_@_DIV_@_W_x_H_",
+ models.SERVER_SIDE_FLAG: "1",
+ },
+ },
+ },
+ cache: mockCache,
+ impExt: models.ImpExtension{
+ Data: openrtb_ext.ExtImpData{
+ PbAdslot: "/43743431/DMDEMO1",
+ },
+ },
+ imp: getTestImp("/43743431/DMDEMO1", true, false),
+ partnerID: 19323,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ "^/43743431/dmdemo[0-9]*@div[12]@^200x300$": {
+ PartnerId: 19323,
+ AdapterId: 2,
+ VersionId: 92588,
+ SlotName: "^/43743431/DMDemo[0-9]*@Div[12]@^200x300$",
+ MappingJson: "{\"placementId\":\"9880618\"}",
+ SlotMappings: map[string]interface{}{
+ "placementId": "9880618",
+ },
+ OrderID: 1,
+ Hash: "",
+ },
+ })
+ mockCache.EXPECT().GetSlotToHashValueMapFromCacheV25(gomock.Any(), gomock.Any()).Return(models.SlotMappingInfo{
+ OrderedSlotList: []string{"^/43743431/DMDemo[0-9]*@Div[12]@^200x300$"},
+ HashValueMap: map[string]string{"^/43743431/DMDemo[0-9]*@Div[12]@^200x300$": ""},
+ })
+ mockCache.EXPECT().Get("psregex_5890_123_1_19323_/43743431/DMDEMO1@@200x300").Return(regexSlotEntry{
+ SlotName: "/43743431/DMDEMO1@@200x300",
+ RegexPattern: "^/43743431/DMDemo[0-9]*@Div[12]@^200x300$",
+ }, true)
+ },
+ want: want{
+ matchedSlot: "/43743431/DMDEMO1@@200x300",
+ matchedPattern: "^/43743431/DMDemo[0-9]*@Div[12]@^200x300$",
+ isRegexSlot: true,
+ params: []byte("{\"placementId\":9880618}"),
+ wantErr: false,
+ },
+ },
+ {
+ name: "prebid s2s regex mapping slot found",
+ args: args{
+ rctx: models.RequestCtx{
+ PubID: 5890,
+ ProfileID: 123,
+ DisplayID: 1,
+ PartnerConfigMap: map[int]map[string]string{
+ 19323: {
+ models.PREBID_PARTNER_NAME: "appnexus",
+ models.BidderCode: "appnexus",
+ models.TIMEOUT: "200",
+ models.KEY_GEN_PATTERN: "_RE_@_W_x_H_",
+ models.SERVER_SIDE_FLAG: "1",
+ },
+ },
+ },
+ cache: mockCache,
+ impExt: models.ImpExtension{
+ Data: openrtb_ext.ExtImpData{
+ PbAdslot: "/43743431/DMDEMO1",
+ },
+ },
+ imp: getTestImp("/43743431/DMDEMO1", true, false),
+ partnerID: 19323,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ "^/43743431/dmdemo[0-9]*@^200x300$": {
+ PartnerId: 19323,
+ AdapterId: 2,
+ VersionId: 92588,
+ SlotName: "^/43743431/DMDemo[0-9]*@^200x300$",
+ MappingJson: "{\"placementId\":\"9880618\"}",
+ SlotMappings: map[string]interface{}{
+ "placementId": "9880618",
+ },
+ OrderID: 1,
+ Hash: "",
+ },
+ })
+ mockCache.EXPECT().GetSlotToHashValueMapFromCacheV25(gomock.Any(), gomock.Any()).Return(models.SlotMappingInfo{
+ OrderedSlotList: []string{"^/43743431/DMDemo[0-9]*@^200x300$"},
+ HashValueMap: map[string]string{"^/43743431/DMDemo[0-9]*@^200x300$": ""},
+ })
+ mockCache.EXPECT().Get("psregex_5890_123_1_19323_/43743431/DMDEMO1@200x300").Return(regexSlotEntry{
+ SlotName: "/43743431/DMDEMO1@200x300",
+ RegexPattern: "^/43743431/DMDemo[0-9]*@^200x300$",
+ }, true)
+ },
+ want: want{
+ matchedSlot: "/43743431/DMDEMO1@200x300",
+ matchedPattern: "^/43743431/DMDemo[0-9]*@^200x300$",
+ isRegexSlot: true,
+ params: []byte("{\"placementId\":9880618}"),
+ wantErr: false,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if tt.setup != nil {
+ tt.setup()
+ }
+ adapters.InitBidders("./static/bidder-params/")
+ matchedSlot, matchedPattern, isRegexSlot, params, err := PrepareAdapterParamsV25(tt.args.rctx, tt.args.cache, tt.args.bidRequest, tt.args.imp, tt.args.impExt, tt.args.partnerID)
+ if (err != nil) != tt.want.wantErr {
+ assert.Equal(t, tt.want.wantErr, err != nil)
+ return
+ }
+ assert.Equal(t, tt.want.matchedSlot, matchedSlot)
+ assert.Equal(t, tt.want.matchedPattern, matchedPattern)
+ assert.Equal(t, tt.want.isRegexSlot, isRegexSlot)
+ assert.Equal(t, tt.want.params, params)
+ })
+ }
+}
diff --git a/modules/pubmatic/openwrap/bidderparams/pubmatic.go b/modules/pubmatic/openwrap/bidderparams/pubmatic.go
index 5eadf568d1e..afb65b57651 100644
--- a/modules/pubmatic/openwrap/bidderparams/pubmatic.go
+++ b/modules/pubmatic/openwrap/bidderparams/pubmatic.go
@@ -39,10 +39,12 @@ func PreparePubMaticParamsV25(rctx models.RequestCtx, cache cache.Cache, bidRequ
hash := ""
var err error
var matchedSlot, matchedPattern string
- isRegexSlot := false
+ var isRegexSlot, isRegexKGP bool
kgp := rctx.PartnerConfigMap[partnerID][models.KEY_GEN_PATTERN]
- isRegexKGP := kgp == models.REGEX_KGP
+ if kgp == models.REGEX_KGP || kgp == models.ADUNIT_SIZE_REGEX_KGP {
+ isRegexKGP = true
+ }
// simple+regex key match
for _, slot := range slots {
diff --git a/modules/pubmatic/openwrap/bidderparams/pubmatic_test.go b/modules/pubmatic/openwrap/bidderparams/pubmatic_test.go
index 3186edb4bfc..d51b35b486d 100644
--- a/modules/pubmatic/openwrap/bidderparams/pubmatic_test.go
+++ b/modules/pubmatic/openwrap/bidderparams/pubmatic_test.go
@@ -374,6 +374,202 @@ func TestPreparePubMaticParamsV25(t *testing.T) {
wantErr: false,
},
},
+ {
+ name: "exact_matched_slot_found_adslot_updated_from_PubMatic_secondary_flow_for_prebids2s_regex",
+ args: args{
+ rctx: models.RequestCtx{
+ IsTestRequest: 0,
+ PubID: 5890,
+ ProfileID: 123,
+ DisplayID: 1,
+ PartnerConfigMap: map[int]map[string]string{
+ 1: {
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubmatic",
+ models.TIMEOUT: "200",
+ models.KEY_GEN_PATTERN: "_RE_@_W_x_H_",
+ models.SERVER_SIDE_FLAG: "1",
+ models.KEY_PROFILE_ID: "1323",
+ },
+ },
+ },
+ cache: mockCache,
+ impExt: models.ImpExtension{
+ Bidder: map[string]*models.BidderExtension{
+ "pubmatic": {
+ KeyWords: []models.KeyVal{
+ {
+ Key: "test_key1",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ {
+ Key: "test_key2",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ },
+ },
+ },
+ },
+ imp: getTestImp("/Test_Adunit1234", true, false),
+ partnerID: 1,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ "/test_adunit1234@200x300": {
+ PartnerId: 1,
+ AdapterId: 1,
+ SlotName: "/Test_Adunit1234@200x300",
+ SlotMappings: map[string]interface{}{
+ "site": "12313",
+ "adtag": "45343",
+ "slotName": "/Test_Adunit1234@200x300",
+ },
+ },
+ })
+ mockCache.EXPECT().GetSlotToHashValueMapFromCacheV25(gomock.Any(), gomock.Any()).Return(models.SlotMappingInfo{
+ OrderedSlotList: []string{"test", "test1"},
+ })
+ },
+ want: want{
+ matchedSlot: "/Test_Adunit1234@200x300",
+ matchedPattern: "",
+ isRegexSlot: false,
+ params: []byte(`{"publisherId":"5890","adSlot":"/Test_Adunit1234@200x300","wrapper":{"version":0,"profile":1323},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
+ wantErr: false,
+ },
+ },
+ {
+ name: "exact_matched_slot_found_adSlot_upadted_from_owSlotName_prebids2s_regex",
+ args: args{
+ rctx: models.RequestCtx{
+ IsTestRequest: 0,
+ PubID: 5890,
+ ProfileID: 123,
+ DisplayID: 1,
+ PartnerConfigMap: map[int]map[string]string{
+ 1: {
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubmatic",
+ models.TIMEOUT: "200",
+ models.KEY_GEN_PATTERN: "_RE_@_W_x_H_",
+ models.SERVER_SIDE_FLAG: "1",
+ },
+ },
+ },
+ cache: mockCache,
+ impExt: models.ImpExtension{
+ Bidder: map[string]*models.BidderExtension{
+ "pubmatic": {
+ KeyWords: []models.KeyVal{
+ {
+ Key: "test_key1",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ {
+ Key: "test_key2",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ },
+ },
+ },
+ },
+ imp: getTestImp("/Test_Adunit1234", true, false),
+ partnerID: 1,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ "/test_adunit1234@200x300": {
+ PartnerId: 1,
+ AdapterId: 1,
+ SlotName: "/Test_Adunit1234@200x300",
+ SlotMappings: map[string]interface{}{
+ "site": "12313",
+ "adtag": "45343",
+ models.KEY_OW_SLOT_NAME: "/Test_Adunit1234@200x300",
+ },
+ },
+ })
+ mockCache.EXPECT().GetSlotToHashValueMapFromCacheV25(gomock.Any(), gomock.Any()).Return(models.SlotMappingInfo{
+ OrderedSlotList: []string{"test", "test1"},
+ })
+ },
+ want: want{
+ matchedSlot: "/Test_Adunit1234@200x300",
+ matchedPattern: "",
+ isRegexSlot: false,
+ params: []byte(`{"publisherId":"5890","adSlot":"/Test_Adunit1234@200x300","wrapper":{"version":1,"profile":123},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
+ wantErr: false,
+ },
+ },
+ {
+ name: "prebids2s_regex_matched_slot_found_adSlot_upadted_from_hashValue",
+ args: args{
+ rctx: models.RequestCtx{
+ IsTestRequest: 0,
+ PubID: 5890,
+ ProfileID: 123,
+ DisplayID: 1,
+ PartnerConfigMap: map[int]map[string]string{
+ 1: {
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubmatic",
+ models.TIMEOUT: "200",
+ models.KEY_GEN_PATTERN: "_RE_@_W_x_H_",
+ models.SERVER_SIDE_FLAG: "1",
+ },
+ },
+ },
+ cache: mockCache,
+ impExt: models.ImpExtension{
+ Bidder: map[string]*models.BidderExtension{
+ "pubmatic": {
+ KeyWords: []models.KeyVal{
+ {
+ Key: "test_key1",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ {
+ Key: "test_key2",
+ Values: []string{"test_value1", "test_value2"},
+ },
+ },
+ },
+ },
+ },
+ imp: getTestImp("/Test_Adunit1234", true, false),
+ partnerID: 1,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetMappingsFromCacheV25(gomock.Any(), gomock.Any()).Return(map[string]models.SlotMapping{
+ ".*@.*": {
+ PartnerId: 1,
+ AdapterId: 1,
+ SlotName: "/Test_Adunit1234@200x300",
+ SlotMappings: map[string]interface{}{
+ "site": "12313",
+ "adtag": "45343",
+ },
+ },
+ })
+ mockCache.EXPECT().GetSlotToHashValueMapFromCacheV25(gomock.Any(), gomock.Any()).Return(models.SlotMappingInfo{
+ OrderedSlotList: []string{"test", "test1"},
+ HashValueMap: map[string]string{
+ ".*@.*": "2aa34b52a9e941c1594af7565e599c8d",
+ },
+ })
+ mockCache.EXPECT().Get("psregex_5890_123_1_1_/Test_Adunit1234@200x300").Return(regexSlotEntry{
+ SlotName: "/Test_Adunit1234@200x300",
+ RegexPattern: ".*@.*",
+ }, true)
+ },
+ want: want{
+ matchedSlot: "/Test_Adunit1234@200x300",
+ matchedPattern: ".*@.*",
+ isRegexSlot: true,
+ params: []byte(`{"publisherId":"5890","adSlot":"2aa34b52a9e941c1594af7565e599c8d","wrapper":{"version":1,"profile":123},"keywords":[{"key":"test_key1","value":["test_value1","test_value2"]},{"key":"test_key2","value":["test_value1","test_value2"]}]}`),
+ wantErr: false,
+ },
+ },
{
name: "exact_matched_slot_found_adSlot_upadted_from_owSlotName",
args: args{
diff --git a/modules/pubmatic/openwrap/cache/mock/mock.go b/modules/pubmatic/openwrap/cache/mock/mock.go
index e7f1cf2bd05..8679e1f5792 100644
--- a/modules/pubmatic/openwrap/cache/mock/mock.go
+++ b/modules/pubmatic/openwrap/cache/mock/mock.go
@@ -5,38 +5,37 @@
package mock_cache
import (
- reflect "reflect"
-
gomock "github.com/golang/mock/gomock"
openrtb2 "github.com/prebid/openrtb/v20/openrtb2"
models "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
adunitconfig "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/adunitconfig"
+ reflect "reflect"
)
-// MockCache is a mock of Cache interface.
+// MockCache is a mock of Cache interface
type MockCache struct {
ctrl *gomock.Controller
recorder *MockCacheMockRecorder
}
-// MockCacheMockRecorder is the mock recorder for MockCache.
+// MockCacheMockRecorder is the mock recorder for MockCache
type MockCacheMockRecorder struct {
mock *MockCache
}
-// NewMockCache creates a new mock instance.
+// NewMockCache creates a new mock instance
func NewMockCache(ctrl *gomock.Controller) *MockCache {
mock := &MockCache{ctrl: ctrl}
mock.recorder = &MockCacheMockRecorder{mock}
return mock
}
-// EXPECT returns an object that allows the caller to indicate expected use.
+// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockCache) EXPECT() *MockCacheMockRecorder {
return m.recorder
}
-// Get mocks base method.
+// Get mocks base method
func (m *MockCache) Get(arg0 string) (interface{}, bool) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", arg0)
@@ -45,13 +44,13 @@ func (m *MockCache) Get(arg0 string) (interface{}, bool) {
return ret0, ret1
}
-// Get indicates an expected call of Get.
+// Get indicates an expected call of Get
func (mr *MockCacheMockRecorder) Get(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockCache)(nil).Get), arg0)
}
-// GetAdunitConfigFromCache mocks base method.
+// GetAdunitConfigFromCache mocks base method
func (m *MockCache) GetAdunitConfigFromCache(arg0 *openrtb2.BidRequest, arg1, arg2, arg3 int) *adunitconfig.AdUnitConfig {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAdunitConfigFromCache", arg0, arg1, arg2, arg3)
@@ -59,13 +58,13 @@ func (m *MockCache) GetAdunitConfigFromCache(arg0 *openrtb2.BidRequest, arg1, ar
return ret0
}
-// GetAdunitConfigFromCache indicates an expected call of GetAdunitConfigFromCache.
+// GetAdunitConfigFromCache indicates an expected call of GetAdunitConfigFromCache
func (mr *MockCacheMockRecorder) GetAdunitConfigFromCache(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAdunitConfigFromCache", reflect.TypeOf((*MockCache)(nil).GetAdunitConfigFromCache), arg0, arg1, arg2, arg3)
}
-// GetFSCThresholdPerDSP mocks base method.
+// GetFSCThresholdPerDSP mocks base method
func (m *MockCache) GetFSCThresholdPerDSP() (map[int]int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetFSCThresholdPerDSP")
@@ -74,13 +73,13 @@ func (m *MockCache) GetFSCThresholdPerDSP() (map[int]int, error) {
return ret0, ret1
}
-// GetFSCThresholdPerDSP indicates an expected call of GetFSCThresholdPerDSP.
+// GetFSCThresholdPerDSP indicates an expected call of GetFSCThresholdPerDSP
func (mr *MockCacheMockRecorder) GetFSCThresholdPerDSP() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFSCThresholdPerDSP", reflect.TypeOf((*MockCache)(nil).GetFSCThresholdPerDSP))
}
-// GetMappingsFromCacheV25 mocks base method.
+// GetMappingsFromCacheV25 mocks base method
func (m *MockCache) GetMappingsFromCacheV25(arg0 models.RequestCtx, arg1 int) map[string]models.SlotMapping {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetMappingsFromCacheV25", arg0, arg1)
@@ -88,13 +87,13 @@ func (m *MockCache) GetMappingsFromCacheV25(arg0 models.RequestCtx, arg1 int) ma
return ret0
}
-// GetMappingsFromCacheV25 indicates an expected call of GetMappingsFromCacheV25.
+// GetMappingsFromCacheV25 indicates an expected call of GetMappingsFromCacheV25
func (mr *MockCacheMockRecorder) GetMappingsFromCacheV25(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMappingsFromCacheV25", reflect.TypeOf((*MockCache)(nil).GetMappingsFromCacheV25), arg0, arg1)
}
-// GetPartnerConfigMap mocks base method.
+// GetPartnerConfigMap mocks base method
func (m *MockCache) GetPartnerConfigMap(arg0, arg1, arg2 int) (map[int]map[string]string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetPartnerConfigMap", arg0, arg1, arg2)
@@ -103,13 +102,13 @@ func (m *MockCache) GetPartnerConfigMap(arg0, arg1, arg2 int) (map[int]map[strin
return ret0, ret1
}
-// GetPartnerConfigMap indicates an expected call of GetPartnerConfigMap.
+// GetPartnerConfigMap indicates an expected call of GetPartnerConfigMap
func (mr *MockCacheMockRecorder) GetPartnerConfigMap(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPartnerConfigMap", reflect.TypeOf((*MockCache)(nil).GetPartnerConfigMap), arg0, arg1, arg2)
}
-// GetPublisherFeatureMap mocks base method.
+// GetPublisherFeatureMap mocks base method
func (m *MockCache) GetPublisherFeatureMap() (map[int]map[int]models.FeatureData, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetPublisherFeatureMap")
@@ -118,13 +117,13 @@ func (m *MockCache) GetPublisherFeatureMap() (map[int]map[int]models.FeatureData
return ret0, ret1
}
-// GetPublisherFeatureMap indicates an expected call of GetPublisherFeatureMap.
+// GetPublisherFeatureMap indicates an expected call of GetPublisherFeatureMap
func (mr *MockCacheMockRecorder) GetPublisherFeatureMap() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPublisherFeatureMap", reflect.TypeOf((*MockCache)(nil).GetPublisherFeatureMap))
}
-// GetPublisherVASTTagsFromCache mocks base method.
+// GetPublisherVASTTagsFromCache mocks base method
func (m *MockCache) GetPublisherVASTTagsFromCache(arg0 int) map[int]*models.VASTTag {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetPublisherVASTTagsFromCache", arg0)
@@ -132,13 +131,13 @@ func (m *MockCache) GetPublisherVASTTagsFromCache(arg0 int) map[int]*models.VAST
return ret0
}
-// GetPublisherVASTTagsFromCache indicates an expected call of GetPublisherVASTTagsFromCache.
+// GetPublisherVASTTagsFromCache indicates an expected call of GetPublisherVASTTagsFromCache
func (mr *MockCacheMockRecorder) GetPublisherVASTTagsFromCache(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPublisherVASTTagsFromCache", reflect.TypeOf((*MockCache)(nil).GetPublisherVASTTagsFromCache), arg0)
}
-// GetSlotToHashValueMapFromCacheV25 mocks base method.
+// GetSlotToHashValueMapFromCacheV25 mocks base method
func (m *MockCache) GetSlotToHashValueMapFromCacheV25(arg0 models.RequestCtx, arg1 int) models.SlotMappingInfo {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetSlotToHashValueMapFromCacheV25", arg0, arg1)
@@ -146,19 +145,19 @@ func (m *MockCache) GetSlotToHashValueMapFromCacheV25(arg0 models.RequestCtx, ar
return ret0
}
-// GetSlotToHashValueMapFromCacheV25 indicates an expected call of GetSlotToHashValueMapFromCacheV25.
+// GetSlotToHashValueMapFromCacheV25 indicates an expected call of GetSlotToHashValueMapFromCacheV25
func (mr *MockCacheMockRecorder) GetSlotToHashValueMapFromCacheV25(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSlotToHashValueMapFromCacheV25", reflect.TypeOf((*MockCache)(nil).GetSlotToHashValueMapFromCacheV25), arg0, arg1)
}
-// Set mocks base method.
+// Set mocks base method
func (m *MockCache) Set(arg0 string, arg1 interface{}) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Set", arg0, arg1)
}
-// Set indicates an expected call of Set.
+// Set indicates an expected call of Set
func (mr *MockCacheMockRecorder) Set(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockCache)(nil).Set), arg0, arg1)
diff --git a/modules/pubmatic/openwrap/database/mysql/adunit_config.go b/modules/pubmatic/openwrap/database/mysql/adunit_config.go
index d3a27c2edaa..9254c4ac215 100644
--- a/modules/pubmatic/openwrap/database/mysql/adunit_config.go
+++ b/modules/pubmatic/openwrap/database/mysql/adunit_config.go
@@ -58,6 +58,5 @@ func (db *mySqlDB) GetAdunitConfig(profileID, displayVersion int) (*adunitconfig
if _, ok := adunitConfig.Config["default"]; !ok {
adunitConfig.Config["default"] = &adunitconfig.AdConfig{}
}
-
return adunitConfig, err
}
diff --git a/modules/pubmatic/openwrap/database/mysql/partner_config.go b/modules/pubmatic/openwrap/database/mysql/partner_config.go
index aa70aca4e69..657a52226a2 100644
--- a/modules/pubmatic/openwrap/database/mysql/partner_config.go
+++ b/modules/pubmatic/openwrap/database/mysql/partner_config.go
@@ -14,7 +14,7 @@ import (
// return the list of active server side header bidding partners
// with their configurations at publisher-profile-version level
func (db *mySqlDB) GetActivePartnerConfigurations(pubID, profileID int, displayVersion int) (map[int]map[string]string, error) {
- versionID, displayVersionID, err := db.getVersionID(profileID, displayVersion, pubID)
+ versionID, displayVersionID, platform, err := db.getVersionID(profileID, displayVersion, pubID)
if err != nil {
return nil, err
}
@@ -22,6 +22,10 @@ func (db *mySqlDB) GetActivePartnerConfigurations(pubID, profileID int, displayV
partnerConfigMap, err := db.getActivePartnerConfigurations(versionID)
if err == nil && partnerConfigMap[-1] != nil {
partnerConfigMap[-1][models.DisplayVersionID] = strconv.Itoa(displayVersionID)
+ // check for SDK new UI
+ if platform != "" {
+ partnerConfigMap[-1][models.PLATFORM_KEY] = platform
+ }
}
return partnerConfigMap, err
}
@@ -76,7 +80,7 @@ func (db *mySqlDB) getActivePartnerConfigurations(versionID int) (map[int]map[st
return partnerConfigMap, nil
}
-func (db *mySqlDB) getVersionID(profileID, displayVersion, pubID int) (int, int, error) {
+func (db *mySqlDB) getVersionID(profileID, displayVersion, pubID int) (int, int, string, error) {
var row *sql.Row
if displayVersion == 0 {
row = db.conn.QueryRow(db.cfg.Queries.LiveVersionInnerQuery, profileID, pubID)
@@ -84,10 +88,11 @@ func (db *mySqlDB) getVersionID(profileID, displayVersion, pubID int) (int, int,
row = db.conn.QueryRow(db.cfg.Queries.DisplayVersionInnerQuery, profileID, displayVersion, pubID)
}
+ var platform sql.NullString
var versionID, displayVersionIDFromDB int
- err := row.Scan(&versionID, &displayVersionIDFromDB)
+ err := row.Scan(&versionID, &displayVersionIDFromDB, &platform)
if err != nil {
- return versionID, displayVersionIDFromDB, err
+ return versionID, displayVersionIDFromDB, platform.String, err
}
- return versionID, displayVersionIDFromDB, nil
+ return versionID, displayVersionIDFromDB, platform.String, nil
}
diff --git a/modules/pubmatic/openwrap/database/mysql/partner_config_test.go b/modules/pubmatic/openwrap/database/mysql/partner_config_test.go
index ea89b8b2116..bae4d8d7187 100644
--- a/modules/pubmatic/openwrap/database/mysql/partner_config_test.go
+++ b/modules/pubmatic/openwrap/database/mysql/partner_config_test.go
@@ -7,6 +7,7 @@ import (
"github.com/DATA-DOG/go-sqlmock"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/config"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
"github.com/stretchr/testify/assert"
)
@@ -32,7 +33,7 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE",
+ LiveVersionInnerQuery: models.TestQuery,
},
MaxDbContextTimeout: 1000,
},
@@ -51,8 +52,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
- rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("25_1", "9")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion)
+ rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("25_1", "9", models.PLATFORM_DISPLAY)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion)
return db
},
@@ -62,7 +63,7 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE",
+ LiveVersionInnerQuery: models.TestQuery,
},
MaxDbContextTimeout: 1000,
},
@@ -81,8 +82,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
- rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion)
+ rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_DISPLAY)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion)
return db
},
@@ -92,8 +93,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE",
- GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)",
+ LiveVersionInnerQuery: models.TestQuery,
+ GetParterConfig: models.TestQuery,
},
MaxDbContextTimeout: 1000,
},
@@ -133,8 +134,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
- rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion)
+ rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_DISPLAY)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion)
rowsPartnerConfig := sqlmock.NewRows([]string{"partnerId", "prebidPartnerName", "bidderCode", "isAlias", "entityTypeID", "testConfig", "vendorId", "keyName", "value"}).
AddRow("-1", "ALL", "ALL", 0, -1, 0, -1, "platform", "display").
@@ -142,7 +143,7 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "kgp", "_AU_@_W_x_H_").
AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "timeout", "200").
AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "serverSideEnabled", "1")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rowsPartnerConfig)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rowsPartnerConfig)
return db
},
},
@@ -151,8 +152,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- DisplayVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+)",
- GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)",
+ DisplayVersionInnerQuery: models.TestQuery,
+ GetParterConfig: models.TestQuery,
},
MaxDbContextTimeout: 1000,
},
@@ -192,8 +193,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
- rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+)")).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion)
+ rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_DISPLAY)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion)
rowsPartnerConfig := sqlmock.NewRows([]string{"partnerId", "prebidPartnerName", "bidderCode", "isAlias", "entityTypeID", "testConfig", "vendorId", "keyName", "value"}).
AddRow("-1", "ALL", "ALL", 0, -1, 0, -1, "platform", "display").
@@ -201,7 +202,7 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "kgp", "_AU_@_W_x_H_").
AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "timeout", "200").
AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "serverSideEnabled", "1")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rowsPartnerConfig)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rowsPartnerConfig)
return db
},
},
@@ -210,8 +211,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- DisplayVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+)",
- GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)",
+ DisplayVersionInnerQuery: models.TestQuery,
+ GetParterConfig: models.TestQuery,
},
MaxDbContextTimeout: 1000,
},
@@ -259,8 +260,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
- rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+)")).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion)
+ rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_DISPLAY)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion)
rowsPartnerConfig := sqlmock.NewRows([]string{"partnerId", "prebidPartnerName", "bidderCode", "isAlias", "entityTypeID", "testConfig", "vendorId", "keyName", "value"}).
AddRow("-1", "ALL", "ALL", 0, -1, 0, -1, "platform", "display").
@@ -268,9 +269,9 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "kgp", "_AU_@_W_x_H_").
AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "timeout", "200").
AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "serverSideEnabled", "1").
- AddRow("234", "vastbidder", "test-vastbidder", 0, 3, 0, 546, "vendorId", "999").
- AddRow("234", "vastbidder", "test-vastbidder", 0, 3, 0, 546, "serverSideEnabled", "1")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rowsPartnerConfig)
+ AddRow("234", "vastbidder", "test-vastbidder", 0, 3, 0, -1, "serverSideEnabled", "1").
+ AddRow("234", "vastbidder", "test-vastbidder", 0, 3, 0, -1, "vendorId", "546")
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rowsPartnerConfig)
return db
},
},
@@ -281,12 +282,12 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) {
conn: tt.setup(),
cfg: tt.fields.cfg,
}
- got, err := db.GetActivePartnerConfigurations(tt.args.pubID, tt.args.profileID, tt.args.displayVersion)
+ gotPartnerConfigMap, err := db.GetActivePartnerConfigurations(tt.args.pubID, tt.args.profileID, tt.args.displayVersion)
if (err != nil) != tt.wantErr {
t.Errorf("mySqlDB.GetActivePartnerConfigurations() error = %v, wantErr %v", err, tt.wantErr)
return
}
- assert.Equal(t, tt.want, got)
+ assert.Equal(t, tt.want, gotPartnerConfigMap)
})
}
}
@@ -323,7 +324,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)",
+ GetParterConfig: models.TestQuery,
},
MaxDbContextTimeout: 1000,
},
@@ -340,7 +341,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) {
}
rows := sqlmock.NewRows([]string{"partnerId", "prebidPartnerName", "bidderCode", "isAlias", "entityTypeID", "testConfig", "vendorId", "keyName", "value"}).
AddRow("11_11", "openx", "openx", 0, -1, 0, -1, "k1", "v1")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows)
return db
},
},
@@ -349,7 +350,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)",
+ GetParterConfig: models.TestQuery,
},
MaxDbContextTimeout: 1000,
},
@@ -386,7 +387,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) {
AddRow(101, "openx", "openx", 0, -1, 0, 152, "k1", "v1").
AddRow(101, "openx", "openx", 0, -1, 0, 152, "k2", "v2").
AddRow(102, "pubmatic", "pubmatic", 0, -1, 0, 76, "k1", "v2")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows)
return db
},
},
@@ -395,7 +396,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)",
+ GetParterConfig: models.TestQuery,
},
MaxDbContextTimeout: 1000,
},
@@ -438,7 +439,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) {
AddRow(101, "FirstPartnerName", "FirstBidder", 0, 3, 0, 152, "rev_share", "10").
AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k1", "v1").
AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k2", "v2")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows)
return db
},
},
@@ -447,7 +448,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)",
+ GetParterConfig: models.TestQuery,
},
MaxDbContextTimeout: 1000,
},
@@ -493,7 +494,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) {
AddRow(101, "FirstPartnerName", "FirstBidder", 0, 3, 0, 76, "rev_share", "10").
AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k1", "v1").
AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k2", "v2")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows)
return db
},
},
@@ -502,7 +503,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)",
+ GetParterConfig: models.TestQuery,
},
MaxDbContextTimeout: 1000,
},
@@ -546,7 +547,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) {
AddRow(101, "FirstPartnerName", "FirstBidder", 0, 3, 0, 76, "rev_share", "10").
AddRow(102, "SecondPartnerName", "SecondBidder", 1, -1, 0, 100, "k1", "v1").
AddRow(102, "SecondPartnerName", "SecondBidder", 1, -1, 0, 100, "k2", "v2")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows)
return db
},
},
@@ -555,7 +556,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)",
+ GetParterConfig: models.TestQuery,
},
MaxDbContextTimeout: 1000,
},
@@ -599,7 +600,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) {
AddRow(101, "FirstPartnerName", "FirstBidder", 0, 3, 0, 76, "rev_share", "10").
AddRow(102, "-", "-", 0, -1, 0, 100, "k1", "v1").
AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k2", "v2")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows)
return db
},
},
@@ -610,12 +611,12 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) {
conn: tt.setup(),
cfg: tt.fields.cfg,
}
- got, err := db.getActivePartnerConfigurations(tt.args.versionID)
+ gotPartnerConfigMap, err := db.getActivePartnerConfigurations(tt.args.versionID)
if (err != nil) != tt.wantErr {
t.Errorf("mySqlDB.getActivePartnerConfigurations() error = %v, wantErr %v", err, tt.wantErr)
return
}
- assert.Equal(t, tt.want, got)
+ assert.Equal(t, tt.want, gotPartnerConfigMap)
})
}
}
@@ -635,6 +636,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) {
args args
expectedVersionID int
expectedDisplayVersionIDFromDB int
+ expectedPlatform string
wantErr bool
setup func() *sql.DB
}{
@@ -643,7 +645,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE",
+ LiveVersionInnerQuery: models.TestQuery,
},
},
},
@@ -654,6 +656,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) {
},
expectedVersionID: 0,
expectedDisplayVersionIDFromDB: 0,
+ expectedPlatform: "",
wantErr: true,
setup: func() *sql.DB {
db, mock, err := sqlmock.New()
@@ -661,8 +664,8 @@ func Test_mySqlDB_getVersionID(t *testing.T) {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
- rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("25_1", "9")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion)
+ rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("25_1", "9", models.PLATFORM_APP)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion)
return db
},
@@ -672,7 +675,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE",
+ LiveVersionInnerQuery: models.TestQuery,
},
},
},
@@ -684,6 +687,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) {
expectedVersionID: 251,
expectedDisplayVersionIDFromDB: 9,
+ expectedPlatform: "in-app",
wantErr: false,
setup: func() *sql.DB {
db, mock, err := sqlmock.New()
@@ -691,8 +695,8 @@ func Test_mySqlDB_getVersionID(t *testing.T) {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
- rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion)
+ rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_APP)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion)
return db
},
@@ -702,7 +706,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) {
fields: fields{
cfg: config.Database{
Queries: config.Queries{
- DisplayVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+)",
+ DisplayVersionInnerQuery: models.TestQuery,
},
},
},
@@ -714,6 +718,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) {
expectedVersionID: 251,
expectedDisplayVersionIDFromDB: 9,
+ expectedPlatform: "in-app",
wantErr: false,
setup: func() *sql.DB {
db, mock, err := sqlmock.New()
@@ -721,12 +726,96 @@ func Test_mySqlDB_getVersionID(t *testing.T) {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
- rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9")
- mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+)")).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion)
+ rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_APP)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion)
return db
},
},
+ {
+ name: "Platform is null",
+ fields: fields{
+ cfg: config.Database{
+ Queries: config.Queries{
+ DisplayVersionInnerQuery: models.TestQuery,
+ },
+ },
+ },
+ args: args{
+ profileID: 19109,
+ displayVersion: 2,
+ pubID: 5890,
+ },
+ expectedVersionID: 123,
+ expectedDisplayVersionIDFromDB: 12,
+ expectedPlatform: "",
+ wantErr: false,
+ setup: func() *sql.DB {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("123", "12", nil)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 2, 5890).WillReturnRows(rowsWrapperVersion)
+ return db
+ },
+ },
+ {
+ name: "Platform is empty string",
+ fields: fields{
+ cfg: config.Database{
+ Queries: config.Queries{
+ LiveVersionInnerQuery: models.TestQuery,
+ },
+ },
+ },
+ args: args{
+ profileID: 19109,
+ displayVersion: 0,
+ pubID: 5890,
+ },
+ expectedVersionID: 251,
+ expectedDisplayVersionIDFromDB: 9,
+ expectedPlatform: "",
+ wantErr: false,
+ setup: func() *sql.DB {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", "")
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion)
+ return db
+ },
+ },
+ {
+ name: "Platform is not null",
+ fields: fields{
+ cfg: config.Database{
+ Queries: config.Queries{
+ LiveVersionInnerQuery: models.TestQuery,
+ },
+ },
+ },
+ args: args{
+ profileID: 19109,
+ displayVersion: 0,
+ pubID: 5890,
+ },
+ expectedVersionID: 251,
+ expectedDisplayVersionIDFromDB: 9,
+ expectedPlatform: "in-app",
+ wantErr: false,
+ setup: func() *sql.DB {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_APP)
+ mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion)
+ return db
+ },
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -734,17 +823,14 @@ func Test_mySqlDB_getVersionID(t *testing.T) {
conn: tt.setup(),
cfg: tt.fields.cfg,
}
- got, got1, err := db.getVersionID(tt.args.profileID, tt.args.displayVersion, tt.args.pubID)
+ gotVersionID, gotDisplayVersionID, gotPlatform, err := db.getVersionID(tt.args.profileID, tt.args.displayVersion, tt.args.pubID)
if (err != nil) != tt.wantErr {
t.Errorf("mySqlDB.getVersionID() error = %v, wantErr %v", err, tt.wantErr)
return
}
- if got != tt.expectedVersionID {
- t.Errorf("mySqlDB.getVersionID() got = %v, want %v", got, tt.expectedVersionID)
- }
- if got1 != tt.expectedDisplayVersionIDFromDB {
- t.Errorf("mySqlDB.getVersionID() got1 = %v, want %v", got1, tt.expectedDisplayVersionIDFromDB)
- }
+ assert.Equal(t, tt.expectedVersionID, gotVersionID)
+ assert.Equal(t, tt.expectedDisplayVersionIDFromDB, gotDisplayVersionID)
+ assert.Equal(t, tt.expectedPlatform, gotPlatform)
})
}
}
diff --git a/modules/pubmatic/openwrap/metrics/config/multimetrics.go b/modules/pubmatic/openwrap/metrics/config/multimetrics.go
index a8ae0176a37..fe6788e28c1 100644
--- a/modules/pubmatic/openwrap/metrics/config/multimetrics.go
+++ b/modules/pubmatic/openwrap/metrics/config/multimetrics.go
@@ -460,12 +460,6 @@ func (me *MultiMetricsEngine) RecordAmpVideoResponses(pubid, profileid string) {
}
}
-func (me *MultiMetricsEngine) RecordHTTPCounter() {
- for _, thisME := range *me {
- thisME.RecordHTTPCounter()
- }
-}
-
// RecordUnwrapRequestStatus record VAST unwrap status
func (me *MultiMetricsEngine) RecordUnwrapRequestStatus(accountId, bidder, status string) {
for _, thisME := range *me {
diff --git a/modules/pubmatic/openwrap/metrics/config/multimetrics_test.go b/modules/pubmatic/openwrap/metrics/config/multimetrics_test.go
index 81aea23ae64..7a677de5c41 100644
--- a/modules/pubmatic/openwrap/metrics/config/multimetrics_test.go
+++ b/modules/pubmatic/openwrap/metrics/config/multimetrics_test.go
@@ -220,7 +220,6 @@ func TestRecordFunctionForMultiMetricsEngine(t *testing.T) {
mockEngine.EXPECT().RecordOWServerPanic("endpoint", "methodName", "nodeName", "podName")
mockEngine.EXPECT().RecordAmpVideoRequests("pubid", "profileid")
mockEngine.EXPECT().RecordAmpVideoResponses("pubid", "profileid")
- mockEngine.EXPECT().RecordHTTPCounter()
// create the multi-metric engine
multiMetricEngine := MultiMetricsEngine{}
@@ -286,5 +285,4 @@ func TestRecordFunctionForMultiMetricsEngine(t *testing.T) {
multiMetricEngine.RecordOWServerPanic("endpoint", "methodName", "nodeName", "podName")
multiMetricEngine.RecordAmpVideoRequests("pubid", "profileid")
multiMetricEngine.RecordAmpVideoResponses("pubid", "profileid")
- multiMetricEngine.RecordHTTPCounter()
}
diff --git a/modules/pubmatic/openwrap/metrics/metrics.go b/modules/pubmatic/openwrap/metrics/metrics.go
index b6a96ca8335..24c75136846 100644
--- a/modules/pubmatic/openwrap/metrics/metrics.go
+++ b/modules/pubmatic/openwrap/metrics/metrics.go
@@ -25,7 +25,6 @@ type MetricsEngine interface {
RecordPublisherRequests(endpoint string, publisher string, platform string)
RecordReqImpsWithContentCount(publisher, contentType string)
RecordInjectTrackerErrorCount(adformat, publisher, partner string)
- RecordHTTPCounter()
// not-captured in openwrap module, dont provide enough insights
RecordPBSAuctionRequestsStats()
diff --git a/modules/pubmatic/openwrap/metrics/mock/mock.go b/modules/pubmatic/openwrap/metrics/mock/mock.go
index 270381b7abc..1d600c020cd 100644
--- a/modules/pubmatic/openwrap/metrics/mock/mock.go
+++ b/modules/pubmatic/openwrap/metrics/mock/mock.go
@@ -5,55 +5,54 @@
package mock_metrics
import (
- reflect "reflect"
- time "time"
-
gomock "github.com/golang/mock/gomock"
metrics "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics"
+ reflect "reflect"
+ time "time"
)
-// MockMetricsEngine is a mock of MetricsEngine interface.
+// MockMetricsEngine is a mock of MetricsEngine interface
type MockMetricsEngine struct {
ctrl *gomock.Controller
recorder *MockMetricsEngineMockRecorder
}
-// MockMetricsEngineMockRecorder is the mock recorder for MockMetricsEngine.
+// MockMetricsEngineMockRecorder is the mock recorder for MockMetricsEngine
type MockMetricsEngineMockRecorder struct {
mock *MockMetricsEngine
}
-// NewMockMetricsEngine creates a new mock instance.
+// NewMockMetricsEngine creates a new mock instance
func NewMockMetricsEngine(ctrl *gomock.Controller) *MockMetricsEngine {
mock := &MockMetricsEngine{ctrl: ctrl}
mock.recorder = &MockMetricsEngineMockRecorder{mock}
return mock
}
-// EXPECT returns an object that allows the caller to indicate expected use.
+// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockMetricsEngine) EXPECT() *MockMetricsEngineMockRecorder {
return m.recorder
}
-// RecordAdPodGeneratedImpressionsCount mocks base method.
+// RecordAdPodGeneratedImpressionsCount mocks base method
func (m *MockMetricsEngine) RecordAdPodGeneratedImpressionsCount(arg0 int, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordAdPodGeneratedImpressionsCount", arg0, arg1)
}
-// RecordAdPodGeneratedImpressionsCount indicates an expected call of RecordAdPodGeneratedImpressionsCount.
+// RecordAdPodGeneratedImpressionsCount indicates an expected call of RecordAdPodGeneratedImpressionsCount
func (mr *MockMetricsEngineMockRecorder) RecordAdPodGeneratedImpressionsCount(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordAdPodGeneratedImpressionsCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordAdPodGeneratedImpressionsCount), arg0, arg1)
}
-// RecordAdPodImpressionYield mocks base method.
+// RecordAdPodImpressionYield mocks base method
func (m *MockMetricsEngine) RecordAdPodImpressionYield(arg0, arg1 int, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordAdPodImpressionYield", arg0, arg1, arg2)
}
-// RecordAdPodImpressionYield indicates an expected call of RecordAdPodImpressionYield.
+// RecordAdPodImpressionYield indicates an expected call of RecordAdPodImpressionYield
func (mr *MockMetricsEngineMockRecorder) RecordAdPodImpressionYield(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordAdPodImpressionYield", reflect.TypeOf((*MockMetricsEngine)(nil).RecordAdPodImpressionYield), arg0, arg1, arg2)
@@ -101,151 +100,151 @@ func (m *MockMetricsEngine) RecordBadRequests(arg0 string, arg1 int) {
m.ctrl.Call(m, "RecordBadRequests", arg0, arg1)
}
-// RecordBadRequests indicates an expected call of RecordBadRequests.
+// RecordBadRequests indicates an expected call of RecordBadRequests
func (mr *MockMetricsEngineMockRecorder) RecordBadRequests(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordBadRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordBadRequests), arg0, arg1)
}
-// RecordBidResponseByDealCountInHB mocks base method.
+// RecordBidResponseByDealCountInHB mocks base method
func (m *MockMetricsEngine) RecordBidResponseByDealCountInHB(arg0, arg1, arg2, arg3 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordBidResponseByDealCountInHB", arg0, arg1, arg2, arg3)
}
-// RecordBidResponseByDealCountInHB indicates an expected call of RecordBidResponseByDealCountInHB.
+// RecordBidResponseByDealCountInHB indicates an expected call of RecordBidResponseByDealCountInHB
func (mr *MockMetricsEngineMockRecorder) RecordBidResponseByDealCountInHB(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordBidResponseByDealCountInHB", reflect.TypeOf((*MockMetricsEngine)(nil).RecordBidResponseByDealCountInHB), arg0, arg1, arg2, arg3)
}
-// RecordBidResponseByDealCountInPBS mocks base method.
+// RecordBidResponseByDealCountInPBS mocks base method
func (m *MockMetricsEngine) RecordBidResponseByDealCountInPBS(arg0, arg1, arg2, arg3 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordBidResponseByDealCountInPBS", arg0, arg1, arg2, arg3)
}
-// RecordBidResponseByDealCountInPBS indicates an expected call of RecordBidResponseByDealCountInPBS.
+// RecordBidResponseByDealCountInPBS indicates an expected call of RecordBidResponseByDealCountInPBS
func (mr *MockMetricsEngineMockRecorder) RecordBidResponseByDealCountInPBS(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordBidResponseByDealCountInPBS", reflect.TypeOf((*MockMetricsEngine)(nil).RecordBidResponseByDealCountInPBS), arg0, arg1, arg2, arg3)
}
-// RecordBids mocks base method.
+// RecordBids mocks base method
func (m *MockMetricsEngine) RecordBids(arg0, arg1, arg2, arg3 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordBids", arg0, arg1, arg2, arg3)
}
-// RecordBids indicates an expected call of RecordBids.
+// RecordBids indicates an expected call of RecordBids
func (mr *MockMetricsEngineMockRecorder) RecordBids(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordBids", reflect.TypeOf((*MockMetricsEngine)(nil).RecordBids), arg0, arg1, arg2, arg3)
}
-// RecordCTVHTTPMethodRequests mocks base method.
+// RecordCTVHTTPMethodRequests mocks base method
func (m *MockMetricsEngine) RecordCTVHTTPMethodRequests(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordCTVHTTPMethodRequests", arg0, arg1, arg2)
}
-// RecordCTVHTTPMethodRequests indicates an expected call of RecordCTVHTTPMethodRequests.
+// RecordCTVHTTPMethodRequests indicates an expected call of RecordCTVHTTPMethodRequests
func (mr *MockMetricsEngineMockRecorder) RecordCTVHTTPMethodRequests(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVHTTPMethodRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVHTTPMethodRequests), arg0, arg1, arg2)
}
-// RecordCTVInvalidReasonCount mocks base method.
+// RecordCTVInvalidReasonCount mocks base method
func (m *MockMetricsEngine) RecordCTVInvalidReasonCount(arg0 int, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordCTVInvalidReasonCount", arg0, arg1)
}
-// RecordCTVInvalidReasonCount indicates an expected call of RecordCTVInvalidReasonCount.
+// RecordCTVInvalidReasonCount indicates an expected call of RecordCTVInvalidReasonCount
func (mr *MockMetricsEngineMockRecorder) RecordCTVInvalidReasonCount(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVInvalidReasonCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVInvalidReasonCount), arg0, arg1)
}
-// RecordCTVReqCountWithAdPod mocks base method.
+// RecordCTVReqCountWithAdPod mocks base method
func (m *MockMetricsEngine) RecordCTVReqCountWithAdPod(arg0, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordCTVReqCountWithAdPod", arg0, arg1)
}
-// RecordCTVReqCountWithAdPod indicates an expected call of RecordCTVReqCountWithAdPod.
+// RecordCTVReqCountWithAdPod indicates an expected call of RecordCTVReqCountWithAdPod
func (mr *MockMetricsEngineMockRecorder) RecordCTVReqCountWithAdPod(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVReqCountWithAdPod", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVReqCountWithAdPod), arg0, arg1)
}
-// RecordCTVReqImpsWithDbConfigCount mocks base method.
+// RecordCTVReqImpsWithDbConfigCount mocks base method
func (m *MockMetricsEngine) RecordCTVReqImpsWithDbConfigCount(arg0 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordCTVReqImpsWithDbConfigCount", arg0)
}
-// RecordCTVReqImpsWithDbConfigCount indicates an expected call of RecordCTVReqImpsWithDbConfigCount.
+// RecordCTVReqImpsWithDbConfigCount indicates an expected call of RecordCTVReqImpsWithDbConfigCount
func (mr *MockMetricsEngineMockRecorder) RecordCTVReqImpsWithDbConfigCount(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVReqImpsWithDbConfigCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVReqImpsWithDbConfigCount), arg0)
}
-// RecordCTVReqImpsWithReqConfigCount mocks base method.
+// RecordCTVReqImpsWithReqConfigCount mocks base method
func (m *MockMetricsEngine) RecordCTVReqImpsWithReqConfigCount(arg0 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordCTVReqImpsWithReqConfigCount", arg0)
}
-// RecordCTVReqImpsWithReqConfigCount indicates an expected call of RecordCTVReqImpsWithReqConfigCount.
+// RecordCTVReqImpsWithReqConfigCount indicates an expected call of RecordCTVReqImpsWithReqConfigCount
func (mr *MockMetricsEngineMockRecorder) RecordCTVReqImpsWithReqConfigCount(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVReqImpsWithReqConfigCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVReqImpsWithReqConfigCount), arg0)
}
-// RecordCTVRequests mocks base method.
+// RecordCTVRequests mocks base method
func (m *MockMetricsEngine) RecordCTVRequests(arg0, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordCTVRequests", arg0, arg1)
}
-// RecordCTVRequests indicates an expected call of RecordCTVRequests.
+// RecordCTVRequests indicates an expected call of RecordCTVRequests
func (mr *MockMetricsEngineMockRecorder) RecordCTVRequests(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCTVRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCTVRequests), arg0, arg1)
}
-// RecordCacheErrorRequests mocks base method.
+// RecordCacheErrorRequests mocks base method
func (m *MockMetricsEngine) RecordCacheErrorRequests(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordCacheErrorRequests", arg0, arg1, arg2)
}
-// RecordCacheErrorRequests indicates an expected call of RecordCacheErrorRequests.
+// RecordCacheErrorRequests indicates an expected call of RecordCacheErrorRequests
func (mr *MockMetricsEngineMockRecorder) RecordCacheErrorRequests(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCacheErrorRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCacheErrorRequests), arg0, arg1, arg2)
}
-// RecordCtvUaAccuracy mocks base method.
+// RecordCtvUaAccuracy mocks base method
func (m *MockMetricsEngine) RecordCtvUaAccuracy(arg0, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordCtvUaAccuracy", arg0, arg1)
}
-// RecordCtvUaAccuracy indicates an expected call of RecordCtvUaAccuracy.
+// RecordCtvUaAccuracy indicates an expected call of RecordCtvUaAccuracy
func (mr *MockMetricsEngineMockRecorder) RecordCtvUaAccuracy(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordCtvUaAccuracy", reflect.TypeOf((*MockMetricsEngine)(nil).RecordCtvUaAccuracy), arg0, arg1)
}
-// RecordDBQueryFailure mocks base method.
+// RecordDBQueryFailure mocks base method
func (m *MockMetricsEngine) RecordDBQueryFailure(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordDBQueryFailure", arg0, arg1, arg2)
}
-// RecordDBQueryFailure indicates an expected call of RecordDBQueryFailure.
+// RecordDBQueryFailure indicates an expected call of RecordDBQueryFailure
func (mr *MockMetricsEngineMockRecorder) RecordDBQueryFailure(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordDBQueryFailure", reflect.TypeOf((*MockMetricsEngine)(nil).RecordDBQueryFailure), arg0, arg1, arg2)
@@ -263,397 +262,385 @@ func (mr *MockMetricsEngineMockRecorder) RecordGetProfileDataTime(arg0 interface
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordGetProfileDataTime", reflect.TypeOf((*MockMetricsEngine)(nil).RecordGetProfileDataTime), arg0)
}
-// RecordHTTPCounter mocks base method.
-func (m *MockMetricsEngine) RecordHTTPCounter() {
- m.ctrl.T.Helper()
- m.ctrl.Call(m, "RecordHTTPCounter")
-}
-
-// RecordHTTPCounter indicates an expected call of RecordHTTPCounter.
-func (mr *MockMetricsEngineMockRecorder) RecordHTTPCounter() *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordHTTPCounter", reflect.TypeOf((*MockMetricsEngine)(nil).RecordHTTPCounter))
-}
-
-// RecordImpDisabledViaConfigStats mocks base method.
+// RecordImpDisabledViaConfigStats mocks base method
func (m *MockMetricsEngine) RecordImpDisabledViaConfigStats(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordImpDisabledViaConfigStats", arg0, arg1, arg2)
}
-// RecordImpDisabledViaConfigStats indicates an expected call of RecordImpDisabledViaConfigStats.
+// RecordImpDisabledViaConfigStats indicates an expected call of RecordImpDisabledViaConfigStats
func (mr *MockMetricsEngineMockRecorder) RecordImpDisabledViaConfigStats(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordImpDisabledViaConfigStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordImpDisabledViaConfigStats), arg0, arg1, arg2)
}
-// RecordInjectTrackerErrorCount mocks base method.
+// RecordInjectTrackerErrorCount mocks base method
func (m *MockMetricsEngine) RecordInjectTrackerErrorCount(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordInjectTrackerErrorCount", arg0, arg1, arg2)
}
-// RecordInjectTrackerErrorCount indicates an expected call of RecordInjectTrackerErrorCount.
+// RecordInjectTrackerErrorCount indicates an expected call of RecordInjectTrackerErrorCount
func (mr *MockMetricsEngineMockRecorder) RecordInjectTrackerErrorCount(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordInjectTrackerErrorCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordInjectTrackerErrorCount), arg0, arg1, arg2)
}
-// RecordInvalidCreativeStats mocks base method.
+// RecordInvalidCreativeStats mocks base method
func (m *MockMetricsEngine) RecordInvalidCreativeStats(arg0, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordInvalidCreativeStats", arg0, arg1)
}
-// RecordInvalidCreativeStats indicates an expected call of RecordInvalidCreativeStats.
+// RecordInvalidCreativeStats indicates an expected call of RecordInvalidCreativeStats
func (mr *MockMetricsEngineMockRecorder) RecordInvalidCreativeStats(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordInvalidCreativeStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordInvalidCreativeStats), arg0, arg1)
}
-// RecordLurlBatchSent mocks base method.
+// RecordLurlBatchSent mocks base method
func (m *MockMetricsEngine) RecordLurlBatchSent(arg0 metrics.LurlBatchStatusLabels) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordLurlBatchSent", arg0)
}
-// RecordLurlBatchSent indicates an expected call of RecordLurlBatchSent.
+// RecordLurlBatchSent indicates an expected call of RecordLurlBatchSent
func (mr *MockMetricsEngineMockRecorder) RecordLurlBatchSent(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordLurlBatchSent", reflect.TypeOf((*MockMetricsEngine)(nil).RecordLurlBatchSent), arg0)
}
-// RecordLurlSent mocks base method.
+// RecordLurlSent mocks base method
func (m *MockMetricsEngine) RecordLurlSent(arg0 metrics.LurlStatusLabels) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordLurlSent", arg0)
}
-// RecordLurlSent indicates an expected call of RecordLurlSent.
+// RecordLurlSent indicates an expected call of RecordLurlSent
func (mr *MockMetricsEngineMockRecorder) RecordLurlSent(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordLurlSent", reflect.TypeOf((*MockMetricsEngine)(nil).RecordLurlSent), arg0)
}
-// RecordNobidErrPrebidServerRequests mocks base method.
+// RecordNobidErrPrebidServerRequests mocks base method
func (m *MockMetricsEngine) RecordNobidErrPrebidServerRequests(arg0 string, arg1 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordNobidErrPrebidServerRequests", arg0, arg1)
}
-// RecordNobidErrPrebidServerRequests indicates an expected call of RecordNobidErrPrebidServerRequests.
+// RecordNobidErrPrebidServerRequests indicates an expected call of RecordNobidErrPrebidServerRequests
func (mr *MockMetricsEngineMockRecorder) RecordNobidErrPrebidServerRequests(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordNobidErrPrebidServerRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordNobidErrPrebidServerRequests), arg0, arg1)
}
-// RecordNobidErrPrebidServerResponse mocks base method.
+// RecordNobidErrPrebidServerResponse mocks base method
func (m *MockMetricsEngine) RecordNobidErrPrebidServerResponse(arg0 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordNobidErrPrebidServerResponse", arg0)
}
-// RecordNobidErrPrebidServerResponse indicates an expected call of RecordNobidErrPrebidServerResponse.
+// RecordNobidErrPrebidServerResponse indicates an expected call of RecordNobidErrPrebidServerResponse
func (mr *MockMetricsEngineMockRecorder) RecordNobidErrPrebidServerResponse(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordNobidErrPrebidServerResponse", reflect.TypeOf((*MockMetricsEngine)(nil).RecordNobidErrPrebidServerResponse), arg0)
}
-// RecordOWServerPanic mocks base method.
+// RecordOWServerPanic mocks base method
func (m *MockMetricsEngine) RecordOWServerPanic(arg0, arg1, arg2, arg3 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordOWServerPanic", arg0, arg1, arg2, arg3)
}
-// RecordOWServerPanic indicates an expected call of RecordOWServerPanic.
+// RecordOWServerPanic indicates an expected call of RecordOWServerPanic
func (mr *MockMetricsEngineMockRecorder) RecordOWServerPanic(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordOWServerPanic", reflect.TypeOf((*MockMetricsEngine)(nil).RecordOWServerPanic), arg0, arg1, arg2, arg3)
}
-// RecordOpenWrapServerPanicStats mocks base method.
+// RecordOpenWrapServerPanicStats mocks base method
func (m *MockMetricsEngine) RecordOpenWrapServerPanicStats(arg0, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordOpenWrapServerPanicStats", arg0, arg1)
}
-// RecordOpenWrapServerPanicStats indicates an expected call of RecordOpenWrapServerPanicStats.
+// RecordOpenWrapServerPanicStats indicates an expected call of RecordOpenWrapServerPanicStats
func (mr *MockMetricsEngineMockRecorder) RecordOpenWrapServerPanicStats(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordOpenWrapServerPanicStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordOpenWrapServerPanicStats), arg0, arg1)
}
-// RecordPBSAuctionRequestsStats mocks base method.
+// RecordPBSAuctionRequestsStats mocks base method
func (m *MockMetricsEngine) RecordPBSAuctionRequestsStats() {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPBSAuctionRequestsStats")
}
-// RecordPBSAuctionRequestsStats indicates an expected call of RecordPBSAuctionRequestsStats.
+// RecordPBSAuctionRequestsStats indicates an expected call of RecordPBSAuctionRequestsStats
func (mr *MockMetricsEngineMockRecorder) RecordPBSAuctionRequestsStats() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPBSAuctionRequestsStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPBSAuctionRequestsStats))
}
-// RecordPartnerConfigErrors mocks base method.
+// RecordPartnerConfigErrors mocks base method
func (m *MockMetricsEngine) RecordPartnerConfigErrors(arg0, arg1, arg2 string, arg3 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPartnerConfigErrors", arg0, arg1, arg2, arg3)
}
-// RecordPartnerConfigErrors indicates an expected call of RecordPartnerConfigErrors.
+// RecordPartnerConfigErrors indicates an expected call of RecordPartnerConfigErrors
func (mr *MockMetricsEngineMockRecorder) RecordPartnerConfigErrors(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPartnerConfigErrors", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPartnerConfigErrors), arg0, arg1, arg2, arg3)
}
-// RecordPartnerResponseErrors mocks base method.
+// RecordPartnerResponseErrors mocks base method
func (m *MockMetricsEngine) RecordPartnerResponseErrors(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPartnerResponseErrors", arg0, arg1, arg2)
}
-// RecordPartnerResponseErrors indicates an expected call of RecordPartnerResponseErrors.
+// RecordPartnerResponseErrors indicates an expected call of RecordPartnerResponseErrors
func (mr *MockMetricsEngineMockRecorder) RecordPartnerResponseErrors(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPartnerResponseErrors", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPartnerResponseErrors), arg0, arg1, arg2)
}
-// RecordPartnerResponseTimeStats mocks base method.
+// RecordPartnerResponseTimeStats mocks base method
func (m *MockMetricsEngine) RecordPartnerResponseTimeStats(arg0, arg1 string, arg2 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPartnerResponseTimeStats", arg0, arg1, arg2)
}
-// RecordPartnerResponseTimeStats indicates an expected call of RecordPartnerResponseTimeStats.
+// RecordPartnerResponseTimeStats indicates an expected call of RecordPartnerResponseTimeStats
func (mr *MockMetricsEngineMockRecorder) RecordPartnerResponseTimeStats(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPartnerResponseTimeStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPartnerResponseTimeStats), arg0, arg1, arg2)
}
-// RecordPartnerTimeoutInPBS mocks base method.
+// RecordPartnerTimeoutInPBS mocks base method
func (m *MockMetricsEngine) RecordPartnerTimeoutInPBS(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPartnerTimeoutInPBS", arg0, arg1, arg2)
}
-// RecordPartnerTimeoutInPBS indicates an expected call of RecordPartnerTimeoutInPBS.
+// RecordPartnerTimeoutInPBS indicates an expected call of RecordPartnerTimeoutInPBS
func (mr *MockMetricsEngineMockRecorder) RecordPartnerTimeoutInPBS(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPartnerTimeoutInPBS", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPartnerTimeoutInPBS), arg0, arg1, arg2)
}
-// RecordPartnerTimeoutRequests mocks base method.
+// RecordPartnerTimeoutRequests mocks base method
func (m *MockMetricsEngine) RecordPartnerTimeoutRequests(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPartnerTimeoutRequests", arg0, arg1, arg2)
}
-// RecordPartnerTimeoutRequests indicates an expected call of RecordPartnerTimeoutRequests.
+// RecordPartnerTimeoutRequests indicates an expected call of RecordPartnerTimeoutRequests
func (mr *MockMetricsEngineMockRecorder) RecordPartnerTimeoutRequests(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPartnerTimeoutRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPartnerTimeoutRequests), arg0, arg1, arg2)
}
-// RecordPlatformPublisherPartnerReqStats mocks base method.
+// RecordPlatformPublisherPartnerReqStats mocks base method
func (m *MockMetricsEngine) RecordPlatformPublisherPartnerReqStats(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPlatformPublisherPartnerReqStats", arg0, arg1, arg2)
}
-// RecordPlatformPublisherPartnerReqStats indicates an expected call of RecordPlatformPublisherPartnerReqStats.
+// RecordPlatformPublisherPartnerReqStats indicates an expected call of RecordPlatformPublisherPartnerReqStats
func (mr *MockMetricsEngineMockRecorder) RecordPlatformPublisherPartnerReqStats(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPlatformPublisherPartnerReqStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPlatformPublisherPartnerReqStats), arg0, arg1, arg2)
}
-// RecordPlatformPublisherPartnerResponseStats mocks base method.
+// RecordPlatformPublisherPartnerResponseStats mocks base method
func (m *MockMetricsEngine) RecordPlatformPublisherPartnerResponseStats(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPlatformPublisherPartnerResponseStats", arg0, arg1, arg2)
}
-// RecordPlatformPublisherPartnerResponseStats indicates an expected call of RecordPlatformPublisherPartnerResponseStats.
+// RecordPlatformPublisherPartnerResponseStats indicates an expected call of RecordPlatformPublisherPartnerResponseStats
func (mr *MockMetricsEngineMockRecorder) RecordPlatformPublisherPartnerResponseStats(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPlatformPublisherPartnerResponseStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPlatformPublisherPartnerResponseStats), arg0, arg1, arg2)
}
-// RecordPreProcessingTimeStats mocks base method.
+// RecordPreProcessingTimeStats mocks base method
func (m *MockMetricsEngine) RecordPreProcessingTimeStats(arg0 string, arg1 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPreProcessingTimeStats", arg0, arg1)
}
-// RecordPreProcessingTimeStats indicates an expected call of RecordPreProcessingTimeStats.
+// RecordPreProcessingTimeStats indicates an expected call of RecordPreProcessingTimeStats
func (mr *MockMetricsEngineMockRecorder) RecordPreProcessingTimeStats(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPreProcessingTimeStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPreProcessingTimeStats), arg0, arg1)
}
-// RecordPrebidTimeoutRequests mocks base method.
+// RecordPrebidTimeoutRequests mocks base method
func (m *MockMetricsEngine) RecordPrebidTimeoutRequests(arg0, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPrebidTimeoutRequests", arg0, arg1)
}
-// RecordPrebidTimeoutRequests indicates an expected call of RecordPrebidTimeoutRequests.
+// RecordPrebidTimeoutRequests indicates an expected call of RecordPrebidTimeoutRequests
func (mr *MockMetricsEngineMockRecorder) RecordPrebidTimeoutRequests(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPrebidTimeoutRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPrebidTimeoutRequests), arg0, arg1)
}
-// RecordPublisherInvalidProfileImpressions mocks base method.
+// RecordPublisherInvalidProfileImpressions mocks base method
func (m *MockMetricsEngine) RecordPublisherInvalidProfileImpressions(arg0, arg1 string, arg2 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPublisherInvalidProfileImpressions", arg0, arg1, arg2)
}
-// RecordPublisherInvalidProfileImpressions indicates an expected call of RecordPublisherInvalidProfileImpressions.
+// RecordPublisherInvalidProfileImpressions indicates an expected call of RecordPublisherInvalidProfileImpressions
func (mr *MockMetricsEngineMockRecorder) RecordPublisherInvalidProfileImpressions(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherInvalidProfileImpressions", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherInvalidProfileImpressions), arg0, arg1, arg2)
}
-// RecordPublisherInvalidProfileRequests mocks base method.
+// RecordPublisherInvalidProfileRequests mocks base method
func (m *MockMetricsEngine) RecordPublisherInvalidProfileRequests(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPublisherInvalidProfileRequests", arg0, arg1, arg2)
}
-// RecordPublisherInvalidProfileRequests indicates an expected call of RecordPublisherInvalidProfileRequests.
+// RecordPublisherInvalidProfileRequests indicates an expected call of RecordPublisherInvalidProfileRequests
func (mr *MockMetricsEngineMockRecorder) RecordPublisherInvalidProfileRequests(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherInvalidProfileRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherInvalidProfileRequests), arg0, arg1, arg2)
}
-// RecordPublisherPartnerNoCookieStats mocks base method.
+// RecordPublisherPartnerNoCookieStats mocks base method
func (m *MockMetricsEngine) RecordPublisherPartnerNoCookieStats(arg0, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPublisherPartnerNoCookieStats", arg0, arg1)
}
-// RecordPublisherPartnerNoCookieStats indicates an expected call of RecordPublisherPartnerNoCookieStats.
+// RecordPublisherPartnerNoCookieStats indicates an expected call of RecordPublisherPartnerNoCookieStats
func (mr *MockMetricsEngineMockRecorder) RecordPublisherPartnerNoCookieStats(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherPartnerNoCookieStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherPartnerNoCookieStats), arg0, arg1)
}
-// RecordPublisherProfileRequests mocks base method.
+// RecordPublisherProfileRequests mocks base method
func (m *MockMetricsEngine) RecordPublisherProfileRequests(arg0, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPublisherProfileRequests", arg0, arg1)
}
-// RecordPublisherProfileRequests indicates an expected call of RecordPublisherProfileRequests.
+// RecordPublisherProfileRequests indicates an expected call of RecordPublisherProfileRequests
func (mr *MockMetricsEngineMockRecorder) RecordPublisherProfileRequests(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherProfileRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherProfileRequests), arg0, arg1)
}
-// RecordPublisherRequests mocks base method.
+// RecordPublisherRequests mocks base method
func (m *MockMetricsEngine) RecordPublisherRequests(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPublisherRequests", arg0, arg1, arg2)
}
-// RecordPublisherRequests indicates an expected call of RecordPublisherRequests.
+// RecordPublisherRequests indicates an expected call of RecordPublisherRequests
func (mr *MockMetricsEngineMockRecorder) RecordPublisherRequests(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherRequests), arg0, arg1, arg2)
}
-// RecordPublisherResponseEncodingErrorStats mocks base method.
+// RecordPublisherResponseEncodingErrorStats mocks base method
func (m *MockMetricsEngine) RecordPublisherResponseEncodingErrorStats(arg0 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPublisherResponseEncodingErrorStats", arg0)
}
-// RecordPublisherResponseEncodingErrorStats indicates an expected call of RecordPublisherResponseEncodingErrorStats.
+// RecordPublisherResponseEncodingErrorStats indicates an expected call of RecordPublisherResponseEncodingErrorStats
func (mr *MockMetricsEngineMockRecorder) RecordPublisherResponseEncodingErrorStats(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherResponseEncodingErrorStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherResponseEncodingErrorStats), arg0)
}
-// RecordPublisherResponseTimeStats mocks base method.
+// RecordPublisherResponseTimeStats mocks base method
func (m *MockMetricsEngine) RecordPublisherResponseTimeStats(arg0 string, arg1 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPublisherResponseTimeStats", arg0, arg1)
}
-// RecordPublisherResponseTimeStats indicates an expected call of RecordPublisherResponseTimeStats.
+// RecordPublisherResponseTimeStats indicates an expected call of RecordPublisherResponseTimeStats
func (mr *MockMetricsEngineMockRecorder) RecordPublisherResponseTimeStats(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherResponseTimeStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherResponseTimeStats), arg0, arg1)
}
-// RecordPublisherWrapperLoggerFailure mocks base method.
+// RecordPublisherWrapperLoggerFailure mocks base method
func (m *MockMetricsEngine) RecordPublisherWrapperLoggerFailure(arg0, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordPublisherWrapperLoggerFailure", arg0, arg1, arg2)
}
-// RecordPublisherWrapperLoggerFailure indicates an expected call of RecordPublisherWrapperLoggerFailure.
+// RecordPublisherWrapperLoggerFailure indicates an expected call of RecordPublisherWrapperLoggerFailure
func (mr *MockMetricsEngineMockRecorder) RecordPublisherWrapperLoggerFailure(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPublisherWrapperLoggerFailure", reflect.TypeOf((*MockMetricsEngine)(nil).RecordPublisherWrapperLoggerFailure), arg0, arg1, arg2)
}
-// RecordReqImpsWithContentCount mocks base method.
+// RecordReqImpsWithContentCount mocks base method
func (m *MockMetricsEngine) RecordReqImpsWithContentCount(arg0, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordReqImpsWithContentCount", arg0, arg1)
}
-// RecordReqImpsWithContentCount indicates an expected call of RecordReqImpsWithContentCount.
+// RecordReqImpsWithContentCount indicates an expected call of RecordReqImpsWithContentCount
func (mr *MockMetricsEngineMockRecorder) RecordReqImpsWithContentCount(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordReqImpsWithContentCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordReqImpsWithContentCount), arg0, arg1)
}
-// RecordRequest mocks base method.
+// RecordRequest mocks base method
func (m *MockMetricsEngine) RecordRequest(arg0 metrics.Labels) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordRequest", arg0)
}
-// RecordRequest indicates an expected call of RecordRequest.
+// RecordRequest indicates an expected call of RecordRequest
func (mr *MockMetricsEngineMockRecorder) RecordRequest(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordRequest", reflect.TypeOf((*MockMetricsEngine)(nil).RecordRequest), arg0)
}
-// RecordRequestAdPodGeneratedImpressionsCount mocks base method.
+// RecordRequestAdPodGeneratedImpressionsCount mocks base method
func (m *MockMetricsEngine) RecordRequestAdPodGeneratedImpressionsCount(arg0 int, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordRequestAdPodGeneratedImpressionsCount", arg0, arg1)
}
-// RecordRequestAdPodGeneratedImpressionsCount indicates an expected call of RecordRequestAdPodGeneratedImpressionsCount.
+// RecordRequestAdPodGeneratedImpressionsCount indicates an expected call of RecordRequestAdPodGeneratedImpressionsCount
func (mr *MockMetricsEngineMockRecorder) RecordRequestAdPodGeneratedImpressionsCount(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordRequestAdPodGeneratedImpressionsCount", reflect.TypeOf((*MockMetricsEngine)(nil).RecordRequestAdPodGeneratedImpressionsCount), arg0, arg1)
}
-// RecordRequestTime mocks base method.
+// RecordRequestTime mocks base method
func (m *MockMetricsEngine) RecordRequestTime(arg0 string, arg1 time.Duration) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordRequestTime", arg0, arg1)
}
-// RecordRequestTime indicates an expected call of RecordRequestTime.
+// RecordRequestTime indicates an expected call of RecordRequestTime
func (mr *MockMetricsEngineMockRecorder) RecordRequestTime(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordRequestTime", reflect.TypeOf((*MockMetricsEngine)(nil).RecordRequestTime), arg0, arg1)
}
-// RecordSSTimeoutRequests mocks base method.
+// RecordSSTimeoutRequests mocks base method
func (m *MockMetricsEngine) RecordSSTimeoutRequests(arg0, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordSSTimeoutRequests", arg0, arg1)
}
-// RecordSSTimeoutRequests indicates an expected call of RecordSSTimeoutRequests.
+// RecordSSTimeoutRequests indicates an expected call of RecordSSTimeoutRequests
func (mr *MockMetricsEngineMockRecorder) RecordSSTimeoutRequests(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordSSTimeoutRequests", reflect.TypeOf((*MockMetricsEngine)(nil).RecordSSTimeoutRequests), arg0, arg1)
@@ -671,25 +658,25 @@ func (mr *MockMetricsEngineMockRecorder) RecordSendLoggerDataTime(arg0 interface
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordSendLoggerDataTime", reflect.TypeOf((*MockMetricsEngine)(nil).RecordSendLoggerDataTime), arg0)
}
-// RecordStatsKeyCTVPrebidFailedImpression mocks base method.
+// RecordStatsKeyCTVPrebidFailedImpression mocks base method
func (m *MockMetricsEngine) RecordStatsKeyCTVPrebidFailedImpression(arg0 int, arg1, arg2 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordStatsKeyCTVPrebidFailedImpression", arg0, arg1, arg2)
}
-// RecordStatsKeyCTVPrebidFailedImpression indicates an expected call of RecordStatsKeyCTVPrebidFailedImpression.
+// RecordStatsKeyCTVPrebidFailedImpression indicates an expected call of RecordStatsKeyCTVPrebidFailedImpression
func (mr *MockMetricsEngineMockRecorder) RecordStatsKeyCTVPrebidFailedImpression(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordStatsKeyCTVPrebidFailedImpression", reflect.TypeOf((*MockMetricsEngine)(nil).RecordStatsKeyCTVPrebidFailedImpression), arg0, arg1, arg2)
}
-// RecordUidsCookieNotPresentErrorStats mocks base method.
+// RecordUidsCookieNotPresentErrorStats mocks base method
func (m *MockMetricsEngine) RecordUidsCookieNotPresentErrorStats(arg0, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordUidsCookieNotPresentErrorStats", arg0, arg1)
}
-// RecordUidsCookieNotPresentErrorStats indicates an expected call of RecordUidsCookieNotPresentErrorStats.
+// RecordUidsCookieNotPresentErrorStats indicates an expected call of RecordUidsCookieNotPresentErrorStats
func (mr *MockMetricsEngineMockRecorder) RecordUidsCookieNotPresentErrorStats(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordUidsCookieNotPresentErrorStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordUidsCookieNotPresentErrorStats), arg0, arg1)
@@ -749,31 +736,31 @@ func (m *MockMetricsEngine) RecordVideoImpDisabledViaConnTypeStats(arg0, arg1 st
m.ctrl.Call(m, "RecordVideoImpDisabledViaConnTypeStats", arg0, arg1)
}
-// RecordVideoImpDisabledViaConnTypeStats indicates an expected call of RecordVideoImpDisabledViaConnTypeStats.
+// RecordVideoImpDisabledViaConnTypeStats indicates an expected call of RecordVideoImpDisabledViaConnTypeStats
func (mr *MockMetricsEngineMockRecorder) RecordVideoImpDisabledViaConnTypeStats(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordVideoImpDisabledViaConnTypeStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordVideoImpDisabledViaConnTypeStats), arg0, arg1)
}
-// RecordVideoInstlImpsStats mocks base method.
+// RecordVideoInstlImpsStats mocks base method
func (m *MockMetricsEngine) RecordVideoInstlImpsStats(arg0, arg1 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RecordVideoInstlImpsStats", arg0, arg1)
}
-// RecordVideoInstlImpsStats indicates an expected call of RecordVideoInstlImpsStats.
+// RecordVideoInstlImpsStats indicates an expected call of RecordVideoInstlImpsStats
func (mr *MockMetricsEngineMockRecorder) RecordVideoInstlImpsStats(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordVideoInstlImpsStats", reflect.TypeOf((*MockMetricsEngine)(nil).RecordVideoInstlImpsStats), arg0, arg1)
}
-// Shutdown mocks base method.
+// Shutdown mocks base method
func (m *MockMetricsEngine) Shutdown() {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Shutdown")
}
-// Shutdown indicates an expected call of Shutdown.
+// Shutdown indicates an expected call of Shutdown
func (mr *MockMetricsEngineMockRecorder) Shutdown() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Shutdown", reflect.TypeOf((*MockMetricsEngine)(nil).Shutdown))
diff --git a/modules/pubmatic/openwrap/metrics/prometheus/prometheus.go b/modules/pubmatic/openwrap/metrics/prometheus/prometheus.go
index dc6cb8cd614..4e68a07102e 100644
--- a/modules/pubmatic/openwrap/metrics/prometheus/prometheus.go
+++ b/modules/pubmatic/openwrap/metrics/prometheus/prometheus.go
@@ -13,8 +13,7 @@ import (
type Metrics struct {
// general metrics
- panics *prometheus.CounterVec
- httpCounter *prometheus.CounterVec
+ panics *prometheus.CounterVec
// publisher-partner level metrics
pubPartnerNoCookie *prometheus.CounterVec
@@ -119,12 +118,6 @@ func newMetrics(cfg *config.PrometheusMetrics, promRegistry *prometheus.Registry
[]string{hostLabel, methodLabel},
)
- metrics.httpCounter = newCounter(cfg, promRegistry,
- "total_http_request",
- "Count of total http requests",
- []string{},
- )
-
// publisher-partner level metrics
// TODO : check description of this
metrics.pubPartnerNoCookie = newCounter(cfg, promRegistry,
@@ -498,10 +491,6 @@ func (m *Metrics) RecordPublisherWrapperLoggerFailure(publisher, profile, versio
}).Inc()
}
-func (m *Metrics) RecordHTTPCounter() {
- m.httpCounter.With(nil).Inc()
-}
-
// RecordAnalyticsTrackingThrottled record analytics throttling at publisher profile level
func (m *Metrics) RecordAnalyticsTrackingThrottled(pubid, profileid, analyticsType string) {
m.analyticsThrottle.With(prometheus.Labels{
diff --git a/modules/pubmatic/openwrap/metrics/prometheus/prometheus_test.go b/modules/pubmatic/openwrap/metrics/prometheus/prometheus_test.go
index 9d8abf28cec..59e81b9c010 100644
--- a/modules/pubmatic/openwrap/metrics/prometheus/prometheus_test.go
+++ b/modules/pubmatic/openwrap/metrics/prometheus/prometheus_test.go
@@ -325,16 +325,6 @@ func TestRecordDBQueryFailure(t *testing.T) {
})
}
-func TestRecordHTTPCounter(t *testing.T) {
- m := createMetricsForTesting()
-
- m.RecordHTTPCounter()
-
- expectedCount := float64(1)
- assertCounterVecValue(t, "", "httpCounter", m.httpCounter,
- expectedCount, nil)
-}
-
func getHistogramFromHistogram(histogram prometheus.Histogram) dto.Histogram {
var result dto.Histogram
processMetrics(histogram, func(m dto.Metric) {
diff --git a/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go b/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go
index e15fb26bf17..0003f7f8c07 100644
--- a/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go
+++ b/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go
@@ -341,7 +341,6 @@ func (st *StatsTCP) RecordRequestTime(requestType string, requestTime time.Durat
func (st *StatsTCP) RecordOWServerPanic(endpoint, methodName, nodeName, podName string) {}
func (st *StatsTCP) RecordAmpVideoRequests(pubid, profileid string) {}
func (st *StatsTCP) RecordAmpVideoResponses(pubid, profileid string) {}
-func (st *StatsTCP) RecordHTTPCounter() {}
func (st *StatsTCP) RecordUnwrapRequestStatus(accountId, bidder, status string) {}
func (st *StatsTCP) RecordUnwrapWrapperCount(accountId, bidder, wrapper_count string) {}
func (st *StatsTCP) RecordUnwrapRequestTime(accountId, bidder string, respTime time.Duration) {}
diff --git a/modules/pubmatic/openwrap/models/constants.go b/modules/pubmatic/openwrap/models/constants.go
index 4c0a5733511..0d0d56ba230 100755
--- a/modules/pubmatic/openwrap/models/constants.go
+++ b/modules/pubmatic/openwrap/models/constants.go
@@ -390,6 +390,7 @@ const (
MACRO_VASTTAG = "_VASTTAG_"
ADUNIT_SIZE_KGP = "_AU_@_W_x_H_"
+ ADUNIT_SIZE_REGEX_KGP = "_RE_@_W_x_H_"
REGEX_KGP = "_AU_@_DIV_@_W_x_H_"
DIV_SIZE_KGP = "_DIV_@_W_x_H_"
ADUNIT_SOURCE_VASTTAG_KGP = "_AU_@_SRC_@_VASTTAG_"
@@ -493,6 +494,7 @@ const (
//DisplayVersionInnerQuery = "DisplayVersionInnerQuery"
//LiveVersionInnerQuery = "LiveVersionInnerQuery"
//PMSlotToMappings = "GetPMSlotToMappings"
+ TestQuery = "TestQuery"
)
// constants for owlogger Integration Type
diff --git a/modules/pubmatic/openwrap/models/utils.go b/modules/pubmatic/openwrap/models/utils.go
index 42589e38859..baae78b0eaf 100644
--- a/modules/pubmatic/openwrap/models/utils.go
+++ b/modules/pubmatic/openwrap/models/utils.go
@@ -314,11 +314,11 @@ func GetKGPSV(bid openrtb2.Bid, bidderMeta PartnerData, adformat string, tagId s
func GenerateSlotName(h, w int64, kgp, tagid, div, src string) string {
// func (H, W, Div), no need to validate, will always be non-nil
switch kgp {
- case "_AU_": // adunitconfig
+ case "_AU_", "_RE_": // adunitconfig or defaultmappingKGP
return tagid
case "_DIV_":
return div
- case "_AU_@_W_x_H_":
+ case "_AU_@_W_x_H_", "_RE_@_W_x_H_":
return fmt.Sprintf("%s@%dx%d", tagid, w, h)
case "_DIV_@_W_x_H_":
return fmt.Sprintf("%s@%dx%d", div, w, h)
diff --git a/modules/pubmatic/openwrap/models/utils_test.go b/modules/pubmatic/openwrap/models/utils_test.go
index df11e12dd7c..446a0c9b10a 100644
--- a/modules/pubmatic/openwrap/models/utils_test.go
+++ b/modules/pubmatic/openwrap/models/utils_test.go
@@ -457,6 +457,18 @@ func TestGenerateSlotName(t *testing.T) {
},
want: "/15671365/Test_Adunit",
},
+ {
+ name: "_RE_",
+ args: args{
+ h: 100,
+ w: 200,
+ kgp: "_RE_",
+ tagid: "/15671365/Test_Adunit",
+ div: "Div1",
+ src: "test.com",
+ },
+ want: "/15671365/Test_Adunit",
+ },
{
name: "_DIV_",
args: args{
@@ -493,6 +505,18 @@ func TestGenerateSlotName(t *testing.T) {
},
want: "/15671365/Test_Adunit@200x100",
},
+ {
+ name: "_RE_@_W_x_H_",
+ args: args{
+ h: 100,
+ w: 200,
+ kgp: "_RE_@_W_x_H_",
+ tagid: "/15671365/Test_Adunit",
+ div: "Div1",
+ src: "test.com",
+ },
+ want: "/15671365/Test_Adunit@200x100",
+ },
{
name: "_DIV_@_W_x_H_",
args: args{
diff --git a/modules/pubmatic/openwrap/nonbids.go b/modules/pubmatic/openwrap/nonbids.go
index b63a912f2f9..0c44e54a8fa 100644
--- a/modules/pubmatic/openwrap/nonbids.go
+++ b/modules/pubmatic/openwrap/nonbids.go
@@ -1,6 +1,7 @@
package openwrap
import (
+ "github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/nbr"
"github.com/prebid/prebid-server/v2/openrtb_ext"
@@ -8,27 +9,27 @@ import (
// prepareSeatNonBids forms the rctx.SeatNonBids map from rctx values
// currently, this function prepares and returns nonbids for partner-throttle and slot-not-mapped errors
-func prepareSeatNonBids(rctx models.RequestCtx) map[string][]openrtb_ext.NonBid {
+// prepareSeatNonBids forms the rctx.SeatNonBids map from rctx values
+// currently, this function prepares and returns nonbids for partner-throttle and slot-not-mapped errors
+func prepareSeatNonBids(rctx models.RequestCtx) openrtb_ext.NonBidCollection {
- seatNonBids := make(map[string][]openrtb_ext.NonBid, 0)
+ var seatNonBid openrtb_ext.NonBidCollection
for impID, impCtx := range rctx.ImpBidCtx {
// seat-non-bid for partner-throttled error
for bidder := range rctx.AdapterThrottleMap {
- seatNonBids[bidder] = append(seatNonBids[bidder], openrtb_ext.NonBid{
- ImpId: impID,
- StatusCode: int(nbr.RequestBlockedPartnerThrottle),
- })
+ nonBid := openrtb_ext.NewNonBid(openrtb_ext.NonBidParams{Bid: &openrtb2.Bid{ImpID: impID}, NonBidReason: int(nbr.RequestBlockedPartnerThrottle)})
+ seatNonBid.AddBid(nonBid, bidder)
+
}
+
// seat-non-bid for slot-not-mapped error
// Note : Throttled partner will not be a part of impCtx.NonMapped
for bidder := range impCtx.NonMapped {
- seatNonBids[bidder] = append(seatNonBids[bidder], openrtb_ext.NonBid{
- ImpId: impID,
- StatusCode: int(nbr.RequestBlockedSlotNotMapped),
- })
+ nonBid := openrtb_ext.NewNonBid(openrtb_ext.NonBidParams{Bid: &openrtb2.Bid{ImpID: impID}, NonBidReason: int(nbr.RequestBlockedSlotNotMapped)})
+ seatNonBid.AddBid(nonBid, bidder)
}
}
- return seatNonBids
+ return seatNonBid
}
// addSeatNonBidsInResponseExt adds the rctx.SeatNonBids in the response-ext
diff --git a/modules/pubmatic/openwrap/nonbids_test.go b/modules/pubmatic/openwrap/nonbids_test.go
index ac7573a0ef9..b0c7217244d 100644
--- a/modules/pubmatic/openwrap/nonbids_test.go
+++ b/modules/pubmatic/openwrap/nonbids_test.go
@@ -3,6 +3,7 @@ package openwrap
import (
"testing"
+ "github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/nbr"
"github.com/prebid/prebid-server/v2/openrtb_ext"
@@ -17,7 +18,7 @@ func TestPrepareSeatNonBids(t *testing.T) {
tests := []struct {
name string
args args
- seatNonBids map[string][]openrtb_ext.NonBid
+ seatNonBids openrtb_ext.NonBidCollection
}{
{
name: "empty_impbidctx",
@@ -26,7 +27,7 @@ func TestPrepareSeatNonBids(t *testing.T) {
SeatNonBids: make(map[string][]openrtb_ext.NonBid),
},
},
- seatNonBids: make(map[string][]openrtb_ext.NonBid),
+ seatNonBids: openrtb_ext.NonBidCollection{},
},
{
name: "empty_seatnonbids",
@@ -40,7 +41,7 @@ func TestPrepareSeatNonBids(t *testing.T) {
SeatNonBids: make(map[string][]openrtb_ext.NonBid),
},
},
- seatNonBids: make(map[string][]openrtb_ext.NonBid),
+ seatNonBids: openrtb_ext.NonBidCollection{},
},
{
name: "partner_throttled_nonbids",
@@ -57,14 +58,7 @@ func TestPrepareSeatNonBids(t *testing.T) {
SeatNonBids: map[string][]openrtb_ext.NonBid{},
},
},
- seatNonBids: map[string][]openrtb_ext.NonBid{
- "pubmatic": {
- openrtb_ext.NonBid{
- ImpId: "imp1",
- StatusCode: int(nbr.RequestBlockedPartnerThrottle),
- },
- },
- },
+ seatNonBids: getNonBids(map[string][]openrtb_ext.NonBidParams{"pubmatic": {{Bid: &openrtb2.Bid{ImpID: "imp1"}, NonBidReason: int(nbr.RequestBlockedPartnerThrottle)}}}),
},
{
name: "slot_not_mapped_nonbids",
@@ -88,20 +82,22 @@ func TestPrepareSeatNonBids(t *testing.T) {
},
},
},
- seatNonBids: map[string][]openrtb_ext.NonBid{
+ seatNonBids: getNonBids(map[string][]openrtb_ext.NonBidParams{
"pubmatic": {
{
- ImpId: "imp1",
- StatusCode: int(nbr.RequestBlockedSlotNotMapped),
+ Bid: &openrtb2.Bid{
+ ImpID: "imp1",
+ },
+ NonBidReason: int(nbr.RequestBlockedSlotNotMapped),
},
},
"appnexus": {
{
- ImpId: "imp1",
- StatusCode: int(nbr.RequestBlockedSlotNotMapped),
+ Bid: &openrtb2.Bid{ImpID: "imp1"},
+ NonBidReason: int(nbr.RequestBlockedSlotNotMapped),
},
},
- },
+ }),
},
{
name: "slot_not_mapped_plus_partner_throttled_nonbids",
@@ -113,42 +109,33 @@ func TestPrepareSeatNonBids(t *testing.T) {
"pubmatic": {},
},
},
- "imp2": {},
},
AdapterThrottleMap: map[string]struct{}{
"appnexus": {},
},
},
},
- seatNonBids: map[string][]openrtb_ext.NonBid{
+ seatNonBids: getNonBids(map[string][]openrtb_ext.NonBidParams{
"pubmatic": {
{
- ImpId: "imp1",
- StatusCode: int(nbr.RequestBlockedSlotNotMapped),
+ Bid: &openrtb2.Bid{ImpID: "imp1"},
+ NonBidReason: int(nbr.RequestBlockedSlotNotMapped),
},
},
"appnexus": {
{
- ImpId: "imp2",
- StatusCode: int(nbr.RequestBlockedPartnerThrottle),
- },
- {
- ImpId: "imp1",
- StatusCode: int(nbr.RequestBlockedPartnerThrottle),
+ Bid: &openrtb2.Bid{ImpID: "imp1"},
+ NonBidReason: int(nbr.RequestBlockedPartnerThrottle),
},
},
- },
+ }),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- seatNonBids := prepareSeatNonBids(tt.args.rctx)
- assert.Equal(t, len(seatNonBids), len(tt.seatNonBids))
- for k, v := range seatNonBids {
- // ignore order of elements in slice while comparing
- assert.ElementsMatch(t, v, tt.seatNonBids[k], tt.name)
- }
+ got := prepareSeatNonBids(tt.args.rctx)
+ assert.Equal(t, tt.seatNonBids, got, "mismatched seatnonbids")
})
}
}
@@ -826,3 +813,14 @@ func TestAddLostToDealBidNonBRCode(t *testing.T) {
})
}
}
+
+func getNonBids(bidParamsMap map[string][]openrtb_ext.NonBidParams) openrtb_ext.NonBidCollection {
+ nonBids := openrtb_ext.NonBidCollection{}
+ for bidder, bidParams := range bidParamsMap {
+ for _, bidParam := range bidParams {
+ nonBid := openrtb_ext.NewNonBid(bidParam)
+ nonBids.AddBid(nonBid, bidder)
+ }
+ }
+ return nonBids
+}
diff --git a/modules/pubmatic/openwrap/prometheus_handler.go b/modules/pubmatic/openwrap/prometheus_handler.go
new file mode 100644
index 00000000000..4eba5bc8af1
--- /dev/null
+++ b/modules/pubmatic/openwrap/prometheus_handler.go
@@ -0,0 +1,56 @@
+package openwrap
+
+import (
+ "net/http"
+ "time"
+
+ "github.com/golang/glog"
+ "github.com/prebid/prebid-server/v2/config"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics"
+
+ ow_metrics_prometheus "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics/prometheus"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
+)
+
+type loggerForPrometheus struct{}
+
+func (loggerForPrometheus) Println(v ...interface{}) {
+ glog.Warningln(v...)
+}
+
+func PrometheusHandler(reg prometheus.Gatherer, timeDur time.Duration, endpoint string) http.Handler {
+ handler := promhttp.HandlerFor(
+ reg,
+ promhttp.HandlerOpts{
+ ErrorLog: loggerForPrometheus{},
+ MaxRequestsInFlight: 5,
+ Timeout: timeDur,
+ },
+ )
+ return http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) {
+ ow.metricEngine.RecordRequest(
+ metrics.Labels{
+ RType: metrics.RequestType(endpoint),
+ RequestStatus: ow_metrics_prometheus.RequestStatusOK,
+ },
+ )
+ handler.ServeHTTP(rsp, req)
+ })
+}
+
+func initPrometheusStatsEndpoint(cfg *config.Configuration, gatherer *prometheus.Registry, promMux *http.ServeMux) {
+ promMux.Handle("/stats", PrometheusHandler(gatherer, cfg.Metrics.Prometheus.Timeout(), "stats"))
+}
+
+func initPrometheusMetricsEndpoint(cfg *config.Configuration, promMux *http.ServeMux) {
+ promMux.Handle("/metrics", PrometheusHandler(prometheus.DefaultGatherer, cfg.Metrics.Prometheus.Timeout(), "metrics"))
+}
+
+func GetOpenWrapPrometheusServer(cfg *config.Configuration, gatherer *prometheus.Registry, server *http.Server) *http.Server {
+ promMux := http.NewServeMux()
+ initPrometheusStatsEndpoint(cfg, gatherer, promMux)
+ initPrometheusMetricsEndpoint(cfg, promMux)
+ server.Handler = promMux
+ return server
+}
diff --git a/server/prometheus_ow_test.go b/modules/pubmatic/openwrap/prometheus_handler_test.go
similarity index 63%
rename from server/prometheus_ow_test.go
rename to modules/pubmatic/openwrap/prometheus_handler_test.go
index d4e1b6f6e37..7f5944b00c1 100644
--- a/server/prometheus_ow_test.go
+++ b/modules/pubmatic/openwrap/prometheus_handler_test.go
@@ -1,21 +1,78 @@
-package server
+package openwrap
import (
"context"
"net/http"
"net/http/httptest"
"testing"
+ "time"
- "github.com/magiconair/properties/assert"
+ "github.com/golang/mock/gomock"
"github.com/prebid/prebid-server/v2/config"
+ mock_metrics "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics/mock"
"github.com/prometheus/client_golang/prometheus"
+ "github.com/stretchr/testify/assert"
)
+func TestPrometheusHandler(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ mockMetrics := mock_metrics.NewMockMetricsEngine(ctrl)
+ ow = &OpenWrap{}
+ ow.metricEngine = mockMetrics
+ type args struct {
+ gatherer prometheus.Gatherer
+ duration time.Duration
+ setup func()
+ endpoint string
+ }
+ type testCase struct {
+ name string
+ args args
+ expectCode int
+ }
+
+ tests := []testCase{
+ {
+ name: "valid test",
+ args: args{
+ gatherer: prometheus.Gatherers{},
+ duration: 10 * time.Second,
+ endpoint: "/abc",
+ setup: func() {
+ mockMetrics.EXPECT().RecordRequest(gomock.Any()).AnyTimes()
+ },
+ },
+ expectCode: http.StatusOK,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ tt.args.setup()
+ handler := PrometheusHandler(tt.args.gatherer, tt.args.duration, tt.args.endpoint)
+ server := &http.Server{
+ Addr: ":" + "8991",
+ Handler: handler,
+ }
+ server.Shutdown(context.Background())
+ req := httptest.NewRequest("GET", tt.args.endpoint, nil)
+ rec := httptest.NewRecorder()
+ server.Handler.ServeHTTP(rec, req)
+ assert.Equal(t, rec.Code, tt.expectCode)
+
+ })
+ }
+}
+
func TestInitPrometheusStatsEndpoint(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ mockMetrics := mock_metrics.NewMockMetricsEngine(ctrl)
+ ow = &OpenWrap{}
+ ow.metricEngine = mockMetrics
type args struct {
endpoint string
cfg *config.Configuration
gatherer *prometheus.Registry
+ setup func()
promMux *http.ServeMux
}
tests := []struct {
@@ -36,7 +93,10 @@ func TestInitPrometheusStatsEndpoint(t *testing.T) {
},
},
gatherer: &prometheus.Registry{},
- promMux: http.NewServeMux(),
+ setup: func() {
+ mockMetrics.EXPECT().RecordRequest(gomock.Any()).AnyTimes()
+ },
+ promMux: http.NewServeMux(),
},
want: http.StatusOK,
@@ -54,7 +114,10 @@ func TestInitPrometheusStatsEndpoint(t *testing.T) {
},
},
gatherer: &prometheus.Registry{},
- promMux: http.NewServeMux(),
+ setup: func() {
+ mockMetrics.EXPECT().RecordRequest(gomock.Any()).AnyTimes()
+ },
+ promMux: http.NewServeMux(),
},
want: http.StatusNotFound,
@@ -62,6 +125,7 @@ func TestInitPrometheusStatsEndpoint(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
+ tt.args.setup()
initPrometheusStatsEndpoint(tt.args.cfg, tt.args.gatherer, tt.args.promMux)
req := httptest.NewRequest("GET", tt.args.endpoint, nil)
rec := httptest.NewRecorder()
@@ -72,9 +136,14 @@ func TestInitPrometheusStatsEndpoint(t *testing.T) {
}
func TestInitPrometheusMetricsEndpoint(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ mockMetrics := mock_metrics.NewMockMetricsEngine(ctrl)
+ ow = &OpenWrap{}
+ ow.metricEngine = mockMetrics
type args struct {
endpoint string
cfg *config.Configuration
+ setup func()
promMux *http.ServeMux
}
tests := []struct {
@@ -94,6 +163,9 @@ func TestInitPrometheusMetricsEndpoint(t *testing.T) {
},
},
},
+ setup: func() {
+ mockMetrics.EXPECT().RecordRequest(gomock.Any()).AnyTimes()
+ },
promMux: http.NewServeMux(),
},
want: http.StatusOK,
@@ -110,6 +182,9 @@ func TestInitPrometheusMetricsEndpoint(t *testing.T) {
},
},
},
+ setup: func() {
+ mockMetrics.EXPECT().RecordRequest(gomock.Any()).AnyTimes()
+ },
promMux: http.NewServeMux(),
},
want: http.StatusNotFound,
@@ -117,6 +192,7 @@ func TestInitPrometheusMetricsEndpoint(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
+ tt.args.setup()
initPrometheusMetricsEndpoint(tt.args.cfg, tt.args.promMux)
req := httptest.NewRequest("GET", tt.args.endpoint, nil)
rec := httptest.NewRecorder()
@@ -127,9 +203,14 @@ func TestInitPrometheusMetricsEndpoint(t *testing.T) {
}
func TestGetOpenWrapPrometheusServer(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ mockMetrics := mock_metrics.NewMockMetricsEngine(ctrl)
+ ow = &OpenWrap{}
+ ow.metricEngine = mockMetrics
type args struct {
endpoint string
cfg *config.Configuration
+ setup func()
gatherer *prometheus.Registry
}
@@ -153,6 +234,9 @@ func TestGetOpenWrapPrometheusServer(t *testing.T) {
},
},
},
+ setup: func() {
+ mockMetrics.EXPECT().RecordRequest(gomock.Any()).AnyTimes()
+ },
gatherer: prometheus.NewRegistry(),
},
want: http.StatusOK,
@@ -169,6 +253,9 @@ func TestGetOpenWrapPrometheusServer(t *testing.T) {
},
},
},
+ setup: func() {
+ mockMetrics.EXPECT().RecordRequest(gomock.Any()).AnyTimes()
+ },
gatherer: prometheus.NewRegistry(),
},
want: http.StatusOK,
@@ -185,6 +272,9 @@ func TestGetOpenWrapPrometheusServer(t *testing.T) {
},
},
},
+ setup: func() {
+ mockMetrics.EXPECT().RecordRequest(gomock.Any()).AnyTimes()
+ },
gatherer: prometheus.NewRegistry(),
},
want: http.StatusNotFound,
@@ -201,6 +291,9 @@ func TestGetOpenWrapPrometheusServer(t *testing.T) {
},
},
},
+ setup: func() {
+ mockMetrics.EXPECT().RecordRequest(gomock.Any()).AnyTimes()
+ },
gatherer: prometheus.NewRegistry(),
},
want: http.StatusNotFound,
@@ -208,7 +301,8 @@ func TestGetOpenWrapPrometheusServer(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- promServer := getOpenWrapPrometheusServer(tt.args.cfg, tt.args.gatherer, server)
+ tt.args.setup()
+ promServer := GetOpenWrapPrometheusServer(tt.args.cfg, tt.args.gatherer, server)
defer promServer.Shutdown(context.Background())
req := httptest.NewRequest("GET", tt.args.endpoint, nil)
rec := httptest.NewRecorder()
diff --git a/modules/pubmatic/openwrap/util.go b/modules/pubmatic/openwrap/util.go
index a4fd1206090..4e597e4b8f2 100644
--- a/modules/pubmatic/openwrap/util.go
+++ b/modules/pubmatic/openwrap/util.go
@@ -277,7 +277,6 @@ func getPubmaticErrorCode(standardNBR openrtb3.NoBidReason) int {
case nbr.InternalError:
return 17 // ErrInvalidImpression
-
}
return -1
diff --git a/openrtb_ext/response.go b/openrtb_ext/response.go
index 7b6eacf2830..f3700799ea6 100644
--- a/openrtb_ext/response.go
+++ b/openrtb_ext/response.go
@@ -112,10 +112,10 @@ const (
UserSyncPixel UserSyncType = "pixel"
)
-// NonBidObject is subset of Bid object with exact json signature
+// ExtNonBidPrebidBid is subset of Bid object with exact json signature
+// defined at https://github.com/prebid/openrtb/blob/v19.0.0/openrtb2/bid.go
// It also contains the custom fields
-type NonBidObject struct {
- // SubSet
+type ExtNonBidPrebidBid struct {
Price float64 `json:"price,omitempty"`
ADomain []string `json:"adomain,omitempty"`
CatTax adcom1.CategoryTaxonomy `json:"cattax,omitempty"`
@@ -131,7 +131,7 @@ type NonBidObject struct {
OriginalBidCur string `json:"origbidcur,omitempty"`
//OW specific fields
- ID string `json:"id"`
+ ID string `json:"id,omitempty"` // need to check
DealPriority int `json:"dealpriority,omitempty"`
DealTierSatisfied bool `json:"dealtiersatisfied,omitempty"`
Meta *ExtBidPrebidMeta `json:"meta,omitempty"`
@@ -143,22 +143,21 @@ type NonBidObject struct {
OriginalBidCPMUSD float64 `json:"origbidcpmusd,omitempty"`
}
-// ExtResponseNonBidPrebid represents bidresponse.ext.prebid.seatnonbid[].nonbid[].ext
-type ExtResponseNonBidPrebid struct {
- Bid NonBidObject `json:"bid"`
+// ExtNonBidPrebid represents bidresponse.ext.prebid.seatnonbid[].nonbid[].ext
+type ExtNonBidPrebid struct {
+ Bid ExtNonBidPrebidBid `json:"bid"`
}
-type NonBidExt struct {
- Prebid ExtResponseNonBidPrebid `json:"prebid"`
- IsAdPod *bool `json:"-"` // OW specific Flag to determine if it is Ad-Pod specific nonbid
-
+type ExtNonBid struct {
+ Prebid ExtNonBidPrebid `json:"prebid"`
+ IsAdPod *bool `json:"-"` // OW specific Flag to determine if it is Ad-Pod specific nonbid
}
// NonBid represnts the Non Bid Reason (statusCode) for given impression ID
type NonBid struct {
ImpId string `json:"impid"`
StatusCode int `json:"statuscode"`
- Ext NonBidExt `json:"ext"`
+ Ext ExtNonBid `json:"ext"`
}
// SeatNonBid is collection of NonBid objects with seat information
diff --git a/openrtb_ext/seat_non_bids.go b/openrtb_ext/seat_non_bids.go
new file mode 100644
index 00000000000..ff00e5a0992
--- /dev/null
+++ b/openrtb_ext/seat_non_bids.go
@@ -0,0 +1,112 @@
+package openrtb_ext
+
+import "github.com/prebid/openrtb/v20/openrtb2"
+
+// NonBidCollection contains the map of seat with list of nonBids
+type NonBidCollection struct {
+ seatNonBidsMap map[string][]NonBid
+}
+
+// NonBidParams contains the fields that are required to form the nonBid object
+type NonBidParams struct {
+ Bid *openrtb2.Bid
+ NonBidReason int
+ OriginalBidCPM float64
+ OriginalBidCur string
+ DealPriority int
+ DealTierSatisfied bool
+ GeneratedBidID string
+ TargetBidderCode string
+ OriginalBidCPMUSD float64
+ BidMeta *ExtBidPrebidMeta
+ BidType BidType
+ BidTargets map[string]string
+ BidVideo *ExtBidPrebidVideo
+ BidEvents *ExtBidPrebidEvents
+ BidFloors *ExtBidPrebidFloors
+}
+
+// NewNonBid creates the NonBid object from NonBidParams and return it
+func NewNonBid(bidParams NonBidParams) NonBid {
+ if bidParams.Bid == nil {
+ bidParams.Bid = &openrtb2.Bid{}
+ }
+ return NonBid{
+ ImpId: bidParams.Bid.ImpID,
+ StatusCode: bidParams.NonBidReason,
+ Ext: ExtNonBid{
+ Prebid: ExtNonBidPrebid{Bid: ExtNonBidPrebidBid{
+ Price: bidParams.Bid.Price,
+ ADomain: bidParams.Bid.ADomain,
+ CatTax: bidParams.Bid.CatTax,
+ Cat: bidParams.Bid.Cat,
+ DealID: bidParams.Bid.DealID,
+ W: bidParams.Bid.W,
+ H: bidParams.Bid.H,
+ Dur: bidParams.Bid.Dur,
+ MType: bidParams.Bid.MType,
+ OriginalBidCPM: bidParams.OriginalBidCPM,
+ OriginalBidCur: bidParams.OriginalBidCur,
+
+ //OW specific
+ ID: bidParams.Bid.ID,
+ DealPriority: bidParams.DealPriority,
+ DealTierSatisfied: bidParams.DealTierSatisfied,
+ Meta: bidParams.BidMeta,
+ Targeting: bidParams.BidTargets,
+ Type: bidParams.BidType,
+ Video: bidParams.BidVideo,
+ BidId: bidParams.GeneratedBidID,
+ Floors: bidParams.BidFloors,
+ OriginalBidCPMUSD: bidParams.OriginalBidCPMUSD,
+ }},
+ },
+ }
+}
+
+// AddBid adds the nonBid into the map against the respective seat.
+// Note: This function is not a thread safe.
+func (snb *NonBidCollection) AddBid(nonBid NonBid, seat string) {
+ if snb.seatNonBidsMap == nil {
+ snb.seatNonBidsMap = make(map[string][]NonBid)
+ }
+ snb.seatNonBidsMap[seat] = append(snb.seatNonBidsMap[seat], nonBid)
+}
+
+// Append functions appends the NonBids from the input instance into the current instance's seatNonBidsMap, creating the map if needed.
+// Note: This function is not a thread safe.
+func (snb *NonBidCollection) Append(nonbid NonBidCollection) {
+ if snb == nil || len(nonbid.seatNonBidsMap) == 0 {
+ return
+ }
+ if snb.seatNonBidsMap == nil {
+ snb.seatNonBidsMap = make(map[string][]NonBid, len(nonbid.seatNonBidsMap))
+ }
+ for seat, nonBids := range nonbid.seatNonBidsMap {
+ snb.seatNonBidsMap[seat] = append(snb.seatNonBidsMap[seat], nonBids...)
+ }
+}
+
+// Get function converts the internal seatNonBidsMap to standard openrtb seatNonBid structure and returns it
+func (snb *NonBidCollection) Get() []SeatNonBid {
+ if snb == nil {
+ return nil
+ }
+
+ // seatNonBid := make([]SeatNonBid, len(snb.seatNonBidsMap))
+ var seatNonBid []SeatNonBid
+ for seat, nonBids := range snb.seatNonBidsMap {
+ seatNonBid = append(seatNonBid, SeatNonBid{
+ Seat: seat,
+ NonBid: nonBids,
+ })
+ }
+ return seatNonBid
+}
+
+func (snb *NonBidCollection) GetSeatNonBidMap() map[string][]NonBid {
+ if snb == nil {
+ return nil
+ }
+ return snb.seatNonBidsMap
+}
diff --git a/openrtb_ext/seat_non_bids_test.go b/openrtb_ext/seat_non_bids_test.go
new file mode 100644
index 00000000000..b7eeed56c2f
--- /dev/null
+++ b/openrtb_ext/seat_non_bids_test.go
@@ -0,0 +1,191 @@
+package openrtb_ext
+
+import (
+ "testing"
+
+ "github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestNewNonBid(t *testing.T) {
+ tests := []struct {
+ name string
+ bidParams NonBidParams
+ expectedNonBid NonBid
+ }{
+ {
+ name: "nil-bid-present-in-bidparams",
+ bidParams: NonBidParams{Bid: nil},
+ expectedNonBid: NonBid{},
+ },
+ {
+ name: "non-nil-bid-present-in-bidparams",
+ bidParams: NonBidParams{Bid: &openrtb2.Bid{ImpID: "imp1"}, NonBidReason: 100},
+ expectedNonBid: NonBid{ImpId: "imp1", StatusCode: 100},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ nonBid := NewNonBid(tt.bidParams)
+ assert.Equal(t, tt.expectedNonBid, nonBid, "found incorrect nonBid")
+ })
+ }
+}
+
+func TestSeatNonBidsAdd(t *testing.T) {
+ type fields struct {
+ seatNonBidsMap map[string][]NonBid
+ }
+ type args struct {
+ nonbid NonBid
+ seat string
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ want map[string][]NonBid
+ }{
+ {
+ name: "nil-seatNonBidsMap",
+ fields: fields{seatNonBidsMap: nil},
+ args: args{
+ nonbid: NonBid{},
+ seat: "bidder1",
+ },
+ want: sampleSeatNonBidMap("bidder1", 1),
+ },
+ {
+ name: "non-nil-seatNonBidsMap",
+ fields: fields{seatNonBidsMap: nil},
+ args: args{
+
+ nonbid: NonBid{},
+ seat: "bidder1",
+ },
+ want: sampleSeatNonBidMap("bidder1", 1),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ snb := &NonBidCollection{
+ seatNonBidsMap: tt.fields.seatNonBidsMap,
+ }
+ snb.AddBid(tt.args.nonbid, tt.args.seat)
+ assert.Equalf(t, tt.want, snb.seatNonBidsMap, "found incorrect seatNonBidsMap")
+ })
+ }
+}
+
+func TestSeatNonBidsGet(t *testing.T) {
+ type fields struct {
+ snb *NonBidCollection
+ }
+ tests := []struct {
+ name string
+ fields fields
+ want []SeatNonBid
+ }{
+ {
+ name: "get-seat-nonbids",
+ fields: fields{&NonBidCollection{sampleSeatNonBidMap("bidder1", 2)}},
+ want: sampleSeatBids("bidder1", 2),
+ },
+ {
+ name: "nil-seat-nonbids",
+ fields: fields{nil},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := tt.fields.snb.Get(); !assert.Equal(t, tt.want, got) {
+ t.Errorf("seatNonBids.get() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+var sampleSeatNonBidMap = func(seat string, nonBidCount int) map[string][]NonBid {
+ nonBids := make([]NonBid, 0)
+ for i := 0; i < nonBidCount; i++ {
+ nonBids = append(nonBids, NonBid{
+ Ext: ExtNonBid{Prebid: ExtNonBidPrebid{Bid: ExtNonBidPrebidBid{}}},
+ })
+ }
+ return map[string][]NonBid{
+ seat: nonBids,
+ }
+}
+
+var sampleSeatBids = func(seat string, nonBidCount int) []SeatNonBid {
+ seatNonBids := make([]SeatNonBid, 0)
+ seatNonBid := SeatNonBid{
+ Seat: seat,
+ NonBid: make([]NonBid, 0),
+ }
+ for i := 0; i < nonBidCount; i++ {
+ seatNonBid.NonBid = append(seatNonBid.NonBid, NonBid{
+ Ext: ExtNonBid{Prebid: ExtNonBidPrebid{Bid: ExtNonBidPrebidBid{}}},
+ })
+ }
+ seatNonBids = append(seatNonBids, seatNonBid)
+ return seatNonBids
+}
+
+func TestSeatNonBidsMerge(t *testing.T) {
+ type target struct {
+ snb *NonBidCollection
+ }
+ tests := []struct {
+ name string
+ fields target
+ input NonBidCollection
+ want *NonBidCollection
+ }{
+ {
+ name: "target-NonBidCollection-is-nil",
+ fields: target{nil},
+ want: nil,
+ },
+ {
+ name: "input-NonBidCollection-contains-nil-map",
+ fields: target{&NonBidCollection{}},
+ input: NonBidCollection{seatNonBidsMap: nil},
+ want: &NonBidCollection{},
+ },
+ {
+ name: "input-NonBidCollection-contains-empty-nonBids",
+ fields: target{&NonBidCollection{}},
+ input: NonBidCollection{seatNonBidsMap: make(map[string][]NonBid)},
+ want: &NonBidCollection{},
+ },
+ {
+ name: "append-nonbids-in-empty-target-NonBidCollection",
+ fields: target{&NonBidCollection{}},
+ input: NonBidCollection{
+ seatNonBidsMap: sampleSeatNonBidMap("pubmatic", 1),
+ },
+ want: &NonBidCollection{
+ seatNonBidsMap: sampleSeatNonBidMap("pubmatic", 1),
+ },
+ },
+ {
+ name: "merge-multiple-nonbids-in-non-empty-target-NonBidCollection",
+ fields: target{&NonBidCollection{
+ seatNonBidsMap: sampleSeatNonBidMap("pubmatic", 1),
+ }},
+ input: NonBidCollection{
+ seatNonBidsMap: sampleSeatNonBidMap("pubmatic", 1),
+ },
+ want: &NonBidCollection{
+ seatNonBidsMap: sampleSeatNonBidMap("pubmatic", 2),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ tt.fields.snb.Append(tt.input)
+ assert.Equal(t, tt.want, tt.fields.snb, "incorrect NonBidCollection generated by Append")
+ })
+ }
+}
diff --git a/scripts/coverage.sh b/scripts/coverage.sh
index 2f4c09fb7be..b6c8315e3d0 100755
--- a/scripts/coverage.sh
+++ b/scripts/coverage.sh
@@ -1,6 +1,6 @@
#!/bin/bash
# Generate test coverage statistics for Go packages.
-#
+#
# Works around the fact that `go test -coverprofile` currently does not work
# with multiple packages, see https://code.google.com/p/go/issues/detail?id=6909
#
@@ -91,4 +91,4 @@ case "$1" in
show_cover_report html ;;
*)
echo >&2 "error: invalid option: $1"; exit 1 ;;
-esac
+esac
\ No newline at end of file
diff --git a/server/prometheus_ow.go b/server/prometheus_ow.go
deleted file mode 100644
index 8766f43ab15..00000000000
--- a/server/prometheus_ow.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package server
-
-import (
- "net/http"
-
- "github.com/prebid/prebid-server/v2/config"
- "github.com/prometheus/client_golang/prometheus"
- "github.com/prometheus/client_golang/prometheus/promhttp"
-)
-
-func initPrometheusStatsEndpoint(cfg *config.Configuration, gatherer *prometheus.Registry, promMux *http.ServeMux) {
- promMux.Handle("/stats", promhttp.HandlerFor(gatherer, promhttp.HandlerOpts{
- ErrorLog: loggerForPrometheus{},
- MaxRequestsInFlight: 5,
- Timeout: cfg.Metrics.Prometheus.Timeout(),
- }))
-}
-
-func initPrometheusMetricsEndpoint(cfg *config.Configuration, promMux *http.ServeMux) {
- promMux.Handle("/metrics", promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{
- ErrorLog: loggerForPrometheus{},
- MaxRequestsInFlight: 5,
- Timeout: cfg.Metrics.Prometheus.Timeout(),
- }))
-}
-
-func getOpenWrapPrometheusServer(cfg *config.Configuration, gatherer *prometheus.Registry, server *http.Server) *http.Server {
- promMux := http.NewServeMux()
- initPrometheusStatsEndpoint(cfg, gatherer, promMux)
- initPrometheusMetricsEndpoint(cfg, promMux)
- server.Handler = promMux
- return server
-}
diff --git a/server/server.go b/server/server.go
index fd377517f59..9c5cdc66acc 100644
--- a/server/server.go
+++ b/server/server.go
@@ -16,6 +16,7 @@ import (
"github.com/prebid/prebid-server/v2/config"
"github.com/prebid/prebid-server/v2/metrics"
metricsconfig "github.com/prebid/prebid-server/v2/metrics/config"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap"
)
// Listen blocks forever, serving PBS requests on the given port. This will block forever, until the process is shut down.
@@ -68,7 +69,7 @@ func Listen(cfg *config.Configuration, handler http.Handler, adminHandler http.H
prometheusListener net.Listener
prometheusServer = newPrometheusServer(cfg, metrics)
)
- prometheusServer = getOpenWrapPrometheusServer(cfg, metrics.PrometheusMetrics.Gatherer, prometheusServer)
+ prometheusServer = openwrap.GetOpenWrapPrometheusServer(cfg, metrics.PrometheusMetrics.Gatherer, prometheusServer)
go shutdownAfterSignals(prometheusServer, stopPrometheus, done)
if prometheusListener, err = newTCPListener(prometheusServer.Addr, nil); err != nil {
glog.Errorf("Error listening for TCP connections on %s: %v for prometheus server", adminServer.Addr, err)
diff --git a/validate.sh b/validate.sh
index ca4fbc1dfd7..1c44a26aaa4 100755
--- a/validate.sh
+++ b/validate.sh
@@ -19,11 +19,12 @@ done
./scripts/format.sh -f $AUTOFMT
+
# Run the actual tests. Make sure there's enough coverage too, if the flags call for it.
if $COVERAGE; then
./scripts/check_coverage.sh
else
- go test -timeout 120s $(go list ./... | grep -v /vendor/)
+ go test -timeout 120s $(go list ./... | grep -v /vendor/)
fi
# Then run the race condition tests. These only run on tests named TestRace.* for two reasons.