diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
index a3d0f243548..1eae515403a 100644
--- a/.github/workflows/validate.yml
+++ b/.github/workflows/validate.yml
@@ -2,15 +2,21 @@ name: Validate
on:
push:
- branches: [master]
+ branches:
+ - master
+ - main
+ - ci
pull_request:
- branches: [master]
+ branches:
+ - master
+ - main
+ - ci
jobs:
validate:
strategy:
matrix:
- go-version: [1.19.x, 1.20.x]
+ go-version: [1.20.x]
os: [ubuntu-20.04]
runs-on: ${{ matrix.os }}
diff --git a/analytics/pubmatic/helper.go b/analytics/pubmatic/helper.go
index 01a94bea9e4..c025b4436c0 100644
--- a/analytics/pubmatic/helper.go
+++ b/analytics/pubmatic/helper.go
@@ -2,12 +2,15 @@ package pubmatic
import (
"encoding/json"
+ "errors"
"net/http"
"net/url"
"strconv"
"time"
"github.com/golang/glog"
+ "github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/prebid/prebid-server/v2/analytics"
"github.com/prebid/prebid-server/v2/analytics/pubmatic/mhttp"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
)
@@ -69,6 +72,34 @@ func send(rCtx *models.RequestCtx, url string, headers http.Header, mhc mhttp.Mu
rCtx.MetricsEngine.RecordPublisherWrapperLoggerFailure(rCtx.PubIDStr, rCtx.ProfileIDStr, "")
return
}
- rCtx.MetricsEngine.RecordSendLoggerDataTime(rCtx.Endpoint, rCtx.ProfileIDStr, time.Since(startTime))
+ rCtx.MetricsEngine.RecordSendLoggerDataTime(time.Since(startTime))
// TODO: this will increment HB specific metric (ow_pbs_sshb_*), verify labels
}
+
+// RestoreBidResponse restores the original bid response for AppLovinMax from the signal data
+func RestoreBidResponse(rctx *models.RequestCtx, ao analytics.AuctionObject) error {
+ if rctx.Endpoint != models.EndpointAppLovinMax {
+ return nil
+ }
+
+ if ao.Response.NBR != nil {
+ return nil
+ }
+
+ signalData := map[string]string{}
+ if err := json.Unmarshal(ao.Response.SeatBid[0].Bid[0].Ext, &signalData); err != nil {
+ return err
+ }
+
+ if val, ok := signalData[models.SignalData]; !ok || val == "" {
+ return errors.New("signal data not found in the response")
+ }
+
+ orignalResponse := &openrtb2.BidResponse{}
+ if err := json.Unmarshal([]byte(signalData[models.SignalData]), orignalResponse); err != nil {
+ return err
+ }
+
+ *ao.Response = *orignalResponse
+ return nil
+}
diff --git a/analytics/pubmatic/helper_test.go b/analytics/pubmatic/helper_test.go
index 6d5e69a45ce..0e43b15fa03 100644
--- a/analytics/pubmatic/helper_test.go
+++ b/analytics/pubmatic/helper_test.go
@@ -1,15 +1,20 @@
package pubmatic
import (
+ "encoding/json"
"net/http"
"net/url"
"testing"
"github.com/golang/mock/gomock"
+ "github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/prebid/prebid-server/v2/analytics"
"github.com/prebid/prebid-server/v2/analytics/pubmatic/mhttp"
mock_mhttp "github.com/prebid/prebid-server/v2/analytics/pubmatic/mhttp/mock"
mock_metrics "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics/mock"
"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/util/ptrutil"
"github.com/stretchr/testify/assert"
)
@@ -176,7 +181,7 @@ func TestSendMethod(t *testing.T) {
},
getMetricsEngine: func() *mock_metrics.MockMetricsEngine {
mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
- mockEngine.EXPECT().RecordSendLoggerDataTime(models.EndpointV25, "1", gomock.Any())
+ mockEngine.EXPECT().RecordSendLoggerDataTime(gomock.Any())
return mockEngine
},
getMockMultiHttpContext: func() *mock_mhttp.MockMultiHttpContextInterface {
@@ -220,3 +225,223 @@ func TestSendMethod(t *testing.T) {
})
}
}
+
+func TestRestoreBidResponse(t *testing.T) {
+ type args struct {
+ ao analytics.AuctionObject
+ rctx *models.RequestCtx
+ }
+ tests := []struct {
+ name string
+ args args
+ want *openrtb2.BidResponse
+ wantErr string
+ }{
+ {
+ name: "Endpoint is not AppLovinMax",
+ args: args{
+ ao: analytics.AuctionObject{
+ Response: &openrtb2.BidResponse{
+ ID: "test-case-1",
+ },
+ },
+ rctx: &models.RequestCtx{
+ Endpoint: models.EndpointV25,
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "test-case-1",
+ },
+ },
+ {
+ name: "NBR is not nil",
+ args: args{
+ ao: analytics.AuctionObject{
+ Response: &openrtb2.BidResponse{
+ ID: "test-case-1",
+ NBR: ptrutil.ToPtr(nbr.InvalidProfileConfiguration),
+ },
+ },
+ rctx: &models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "test-case-1",
+ NBR: ptrutil.ToPtr(nbr.InvalidProfileConfiguration),
+ },
+ },
+ {
+ name: "failed to unmarshal BidResponse.SeatBid[0].Bid[0].Ext",
+ args: args{
+ ao: analytics.AuctionObject{
+ Response: &openrtb2.BidResponse{
+ ID: "test-case-1",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "123",
+ Ext: json.RawMessage(`{`),
+ },
+ },
+ },
+ },
+ },
+ },
+ rctx: &models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "test-case-1",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "123",
+ Ext: json.RawMessage(`{`),
+ },
+ },
+ },
+ },
+ },
+ wantErr: "unexpected end of JSON input",
+ },
+ {
+ name: "signaldata not present in ext",
+ args: args{
+ ao: analytics.AuctionObject{
+ Response: &openrtb2.BidResponse{
+ ID: "test-case-1",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "123",
+ Ext: json.RawMessage(`{"signalData1": "{\"matchedimpression\":{\"appnexus\":50,\"pubmatic\":50}}\r\n"}`),
+ },
+ },
+ },
+ },
+ },
+ },
+ rctx: &models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "test-case-1",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "123",
+ Ext: json.RawMessage(`{"signalData1": "{\"matchedimpression\":{\"appnexus\":50,\"pubmatic\":50}}\r\n"}`),
+ },
+ },
+ },
+ },
+ },
+ wantErr: "signal data not found in the response",
+ },
+ {
+ name: "failed to unmarshal signaldata",
+ args: args{
+ ao: analytics.AuctionObject{
+ Response: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ Ext: json.RawMessage(`{"signaldata": "{"id":123}"}"`),
+ },
+ },
+ },
+ },
+ },
+ },
+ rctx: &models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ Ext: json.RawMessage(`{"signaldata": "{"id":123}"}"`),
+ },
+ },
+ },
+ },
+ },
+ wantErr: `invalid character 'i' after object key:value pair`,
+ },
+ {
+ name: "valid AppLovinMax Response",
+ args: args{
+ ao: analytics.AuctionObject{
+ Response: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ Ext: json.RawMessage(`{"signaldata":"{\"id\":\"123\",\"seatbid\":[{\"bid\":[{\"id\":\"bid-id-1\",\"impid\":\"imp_1\",\"price\":0}],\"seat\":\"pubmatic\"}],\"bidid\":\"bid-id-1\",\"cur\":\"USD\",\"ext\":{\"matchedimpression\":{\"appnexus\":50,\"pubmatic\":50}}}\r\n"}`),
+ },
+ },
+ },
+ },
+ },
+ },
+ rctx: &models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ err := RestoreBidResponse(tt.args.rctx, tt.args.ao)
+ if err != nil {
+ assert.Equal(t, tt.wantErr, err.Error(), tt.name)
+ }
+ assert.Equal(t, tt.want, tt.args.ao.Response, tt.name)
+ })
+ }
+}
diff --git a/analytics/pubmatic/logger.go b/analytics/pubmatic/logger.go
index 6a15f5be3a5..67fb1562265 100644
--- a/analytics/pubmatic/logger.go
+++ b/analytics/pubmatic/logger.go
@@ -25,8 +25,8 @@ type bidWrapper struct {
Nbr *openrtb3.NoBidReason
}
-// getUUID is a function variable which will return uuid
-var getUUID = func() string {
+// GetUUID is a function variable which will return uuid
+var GetUUID = func() string {
return uuid.NewV4().String()
}
@@ -103,7 +103,7 @@ func GetLogAuctionObjectAsURL(ao analytics.AuctionObject, rCtx *models.RequestCt
}
slots = append(slots, SlotRecord{
- SlotId: getUUID(),
+ SlotId: GetUUID(),
SlotName: impCtx.SlotName,
SlotSize: impCtx.IncomingSlots,
Adunit: impCtx.AdUnitName,
diff --git a/analytics/pubmatic/logger_test.go b/analytics/pubmatic/logger_test.go
index 21bcae7d2d0..82328929f36 100644
--- a/analytics/pubmatic/logger_test.go
+++ b/analytics/pubmatic/logger_test.go
@@ -4011,13 +4011,13 @@ func TestGetLogAuctionObjectAsURLForFloorType(t *testing.T) {
}
func TestGetLogAuctionObjectAsURLForFloorDetailsAndCDS(t *testing.T) {
cfg := ow.cfg
- uuidFunc := getUUID
+ uuidFunc := GetUUID
defer func() {
ow.cfg = cfg
- getUUID = uuidFunc
+ GetUUID = uuidFunc
}()
- getUUID = func() string { return "uuid" }
+ GetUUID = func() string { return "uuid" }
ow.cfg.Endpoint = "http://10.172.141.11/wl"
ow.cfg.PublicEndpoint = "http://t.pubmatic.com/wl"
@@ -4204,13 +4204,13 @@ func TestGetLogAuctionObjectAsURLForFloorDetailsAndCDS(t *testing.T) {
}
func TestSlotRecordsInGetLogAuctionObjectAsURL(t *testing.T) {
cfg := ow.cfg
- uuidFunc := getUUID
+ uuidFunc := GetUUID
defer func() {
ow.cfg = cfg
- getUUID = uuidFunc
+ GetUUID = uuidFunc
}()
- getUUID = func() string {
+ GetUUID = func() string {
return "sid"
}
diff --git a/analytics/pubmatic/pubmatic.go b/analytics/pubmatic/pubmatic.go
index 293003d1d2d..ef9cac22f9e 100644
--- a/analytics/pubmatic/pubmatic.go
+++ b/analytics/pubmatic/pubmatic.go
@@ -59,6 +59,11 @@ func (ow HTTPLogger) LogAuctionObject(ao *analytics.AuctionObject) {
return
}
+ err := RestoreBidResponse(rCtx, *ao)
+ if err != nil {
+ glog.Error("Failed to restore bid response for pub:[%d], profile:[%d], version:[%d], err:[%s].", rCtx.PubID, rCtx.ProfileID, rCtx.VersionID, err.Error())
+ }
+
url, headers := GetLogAuctionObjectAsURL(*ao, rCtx, false, false)
if url == "" {
glog.Errorf("Failed to prepare the owlogger for pub:[%d], profile:[%d], version:[%d].",
diff --git a/analytics/pubmatic/pubmatic_test.go b/analytics/pubmatic/pubmatic_test.go
index 6bef274d2e4..186c684e8e6 100644
--- a/analytics/pubmatic/pubmatic_test.go
+++ b/analytics/pubmatic/pubmatic_test.go
@@ -1,8 +1,10 @@
package pubmatic
import (
+ "encoding/json"
"testing"
+ "github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/analytics"
"github.com/prebid/prebid-server/v2/config"
"github.com/prebid/prebid-server/v2/hooks/hookanalytics"
@@ -35,8 +37,9 @@ func TestNewHTTPLogger(t *testing.T) {
// TestLogAuctionObject just increases code coverage, it does not validate anything
func TestLogAuctionObject(t *testing.T) {
tests := []struct {
- name string
- ao *analytics.AuctionObject
+ name string
+ ao *analytics.AuctionObject
+ RestoredResponse *openrtb2.BidResponse
}{
{
name: "rctx is nil",
@@ -72,6 +75,74 @@ func TestLogAuctionObject(t *testing.T) {
},
},
},
+ {
+ name: "AppLovinMax request . RestoreBidResponse for logger",
+ ao: &analytics.AuctionObject{
+ HookExecutionOutcome: []hookexecution.StageOutcome{
+ {
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ AnalyticsTags: hookanalytics.Analytics{
+ Activities: []hookanalytics.Activity{
+ {
+ Results: []hookanalytics.Result{
+ {
+ Values: map[string]interface{}{
+ "request-ctx": &models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ Debug: false,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+
+ Response: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ Ext: json.RawMessage(`{"signaldata":"{\"id\":\"123\",\"seatbid\":[{\"bid\":[{\"id\":\"bid-id-1\",\"impid\":\"imp_1\",\"price\":0}],\"seat\":\"pubmatic\"}],\"bidid\":\"bid-id-1\",\"cur\":\"USD\",\"ext\":{\"matchedimpression\":{\"appnexus\":50,\"pubmatic\":50}}}\r\n"}`),
+ },
+ },
+ },
+ },
+ },
+ },
+ RestoredResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ },
{
name: "logger_disabled",
ao: &analytics.AuctionObject{
@@ -107,5 +178,6 @@ func TestLogAuctionObject(t *testing.T) {
}
for _, tt := range tests {
HTTPLogger{}.LogAuctionObject(tt.ao)
+ assert.Equal(t, tt.RestoredResponse, tt.ao.Response, tt.name)
}
}
diff --git a/analytics/pubmatic/record.go b/analytics/pubmatic/record.go
index a408e6a6775..4b98ed36d29 100644
--- a/analytics/pubmatic/record.go
+++ b/analytics/pubmatic/record.go
@@ -178,7 +178,7 @@ func (wlog *WloggerRecord) logIntegrationType(endpoint string) {
switch endpoint {
case models.EndpointAMP:
wlog.IntegrationType = models.TypeAmp
- case models.EndpointV25:
+ case models.EndpointV25, models.EndpointAppLovinMax:
wlog.IntegrationType = models.TypeSDK
case models.EndpointVAST:
wlog.IntegrationType = models.TypeTag
diff --git a/analytics/pubmatic/record_test.go b/analytics/pubmatic/record_test.go
index 86d25d6e119..57f8d20f66c 100644
--- a/analytics/pubmatic/record_test.go
+++ b/analytics/pubmatic/record_test.go
@@ -21,6 +21,11 @@ func TestLogIntegrationType(t *testing.T) {
endpoint: models.EndpointV25,
integrationType: models.TypeSDK,
},
+ {
+ name: "applovinmax",
+ endpoint: models.EndpointAppLovinMax,
+ integrationType: models.TypeSDK,
+ },
{
name: "amp",
endpoint: models.EndpointAMP,
diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go
index c94f3e50575..4e0b096dd81 100644
--- a/endpoints/openrtb2/auction.go
+++ b/endpoints/openrtb2/auction.go
@@ -344,7 +344,7 @@ func rejectAuctionRequest(
// TODO merge this with success case
stageOutcomes := hookExecutor.GetOutcomes()
ao.HookExecutionOutcome = stageOutcomes
- UpdateResponseExtOW(response, ao)
+ UpdateResponseExtOW(w, response, ao)
ao.Response = response
ao.Errors = append(ao.Errors, rejectErr)
@@ -366,7 +366,7 @@ func sendAuctionResponse(
if response != nil {
stageOutcomes := hookExecutor.GetOutcomes()
ao.HookExecutionOutcome = stageOutcomes
- UpdateResponseExtOW(response, ao)
+ UpdateResponseExtOW(w, response, ao)
ext, warns, err := hookexecution.EnrichExtBidResponse(response.Ext, stageOutcomes, request, account)
if err != nil {
diff --git a/endpoints/openrtb2/auction_ow.go b/endpoints/openrtb2/auction_ow.go
index ce91e1ec5d3..48fe957387c 100644
--- a/endpoints/openrtb2/auction_ow.go
+++ b/endpoints/openrtb2/auction_ow.go
@@ -2,15 +2,18 @@ package openrtb2
import (
"encoding/json"
+ "net/http"
"runtime/debug"
"strconv"
+ "github.com/buger/jsonparser"
"github.com/golang/glog"
"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/analytics/pubmatic"
"github.com/prebid/prebid-server/v2/metrics"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
"github.com/prebid/prebid-server/v2/openrtb_ext"
)
@@ -32,7 +35,7 @@ func recordRejectedBids(pubID string, seatNonBids []openrtb_ext.SeatNonBid, metr
}
}
-func UpdateResponseExtOW(bidResponse *openrtb2.BidResponse, ao analytics.AuctionObject) {
+func UpdateResponseExtOW(w http.ResponseWriter, bidResponse *openrtb2.BidResponse, ao analytics.AuctionObject) {
defer func() {
if r := recover(); r != nil {
response, err := json.Marshal(bidResponse)
@@ -53,89 +56,31 @@ func UpdateResponseExtOW(bidResponse *openrtb2.BidResponse, ao analytics.Auction
return
}
- extBidResponse := openrtb_ext.ExtBidResponse{}
- if len(bidResponse.Ext) != 0 {
- if err := json.Unmarshal(bidResponse.Ext, &extBidResponse); err != nil {
- return
+ //Send owlogger in response only in case of debug mode
+ if rCtx.Debug {
+ var orignalMaxBidResponse *openrtb2.BidResponse
+ if rCtx.Endpoint == models.EndpointAppLovinMax {
+ orignalMaxBidResponse = new(openrtb2.BidResponse)
+ *orignalMaxBidResponse = *bidResponse
+ pubmatic.RestoreBidResponse(rCtx, ao)
}
- }
-
- if rCtx.LogInfoFlag == 1 && !rCtx.LoggerDisabled {
- extBidResponse.OwLogInfo.Logger, _ = pubmatic.GetLogAuctionObjectAsURL(ao, rCtx, true, true)
- }
- // TODO: uncomment after seatnonbid PR is merged https://github.com/prebid/prebid-server/v2/pull/2505
- // if seatNonBids := updateSeatNoBid(rCtx, ao); len(seatNonBids) != 0 {
- // if extBidResponse.Prebid == nil {
- // extBidResponse.Prebid = &openrtb_ext.ExtResponsePrebid{}
- // }
- // extBidResponse.Prebid.SeatNonBid = seatNonBids
- // }
-
- if rCtx.Debug && !rCtx.LoggerDisabled {
- extBidResponse.OwLogger, _ = pubmatic.GetLogAuctionObjectAsURL(ao, rCtx, false, true)
+ if !rCtx.LoggerDisabled {
+ owlogger, _ := pubmatic.GetLogAuctionObjectAsURL(ao, rCtx, false, true)
+ if rCtx.Endpoint == models.EndpointAppLovinMax {
+ *bidResponse = *orignalMaxBidResponse
+ }
+ if len(bidResponse.Ext) == 0 {
+ bidResponse.Ext = []byte("{}")
+ }
+ if updatedExt, err := jsonparser.Set([]byte(bidResponse.Ext), []byte(strconv.Quote(owlogger)), "owlogger"); err == nil {
+ bidResponse.Ext = updatedExt
+ }
+ }
+ } else if rCtx.Endpoint == models.EndpointAppLovinMax {
+ bidResponse.Ext = nil
+ if rCtx.AppLovinMax.Reject {
+ w.WriteHeader(http.StatusNoContent)
+ }
}
-
- bidResponse.Ext, _ = json.Marshal(extBidResponse)
}
-
-// TODO: uncomment after seatnonbid PR is merged https://github.com/prebid/prebid-server/v2/pull/2505
-// TODO: Move this to module once it gets []analytics.RejectedBid as param (submit it in vanilla)
-// func updateSeatNoBid(rCtx *models.RequestCtx, ao analytics.AuctionObject) []openrtb_ext.SeatNonBid {
-// seatNonBids := make([]openrtb_ext.SeatNonBid, 0, len(ao.RejectedBids))
-
-// seatNoBids := make(map[string][]analytics.RejectedBid)
-// for _, rejectedBid := range ao.RejectedBids {
-// seatNoBids[rejectedBid.Seat] = append(seatNoBids[rejectedBid.Seat], rejectedBid)
-// }
-
-// for seat, rejectedBids := range seatNoBids {
-// extSeatNoBid := openrtb_ext.SeatNonBid{
-// Seat: seat,
-// NonBids: make([]openrtb_ext.NonBid, 0, len(rejectedBids)),
-// }
-
-// for _, rejectedBid := range rejectedBids {
-// bid := *rejectedBid.Bid.Bid
-// addClientConfig(rCtx, seat, &bid)
-// extSeatNoBid.NonBids = append(extSeatNoBid.NonBids, openrtb_ext.NonBid{
-// ImpId: rejectedBid.Bid.Bid.ImpID,
-// StatusCode: rejectedBid.RejectionReason,
-// Ext: openrtb_ext.NonBidExt{
-// Prebid: openrtb_ext.ExtResponseNonBidPrebid{
-// Bid: openrtb_ext.Bid{
-// Bid: bid,
-// },
-// },
-// },
-// })
-// }
-
-// seatNonBids = append(seatNonBids, extSeatNoBid)
-// }
-
-// return seatNonBids
-// }
-
-// func addClientConfig(rCtx *models.RequestCtx, seat string, bid *openrtb2.Bid) {
-// if seatNoBidBySeat, ok := rCtx.NoSeatBids[bid.ImpID]; ok {
-// if seatNoBids, ok := seatNoBidBySeat[seat]; ok {
-// for _, seatNoBid := range seatNoBids {
-// bidExt := models.BidExt{}
-// if err := json.Unmarshal(seatNoBid.Ext, &bidExt); err != nil {
-// continue
-// }
-
-// inBidExt := models.BidExt{}
-// if err := json.Unmarshal(bid.Ext, &inBidExt); err != nil {
-// continue
-// }
-
-// inBidExt.Banner = bidExt.Banner
-// inBidExt.Video = bidExt.Video
-
-// bid.Ext, _ = json.Marshal(inBidExt)
-// }
-// }
-// }
-// }
diff --git a/endpoints/openrtb2/auction_ow_test.go b/endpoints/openrtb2/auction_ow_test.go
index 936c16969f1..228fb2f709c 100644
--- a/endpoints/openrtb2/auction_ow_test.go
+++ b/endpoints/openrtb2/auction_ow_test.go
@@ -3,19 +3,27 @@ package openrtb2
import (
"encoding/json"
"fmt"
-
+ "net/http"
+ "net/http/httptest"
"testing"
+ "github.com/prebid/prebid-server/v2/analytics/pubmatic"
+
"github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/prebid/prebid-server/v2/analytics"
analyticsBuild "github.com/prebid/prebid-server/v2/analytics/build"
"github.com/prebid/prebid-server/v2/config"
"github.com/prebid/prebid-server/v2/errortypes"
"github.com/prebid/prebid-server/v2/exchange"
"github.com/prebid/prebid-server/v2/hooks"
+ "github.com/prebid/prebid-server/v2/hooks/hookanalytics"
+ "github.com/prebid/prebid-server/v2/hooks/hookexecution"
"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/models"
"github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/prebid/prebid-server/v2/stored_requests/backends/empty_fetcher"
+ "github.com/prebid/prebid-server/v2/util/ptrutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
@@ -177,3 +185,662 @@ func TestRecordRejectedBids(t *testing.T) {
me.AssertNumberOfCalls(t, "RecordRejectedBids", test.want.expectedCalls)
}
}
+
+func TestUpdateResponseExtOW(t *testing.T) {
+ uuidFunc := pubmatic.GetUUID
+ defer func() {
+ pubmatic.GetUUID = uuidFunc
+ }()
+
+ pubmatic.GetUUID = func() string { return "uuid" }
+ type args struct {
+ w http.ResponseWriter
+ bidResponse *openrtb2.BidResponse
+ ao analytics.AuctionObject
+ }
+ tests := []struct {
+ name string
+ args args
+ want *openrtb2.BidResponse
+ RestoredResponse *openrtb2.BidResponse
+ rejectResponse bool
+ }{
+ {
+ name: "empty bid response",
+ args: args{
+ bidResponse: nil,
+ ao: analytics.AuctionObject{
+ Response: nil,
+ },
+ },
+ want: nil,
+ RestoredResponse: nil,
+ },
+ {
+ name: "rctx is nil",
+ args: args{
+ bidResponse: &openrtb2.BidResponse{},
+ ao: analytics.AuctionObject{
+ HookExecutionOutcome: []hookexecution.StageOutcome{
+ {
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ AnalyticsTags: hookanalytics.Analytics{
+ Activities: []hookanalytics.Activity{
+ {
+ Results: []hookanalytics.Result{
+ {
+ Values: map[string]interface{}{
+ "request-ctx": nil,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Response: &openrtb2.BidResponse{},
+ },
+ },
+ want: &openrtb2.BidResponse{},
+ RestoredResponse: &openrtb2.BidResponse{},
+ },
+ {
+ name: "debug is enabled and endpoint is other than applovinmax",
+ args: args{
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ ao: analytics.AuctionObject{
+ HookExecutionOutcome: []hookexecution.StageOutcome{
+ {
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ AnalyticsTags: hookanalytics.Analytics{
+ Activities: []hookanalytics.Activity{
+ {
+ Results: []hookanalytics.Result{
+ {
+ Values: map[string]interface{}{
+ "request-ctx": &models.RequestCtx{
+ PubID: 5890,
+ Debug: true,
+ Endpoint: models.EndpointV25,
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp_1": {
+ IncomingSlots: []string{"0x0v", "100x200"},
+ IsRewardInventory: ptrutil.ToPtr(int8(1)),
+ SlotName: "imp_1_tagid_1",
+ AdUnitName: "tagid_1",
+ },
+ "imp_2": {
+ AdUnitName: "tagid_2",
+ SlotName: "imp_2_tagid_2",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp_1",
+ TagID: "tagid_1",
+ },
+ {
+ ID: "imp_2",
+ TagID: "tagid_2",
+ },
+ },
+ },
+ },
+ Response: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50},"owlogger":"?json=%7B%22pubid%22%3A5890%2C%22pid%22%3A%220%22%2C%22pdvid%22%3A%220%22%2C%22sl%22%3A1%2C%22s%22%3A%5B%7B%22sid%22%3A%22uuid%22%2C%22sn%22%3A%22imp_1_tagid_1%22%2C%22sz%22%3A%5B%220x0v%22%2C%22100x200%22%5D%2C%22au%22%3A%22tagid_1%22%2C%22ps%22%3A%5B%7B%22pn%22%3A%22pubmatic%22%2C%22bc%22%3A%22pubmatic%22%2C%22kgpv%22%3A%22%22%2C%22kgpsv%22%3A%22%22%2C%22psz%22%3A%220x0%22%2C%22af%22%3A%22%22%2C%22eg%22%3A0%2C%22en%22%3A0%2C%22l1%22%3A0%2C%22l2%22%3A0%2C%22t%22%3A0%2C%22wb%22%3A0%2C%22bidid%22%3A%22bid-id-1%22%2C%22origbidid%22%3A%22bid-id-1%22%2C%22di%22%3A%22-1%22%2C%22dc%22%3A%22%22%2C%22db%22%3A0%2C%22ss%22%3A1%2C%22mi%22%3A0%2C%22ocpm%22%3A0%2C%22ocry%22%3A%22USD%22%7D%5D%2C%22rwrd%22%3A1%7D%2C%7B%22sid%22%3A%22uuid%22%2C%22sn%22%3A%22imp_2_tagid_2%22%2C%22au%22%3A%22tagid_2%22%2C%22ps%22%3A%5B%5D%7D%5D%2C%22dvc%22%3A%7B%7D%2C%22ft%22%3A0%2C%22it%22%3A%22sdk%22%7D&pubid=5890"}`),
+ },
+ RestoredResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ },
+ {
+ name: "debug is enabled and endpoint is AppLovinMax",
+ args: args{
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ Ext: json.RawMessage(`{"signaldata":"{\"id\":\"123\",\"seatbid\":[{\"bid\":[{\"id\":\"bid-id-1\",\"impid\":\"imp_1\",\"price\":0}],\"seat\":\"pubmatic\"}],\"bidid\":\"bid-id-1\",\"cur\":\"USD\",\"ext\":{\"matchedimpression\":{\"appnexus\":50,\"pubmatic\":50}}}\r\n"}`),
+ },
+ },
+ },
+ },
+ },
+ ao: analytics.AuctionObject{
+ HookExecutionOutcome: []hookexecution.StageOutcome{
+ {
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ AnalyticsTags: hookanalytics.Analytics{
+ Activities: []hookanalytics.Activity{
+ {
+ Results: []hookanalytics.Result{
+ {
+ Values: map[string]interface{}{
+ "request-ctx": &models.RequestCtx{
+ PubID: 5890,
+ Debug: true,
+ Endpoint: models.EndpointAppLovinMax,
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp_1": {
+ IncomingSlots: []string{"0x0v", "100x200"},
+ IsRewardInventory: ptrutil.ToPtr(int8(1)),
+ SlotName: "imp_1_tagid_1",
+ AdUnitName: "tagid_1",
+ },
+ "imp_2": {
+ AdUnitName: "tagid_2",
+ SlotName: "imp_2_tagid_2",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ RequestWrapper: &openrtb_ext.RequestWrapper{
+ BidRequest: &openrtb2.BidRequest{
+ Imp: []openrtb2.Imp{
+ {
+ ID: "imp_1",
+ TagID: "tagid_1",
+ },
+ {
+ ID: "imp_2",
+ TagID: "tagid_2",
+ },
+ },
+ },
+ },
+ Response: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ Ext: json.RawMessage(`{"signaldata":"{\"id\":\"123\",\"seatbid\":[{\"bid\":[{\"id\":\"bid-id-1\",\"impid\":\"imp_1\",\"price\":0}],\"seat\":\"pubmatic\"}],\"bidid\":\"bid-id-1\",\"cur\":\"USD\",\"ext\":{\"matchedimpression\":{\"appnexus\":50,\"pubmatic\":50}}}\r\n"}`),
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ Ext: json.RawMessage(`{"signaldata":"{\"id\":\"123\",\"seatbid\":[{\"bid\":[{\"id\":\"bid-id-1\",\"impid\":\"imp_1\",\"price\":0}],\"seat\":\"pubmatic\"}],\"bidid\":\"bid-id-1\",\"cur\":\"USD\",\"ext\":{\"matchedimpression\":{\"appnexus\":50,\"pubmatic\":50}}}\r\n"}`),
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"owlogger":"?json=%7B%22pubid%22%3A5890%2C%22pid%22%3A%220%22%2C%22pdvid%22%3A%220%22%2C%22sl%22%3A1%2C%22s%22%3A%5B%7B%22sid%22%3A%22uuid%22%2C%22sn%22%3A%22imp_1_tagid_1%22%2C%22sz%22%3A%5B%220x0v%22%2C%22100x200%22%5D%2C%22au%22%3A%22tagid_1%22%2C%22ps%22%3A%5B%7B%22pn%22%3A%22pubmatic%22%2C%22bc%22%3A%22pubmatic%22%2C%22kgpv%22%3A%22%22%2C%22kgpsv%22%3A%22%22%2C%22psz%22%3A%220x0%22%2C%22af%22%3A%22%22%2C%22eg%22%3A0%2C%22en%22%3A0%2C%22l1%22%3A0%2C%22l2%22%3A0%2C%22t%22%3A0%2C%22wb%22%3A0%2C%22bidid%22%3A%22bid-id-1%22%2C%22origbidid%22%3A%22bid-id-1%22%2C%22di%22%3A%22-1%22%2C%22dc%22%3A%22%22%2C%22db%22%3A0%2C%22ss%22%3A1%2C%22mi%22%3A0%2C%22ocpm%22%3A0%2C%22ocry%22%3A%22USD%22%7D%5D%2C%22rwrd%22%3A1%7D%2C%7B%22sid%22%3A%22uuid%22%2C%22sn%22%3A%22imp_2_tagid_2%22%2C%22au%22%3A%22tagid_2%22%2C%22ps%22%3A%5B%5D%7D%5D%2C%22dvc%22%3A%7B%7D%2C%22ft%22%3A0%2C%22it%22%3A%22sdk%22%7D&pubid=5890"}`),
+ },
+ RestoredResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ },
+ {
+ name: "debug is not enabled and request is other than AppLovinMax",
+ args: args{
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ ao: analytics.AuctionObject{
+ HookExecutionOutcome: []hookexecution.StageOutcome{
+ {
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ AnalyticsTags: hookanalytics.Analytics{
+ Activities: []hookanalytics.Activity{
+ {
+ Results: []hookanalytics.Result{
+ {
+ Values: map[string]interface{}{
+ "request-ctx": &models.RequestCtx{
+ PubID: 5890,
+ Debug: false,
+ Endpoint: models.EndpintInappVideo,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Response: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ RestoredResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ },
+ {
+ name: "debug is not enabled and endpoint is AppLovinMax but AppLovinMax reject is false",
+ args: args{
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ ao: analytics.AuctionObject{
+ HookExecutionOutcome: []hookexecution.StageOutcome{
+ {
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ AnalyticsTags: hookanalytics.Analytics{
+ Activities: []hookanalytics.Activity{
+ {
+ Results: []hookanalytics.Result{
+ {
+ Values: map[string]interface{}{
+ "request-ctx": &models.RequestCtx{
+ PubID: 5890,
+ Debug: false,
+ Endpoint: models.EndpointAppLovinMax,
+ AppLovinMax: models.AppLovinMax{
+ Reject: false,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Response: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: nil,
+ },
+ RestoredResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ },
+ {
+ name: "debug is not enabled and endpoint is AppLovinMax but AppLovinMax reject is true",
+ args: args{
+ w: httptest.NewRecorder(),
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ ao: analytics.AuctionObject{
+ HookExecutionOutcome: []hookexecution.StageOutcome{
+ {
+ Groups: []hookexecution.GroupOutcome{
+ {
+ InvocationResults: []hookexecution.HookOutcome{
+ {
+ AnalyticsTags: hookanalytics.Analytics{
+ Activities: []hookanalytics.Activity{
+ {
+ Results: []hookanalytics.Result{
+ {
+ Values: map[string]interface{}{
+ "request-ctx": &models.RequestCtx{
+ PubID: 5890,
+ Debug: false,
+ Endpoint: models.EndpointAppLovinMax,
+ AppLovinMax: models.AppLovinMax{
+ Reject: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Response: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ },
+ },
+ rejectResponse: true,
+ want: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ },
+ RestoredResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "bid-id-1",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Seat: "pubmatic",
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "imp_1",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{"matchedimpression":{"appnexus":50,"pubmatic":50}}`),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ UpdateResponseExtOW(tt.args.w, tt.args.bidResponse, tt.args.ao)
+ assert.Equal(t, tt.want, tt.args.bidResponse, tt.name)
+ assert.Equal(t, tt.RestoredResponse, tt.args.ao.Response)
+ if tt.rejectResponse {
+ assert.Equal(t, http.StatusNoContent, tt.args.w.(*httptest.ResponseRecorder).Code, tt.name)
+ }
+ })
+ }
+}
diff --git a/modules/pubmatic/openwrap/applovinmax.go b/modules/pubmatic/openwrap/applovinmax.go
new file mode 100644
index 00000000000..4d90d385c45
--- /dev/null
+++ b/modules/pubmatic/openwrap/applovinmax.go
@@ -0,0 +1,287 @@
+package openwrap
+
+import (
+ "encoding/json"
+ "strconv"
+
+ "github.com/buger/jsonparser"
+ "github.com/prebid/openrtb/v20/openrtb2"
+ "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
+)
+
+func getSignalData(requestBody []byte) *openrtb2.BidRequest {
+ signal, err := jsonparser.GetString(requestBody, "user", "data", "[0]", "segment", "[0]", "signal")
+ if err != nil {
+ return nil
+ }
+
+ signalData := &openrtb2.BidRequest{}
+ if err := json.Unmarshal([]byte(signal), signalData); err != nil {
+ return nil
+ }
+ return signalData
+}
+
+func addSignalDataInRequest(signalData *openrtb2.BidRequest, maxRequest *openrtb2.BidRequest) {
+ updateRequestWrapper(signalData.Ext, maxRequest)
+ updateImpression(signalData.Imp, maxRequest.Imp)
+ updateDevice(signalData.Device, maxRequest)
+ updateApp(signalData.App, maxRequest)
+ updateRegs(signalData.Regs, maxRequest)
+ updateSource(signalData.Source, maxRequest)
+ updateUser(signalData.User, maxRequest)
+}
+
+func updateImpression(signalImps []openrtb2.Imp, maxImps []openrtb2.Imp) {
+ if len(maxImps) == 0 || len(signalImps) == 0 {
+ return
+ }
+
+ signalImp := signalImps[0]
+ if signalImp.DisplayManager != "" {
+ maxImps[0].DisplayManager = signalImp.DisplayManager
+ }
+
+ if signalImp.DisplayManagerVer != "" {
+ maxImps[0].DisplayManagerVer = signalImp.DisplayManagerVer
+ }
+
+ if signalImp.ClickBrowser != nil {
+ maxImps[0].ClickBrowser = signalImp.ClickBrowser
+ }
+
+ if signalImp.Video != nil {
+ maxImps[0].Video = signalImp.Video
+ }
+
+ if maxImps[0].Banner != nil {
+ if signalImp.Banner != nil && len(signalImp.Banner.API) > 0 {
+ maxImps[0].Banner.API = signalImp.Banner.API
+ }
+
+ bannertype, err := jsonparser.GetString(maxImps[0].Banner.Ext, "bannertype")
+ if err == nil && bannertype == models.TypeRewarded {
+ maxImps[0].Banner = nil
+ }
+ }
+
+ maxImps[0].Ext = setIfKeysExists(signalImp.Ext, maxImps[0].Ext, "reward", "skadn")
+}
+
+func updateDevice(signalDevice *openrtb2.Device, maxRequest *openrtb2.BidRequest) {
+ if signalDevice == nil {
+ return
+ }
+
+ if maxRequest.Device == nil {
+ maxRequest.Device = &openrtb2.Device{}
+ }
+
+ if signalDevice.MCCMNC != "" {
+ maxRequest.Device.MCCMNC = signalDevice.MCCMNC
+ }
+
+ if signalDevice.ConnectionType != nil {
+ maxRequest.Device.ConnectionType = signalDevice.ConnectionType
+ }
+
+ maxRequest.Device.Ext = setIfKeysExists(signalDevice.Ext, maxRequest.Device.Ext, "atts")
+
+ if signalDevice.Geo == nil {
+ return
+ }
+
+ if maxRequest.Device.Geo == nil {
+ maxRequest.Device.Geo = &openrtb2.Geo{}
+ }
+
+ if signalDevice.Geo.City != "" {
+ maxRequest.Device.Geo.City = signalDevice.Geo.City
+ }
+
+ if signalDevice.Geo.UTCOffset != 0 {
+ maxRequest.Device.Geo.UTCOffset = signalDevice.Geo.UTCOffset
+ }
+}
+
+func updateApp(signalApp *openrtb2.App, maxRequest *openrtb2.BidRequest) {
+ if signalApp == nil {
+ return
+ }
+
+ if maxRequest.App == nil {
+ maxRequest.App = &openrtb2.App{}
+ }
+
+ if signalApp.Paid != nil {
+ maxRequest.App.Paid = signalApp.Paid
+ }
+
+ if signalApp.Keywords != "" {
+ maxRequest.App.Keywords = signalApp.Keywords
+ }
+
+ if signalApp.Domain != "" {
+ maxRequest.App.Domain = signalApp.Domain
+ }
+}
+
+func updateRegs(signalRegs *openrtb2.Regs, maxRequest *openrtb2.BidRequest) {
+ if signalRegs == nil {
+ return
+ }
+
+ if maxRequest.Regs == nil {
+ maxRequest.Regs = &openrtb2.Regs{}
+ }
+
+ if signalRegs.COPPA != 0 {
+ maxRequest.Regs.COPPA = signalRegs.COPPA
+ }
+ maxRequest.Regs.Ext = setIfKeysExists(signalRegs.Ext, maxRequest.Regs.Ext, "gdpr", "gpp", "gpp_sid", "us_privacy")
+}
+
+func updateSource(signalSource *openrtb2.Source, maxRequest *openrtb2.BidRequest) {
+ if signalSource == nil || len(signalSource.Ext) == 0 {
+ return
+ }
+
+ if maxRequest.Source == nil {
+ maxRequest.Source = &openrtb2.Source{}
+ }
+
+ maxRequest.Source.Ext = setIfKeysExists(signalSource.Ext, maxRequest.Source.Ext, "omidpn", "omidpv")
+}
+
+func updateUser(signalUser *openrtb2.User, maxRequest *openrtb2.BidRequest) {
+ if signalUser == nil {
+ return
+ }
+
+ if maxRequest.User == nil {
+ maxRequest.User = &openrtb2.User{}
+ }
+
+ if signalUser.Yob != 0 {
+ maxRequest.User.Yob = signalUser.Yob
+ }
+
+ if signalUser.Gender != "" {
+ maxRequest.User.Gender = signalUser.Gender
+ }
+
+ if signalUser.Keywords != "" {
+ maxRequest.User.Keywords = signalUser.Keywords
+ }
+
+ maxRequest.User.Data = signalUser.Data
+ maxRequest.User.Ext = setIfKeysExists(signalUser.Ext, maxRequest.User.Ext, "consent", "eids")
+}
+
+func setIfKeysExists(source []byte, target []byte, keys ...string) []byte {
+ newTarget := target
+ if len(keys) > 0 && len(newTarget) == 0 {
+ newTarget = []byte(`{}`)
+ }
+
+ for _, key := range keys {
+ field, dataType, _, err := jsonparser.Get(source, key)
+ if err != nil {
+ continue
+ }
+
+ if dataType == jsonparser.String {
+ quotedStr := strconv.Quote(string(field))
+ field = []byte(quotedStr)
+ }
+
+ newTarget, err = jsonparser.Set(newTarget, field, key)
+ if err != nil {
+ return target
+ }
+ }
+
+ if len(newTarget) == 2 {
+ return target
+ }
+ return newTarget
+}
+
+func updateRequestWrapper(signalExt json.RawMessage, maxRequest *openrtb2.BidRequest) {
+ clientConfigFlag, err := jsonparser.GetInt(signalExt, "wrapper", "clientconfig")
+ if err != nil || clientConfigFlag != 1 {
+ return
+ }
+
+ if maxReqExt, err := jsonparser.Set(maxRequest.Ext, []byte(`1`), "prebid", "bidderparams", "pubmatic", "wrapper", "clientconfig"); err == nil {
+ maxRequest.Ext = maxReqExt
+ }
+}
+
+func updateAppLovinMaxRequest(requestBody []byte) []byte {
+ signalData := getSignalData(requestBody)
+ if signalData == nil {
+ return requestBody
+ }
+
+ maxRequest := &openrtb2.BidRequest{}
+ if err := json.Unmarshal(requestBody, maxRequest); err != nil {
+ return requestBody
+ }
+
+ addSignalDataInRequest(signalData, maxRequest)
+ if maxRequestbytes, err := json.Marshal(maxRequest); err == nil {
+ return maxRequestbytes
+ }
+ return requestBody
+}
+
+func updateAppLovinMaxResponse(rctx models.RequestCtx, bidResponse *openrtb2.BidResponse) models.AppLovinMax {
+ maxAppLovin := models.AppLovinMax{Reject: false}
+
+ if bidResponse.NBR != nil {
+ if !rctx.Debug {
+ maxAppLovin.Reject = true
+ }
+ } else if len(bidResponse.SeatBid) == 0 || len(bidResponse.SeatBid[0].Bid) == 0 {
+ maxAppLovin.Reject = true
+ }
+ return maxAppLovin
+}
+
+func applyAppLovinMaxResponse(rctx models.RequestCtx, bidResponse *openrtb2.BidResponse) *openrtb2.BidResponse {
+ if rctx.AppLovinMax.Reject {
+ return bidResponse
+ }
+
+ //This condition is applied only in case if debug=1 refer func updateMaxAppLovinResponse
+ if bidResponse.NBR != nil {
+ return bidResponse
+ }
+
+ resp, err := json.Marshal(bidResponse)
+ if err != nil {
+ return bidResponse
+ }
+
+ signaldata := `{"` + models.SignalData + `":` + strconv.Quote(string(resp)) + `}`
+ *bidResponse = openrtb2.BidResponse{
+ ID: bidResponse.ID,
+ BidID: bidResponse.SeatBid[0].Bid[0].ID,
+ Cur: bidResponse.Cur,
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: bidResponse.SeatBid[0].Bid[0].ID,
+ ImpID: bidResponse.SeatBid[0].Bid[0].ImpID,
+ Price: bidResponse.SeatBid[0].Bid[0].Price,
+ BURL: bidResponse.SeatBid[0].Bid[0].BURL,
+ Ext: json.RawMessage(signaldata),
+ },
+ },
+ },
+ },
+ }
+ return bidResponse
+}
diff --git a/modules/pubmatic/openwrap/applovinmax_test.go b/modules/pubmatic/openwrap/applovinmax_test.go
new file mode 100644
index 00000000000..f33a55a6a52
--- /dev/null
+++ b/modules/pubmatic/openwrap/applovinmax_test.go
@@ -0,0 +1,963 @@
+package openwrap
+
+import (
+ "encoding/json"
+ "testing"
+
+ "github.com/prebid/openrtb/v20/adcom1"
+ "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/util/ptrutil"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestUpdateImpression(t *testing.T) {
+ type args struct {
+ signalImps []openrtb2.Imp
+ maxImps []openrtb2.Imp
+ }
+ tests := []struct {
+ name string
+ args args
+ want []openrtb2.Imp
+ }{
+ {
+ name: "maxImps nil",
+ args: args{
+ maxImps: nil,
+ },
+ want: nil,
+ },
+ {
+ name: "signalImps nil",
+ args: args{
+ maxImps: nil,
+ signalImps: nil,
+ },
+ want: nil,
+ },
+ {
+ name: "signalImps with no impressions",
+ args: args{
+ maxImps: nil,
+ signalImps: []openrtb2.Imp{},
+ },
+ want: nil,
+ },
+ {
+ name: "maxImps with no impressions",
+ args: args{
+ maxImps: []openrtb2.Imp{},
+ signalImps: []openrtb2.Imp{},
+ },
+ want: []openrtb2.Imp{},
+ },
+ {
+ name: "maxImps and signalImps with empty impressions",
+ args: args{
+ maxImps: []openrtb2.Imp{{}},
+ signalImps: []openrtb2.Imp{{}},
+ },
+ want: []openrtb2.Imp{{}},
+ },
+ {
+ name: "maxImp video not present",
+ args: args{
+ signalImps: []openrtb2.Imp{{ClickBrowser: openrtb2.Int8Ptr(0), DisplayManager: "PubMatic_SDK", DisplayManagerVer: "1.2"}},
+ maxImps: []openrtb2.Imp{{ClickBrowser: openrtb2.Int8Ptr(1), DisplayManager: "Applovin_SDK"}},
+ },
+ want: []openrtb2.Imp{{ClickBrowser: openrtb2.Int8Ptr(0), DisplayManager: "PubMatic_SDK", DisplayManagerVer: "1.2"}},
+ },
+ {
+ name: "only maxImp has video",
+ args: args{
+ signalImps: []openrtb2.Imp{{ClickBrowser: openrtb2.Int8Ptr(0), DisplayManager: "PubMatic_SDK", DisplayManagerVer: "1.2"}},
+ maxImps: []openrtb2.Imp{{ClickBrowser: openrtb2.Int8Ptr(1), DisplayManager: "Applovin_SDK", Video: &openrtb2.Video{W: openrtb2.Int64Ptr(300), H: openrtb2.Int64Ptr(250)}}},
+ },
+ want: []openrtb2.Imp{{ClickBrowser: openrtb2.Int8Ptr(0), DisplayManager: "PubMatic_SDK", DisplayManagerVer: "1.2", Video: &openrtb2.Video{W: openrtb2.Int64Ptr(300), H: openrtb2.Int64Ptr(250)}}},
+ },
+ {
+ name: "maxImp and sdkImp has video",
+ args: args{
+ signalImps: []openrtb2.Imp{{ClickBrowser: openrtb2.Int8Ptr(0), DisplayManager: "PubMatic_SDK", DisplayManagerVer: "1.2", Video: &openrtb2.Video{W: openrtb2.Int64Ptr(300), H: openrtb2.Int64Ptr(250), BAttr: []adcom1.CreativeAttribute{1, 2}}}},
+ maxImps: []openrtb2.Imp{{ClickBrowser: openrtb2.Int8Ptr(1), DisplayManager: "Applovin_SDK", Video: &openrtb2.Video{W: openrtb2.Int64Ptr(750), H: openrtb2.Int64Ptr(500), BAttr: []adcom1.CreativeAttribute{6, 1, 8, 4}}}},
+ },
+ want: []openrtb2.Imp{{ClickBrowser: openrtb2.Int8Ptr(0), DisplayManager: "PubMatic_SDK", DisplayManagerVer: "1.2", Video: &openrtb2.Video{W: openrtb2.Int64Ptr(300), H: openrtb2.Int64Ptr(250), BAttr: []adcom1.CreativeAttribute{1, 2}}}},
+ },
+ {
+ name: "maxImp has and sdkImp has banner with api",
+ args: args{
+ signalImps: []openrtb2.Imp{{Banner: &openrtb2.Banner{ID: "sdk_banner", API: []adcom1.APIFramework{1, 2, 3, 4}}}},
+ maxImps: []openrtb2.Imp{{Banner: &openrtb2.Banner{ID: "max_banner"}}},
+ },
+ want: []openrtb2.Imp{{Banner: &openrtb2.Banner{ID: "max_banner", API: []adcom1.APIFramework{1, 2, 3, 4}}}},
+ },
+ {
+ name: "maxImp has bannertype rewarded",
+ args: args{
+ signalImps: []openrtb2.Imp{{Banner: &openrtb2.Banner{ID: "sdk_banner", API: []adcom1.APIFramework{1, 2, 3, 4}}}},
+ maxImps: []openrtb2.Imp{{Banner: &openrtb2.Banner{ID: "max_banner", Ext: json.RawMessage(`{"bannertype":"rewarded"}`)}}},
+ },
+ want: []openrtb2.Imp{{}},
+ },
+ {
+ name: "Banner API not present in signalImp",
+ args: args{
+ signalImps: []openrtb2.Imp{{Banner: &openrtb2.Banner{ID: "sdk_banner"}}},
+ maxImps: []openrtb2.Imp{{Banner: &openrtb2.Banner{ID: "max_banner", API: []adcom1.APIFramework{1, 2}, Ext: json.RawMessage(`{"bannertype":"not-rewarded"}`)}}},
+ },
+ want: []openrtb2.Imp{{Banner: &openrtb2.Banner{ID: "max_banner", API: []adcom1.APIFramework{1, 2}, Ext: json.RawMessage(`{"bannertype":"not-rewarded"}`)}}},
+ },
+ {
+ name: "maxImp has no ext, signalImp has reward in ext",
+ args: args{
+ signalImps: []openrtb2.Imp{{Ext: json.RawMessage(`{"reward":1}`)}},
+ maxImps: []openrtb2.Imp{{}},
+ },
+ want: []openrtb2.Imp{{Ext: json.RawMessage(`{"reward":1}`)}},
+ },
+ {
+ name: "maxImp has no ext, signalImp has reward and skadn in ext",
+ args: args{
+ signalImps: []openrtb2.Imp{{Ext: json.RawMessage(`{"reward":1,"skadn":{"versions":["2.0","2.1"],"sourceapp":"11111","skadnetids":["424m5254lk.skadnetwork","4fzdc2evr5.skadnetwork"]}}`)}},
+ maxImps: []openrtb2.Imp{{}},
+ },
+ want: []openrtb2.Imp{{Ext: json.RawMessage(`{"reward":1,"skadn":{"versions":["2.0","2.1"],"sourceapp":"11111","skadnetids":["424m5254lk.skadnetwork","4fzdc2evr5.skadnetwork"]}}`)}},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ updateImpression(tt.args.signalImps, tt.args.maxImps)
+ assert.Equal(t, tt.want, tt.args.maxImps, tt.name)
+ })
+ }
+}
+
+func TestUpdateDevice(t *testing.T) {
+ type args struct {
+ sdkDevice *openrtb2.Device
+ maxRequest *openrtb2.BidRequest
+ }
+ tests := []struct {
+ name string
+ args args
+ want *openrtb2.Device
+ }{
+ {
+ name: "sdkDevice nil",
+ args: args{
+ sdkDevice: nil,
+ maxRequest: &openrtb2.BidRequest{Device: &openrtb2.Device{DeviceType: 5}},
+ },
+ want: &openrtb2.Device{DeviceType: 5},
+ },
+ {
+ name: "sdkDevice has mccmnc,connectiontype",
+ args: args{
+ sdkDevice: &openrtb2.Device{MCCMNC: "mccmnc", ConnectionType: adcom1.Connection2G.Ptr()},
+ maxRequest: &openrtb2.BidRequest{Device: &openrtb2.Device{DeviceType: 5}},
+ },
+ want: &openrtb2.Device{DeviceType: 5, MCCMNC: "mccmnc", ConnectionType: adcom1.Connection2G.Ptr()},
+ },
+ {
+ name: "sdkDeviceExt has atts",
+ args: args{
+ sdkDevice: &openrtb2.Device{Ext: json.RawMessage(`{"atts":3}`)},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: &openrtb2.Device{Ext: json.RawMessage(`{"atts":3}`)},
+ },
+ {
+ name: "sdkDevice has geo city and utcoffset",
+ args: args{
+ sdkDevice: &openrtb2.Device{Geo: &openrtb2.Geo{City: "Delhi", UTCOffset: 3}, Ext: json.RawMessage(`{"atts":3}`)},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: &openrtb2.Device{Geo: &openrtb2.Geo{City: "Delhi", UTCOffset: 3}, Ext: json.RawMessage(`{"atts":3}`)},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ updateDevice(tt.args.sdkDevice, tt.args.maxRequest)
+ assert.Equal(t, tt.want, tt.args.maxRequest.Device, tt.name)
+ })
+ }
+}
+
+func TestUpdateApp(t *testing.T) {
+ type args struct {
+ signalApp *openrtb2.App
+ maxRequest *openrtb2.BidRequest
+ }
+ tests := []struct {
+ name string
+ args args
+ want *openrtb2.App
+ }{
+ {
+ name: "signalApp is nil",
+ args: args{
+ signalApp: nil,
+ maxRequest: &openrtb2.BidRequest{App: &openrtb2.App{ID: "signalApp"}},
+ },
+ want: &openrtb2.App{ID: "signalApp"},
+ },
+ {
+ name: "maxDevice is nil",
+ args: args{
+ signalApp: &openrtb2.App{},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: &openrtb2.App{},
+ },
+ {
+ name: "signalApp has Paid,Keywords and Domain",
+ args: args{
+ signalApp: &openrtb2.App{Paid: openrtb2.Int8Ptr(1), Keywords: "k1=v1", Domain: "abc.com"},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: &openrtb2.App{Paid: openrtb2.Int8Ptr(1), Keywords: "k1=v1", Domain: "abc.com"},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ updateApp(tt.args.signalApp, tt.args.maxRequest)
+ assert.Equal(t, tt.want, tt.args.maxRequest.App, tt.name)
+ })
+ }
+}
+
+func TestUpdateRegs(t *testing.T) {
+ type args struct {
+ signalRegs *openrtb2.Regs
+ maxRequest *openrtb2.BidRequest
+ }
+ tests := []struct {
+ name string
+ args args
+ want *openrtb2.Regs
+ }{
+ {
+ name: "signalRegs is nil",
+ args: args{
+ signalRegs: nil,
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: nil,
+ },
+ {
+ name: "signalRegsExt is nil",
+ args: args{
+ signalRegs: &openrtb2.Regs{},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: &openrtb2.Regs{},
+ },
+ {
+ name: "maxRegs is nil",
+ args: args{
+ signalRegs: &openrtb2.Regs{Ext: json.RawMessage(`{}`)},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: &openrtb2.Regs{},
+ },
+ {
+ name: "signalRegs has coppa, signalRegsExt has gdpr, gpp",
+ args: args{
+ signalRegs: &openrtb2.Regs{COPPA: 1, Ext: json.RawMessage(`{"gdpr":1,"gpp":"sdfewe3cer"}`)},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: &openrtb2.Regs{COPPA: 1, Ext: json.RawMessage(`{"gdpr":1,"gpp":"sdfewe3cer"}`)},
+ },
+ {
+ name: "signalRegs has coppa as 0, signalRegsExt has gdpr, gpp",
+ args: args{
+ signalRegs: &openrtb2.Regs{COPPA: 0, Ext: json.RawMessage(`{"gdpr":1,"gpp":"sdfewe3cer"}`)},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: &openrtb2.Regs{Ext: json.RawMessage(`{"gdpr":1,"gpp":"sdfewe3cer"}`)},
+ },
+ {
+ name: "signalRegsExt has gdpr, gpp, gpp_sid, us_privacy and maxRegsExt has gpp",
+ args: args{
+ signalRegs: &openrtb2.Regs{Ext: json.RawMessage(`{"gdpr":1,"gpp":"sdfewe3cer","gpp_sid":[6],"us_privacy":"uspConsentString"}`)},
+ maxRequest: &openrtb2.BidRequest{Regs: &openrtb2.Regs{Ext: json.RawMessage(`{"gpp":"gpp_string"}`)}},
+ },
+ want: &openrtb2.Regs{Ext: json.RawMessage(`{"gpp":"sdfewe3cer","gdpr":1,"gpp_sid":[6],"us_privacy":"uspConsentString"}`)},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ updateRegs(tt.args.signalRegs, tt.args.maxRequest)
+ assert.Equal(t, tt.want, tt.args.maxRequest.Regs, tt.name)
+ })
+ }
+}
+
+func TestUpdateSource(t *testing.T) {
+ type args struct {
+ signalSource *openrtb2.Source
+ maxRequest *openrtb2.BidRequest
+ }
+ tests := []struct {
+ name string
+ args args
+ want *openrtb2.Source
+ }{
+ {
+ name: "signalSource is nil",
+ args: args{
+ signalSource: nil,
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: nil,
+ },
+ {
+ name: "signalSourceExt is nil",
+ args: args{
+ signalSource: &openrtb2.Source{},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: nil,
+ },
+ {
+ name: "maxSource is nil",
+ args: args{
+ signalSource: &openrtb2.Source{Ext: json.RawMessage(`{}`)},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: &openrtb2.Source{},
+ },
+ {
+ name: "signalSourceExt has omidpn, omidpv",
+ args: args{
+ signalSource: &openrtb2.Source{Ext: json.RawMessage(`{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}`)},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: &openrtb2.Source{Ext: json.RawMessage(`{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}`)},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ updateSource(tt.args.signalSource, tt.args.maxRequest)
+ assert.Equal(t, tt.want, tt.args.maxRequest.Source, tt.name)
+ })
+ }
+}
+
+func TestUpdateUser(t *testing.T) {
+ type args struct {
+ signalUser *openrtb2.User
+ maxRequest *openrtb2.BidRequest
+ }
+ tests := []struct {
+ name string
+ args args
+ want *openrtb2.User
+ }{
+ {
+ name: "signalUser is nil",
+ args: args{
+ signalUser: nil,
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: nil,
+ },
+ {
+ name: "maxUser is nil",
+ args: args{
+ signalUser: &openrtb2.User{Ext: json.RawMessage(``)},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: &openrtb2.User{},
+ },
+ {
+ name: "signalUser has yob, gender, keywords",
+ args: args{
+ signalUser: &openrtb2.User{Yob: 1999, Gender: "M", Keywords: "k1=v2;k2=v2", Ext: json.RawMessage(``)},
+ maxRequest: &openrtb2.BidRequest{},
+ },
+ want: &openrtb2.User{Yob: 1999, Gender: "M", Keywords: "k1=v2;k2=v2"},
+ },
+ {
+ name: "signalUser and maxUser has yob, gender, keywords and data",
+ args: args{
+ signalUser: &openrtb2.User{Data: []openrtb2.Data{{ID: "123", Name: "PubMatic_SDK", Segment: []openrtb2.Segment{{ID: "seg_id", Name: "PubMatic_Seg", Value: "segment_value", Ext: json.RawMessage(`{"segtax":4}`)}}}}, Yob: 1999, Gender: "M", Keywords: "k1=v2;k2=v2", Ext: json.RawMessage(``)},
+ maxRequest: &openrtb2.BidRequest{User: &openrtb2.User{Data: []openrtb2.Data{{ID: "max_id", Name: "Publisher Passed", Segment: []openrtb2.Segment{{ID: "max_seg_id", Name: "max_Seg", Value: "max_segment_value"}}}}, Yob: 2000, Gender: "F", Keywords: "k52=v43"}},
+ },
+ want: &openrtb2.User{Data: []openrtb2.Data{{ID: "123", Name: "PubMatic_SDK", Segment: []openrtb2.Segment{{ID: "seg_id", Name: "PubMatic_Seg", Value: "segment_value", Ext: json.RawMessage(`{"segtax":4}`)}}}}, Yob: 1999, Gender: "M", Keywords: "k1=v2;k2=v2"},
+ },
+ {
+ name: "signalUserExt has consent",
+ args: args{
+ signalUser: &openrtb2.User{ID: "sdkID", Yob: 1999, Gender: "M", Keywords: "k1=v2;k2=v2", Ext: json.RawMessage(`{"consent":"consent_string"}`)},
+ maxRequest: &openrtb2.BidRequest{User: &openrtb2.User{ID: "maxID", Yob: 2000, Gender: "F", Keywords: "k52=v43"}},
+ },
+ want: &openrtb2.User{ID: "maxID", Yob: 1999, Gender: "M", Keywords: "k1=v2;k2=v2", Ext: json.RawMessage(`{"consent":"consent_string"}`)},
+ },
+ {
+ name: "signalUserExt has consent and eids",
+ args: args{
+ signalUser: &openrtb2.User{ID: "sdkID", Yob: 1999, Gender: "M", Keywords: "k1=v2;k2=v2", Ext: json.RawMessage(`{"consent":"consent_string","eids":[{"source":"amxid","uids":[{"atype":1,"id":"88de601e-3d98-48e7-81d7-00000000"}]},{"source":"adserver.org","uids":[{"id":"1234567","ext":{"rtiPartner":"TDID"}}]}]}`)},
+ maxRequest: &openrtb2.BidRequest{User: &openrtb2.User{ID: "maxID", Yob: 2000, Gender: "F", Keywords: "k52=v43"}},
+ },
+ want: &openrtb2.User{ID: "maxID", Yob: 1999, Gender: "M", Keywords: "k1=v2;k2=v2", Ext: json.RawMessage(`{"consent":"consent_string","eids":[{"source":"amxid","uids":[{"atype":1,"id":"88de601e-3d98-48e7-81d7-00000000"}]},{"source":"adserver.org","uids":[{"id":"1234567","ext":{"rtiPartner":"TDID"}}]}]}`)},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ updateUser(tt.args.signalUser, tt.args.maxRequest)
+ assert.Equal(t, tt.want, tt.args.maxRequest.User, tt.name)
+ })
+ }
+}
+
+func TestSetIfKeysExists(t *testing.T) {
+ type args struct {
+ source []byte
+ target []byte
+ keys []string
+ }
+ tests := []struct {
+ name string
+ args args
+ want []byte
+ }{
+ {
+ name: "keys not found in source",
+ args: args{
+ source: nil,
+ target: nil,
+ keys: []string{"key1", "key2"},
+ },
+ want: nil,
+ },
+ {
+ name: "int value key found out of all keys",
+ args: args{
+ source: []byte(`{"key1":23,"key40":"v40"}`),
+ target: nil,
+ keys: []string{"key1", "key2"},
+ },
+ want: []byte(`{"key1":23}`),
+ },
+ {
+ name: "string value key found out of all keys",
+ args: args{
+ source: []byte(`{"key1":23,"key40":"v40"}`),
+ target: nil,
+ keys: []string{"key40", "key2"},
+ },
+ want: []byte(`{"key40":"v40"}`),
+ },
+ {
+ name: "overwrite string value key in target",
+ args: args{
+ source: []byte(`{"key1":55555,"key40":"v40"}`),
+ target: []byte(`{"key1":23,"key40":"will_overwrite"}`),
+ keys: []string{"key40", "key2"},
+ },
+ want: []byte(`{"key1":23,"key40":"v40"}`),
+ },
+ {
+ name: "error while setting key, return oldTarget",
+ args: args{
+ source: []byte(`{"key1":555555,"key40":"v40"}`),
+ target: []byte(`"key1":23,"key40":"value40"}`),
+ keys: []string{"key40", "key2"},
+ },
+ want: []byte(`"key1":23,"key40":"value40"}`),
+ },
+ {
+ name: "overwrite key in target with object",
+ args: args{
+ source: []byte(`{"key1":55555,"key40":{"user":{"id":"1kjh3429kjh295jkl","ext":{"consent":"CONSENT_STRING"}},"regs":{"ext":{"gdpr":1}}}}`),
+ target: []byte(`{"key1":23,"key40":[]}`),
+ keys: []string{"key40", "key2"},
+ },
+ want: []byte(`{"key1":23,"key40":{"user":{"id":"1kjh3429kjh295jkl","ext":{"consent":"CONSENT_STRING"}},"regs":{"ext":{"gdpr":1}}}}`),
+ },
+ {
+ name: "set slice in key",
+ args: args{
+ source: []byte(`{"key1":555555,"key40":[1,2,3,4,5]}`),
+ target: []byte(`{"key1":23,"key40":"value40"}`),
+ keys: []string{"key40", "key2"},
+ },
+ want: []byte(`{"key1":23,"key40":[1,2,3,4,5]}`),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := setIfKeysExists(tt.args.source, tt.args.target, tt.args.keys...)
+ assert.Equal(t, tt.want, got, tt.name)
+ })
+ }
+}
+
+func TestAddSignalDataInRequest(t *testing.T) {
+ type args struct {
+ signal string
+ maxRequest json.RawMessage
+ }
+ tests := []struct {
+ name string
+ args args
+ wantMaxRequest json.RawMessage
+ }{
+ {
+ name: "replace or add from signal",
+ args: args{
+ signal: `{"device":{"devicetype":4,"w":393,"h":852,"ifa":"F5BA1637-7156-4369-BA7E-3C45033D9F61","mccmnc":"311-480","js":1,"osv":"17.3.1","connectiontype":5,"os":"iOS","pxratio":3,"geo":{"lastfix":8,"lat":37.48773508935608,"utcoffset":-480,"lon":-122.22855027909678,"type":1},"language":"en","make":"Apple","ext":{"atts":3},"ua":"Mozilla/5.0 (iPhone; CPU iPhone OS 17_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148","model":"iPhone15,2","carrier":"Verizon"},"source":{"ext":{"omidpn":"Pubmatic","omidpv":"3.1.0"}},"id":"CE204A0E-31C3-4D7F-A1A0-D34AF5ED1A7F","app":{"id":"406719683","paid":1,"keywords":"k1=v1","domain":"abc.com","bundle":"406719683","storeurl":"https://apps.apple.com/us/app/gasbuddy-find-pay-for-gas/id406719683","name":"GasBuddy","publisher":{"id":"160361"},"ver":"700.89.22927"},"ext":{"wrapper":{"sumry_disable":1,"profileid":3422}},"imp":[{"secure":1,"tagid":"Mobile_iPhone_List_Screen_Bottom","banner":{"pos":0,"format":[{"w":300,"h":250}],"api":[5,6,7]},"id":"98D9318E-5276-402F-BAA4-CDBD8A364957","ext":{"skadn":{"sourceapp":"406719683","versions":["2.0","2.1","2.2","3.0","4.0"],"skadnetids":["cstr6suwn9.skadnetwork","7ug5zh24hu.skadnetwork","uw77j35x4d.skadnetwork","c6k4g5qg8m.skadnetwork","hs6bdukanm.skadnetwork","yclnxrl5pm.skadnetwork","3sh42y64q3.skadnetwork","cj5566h2ga.skadnetwork","klf5c3l5u5.skadnetwork","8s468mfl3y.skadnetwork","2u9pt9hc89.skadnetwork","7rz58n8ntl.skadnetwork","ppxm28t8ap.skadnetwork","mtkv5xtk9e.skadnetwork","cg4yq2srnc.skadnetwork","wzmmz9fp6w.skadnetwork","k674qkevps.skadnetwork","v72qych5uu.skadnetwork","578prtvx9j.skadnetwork","3rd42ekr43.skadnetwork","g28c52eehv.skadnetwork","2fnua5tdw4.skadnetwork","9nlqeag3gk.skadnetwork","5lm9lj6jb7.skadnetwork","97r2b46745.skadnetwork","e5fvkxwrpn.skadnetwork","4pfyvq9l8r.skadnetwork","tl55sbb4fm.skadnetwork","t38b2kh725.skadnetwork","prcb7njmu6.skadnetwork","mlmmfzh3r3.skadnetwork","9t245vhmpl.skadnetwork","9rd848q2bz.skadnetwork","4fzdc2evr5.skadnetwork","4468km3ulz.skadnetwork","m8dbw4sv7c.skadnetwork","ejvt5qm6ak.skadnetwork","5lm9lj6jb7.skadnetwork","44jx6755aq.skadnetwork","6g9af3uyq4.skadnetwork","u679fj5vs4.skadnetwork","rx5hdcabgc.skadnetwork","275upjj5gd.skadnetwork","p78axxw29g.skadnetwork"],"productpage":1,"version":"2.0"}},"displaymanagerver":"3.1.0","clickbrowser":1,"video":{"companionad":[{"pos":0,"format":[{"w":300,"h":250}],"vcm":1}],"protocols":[2,3,5,6,7,8,11,12,13,14],"h":250,"w":300,"linearity":1,"pos":0,"boxingallowed":1,"placement":2,"mimes":["video/3gpp2","video/quicktime","video/mp4","video/x-m4v","video/3gpp"],"companiontype":[1,2,3],"delivery":[2],"startdelay":0,"playbackend":1,"api":[7]},"displaymanager":"PubMatic_OpenWrap_SDK","instl":0}],"at":1,"cur":["USD"],"regs":{"coppa":1,"ext":{"ccpa":0,"gdpr":1,"gpp":"gpp_string","gpp_sid":[7],"us_privacy":"uspConsentString","consent":"0"}}}`,
+ maxRequest: json.RawMessage(`{"id":"{BID_ID}","at":1,"bcat":["IAB26-4","IAB26-2","IAB25-6","IAB25-5","IAB25-4","IAB25-3","IAB25-1","IAB25-7","IAB8-18","IAB26-3","IAB26-1","IAB8-5","IAB25-2","IAB11-4"],"tmax":3000,"app":{"name":"DrawHappyAngel","ver":"0.5.4","bundle":"com.newstory.DrawHappyAngel","cat":["IAB9-30"],"id":"{NETWORK_APP_ID}","publisher":{"name":"New Story Inc.","ext":{"installed_sdk":{"id":"MOLOCO_BIDDING","sdk_version":{"major":1,"minor":0,"micro":0},"adapter_version":{"major":1,"minor":0,"micro":0}}}},"ext":{"orientation":1}},"device":{"ifa":"497a10d6-c4dd-4e04-a986-c32b7180d462","ip":"38.158.207.171","carrier":"MYTEL","language":"en_US","hwv":"ruby","ppi":440,"pxratio":2.75,"devicetype":4,"connectiontype":2,"js":1,"h":2400,"w":1080,"geo":{"type":2,"ipservice":3,"lat":40.7429,"lon":-73.9392,"long":-73.9392,"city":"Queens","country":"USA","region":"ny","dma":"501","metro":"501","zip":"11101","ext":{"org":"Myanmar Broadband Telecom Co.","isp":"Myanmar Broadband Telecom Co."}},"ext":{},"osv":"13.0.0","ua":"Mozilla/5.0 (Linux; Android 13; 22101316C Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/120.0.6099.230 Mobile Safari/537.36","make":"xiaomi","model":"22101316c","os":"android"},"imp":[{"id":"1","displaymanager":"applovin_mediation","displaymanagerver":"11.8.2","instl":0,"secure":0,"tagid":"{NETWORK_PLACEMENT_ID}","bidfloor":0.01,"bidfloorcur":"USD","exp":14400,"banner":{"id":"1","w":320,"h":50,"btype":[],"battr":[1,2,5,8,9,14,17],"pos":1,"format":[{"w":320,"h":50}]},"rwdd":0}],"user":{"data":[{"id":"1","name":"Publisher Passed","segment":[{"signal":"{BIDDING_SIGNAL}"}]}],"ext":{"gdpr":0}},"regs":{"ext":{"ccpa":0,"gdpr":1,"consent":"0","tcf_consent_string":"{TCF_STRING}"}},"source":{"ext":{"schain":{"ver":"1.0","complete":1,"nodes":[{"asi":"applovin.com","sid":"53bf468f18c5a0e2b7d4e3f748c677c1","rid":"494dbe15a3ce08c54f4e456363f35a022247f997","hp":1}]}}},"ext":{"prebid":{"bidderparams":{"pubmatic":{"wrapper":{"profileid":1234}}}}}}`),
+ },
+ wantMaxRequest: json.RawMessage(`{"id":"{BID_ID}","at":1,"bcat":["IAB26-4","IAB26-2","IAB25-6","IAB25-5","IAB25-4","IAB25-3","IAB25-1","IAB25-7","IAB8-18","IAB26-3","IAB26-1","IAB8-5","IAB25-2","IAB11-4"],"tmax":3000,"app":{"paid":1,"keywords":"k1=v1","domain":"abc.com","name":"DrawHappyAngel","ver":"0.5.4","bundle":"com.newstory.DrawHappyAngel","cat":["IAB9-30"],"id":"{NETWORK_APP_ID}","publisher":{"name":"New Story Inc.","ext":{"installed_sdk":{"id":"MOLOCO_BIDDING","sdk_version":{"major":1,"minor":0,"micro":0},"adapter_version":{"major":1,"minor":0,"micro":0}}}},"ext":{"orientation":1}},"device":{"ifa":"497a10d6-c4dd-4e04-a986-c32b7180d462","ip":"38.158.207.171","carrier":"MYTEL","language":"en_US","hwv":"ruby","ppi":440,"pxratio":2.75,"devicetype":4,"mccmnc":"311-480","connectiontype":5,"js":1,"h":2400,"w":1080,"geo":{"city":"Queens","type":2,"ipservice":3,"lat":40.7429,"lon":-73.9392,"long":-73.9392,"country":"USA","region":"ny","dma":"501","metro":"501","zip":"11101","utcoffset":-480,"ext":{"org":"Myanmar Broadband Telecom Co.","isp":"Myanmar Broadband Telecom Co."}},"ext":{"atts":3},"osv":"13.0.0","ua":"Mozilla/5.0 (Linux; Android 13; 22101316C Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/120.0.6099.230 Mobile Safari/537.36","make":"xiaomi","model":"22101316c","os":"android"},"imp":[{"id":"1","displaymanagerver":"3.1.0","clickbrowser":1,"displaymanager":"PubMatic_OpenWrap_SDK","instl":0,"secure":0,"tagid":"{NETWORK_PLACEMENT_ID}","bidfloor":0.01,"bidfloorcur":"USD","exp":14400,"banner":{"id":"1","w":320,"h":50,"btype":[],"api":[5,6,7],"battr":[1,2,5,8,9,14,17],"pos":1,"format":[{"w":320,"h":50}]},"video":{"companionad":[{"pos":0,"format":[{"w":300,"h":250}],"vcm":1}],"protocols":[2,3,5,6,7,8,11,12,13,14],"h":250,"w":300,"linearity":1,"pos":0,"boxingallowed":1,"placement":2,"mimes":["video/3gpp2","video/quicktime","video/mp4","video/x-m4v","video/3gpp"],"companiontype":[1,2,3],"delivery":[2],"startdelay":0,"playbackend":1,"api":[7]},"rwdd":0,"ext":{"skadn":{"sourceapp":"406719683","versions":["2.0","2.1","2.2","3.0","4.0"],"skadnetids":["cstr6suwn9.skadnetwork","7ug5zh24hu.skadnetwork","uw77j35x4d.skadnetwork","c6k4g5qg8m.skadnetwork","hs6bdukanm.skadnetwork","yclnxrl5pm.skadnetwork","3sh42y64q3.skadnetwork","cj5566h2ga.skadnetwork","klf5c3l5u5.skadnetwork","8s468mfl3y.skadnetwork","2u9pt9hc89.skadnetwork","7rz58n8ntl.skadnetwork","ppxm28t8ap.skadnetwork","mtkv5xtk9e.skadnetwork","cg4yq2srnc.skadnetwork","wzmmz9fp6w.skadnetwork","k674qkevps.skadnetwork","v72qych5uu.skadnetwork","578prtvx9j.skadnetwork","3rd42ekr43.skadnetwork","g28c52eehv.skadnetwork","2fnua5tdw4.skadnetwork","9nlqeag3gk.skadnetwork","5lm9lj6jb7.skadnetwork","97r2b46745.skadnetwork","e5fvkxwrpn.skadnetwork","4pfyvq9l8r.skadnetwork","tl55sbb4fm.skadnetwork","t38b2kh725.skadnetwork","prcb7njmu6.skadnetwork","mlmmfzh3r3.skadnetwork","9t245vhmpl.skadnetwork","9rd848q2bz.skadnetwork","4fzdc2evr5.skadnetwork","4468km3ulz.skadnetwork","m8dbw4sv7c.skadnetwork","ejvt5qm6ak.skadnetwork","5lm9lj6jb7.skadnetwork","44jx6755aq.skadnetwork","6g9af3uyq4.skadnetwork","u679fj5vs4.skadnetwork","rx5hdcabgc.skadnetwork","275upjj5gd.skadnetwork","p78axxw29g.skadnetwork"],"productpage":1,"version":"2.0"}}}],"user":{"data":[{"id":"1","name":"Publisher Passed","segment":[{"signal":"{BIDDING_SIGNAL}"}]}],"ext":{"gdpr":0}},"regs":{"coppa":1,"ext":{"ccpa":0,"gdpr":1,"consent":"0","tcf_consent_string":"{TCF_STRING}","gpp":"gpp_string","gpp_sid":[7],"us_privacy":"uspConsentString"}},"source":{"ext":{"schain":{"ver":"1.0","complete":1,"nodes":[{"asi":"applovin.com","sid":"53bf468f18c5a0e2b7d4e3f748c677c1","rid":"494dbe15a3ce08c54f4e456363f35a022247f997","hp":1}]},"omidpn":"Pubmatic","omidpv":"3.1.0"}},"ext":{"prebid":{"bidderparams":{"pubmatic":{"wrapper":{"profileid":1234}}}}}}`),
+ },
+ {
+ name: "replace or add from signal,and remove banner as bannertype rewarded",
+ args: args{
+ signal: `{"device":{"devicetype":4,"w":393,"h":852,"ifa":"F5BA1637-7156-4369-BA7E-3C45033D9F61","mccmnc":"311-480","js":1,"osv":"17.3.1","connectiontype":5,"os":"iOS","pxratio":3,"geo":{"lastfix":8,"lat":37.48773508935608,"utcoffset":-480,"lon":-122.22855027909678,"type":1},"language":"en","make":"Apple","ext":{"atts":3},"ua":"Mozilla/5.0 (iPhone; CPU iPhone OS 17_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148","model":"iPhone15,2","carrier":"Verizon"},"source":{"ext":{"omidpn":"Pubmatic","omidpv":"3.1.0"}},"id":"CE204A0E-31C3-4D7F-A1A0-D34AF5ED1A7F","app":{"id":"406719683","paid":1,"keywords":"k1=v1","domain":"abc.com","bundle":"406719683","storeurl":"https://apps.apple.com/us/app/gasbuddy-find-pay-for-gas/id406719683","name":"GasBuddy","publisher":{"id":"160361"},"ver":"700.89.22927"},"ext":{"wrapper":{"sumry_disable":1,"clientconfig":1,"profileid":3422}},"imp":[{"secure":1,"tagid":"Mobile_iPhone_List_Screen_Bottom","banner":{"pos":0,"format":[{"w":300,"h":250}],"api":[5,6,7]},"id":"98D9318E-5276-402F-BAA4-CDBD8A364957","ext":{"skadn":{"sourceapp":"406719683","versions":["2.0","2.1","2.2","3.0","4.0"],"skadnetids":["cstr6suwn9.skadnetwork","7ug5zh24hu.skadnetwork","uw77j35x4d.skadnetwork","c6k4g5qg8m.skadnetwork","hs6bdukanm.skadnetwork","yclnxrl5pm.skadnetwork","3sh42y64q3.skadnetwork","cj5566h2ga.skadnetwork","klf5c3l5u5.skadnetwork","8s468mfl3y.skadnetwork","2u9pt9hc89.skadnetwork","7rz58n8ntl.skadnetwork","ppxm28t8ap.skadnetwork","mtkv5xtk9e.skadnetwork","cg4yq2srnc.skadnetwork","wzmmz9fp6w.skadnetwork","k674qkevps.skadnetwork","v72qych5uu.skadnetwork","578prtvx9j.skadnetwork","3rd42ekr43.skadnetwork","g28c52eehv.skadnetwork","2fnua5tdw4.skadnetwork","9nlqeag3gk.skadnetwork","5lm9lj6jb7.skadnetwork","97r2b46745.skadnetwork","e5fvkxwrpn.skadnetwork","4pfyvq9l8r.skadnetwork","tl55sbb4fm.skadnetwork","t38b2kh725.skadnetwork","prcb7njmu6.skadnetwork","mlmmfzh3r3.skadnetwork","9t245vhmpl.skadnetwork","9rd848q2bz.skadnetwork","4fzdc2evr5.skadnetwork","4468km3ulz.skadnetwork","m8dbw4sv7c.skadnetwork","ejvt5qm6ak.skadnetwork","5lm9lj6jb7.skadnetwork","44jx6755aq.skadnetwork","6g9af3uyq4.skadnetwork","u679fj5vs4.skadnetwork","rx5hdcabgc.skadnetwork","275upjj5gd.skadnetwork","p78axxw29g.skadnetwork"],"productpage":1,"version":"2.0"}},"displaymanagerver":"3.1.0","clickbrowser":1,"video":{"companionad":[{"pos":0,"format":[{"w":300,"h":250}],"vcm":1}],"protocols":[2,3,5,6,7,8,11,12,13,14],"h":250,"w":300,"linearity":1,"pos":0,"boxingallowed":1,"placement":2,"mimes":["video/3gpp2","video/quicktime","video/mp4","video/x-m4v","video/3gpp"],"companiontype":[1,2,3],"delivery":[2],"startdelay":0,"playbackend":1,"api":[7]},"displaymanager":"PubMatic_OpenWrap_SDK","instl":0}],"at":1,"cur":["USD"],"regs":{"coppa":1,"ext":{"ccpa":0,"gdpr":1,"gpp":"gpp_string","gpp_sid":[7],"us_privacy":"uspConsentString","consent":"0"}}}`,
+ maxRequest: json.RawMessage(`{"id":"{BID_ID}","at":1,"bcat":["IAB26-4","IAB26-2","IAB25-6","IAB25-5","IAB25-4","IAB25-3","IAB25-1","IAB25-7","IAB8-18","IAB26-3","IAB26-1","IAB8-5","IAB25-2","IAB11-4"],"tmax":3000,"app":{"name":"DrawHappyAngel","ver":"0.5.4","bundle":"com.newstory.DrawHappyAngel","cat":["IAB9-30"],"id":"{NETWORK_APP_ID}","publisher":{"name":"New Story Inc.","ext":{"installed_sdk":{"id":"MOLOCO_BIDDING","sdk_version":{"major":1,"minor":0,"micro":0},"adapter_version":{"major":1,"minor":0,"micro":0}}}},"ext":{"orientation":1}},"device":{"ifa":"497a10d6-c4dd-4e04-a986-c32b7180d462","ip":"38.158.207.171","carrier":"MYTEL","language":"en_US","hwv":"ruby","ppi":440,"pxratio":2.75,"devicetype":4,"connectiontype":2,"js":1,"h":2400,"w":1080,"geo":{"type":2,"ipservice":3,"lat":40.7429,"lon":-73.9392,"long":-73.9392,"city":"Queens","country":"USA","region":"ny","dma":"501","metro":"501","zip":"11101","ext":{"org":"Myanmar Broadband Telecom Co.","isp":"Myanmar Broadband Telecom Co."}},"ext":{},"osv":"13.0.0","ua":"Mozilla/5.0 (Linux; Android 13; 22101316C Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/120.0.6099.230 Mobile Safari/537.36","make":"xiaomi","model":"22101316c","os":"android"},"imp":[{"id":"1","displaymanager":"applovin_mediation","displaymanagerver":"11.8.2","instl":0,"secure":0,"tagid":"{NETWORK_PLACEMENT_ID}","bidfloor":0.01,"bidfloorcur":"USD","exp":14400,"banner":{"id":"1","w":320,"h":50,"btype":[],"battr":[1,2,5,8,9,14,17],"pos":1,"format":[{"w":320,"h":50}],"ext":{"bannertype":"rewarded"}},"rwdd":0}],"user":{"data":[{"id":"1","name":"Publisher Passed","segment":[{"signal":"{BIDDING_SIGNAL}"}]}],"ext":{"gdpr":0}},"regs":{"ext":{"ccpa":0,"gdpr":1,"consent":"0","tcf_consent_string":"{TCF_STRING}"}},"source":{"ext":{"schain":{"ver":"1.0","complete":1,"nodes":[{"asi":"applovin.com","sid":"53bf468f18c5a0e2b7d4e3f748c677c1","rid":"494dbe15a3ce08c54f4e456363f35a022247f997","hp":1}]}}}}`),
+ },
+ wantMaxRequest: json.RawMessage(`{"id":"{BID_ID}","at":1,"bcat":["IAB26-4","IAB26-2","IAB25-6","IAB25-5","IAB25-4","IAB25-3","IAB25-1","IAB25-7","IAB8-18","IAB26-3","IAB26-1","IAB8-5","IAB25-2","IAB11-4"],"tmax":3000,"app":{"paid":1,"keywords":"k1=v1","domain":"abc.com","name":"DrawHappyAngel","ver":"0.5.4","bundle":"com.newstory.DrawHappyAngel","cat":["IAB9-30"],"id":"{NETWORK_APP_ID}","publisher":{"name":"New Story Inc.","ext":{"installed_sdk":{"id":"MOLOCO_BIDDING","sdk_version":{"major":1,"minor":0,"micro":0},"adapter_version":{"major":1,"minor":0,"micro":0}}}},"ext":{"orientation":1}},"device":{"ifa":"497a10d6-c4dd-4e04-a986-c32b7180d462","ip":"38.158.207.171","carrier":"MYTEL","language":"en_US","hwv":"ruby","ppi":440,"pxratio":2.75,"devicetype":4,"mccmnc":"311-480","connectiontype":5,"js":1,"h":2400,"w":1080,"geo":{"city":"Queens","type":2,"ipservice":3,"lat":40.7429,"lon":-73.9392,"long":-73.9392,"country":"USA","region":"ny","dma":"501","metro":"501","zip":"11101","utcoffset":-480,"ext":{"org":"Myanmar Broadband Telecom Co.","isp":"Myanmar Broadband Telecom Co."}},"ext":{"atts":3},"osv":"13.0.0","ua":"Mozilla/5.0 (Linux; Android 13; 22101316C Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/120.0.6099.230 Mobile Safari/537.36","make":"xiaomi","model":"22101316c","os":"android"},"imp":[{"id":"1","displaymanagerver":"3.1.0","clickbrowser":1,"displaymanager":"PubMatic_OpenWrap_SDK","instl":0,"secure":0,"tagid":"{NETWORK_PLACEMENT_ID}","bidfloor":0.01,"bidfloorcur":"USD","exp":14400,"rwdd":0,"video":{"companionad":[{"pos":0,"format":[{"w":300,"h":250}],"vcm":1}],"protocols":[2,3,5,6,7,8,11,12,13,14],"h":250,"w":300,"linearity":1,"pos":0,"boxingallowed":1,"placement":2,"mimes":["video/3gpp2","video/quicktime","video/mp4","video/x-m4v","video/3gpp"],"companiontype":[1,2,3],"delivery":[2],"startdelay":0,"playbackend":1,"api":[7]},"ext":{"skadn":{"sourceapp":"406719683","versions":["2.0","2.1","2.2","3.0","4.0"],"skadnetids":["cstr6suwn9.skadnetwork","7ug5zh24hu.skadnetwork","uw77j35x4d.skadnetwork","c6k4g5qg8m.skadnetwork","hs6bdukanm.skadnetwork","yclnxrl5pm.skadnetwork","3sh42y64q3.skadnetwork","cj5566h2ga.skadnetwork","klf5c3l5u5.skadnetwork","8s468mfl3y.skadnetwork","2u9pt9hc89.skadnetwork","7rz58n8ntl.skadnetwork","ppxm28t8ap.skadnetwork","mtkv5xtk9e.skadnetwork","cg4yq2srnc.skadnetwork","wzmmz9fp6w.skadnetwork","k674qkevps.skadnetwork","v72qych5uu.skadnetwork","578prtvx9j.skadnetwork","3rd42ekr43.skadnetwork","g28c52eehv.skadnetwork","2fnua5tdw4.skadnetwork","9nlqeag3gk.skadnetwork","5lm9lj6jb7.skadnetwork","97r2b46745.skadnetwork","e5fvkxwrpn.skadnetwork","4pfyvq9l8r.skadnetwork","tl55sbb4fm.skadnetwork","t38b2kh725.skadnetwork","prcb7njmu6.skadnetwork","mlmmfzh3r3.skadnetwork","9t245vhmpl.skadnetwork","9rd848q2bz.skadnetwork","4fzdc2evr5.skadnetwork","4468km3ulz.skadnetwork","m8dbw4sv7c.skadnetwork","ejvt5qm6ak.skadnetwork","5lm9lj6jb7.skadnetwork","44jx6755aq.skadnetwork","6g9af3uyq4.skadnetwork","u679fj5vs4.skadnetwork","rx5hdcabgc.skadnetwork","275upjj5gd.skadnetwork","p78axxw29g.skadnetwork"],"productpage":1,"version":"2.0"}}}],"user":{"data":[{"id":"1","name":"Publisher Passed","segment":[{"signal":"{BIDDING_SIGNAL}"}]}],"ext":{"gdpr":0}},"regs":{"coppa":1,"ext":{"ccpa":0,"gdpr":1,"consent":"0","tcf_consent_string":"{TCF_STRING}","gpp":"gpp_string","gpp_sid":[7],"us_privacy":"uspConsentString"}},"source":{"ext":{"schain":{"ver":"1.0","complete":1,"nodes":[{"asi":"applovin.com","sid":"53bf468f18c5a0e2b7d4e3f748c677c1","rid":"494dbe15a3ce08c54f4e456363f35a022247f997","hp":1}]},"omidpn":"Pubmatic","omidpv":"3.1.0"}}}`),
+ },
+ {
+ name: "replace imp.video from signal",
+ args: args{
+ signal: `{"device":{"devicetype":4,"w":393,"h":852,"ifa":"F5BA1637-7156-4369-BA7E-3C45033D9F61","mccmnc":"311-480","js":1,"osv":"17.3.1","connectiontype":5,"os":"iOS","pxratio":3,"geo":{"lastfix":8,"lat":37.48773508935608,"utcoffset":-480,"lon":-122.22855027909678,"type":1},"language":"en","make":"Apple","ext":{"atts":3},"ua":"Mozilla/5.0 (iPhone; CPU iPhone OS 17_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148","model":"iPhone15,2","carrier":"Verizon"},"source":{"ext":{"omidpn":"Pubmatic","omidpv":"3.1.0"}},"id":"CE204A0E-31C3-4D7F-A1A0-D34AF5ED1A7F","app":{"id":"406719683","paid":1,"keywords":"k1=v1","domain":"abc.com","bundle":"406719683","storeurl":"https://apps.apple.com/us/app/gasbuddy-find-pay-for-gas/id406719683","name":"GasBuddy","publisher":{"id":"160361"},"ver":"700.89.22927"},"ext":{"wrapper":{"sumry_disable":1,"clientconfig":1,"profileid":3422}},"imp":[{"secure":1,"tagid":"Mobile_iPhone_List_Screen_Bottom","banner":{"pos":0,"format":[{"w":300,"h":250}],"api":[5,6,7]},"id":"98D9318E-5276-402F-BAA4-CDBD8A364957","ext":{"skadn":{"sourceapp":"406719683","versions":["2.0","2.1","2.2","3.0","4.0"],"skadnetids":["cstr6suwn9.skadnetwork","7ug5zh24hu.skadnetwork","uw77j35x4d.skadnetwork","c6k4g5qg8m.skadnetwork","hs6bdukanm.skadnetwork","yclnxrl5pm.skadnetwork","3sh42y64q3.skadnetwork","cj5566h2ga.skadnetwork","klf5c3l5u5.skadnetwork","8s468mfl3y.skadnetwork","2u9pt9hc89.skadnetwork","7rz58n8ntl.skadnetwork","ppxm28t8ap.skadnetwork","mtkv5xtk9e.skadnetwork","cg4yq2srnc.skadnetwork","wzmmz9fp6w.skadnetwork","k674qkevps.skadnetwork","v72qych5uu.skadnetwork","578prtvx9j.skadnetwork","3rd42ekr43.skadnetwork","g28c52eehv.skadnetwork","2fnua5tdw4.skadnetwork","9nlqeag3gk.skadnetwork","5lm9lj6jb7.skadnetwork","97r2b46745.skadnetwork","e5fvkxwrpn.skadnetwork","4pfyvq9l8r.skadnetwork","tl55sbb4fm.skadnetwork","t38b2kh725.skadnetwork","prcb7njmu6.skadnetwork","mlmmfzh3r3.skadnetwork","9t245vhmpl.skadnetwork","9rd848q2bz.skadnetwork","4fzdc2evr5.skadnetwork","4468km3ulz.skadnetwork","m8dbw4sv7c.skadnetwork","ejvt5qm6ak.skadnetwork","5lm9lj6jb7.skadnetwork","44jx6755aq.skadnetwork","6g9af3uyq4.skadnetwork","u679fj5vs4.skadnetwork","rx5hdcabgc.skadnetwork","275upjj5gd.skadnetwork","p78axxw29g.skadnetwork"],"productpage":1,"version":"2.0"}},"displaymanagerver":"3.1.0","clickbrowser":1,"video":{"companionad":[{"pos":0,"format":[{"w":300,"h":250}],"vcm":1}],"protocols":[2,3,5,6,7,8,11,12,13,14],"h":250,"w":300,"linearity":1,"pos":0,"boxingallowed":1,"placement":2,"mimes":["video/3gpp2","video/quicktime","video/mp4","video/x-m4v","video/3gpp"],"companiontype":[1,2,3],"delivery":[2],"startdelay":0,"playbackend":1,"api":[7]},"displaymanager":"PubMatic_OpenWrap_SDK","instl":0}],"at":1,"cur":["USD"],"regs":{"coppa":1,"ext":{"ccpa":0,"gdpr":1,"gpp":"gpp_string","gpp_sid":[7],"us_privacy":"uspConsentString","consent":"0"}}}`,
+ maxRequest: json.RawMessage(`{"id":"{BID_ID}","at":1,"bcat":["IAB26-4","IAB26-2","IAB25-6","IAB25-5","IAB25-4","IAB25-3","IAB25-1","IAB25-7","IAB8-18","IAB26-3","IAB26-1","IAB8-5","IAB25-2","IAB11-4"],"tmax":3000,"app":{"name":"DrawHappyAngel","ver":"0.5.4","bundle":"com.newstory.DrawHappyAngel","cat":["IAB9-30"],"id":"{NETWORK_APP_ID}","publisher":{"name":"New Story Inc.","ext":{"installed_sdk":{"id":"MOLOCO_BIDDING","sdk_version":{"major":1,"minor":0,"micro":0},"adapter_version":{"major":1,"minor":0,"micro":0}}}},"ext":{"orientation":1}},"device":{"ifa":"497a10d6-c4dd-4e04-a986-c32b7180d462","ip":"38.158.207.171","carrier":"MYTEL","language":"en_US","hwv":"ruby","ppi":440,"pxratio":2.75,"devicetype":4,"connectiontype":2,"js":1,"h":2400,"w":1080,"geo":{"type":2,"ipservice":3,"lat":40.7429,"lon":-73.9392,"long":-73.9392,"city":"Queens","country":"USA","region":"ny","dma":"501","metro":"501","zip":"11101","ext":{"org":"Myanmar Broadband Telecom Co.","isp":"Myanmar Broadband Telecom Co."}},"ext":{},"osv":"13.0.0","ua":"Mozilla/5.0 (Linux; Android 13; 22101316C Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/120.0.6099.230 Mobile Safari/537.36","make":"xiaomi","model":"22101316c","os":"android"},"imp":[{"id":"1","displaymanager":"applovin_mediation","displaymanagerver":"11.8.2","instl":1,"secure":0,"tagid":"{NETWORK_PLACEMENT_ID}","exp":14400,"banner":{"id":"1","w":320,"h":480,"btype":[],"battr":[1,2,5,8,9,14,17],"pos":7,"format":[{"w":320,"h":480}]},"video":{"w":320,"h":480,"battr":[1,2,5,8,9,14,17],"mimes":["video/mp4","video/3gpp","video/3gpp2","video/x-m4v"],"placement":5,"pos":7,"minduration":5,"maxduration":60,"skipafter":5,"skipmin":0,"startdelay":0,"playbackmethod":[1],"linearity":1},"rwdd":0}],"user":{"data":[{"id":"1","name":"Publisher Passed","segment":[{"signal":"{BIDDING_SIGNAL}"}]}],"ext":{"gdpr":0}},"regs":{"ext":{"ccpa":0,"gdpr":1,"consent":"0","tcf_consent_string":"{TCF_STRING}"}},"source":{"ext":{"schain":{"ver":"1.0","complete":1,"nodes":[{"asi":"applovin.com","sid":"53bf468f18c5a0e2b7d4e3f748c677c1","rid":"494dbe15a3ce08c54f4e456363f35a022247f997","hp":1}]}}}}`),
+ },
+ wantMaxRequest: json.RawMessage(`{"id":"{BID_ID}","at":1,"bcat":["IAB26-4","IAB26-2","IAB25-6","IAB25-5","IAB25-4","IAB25-3","IAB25-1","IAB25-7","IAB8-18","IAB26-3","IAB26-1","IAB8-5","IAB25-2","IAB11-4"],"tmax":3000,"app":{"paid":1,"keywords":"k1=v1","domain":"abc.com","name":"DrawHappyAngel","ver":"0.5.4","bundle":"com.newstory.DrawHappyAngel","cat":["IAB9-30"],"id":"{NETWORK_APP_ID}","publisher":{"name":"New Story Inc.","ext":{"installed_sdk":{"id":"MOLOCO_BIDDING","sdk_version":{"major":1,"minor":0,"micro":0},"adapter_version":{"major":1,"minor":0,"micro":0}}}},"ext":{"orientation":1}},"device":{"ifa":"497a10d6-c4dd-4e04-a986-c32b7180d462","ip":"38.158.207.171","carrier":"MYTEL","language":"en_US","hwv":"ruby","ppi":440,"pxratio":2.75,"devicetype":4,"mccmnc":"311-480","connectiontype":5,"js":1,"h":2400,"w":1080,"geo":{"city":"Queens","type":2,"ipservice":3,"lat":40.7429,"lon":-73.9392,"long":-73.9392,"country":"USA","region":"ny","dma":"501","metro":"501","zip":"11101","utcoffset":-480,"ext":{"org":"Myanmar Broadband Telecom Co.","isp":"Myanmar Broadband Telecom Co."}},"ext":{"atts":3},"osv":"13.0.0","ua":"Mozilla/5.0 (Linux; Android 13; 22101316C Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/120.0.6099.230 Mobile Safari/537.36","make":"xiaomi","model":"22101316c","os":"android"},"imp":[{"id":"1","displaymanagerver":"3.1.0","clickbrowser":1,"displaymanager":"PubMatic_OpenWrap_SDK","instl":1,"secure":0,"tagid":"{NETWORK_PLACEMENT_ID}","exp":14400,"banner":{"id":"1","w":320,"h":480,"btype":[],"api":[5,6,7],"battr":[1,2,5,8,9,14,17],"pos":7,"format":[{"w":320,"h":480}]},"video":{"companionad":[{"pos":0,"format":[{"w":300,"h":250}],"vcm":1}],"protocols":[2,3,5,6,7,8,11,12,13,14],"h":250,"w":300,"linearity":1,"pos":0,"boxingallowed":1,"placement":2,"mimes":["video/3gpp2","video/quicktime","video/mp4","video/x-m4v","video/3gpp"],"companiontype":[1,2,3],"delivery":[2],"startdelay":0,"playbackend":1,"api":[7]},"rwdd":0,"ext":{"skadn":{"sourceapp":"406719683","versions":["2.0","2.1","2.2","3.0","4.0"],"skadnetids":["cstr6suwn9.skadnetwork","7ug5zh24hu.skadnetwork","uw77j35x4d.skadnetwork","c6k4g5qg8m.skadnetwork","hs6bdukanm.skadnetwork","yclnxrl5pm.skadnetwork","3sh42y64q3.skadnetwork","cj5566h2ga.skadnetwork","klf5c3l5u5.skadnetwork","8s468mfl3y.skadnetwork","2u9pt9hc89.skadnetwork","7rz58n8ntl.skadnetwork","ppxm28t8ap.skadnetwork","mtkv5xtk9e.skadnetwork","cg4yq2srnc.skadnetwork","wzmmz9fp6w.skadnetwork","k674qkevps.skadnetwork","v72qych5uu.skadnetwork","578prtvx9j.skadnetwork","3rd42ekr43.skadnetwork","g28c52eehv.skadnetwork","2fnua5tdw4.skadnetwork","9nlqeag3gk.skadnetwork","5lm9lj6jb7.skadnetwork","97r2b46745.skadnetwork","e5fvkxwrpn.skadnetwork","4pfyvq9l8r.skadnetwork","tl55sbb4fm.skadnetwork","t38b2kh725.skadnetwork","prcb7njmu6.skadnetwork","mlmmfzh3r3.skadnetwork","9t245vhmpl.skadnetwork","9rd848q2bz.skadnetwork","4fzdc2evr5.skadnetwork","4468km3ulz.skadnetwork","m8dbw4sv7c.skadnetwork","ejvt5qm6ak.skadnetwork","5lm9lj6jb7.skadnetwork","44jx6755aq.skadnetwork","6g9af3uyq4.skadnetwork","u679fj5vs4.skadnetwork","rx5hdcabgc.skadnetwork","275upjj5gd.skadnetwork","p78axxw29g.skadnetwork"],"productpage":1,"version":"2.0"}}}],"user":{"data":[{"id":"1","name":"Publisher Passed","segment":[{"signal":"{BIDDING_SIGNAL}"}]}],"ext":{"gdpr":0}},"regs":{"coppa":1,"ext":{"ccpa":0,"gdpr":1,"consent":"0","tcf_consent_string":"{TCF_STRING}","gpp":"gpp_string","gpp_sid":[7],"us_privacy":"uspConsentString"}},"source":{"ext":{"schain":{"ver":"1.0","complete":1,"nodes":[{"asi":"applovin.com","sid":"53bf468f18c5a0e2b7d4e3f748c677c1","rid":"494dbe15a3ce08c54f4e456363f35a022247f997","hp":1}]},"omidpn":"Pubmatic","omidpv":"3.1.0"}}}`),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ var maxRequest openrtb2.BidRequest
+ if err := json.Unmarshal(tt.args.maxRequest, &maxRequest); err != nil {
+ t.Errorf("Unmarshal Faild for Incoming MaxRequest, Error: %s", err)
+ }
+
+ signalData := &openrtb2.BidRequest{}
+ if err := json.Unmarshal([]byte(tt.args.signal), &signalData); err != nil {
+ t.Errorf("Unmarshal Faild for Incoming MaxRequest, Error: %s", err)
+ }
+
+ var expectedMaxRequest openrtb2.BidRequest
+ addSignalDataInRequest(signalData, &maxRequest)
+ if err := json.Unmarshal(tt.wantMaxRequest, &expectedMaxRequest); err != nil {
+ t.Errorf("Unmarshal Faild for Expected MaxRequest, Error: %s", err)
+ }
+ assert.Equal(t, expectedMaxRequest, maxRequest, tt.name)
+ })
+ }
+}
+
+func TestGetSignalData(t *testing.T) {
+ type args struct {
+ requestBody []byte
+ }
+ tests := []struct {
+ name string
+ args args
+ want *openrtb2.BidRequest
+ }{
+ {
+ name: "incorrect body",
+ args: args{
+ requestBody: []byte(`{"id":"123","user":Passed","segment":[{"signal":{BIDDING_SIGNA}]}],"ext":{"gdpr":0}}}`),
+ },
+ want: nil,
+ },
+ {
+ name: "signal parsing fail",
+ args: args{
+ requestBody: []byte(`{"id":"123","user":{"data":[{"id":"1","name":"Publisher Passed","segment":[{"signal":"{BIDDING_SIGNA}"]}],"ext":{"gdpr":0}}}`),
+ },
+ want: nil,
+ },
+ {
+ name: "single user.data with signal with incorrect signal",
+ args: args{
+ requestBody: []byte(`{"id":"123","user":{"data":[{"id":"1","name":"Publisher Passed","segment":[{"signal":{BIDDING_SIGNA}]}],"ext":{"gdpr":0}}}`),
+ },
+ want: nil,
+ },
+ {
+ name: "single user.data with signal",
+ args: args{
+ requestBody: []byte(`{"id":"123","user":{"data":[{"id":"1","name":"Publisher Passed","segment":[{"signal":"{\"device\":{\"devicetype\":4,\"w\":393,\"h\":852}}"}]}],"ext":{"gdpr":0}}}`),
+ },
+ want: &openrtb2.BidRequest{
+ Device: &openrtb2.Device{
+ DeviceType: 4,
+ W: 393,
+ H: 852,
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := getSignalData(tt.args.requestBody)
+ assert.Equal(t, tt.want, got, tt.name)
+ })
+ }
+}
+
+func TestUpdateMaxAppLovinRequest(t *testing.T) {
+ type args struct {
+ requestBody []byte
+ }
+ tests := []struct {
+ name string
+ args args
+ want []byte
+ }{
+ {
+ name: "signal not present",
+ args: args{
+ requestBody: []byte(``),
+ },
+ want: []byte(``),
+ },
+ {
+ name: "invalid request body",
+ args: args{
+ requestBody: []byte(`{"id","user":{"data":[{"segment":[{"signal":"{}"}]}]}}`),
+ },
+ want: []byte(`{"id","user":{"data":[{"segment":[{"signal":"{}"}]}]}}`),
+ },
+ {
+ name: "update maxrequest body from signal",
+ args: args{
+ requestBody: []byte(`{"id":"test-case-1","at":1,"bcat":["IAB26-4","IAB26-2","IAB25-6","IAB25-5","IAB25-4","IAB25-3","IAB25-1","IAB25-7","IAB8-18","IAB26-3","IAB26-1","IAB8-5","IAB25-2","IAB11-4"],"tmax":1000,"app":{"publisher":{"name":"New Story Inc.","id":"5890","ext":{"installed_sdk":{"id":"MOLOCO_BIDDING","sdk_version":{"major":1,"minor":0,"micro":0},"adapter_version":{"major":1,"minor":0,"micro":0}}}},"paid":0,"name":"DrawHappyAngel","ver":"0.5.4","bundle":"com.newstory.DrawHappyAngel","cat":["IAB9-30"],"id":"1234567","ext":{"orientation":1}},"device":{"ifa":"497a10d6-c4dd-4e04-a986-c32b7180d462","ip":"38.158.207.171","carrier":"MYTEL","language":"en_US","hwv":"ruby","ppi":440,"pxratio":2.75,"devicetype":4,"connectiontype":2,"js":1,"h":2400,"w":1080,"geo":{"type":2,"ipservice":3,"lat":40.7429,"lon":-73.9392,"long":-73.9392,"city":"Queens","country":"USA","region":"ny","dma":"501","metro":"501","zip":"11101","ext":{"org":"Myanmar Broadband Telecom Co.","isp":"Myanmar Broadband Telecom Co."}},"ext":{},"osv":"13.0.0","ua":"Mozilla/5.0 (Linux; Android 13; 22101316C Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/120.0.6099.230 Mobile Safari/537.36","make":"xiaomi","model":"22101316c","os":"android"},"imp":[{"id":"1","displaymanager":"applovin_mediation","displaymanagerver":"11.8.2","instl":0,"secure":0,"tagid":"/43743431/DMDemo","bidfloor":0.01,"bidfloorcur":"USD","exp":14400,"banner":{"format":[{"w":728,"h":90},{"w":300,"h":250}],"w":700,"h":900},"video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"rwdd":0}],"user":{"data":[{"id":"1","name":"Publisher Passed","segment":[{"signal":"{\"id\":\"95d6643c-3da6-40a2-b9ca-12279393ffbf\",\"at\":1,\"tmax\":500,\"cur\":[\"USD\"],\"imp\":[{\"id\":\"imp176227948\",\"clickbrowser\":0,\"displaymanager\":\"PubMatic_OpenBid_SDK\",\"displaymanagerver\":\"1.4.0\",\"tagid\":\"\/43743431\/DMDemo\",\"secure\":0,\"banner\":{\"pos\":7,\"format\":[{\"w\":300,\"h\":250}],\"api\":[5,6,7]},\"instl\":1}],\"app\":{\"paid\":4,\"name\":\"OpenWrapperSample\",\"bundle\":\"com.pubmatic.openbid.app\",\"storeurl\":\"https:\/\/itunes.apple.com\/us\/app\/pubmatic-sdk-app\/id1175273098?appnexus_banner_fixedbid=1&fixedbid=1\",\"ver\":\"1.0\",\"publisher\":{\"id\":\"5890\"}},\"device\":{\"geo\":{\"type\":1,\"lat\":37.421998333333335,\"lon\":-122.08400000000002},\"pxratio\":2.625,\"mccmnc\":\"310-260\",\"lmt\":0,\"ifa\":\"07c387f2-e030-428f-8336-42f682150759\",\"connectiontype\":5,\"carrier\":\"Android\",\"js\":1,\"ua\":\"Mozilla\/5.0(Linux;Android9;AndroidSDKbuiltforx86Build\/PSR1.180720.075;wv)AppleWebKit\/537.36(KHTML,likeGecko)Version\/4.0Chrome\/69.0.3497.100MobileSafari\/537.36\",\"make\":\"Google\",\"model\":\"AndroidSDKbuiltforx86\",\"os\":\"Android\",\"osv\":\"9\",\"h\":1794,\"w\":1080,\"language\":\"en-US\",\"devicetype\":4,\"ext\":{\"atts\":3}},\"source\":{\"ext\":{\"omidpn\":\"PubMatic\",\"omidpv\":\"1.2.11-Pubmatic\"}},\"user\":{\"data\":[{\"id\":\"1234\"}]},\"ext\":{\"wrapper\":{\"ssauction\":1,\"sumry_disable\":0,\"profileid\":58135,\"versionid\":1,\"clientconfig\":1}}}"}]}],"ext":{"gdpr":0}},"regs":{"coppa":0,"ext":{"gdpr":0}},"source":{"ext":{"schain":{"ver":"1.0","complete":1,"nodes":[{"asi":"applovin.com","sid":"53bf468f18c5a0e2b7d4e3f748c677c1","rid":"494dbe15a3ce08c54f4e456363f35a022247f997","hp":1}]}}},"ext":{"prebid":{"bidderparams":{"pubmatic":{"wrapper":{"profileid":12929,"versionid":1,"clientconfig":1}}}}}}`),
+ },
+ want: []byte(`{"id":"test-case-1","imp":[{"id":"1","banner":{"format":[{"w":728,"h":90},{"w":300,"h":250}],"w":700,"h":900,"api":[5,6,7]},"video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"displaymanager":"PubMatic_OpenBid_SDK","displaymanagerver":"1.4.0","tagid":"/43743431/DMDemo","bidfloor":0.01,"bidfloorcur":"USD","clickbrowser":0,"secure":0,"exp":14400}],"app":{"id":"1234567","name":"DrawHappyAngel","bundle":"com.newstory.DrawHappyAngel","cat":["IAB9-30"],"ver":"0.5.4","paid":4,"publisher":{"id":"5890","name":"New Story Inc.","ext":{"installed_sdk":{"id":"MOLOCO_BIDDING","sdk_version":{"major":1,"minor":0,"micro":0},"adapter_version":{"major":1,"minor":0,"micro":0}}}},"ext":{"orientation":1}},"device":{"geo":{"lat":40.7429,"lon":-73.9392,"type":2,"ipservice":3,"country":"USA","region":"ny","metro":"501","city":"Queens","zip":"11101","ext":{"org":"Myanmar Broadband Telecom Co.","isp":"Myanmar Broadband Telecom Co."}},"ua":"Mozilla/5.0 (Linux; Android 13; 22101316C Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/120.0.6099.230 Mobile Safari/537.36","ip":"38.158.207.171","devicetype":4,"make":"xiaomi","model":"22101316c","os":"android","osv":"13.0.0","hwv":"ruby","h":2400,"w":1080,"ppi":440,"pxratio":2.75,"js":1,"language":"en_US","carrier":"MYTEL","mccmnc":"310-260","connectiontype":5,"ifa":"497a10d6-c4dd-4e04-a986-c32b7180d462","ext":{"atts":3}},"user":{"data":[{"id":"1234"}],"ext":{"gdpr":0}},"at":1,"tmax":1000,"bcat":["IAB26-4","IAB26-2","IAB25-6","IAB25-5","IAB25-4","IAB25-3","IAB25-1","IAB25-7","IAB8-18","IAB26-3","IAB26-1","IAB8-5","IAB25-2","IAB11-4"],"source":{"ext":{"schain":{"ver":"1.0","complete":1,"nodes":[{"asi":"applovin.com","sid":"53bf468f18c5a0e2b7d4e3f748c677c1","rid":"494dbe15a3ce08c54f4e456363f35a022247f997","hp":1}]},"omidpn":"PubMatic","omidpv":"1.2.11-Pubmatic"}},"regs":{"ext":{"gdpr":0}},"ext":{"prebid":{"bidderparams":{"pubmatic":{"wrapper":{"profileid":12929,"versionid":1,"clientconfig":1}}}}}}`),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := updateAppLovinMaxRequest(tt.args.requestBody)
+ assert.Equal(t, tt.want, got, tt.name)
+ })
+ }
+}
+
+func TestUpdateRequestWrapper(t *testing.T) {
+ type args struct {
+ signalExt json.RawMessage
+ maxRequest *openrtb2.BidRequest
+ }
+ tests := []struct {
+ name string
+ args args
+ want json.RawMessage
+ }{
+ {
+ name: "clientconfig not present",
+ args: args{
+ signalExt: json.RawMessage(`{"ssauction":1}`),
+ maxRequest: &openrtb2.BidRequest{Ext: json.RawMessage(``)},
+ },
+ want: json.RawMessage(``),
+ },
+ {
+ name: "clientconfig is 0",
+ args: args{
+ signalExt: json.RawMessage(`{"wrapper":{"ssauction":1,"clientconfig":0}}`),
+ maxRequest: &openrtb2.BidRequest{Ext: json.RawMessage(``)},
+ },
+ want: json.RawMessage(``),
+ },
+ {
+ name: "clientconfig is 1",
+ args: args{
+ signalExt: json.RawMessage(`{"wrapper":{"ssauction":1,"clientconfig":1}}`),
+ maxRequest: &openrtb2.BidRequest{Ext: json.RawMessage(`{}`)},
+ },
+ want: json.RawMessage(`{"prebid":{"bidderparams":{"pubmatic":{"wrapper":{"clientconfig":1}}}}}`),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ updateRequestWrapper(tt.args.signalExt, tt.args.maxRequest)
+ assert.Equal(t, tt.want, tt.args.maxRequest.Ext)
+ })
+ }
+}
+
+func TestUpdateMaxApplovinResponse(t *testing.T) {
+ type args struct {
+ rctx models.RequestCtx
+ bidResponse *openrtb2.BidResponse
+ }
+ tests := []struct {
+ name string
+ args args
+ want models.AppLovinMax
+ }{
+ {
+ name: "bidresponse contains NBR and debug is disabled",
+ args: args{
+ rctx: models.RequestCtx{
+ Debug: false,
+ },
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ NBR: ptrutil.ToPtr(nbr.InvalidPlatform),
+ },
+ },
+ want: models.AppLovinMax{
+ Reject: true,
+ },
+ },
+ {
+ name: "bidresponse contains NBR and debug is enabled",
+ args: args{
+ rctx: models.RequestCtx{
+ Debug: true,
+ },
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ NBR: ptrutil.ToPtr(nbr.InvalidPlatform),
+ },
+ },
+ want: models.AppLovinMax{
+ Reject: false,
+ },
+ },
+ {
+ name: "bidresponse seatbid is empty",
+ args: args{
+ rctx: models.RequestCtx{
+ Debug: false,
+ },
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ SeatBid: []openrtb2.SeatBid{},
+ },
+ },
+ want: models.AppLovinMax{
+ Reject: true,
+ },
+ },
+ {
+ name: "bidresponse seatbid.bid is empty",
+ args: args{
+ rctx: models.RequestCtx{
+ Debug: false,
+ },
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{},
+ },
+ },
+ },
+ },
+ want: models.AppLovinMax{
+ Reject: true,
+ },
+ },
+ {
+ name: "No NBR and valid bidresponse",
+ args: args{
+ rctx: models.RequestCtx{
+ Debug: false,
+ },
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "456",
+ ImpID: "789",
+ Price: 1.0,
+ AdM: "",
+ BURL: "http://example.com",
+ Ext: json.RawMessage(`{"key":"value"}`),
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ },
+ },
+ want: models.AppLovinMax{
+ Reject: false,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := updateAppLovinMaxResponse(tt.args.rctx, tt.args.bidResponse)
+ assert.Equal(t, tt.want, got, tt.name)
+ })
+ }
+}
+
+func TestApplyMaxAppLovinResponse(t *testing.T) {
+ type args struct {
+ rctx models.RequestCtx
+ bidResponse *openrtb2.BidResponse
+ }
+ tests := []struct {
+ name string
+ args args
+ want *openrtb2.BidResponse
+ }{
+ {
+ name: "AppLovinMax.Reject is true",
+ args: args{
+ rctx: models.RequestCtx{
+ Debug: true,
+ AppLovinMax: models.AppLovinMax{
+ Reject: true,
+ },
+ },
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "456",
+ ImpID: "789",
+ },
+ },
+ },
+ },
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "123",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "456",
+ ImpID: "789",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "bidresponse contains NBR and AppLovinMax.Reject is false",
+ args: args{
+ rctx: models.RequestCtx{
+ Debug: false,
+ AppLovinMax: models.AppLovinMax{
+ Reject: false,
+ },
+ },
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ NBR: ptrutil.ToPtr(nbr.InvalidPlatform),
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "123",
+ NBR: ptrutil.ToPtr(nbr.InvalidPlatform),
+ },
+ },
+ {
+ name: "failed to marshal bidresponse",
+ args: args{
+ rctx: models.RequestCtx{
+ Debug: true,
+ AppLovinMax: models.AppLovinMax{
+ Reject: false,
+ },
+ },
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "123",
+ ImpID: "789",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{`),
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "123",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "123",
+ ImpID: "789",
+ },
+ },
+ },
+ },
+ Ext: json.RawMessage(`{`),
+ },
+ },
+ {
+ name: "valid bidresponse",
+ args: args{
+ rctx: models.RequestCtx{
+ AppLovinMax: models.AppLovinMax{
+ Reject: false,
+ },
+ },
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "456",
+ ImpID: "789",
+ Price: 1.0,
+ AdM: "",
+ BURL: "http://example.com",
+ Ext: json.RawMessage(`{"key":"value"}`),
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ Ext: json.RawMessage(`{"key":"value"}`),
+ },
+ },
+ want: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "456",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "456",
+ ImpID: "789",
+ Price: 1.0,
+ BURL: "http://example.com",
+ Ext: json.RawMessage(`{"signaldata":"{\"id\":\"123\",\"seatbid\":[{\"bid\":[{\"id\":\"456\",\"impid\":\"789\",\"price\":1,\"burl\":\"http://example.com\",\"adm\":\"\\u003cimg src=\\\"http://example.com\\\"\\u003e\\u003c/img\\u003e\",\"ext\":{\"key\":\"value\"}}],\"seat\":\"pubmatic\"}],\"cur\":\"USD\",\"ext\":{\"key\":\"value\"}}"}`),
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := applyAppLovinMaxResponse(tt.args.rctx, tt.args.bidResponse)
+ assert.Equal(t, tt.want, got, tt.name)
+ })
+ }
+}
diff --git a/modules/pubmatic/openwrap/auctionresponsehook.go b/modules/pubmatic/openwrap/auctionresponsehook.go
index 9a5f97e112f..7c546a11b9b 100644
--- a/modules/pubmatic/openwrap/auctionresponsehook.go
+++ b/modules/pubmatic/openwrap/auctionresponsehook.go
@@ -280,6 +280,8 @@ func (m OpenWrap) handleAuctionResponseHook(
result.DebugMessages = append(result.DebugMessages, string(rCtxBytes))
}
+ rctx.AppLovinMax = updateAppLovinMaxResponse(rctx, payload.BidResponse)
+
if rctx.Endpoint == models.EndpointWebS2S {
result.ChangeSet.AddMutation(func(ap hookstage.AuctionResponsePayload) (hookstage.AuctionResponsePayload, error) {
rctx := moduleCtx.ModuleContext["rctx"].(models.RequestCtx)
@@ -315,6 +317,10 @@ func (m OpenWrap) handleAuctionResponseHook(
ap.BidResponse.Ext = responseExtjson
resetBidIdtoOriginal(ap.BidResponse)
+
+ if rctx.Endpoint == models.EndpointAppLovinMax {
+ ap.BidResponse = applyAppLovinMaxResponse(rctx, ap.BidResponse)
+ }
return ap, err
}, hookstage.MutationUpdate, "response-body-with-sshb-format")
diff --git a/modules/pubmatic/openwrap/auctionresponsehook_test.go b/modules/pubmatic/openwrap/auctionresponsehook_test.go
index ac61e5d9b48..5f75bf056b8 100644
--- a/modules/pubmatic/openwrap/auctionresponsehook_test.go
+++ b/modules/pubmatic/openwrap/auctionresponsehook_test.go
@@ -1935,3 +1935,126 @@ func TestOpenWrap_handleAuctionResponseHook(t *testing.T) {
})
}
}
+
+func TestAuctionResponseHookForApplovinMax(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ mockCache := mock_cache.NewMockCache(ctrl)
+ mockFeature := mock_feature.NewMockFeature(ctrl)
+ defer ctrl.Finish()
+
+ type args struct {
+ ctx context.Context
+ moduleCtx hookstage.ModuleInvocationContext
+ payload hookstage.AuctionResponsePayload
+ }
+
+ type want struct {
+ bidResponse *openrtb2.BidResponse
+ err error
+ }
+
+ tests := []struct {
+ name string
+ args args
+ want want
+ getMetricsEngine func() *mock_metrics.MockMetricsEngine
+ }{
+ {
+ name: "update_the_bid_response_in_applovin_max_format",
+ args: args{
+ ctx: nil,
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": models.RequestCtx{
+ Platform: models.PLATFORM_VIDEO,
+ Endpoint: models.EndpointAppLovinMax,
+ ImpBidCtx: map[string]models.ImpCtx{
+ "789": {
+ ImpID: "789",
+ },
+ },
+ BidderResponseTimeMillis: map[string]int{},
+ Trackers: map[string]models.OWTracker{
+ "456": {
+ TrackerURL: `Tracker URL`,
+ ErrorURL: `Error URL`,
+ Price: 1.2,
+ },
+ },
+ },
+ },
+ },
+ payload: hookstage.AuctionResponsePayload{
+ BidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "456",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "456",
+ ImpID: "789",
+ Price: 1.0,
+ AdM: `Acudeo CompatibleVAST 2.0 Instream Test 1VAST 2.0 Instream Test 1https://dsptracker.com/{PSPM}00:00:04https://www.sample.com`,
+ BURL: "http://example.com",
+ Ext: json.RawMessage(`{"key":"value"}`),
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ Ext: json.RawMessage(`{"key":"value"}`),
+ },
+ },
+ },
+ want: want{
+ bidResponse: &openrtb2.BidResponse{
+ ID: "123",
+ BidID: "456",
+ Cur: "USD",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "456",
+ ImpID: "789",
+ Price: 1.0,
+ BURL: `https:?adv=&af=video&aps=0&au=&bc=pubmatic&bidid=456&di=-1&eg=1&en=1&ft=0&iid=&kgpv=&orig=&origbidid=456&pdvid=0&pid=0&plt=0&pn=pubmatic&psz=0x0v&pubid=0&purl=&sl=1&slot=&ss=1&tgid=0&tst=0&owsspburl=http://example.com`,
+ Ext: json.RawMessage(`{"signaldata":"{\"id\":\"123\",\"seatbid\":[{\"bid\":[{\"id\":\"456\",\"impid\":\"789\",\"price\":1,\"burl\":\"https:?adv=\\u0026af=video\\u0026aps=0\\u0026au=\\u0026bc=pubmatic\\u0026bidid=456\\u0026di=-1\\u0026eg=1\\u0026en=1\\u0026ft=0\\u0026iid=\\u0026kgpv=\\u0026orig=\\u0026origbidid=456\\u0026pdvid=0\\u0026pid=0\\u0026plt=0\\u0026pn=pubmatic\\u0026psz=0x0v\\u0026pubid=0\\u0026purl=\\u0026sl=1\\u0026slot=\\u0026ss=1\\u0026tgid=0\\u0026tst=0\\u0026owsspburl=http://example.com\",\"adm\":\"\\u003cVAST version=\\\"3.0\\\"\\u003e\\u003cAd id=\\\"601364\\\"\\u003e\\u003cInLine\\u003e\\u003cAdSystem\\u003e\\u003c![CDATA[Acudeo Compatible]]\\u003e\\u003c/AdSystem\\u003e\\u003cAdTitle\\u003e\\u003c![CDATA[VAST 2.0 Instream Test 1]]\\u003e\\u003c/AdTitle\\u003e\\u003cDescription\\u003e\\u003c![CDATA[VAST 2.0 Instream Test 1]]\\u003e\\u003c/Description\\u003e\\u003cImpression\\u003e\\u003c![CDATA[http://172.16.4.213/AdServer/AdDisplayTrackerServlet?operId=1\\u0026pubId=5890\\u0026siteId=47163\\u0026adId=1405268\\u0026adType=13\\u0026adServerId=243\\u0026kefact=70.000000\\u0026kaxefact=70.000000\\u0026kadNetFrequecy=0\\u0026kadwidth=0\\u0026kadheight=0\\u0026kadsizeid=97\\u0026kltstamp=1529929473\\u0026indirectAdId=0\\u0026adServerOptimizerId=2\\u0026ranreq=0.1\\u0026kpbmtpfact=100.000000\\u0026dcId=1\\u0026tldId=0\\u0026passback=0\\u0026svr=MADS1107\\u0026ekefact=Ad8wW91TCwCmdG0jlfjXn7Tyzh20hnTVx-m5DoNSep-RXGDr\\u0026ekaxefact=Ad8wWwRUCwAGir4Zzl1eF0bKiC-qrCV0D0yp_eE7YizB_BQk\\u0026ekpbmtpfact=Ad8wWxRUCwD7qgzwwPE2LnS5-Ou19uO5amJl1YT6-XVFvQ41\\u0026imprId=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F\\u0026oid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F\\u0026crID=creative-1_1_2\\u0026ucrid=160175026529250297\\u0026campaignId=17050\\u0026creativeId=0\\u0026pctr=0.000000\\u0026wDSPByrId=511\\u0026wDspId=6\\u0026wbId=0\\u0026wrId=0\\u0026wAdvID=3170\\u0026isRTB=1\\u0026rtbId=EBCA079F-8D7C-45B8-B733-92951F670AA1\\u0026pmZoneId=zone1\\u0026pageURL=www.yahoo.com\\u0026lpu=ae.com]]\\u003e\\u003c/Impression\\u003e\\u003cImpression\\u003e\\u003c![CDATA[https://dsptracker.com/{PSPM}]]\\u003e\\u003c/Impression\\u003e\\u003cError\\u003e\\u003c![CDATA[http://172.16.4.213/track?operId=7\\u0026p=5890\\u0026s=47163\\u0026a=1405268\\u0026wa=243\\u0026ts=1529929473\\u0026wc=17050\\u0026crId=creative-1_1_2\\u0026ucrid=160175026529250297\\u0026impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F\\u0026advertiser_id=3170\\u0026ecpm=70.000000\\u0026er=[ERRORCODE]]]\\u003e\\u003c/Error\\u003e\\u003cError\\u003e\\u003c![CDATA[https://Errortrack.com?p=1234\\u0026er=[ERRORCODE]]]\\u003e\\u003c/Error\\u003e\\u003cCreatives\\u003e\\u003cCreative AdID=\\\"601364\\\"\\u003e\\u003cLinear skipoffset=\\\"20%\\\"\\u003e\\u003cDuration\\u003e\\u003c![CDATA[00:00:04]]\\u003e\\u003c/Duration\\u003e\\u003cVideoClicks\\u003e\\u003cClickTracking\\u003e\\u003c![CDATA[http://172.16.4.213/track?operId=7\\u0026p=5890\\u0026s=47163\\u0026a=1405268\\u0026wa=243\\u0026ts=1529929473\\u0026wc=17050\\u0026crId=creative-1_1_2\\u0026ucrid=160175026529250297\\u0026impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F\\u0026advertiser_id=3170\\u0026ecpm=70.000000\\u0026e=99]]\\u003e\\u003c/ClickTracking\\u003e\\u003cClickThrough\\u003e\\u003c![CDATA[https://www.sample.com]]\\u003e\\u003c/ClickThrough\\u003e\\u003c/VideoClicks\\u003e\\u003cMediaFiles\\u003e\\u003cMediaFile delivery=\\\"progressive\\\" type=\\\"video/mp4\\\" bitrate=\\\"500\\\" width=\\\"400\\\" height=\\\"300\\\" scalable=\\\"true\\\" maintainAspectRatio=\\\"true\\\"\\u003e\\u003c![CDATA[https://stagingnyc.pubmatic.com:8443/video/Shashank/mediaFileHost/media/mp4-sample-1.mp4]]\\u003e\\u003c/MediaFile\\u003e\\u003cMediaFile delivery=\\\"progressive\\\" type=\\\"video/mp4\\\" bitrate=\\\"500\\\" width=\\\"400\\\" height=\\\"300\\\" scalable=\\\"true\\\" maintainAspectRatio=\\\"true\\\"\\u003e\\u003c![CDATA[https://stagingnyc.pubmatic.com:8443/video/Shashank/mediaFileHost/media/mp4-sample-2.mp4]]\\u003e\\u003c/MediaFile\\u003e\\u003c/MediaFiles\\u003e\\u003c/Linear\\u003e\\u003c/Creative\\u003e\\u003c/Creatives\\u003e\\u003cPricing model=\\\"CPM\\\" currency=\\\"USD\\\"\\u003e\\u003c![CDATA[1]]\\u003e\\u003c/Pricing\\u003e\\u003c/InLine\\u003e\\u003c/Ad\\u003e\\u003c/VAST\\u003e\",\"ext\":{\"prebid\":{},\"crtype\":\"video\",\"netecpm\":1}}],\"seat\":\"pubmatic\"}],\"bidid\":\"456\",\"cur\":\"USD\",\"ext\":{\"matchedimpression\":{}}}"}`),
+ },
+ },
+ },
+ },
+ },
+ err: nil,
+ },
+ getMetricsEngine: func() *mock_metrics.MockMetricsEngine {
+ mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
+ mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats(gomock.Any(), gomock.Any(), gomock.Any())
+ mockEngine.EXPECT().RecordPublisherResponseTimeStats(gomock.Any(), gomock.Any())
+ mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false)
+ mockEngine.EXPECT().RecordPartnerResponseTimeStats(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
+ return mockEngine
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ o := OpenWrap{
+ metricEngine: tt.getMetricsEngine(),
+ cache: mockCache,
+ pubFeatures: mockFeature,
+ }
+ 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.bidResponse, result.BidResponse, tt.name)
+ }
+ })
+ }
+}
diff --git a/modules/pubmatic/openwrap/beforevalidationhook_test.go b/modules/pubmatic/openwrap/beforevalidationhook_test.go
index d5ac47da6a1..e9506cac09b 100644
--- a/modules/pubmatic/openwrap/beforevalidationhook_test.go
+++ b/modules/pubmatic/openwrap/beforevalidationhook_test.go
@@ -2291,7 +2291,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -2337,7 +2337,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{}, nil)
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{}, nil)
//prometheus metrics
mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234")
mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.InvalidProfileConfiguration))
@@ -2370,7 +2370,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -2415,7 +2415,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -2461,7 +2461,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -2511,7 +2511,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -2557,7 +2557,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -2631,7 +2631,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -2721,7 +2721,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -2830,7 +2830,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PREBID_PARTNER_NAME: "appnexus",
models.BidderCode: "appnexus",
@@ -2918,7 +2918,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
"adunit@700x900": "1232433543534543",
},
}).Times(3)
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
1: {
models.PARTNER_ID: "1",
models.PREBID_PARTNER_NAME: "pubmatic2",
@@ -3033,7 +3033,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
"adunit@700x900": "1232433543534543",
},
})
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -3176,7 +3176,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) {
"adunit@700x900": "1232433543534543",
},
})
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -3452,7 +3452,7 @@ func TestVASTUnwrap_handleBeforeValidationHook(t *testing.T) {
"adunit@700x900": "1232433543534543",
},
})
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -3513,7 +3513,7 @@ func TestVASTUnwrap_handleBeforeValidationHook(t *testing.T) {
"adunit@700x900": "1232433543534543",
},
})
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -3579,7 +3579,7 @@ func TestVASTUnwrap_handleBeforeValidationHook(t *testing.T) {
"adunit@700x900": "1232433543534543",
},
})
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -3645,7 +3645,7 @@ func TestVASTUnwrap_handleBeforeValidationHook(t *testing.T) {
"adunit@700x900": "1232433543534543",
},
})
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -3707,7 +3707,7 @@ func TestVASTUnwrap_handleBeforeValidationHook(t *testing.T) {
"adunit@700x900": "1232433543534543",
},
})
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -3810,7 +3810,7 @@ func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -3863,7 +3863,7 @@ func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -3916,7 +3916,7 @@ func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -3970,7 +3970,7 @@ func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
@@ -4016,7 +4016,7 @@ func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) {
metricEngine: mockEngine,
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
2: {
models.PARTNER_ID: "2",
models.PREBID_PARTNER_NAME: "appnexus",
diff --git a/modules/pubmatic/openwrap/cache/cache.go b/modules/pubmatic/openwrap/cache/cache.go
index 1890ea483c0..3f328b14635 100644
--- a/modules/pubmatic/openwrap/cache/cache.go
+++ b/modules/pubmatic/openwrap/cache/cache.go
@@ -7,7 +7,7 @@ import (
)
type Cache interface {
- GetPartnerConfigMap(pubid, profileid, displayversion int, endpoint string) (map[int]map[string]string, error)
+ GetPartnerConfigMap(pubid, profileid, displayversion int) (map[int]map[string]string, error)
GetAdunitConfigFromCache(request *openrtb2.BidRequest, pubID int, profileID, displayVersion int) *adunitconfig.AdUnitConfig
GetMappingsFromCacheV25(rctx models.RequestCtx, partnerID int) map[string]models.SlotMapping
GetSlotToHashValueMapFromCacheV25(rctx models.RequestCtx, partnerID int) models.SlotMappingInfo
diff --git a/modules/pubmatic/openwrap/cache/gocache/partner_config.go b/modules/pubmatic/openwrap/cache/gocache/partner_config.go
index 51579f20958..64cf28b65e9 100644
--- a/modules/pubmatic/openwrap/cache/gocache/partner_config.go
+++ b/modules/pubmatic/openwrap/cache/gocache/partner_config.go
@@ -11,7 +11,7 @@ import (
)
// GetPartnerConfigMap returns partnerConfigMap using given parameters
-func (c *cache) GetPartnerConfigMap(pubID, profileID, displayVersion int, endpoint string) (map[int]map[string]string, error) {
+func (c *cache) GetPartnerConfigMap(pubID, profileID, displayVersion int) (map[int]map[string]string, error) {
dbAccessed := false
var err error
startTime := time.Now()
@@ -58,7 +58,7 @@ func (c *cache) GetPartnerConfigMap(pubID, profileID, displayVersion int, endpoi
}
if dbAccessed {
- c.metricEngine.RecordGetProfileDataTime(endpoint, strconv.Itoa(profileID), time.Since(startTime))
+ c.metricEngine.RecordGetProfileDataTime(time.Since(startTime))
}
return partnerConfigMap, err
}
@@ -75,25 +75,29 @@ func (c *cache) getActivePartnerConfigAndPopulateWrapperMappings(pubID, profileI
return fmt.Errorf("there are no active partners for pubId:%d, profileId:%d, displayVersion:%d", pubID, profileID, displayVersion)
}
- c.cache.Set(cacheKey, partnerConfigMap, getSeconds(c.cfg.CacheDefaultExpiry))
- if errWrapperSlotMapping := c.populateCacheWithWrapperSlotMappings(pubID, partnerConfigMap, profileID, displayVersion); errWrapperSlotMapping != nil {
- err = models.ErrorWrap(err, errWrapperSlotMapping)
+ err = c.populateCacheWithWrapperSlotMappings(pubID, partnerConfigMap, profileID, displayVersion)
+ if err != nil {
queryType := models.WrapperSlotMappingsQuery
if displayVersion == 0 {
queryType = models.WrapperLiveVersionSlotMappings
}
c.metricEngine.RecordDBQueryFailure(queryType, strconv.Itoa(pubID), strconv.Itoa(profileID))
+ return err
}
- if errAdunitConfig := c.populateCacheWithAdunitConfig(pubID, profileID, displayVersion); errAdunitConfig != nil {
+
+ err = c.populateCacheWithAdunitConfig(pubID, profileID, displayVersion)
+ if err != nil {
queryType := models.AdunitConfigQuery
if displayVersion == 0 {
queryType = models.AdunitConfigForLiveVersion
}
- if errors.Is(errAdunitConfig, adunitconfig.ErrAdUnitUnmarshal) {
+ if errors.Is(err, adunitconfig.ErrAdUnitUnmarshal) {
queryType = models.AdUnitFailUnmarshal
}
c.metricEngine.RecordDBQueryFailure(queryType, strconv.Itoa(pubID), strconv.Itoa(profileID))
- err = models.ErrorWrap(err, errAdunitConfig)
+ return err
}
+
+ c.cache.Set(cacheKey, partnerConfigMap, getSeconds(c.cfg.CacheDefaultExpiry))
return
}
diff --git a/modules/pubmatic/openwrap/cache/gocache/partner_config_test.go b/modules/pubmatic/openwrap/cache/gocache/partner_config_test.go
index 464d1ce5ad5..31783709235 100644
--- a/modules/pubmatic/openwrap/cache/gocache/partner_config_test.go
+++ b/modules/pubmatic/openwrap/cache/gocache/partner_config_test.go
@@ -1,6 +1,7 @@
package gocache
import (
+ "errors"
"fmt"
"sync"
"testing"
@@ -26,7 +27,6 @@ func Test_cache_GetPartnerConfigMap(t *testing.T) {
pubID int
profileID int
displayVersion int
- endpoint string
}
tests := []struct {
name string
@@ -49,7 +49,6 @@ func Test_cache_GetPartnerConfigMap(t *testing.T) {
pubID: testPubID,
profileID: testProfileID,
displayVersion: testVersionID,
- endpoint: models.EndpointV25,
},
setup: func(ctrl *gomock.Controller) (*mock_database.MockDatabase, *mock_metrics.MockMetricsEngine) {
mockDatabase := mock_database.NewMockDatabase(ctrl)
@@ -69,7 +68,7 @@ func Test_cache_GetPartnerConfigMap(t *testing.T) {
},
},
}, nil)
- mockEngine.EXPECT().RecordGetProfileDataTime(models.EndpointV25, "123", gomock.Any()).Return().Times(1)
+ mockEngine.EXPECT().RecordGetProfileDataTime(gomock.Any()).Return().Times(1)
return mockDatabase, mockEngine
},
wantErr: false,
@@ -98,7 +97,6 @@ func Test_cache_GetPartnerConfigMap(t *testing.T) {
pubID: testPubID,
profileID: testProfileID,
displayVersion: testVersionID,
- endpoint: models.EndpointV25,
},
setup: func(ctrl *gomock.Controller) (*mock_database.MockDatabase, *mock_metrics.MockMetricsEngine) {
mockDatabase := mock_database.NewMockDatabase(ctrl)
@@ -106,7 +104,7 @@ func Test_cache_GetPartnerConfigMap(t *testing.T) {
mockDatabase.EXPECT().GetActivePartnerConfigurations(testPubID, testProfileID, testVersionID).Return(nil, fmt.Errorf("Error from the DB"))
mockDatabase.EXPECT().GetPublisherSlotNameHash(testPubID).Return(nil, fmt.Errorf("Error from the DB"))
mockDatabase.EXPECT().GetPublisherVASTTags(testPubID).Return(nil, fmt.Errorf("Error from the DB"))
- mockEngine.EXPECT().RecordGetProfileDataTime(models.EndpointV25, "123", gomock.Any()).Return()
+ mockEngine.EXPECT().RecordGetProfileDataTime(gomock.Any()).Return()
mockEngine.EXPECT().RecordDBQueryFailure(models.SlotNameHash, "5890", "123").Return()
mockEngine.EXPECT().RecordDBQueryFailure(models.PartnerConfigQuery, "5890", "123").Return()
mockEngine.EXPECT().RecordDBQueryFailure(models.PublisherVASTTagsQuery, "5890", "123").Return()
@@ -116,7 +114,7 @@ func Test_cache_GetPartnerConfigMap(t *testing.T) {
want: nil,
},
{
- name: "db_queries_failed_getting_adunitconfig_and_wrapper_slotmappings",
+ name: "error_in_adunitconfig_unmarshal",
fields: fields{
cache: gocache.New(100, 100),
cfg: config.Cache{
@@ -128,7 +126,6 @@ func Test_cache_GetPartnerConfigMap(t *testing.T) {
pubID: testPubID,
profileID: testProfileID,
displayVersion: 0,
- endpoint: models.EndpointAMP,
},
setup: func(ctrl *gomock.Controller) (*mock_database.MockDatabase, *mock_metrics.MockMetricsEngine) {
mockDatabase := mock_database.NewMockDatabase(ctrl)
@@ -137,24 +134,69 @@ func Test_cache_GetPartnerConfigMap(t *testing.T) {
mockDatabase.EXPECT().GetPublisherSlotNameHash(testPubID).Return(map[string]string{"adunit@728x90": "2aa34b52a9e941c1594af7565e599c8d"}, nil)
mockDatabase.EXPECT().GetPublisherVASTTags(testPubID).Return(nil, nil)
mockDatabase.EXPECT().GetAdunitConfig(testProfileID, 0).Return(nil, adunitconfig.ErrAdUnitUnmarshal)
- mockDatabase.EXPECT().GetWrapperSlotMappings(formTestPartnerConfig(), testProfileID, 0).Return(nil, fmt.Errorf("Error from the DB"))
- mockEngine.EXPECT().RecordGetProfileDataTime(models.EndpointAMP, "123", gomock.Any()).Return().Times(1)
+ mockDatabase.EXPECT().GetWrapperSlotMappings(formTestPartnerConfig(), testProfileID, 0).Return(nil, nil)
+ mockEngine.EXPECT().RecordGetProfileDataTime(gomock.Any()).Return().Times(1)
mockEngine.EXPECT().RecordDBQueryFailure(models.AdUnitFailUnmarshal, "5890", "123").Return().Times(1)
- mockEngine.EXPECT().RecordDBQueryFailure(models.WrapperLiveVersionSlotMappings, "5890", "123").Return().Times(1)
return mockDatabase, mockEngine
},
wantErr: true,
- want: map[int]map[string]string{
- 1: {
- "partnerId": "1",
- "prebidPartnerName": "pubmatic",
- "serverSideEnabled": "1",
- "level": "multi",
- "kgp": "_AU_@_W_x_H",
- "timeout": "220",
- "bidderCode": "pubmatic",
+ want: nil,
+ },
+ {
+ name: "db_queries_failed_getting_adunitconfig",
+ fields: fields{
+ cache: gocache.New(100, 100),
+ cfg: config.Cache{
+ CacheDefaultExpiry: 1000,
+ VASTTagCacheExpiry: 1000,
+ },
+ },
+ args: args{
+ pubID: testPubID,
+ profileID: testProfileID,
+ displayVersion: 0,
+ },
+ setup: func(ctrl *gomock.Controller) (*mock_database.MockDatabase, *mock_metrics.MockMetricsEngine) {
+ mockDatabase := mock_database.NewMockDatabase(ctrl)
+ mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
+ mockDatabase.EXPECT().GetActivePartnerConfigurations(testPubID, testProfileID, 0).Return(formTestPartnerConfig(), nil)
+ mockDatabase.EXPECT().GetPublisherSlotNameHash(testPubID).Return(map[string]string{"adunit@728x90": "2aa34b52a9e941c1594af7565e599c8d"}, nil)
+ mockDatabase.EXPECT().GetPublisherVASTTags(testPubID).Return(nil, nil)
+ mockDatabase.EXPECT().GetAdunitConfig(testProfileID, 0).Return(nil, errors.New("Failed to connect DB"))
+ mockDatabase.EXPECT().GetWrapperSlotMappings(formTestPartnerConfig(), testProfileID, 0).Return(nil, nil)
+ mockEngine.EXPECT().RecordGetProfileDataTime(gomock.Any()).Return().Times(1)
+ mockEngine.EXPECT().RecordDBQueryFailure(models.AdunitConfigForLiveVersion, "5890", "123").Return().Times(1)
+ return mockDatabase, mockEngine
+ },
+ wantErr: true,
+ want: nil},
+ {
+ name: "db_queries_failed_getting_wrapper_slotmappings",
+ fields: fields{
+ cache: gocache.New(100, 100),
+ cfg: config.Cache{
+ CacheDefaultExpiry: 1000,
+ VASTTagCacheExpiry: 1000,
},
},
+ args: args{
+ pubID: testPubID,
+ profileID: testProfileID,
+ displayVersion: 0,
+ },
+ setup: func(ctrl *gomock.Controller) (*mock_database.MockDatabase, *mock_metrics.MockMetricsEngine) {
+ mockDatabase := mock_database.NewMockDatabase(ctrl)
+ mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
+ mockDatabase.EXPECT().GetActivePartnerConfigurations(testPubID, testProfileID, 0).Return(formTestPartnerConfig(), nil)
+ mockDatabase.EXPECT().GetPublisherSlotNameHash(testPubID).Return(map[string]string{"adunit@728x90": "2aa34b52a9e941c1594af7565e599c8d"}, nil)
+ mockDatabase.EXPECT().GetPublisherVASTTags(testPubID).Return(nil, nil)
+ mockDatabase.EXPECT().GetWrapperSlotMappings(formTestPartnerConfig(), testProfileID, 0).Return(nil, fmt.Errorf("Error from the DB"))
+ mockEngine.EXPECT().RecordGetProfileDataTime(gomock.Any()).Return().Times(1)
+ mockEngine.EXPECT().RecordDBQueryFailure(models.WrapperLiveVersionSlotMappings, "5890", "123").Return().Times(1)
+ return mockDatabase, mockEngine
+ },
+ wantErr: true,
+ want: nil,
},
}
for ind := range tests {
@@ -169,7 +211,7 @@ func Test_cache_GetPartnerConfigMap(t *testing.T) {
}
c.db, c.metricEngine = tt.setup(ctrl)
- got, err := c.GetPartnerConfigMap(tt.args.pubID, tt.args.profileID, tt.args.displayVersion, tt.args.endpoint)
+ got, err := c.GetPartnerConfigMap(tt.args.pubID, tt.args.profileID, tt.args.displayVersion)
if (err != nil) != tt.wantErr {
t.Errorf("cache.GetPartnerConfigMap() error = %v, wantErr %v", err, tt.wantErr)
return
@@ -189,7 +231,6 @@ func Test_cache_GetPartnerConfigMap_LockandLoad(t *testing.T) {
pubID int
profileID int
displayVersion int
- endpoint string
}
tests := []struct {
name string
@@ -212,7 +253,6 @@ func Test_cache_GetPartnerConfigMap_LockandLoad(t *testing.T) {
pubID: testPubID,
profileID: testProfileID,
displayVersion: testVersionID,
- endpoint: models.EndpointV25,
},
setup: func(ctrl *gomock.Controller) (*mock_database.MockDatabase, *mock_metrics.MockMetricsEngine) {
mockDatabase := mock_database.NewMockDatabase(ctrl)
@@ -232,7 +272,7 @@ func Test_cache_GetPartnerConfigMap_LockandLoad(t *testing.T) {
},
},
}, nil)
- mockEngine.EXPECT().RecordGetProfileDataTime(models.EndpointV25, "123", gomock.Any()).Return().Times(1)
+ mockEngine.EXPECT().RecordGetProfileDataTime(gomock.Any()).Return().Times(1)
return mockDatabase, mockEngine
},
},
@@ -253,7 +293,7 @@ func Test_cache_GetPartnerConfigMap_LockandLoad(t *testing.T) {
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
- c.GetPartnerConfigMap(tt.args.pubID, tt.args.profileID, tt.args.displayVersion, tt.args.endpoint)
+ c.GetPartnerConfigMap(tt.args.pubID, tt.args.profileID, tt.args.displayVersion)
wg.Done()
}()
}
@@ -302,6 +342,73 @@ func Test_cache_getActivePartnerConfigAndPopulateWrapperMappings(t *testing.T) {
want want
setup func()
}{
+ {
+ name: "non_nil_partnerConfigMap_from_DB",
+ fields: fields{
+ cache: gocache.New(100, 100),
+ cfg: config.Cache{
+ CacheDefaultExpiry: 100,
+ },
+ db: mockDatabase,
+ },
+ args: args{
+ pubID: testPubID,
+ profileID: testProfileID,
+ displayVersion: testVersionID,
+ },
+ want: want{
+ cacheEntry: true,
+ err: nil,
+ partnerConfigMap: map[int]map[string]string{
+ 1: {
+ "bidderCode": "pubmatic",
+ "kgp": "_AU_@_W_x_H",
+ "level": "multi",
+ "partnerId": "1",
+ "prebidPartnerName": "pubmatic",
+ "serverSideEnabled": "1",
+ "timeout": "220",
+ },
+ },
+ },
+ setup: func() {
+ mockDatabase.EXPECT().GetActivePartnerConfigurations(testPubID, testProfileID, testVersionID).Return(formTestPartnerConfig(), nil)
+ mockDatabase.EXPECT().GetAdunitConfig(testProfileID, testVersionID).Return(nil, nil)
+ mockDatabase.EXPECT().GetWrapperSlotMappings(formTestPartnerConfig(), testProfileID, testVersionID).Return(map[int][]models.SlotMapping{
+ 1: {
+ {
+ PartnerId: testPartnerID,
+ AdapterId: testAdapterID,
+ VersionId: testVersionID,
+ SlotName: testSlotName,
+ MappingJson: "{\"adtag\":\"1405192\",\"site\":\"47124\",\"video\":{\"skippable\":\"TRUE\"}}",
+ },
+ },
+ }, nil)
+ },
+ },
+ {
+ name: "empty_partnerConfigMap_from_DB",
+ fields: fields{
+ cache: gocache.New(100, 100),
+ cfg: config.Cache{
+ CacheDefaultExpiry: 100,
+ },
+ db: mockDatabase,
+ },
+ args: args{
+ pubID: testPubID,
+ profileID: testProfileID,
+ displayVersion: testVersionID,
+ },
+ want: want{
+ cacheEntry: false,
+ err: fmt.Errorf("there are no active partners for pubId:%d, profileId:%d, displayVersion:%d", testPubID, testProfileID, testVersionID),
+ },
+ setup: func() {
+ mockDatabase.EXPECT().GetActivePartnerConfigurations(testPubID, testProfileID, testVersionID).Return(nil, nil)
+ },
+ },
{
name: "error_returning_Active_partner_configuration_from_DB",
fields: fields{
@@ -317,9 +424,8 @@ func Test_cache_getActivePartnerConfigAndPopulateWrapperMappings(t *testing.T) {
displayVersion: testVersionID,
},
want: want{
- cacheEntry: false,
- err: fmt.Errorf("Error from the DB"),
- partnerConfigMap: nil,
+ cacheEntry: false,
+ err: fmt.Errorf("Error from the DB"),
},
setup: func() {
mockDatabase.EXPECT().GetActivePartnerConfigurations(testPubID, testProfileID, testVersionID).Return(nil, fmt.Errorf("Error from the DB"))
@@ -327,7 +433,67 @@ func Test_cache_getActivePartnerConfigAndPopulateWrapperMappings(t *testing.T) {
},
},
{
- name: "non_nil_partnerConfigMap_from_DB",
+ name: "No partner config in case of error in GetWrapperSlotMappings",
+ fields: fields{
+ cache: gocache.New(100, 100),
+ cfg: config.Cache{
+ CacheDefaultExpiry: 100,
+ },
+ db: mockDatabase,
+ },
+ args: args{
+ pubID: testPubID,
+ profileID: testProfileID,
+ displayVersion: testVersionID,
+ },
+ want: want{
+ cacheEntry: false,
+ err: fmt.Errorf("Error from the DB"),
+ },
+ setup: func() {
+ mockDatabase.EXPECT().GetActivePartnerConfigurations(testPubID, testProfileID, testVersionID).Return(formTestPartnerConfig(), nil)
+
+ mockDatabase.EXPECT().GetWrapperSlotMappings(formTestPartnerConfig(), testProfileID, testVersionID).Return(nil, errors.New("Error from the DB"))
+ mockEngine.EXPECT().RecordDBQueryFailure(models.WrapperSlotMappingsQuery, "5890", "123").Return()
+ },
+ },
+ {
+ name: "No partner config in case of error in GetAdunitConfig",
+ fields: fields{
+ cache: gocache.New(100, 100),
+ cfg: config.Cache{
+ CacheDefaultExpiry: 100,
+ },
+ db: mockDatabase,
+ },
+ args: args{
+ pubID: testPubID,
+ profileID: testProfileID,
+ displayVersion: testVersionID,
+ },
+ want: want{
+ cacheEntry: false,
+ err: fmt.Errorf("Error from the DB"),
+ },
+ setup: func() {
+ mockDatabase.EXPECT().GetActivePartnerConfigurations(testPubID, testProfileID, testVersionID).Return(formTestPartnerConfig(), nil)
+ mockDatabase.EXPECT().GetAdunitConfig(testProfileID, testVersionID).Return(nil, errors.New("Error from the DB"))
+ mockEngine.EXPECT().RecordDBQueryFailure(models.AdunitConfigQuery, "5890", "123").Return()
+ mockDatabase.EXPECT().GetWrapperSlotMappings(formTestPartnerConfig(), testProfileID, testVersionID).Return(map[int][]models.SlotMapping{
+ 1: {
+ {
+ PartnerId: testPartnerID,
+ AdapterId: testAdapterID,
+ VersionId: testVersionID,
+ SlotName: testSlotName,
+ MappingJson: "{\"adtag\":\"1405192\",\"site\":\"47124\",\"video\":{\"skippable\":\"TRUE\"}}",
+ },
+ },
+ }, nil)
+ },
+ },
+ {
+ name: "Partner config in case of empty wrapperSlotMappings",
fields: fields{
cache: gocache.New(100, 100),
cfg: config.Cache{
@@ -358,21 +524,47 @@ func Test_cache_getActivePartnerConfigAndPopulateWrapperMappings(t *testing.T) {
setup: func() {
mockDatabase.EXPECT().GetActivePartnerConfigurations(testPubID, testProfileID, testVersionID).Return(formTestPartnerConfig(), nil)
mockDatabase.EXPECT().GetAdunitConfig(testProfileID, testVersionID).Return(nil, nil)
- mockDatabase.EXPECT().GetWrapperSlotMappings(formTestPartnerConfig(), testProfileID, testVersionID).Return(map[int][]models.SlotMapping{
+ mockDatabase.EXPECT().GetWrapperSlotMappings(formTestPartnerConfig(), testProfileID, testVersionID).Return(nil, nil)
+ },
+ },
+ {
+ name: "Partner config in case of empty adunitConfig",
+ fields: fields{
+ cache: gocache.New(100, 100),
+ cfg: config.Cache{
+ CacheDefaultExpiry: 100,
+ },
+ db: mockDatabase,
+ },
+ args: args{
+ pubID: testPubID,
+ profileID: testProfileID,
+ displayVersion: testVersionID,
+ },
+ want: want{
+ cacheEntry: true,
+ err: nil,
+ partnerConfigMap: map[int]map[string]string{
1: {
- {
- PartnerId: testPartnerID,
- AdapterId: testAdapterID,
- VersionId: testVersionID,
- SlotName: testSlotName,
- MappingJson: "{\"adtag\":\"1405192\",\"site\":\"47124\",\"video\":{\"skippable\":\"TRUE\"}}",
- },
+ "bidderCode": "pubmatic",
+ "kgp": "_AU_@_W_x_H",
+ "level": "multi",
+ "partnerId": "1",
+ "prebidPartnerName": "pubmatic",
+ "serverSideEnabled": "1",
+ "timeout": "220",
},
- }, nil)
+ },
+ },
+ setup: func() {
+ mockDatabase.EXPECT().GetActivePartnerConfigurations(testPubID, testProfileID, testVersionID).Return(formTestPartnerConfig(), nil)
+ mockDatabase.EXPECT().GetAdunitConfig(testProfileID, testVersionID).Return(nil, nil)
+ mockDatabase.EXPECT().GetWrapperSlotMappings(formTestPartnerConfig(), testProfileID, testVersionID).Return(nil, nil)
},
},
+
{
- name: "empty_partnerConfigMap_from_DB",
+ name: "Partner config in case of empty adunitConfig and wrapperSlotMappings",
fields: fields{
cache: gocache.New(100, 100),
cfg: config.Cache{
@@ -386,12 +578,24 @@ func Test_cache_getActivePartnerConfigAndPopulateWrapperMappings(t *testing.T) {
displayVersion: testVersionID,
},
want: want{
- cacheEntry: false,
- err: fmt.Errorf("there are no active partners for pubId:%d, profileId:%d, displayVersion:%d", testPubID, testProfileID, testVersionID),
- partnerConfigMap: nil,
+ cacheEntry: true,
+ err: nil,
+ partnerConfigMap: map[int]map[string]string{
+ 1: {
+ "bidderCode": "pubmatic",
+ "kgp": "_AU_@_W_x_H",
+ "level": "multi",
+ "partnerId": "1",
+ "prebidPartnerName": "pubmatic",
+ "serverSideEnabled": "1",
+ "timeout": "220",
+ },
+ },
},
setup: func() {
- mockDatabase.EXPECT().GetActivePartnerConfigurations(testPubID, testProfileID, testVersionID).Return(nil, nil)
+ mockDatabase.EXPECT().GetActivePartnerConfigurations(testPubID, testProfileID, testVersionID).Return(formTestPartnerConfig(), nil)
+ mockDatabase.EXPECT().GetAdunitConfig(testProfileID, testVersionID).Return(nil, nil)
+ mockDatabase.EXPECT().GetWrapperSlotMappings(formTestPartnerConfig(), testProfileID, testVersionID).Return(nil, nil)
},
},
}
@@ -408,13 +612,13 @@ func Test_cache_getActivePartnerConfigAndPopulateWrapperMappings(t *testing.T) {
metricEngine: mockEngine,
}
err := c.getActivePartnerConfigAndPopulateWrapperMappings(tt.args.pubID, tt.args.profileID, tt.args.displayVersion)
- assert.Equal(t, tt.want.err, err)
cacheKey := key(PUB_HB_PARTNER, tt.args.pubID, tt.args.profileID, tt.args.displayVersion)
partnerConfigMap, found := c.Get(cacheKey)
if tt.want.cacheEntry {
assert.True(t, found)
assert.Equal(t, tt.want.partnerConfigMap, partnerConfigMap)
} else {
+ assert.Equal(t, tt.want.err.Error(), err.Error())
assert.False(t, found)
assert.Nil(t, partnerConfigMap)
}
diff --git a/modules/pubmatic/openwrap/cache/mock/mock.go b/modules/pubmatic/openwrap/cache/mock/mock.go
index fd2c88b0506..e7f1cf2bd05 100644
--- a/modules/pubmatic/openwrap/cache/mock/mock.go
+++ b/modules/pubmatic/openwrap/cache/mock/mock.go
@@ -95,18 +95,18 @@ func (mr *MockCacheMockRecorder) GetMappingsFromCacheV25(arg0, arg1 interface{})
}
// GetPartnerConfigMap mocks base method.
-func (m *MockCache) GetPartnerConfigMap(arg0, arg1, arg2 int, arg3 string) (map[int]map[string]string, error) {
+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, arg3)
+ ret := m.ctrl.Call(m, "GetPartnerConfigMap", arg0, arg1, arg2)
ret0, _ := ret[0].(map[int]map[string]string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetPartnerConfigMap indicates an expected call of GetPartnerConfigMap.
-func (mr *MockCacheMockRecorder) GetPartnerConfigMap(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
+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, arg3)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPartnerConfigMap", reflect.TypeOf((*MockCache)(nil).GetPartnerConfigMap), arg0, arg1, arg2)
}
// GetPublisherFeatureMap mocks base method.
diff --git a/modules/pubmatic/openwrap/entrypointhook.go b/modules/pubmatic/openwrap/entrypointhook.go
index 7e619b8f65f..215289f698d 100644
--- a/modules/pubmatic/openwrap/entrypointhook.go
+++ b/modules/pubmatic/openwrap/entrypointhook.go
@@ -55,12 +55,21 @@ func (m OpenWrap) handleEntrypointHook(
rCtx.VastUnwrapEnabled = getVastUnwrapperEnable(payload.Request.Context(), models.VastUnwrapperEnableKey)
return result, nil
}
- endpoint = GetEndpoint(payload.Request.URL.Path, source)
+ endpoint = GetEndpoint(payload.Request.URL.Path, source, queryParams.Get(models.Agent))
if endpoint == models.EndpointHybrid {
rCtx.Endpoint = models.EndpointHybrid
return result, nil
}
+ if endpoint == models.EndpointAppLovinMax {
+ // updating body locally to access updated fields from signal
+ payload.Body = updateAppLovinMaxRequest(payload.Body)
+ result.ChangeSet.AddMutation(func(ep hookstage.EntrypointPayload) (hookstage.EntrypointPayload, error) {
+ ep.Body = payload.Body
+ return ep, nil
+ }, hookstage.MutationUpdate, "update-max-app-lovin-request")
+ }
+
// init default for all modules
result.Reject = true
@@ -149,7 +158,7 @@ func GetRequestWrapper(payload hookstage.EntrypointPayload, result hookstage.Hoo
fallthrough
case models.EndpointVideo, models.EndpointVAST, models.EndpointJson:
requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body, "ext", "wrapper")
- case models.EndpointWebS2S:
+ case models.EndpointWebS2S, models.EndpointAppLovinMax:
fallthrough
default:
requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body)
@@ -158,13 +167,17 @@ func GetRequestWrapper(payload hookstage.EntrypointPayload, result hookstage.Hoo
return requestExtWrapper, err
}
-func GetEndpoint(path, source string) string {
+func GetEndpoint(path, source string, agent string) string {
switch path {
case hookexecution.EndpointAuction:
switch source {
case "pbjs":
return models.EndpointWebS2S
case "owsdk":
+ switch agent {
+ case models.AppLovinMaxAgent:
+ return models.EndpointAppLovinMax
+ }
return models.EndpointV25
default:
return models.EndpointHybrid
diff --git a/modules/pubmatic/openwrap/entrypointhook_test.go b/modules/pubmatic/openwrap/entrypointhook_test.go
index 317c73c1681..bea55d862b6 100644
--- a/modules/pubmatic/openwrap/entrypointhook_test.go
+++ b/modules/pubmatic/openwrap/entrypointhook_test.go
@@ -34,11 +34,13 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) {
setup func(*mock_metrics.MockMetricsEngine)
}
tests := []struct {
- name string
- fields fields
- args args
- want hookstage.HookResult[hookstage.EntrypointPayload]
- wantErr error
+ name string
+ fields fields
+ args args
+ want hookstage.HookResult[hookstage.EntrypointPayload]
+ wantBody []byte
+ wantErr error
+ doMutate bool
}{
{
name: "request with sshb=1 should not execute entrypointhook",
@@ -494,6 +496,73 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) {
},
wantErr: nil,
},
+ {
+ name: "valid request for applovin max /openrtb2/auction?source=owsdk&agent=max request",
+ fields: fields{
+ cfg: config.Config{
+ Tracker: config.Tracker{
+ Endpoint: "t.pubmatic.com",
+ VideoErrorTrackerEndpoint: "t.pubmatic.com/error",
+ },
+ },
+ cache: nil,
+ },
+ args: args{
+ in0: context.Background(),
+ miCtx: hookstage.ModuleInvocationContext{},
+ payload: hookstage.EntrypointPayload{
+ Request: func() *http.Request {
+ r, err := http.NewRequest("POST", "http://localhost/openrtb2/auction?source=owsdk&agent=max&debug=1", nil)
+ if err != nil {
+ panic(err)
+ }
+ r.Header.Add("User-Agent", "go-test")
+ r.Header.Add("SOURCE_IP", "127.0.0.1")
+ r.Header.Add("Cookie", `KADUSERCOOKIE=7D75D25F-FAC9-443D-B2D1-B17FEE11E027; DPSync3=1684886400%3A248%7C1685491200%3A245_226_201; KRTBCOOKIE_80=16514-CAESEMih0bN7ISRdZT8xX8LXzEw&KRTB&22987-CAESEMih0bN7ISRdZT8xX8LXzEw&KRTB&23025-CAESEMih0bN7ISRdZT8xX8LXzEw&KRTB&23386-CAESEMih0bN7ISRdZT8xX8LXzEw; KRTBCOOKIE_377=6810-59dc50c9-d658-44ce-b442-5a1f344d97c0&KRTB&22918-59dc50c9-d658-44ce-b442-5a1f344d97c0&KRTB&23031-59dc50c9-d658-44ce-b442-5a1f344d97c0; uids=eyJ0ZW1wVUlEcyI6eyIzM2Fjcm9zcyI6eyJ1aWQiOiIxMTkxNzkxMDk5Nzc2NjEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTo0My4zODg4Nzk5NVoifSwiYWRmIjp7InVpZCI6IjgwNDQ2MDgzMzM3Nzg4MzkwNzgiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMS4wMzMwNTQ3MjdaIn0sImFka2VybmVsIjp7InVpZCI6IkE5MTYzNTAwNzE0OTkyOTMyOTkwIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MDkuMzczMzg1NjYyWiJ9LCJhZGtlcm5lbEFkbiI6eyJ1aWQiOiJBOTE2MzUwMDcxNDk5MjkzMjk5MCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEzLjQzNDkyNTg5NloifSwiYWRtaXhlciI6eyJ1aWQiOiIzNjZhMTdiMTJmMjI0ZDMwOGYzZTNiOGRhOGMzYzhhMCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjU5MjkxNDgwMVoifSwiYWRueHMiOnsidWlkIjoiNDE5Mjg5ODUzMDE0NTExOTMiLCJleHBpcmVzIjoiMjAyMy0wMS0xOFQwOTo1MzowOC44MjU0NDI2NzZaIn0sImFqYSI6eyJ1aWQiOiJzMnN1aWQ2RGVmMFl0bjJveGQ1aG9zS1AxVmV3IiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTMuMjM5MTc2MDU0WiJ9LCJlcGxhbm5pbmciOnsidWlkIjoiQUoxRjBTOE5qdTdTQ0xWOSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjkyOTk2MDQ3M1oifSwiZ2Ftb3NoaSI6eyJ1aWQiOiJndXNyXzM1NmFmOWIxZDhjNjQyYjQ4MmNiYWQyYjdhMjg4MTYxIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTAuNTI0MTU3MjI1WiJ9LCJncmlkIjp7InVpZCI6IjRmYzM2MjUwLWQ4NTItNDU5Yy04NzcyLTczNTZkZTE3YWI5NyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjE0LjY5NjMxNjIyN1oifSwiZ3JvdXBtIjp7InVpZCI6IjdENzVEMjVGLUZBQzktNDQzRC1CMkQxLUIxN0ZFRTExRTAyNyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjM5LjIyNjIxMjUzMloifSwiaXgiOnsidWlkIjoiWW9ORlNENlc5QkphOEh6eEdtcXlCUUFBXHUwMDI2Mjk3IiwiZXhwaXJlcyI6IjIwMjMtMDUtMzFUMDc6NTM6MzguNTU1ODI3MzU0WiJ9LCJqaXhpZSI6eyJ1aWQiOiI3MzY3MTI1MC1lODgyLTExZWMtYjUzOC0xM2FjYjdhZjBkZTQiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMi4xOTEwOTk3MzJaIn0sImxvZ2ljYWQiOnsidWlkIjoiQVZ4OVROQS11c25pa3M4QURzTHpWa3JvaDg4QUFBR0JUREh0UUEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTowOS40NTUxNDk2MTZaIn0sIm1lZGlhbmV0Ijp7InVpZCI6IjI5Nzg0MjM0OTI4OTU0MTAwMDBWMTAiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMy42NzIyMTUxMjhaIn0sIm1naWQiOnsidWlkIjoibTU5Z1hyN0xlX1htIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTcuMDk3MDAxNDcxWiJ9LCJuYW5vaW50ZXJhY3RpdmUiOnsidWlkIjoiNmFlYzhjMTAzNzlkY2I3ODQxMmJjODBiNmRkOWM5NzMxNzNhYjdkNzEyZTQzMWE1YTVlYTcwMzRlNTZhNThhMCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjE2LjcxNDgwNzUwNVoifSwib25ldGFnIjp7InVpZCI6IjdPelZoVzFOeC1LOGFVak1HMG52NXVNYm5YNEFHUXZQbnVHcHFrZ3k0ckEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTowOS4xNDE3NDEyNjJaIn0sIm9wZW54Ijp7InVpZCI6IjVkZWNlNjIyLTBhMjMtMGRhYi0zYTI0LTVhNzcwMTBlNDU4MiIsImV4cGlyZXMiOiIyMDIzLTA1LTMxVDA3OjUyOjQ3LjE0MDQxNzM2M1oifSwicHVibWF0aWMiOnsidWlkIjoiN0Q3NUQyNUYtRkFDOS00NDNELUIyRDEtQjE3RkVFMTFFMDI3IiwiZXhwaXJlcyI6IjIwMjItMTAtMzFUMDk6MTQ6MjUuNzM3MjU2ODk5WiJ9LCJyaWNoYXVkaWVuY2UiOnsidWlkIjoiY2I2YzYzMjAtMzNlMi00Nzc0LWIxNjAtMXp6MTY1NDg0MDc0OSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjUyNTA3NDE4WiJ9LCJzbWFydHlhZHMiOnsidWlkIjoiMTJhZjE1ZTQ0ZjAwZDA3NjMwZTc0YzQ5MTU0Y2JmYmE0Zjg0N2U4ZDRhMTU0YzhjM2Q1MWY1OGNmNzJhNDYyNyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjgyNTAzMTg4NFoifSwic21pbGV3YW50ZWQiOnsidWlkIjoiZGQ5YzNmZTE4N2VmOWIwOWNhYTViNzExNDA0YzI4MzAiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxNC4yNTU2MDkzNjNaIn0sInN5bmFjb3JtZWRpYSI6eyJ1aWQiOiJHRFBSIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MDkuOTc5NTgzNDM4WiJ9LCJ0cmlwbGVsaWZ0Ijp7InVpZCI6IjcwMjE5NzUwNTQ4MDg4NjUxOTQ2MyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA4Ljk4OTY3MzU3NFoifSwidmFsdWVpbXByZXNzaW9uIjp7InVpZCI6IjlkMDgxNTVmLWQ5ZmUtNGI1OC04OThlLWUyYzU2MjgyYWIzZSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjA2NzgzOTE2NFoifSwidmlzeCI6eyJ1aWQiOiIyN2UwYWMzYy1iNDZlLTQxYjMtOTkyYy1mOGQyNzE0OTQ5NWUiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMi45ODk1MjM1NzNaIn0sInlpZWxkbGFiIjp7InVpZCI6IjY5NzE0ZDlmLWZiMDAtNGE1Zi04MTljLTRiZTE5MTM2YTMyNSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjExLjMwMzAyNjYxNVoifSwieWllbGRtbyI6eyJ1aWQiOiJnOTZjMmY3MTlmMTU1MWIzMWY2MyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjExMDUyODYwOVoifSwieWllbGRvbmUiOnsidWlkIjoiMmE0MmZiZDMtMmM3MC00ZWI5LWIxYmQtMDQ2OTY2NTBkOTQ4IiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTAuMzE4MzMzOTM5WiJ9LCJ6ZXJvY2xpY2tmcmF1ZCI6eyJ1aWQiOiJiOTk5NThmZS0yYTg3LTJkYTQtOWNjNC05NjFmZDExM2JlY2UiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxNS43MTk1OTQ1NjZaIn19LCJiZGF5IjoiMjAyMi0wNS0xN1QwNjo0ODozOC4wMTc5ODgyMDZaIn0=; KRTBCOOKIE_153=1923-LZw-Ny-bMjI2m2Q8IpsrNnnIYzw2yjdnLJsrdYse&KRTB&19420-LZw-Ny-bMjI2m2Q8IpsrNnnIYzw2yjdnLJsrdYse&KRTB&22979-LZw-Ny-bMjI2m2Q8IpsrNnnIYzw2yjdnLJsrdYse&KRTB&23462-LZw-Ny-bMjI2m2Q8IpsrNnnIYzw2yjdnLJsrdYse; KRTBCOOKIE_57=22776-41928985301451193&KRTB&23339-41928985301451193; KRTBCOOKIE_27=16735-uid:3cab6283-4546-4500-a7b6-40ef605fe745&KRTB&16736-uid:3cab6283-4546-4500-a7b6-40ef605fe745&KRTB&23019-uid:3cab6283-4546-4500-a7b6-40ef605fe745&KRTB&23114-uid:3cab6283-4546-4500-a7b6-40ef605fe745; KRTBCOOKIE_18=22947-1978557989514665832; KRTBCOOKIE_466=16530-4fc36250-d852-459c-8772-7356de17ab97; KRTBCOOKIE_391=22924-8044608333778839078&KRTB&23263-8044608333778839078&KRTB&23481-8044608333778839078; KRTBCOOKIE_1310=23431-b81c3g7dr67i&KRTB&23446-b81c3g7dr67i&KRTB&23465-b81c3g7dr67i; KRTBCOOKIE_1290=23368-vkf3yv9lbbl; KRTBCOOKIE_22=14911-4554572065121110164&KRTB&23150-4554572065121110164; KRTBCOOKIE_860=16335-YGAqDU1zUTdjyAFxCoe3kctlNPo&KRTB&23334-YGAqDU1zUTdjyAFxCoe3kctlNPo&KRTB&23417-YGAqDU1zUTdjyAFxCoe3kctlNPo&KRTB&23426-YGAqDU1zUTdjyAFxCoe3kctlNPo; KRTBCOOKIE_904=16787-KwJwE7NkCZClNJRysN2iYg; KRTBCOOKIE_1159=23138-5545f53f3d6e4ec199d8ed627ff026f3&KRTB&23328-5545f53f3d6e4ec199d8ed627ff026f3&KRTB&23427-5545f53f3d6e4ec199d8ed627ff026f3&KRTB&23445-5545f53f3d6e4ec199d8ed627ff026f3; KRTBCOOKIE_32=11175-AQEI_1QecY2ESAIjEW6KAQEBAQE&KRTB&22713-AQEI_1QecY2ESAIjEW6KAQEBAQE&KRTB&22715-AQEI_1QecY2ESAIjEW6KAQEBAQE; SyncRTB3=1685577600%3A35%7C1685491200%3A107_21_71_56_204_247_165_231_233_179_22_209_54_254_238_96_99_220_7_214_13_3_8_234_176_46_5%7C1684886400%3A2_223_15%7C1689465600%3A69%7C1685145600%3A63; KRTBCOOKIE_107=1471-uid:EK38R0PM1NQR0H5&KRTB&23421-uid:EK38R0PM1NQR0H5; KRTBCOOKIE_594=17105-RX-447a6332-530e-456a-97f4-3f0fd1ed48c9-004&KRTB&17107-RX-447a6332-530e-456a-97f4-3f0fd1ed48c9-004; SPugT=1684310122; chkChromeAb67Sec=133; KRTBCOOKIE_699=22727-AAFy2k7FBosAAEasbJoXnw; PugT=1684310473; origin=go-test`)
+ return r
+ }(),
+ Body: []byte(`{"id":"test-case-1","at":1,"bcat":["IAB26-4","IAB26-2","IAB25-6","IAB25-5","IAB25-4","IAB25-3","IAB25-1","IAB25-7","IAB8-18","IAB26-3","IAB26-1","IAB8-5","IAB25-2","IAB11-4"],"tmax":1000,"app":{"publisher":{"name":"New Story Inc.","id":"5890","ext":{"installed_sdk":{"id":"MOLOCO_BIDDING","sdk_version":{"major":1,"minor":0,"micro":0},"adapter_version":{"major":1,"minor":0,"micro":0}}}},"paid":0,"name":"DrawHappyAngel","ver":"0.5.4","bundle":"com.newstory.DrawHappyAngel","cat":["IAB9-30"],"id":"1234567","ext":{"orientation":1}},"device":{"ifa":"497a10d6-c4dd-4e04-a986-c32b7180d462","ip":"38.158.207.171","carrier":"MYTEL","language":"en_US","hwv":"ruby","ppi":440,"pxratio":2.75,"devicetype":4,"connectiontype":2,"js":1,"h":2400,"w":1080,"geo":{"type":2,"ipservice":3,"lat":40.7429,"lon":-73.9392,"long":-73.9392,"city":"Queens","country":"USA","region":"ny","dma":"501","metro":"501","zip":"11101","ext":{"org":"Myanmar Broadband Telecom Co.","isp":"Myanmar Broadband Telecom Co."}},"ext":{},"osv":"13.0.0","ua":"Mozilla/5.0 (Linux; Android 13; 22101316C Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/120.0.6099.230 Mobile Safari/537.36","make":"xiaomi","model":"22101316c","os":"android"},"imp":[{"id":"1","displaymanager":"applovin_mediation","displaymanagerver":"11.8.2","instl":0,"secure":0,"tagid":"/43743431/DMDemo","bidfloor":0.01,"bidfloorcur":"USD","exp":14400,"banner":{"format":[{"w":728,"h":90},{"w":300,"h":250}],"w":700,"h":900},"video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"rwdd":0}],"user":{"data":[{"id":"1","name":"Publisher Passed","segment":[{"signal":"{\"id\":\"95d6643c-3da6-40a2-b9ca-12279393ffbf\",\"at\":1,\"tmax\":500,\"cur\":[\"USD\"],\"imp\":[{\"id\":\"imp176227948\",\"clickbrowser\":0,\"displaymanager\":\"PubMatic_OpenBid_SDK\",\"displaymanagerver\":\"1.4.0\",\"tagid\":\"\/43743431\/DMDemo\",\"secure\":0,\"banner\":{\"pos\":7,\"format\":[{\"w\":300,\"h\":250}],\"api\":[5,6,7]},\"instl\":1}],\"app\":{\"paid\":4,\"name\":\"OpenWrapperSample\",\"bundle\":\"com.pubmatic.openbid.app\",\"storeurl\":\"https:\/\/itunes.apple.com\/us\/app\/pubmatic-sdk-app\/id1175273098?appnexus_banner_fixedbid=1&fixedbid=1\",\"ver\":\"1.0\",\"publisher\":{\"id\":\"5890\"}},\"device\":{\"geo\":{\"type\":1,\"lat\":37.421998333333335,\"lon\":-122.08400000000002},\"pxratio\":2.625,\"mccmnc\":\"310-260\",\"lmt\":0,\"ifa\":\"07c387f2-e030-428f-8336-42f682150759\",\"connectiontype\":5,\"carrier\":\"Android\",\"js\":1,\"ua\":\"Mozilla\/5.0(Linux;Android9;AndroidSDKbuiltforx86Build\/PSR1.180720.075;wv)AppleWebKit\/537.36(KHTML,likeGecko)Version\/4.0Chrome\/69.0.3497.100MobileSafari\/537.36\",\"make\":\"Google\",\"model\":\"AndroidSDKbuiltforx86\",\"os\":\"Android\",\"osv\":\"9\",\"h\":1794,\"w\":1080,\"language\":\"en-US\",\"devicetype\":4,\"ext\":{\"atts\":3}},\"source\":{\"ext\":{\"omidpn\":\"PubMatic\",\"omidpv\":\"1.2.11-Pubmatic\"}},\"user\":{\"data\":[{\"id\":\"1234\"}]},\"ext\":{\"wrapper\":{\"ssauction\":1,\"sumry_disable\":0,\"profileid\":58135,\"versionid\":1,\"clientconfig\":1}}}"}]}],"ext":{"gdpr":0}},"regs":{"coppa":0,"ext":{"gdpr":0}},"source":{"ext":{"schain":{"ver":"1.0","complete":1,"nodes":[{"asi":"applovin.com","sid":"53bf468f18c5a0e2b7d4e3f748c677c1","rid":"494dbe15a3ce08c54f4e456363f35a022247f997","hp":1}]}}},"ext":{"prebid":{"bidderparams":{"pubmatic":{"wrapper":{"profileid":12929,"versionid":1}}}}}}`),
+ },
+ setup: func(mme *mock_metrics.MockMetricsEngine) {},
+ },
+ want: hookstage.HookResult[hookstage.EntrypointPayload]{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": models.RequestCtx{
+ ProfileID: 12929,
+ DisplayID: 1,
+ DisplayVersionID: 1,
+ SSAuction: -1,
+ ClientConfigFlag: 1,
+ Debug: true,
+ UA: "go-test",
+ IP: "127.0.0.1",
+ IsCTVRequest: false,
+ TrackerEndpoint: "t.pubmatic.com",
+ VideoErrorTrackerEndpoint: "t.pubmatic.com/error",
+ UidCookie: &http.Cookie{
+ Name: "uids",
+ Value: `eyJ0ZW1wVUlEcyI6eyIzM2Fjcm9zcyI6eyJ1aWQiOiIxMTkxNzkxMDk5Nzc2NjEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTo0My4zODg4Nzk5NVoifSwiYWRmIjp7InVpZCI6IjgwNDQ2MDgzMzM3Nzg4MzkwNzgiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMS4wMzMwNTQ3MjdaIn0sImFka2VybmVsIjp7InVpZCI6IkE5MTYzNTAwNzE0OTkyOTMyOTkwIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MDkuMzczMzg1NjYyWiJ9LCJhZGtlcm5lbEFkbiI6eyJ1aWQiOiJBOTE2MzUwMDcxNDk5MjkzMjk5MCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEzLjQzNDkyNTg5NloifSwiYWRtaXhlciI6eyJ1aWQiOiIzNjZhMTdiMTJmMjI0ZDMwOGYzZTNiOGRhOGMzYzhhMCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjU5MjkxNDgwMVoifSwiYWRueHMiOnsidWlkIjoiNDE5Mjg5ODUzMDE0NTExOTMiLCJleHBpcmVzIjoiMjAyMy0wMS0xOFQwOTo1MzowOC44MjU0NDI2NzZaIn0sImFqYSI6eyJ1aWQiOiJzMnN1aWQ2RGVmMFl0bjJveGQ1aG9zS1AxVmV3IiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTMuMjM5MTc2MDU0WiJ9LCJlcGxhbm5pbmciOnsidWlkIjoiQUoxRjBTOE5qdTdTQ0xWOSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjkyOTk2MDQ3M1oifSwiZ2Ftb3NoaSI6eyJ1aWQiOiJndXNyXzM1NmFmOWIxZDhjNjQyYjQ4MmNiYWQyYjdhMjg4MTYxIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTAuNTI0MTU3MjI1WiJ9LCJncmlkIjp7InVpZCI6IjRmYzM2MjUwLWQ4NTItNDU5Yy04NzcyLTczNTZkZTE3YWI5NyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjE0LjY5NjMxNjIyN1oifSwiZ3JvdXBtIjp7InVpZCI6IjdENzVEMjVGLUZBQzktNDQzRC1CMkQxLUIxN0ZFRTExRTAyNyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjM5LjIyNjIxMjUzMloifSwiaXgiOnsidWlkIjoiWW9ORlNENlc5QkphOEh6eEdtcXlCUUFBXHUwMDI2Mjk3IiwiZXhwaXJlcyI6IjIwMjMtMDUtMzFUMDc6NTM6MzguNTU1ODI3MzU0WiJ9LCJqaXhpZSI6eyJ1aWQiOiI3MzY3MTI1MC1lODgyLTExZWMtYjUzOC0xM2FjYjdhZjBkZTQiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMi4xOTEwOTk3MzJaIn0sImxvZ2ljYWQiOnsidWlkIjoiQVZ4OVROQS11c25pa3M4QURzTHpWa3JvaDg4QUFBR0JUREh0UUEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTowOS40NTUxNDk2MTZaIn0sIm1lZGlhbmV0Ijp7InVpZCI6IjI5Nzg0MjM0OTI4OTU0MTAwMDBWMTAiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMy42NzIyMTUxMjhaIn0sIm1naWQiOnsidWlkIjoibTU5Z1hyN0xlX1htIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTcuMDk3MDAxNDcxWiJ9LCJuYW5vaW50ZXJhY3RpdmUiOnsidWlkIjoiNmFlYzhjMTAzNzlkY2I3ODQxMmJjODBiNmRkOWM5NzMxNzNhYjdkNzEyZTQzMWE1YTVlYTcwMzRlNTZhNThhMCIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjE2LjcxNDgwNzUwNVoifSwib25ldGFnIjp7InVpZCI6IjdPelZoVzFOeC1LOGFVak1HMG52NXVNYm5YNEFHUXZQbnVHcHFrZ3k0ckEiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OTowOS4xNDE3NDEyNjJaIn0sIm9wZW54Ijp7InVpZCI6IjVkZWNlNjIyLTBhMjMtMGRhYi0zYTI0LTVhNzcwMTBlNDU4MiIsImV4cGlyZXMiOiIyMDIzLTA1LTMxVDA3OjUyOjQ3LjE0MDQxNzM2M1oifSwicHVibWF0aWMiOnsidWlkIjoiN0Q3NUQyNUYtRkFDOS00NDNELUIyRDEtQjE3RkVFMTFFMDI3IiwiZXhwaXJlcyI6IjIwMjItMTAtMzFUMDk6MTQ6MjUuNzM3MjU2ODk5WiJ9LCJyaWNoYXVkaWVuY2UiOnsidWlkIjoiY2I2YzYzMjAtMzNlMi00Nzc0LWIxNjAtMXp6MTY1NDg0MDc0OSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjUyNTA3NDE4WiJ9LCJzbWFydHlhZHMiOnsidWlkIjoiMTJhZjE1ZTQ0ZjAwZDA3NjMwZTc0YzQ5MTU0Y2JmYmE0Zjg0N2U4ZDRhMTU0YzhjM2Q1MWY1OGNmNzJhNDYyNyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjgyNTAzMTg4NFoifSwic21pbGV3YW50ZWQiOnsidWlkIjoiZGQ5YzNmZTE4N2VmOWIwOWNhYTViNzExNDA0YzI4MzAiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxNC4yNTU2MDkzNjNaIn0sInN5bmFjb3JtZWRpYSI6eyJ1aWQiOiJHRFBSIiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MDkuOTc5NTgzNDM4WiJ9LCJ0cmlwbGVsaWZ0Ijp7InVpZCI6IjcwMjE5NzUwNTQ4MDg4NjUxOTQ2MyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA4Ljk4OTY3MzU3NFoifSwidmFsdWVpbXByZXNzaW9uIjp7InVpZCI6IjlkMDgxNTVmLWQ5ZmUtNGI1OC04OThlLWUyYzU2MjgyYWIzZSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjA5LjA2NzgzOTE2NFoifSwidmlzeCI6eyJ1aWQiOiIyN2UwYWMzYy1iNDZlLTQxYjMtOTkyYy1mOGQyNzE0OTQ5NWUiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxMi45ODk1MjM1NzNaIn0sInlpZWxkbGFiIjp7InVpZCI6IjY5NzE0ZDlmLWZiMDAtNGE1Zi04MTljLTRiZTE5MTM2YTMyNSIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjExLjMwMzAyNjYxNVoifSwieWllbGRtbyI6eyJ1aWQiOiJnOTZjMmY3MTlmMTU1MWIzMWY2MyIsImV4cGlyZXMiOiIyMDIyLTA2LTI0VDA1OjU5OjEwLjExMDUyODYwOVoifSwieWllbGRvbmUiOnsidWlkIjoiMmE0MmZiZDMtMmM3MC00ZWI5LWIxYmQtMDQ2OTY2NTBkOTQ4IiwiZXhwaXJlcyI6IjIwMjItMDYtMjRUMDU6NTk6MTAuMzE4MzMzOTM5WiJ9LCJ6ZXJvY2xpY2tmcmF1ZCI6eyJ1aWQiOiJiOTk5NThmZS0yYTg3LTJkYTQtOWNjNC05NjFmZDExM2JlY2UiLCJleHBpcmVzIjoiMjAyMi0wNi0yNFQwNTo1OToxNS43MTk1OTQ1NjZaIn19LCJiZGF5IjoiMjAyMi0wNS0xN1QwNjo0ODozOC4wMTc5ODgyMDZaIn0=`,
+ },
+ KADUSERCookie: &http.Cookie{
+ Name: "KADUSERCOOKIE",
+ Value: `7D75D25F-FAC9-443D-B2D1-B17FEE11E027`,
+ },
+ OriginCookie: "go-test",
+ Aliases: make(map[string]string),
+ ImpBidCtx: make(map[string]models.ImpCtx),
+ PrebidBidderCode: make(map[string]string),
+ BidderResponseTimeMillis: make(map[string]int),
+ ProfileIDStr: "12929",
+ Endpoint: models.EndpointAppLovinMax,
+ MetricsEngine: mockEngine,
+ SeatNonBids: make(map[string][]openrtb_ext.NonBid),
+ },
+ },
+ },
+ doMutate: true,
+ wantErr: nil,
+ wantBody: []byte(`{"id":"test-case-1","imp":[{"id":"1","banner":{"format":[{"w":728,"h":90},{"w":300,"h":250}],"w":700,"h":900,"api":[5,6,7]},"video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"displaymanager":"PubMatic_OpenBid_SDK","displaymanagerver":"1.4.0","tagid":"/43743431/DMDemo","bidfloor":0.01,"bidfloorcur":"USD","clickbrowser":0,"secure":0,"exp":14400}],"app":{"id":"1234567","name":"DrawHappyAngel","bundle":"com.newstory.DrawHappyAngel","cat":["IAB9-30"],"ver":"0.5.4","paid":4,"publisher":{"id":"5890","name":"New Story Inc.","ext":{"installed_sdk":{"id":"MOLOCO_BIDDING","sdk_version":{"major":1,"minor":0,"micro":0},"adapter_version":{"major":1,"minor":0,"micro":0}}}},"ext":{"orientation":1}},"device":{"geo":{"lat":40.7429,"lon":-73.9392,"type":2,"ipservice":3,"country":"USA","region":"ny","metro":"501","city":"Queens","zip":"11101","ext":{"org":"Myanmar Broadband Telecom Co.","isp":"Myanmar Broadband Telecom Co."}},"ua":"Mozilla/5.0 (Linux; Android 13; 22101316C Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/120.0.6099.230 Mobile Safari/537.36","ip":"38.158.207.171","devicetype":4,"make":"xiaomi","model":"22101316c","os":"android","osv":"13.0.0","hwv":"ruby","h":2400,"w":1080,"ppi":440,"pxratio":2.75,"js":1,"language":"en_US","carrier":"MYTEL","mccmnc":"310-260","connectiontype":5,"ifa":"497a10d6-c4dd-4e04-a986-c32b7180d462","ext":{"atts":3}},"user":{"data":[{"id":"1234"}],"ext":{"gdpr":0}},"at":1,"tmax":1000,"bcat":["IAB26-4","IAB26-2","IAB25-6","IAB25-5","IAB25-4","IAB25-3","IAB25-1","IAB25-7","IAB8-18","IAB26-3","IAB26-1","IAB8-5","IAB25-2","IAB11-4"],"source":{"ext":{"schain":{"ver":"1.0","complete":1,"nodes":[{"asi":"applovin.com","sid":"53bf468f18c5a0e2b7d4e3f748c677c1","rid":"494dbe15a3ce08c54f4e456363f35a022247f997","hp":1}]},"omidpn":"PubMatic","omidpv":"1.2.11-Pubmatic"}},"regs":{"ext":{"gdpr":0}},"ext":{"prebid":{"bidderparams":{"pubmatic":{"wrapper":{"profileid":12929,"versionid":1,"clientconfig":1}}}}}}`),
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -526,7 +595,17 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) {
gotRctx.CurrencyConversion = nil // ignore currency-conversion
got.ModuleContext["rctx"] = gotRctx
}
- assert.Equal(t, got, tt.want)
+
+ if tt.doMutate {
+ mutations := got.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.wantBody, result.Body)
+ }
+ }
+ assert.Equal(t, tt.want.ModuleContext, got.ModuleContext)
})
}
}
@@ -589,6 +668,7 @@ func TestGetEndpoint(t *testing.T) {
type args struct {
path string
source string
+ agent string
}
tests := []struct {
name string
@@ -667,10 +747,19 @@ func TestGetEndpoint(t *testing.T) {
},
want: models.EndpointJson,
},
+ {
+ name: "ApplovinMax",
+ args: args{
+ path: hookexecution.EndpointAuction,
+ source: "owsdk",
+ agent: models.AppLovinMaxAgent,
+ },
+ want: models.EndpointAppLovinMax,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- got := GetEndpoint(tt.args.path, tt.args.source)
+ got := GetEndpoint(tt.args.path, tt.args.source, tt.args.agent)
assert.Equal(t, tt.want, got)
})
}
diff --git a/modules/pubmatic/openwrap/metrics/config/multimetrics.go b/modules/pubmatic/openwrap/metrics/config/multimetrics.go
index 1c773f704b4..a8ae0176a37 100644
--- a/modules/pubmatic/openwrap/metrics/config/multimetrics.go
+++ b/modules/pubmatic/openwrap/metrics/config/multimetrics.go
@@ -363,9 +363,9 @@ func (me *MultiMetricsEngine) RecordVideoImpDisabledViaConnTypeStats(publisher,
}
// RecordGetProfileDataTime across all engines
-func (me *MultiMetricsEngine) RecordGetProfileDataTime(requestType, profileid string, getTime time.Duration) {
+func (me *MultiMetricsEngine) RecordGetProfileDataTime(getTime time.Duration) {
for _, thisME := range *me {
- thisME.RecordGetProfileDataTime(requestType, profileid, getTime)
+ thisME.RecordGetProfileDataTime(getTime)
}
}
@@ -426,9 +426,9 @@ func (me *MultiMetricsEngine) RecordCtvUaAccuracy(pubId, status string) {
}
// RecordSendLoggerDataTime across all engines
-func (me *MultiMetricsEngine) RecordSendLoggerDataTime(endpoint, profile string, sendTime time.Duration) {
+func (me *MultiMetricsEngine) RecordSendLoggerDataTime(sendTime time.Duration) {
for _, thisME := range *me {
- thisME.RecordSendLoggerDataTime(endpoint, profile, sendTime)
+ thisME.RecordSendLoggerDataTime(sendTime)
}
}
diff --git a/modules/pubmatic/openwrap/metrics/config/multimetrics_test.go b/modules/pubmatic/openwrap/metrics/config/multimetrics_test.go
index 25c183e08c9..81aea23ae64 100644
--- a/modules/pubmatic/openwrap/metrics/config/multimetrics_test.go
+++ b/modules/pubmatic/openwrap/metrics/config/multimetrics_test.go
@@ -203,8 +203,8 @@ func TestRecordFunctionForMultiMetricsEngine(t *testing.T) {
mockEngine.EXPECT().RecordBidResponseByDealCountInHB(publisher, profile, aliasBidder, dealId)
mockEngine.EXPECT().RecordPartnerTimeoutInPBS(publisher, profile, aliasBidder)
mockEngine.EXPECT().RecordVideoImpDisabledViaConnTypeStats(publisher, profile)
- mockEngine.EXPECT().RecordGetProfileDataTime(endpoint, profile, getTime)
- mockEngine.EXPECT().RecordSendLoggerDataTime(endpoint, profile, sendTime)
+ mockEngine.EXPECT().RecordGetProfileDataTime(getTime)
+ mockEngine.EXPECT().RecordSendLoggerDataTime(sendTime)
mockEngine.EXPECT().RecordDBQueryFailure(queryType, publisher, profile)
mockEngine.EXPECT().RecordAnalyticsTrackingThrottled(publisher, profile, "logger")
mockEngine.EXPECT().Shutdown()
@@ -215,7 +215,7 @@ func TestRecordFunctionForMultiMetricsEngine(t *testing.T) {
mockEngine.EXPECT().RecordBids("pubid", "profileid", "bidder", "deal")
mockEngine.EXPECT().RecordPartnerTimeoutRequests("pubid", "profileid", "bidder")
mockEngine.EXPECT().RecordCtvUaAccuracy("pubId", "status")
- mockEngine.EXPECT().RecordSendLoggerDataTime("requestType", "profileid", time.Second)
+ mockEngine.EXPECT().RecordSendLoggerDataTime(time.Second)
mockEngine.EXPECT().RecordRequestTime("requestType", time.Second)
mockEngine.EXPECT().RecordOWServerPanic("endpoint", "methodName", "nodeName", "podName")
mockEngine.EXPECT().RecordAmpVideoRequests("pubid", "profileid")
@@ -269,8 +269,8 @@ func TestRecordFunctionForMultiMetricsEngine(t *testing.T) {
multiMetricEngine.RecordBidResponseByDealCountInHB(publisher, profile, aliasBidder, dealId)
multiMetricEngine.RecordPartnerTimeoutInPBS(publisher, profile, aliasBidder)
multiMetricEngine.RecordVideoImpDisabledViaConnTypeStats(publisher, profile)
- multiMetricEngine.RecordGetProfileDataTime(endpoint, profile, getTime)
- multiMetricEngine.RecordSendLoggerDataTime(endpoint, profile, sendTime)
+ multiMetricEngine.RecordGetProfileDataTime(getTime)
+ multiMetricEngine.RecordSendLoggerDataTime(sendTime)
multiMetricEngine.RecordDBQueryFailure(queryType, publisher, profile)
multiMetricEngine.RecordAnalyticsTrackingThrottled(publisher, profile, "logger")
multiMetricEngine.Shutdown()
@@ -281,7 +281,7 @@ func TestRecordFunctionForMultiMetricsEngine(t *testing.T) {
multiMetricEngine.RecordBids("pubid", "profileid", "bidder", "deal")
multiMetricEngine.RecordPartnerTimeoutRequests("pubid", "profileid", "bidder")
multiMetricEngine.RecordCtvUaAccuracy("pubId", "status")
- multiMetricEngine.RecordSendLoggerDataTime("requestType", "profileid", time.Second)
+ multiMetricEngine.RecordSendLoggerDataTime(time.Second)
multiMetricEngine.RecordRequestTime("requestType", time.Second)
multiMetricEngine.RecordOWServerPanic("endpoint", "methodName", "nodeName", "podName")
multiMetricEngine.RecordAmpVideoRequests("pubid", "profileid")
diff --git a/modules/pubmatic/openwrap/metrics/metrics.go b/modules/pubmatic/openwrap/metrics/metrics.go
index 228dee246be..b6a96ca8335 100644
--- a/modules/pubmatic/openwrap/metrics/metrics.go
+++ b/modules/pubmatic/openwrap/metrics/metrics.go
@@ -57,7 +57,7 @@ type MetricsEngine interface {
RecordBidResponseByDealCountInPBS(publisher, profile, aliasBidder, dealId string)
RecordBidResponseByDealCountInHB(publisher, profile, aliasBidder, dealId string)
- RecordGetProfileDataTime(endpoint, profile string, getTime time.Duration)
+ RecordGetProfileDataTime(getTime time.Duration)
RecordDBQueryFailure(queryType, publisher, profile string)
Shutdown()
@@ -70,7 +70,7 @@ type MetricsEngine interface {
RecordPrebidTimeoutRequests(pubid, profileid string)
RecordPartnerTimeoutRequests(pubid, profileid, bidder string)
RecordCtvUaAccuracy(pubId, status string)
- RecordSendLoggerDataTime(requestType, profileid string, sendTime time.Duration)
+ RecordSendLoggerDataTime(sendTime time.Duration)
RecordRequestTime(requestType string, requestTime time.Duration)
RecordOWServerPanic(endpoint, methodName, nodeName, podName string)
RecordAmpVideoRequests(pubid, profileid string)
diff --git a/modules/pubmatic/openwrap/metrics/mock/mock.go b/modules/pubmatic/openwrap/metrics/mock/mock.go
index 3ba1464ac93..270381b7abc 100644
--- a/modules/pubmatic/openwrap/metrics/mock/mock.go
+++ b/modules/pubmatic/openwrap/metrics/mock/mock.go
@@ -252,15 +252,15 @@ func (mr *MockMetricsEngineMockRecorder) RecordDBQueryFailure(arg0, arg1, arg2 i
}
// RecordGetProfileDataTime mocks base method.
-func (m *MockMetricsEngine) RecordGetProfileDataTime(arg0, arg1 string, arg2 time.Duration) {
+func (m *MockMetricsEngine) RecordGetProfileDataTime(arg0 time.Duration) {
m.ctrl.T.Helper()
- m.ctrl.Call(m, "RecordGetProfileDataTime", arg0, arg1, arg2)
+ m.ctrl.Call(m, "RecordGetProfileDataTime", arg0)
}
// RecordGetProfileDataTime indicates an expected call of RecordGetProfileDataTime.
-func (mr *MockMetricsEngineMockRecorder) RecordGetProfileDataTime(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockMetricsEngineMockRecorder) RecordGetProfileDataTime(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordGetProfileDataTime", reflect.TypeOf((*MockMetricsEngine)(nil).RecordGetProfileDataTime), arg0, arg1, arg2)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordGetProfileDataTime", reflect.TypeOf((*MockMetricsEngine)(nil).RecordGetProfileDataTime), arg0)
}
// RecordHTTPCounter mocks base method.
@@ -660,15 +660,15 @@ func (mr *MockMetricsEngineMockRecorder) RecordSSTimeoutRequests(arg0, arg1 inte
}
// RecordSendLoggerDataTime mocks base method.
-func (m *MockMetricsEngine) RecordSendLoggerDataTime(arg0, arg1 string, arg2 time.Duration) {
+func (m *MockMetricsEngine) RecordSendLoggerDataTime(arg0 time.Duration) {
m.ctrl.T.Helper()
- m.ctrl.Call(m, "RecordSendLoggerDataTime", arg0, arg1, arg2)
+ m.ctrl.Call(m, "RecordSendLoggerDataTime", arg0)
}
// RecordSendLoggerDataTime indicates an expected call of RecordSendLoggerDataTime.
-func (mr *MockMetricsEngineMockRecorder) RecordSendLoggerDataTime(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockMetricsEngineMockRecorder) RecordSendLoggerDataTime(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordSendLoggerDataTime", reflect.TypeOf((*MockMetricsEngine)(nil).RecordSendLoggerDataTime), arg0, arg1, arg2)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordSendLoggerDataTime", reflect.TypeOf((*MockMetricsEngine)(nil).RecordSendLoggerDataTime), arg0)
}
// RecordStatsKeyCTVPrebidFailedImpression mocks base method.
diff --git a/modules/pubmatic/openwrap/metrics/prometheus/prometheus.go b/modules/pubmatic/openwrap/metrics/prometheus/prometheus.go
index 60d3baad4c8..dc6cb8cd614 100644
--- a/modules/pubmatic/openwrap/metrics/prometheus/prometheus.go
+++ b/modules/pubmatic/openwrap/metrics/prometheus/prometheus.go
@@ -49,7 +49,8 @@ type Metrics struct {
// publisher-platform-endpoint level metrics
pubPlatformEndpointRequests *prometheus.CounterVec
- getProfileData *prometheus.HistogramVec
+ getProfileData prometheus.Histogram
+ sendLoggerData prometheus.Histogram
dbQueryError *prometheus.CounterVec
@@ -66,7 +67,6 @@ type Metrics struct {
prebidTimeoutRequests *prometheus.CounterVec
partnerTimeoutRequest *prometheus.CounterVec
panicCounts *prometheus.CounterVec
- sendLoggerData *prometheus.HistogramVec
owRequestTime *prometheus.HistogramVec
ampVideoRequests *prometheus.CounterVec
ampVideoResponses *prometheus.CounterVec
@@ -97,7 +97,7 @@ const (
analyticsTypeLabel = "an_type"
)
-var standardTimeBuckets = []float64{0.05, 0.1, 0.15, 0.20, 0.25, 0.3, 0.4, 0.5, 0.75, 1}
+var standardTimeBuckets = []float64{0.1, 0.3, 0.75, 1}
var once sync.Once
var metric *Metrics
@@ -249,10 +249,9 @@ func newMetrics(cfg *config.PrometheusMetrics, promRegistry *prometheus.Registry
[]string{pubIDLabel, platformLabel, endpointLabel},
)
- metrics.getProfileData = newHistogramVec(cfg, promRegistry,
+ metrics.getProfileData = newHistogram(cfg, promRegistry,
"profile_data_get_time",
- "Time taken to get the profile data in seconds", []string{endpointLabel, profileIDLabel},
- standardTimeBuckets)
+ "Time taken to get the profile data in seconds", standardTimeBuckets)
metrics.dbQueryError = newCounter(cfg, promRegistry,
"db_query_failed",
@@ -304,6 +303,19 @@ func newCounter(cfg *config.PrometheusMetrics, registry *prometheus.Registry, na
return counter
}
+func newHistogram(cfg *config.PrometheusMetrics, registry *prometheus.Registry, name, help string, buckets []float64) prometheus.Histogram {
+ opts := prometheus.HistogramOpts{
+ Namespace: cfg.Namespace,
+ Subsystem: cfg.Subsystem,
+ Name: name,
+ Help: help,
+ Buckets: buckets,
+ }
+ histogram := prometheus.NewHistogram(opts)
+ registry.MustRegister(histogram)
+ return histogram
+}
+
func newHistogramVec(cfg *config.PrometheusMetrics, registry *prometheus.Registry, name, help string, labels []string, buckets []float64) *prometheus.HistogramVec {
opts := prometheus.HistogramOpts{
Namespace: cfg.Namespace,
@@ -465,11 +477,8 @@ func (m *Metrics) RecordInjectTrackerErrorCount(adformat, publisherID, partner s
}
// RecordGetProfileDataTime as a noop
-func (m *Metrics) RecordGetProfileDataTime(endpoint, profileID string, getTime time.Duration) {
- m.getProfileData.With(prometheus.Labels{
- endpointLabel: endpoint,
- profileIDLabel: profileID,
- }).Observe(float64(getTime.Seconds()))
+func (m *Metrics) RecordGetProfileDataTime(getTime time.Duration) {
+ m.getProfileData.Observe(float64(getTime.Seconds()))
}
// RecordDBQueryFailure as a noop
diff --git a/modules/pubmatic/openwrap/metrics/prometheus/prometheus_sshb.go b/modules/pubmatic/openwrap/metrics/prometheus/prometheus_sshb.go
index a3cf81a3dd1..d8b9e7506fe 100644
--- a/modules/pubmatic/openwrap/metrics/prometheus/prometheus_sshb.go
+++ b/modules/pubmatic/openwrap/metrics/prometheus/prometheus_sshb.go
@@ -70,10 +70,9 @@ func newSSHBMetrics(metrics *Metrics, cfg *config.PrometheusMetrics, promRegistr
"Count of total requests to header-bidding server labeled by type and status.",
[]string{requestTypeLabel, requestStatusLabel})
- metrics.sendLoggerData = newHistogramVec(cfg, promRegistry,
+ metrics.sendLoggerData = newHistogram(cfg, promRegistry,
"sshb_logger_data_send_time",
- "Time taken to send the wrapper logger body in seconds", []string{endpointLabel, profileIDLabel},
- standardTimeBuckets)
+ "Time taken to send the wrapper logger body in seconds", standardTimeBuckets)
metrics.owRequestTime = newHistogramVec(cfg, promRegistry,
"sshb_request_time",
@@ -182,11 +181,8 @@ func (m *Metrics) RecordCtvUaAccuracy(pubId, status string) {
}
// RecordSendLoggerDataTime as a noop
-func (m *Metrics) RecordSendLoggerDataTime(endpoint, profileID string, sendTime time.Duration) {
- m.sendLoggerData.With(prometheus.Labels{
- endpointLabel: endpoint,
- profileIDLabel: profileID,
- }).Observe(float64(sendTime.Seconds()))
+func (m *Metrics) RecordSendLoggerDataTime(sendTime time.Duration) {
+ m.sendLoggerData.Observe(float64(sendTime.Seconds()))
}
// RecordSendLoggerDataTime as a noop
diff --git a/modules/pubmatic/openwrap/metrics/prometheus/prometheus_sshb_test.go b/modules/pubmatic/openwrap/metrics/prometheus/prometheus_sshb_test.go
index 2fd059d2b25..ae4ebd90a4e 100644
--- a/modules/pubmatic/openwrap/metrics/prometheus/prometheus_sshb_test.go
+++ b/modules/pubmatic/openwrap/metrics/prometheus/prometheus_sshb_test.go
@@ -279,9 +279,8 @@ func TestRecordPartnerTimeoutRequests(t *testing.T) {
func TestRecordSendLoggerDataTime(t *testing.T) {
m := createMetricsForTesting()
- m.RecordSendLoggerDataTime("v25", "59201", 300*time.Millisecond)
- resultingHistogram := getHistogramFromHistogramVecByTwoKeys(m.sendLoggerData,
- endpointLabel, "v25", profileIDLabel, "59201")
+ m.RecordSendLoggerDataTime(300 * time.Millisecond)
+ resultingHistogram := getHistogramFromHistogram(m.sendLoggerData)
assertHistogram(t, "sshb_logger_data_send_time", resultingHistogram, 1, 0.3)
}
diff --git a/modules/pubmatic/openwrap/metrics/prometheus/prometheus_test.go b/modules/pubmatic/openwrap/metrics/prometheus/prometheus_test.go
index 4706136b4c1..9d8abf28cec 100644
--- a/modules/pubmatic/openwrap/metrics/prometheus/prometheus_test.go
+++ b/modules/pubmatic/openwrap/metrics/prometheus/prometheus_test.go
@@ -304,9 +304,8 @@ func TestRecordPublisherResponseTimeStats(t *testing.T) {
func TestRecordGetProfileDataTime(t *testing.T) {
m := createMetricsForTesting()
- m.RecordGetProfileDataTime("v25", "59201", 300*time.Millisecond)
- resultingHistogram := getHistogramFromHistogramVecByTwoKeys(m.getProfileData,
- endpointLabel, "v25", profileIDLabel, "59201")
+ m.RecordGetProfileDataTime(300 * time.Millisecond)
+ resultingHistogram := getHistogramFromHistogram(m.getProfileData)
assertHistogram(t, "sshb_profile_data_get_time", resultingHistogram, 1, 0.3)
}
@@ -336,6 +335,14 @@ func TestRecordHTTPCounter(t *testing.T) {
expectedCount, nil)
}
+func getHistogramFromHistogram(histogram prometheus.Histogram) dto.Histogram {
+ var result dto.Histogram
+ processMetrics(histogram, func(m dto.Metric) {
+ result = *m.GetHistogram()
+ })
+ return result
+}
+
func getHistogramFromHistogramVec(histogram *prometheus.HistogramVec, labelKey, labelValue string) 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 59fbae851b5..e15fb26bf17 100644
--- a/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go
+++ b/modules/pubmatic/openwrap/metrics/stats/tcp_stats.go
@@ -286,7 +286,7 @@ func (st *StatsTCP) RecordCacheErrorRequests(endpoint, publisher, profileID stri
}
}
-func (st *StatsTCP) RecordGetProfileDataTime(requestType, profileid string, getTime time.Duration) {}
+func (st *StatsTCP) RecordGetProfileDataTime(getTime time.Duration) {}
func (st *StatsTCP) RecordDBQueryFailure(queryType, publisher, profile string) {}
@@ -330,20 +330,20 @@ func (st *StatsTCP) Shutdown() {
st.statsClient.ShutdownProcess()
}
-func (st *StatsTCP) RecordRequest(labels metrics.Labels) {}
-func (st *StatsTCP) RecordLurlSent(labels metrics.LurlStatusLabels) {}
-func (st *StatsTCP) RecordLurlBatchSent(labels metrics.LurlBatchStatusLabels) {}
-func (st *StatsTCP) RecordBids(pubid, profileid, biddder, deal string) {}
-func (st *StatsTCP) RecordPartnerTimeoutRequests(pubid, profileid, bidder string) {}
-func (st *StatsTCP) RecordCtvUaAccuracy(pubId, status string) {}
-func (st *StatsTCP) RecordSendLoggerDataTime(requestType, profileid string, sendTime time.Duration) {}
-func (st *StatsTCP) RecordRequestTime(requestType string, requestTime time.Duration) {}
-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) {}
-func (st *StatsTCP) RecordUnwrapRespTime(accountId, wraperCnt string, respTime time.Duration) {}
-func (st *StatsTCP) RecordAnalyticsTrackingThrottled(pubid, profileid, analyticsType string) {}
+func (st *StatsTCP) RecordRequest(labels metrics.Labels) {}
+func (st *StatsTCP) RecordLurlSent(labels metrics.LurlStatusLabels) {}
+func (st *StatsTCP) RecordLurlBatchSent(labels metrics.LurlBatchStatusLabels) {}
+func (st *StatsTCP) RecordBids(pubid, profileid, biddder, deal string) {}
+func (st *StatsTCP) RecordPartnerTimeoutRequests(pubid, profileid, bidder string) {}
+func (st *StatsTCP) RecordCtvUaAccuracy(pubId, status string) {}
+func (st *StatsTCP) RecordSendLoggerDataTime(sendTime time.Duration) {}
+func (st *StatsTCP) RecordRequestTime(requestType string, requestTime time.Duration) {}
+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) {}
+func (st *StatsTCP) RecordUnwrapRespTime(accountId, wraperCnt string, respTime time.Duration) {}
+func (st *StatsTCP) RecordAnalyticsTrackingThrottled(pubid, profileid, analyticsType string) {}
diff --git a/modules/pubmatic/openwrap/models/constants.go b/modules/pubmatic/openwrap/models/constants.go
index 376a4b46824..4c0a5733511 100755
--- a/modules/pubmatic/openwrap/models/constants.go
+++ b/modules/pubmatic/openwrap/models/constants.go
@@ -446,21 +446,23 @@ const (
)
const (
- EndpointV25 = "v25"
- EndpointAMP = "amp"
- EndpintInappVideo = "inappvideo"
- EndpointVideo = "video"
- EndpointJson = "json"
- EndpointORTB = "ortb"
- EndpointVAST = "vast"
- EndpointWebS2S = "webs2s"
- EndPointCTV = "ctv"
- EndpointHybrid = "hybrid"
- Openwrap = "openwrap"
- ImpTypeBanner = "banner"
- ImpTypeVideo = "video"
- ContentTypeSite = "site"
- ContentTypeApp = "app"
+ EndpointV25 = "v25"
+ EndpointAMP = "amp"
+ EndpintInappVideo = "inappvideo"
+ EndpointVideo = "video"
+ EndpointJson = "json"
+ EndpointORTB = "ortb"
+ EndpointVAST = "vast"
+ EndpointWebS2S = "webs2s"
+ EndPointCTV = "ctv"
+ EndpointHybrid = "hybrid"
+ EndpointAppLovinMax = "applovinmax"
+
+ Openwrap = "openwrap"
+ ImpTypeBanner = "banner"
+ ImpTypeVideo = "video"
+ ContentTypeSite = "site"
+ ContentTypeApp = "app"
)
const (
@@ -529,3 +531,12 @@ const (
FeatureAMPMultiFormat = 3
FeatureAnalyticsThrottle = 4
)
+
+// constants for applovinmax requests
+const (
+ Agent = "agent"
+ AppLovinMaxAgent = "max"
+ TypeRewarded = "rewarded"
+ SignalData = "signaldata"
+ OwSspBurl = "owsspburl"
+)
diff --git a/modules/pubmatic/openwrap/models/openwrap.go b/modules/pubmatic/openwrap/models/openwrap.go
index 90b47315275..9467c8cddf5 100644
--- a/modules/pubmatic/openwrap/models/openwrap.go
+++ b/modules/pubmatic/openwrap/models/openwrap.go
@@ -101,6 +101,7 @@ type RequestCtx struct {
IsTBFFeatureEnabled bool
VastUnwrapEnabled bool
VastUnwrapStatsEnabled bool
+ AppLovinMax AppLovinMax
LoggerDisabled bool
TrackerDisabled bool
}
@@ -198,3 +199,7 @@ type FeatureData struct {
Enabled int // feature enabled/disabled
Value string // feature value if any
}
+
+type AppLovinMax struct {
+ Reject bool
+}
diff --git a/modules/pubmatic/openwrap/profiledata.go b/modules/pubmatic/openwrap/profiledata.go
index 5ebc8c76ed5..caeeeee2aef 100644
--- a/modules/pubmatic/openwrap/profiledata.go
+++ b/modules/pubmatic/openwrap/profiledata.go
@@ -19,7 +19,7 @@ func (m OpenWrap) getProfileData(rCtx models.RequestCtx, bidRequest openrtb2.Bid
return getTestModePartnerConfigMap(platform, m.cfg.Timeout.HBTimeout, rCtx.DisplayID), nil
}
- return m.cache.GetPartnerConfigMap(rCtx.PubID, rCtx.ProfileID, rCtx.DisplayID, rCtx.Endpoint)
+ return m.cache.GetPartnerConfigMap(rCtx.PubID, rCtx.ProfileID, rCtx.DisplayID)
}
func getTestModePartnerConfigMap(platform string, timeout int64, displayVersion int) map[int]map[string]string {
diff --git a/modules/pubmatic/openwrap/profiledata_test.go b/modules/pubmatic/openwrap/profiledata_test.go
index dace8c0d505..61d5a34ec91 100644
--- a/modules/pubmatic/openwrap/profiledata_test.go
+++ b/modules/pubmatic/openwrap/profiledata_test.go
@@ -130,7 +130,7 @@ func TestOpenWrap_getProfileData(t *testing.T) {
},
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(5890, 123, 1, models.PLATFORM_APP).Return(
+ mockCache.EXPECT().GetPartnerConfigMap(5890, 123, 1).Return(
map[int]map[string]string{
1: {
models.PARTNER_ID: "2",
@@ -185,7 +185,7 @@ func TestOpenWrap_getProfileData(t *testing.T) {
},
},
setup: func() {
- mockCache.EXPECT().GetPartnerConfigMap(5890, 123, 1, models.PLATFORM_APP).Return(
+ mockCache.EXPECT().GetPartnerConfigMap(5890, 123, 1).Return(
nil, fmt.Errorf("error GetPartnerConfigMap"))
},
want: nil,
diff --git a/modules/pubmatic/openwrap/tracker/banner.go b/modules/pubmatic/openwrap/tracker/banner.go
index 3ac1ba0262e..b092c2e5bdb 100644
--- a/modules/pubmatic/openwrap/tracker/banner.go
+++ b/modules/pubmatic/openwrap/tracker/banner.go
@@ -9,7 +9,11 @@ import (
"github.com/prebid/prebid-server/v2/openrtb_ext"
)
-func injectBannerTracker(rctx models.RequestCtx, tracker models.OWTracker, bid openrtb2.Bid, seat string, pixels []adunitconfig.UniversalPixel) string {
+func injectBannerTracker(rctx models.RequestCtx, tracker models.OWTracker, bid openrtb2.Bid, seat string, pixels []adunitconfig.UniversalPixel) (string, string) {
+ if rctx.Endpoint == models.EndpointAppLovinMax {
+ return bid.AdM, getBURL(bid.BURL, tracker.TrackerURL)
+ }
+
var replacedTrackerStr, trackerFormat string
trackerFormat = models.TrackerCallWrap
if trackerWithOM(tracker, rctx.Platform, seat) {
@@ -17,7 +21,7 @@ func injectBannerTracker(rctx models.RequestCtx, tracker models.OWTracker, bid o
}
replacedTrackerStr = strings.Replace(trackerFormat, "${escapedUrl}", tracker.TrackerURL, 1)
adm := applyTBFFeature(rctx, bid, replacedTrackerStr)
- return appendUPixelinBanner(adm, pixels)
+ return appendUPixelinBanner(adm, pixels), bid.BURL
}
// append universal pixels in creative based on conditions
diff --git a/modules/pubmatic/openwrap/tracker/banner_test.go b/modules/pubmatic/openwrap/tracker/banner_test.go
index 345b1c29a22..c72f6c6b4e0 100644
--- a/modules/pubmatic/openwrap/tracker/banner_test.go
+++ b/modules/pubmatic/openwrap/tracker/banner_test.go
@@ -18,10 +18,30 @@ func Test_injectBannerTracker(t *testing.T) {
pixels []adunitconfig.UniversalPixel
}
tests := []struct {
- name string
- args args
- want string
+ name string
+ args args
+ wantAdm string
+ wantBurl string
}{
+ {
+ name: "endpoint_applovinmax",
+ args: args{
+ rctx: models.RequestCtx{
+ Platform: models.PLATFORM_APP,
+ Endpoint: models.EndpointAppLovinMax,
+ },
+ tracker: models.OWTracker{
+ TrackerURL: `sample.com/track?tid=1234`,
+ },
+ bid: openrtb2.Bid{
+ AdM: `
`,
+ BURL: `http://burl.com`,
+ },
+ seat: "pubmatic",
+ },
+ wantAdm: ``,
+ wantBurl: `sample.com/track?tid=1234&owsspburl=http://burl.com`,
+ },
{
name: "app_platform",
args: args{
@@ -36,7 +56,7 @@ func Test_injectBannerTracker(t *testing.T) {
},
seat: "test",
},
- want: `sample_creative`,
+ wantAdm: `sample_creative`,
},
{
name: "app_platform_OM_Inactive_pubmatic",
@@ -53,7 +73,7 @@ func Test_injectBannerTracker(t *testing.T) {
},
seat: models.BidderPubMatic,
},
- want: `sample_creative`,
+ wantAdm: `sample_creative`,
},
{
name: "app_platform_OM_Active_pubmatic",
@@ -70,7 +90,7 @@ func Test_injectBannerTracker(t *testing.T) {
},
seat: models.BidderPubMatic,
},
- want: `sample_creative`,
+ wantAdm: `sample_creative`,
},
{
name: "tbf_feature_enabled",
@@ -87,14 +107,14 @@ func Test_injectBannerTracker(t *testing.T) {
AdM: `sample_creative`,
},
},
- want: `sample_creative`,
+ wantAdm: `sample_creative`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- if got := injectBannerTracker(tt.args.rctx, tt.args.tracker, tt.args.bid, tt.args.seat, tt.args.pixels); got != tt.want {
- t.Errorf("injectBannerTracker() = %v, want %v", got, tt.want)
- }
+ gotAdm, gotBurl := injectBannerTracker(tt.args.rctx, tt.args.tracker, tt.args.bid, tt.args.seat, tt.args.pixels)
+ assert.Equal(t, tt.wantAdm, gotAdm)
+ assert.Equal(t, tt.wantBurl, gotBurl)
})
}
}
diff --git a/modules/pubmatic/openwrap/tracker/inject.go b/modules/pubmatic/openwrap/tracker/inject.go
index 47d63afd41c..06cb70c25e3 100644
--- a/modules/pubmatic/openwrap/tracker/inject.go
+++ b/modules/pubmatic/openwrap/tracker/inject.go
@@ -31,13 +31,13 @@ func InjectTrackers(rctx models.RequestCtx, bidResponse *openrtb2.BidResponse) (
switch adformat {
case models.Banner:
- bidResponse.SeatBid[i].Bid[j].AdM = injectBannerTracker(rctx, tracker, bid, seatBid.Seat, pixels)
+ bidResponse.SeatBid[i].Bid[j].AdM, bidResponse.SeatBid[i].Bid[j].BURL = injectBannerTracker(rctx, tracker, bid, seatBid.Seat, pixels)
case models.Video:
trackers := []models.OWTracker{tracker}
- bidResponse.SeatBid[i].Bid[j].AdM, err = injectVideoCreativeTrackers(bid, trackers)
+ bidResponse.SeatBid[i].Bid[j].AdM, bidResponse.SeatBid[i].Bid[j].BURL, err = injectVideoCreativeTrackers(rctx, bid, trackers)
case models.Native:
if impBidCtx, ok := rctx.ImpBidCtx[bid.ImpID]; ok {
- bidResponse.SeatBid[i].Bid[j].AdM, err = injectNativeCreativeTrackers(impBidCtx.Native, bid.AdM, tracker)
+ bidResponse.SeatBid[i].Bid[j].AdM, bidResponse.SeatBid[i].Bid[j].BURL, err = injectNativeCreativeTrackers(impBidCtx.Native, bid, tracker, rctx.Endpoint)
} else {
errMsg = fmt.Sprintf("native obj not found for impid %s", bid.ImpID)
}
@@ -81,3 +81,15 @@ func getUniversalPixels(rctx models.RequestCtx, adformat string, bidderCode stri
}
return pixels
}
+
+func getBURL(burl, trackerURL string) string {
+ if trackerURL == "" {
+ return burl
+ }
+
+ if burl == "" {
+ return trackerURL
+ }
+
+ return trackerURL + "&" + models.OwSspBurl + "=" + burl
+}
diff --git a/modules/pubmatic/openwrap/tracker/inject_test.go b/modules/pubmatic/openwrap/tracker/inject_test.go
index 0738228b7d5..97c054f5f0c 100644
--- a/modules/pubmatic/openwrap/tracker/inject_test.go
+++ b/modules/pubmatic/openwrap/tracker/inject_test.go
@@ -1,15 +1,14 @@
package tracker
import (
- "reflect"
"testing"
"github.com/golang/mock/gomock"
- "github.com/magiconair/properties/assert"
"github.com/prebid/openrtb/v20/openrtb2"
mock_metrics "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics/mock"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models/adunitconfig"
+ "github.com/stretchr/testify/assert"
)
func TestInjectTrackers(t *testing.T) {
@@ -516,6 +515,143 @@ func TestInjectTrackers(t *testing.T) {
},
wantErr: false,
},
+ {
+ name: "adformat_is_banner_and_AppLovinMax_request",
+ args: args{
+ rctx: models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ Platform: "",
+ Trackers: map[string]models.OWTracker{
+ "12345": {
+ BidType: "banner",
+ TrackerURL: `Tracking URL`,
+ },
+ },
+ },
+ bidResponse: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "12345",
+ BURL: `http://burl.com`,
+ AdM: ``,
+ },
+ },
+ },
+ },
+ },
+ },
+ want: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "12345",
+ BURL: `Tracking URL&owsspburl=http://burl.com`,
+ AdM: ``,
+ },
+ },
+ },
+ },
+ },
+ wantErr: false,
+ },
+ {
+ name: "adformat_is_video_and_AppLovinMax_request",
+ args: args{
+ rctx: models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ Platform: "",
+ Trackers: map[string]models.OWTracker{
+ "12345": {
+ BidType: "video",
+ TrackerURL: `Tracking URL`,
+ ErrorURL: `Error URL`,
+ },
+ },
+ },
+ bidResponse: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "12345",
+ BURL: `http://burl.com`,
+ AdM: ``,
+ },
+ },
+ },
+ },
+ },
+ },
+ want: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "12345",
+ BURL: `Tracking URL&owsspburl=http://burl.com`,
+ AdM: ``,
+ },
+ },
+ },
+ },
+ },
+ wantErr: false,
+ },
+ {
+ name: "adformat_is_native_and_AppLovinMax_request",
+ args: args{
+ rctx: models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ Platform: models.PLATFORM_APP,
+ Trackers: map[string]models.OWTracker{
+ "12345": {
+ BidType: "native",
+ TrackerURL: `Tracking URL`,
+ ErrorURL: `Error URL`,
+ },
+ },
+ ImpBidCtx: map[string]models.ImpCtx{
+ "imp123": {
+ Native: &openrtb2.Native{
+ Request: "{\"context\":1,\"plcmttype\":1,\"eventtrackers\":[{\"event\":1,\"methods\":[1]}],\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"required\":0,\"img\":{\"type\":3,\"w\":300,\"h\":250}},{\"id\":1,\"required\":0,\"data\":{\"type\":1,\"len\":2}},{\"id\":2,\"required\":0,\"img\":{\"type\":1,\"w\":50,\"h\":50}},{\"id\":3,\"required\":0,\"title\":{\"len\":80}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":2}}]}",
+ },
+ },
+ },
+ },
+ bidResponse: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "12345",
+ ImpID: "imp123",
+ BURL: `http://burl.com`,
+ AdM: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}]}`,
+ },
+ },
+ },
+ },
+ },
+ },
+ want: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "12345",
+ ImpID: "imp123",
+ BURL: `Tracking URL&owsspburl=http://burl.com`,
+ AdM: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}]}`,
+ },
+ },
+ },
+ },
+ },
+ wantErr: false,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -527,9 +663,7 @@ func TestInjectTrackers(t *testing.T) {
t.Errorf("InjectTrackers() error = %v, wantErr %v", err, tt.wantErr)
return
}
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("InjectTrackers() = %v, want %v", got, tt.want)
- }
+ assert.Equal(t, got, tt.want, tt.name)
})
}
}
@@ -715,3 +849,46 @@ func Test_getUniversalPixels(t *testing.T) {
})
}
}
+
+func Test_getBurlAppLovinMax(t *testing.T) {
+ type args struct {
+ burl string
+ TrackerURL string
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {
+ name: "empty_burl",
+ args: args{
+ burl: "",
+ TrackerURL: `sample.com`,
+ },
+ want: `sample.com`,
+ },
+ {
+ name: "empty_tracker_url",
+ args: args{
+ burl: `sample.com`,
+ TrackerURL: "",
+ },
+ want: `sample.com`,
+ },
+ {
+ name: "valid_burl_and_tracker_url",
+ args: args{
+ burl: `sampleBurl.com`,
+ TrackerURL: `sampleTracker.com?id=123`,
+ },
+ want: `sampleTracker.com?id=123&owsspburl=sampleBurl.com`,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := getBURL(tt.args.burl, tt.args.TrackerURL)
+ assert.Equal(t, got, tt.want)
+ })
+ }
+}
diff --git a/modules/pubmatic/openwrap/tracker/native.go b/modules/pubmatic/openwrap/tracker/native.go
index 1999699e24c..8d9e2ede379 100644
--- a/modules/pubmatic/openwrap/tracker/native.go
+++ b/modules/pubmatic/openwrap/tracker/native.go
@@ -11,12 +11,17 @@ import (
)
// Inject TrackerCall in Native Adm
-func injectNativeCreativeTrackers(native *openrtb2.Native, adm string, tracker models.OWTracker) (string, error) {
+func injectNativeCreativeTrackers(native *openrtb2.Native, bid openrtb2.Bid, tracker models.OWTracker, endpoint string) (string, string, error) {
+ adm := bid.AdM
+ var err error
+ if endpoint == models.EndpointAppLovinMax {
+ return adm, getBURL(bid.BURL, tracker.TrackerURL), nil
+ }
if native == nil {
- return adm, errors.New("native object is missing")
+ return adm, bid.BURL, errors.New("native object is missing")
}
if len(native.Request) == 0 {
- return adm, errors.New("native request is empty")
+ return adm, bid.BURL, errors.New("native request is empty")
}
setTrackerURL := false
callback := func(value []byte, dataType jsonparser.ValueType, offset int, err error) {
@@ -31,9 +36,10 @@ func injectNativeCreativeTrackers(native *openrtb2.Native, adm string, tracker m
jsonparser.ArrayEach([]byte(native.Request), callback, models.EventTrackers)
if setTrackerURL {
- return adm, nil
+ return adm, bid.BURL, nil
}
- return injectNativeImpressionTracker(&adm, tracker)
+ adm, err = injectNativeImpressionTracker(&adm, tracker)
+ return adm, bid.BURL, err
}
// inject tracker in EventTracker Object
diff --git a/modules/pubmatic/openwrap/tracker/native_test.go b/modules/pubmatic/openwrap/tracker/native_test.go
index 078ef4ec3a1..3c8a030d445 100644
--- a/modules/pubmatic/openwrap/tracker/native_test.go
+++ b/modules/pubmatic/openwrap/tracker/native_test.go
@@ -6,41 +6,64 @@ import (
"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
"github.com/prebid/prebid-server/v2/util/ptrutil"
+ "github.com/stretchr/testify/assert"
)
func Test_injectNativeCreativeTrackers(t *testing.T) {
type args struct {
- native *openrtb2.Native
- adm string
- tracker models.OWTracker
+ native *openrtb2.Native
+ bid openrtb2.Bid
+ tracker models.OWTracker
+ endpoint string
}
tests := []struct {
- name string
- args args
- want string
- wantErr bool
+ name string
+ args args
+ wantAdm string
+ wantBurl string
+ wantErr bool
}{
+ {
+ name: "AppLovinMax_endpoint_request",
+ args: args{
+ native: &openrtb2.Native{},
+ bid: openrtb2.Bid{
+ BURL: `http://burl.com`,
+ AdM: ``,
+ },
+ tracker: models.OWTracker{
+ TrackerURL: `t.pubmatic.com/track?tid=1234`,
+ },
+ endpoint: models.EndpointAppLovinMax,
+ },
+ wantBurl: `t.pubmatic.com/track?tid=1234&owsspburl=http://burl.com`,
+ wantAdm: ``,
+ wantErr: false,
+ },
{
name: "native_object_nil",
args: args{
- adm: `creative`,
+ bid: openrtb2.Bid{
+ AdM: `creative`,
+ },
tracker: models.OWTracker{
TrackerURL: `Tracking URL`,
},
},
- want: `creative`,
+ wantAdm: `creative`,
wantErr: true,
},
{
name: "empty_native_object",
args: args{
native: &openrtb2.Native{},
- adm: `creative`,
- tracker: models.OWTracker{
+ bid: openrtb2.Bid{
+ AdM: `creative`,
+ }, tracker: models.OWTracker{
TrackerURL: `Tracking URL`,
},
},
- want: `creative`,
+ wantAdm: `creative`,
wantErr: true,
},
{
@@ -49,12 +72,13 @@ func Test_injectNativeCreativeTrackers(t *testing.T) {
native: &openrtb2.Native{
Request: `request`,
},
- adm: `creative`,
- tracker: models.OWTracker{
+ bid: openrtb2.Bid{
+ AdM: `creative`,
+ }, tracker: models.OWTracker{
TrackerURL: `Tracking URL`,
},
},
- want: `creative`,
+ wantAdm: `creative`,
wantErr: true,
},
{
@@ -63,12 +87,14 @@ func Test_injectNativeCreativeTrackers(t *testing.T) {
native: &openrtb2.Native{
Request: "{\"context\":1,\"plcmttype\":1,\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"required\":0,\"img\":{\"type\":3,\"w\":300,\"h\":250}},{\"id\":1,\"required\":0,\"data\":{\"type\":1,\"len\":2}},{\"id\":2,\"required\":0,\"img\":{\"type\":1,\"w\":50,\"h\":50}},{\"id\":3,\"required\":0,\"title\":{\"len\":80}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":2}}]}",
},
- adm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}]}`,
+ bid: openrtb2.Bid{
+ AdM: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}]}`,
+ },
tracker: models.OWTracker{
TrackerURL: `Tracking URL`,
},
},
- want: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35","Tracking URL"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}]}`,
+ wantAdm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35","Tracking URL"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}]}`,
wantErr: false,
},
{
@@ -77,12 +103,14 @@ func Test_injectNativeCreativeTrackers(t *testing.T) {
native: &openrtb2.Native{
Request: "{\"context\":1,\"plcmttype\":1,\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"required\":0,\"img\":{\"type\":3,\"w\":300,\"h\":250}},{\"id\":1,\"required\":0,\"data\":{\"type\":1,\"len\":2}},{\"id\":2,\"required\":0,\"img\":{\"type\":1,\"w\":50,\"h\":50}},{\"id\":3,\"required\":0,\"title\":{\"len\":80}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":2}}]}",
},
- adm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}]}`,
+ bid: openrtb2.Bid{
+ AdM: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}]}`,
+ },
tracker: models.OWTracker{
TrackerURL: `Tracking URL`,
},
},
- want: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}],"imptrackers":["Tracking URL"]}`,
+ wantAdm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}],"imptrackers":["Tracking URL"]}`,
wantErr: false,
},
{
@@ -91,12 +119,14 @@ func Test_injectNativeCreativeTrackers(t *testing.T) {
native: &openrtb2.Native{
Request: "{\"context\":1,\"plcmttype\":1,\"eventtrackers\":[{\"event\":1,\"methods\":[2]}],\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"required\":0,\"img\":{\"type\":3,\"w\":300,\"h\":250}},{\"id\":1,\"required\":0,\"data\":{\"type\":1,\"len\":2}},{\"id\":2,\"required\":0,\"img\":{\"type\":1,\"w\":50,\"h\":50}},{\"id\":3,\"required\":0,\"title\":{\"len\":80}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":2}}]}",
},
- adm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":2,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet.js"}]}`,
+ bid: openrtb2.Bid{
+ AdM: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":2,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet.js"}]}`,
+ },
tracker: models.OWTracker{
TrackerURL: `Tracking URL`,
},
},
- want: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":2,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet.js"}],"imptrackers":["Tracking URL"]}`,
+ wantAdm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":2,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet.js"}],"imptrackers":["Tracking URL"]}`,
wantErr: false,
},
{
@@ -105,12 +135,14 @@ func Test_injectNativeCreativeTrackers(t *testing.T) {
native: &openrtb2.Native{
Request: "{\"context\":1,\"plcmttype\":1,\"eventtrackers\":[{\"event\":2,\"methods\":[1]}],\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"required\":0,\"img\":{\"type\":3,\"w\":300,\"h\":250}},{\"id\":1,\"required\":0,\"data\":{\"type\":1,\"len\":2}},{\"id\":2,\"required\":0,\"img\":{\"type\":1,\"w\":50,\"h\":50}},{\"id\":3,\"required\":0,\"title\":{\"len\":80}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":2}}]}",
},
- adm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["abc.com"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":2,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet.php"}]}`,
+ bid: openrtb2.Bid{
+ AdM: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["abc.com"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":2,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet.php"}]}`,
+ },
tracker: models.OWTracker{
TrackerURL: `Tracking URL`,
},
},
- want: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["abc.com","Tracking URL"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":2,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet.php"}]}`,
+ wantAdm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["abc.com","Tracking URL"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":2,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet.php"}]}`,
wantErr: false,
},
{
@@ -119,12 +151,14 @@ func Test_injectNativeCreativeTrackers(t *testing.T) {
native: &openrtb2.Native{
Request: "{\"context\":1,\"plcmttype\":1,\"eventtrackers\":[{\"event\":1,\"methods\":[1]}],\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"required\":0,\"img\":{\"type\":3,\"w\":300,\"h\":250}},{\"id\":1,\"required\":0,\"data\":{\"type\":1,\"len\":2}},{\"id\":2,\"required\":0,\"img\":{\"type\":1,\"w\":50,\"h\":50}},{\"id\":3,\"required\":0,\"title\":{\"len\":80}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":2}}]}",
},
- adm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}]}`,
+ bid: openrtb2.Bid{
+ AdM: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}]}`,
+ },
tracker: models.OWTracker{
TrackerURL: `Tracking URL`,
},
},
- want: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"},{"event":1,"method":1,"url":"Tracking URL"}]}`,
+ wantAdm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"},{"event":1,"method":1,"url":"Tracking URL"}]}`,
wantErr: false,
},
{
@@ -133,12 +167,14 @@ func Test_injectNativeCreativeTrackers(t *testing.T) {
native: &openrtb2.Native{
Request: "{\"context\":1,\"plcmttype\":1,\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}],\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"required\":0,\"img\":{\"type\":3,\"w\":300,\"h\":250}},{\"id\":1,\"required\":0,\"data\":{\"type\":1,\"len\":2}},{\"id\":2,\"required\":0,\"img\":{\"type\":1,\"w\":50,\"h\":50}},{\"id\":3,\"required\":0,\"title\":{\"len\":80}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":2}}]}",
},
- adm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}]}`,
+ bid: openrtb2.Bid{
+ AdM: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"}]}`,
+ },
tracker: models.OWTracker{
TrackerURL: `Tracking URL`,
},
},
- want: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"},{"event":1,"method":1,"url":"Tracking URL"}]}`,
+ wantAdm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"},{"event":1,"method":1,"url":"Tracking URL"}]}`,
wantErr: false,
},
{
@@ -147,12 +183,14 @@ func Test_injectNativeCreativeTrackers(t *testing.T) {
native: &openrtb2.Native{
Request: "{\"context\":1,\"plcmttype\":1,\"eventtrackers\":[{\"event\":1,\"methods\":[1]}],\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"required\":0,\"img\":{\"type\":3,\"w\":300,\"h\":250}},{\"id\":1,\"required\":0,\"data\":{\"type\":1,\"len\":2}},{\"id\":2,\"required\":0,\"img\":{\"type\":1,\"w\":50,\"h\":50}},{\"id\":3,\"required\":0,\"title\":{\"len\":80}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":2}}]}",
},
- adm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e"}`,
+ bid: openrtb2.Bid{
+ AdM: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e"}`,
+ },
tracker: models.OWTracker{
TrackerURL: `Tracking URL`,
},
},
- want: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"Tracking URL"}]}`,
+ wantAdm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"Tracking URL"}]}`,
wantErr: false,
},
{
@@ -161,25 +199,26 @@ func Test_injectNativeCreativeTrackers(t *testing.T) {
native: &openrtb2.Native{
Request: "{\"context\":1,\"plcmttype\":1,\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}],\"ver\":\"1.2\",\"assets\":[{\"id\":0,\"required\":0,\"img\":{\"type\":3,\"w\":300,\"h\":250}},{\"id\":1,\"required\":0,\"data\":{\"type\":1,\"len\":2}},{\"id\":2,\"required\":0,\"img\":{\"type\":1,\"w\":50,\"h\":50}},{\"id\":3,\"required\":0,\"title\":{\"len\":80}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":2}}]}",
},
- adm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"},{"event":1,"method":1,"url":"abc.com"}]}`,
+ bid: openrtb2.Bid{
+ AdM: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"},{"event":1,"method":1,"url":"abc.com"}]}`,
+ },
tracker: models.OWTracker{
TrackerURL: `Tracking URL`,
},
},
- want: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"},{"event":1,"method":1,"url":"abc.com"},{"event":1,"method":1,"url":"Tracking URL"}]}`,
+ wantAdm: `{"assets":[{"id":0,"img":{"type":3,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":1,"data":{"type":1,"value":"Sponsored By PubMatic"}},{"id":2,"img":{"type":1,"url":"//sample.com/AdTag/native/728x90.png","w":728,"h":90}},{"id":3,"title":{"text":"Native Test Title"}},{"id":4,"data":{"type":2,"value":"Sponsored By PubMatic"}}],"link":{"url":"//www.sample.com","clicktrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"fallback":"http://www.sample.com"},"imptrackers":["http://sampletracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35"],"jstracker":"\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e\u003cscript src='\\/\\/sample.com\\/AdTag\\/native\\/tempReseponse.js'\u003e","eventtrackers":[{"event":1,"method":1,"url":"http://sample.com/AdServer/AdDisplayTrackerServlet"},{"event":1,"method":1,"url":"abc.com"},{"event":1,"method":1,"url":"Tracking URL"}]}`,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- got, err := injectNativeCreativeTrackers(tt.args.native, tt.args.adm, tt.args.tracker)
+ gotAdm, gotBurl, err := injectNativeCreativeTrackers(tt.args.native, tt.args.bid, tt.args.tracker, tt.args.endpoint)
if (err != nil) != tt.wantErr {
t.Errorf("injectNativeCreativeTrackers() error = %v, wantErr %v", err, tt.wantErr)
return
}
- if got != tt.want {
- t.Errorf("injectNativeCreativeTrackers() = %v, want %v", got, tt.want)
- }
+ assert.Equal(t, tt.wantAdm, gotAdm, tt.name)
+ assert.Equal(t, tt.wantBurl, gotBurl, tt.name)
})
}
}
diff --git a/modules/pubmatic/openwrap/tracker/video.go b/modules/pubmatic/openwrap/tracker/video.go
index 72a0150bdc4..09f75afb3a8 100644
--- a/modules/pubmatic/openwrap/tracker/video.go
+++ b/modules/pubmatic/openwrap/tracker/video.go
@@ -11,28 +11,38 @@ import (
)
// Inject Trackers in Video Creative
-func injectVideoCreativeTrackers(bid openrtb2.Bid, videoParams []models.OWTracker) (string, error) {
+func injectVideoCreativeTrackers(rctx models.RequestCtx, bid openrtb2.Bid, videoParams []models.OWTracker) (string, string, error) {
if bid.AdM == "" || len(videoParams) == 0 {
- return "", errors.New("bid is nil or tracker data is missing")
+ return "", bid.BURL, errors.New("bid is nil or tracker data is missing")
+ }
+
+ injectImpressionTracker := true
+ if rctx.Endpoint == models.EndpointAppLovinMax {
+ injectImpressionTracker = false
}
originalCreativeStr := bid.AdM
if strings.HasPrefix(originalCreativeStr, models.HTTPProtocol) {
originalCreativeStr = strings.Replace(models.VastWrapper, models.PartnerURLPlaceholder, originalCreativeStr, -1)
- originalCreativeStr = strings.Replace(originalCreativeStr, models.TrackerPlaceholder, videoParams[0].TrackerURL, -1)
+ if injectImpressionTracker {
+ originalCreativeStr = strings.Replace(originalCreativeStr, models.TrackerPlaceholder, videoParams[0].TrackerURL, -1)
+ } else {
+ originalCreativeStr = strings.Replace(originalCreativeStr, models.VASTImpressionURLTemplate, "", -1)
+ bid.BURL = getBURL(bid.BURL, videoParams[0].TrackerURL)
+ }
originalCreativeStr = strings.Replace(originalCreativeStr, models.ErrorPlaceholder, videoParams[0].ErrorURL, -1)
bid.AdM = originalCreativeStr
} else {
originalCreativeStr = strings.TrimSpace(originalCreativeStr)
doc := etree.NewDocument()
if err := doc.ReadFromString(originalCreativeStr); err != nil {
- return bid.AdM, errors.New("invalid creative format")
+ return bid.AdM, bid.BURL, errors.New("invalid creative format")
}
//Check VAST Object
vast := doc.Element.FindElement(models.VideoVASTTag)
if vast == nil {
- return bid.AdM, errors.New("VAST Tag Not Found")
+ return bid.AdM, bid.BURL, errors.New("VAST Tag Not Found")
}
//GetVersion
@@ -44,19 +54,23 @@ func injectVideoCreativeTrackers(bid openrtb2.Bid, videoParams []models.OWTracke
element := adElement.FindElement(models.AdWrapperElement)
isWrapper := (nil != element)
- if nil == element {
+ if element == nil {
element = adElement.FindElement(models.AdInlineElement)
}
- if nil == element {
- return bid.AdM, errors.New("video creative not in required VAST format")
+ if element == nil {
+ return bid.AdM, bid.BURL, errors.New("video creative not in required VAST format")
}
if len(videoParams[i].TrackerURL) > 0 {
// set tracker URL
- newElement := etree.NewElement(models.ImpressionElement)
- newElement.SetText(videoParams[i].TrackerURL)
- element.InsertChild(element.SelectElement(models.ImpressionElement), newElement)
+ if injectImpressionTracker {
+ newElement := etree.NewElement(models.ImpressionElement)
+ newElement.SetText(videoParams[i].TrackerURL)
+ element.InsertChild(element.SelectElement(models.ImpressionElement), newElement)
+ } else {
+ bid.BURL = getBURL(bid.BURL, videoParams[i].TrackerURL)
+ }
}
if len(videoParams[i].ErrorURL) > 0 {
@@ -66,7 +80,7 @@ func injectVideoCreativeTrackers(bid openrtb2.Bid, videoParams []models.OWTracke
element.InsertChild(element.SelectElement(models.ErrorElement), newElement)
}
- if false == isWrapper && videoParams[i].Price != 0 {
+ if !isWrapper && videoParams[i].Price != 0 {
if models.VideoVASTVersion2_0 == version {
injectPricingNodeVAST20(element, videoParams[i].Price, videoParams[i].PriceModel, videoParams[i].PriceCurrency)
} else {
@@ -78,11 +92,11 @@ func injectVideoCreativeTrackers(bid openrtb2.Bid, videoParams []models.OWTracke
updatedVastStr, err := doc.WriteToString()
if err != nil {
- return bid.AdM, err
+ return bid.AdM, bid.BURL, err
}
- return updatedVastStr, nil
+ return updatedVastStr, bid.BURL, nil
}
- return bid.AdM, nil
+ return bid.AdM, bid.BURL, nil
}
func injectPricingNodeVAST20(parent *etree.Element, price float64, model string, currency string) {
diff --git a/modules/pubmatic/openwrap/tracker/video_test.go b/modules/pubmatic/openwrap/tracker/video_test.go
index b69b4776010..1b3c188b3b9 100644
--- a/modules/pubmatic/openwrap/tracker/video_test.go
+++ b/modules/pubmatic/openwrap/tracker/video_test.go
@@ -9,16 +9,18 @@ import (
"github.com/stretchr/testify/assert"
)
-func Test_injectVideoCreativeTrackers(t *testing.T) {
+func TestInjectVideoCreativeTrackers(t *testing.T) {
type args struct {
bid openrtb2.Bid
videoParams []models.OWTracker
+ rctx models.RequestCtx
}
tests := []struct {
- name string
- args args
- want string
- wantErr bool
+ name string
+ args args
+ wantAdm string
+ wantBurl string
+ wantErr bool
}{
{
name: "empty_bid",
@@ -31,7 +33,7 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
},
},
- want: ``,
+ wantAdm: ``,
wantErr: true,
},
{
@@ -46,7 +48,7 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
},
},
- want: ``,
+ wantAdm: ``,
wantErr: true,
},
{
@@ -63,7 +65,7 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
},
},
- want: ``,
+ wantAdm: ``,
wantErr: true,
},
{
@@ -80,7 +82,7 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
},
},
- want: `PubMatic Wrapper`,
+ wantAdm: `PubMatic Wrapper`,
wantErr: false,
},
{
@@ -92,7 +94,7 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
videoParams: []models.OWTracker{},
},
- want: ``,
+ wantAdm: ``,
wantErr: true,
},
{
@@ -109,7 +111,7 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
},
},
- want: `invalid_vast_creative`,
+ wantAdm: `invalid_vast_creative`,
wantErr: true,
},
{
@@ -126,7 +128,7 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
},
},
- want: ``,
+ wantAdm: ``,
wantErr: true,
},
{
@@ -144,7 +146,7 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
},
},
- want: ``,
+ wantAdm: ``,
wantErr: false,
},
{
@@ -162,7 +164,7 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
},
},
- want: ``,
+ wantAdm: ``,
wantErr: false,
},
{
@@ -180,7 +182,7 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
},
},
- want: ``,
+ wantAdm: ``,
wantErr: false,
},
{
@@ -198,7 +200,7 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
},
},
- want: ``,
+ wantAdm: ``,
wantErr: false,
},
{
@@ -216,7 +218,7 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
},
},
- want: ``,
+ wantAdm: ``,
wantErr: false,
},
{
@@ -234,7 +236,7 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
},
},
- want: ``,
+ wantAdm: ``,
wantErr: false,
},
{
@@ -251,20 +253,179 @@ func Test_injectVideoCreativeTrackers(t *testing.T) {
},
},
},
- want: ``,
+ wantAdm: ``,
wantErr: false,
},
+ {
+ name: "vast_2.0_inline_pricing_with_EndpointAppLovinMax",
+ args: args{
+
+ bid: openrtb2.Bid{
+ AdM: ``,
+ BURL: "https://burl.com",
+ },
+ videoParams: []models.OWTracker{
+ {
+ TrackerURL: `Tracking URL`,
+ ErrorURL: `Error URL`,
+ Price: 1.2,
+ },
+ },
+ rctx: models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ },
+ },
+ wantBurl: "Tracking URL&owsspburl=https://burl.com",
+ wantAdm: ``,
+ wantErr: false,
+ },
+ {
+ name: "vast_3.0_inline_pricing_with_EndpointAppLovinMax",
+ args: args{
+
+ bid: openrtb2.Bid{
+ AdM: ``,
+ BURL: "https://burl.com",
+ },
+ videoParams: []models.OWTracker{
+ {
+ TrackerURL: `Tracker URL`,
+ ErrorURL: `Error URL`,
+ Price: 1.2,
+ },
+ },
+ rctx: models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ },
+ },
+ wantBurl: "Tracker URL&owsspburl=https://burl.com",
+ wantAdm: ``,
+ wantErr: false,
+ },
+ {
+ name: "inline_vast_3.0_with_EndpointAppLovinMax",
+ args: args{
+
+ bid: openrtb2.Bid{
+ BURL: "https://burl.com",
+ AdM: `Acudeo CompatibleVAST 2.0 Instream Test 1VAST 2.0 Instream Test 1https://dsptracker.com/{PSPM}00:00:04https://www.sample.com`,
+ },
+ videoParams: []models.OWTracker{
+ {
+ TrackerURL: `Tracker URL`,
+ ErrorURL: `Error URL`,
+ Price: 1.2,
+ },
+ },
+ rctx: models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ },
+ },
+ wantBurl: "Tracker URL&owsspburl=https://burl.com",
+ wantAdm: ``,
+ wantErr: false,
+ },
+ {
+ name: "wrapper_vast_2.0_with_EndpointAppLovinMax",
+ args: args{
+
+ bid: openrtb2.Bid{
+ BURL: "https://burl.com",
+ AdM: `DSP`,
+ },
+ videoParams: []models.OWTracker{
+ {
+ TrackerURL: `Tracker URL`,
+ ErrorURL: `Error URL`,
+ Price: 1.2,
+ },
+ },
+ rctx: models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ },
+ },
+ wantBurl: "Tracker URL&owsspburl=https://burl.com",
+ wantAdm: ``,
+ wantErr: false,
+ },
+ {
+ name: "inline_vast_with_no_cdata_and_EndpointAppLovinMax",
+ args: args{
+
+ bid: openrtb2.Bid{
+ BURL: "https://burl.com",
+ AdM: `Acudeo CompatibleVAST 2.0 Instream Test 1VAST 2.0 Instream Test 1http://172.16.4.213/AdServer/AdDisplayTrackerServlethttps://dsptracker.com/{PSPM}http://172.16.4.213/trackhttps://Errortrack.com00:00:04http://172.16.4.213/trackhttps://www.sample.comhttps://stagingnyc.pubmatic.com:8443/video/Shashank/mediaFileHost/media/mp4-sample-1.mp4]https://stagingnyc.pubmatic.com:8443/video/Shashank/mediaFileHost/media/mp4-sample-2.mp4]`,
+ },
+ videoParams: []models.OWTracker{
+ {
+ TrackerURL: `Tracker URL`,
+ ErrorURL: `Error URL`,
+ Price: 1.2,
+ },
+ },
+ rctx: models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ },
+ },
+ wantBurl: "Tracker URL&owsspburl=https://burl.com",
+ wantAdm: ``,
+ wantErr: false,
+ },
+ {
+ name: "wrapper_vast_with_no_cdata_and_EndpointAppLovinMax",
+ args: args{
+
+ bid: openrtb2.Bid{
+ BURL: "https://burl.com",
+ AdM: `DSPhttps://stagingnyc.pubmatic.com:8443/test/pub_vast.xmlhttps://track.dsp.com/er=[ERRORCODE]/tracker/errorhttps://track.dsp.com?e=impressionhttp://track.dsp.com/tracker/click`,
+ },
+ videoParams: []models.OWTracker{
+ {
+ TrackerURL: `Tracker URL`,
+ ErrorURL: `Error URL`,
+ Price: 1.2,
+ },
+ },
+ rctx: models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ },
+ },
+ wantBurl: "Tracker URL&owsspburl=https://burl.com",
+ wantAdm: ``,
+ wantErr: false,
+ },
+ {
+ name: "spaces_in_creative_with_EndpointAppLovinMax",
+ args: args{
+
+ bid: openrtb2.Bid{
+ BURL: "https://burl.com",
+ AdM: ` `,
+ },
+ videoParams: []models.OWTracker{
+ {
+ TrackerURL: `Tracker URL`,
+ ErrorURL: `Error URL`,
+ },
+ },
+ rctx: models.RequestCtx{
+ Endpoint: models.EndpointAppLovinMax,
+ },
+ },
+ wantBurl: "Tracker URL&owsspburl=https://burl.com",
+ wantAdm: ``,
+ wantErr: false,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- got, err := injectVideoCreativeTrackers(tt.args.bid, tt.args.videoParams)
+ gotAdm, gotBurl, err := injectVideoCreativeTrackers(tt.args.rctx, tt.args.bid, tt.args.videoParams)
if (err != nil) != tt.wantErr {
t.Errorf("injectVideoCreativeTrackers() error = %v, wantErr %v", err, tt.wantErr)
return
}
- if got != tt.want {
- t.Errorf("injectVideoCreativeTrackers() = %v, want %v", got, tt.want)
- }
+ assert.Equal(t, tt.wantAdm, gotAdm, tt.name)
+ assert.Equal(t, tt.wantBurl, gotBurl, tt.name)
})
}
}