From f6609aaa4cf0493c0f658aa487d740a69816350a Mon Sep 17 00:00:00 2001 From: pm-avinash-kapre <112699665+AvinashKapre@users.noreply.github.com> Date: Mon, 8 Apr 2024 11:49:48 +0530 Subject: [PATCH 1/5] UOE-10232: AmpMultiformat feature level control (#740) * UOE-10232: Feature level support for AMP-multiformat * Dependancy injection * test cases and refactor * remove unnecessary query * expose feature instache for sshb * import fix * null string scan handle * updated test cases * test update 2 * review comment * review changes2 --- Makefile | 6 +- .../pubmatic/openwrap/auctionresponsehook.go | 2 +- .../openwrap/auctionresponsehook_test.go | 46 ++- .../pubmatic/openwrap/beforevalidationhook.go | 4 +- .../openwrap/beforevalidationhook_test.go | 69 +++- modules/pubmatic/openwrap/cache/cache.go | 4 +- .../cache/gocache/fullscreenclickability.go | 11 - .../gocache/fullscreenclickability_test.go | 80 ----- .../cache/gocache/publisher_feature.go | 19 + .../cache/gocache/publisher_feature_test.go | 112 ++++++ .../cache/gocache/tracking_beacon_first.go | 12 - .../gocache/tracking_beacon_first_test.go | 42 --- modules/pubmatic/openwrap/cache/mock/mock.go | 88 ++--- modules/pubmatic/openwrap/config/config.go | 3 +- .../pubmatic/openwrap/database/database.go | 3 +- .../pubmatic/openwrap/database/mock/mock.go | 84 ++--- .../openwrap/database/mock_driver/mock.go | 63 ++-- .../database/mysql/fullscreenclickability.go | 17 - .../mysql/fullscreenclickability_test.go | 89 ----- .../database/mysql/publisher_feature.go | 34 ++ .../database/mysql/publisher_feature_test.go | 132 +++++++ .../database/mysql/tracking_beacon_first.go | 40 --- .../mysql/tracking_beacon_first_test.go | 167 --------- .../fullscreenclickability.go | 103 ------ .../fullscreenclickability_test.go | 297 --------------- .../fullscreenclickability/reloader.go | 37 -- .../fullscreenclickability/reloader_test.go | 58 --- modules/pubmatic/openwrap/models/constants.go | 10 +- modules/pubmatic/openwrap/models/openwrap.go | 19 +- modules/pubmatic/openwrap/openwrap.go | 13 +- modules/pubmatic/openwrap/openwrap_sshb.go | 6 + .../publisherfeature/ampmultiformat.go | 36 ++ .../publisherfeature/ampmultiformat_test.go | 129 +++++++ .../openwrap/publisherfeature/feature.go | 7 + .../fullscreenclickability.go | 66 ++++ .../fullscreenclickability_test.go | 338 ++++++++++++++++++ .../openwrap/publisherfeature/mock/mock.go | 75 ++++ .../openwrap/publisherfeature/reloader.go | 100 ++++++ .../publisherfeature/reloader_test.go | 266 ++++++++++++++ .../pubmatic/openwrap/publisherfeature/tbf.go | 87 +++++ .../openwrap/publisherfeature/tbf_test.go | 283 +++++++++++++++ modules/pubmatic/openwrap/targeting.go | 5 +- modules/pubmatic/openwrap/tbf/tbf.go | 133 ------- modules/pubmatic/openwrap/tbf/tbf_test.go | 232 ------------ modules/pubmatic/openwrap/tracker/banner.go | 3 +- .../pubmatic/openwrap/tracker/banner_test.go | 38 +- .../pubmatic/openwrap/tracker/inject_test.go | 7 +- 47 files changed, 1940 insertions(+), 1535 deletions(-) create mode 100644 modules/pubmatic/openwrap/cache/gocache/publisher_feature.go create mode 100644 modules/pubmatic/openwrap/cache/gocache/publisher_feature_test.go delete mode 100644 modules/pubmatic/openwrap/cache/gocache/tracking_beacon_first.go delete mode 100644 modules/pubmatic/openwrap/cache/gocache/tracking_beacon_first_test.go create mode 100644 modules/pubmatic/openwrap/database/mysql/publisher_feature.go create mode 100644 modules/pubmatic/openwrap/database/mysql/publisher_feature_test.go delete mode 100644 modules/pubmatic/openwrap/database/mysql/tracking_beacon_first.go delete mode 100644 modules/pubmatic/openwrap/database/mysql/tracking_beacon_first_test.go delete mode 100644 modules/pubmatic/openwrap/fullscreenclickability/fullscreenclickability.go delete mode 100644 modules/pubmatic/openwrap/fullscreenclickability/fullscreenclickability_test.go delete mode 100644 modules/pubmatic/openwrap/fullscreenclickability/reloader.go delete mode 100644 modules/pubmatic/openwrap/fullscreenclickability/reloader_test.go create mode 100644 modules/pubmatic/openwrap/publisherfeature/ampmultiformat.go create mode 100644 modules/pubmatic/openwrap/publisherfeature/ampmultiformat_test.go create mode 100644 modules/pubmatic/openwrap/publisherfeature/feature.go create mode 100644 modules/pubmatic/openwrap/publisherfeature/fullscreenclickability.go create mode 100644 modules/pubmatic/openwrap/publisherfeature/fullscreenclickability_test.go create mode 100644 modules/pubmatic/openwrap/publisherfeature/mock/mock.go create mode 100644 modules/pubmatic/openwrap/publisherfeature/reloader.go create mode 100644 modules/pubmatic/openwrap/publisherfeature/reloader_test.go create mode 100644 modules/pubmatic/openwrap/publisherfeature/tbf.go create mode 100644 modules/pubmatic/openwrap/publisherfeature/tbf_test.go delete mode 100644 modules/pubmatic/openwrap/tbf/tbf.go delete mode 100644 modules/pubmatic/openwrap/tbf/tbf_test.go diff --git a/Makefile b/Makefile index 402bfa10a96..a8a6fc6204e 100644 --- a/Makefile +++ b/Makefile @@ -55,4 +55,8 @@ mockgenmetrics: mockgenlogger: mkdir -p analytics/pubmatic/mhttp/mock - mockgen github.com/PubMatic-OpenWrap/prebid-server/analytics/pubmatic/mhttp HttpCallInterface,MultiHttpContextInterface > analytics/pubmatic/mhttp/mock/mock.go \ No newline at end of file + mockgen github.com/PubMatic-OpenWrap/prebid-server/analytics/pubmatic/mhttp HttpCallInterface,MultiHttpContextInterface > analytics/pubmatic/mhttp/mock/mock.go + +mockgenpublisherfeature: + mkdir -p modules/pubmatic/openwrap/publisherfeature + mockgen github.com/PubMatic-OpenWrap/prebid-server/modules/pubmatic/openwrap/publisherfeature Feature > modules/pubmatic/openwrap/publisherfeature/mock/mock.go \ No newline at end of file diff --git a/modules/pubmatic/openwrap/auctionresponsehook.go b/modules/pubmatic/openwrap/auctionresponsehook.go index ac35e6aaea9..a32e3e727be 100644 --- a/modules/pubmatic/openwrap/auctionresponsehook.go +++ b/modules/pubmatic/openwrap/auctionresponsehook.go @@ -225,7 +225,7 @@ func (m OpenWrap) handleAuctionResponseHook( addLostToDealBidNonBRCode(&rctx) } - droppedBids, warnings := addPWTTargetingForBid(rctx, payload.BidResponse) + droppedBids, warnings := m.addPWTTargetingForBid(rctx, payload.BidResponse) if len(droppedBids) != 0 { rctx.DroppedBids = droppedBids } diff --git a/modules/pubmatic/openwrap/auctionresponsehook_test.go b/modules/pubmatic/openwrap/auctionresponsehook_test.go index 251aa9316e4..b5d8a8ecfb7 100644 --- a/modules/pubmatic/openwrap/auctionresponsehook_test.go +++ b/modules/pubmatic/openwrap/auctionresponsehook_test.go @@ -14,7 +14,7 @@ import ( mock_metrics "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics/mock" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models/nbr" - "github.com/prebid/prebid-server/modules/pubmatic/openwrap/tbf" + mock_feature "github.com/prebid/prebid-server/modules/pubmatic/openwrap/publisherfeature/mock" "github.com/prebid/prebid-server/openrtb_ext" "github.com/prebid/prebid-server/util/ptrutil" "github.com/stretchr/testify/assert" @@ -134,6 +134,7 @@ func TestSeatNonBidsInHandleAuctionResponseHook(t *testing.T) { func TestNonBRCodesInHandleAuctionResponseHook(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() + mockFeature := mock_feature.NewMockFeature(ctrl) type args struct { ctx context.Context @@ -186,6 +187,8 @@ func TestNonBRCodesInHandleAuctionResponseHook(t *testing.T) { mockEngine := mock_metrics.NewMockMetricsEngine(ctrl) mockEngine.EXPECT().RecordPublisherResponseTimeStats("5890", gomock.Any()) mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "pubmatic") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false) return mockEngine }, want: want{ @@ -270,6 +273,8 @@ func TestNonBRCodesInHandleAuctionResponseHook(t *testing.T) { mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "pubmatic") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "appnexus") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "rubicon") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false) return mockEngine }, want: want{ @@ -380,6 +385,8 @@ func TestNonBRCodesInHandleAuctionResponseHook(t *testing.T) { mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "pubmatic") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "appnexus") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "rubicon") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false) return mockEngine }, want: want{ @@ -470,6 +477,8 @@ func TestNonBRCodesInHandleAuctionResponseHook(t *testing.T) { mockEngine := mock_metrics.NewMockMetricsEngine(ctrl) mockEngine.EXPECT().RecordPublisherResponseTimeStats("5890", gomock.Any()) mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "pubmatic") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false) return mockEngine }, want: want{ @@ -555,6 +564,8 @@ func TestNonBRCodesInHandleAuctionResponseHook(t *testing.T) { mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "pubmatic") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "appnexus") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "rubicon") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false) return mockEngine }, want: want{ @@ -666,6 +677,8 @@ func TestNonBRCodesInHandleAuctionResponseHook(t *testing.T) { mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "pubmatic") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "appnexus") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "rubicon") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false) return mockEngine }, want: want{ @@ -778,6 +791,8 @@ func TestNonBRCodesInHandleAuctionResponseHook(t *testing.T) { mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "pubmatic") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "appnexus") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "rubicon") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false) return mockEngine }, want: want{ @@ -890,6 +905,8 @@ func TestNonBRCodesInHandleAuctionResponseHook(t *testing.T) { mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "pubmatic") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "appnexus") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "rubicon") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false) return mockEngine }, want: want{ @@ -1002,6 +1019,8 @@ func TestNonBRCodesInHandleAuctionResponseHook(t *testing.T) { mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "pubmatic") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "appnexus") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "rubicon") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false) return mockEngine }, want: want{ @@ -1058,7 +1077,8 @@ func TestNonBRCodesInHandleAuctionResponseHook(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { o := OpenWrap{ - metricEngine: tt.getMetricsEngine(), + metricEngine: tt.getMetricsEngine(), + featureConfig: mockFeature, } hookResult, _ := o.handleAuctionResponseHook(tt.args.ctx, tt.args.moduleCtx, tt.args.payload) mutations := hookResult.ChangeSet.Mutations() @@ -1073,6 +1093,7 @@ func TestNonBRCodesInHandleAuctionResponseHook(t *testing.T) { func TestPrebidTargetingInHandleAuctionResponseHook(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() + mockFeature := mock_feature.NewMockFeature(ctrl) type args struct { ctx context.Context @@ -1150,6 +1171,8 @@ func TestPrebidTargetingInHandleAuctionResponseHook(t *testing.T) { mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "pubmatic") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "appnexus") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "rubicon") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false) return mockEngine }, want: want{ @@ -1273,6 +1296,8 @@ func TestPrebidTargetingInHandleAuctionResponseHook(t *testing.T) { mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "pubmatic") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "appnexus") mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("", "5890", "rubicon") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false) return mockEngine }, want: want{ @@ -1335,7 +1360,8 @@ func TestPrebidTargetingInHandleAuctionResponseHook(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { o := OpenWrap{ - metricEngine: tt.getMetricsEngine(), + metricEngine: tt.getMetricsEngine(), + featureConfig: mockFeature, } hookResult, _ := o.handleAuctionResponseHook(tt.args.ctx, tt.args.moduleCtx, tt.args.payload) mutations := hookResult.ChangeSet.Mutations() @@ -1419,7 +1445,6 @@ func TestResetBidIdtoOriginal(t *testing.T) { func TestAuctionResponseHookForEndpointWebS2S(t *testing.T) { ctrl := gomock.NewController(t) mockCache := mock_cache.NewMockCache(ctrl) - tbf.SetAndResetTBFConfig(mockCache, nil) defer ctrl.Finish() type args struct { @@ -1568,8 +1593,8 @@ func TestAuctionResponseHookForEndpointWebS2S(t *testing.T) { func TestOpenWrap_handleAuctionResponseHook(t *testing.T) { ctrl := gomock.NewController(t) mockCache := mock_cache.NewMockCache(ctrl) - tbf.SetAndResetTBFConfig(mockCache, nil) defer ctrl.Finish() + mockFeature := mock_feature.NewMockFeature(ctrl) type want struct { result hookstage.HookResult[hookstage.AuctionResponsePayload] @@ -1684,6 +1709,8 @@ func TestOpenWrap_handleAuctionResponseHook(t *testing.T) { mockEngine := mock_metrics.NewMockMetricsEngine(ctrl) mockEngine.EXPECT().RecordNobidErrPrebidServerResponse("5890") mockEngine.EXPECT().RecordPublisherResponseTimeStats("5890", gomock.Any()) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false) return mockEngine }, want: want{ @@ -1766,6 +1793,8 @@ func TestOpenWrap_handleAuctionResponseHook(t *testing.T) { mockEngine.EXPECT().RecordPartnerResponseTimeStats("5890", "pubmatic", 8) mockEngine.EXPECT().RecordPublisherResponseTimeStats("5890", gomock.Any()) mockEngine.EXPECT().RecordPublisherPartnerNoCookieStats("5890", gomock.Any()).AnyTimes() + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false) return mockEngine }, doMutate: true, @@ -1858,6 +1887,8 @@ func TestOpenWrap_handleAuctionResponseHook(t *testing.T) { mockEngine.EXPECT().RecordPartnerResponseTimeStats("5890", "pubmatic", 8) mockEngine.EXPECT().RecordPublisherResponseTimeStats("5890", gomock.Any()) mockEngine.EXPECT().RecordPublisherPartnerNoCookieStats("5890", gomock.Any()).AnyTimes() + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mockFeature.EXPECT().IsFscApplicable(gomock.Any(), gomock.Any(), gomock.Any()).Return(false).AnyTimes() return mockEngine }, doMutate: true, @@ -1875,8 +1906,9 @@ func TestOpenWrap_handleAuctionResponseHook(t *testing.T) { mockEngine = tt.setup() } m := OpenWrap{ - cache: mockCache, - metricEngine: mockEngine, + cache: mockCache, + metricEngine: mockEngine, + featureConfig: mockFeature, } moduleCtx, ok := tt.args.moduleCtx.ModuleContext["rctx"] if ok { diff --git a/modules/pubmatic/openwrap/beforevalidationhook.go b/modules/pubmatic/openwrap/beforevalidationhook.go index 6e275bd19b9..7cf6ef95598 100644 --- a/modules/pubmatic/openwrap/beforevalidationhook.go +++ b/modules/pubmatic/openwrap/beforevalidationhook.go @@ -88,6 +88,8 @@ func (m OpenWrap) handleBeforeValidationHook( rCtx.DeviceCtx.Platform = getDevicePlatform(rCtx, payload.BidRequest) populateDeviceContext(&rCtx.DeviceCtx, payload.BidRequest.Device) + rCtx.IsTBFFeatureEnabled = m.featureConfig.IsTBFFeatureEnabled(rCtx.PubID, rCtx.ProfileID) + if rCtx.UidCookie == nil { m.metricEngine.RecordUidsCookieNotPresentErrorStats(rCtx.PubIDStr, rCtx.ProfileIDStr) } @@ -247,7 +249,7 @@ func (m OpenWrap) handleBeforeValidationHook( } } videoAdUnitCtx = adunitconfig.UpdateVideoObjectWithAdunitConfig(rCtx, imp, div, payload.BidRequest.Device.ConnectionType) - if rCtx.Endpoint == models.EndpointAMP && isVideoEnabledForAMP(videoAdUnitCtx.AppliedSlotAdUnitConfig) { + if rCtx.Endpoint == models.EndpointAMP && m.featureConfig.IsAmpMultiformatEnabled(rCtx.PubID) && isVideoEnabledForAMP(videoAdUnitCtx.AppliedSlotAdUnitConfig) { //Iniitalized local imp.Video object to update macros and get mappings in case of AMP request rCtx.AmpVideoEnabled = true imp.Video = &openrtb2.Video{} diff --git a/modules/pubmatic/openwrap/beforevalidationhook_test.go b/modules/pubmatic/openwrap/beforevalidationhook_test.go index b02681db00b..24523b619af 100644 --- a/modules/pubmatic/openwrap/beforevalidationhook_test.go +++ b/modules/pubmatic/openwrap/beforevalidationhook_test.go @@ -23,6 +23,7 @@ import ( "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models/adunitconfig" modelsAdunitConfig "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models/adunitconfig" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models/nbr" + mock_feature "github.com/prebid/prebid-server/modules/pubmatic/openwrap/publisherfeature/mock" "github.com/prebid/prebid-server/openrtb_ext" "github.com/prebid/prebid-server/util/ptrutil" "github.com/stretchr/testify/assert" @@ -1101,6 +1102,10 @@ func TestOpenWrap_applyProfileChanges(t *testing.T) { } func TestOpenWrap_applyVideoAdUnitConfig(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mockFeature := mock_feature.NewMockFeature(ctrl) + type fields struct { cfg config.Config cache cache.Cache @@ -1550,6 +1555,7 @@ func TestOpenWrap_applyVideoAdUnitConfig(t *testing.T) { }, }, rCtx: models.RequestCtx{ + PubID: 5890, ImpBidCtx: map[string]models.ImpCtx{ "testImp": { VideoAdUnitCtx: models.AdUnitCtx{ @@ -1611,6 +1617,7 @@ func TestOpenWrap_applyVideoAdUnitConfig(t *testing.T) { }, }, rCtx: models.RequestCtx{ + PubID: 5890, ImpBidCtx: map[string]models.ImpCtx{ "testImp": { VideoAdUnitCtx: models.AdUnitCtx{ @@ -1657,6 +1664,7 @@ func TestOpenWrap_applyVideoAdUnitConfig(t *testing.T) { }, }, rCtx: models.RequestCtx{ + PubID: 5890, ImpBidCtx: map[string]models.ImpCtx{ "testImp": { VideoAdUnitCtx: models.AdUnitCtx{ @@ -1698,6 +1706,7 @@ func TestOpenWrap_applyVideoAdUnitConfig(t *testing.T) { }, }, rCtx: models.RequestCtx{ + PubID: 5890, ImpBidCtx: map[string]models.ImpCtx{ "testImp": { VideoAdUnitCtx: models.AdUnitCtx{ @@ -1717,9 +1726,10 @@ func TestOpenWrap_applyVideoAdUnitConfig(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { m := &OpenWrap{ - cfg: tt.fields.cfg, - cache: tt.fields.cache, - metricEngine: tt.fields.metricEngine, + cfg: tt.fields.cfg, + cache: tt.fields.cache, + metricEngine: tt.fields.metricEngine, + featureConfig: mockFeature, } m.applyVideoAdUnitConfig(tt.args.rCtx, tt.args.imp) assert.Equal(t, tt.args.imp, tt.want.imp, "Imp video is not upadted as expected from adunit config") @@ -2111,6 +2121,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { defer ctrl.Finish() mockCache := mock_cache.NewMockCache(ctrl) mockEngine := mock_metrics.NewMockMetricsEngine(ctrl) + mockFeature := mock_feature.NewMockFeature(ctrl) adapters.InitBidders("./static/bidder-params/") type fields struct { @@ -2254,6 +2265,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234") mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.InvalidRequestExt)) mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.InvalidRequestExt)) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: true, @@ -2298,6 +2310,8 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.InvalidProfileConfiguration)) mockEngine.EXPECT().RecordPublisherInvalidProfileRequests(rctx.Endpoint, "5890", rctx.ProfileIDStr) mockEngine.EXPECT().RecordPublisherInvalidProfileImpressions("5890", rctx.ProfileIDStr, gomock.Any()) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) + }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: true, @@ -2329,6 +2343,8 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.InvalidProfileConfiguration)) mockEngine.EXPECT().RecordPublisherInvalidProfileRequests(rctx.Endpoint, "5890", rctx.ProfileIDStr) mockEngine.EXPECT().RecordPublisherInvalidProfileImpressions("5890", rctx.ProfileIDStr, gomock.Any()) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) + }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: true, @@ -2372,6 +2388,8 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.InvalidPlatform)) mockEngine.EXPECT().RecordPublisherInvalidProfileRequests(rctx.Endpoint, "5890", rctx.ProfileIDStr) mockEngine.EXPECT().RecordPublisherInvalidProfileImpressions("5890", rctx.ProfileIDStr, gomock.Any()) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) + }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: true, @@ -2416,6 +2434,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.AllPartnerThrottled)) mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.AllPartnerThrottled)) mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: true, @@ -2460,6 +2479,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.InvalidImpressionTagID)) mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.InvalidImpressionTagID)) mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: true, @@ -2508,6 +2528,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordBadRequests(models.EndpointWebS2S, getPubmaticErrorCode(nbr.InvalidImpressionTagID)) mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.InvalidImpressionTagID)) mockEngine.EXPECT().RecordPublisherRequests(models.EndpointWebS2S, "5890", rctx.Platform) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: true, @@ -2552,6 +2573,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.InternalError)) mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.InternalError)) mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: true, @@ -2640,6 +2662,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform) mockEngine.EXPECT().RecordImpDisabledViaConfigStats(models.ImpTypeVideo, "5890", "1234") mockEngine.EXPECT().RecordImpDisabledViaConfigStats(models.ImpTypeBanner, "5890", "1234") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: true, @@ -2742,6 +2765,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordPlatformPublisherPartnerReqStats(rctx.Platform, "5890", "appnexus") mockEngine.EXPECT().RecordImpDisabledViaConfigStats(models.ImpTypeVideo, "5890", "1234") mockEngine.EXPECT().RecordImpDisabledViaConfigStats(models.ImpTypeBanner, "5890", "1234") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: false, @@ -2818,6 +2842,8 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.ServerSidePartnerNotConfigured)) mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.ServerSidePartnerNotConfigured)) mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) + }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: true, @@ -2927,6 +2953,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordPlatformPublisherPartnerReqStats(rctx.Platform, "5890", "pub2-alias") mockEngine.EXPECT().RecordPlatformPublisherPartnerReqStats(rctx.Platform, "5890", "appnexus") mockEngine.EXPECT().RecordPlatformPublisherPartnerReqStats(rctx.Platform, "5890", "dm-alias") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: false, @@ -3017,6 +3044,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234") mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform) mockEngine.EXPECT().RecordPlatformPublisherPartnerReqStats(rctx.Platform, "5890", "appnexus") + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: false, @@ -3087,6 +3115,7 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { ModuleContext: hookstage.ModuleContext{ "rctx": models.RequestCtx{ ProfileID: 1234, + PubID: 5890, DisplayID: 1, SSAuction: -1, Platform: "amp", @@ -3174,6 +3203,8 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234") mockEngine.EXPECT().RecordPublisherRequests(models.EndpointAMP, "5890", "amp") mockEngine.EXPECT().RecordPlatformPublisherPartnerReqStats("amp", "5890", "appnexus") + mockFeature.EXPECT().IsAmpMultiformatEnabled(5890).Return(true) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: hookstage.HookResult[hookstage.BeforeValidationRequestPayload]{ Reject: false, @@ -3193,9 +3224,10 @@ func TestOpenWrapHandleBeforeValidationHook(t *testing.T) { tt.setup() } m := OpenWrap{ - cfg: tt.fields.cfg, - cache: tt.fields.cache, - metricEngine: tt.fields.metricEngine, + cfg: tt.fields.cfg, + cache: tt.fields.cache, + metricEngine: tt.fields.metricEngine, + featureConfig: mockFeature, } bidrequest := &openrtb2.BidRequest{} @@ -3236,6 +3268,7 @@ func TestUserAgent_handleBeforeValidationHook(t *testing.T) { defer ctrl.Finish() mockCache := mock_cache.NewMockCache(ctrl) mockEngine := mock_metrics.NewMockMetricsEngine(ctrl) + mockFeature := mock_feature.NewMockFeature(ctrl) type fields struct { cfg config.Config @@ -3278,6 +3311,8 @@ func TestUserAgent_handleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234") mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.InvalidRequestExt)) mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.InvalidRequestExt)) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) + }, want: want{ rctx: &models.RequestCtx{ @@ -3305,6 +3340,7 @@ func TestUserAgent_handleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234") mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.InvalidRequestExt)) mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.InvalidRequestExt)) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: want{ rctx: &models.RequestCtx{ @@ -3322,9 +3358,10 @@ func TestUserAgent_handleBeforeValidationHook(t *testing.T) { } adapters.InitBidders("./static/bidder-params/") m := OpenWrap{ - cfg: tt.fields.cfg, - cache: tt.fields.cache, - metricEngine: tt.fields.metricEngine, + cfg: tt.fields.cfg, + cache: tt.fields.cache, + metricEngine: tt.fields.metricEngine, + featureConfig: mockFeature, } tt.args.payload.BidRequest = &openrtb2.BidRequest{} json.Unmarshal(tt.args.bidrequest, tt.args.payload.BidRequest) @@ -3344,6 +3381,7 @@ func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) { defer ctrl.Finish() mockCache := mock_cache.NewMockCache(ctrl) mockEngine := mock_metrics.NewMockMetricsEngine(ctrl) + mockFeature := mock_feature.NewMockFeature(ctrl) type fields struct { cfg config.Config cache cache.Cache @@ -3401,6 +3439,7 @@ func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.InvalidProfileConfiguration)) mockEngine.EXPECT().RecordPublisherInvalidProfileRequests(rctx.Endpoint, "5890", rctx.ProfileIDStr) mockEngine.EXPECT().RecordPublisherInvalidProfileImpressions("5890", rctx.ProfileIDStr, gomock.Any()) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: want{ rctx: &models.RequestCtx{ @@ -3452,6 +3491,8 @@ func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.InvalidPlatform)) mockEngine.EXPECT().RecordPublisherInvalidProfileRequests(rctx.Endpoint, "5890", rctx.ProfileIDStr) mockEngine.EXPECT().RecordPublisherInvalidProfileImpressions("5890", rctx.ProfileIDStr, gomock.Any()) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) + }, want: want{ rctx: &models.RequestCtx{ @@ -3504,6 +3545,7 @@ func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.AllPartnerThrottled)) mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.AllPartnerThrottled)) mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: want{ error: false, @@ -3556,6 +3598,7 @@ func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.InvalidImpressionTagID)) mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.InvalidImpressionTagID)) mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: want{ rctx: &models.RequestCtx{ @@ -3600,6 +3643,7 @@ func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) { mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.InternalError)) mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", int(nbr.InternalError)) mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform) + mockFeature.EXPECT().IsTBFFeatureEnabled(gomock.Any(), gomock.Any()).Return(false) }, want: want{ rctx: &models.RequestCtx{ @@ -3616,9 +3660,10 @@ func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) { } adapters.InitBidders("./static/bidder-params/") m := OpenWrap{ - cfg: tt.fields.cfg, - cache: tt.fields.cache, - metricEngine: tt.fields.metricEngine, + cfg: tt.fields.cfg, + cache: tt.fields.cache, + metricEngine: tt.fields.metricEngine, + featureConfig: mockFeature, } tt.args.payload.BidRequest = &openrtb2.BidRequest{} json.Unmarshal(tt.args.bidrequest, tt.args.payload.BidRequest) diff --git a/modules/pubmatic/openwrap/cache/cache.go b/modules/pubmatic/openwrap/cache/cache.go index 3298225ca5c..392e56e9055 100644 --- a/modules/pubmatic/openwrap/cache/cache.go +++ b/modules/pubmatic/openwrap/cache/cache.go @@ -13,10 +13,8 @@ type Cache interface { GetSlotToHashValueMapFromCacheV25(rctx models.RequestCtx, partnerID int) models.SlotMappingInfo GetPublisherVASTTagsFromCache(pubID int) models.PublisherVASTTags - GetFSCDisabledPublishers() (map[int]struct{}, error) GetFSCThresholdPerDSP() (map[int]int, error) - - GetTBFTrafficForPublishers() (map[int]map[int]int, error) + GetPublisherFeatureMap() (map[int]map[int]models.FeatureData, error) Set(key string, value interface{}) Get(key string) (interface{}, bool) diff --git a/modules/pubmatic/openwrap/cache/gocache/fullscreenclickability.go b/modules/pubmatic/openwrap/cache/gocache/fullscreenclickability.go index a9bf8864b43..fd17754c7d0 100644 --- a/modules/pubmatic/openwrap/cache/gocache/fullscreenclickability.go +++ b/modules/pubmatic/openwrap/cache/gocache/fullscreenclickability.go @@ -7,20 +7,9 @@ import ( ) var ( - errorFscPubMsg = "[ErrorFscPubUpdate]:%w" errorFscDspMsg = "[ErrorFscDspUpdate]:%w" ) -// Populates Cache with Fsc-Disabled Publishers -func (c *cache) GetFSCDisabledPublishers() (map[int]struct{}, error) { - fscDisabledPublishers, err := c.db.GetFSCDisabledPublishers() - if err != nil { - c.metricEngine.RecordDBQueryFailure(models.AllFscDisabledPublishersQuery, "", "") - return fscDisabledPublishers, fmt.Errorf(errorFscPubMsg, err) - } - return fscDisabledPublishers, nil -} - // Populates cache with Fsc-Dsp Threshold Percentages func (c *cache) GetFSCThresholdPerDSP() (map[int]int, error) { fscThreshold, err := c.db.GetFSCThresholdPerDSP() diff --git a/modules/pubmatic/openwrap/cache/gocache/fullscreenclickability_test.go b/modules/pubmatic/openwrap/cache/gocache/fullscreenclickability_test.go index 2ad4f577830..52b40fb721c 100644 --- a/modules/pubmatic/openwrap/cache/gocache/fullscreenclickability_test.go +++ b/modules/pubmatic/openwrap/cache/gocache/fullscreenclickability_test.go @@ -15,86 +15,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestGetFSCDisabledPublishers(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockDatabase := mock_database.NewMockDatabase(ctrl) - mockEngine := mock_metrics.NewMockMetricsEngine(ctrl) - type fields struct { - Map sync.Map - cache *gocache.Cache - cfg config.Cache - db database.Database - } - tests := []struct { - name string - want map[int]struct{} - wantErr bool - setup func() - fields fields - }{ - { - name: "Valid Data present in DB, return same", - want: map[int]struct{}{ - 5890: {}, - 5891: {}, - }, - setup: func() { - mockDatabase.EXPECT().GetFSCDisabledPublishers().Return(map[int]struct{}{ - 5890: {}, - 5891: {}, - }, nil) - }, - fields: fields{ - cache: gocache.New(100, 100), - db: mockDatabase, - cfg: config.Cache{ - CacheDefaultExpiry: 1000, - }, - }, - wantErr: false, - }, - { - name: "Error In DB, Set Empty", - want: map[int]struct{}{}, - setup: func() { - mockDatabase.EXPECT().GetFSCDisabledPublishers().Return(map[int]struct{}{}, errors.New("QUERY FAILED")) - mockEngine.EXPECT().RecordDBQueryFailure(models.AllFscDisabledPublishersQuery, "", "").Return() - }, - fields: fields{ - cache: gocache.New(100, 100), - db: mockDatabase, - cfg: config.Cache{ - CacheDefaultExpiry: 1000, - }, - }, - wantErr: true, - }, - } - for ind := range tests { - tt := &tests[ind] - t.Run(tt.name, func(t *testing.T) { - if tt.setup != nil { - tt.setup() - } - c := &cache{ - cache: tt.fields.cache, - cfg: tt.fields.cfg, - db: tt.fields.db, - metricEngine: mockEngine, - } - got, err := c.GetFSCDisabledPublishers() - if (err != nil) != tt.wantErr { - t.Errorf("mySqlDB.GetFSCDisabledPublishers() error = %v, wantErr %v", err, tt.wantErr) - return - } - assert.Equal(t, tt.want, got) - - }) - } -} - func TestGetFSCThresholdPerDSP(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() diff --git a/modules/pubmatic/openwrap/cache/gocache/publisher_feature.go b/modules/pubmatic/openwrap/cache/gocache/publisher_feature.go new file mode 100644 index 00000000000..3bc27f71274 --- /dev/null +++ b/modules/pubmatic/openwrap/cache/gocache/publisher_feature.go @@ -0,0 +1,19 @@ +package gocache + +import ( + "fmt" + + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" +) + +var errorPubFeatureUpdate = "[ErrorPubFeatureUpdate]:%w" + +// We are not saving data in cache here +func (c *cache) GetPublisherFeatureMap() (map[int]map[int]models.FeatureData, error) { + publisherFeatureMap, err := c.db.GetPublisherFeatureMap() + if err != nil { + c.metricEngine.RecordDBQueryFailure(models.PublisherFeatureMapQuery, "", "") + return publisherFeatureMap, fmt.Errorf(errorPubFeatureUpdate, err) + } + return publisherFeatureMap, nil +} diff --git a/modules/pubmatic/openwrap/cache/gocache/publisher_feature_test.go b/modules/pubmatic/openwrap/cache/gocache/publisher_feature_test.go new file mode 100644 index 00000000000..886b3f5feca --- /dev/null +++ b/modules/pubmatic/openwrap/cache/gocache/publisher_feature_test.go @@ -0,0 +1,112 @@ +package gocache + +import ( + "errors" + "testing" + + "github.com/golang/mock/gomock" + gocache "github.com/patrickmn/go-cache" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/config" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/database" + mock_database "github.com/prebid/prebid-server/modules/pubmatic/openwrap/database/mock" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics" + mock_metrics "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics/mock" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" + "github.com/stretchr/testify/assert" +) + +func Test_cache_GetPublisherFeatureMap(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mockDatabase := mock_database.NewMockDatabase(ctrl) + mockEngine := mock_metrics.NewMockMetricsEngine(ctrl) + type fields struct { + cache *gocache.Cache + cfg config.Cache + db database.Database + metricEngine metrics.MetricsEngine + } + tests := []struct { + name string + fields fields + want map[int]map[int]models.FeatureData + setup func() + wantErr bool + }{ + { + name: "Valid Data present in DB, return same", + want: map[int]map[int]models.FeatureData{ + 5890: { + models.FeatureFSC: { + Enabled: 0, + }, + models.FeatureTBF: { + Enabled: 1, + Value: `{"1234": 100}`, + }, + models.FeatureAMPMultiFormat: { + Enabled: 1, + }, + }, + }, + setup: func() { + mockDatabase.EXPECT().GetPublisherFeatureMap().Return(map[int]map[int]models.FeatureData{ + 5890: { + models.FeatureFSC: { + Enabled: 0, + }, + models.FeatureTBF: { + Enabled: 1, + Value: `{"1234": 100}`, + }, + models.FeatureAMPMultiFormat: { + Enabled: 1, + }, + }, + }, nil) + }, + fields: fields{ + cache: gocache.New(100, 100), + db: mockDatabase, + cfg: config.Cache{ + CacheDefaultExpiry: 1000, + }, + }, + wantErr: false, + }, + { + name: "Error In DB, Set Empty", + want: map[int]map[int]models.FeatureData{}, + setup: func() { + mockDatabase.EXPECT().GetPublisherFeatureMap().Return(map[int]map[int]models.FeatureData{}, errors.New("QUERY FAILD")) + mockEngine.EXPECT().RecordDBQueryFailure(models.PublisherFeatureMapQuery, "", "").Return() + }, + fields: fields{ + cache: gocache.New(100, 100), + db: mockDatabase, + cfg: config.Cache{ + CacheDefaultExpiry: 1000, + }, + metricEngine: mockEngine, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setup() + c := &cache{ + cache: tt.fields.cache, + cfg: tt.fields.cfg, + db: tt.fields.db, + metricEngine: tt.fields.metricEngine, + } + got, err := c.GetPublisherFeatureMap() + if (err != nil) != tt.wantErr { + t.Errorf("cache.GetPublisherFeatureMap() error = %v, wantErr %v", err, tt.wantErr) + return + } + assert.Equal(t, tt.want, got, tt.name) + }) + } +} diff --git a/modules/pubmatic/openwrap/cache/gocache/tracking_beacon_first.go b/modules/pubmatic/openwrap/cache/gocache/tracking_beacon_first.go deleted file mode 100644 index fc128159916..00000000000 --- a/modules/pubmatic/openwrap/cache/gocache/tracking_beacon_first.go +++ /dev/null @@ -1,12 +0,0 @@ -// Package gocache contains caching functionalities of header-bidding repostiry -// This file provides caching functionalities for tracking-beacon-first (TBF) feature details -// associated with publishers. It includes methods to interact with the underlying database package -// for retrieving and caching publisher level TBF data. -package gocache - -// GetTBFTrafficForPublishers simply forwards the call to database -// This will not set the data in cache since TBF feature maintains its own map as cache -// Adding this function only because we are calling all database functions through cache -func (c *cache) GetTBFTrafficForPublishers() (pubProfileTraffic map[int]map[int]int, err error) { - return c.db.GetTBFTrafficForPublishers() -} diff --git a/modules/pubmatic/openwrap/cache/gocache/tracking_beacon_first_test.go b/modules/pubmatic/openwrap/cache/gocache/tracking_beacon_first_test.go deleted file mode 100644 index 229005e5a21..00000000000 --- a/modules/pubmatic/openwrap/cache/gocache/tracking_beacon_first_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package gocache - -import ( - "testing" - - mock_database "github.com/prebid/prebid-server/modules/pubmatic/openwrap/database/mock" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" -) - -func TestGetTBFTrafficForPublishers(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - mockDatabase := mock_database.NewMockDatabase(ctrl) - - tests := []struct { - name string - setup func(dbCache *cache) - wantTrafficDetails map[int]map[int]int - wantErr error - }{ - { - name: "test_call_forwarding", - setup: func(dbCache *cache) { - mockDatabase.EXPECT().GetTBFTrafficForPublishers().Return(map[int]map[int]int{5890: {1234: 100}}, nil) - dbCache.db = mockDatabase - }, - wantTrafficDetails: map[int]map[int]int{5890: {1234: 100}}, - wantErr: nil, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - dbCache := cache{} - tt.setup(&dbCache) - actualTrafficDetails, err := dbCache.GetTBFTrafficForPublishers() - assert.Equal(t, actualTrafficDetails, tt.wantTrafficDetails, tt.name) - assert.Equal(t, tt.wantErr, err, tt.name) - }) - } -} diff --git a/modules/pubmatic/openwrap/cache/mock/mock.go b/modules/pubmatic/openwrap/cache/mock/mock.go index 6af968d18c3..58047adf0d4 100644 --- a/modules/pubmatic/openwrap/cache/mock/mock.go +++ b/modules/pubmatic/openwrap/cache/mock/mock.go @@ -5,38 +5,37 @@ package mock_cache import ( - reflect "reflect" - gomock "github.com/golang/mock/gomock" openrtb2 "github.com/prebid/openrtb/v19/openrtb2" models "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" adunitconfig "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models/adunitconfig" + reflect "reflect" ) -// MockCache is a mock of Cache interface. +// MockCache is a mock of Cache interface type MockCache struct { ctrl *gomock.Controller recorder *MockCacheMockRecorder } -// MockCacheMockRecorder is the mock recorder for MockCache. +// MockCacheMockRecorder is the mock recorder for MockCache type MockCacheMockRecorder struct { mock *MockCache } -// NewMockCache creates a new mock instance. +// NewMockCache creates a new mock instance func NewMockCache(ctrl *gomock.Controller) *MockCache { mock := &MockCache{ctrl: ctrl} mock.recorder = &MockCacheMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. +// EXPECT returns an object that allows the caller to indicate expected use func (m *MockCache) EXPECT() *MockCacheMockRecorder { return m.recorder } -// Get mocks base method. +// Get mocks base method func (m *MockCache) Get(arg0 string) (interface{}, bool) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0) @@ -45,13 +44,13 @@ func (m *MockCache) Get(arg0 string) (interface{}, bool) { return ret0, ret1 } -// Get indicates an expected call of Get. +// Get indicates an expected call of Get func (mr *MockCacheMockRecorder) Get(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockCache)(nil).Get), arg0) } -// GetAdunitConfigFromCache mocks base method. +// GetAdunitConfigFromCache mocks base method func (m *MockCache) GetAdunitConfigFromCache(arg0 *openrtb2.BidRequest, arg1, arg2, arg3 int) *adunitconfig.AdUnitConfig { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetAdunitConfigFromCache", arg0, arg1, arg2, arg3) @@ -59,28 +58,13 @@ func (m *MockCache) GetAdunitConfigFromCache(arg0 *openrtb2.BidRequest, arg1, ar return ret0 } -// GetAdunitConfigFromCache indicates an expected call of GetAdunitConfigFromCache. +// GetAdunitConfigFromCache indicates an expected call of GetAdunitConfigFromCache func (mr *MockCacheMockRecorder) GetAdunitConfigFromCache(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAdunitConfigFromCache", reflect.TypeOf((*MockCache)(nil).GetAdunitConfigFromCache), arg0, arg1, arg2, arg3) } -// GetFSCDisabledPublishers mocks base method. -func (m *MockCache) GetFSCDisabledPublishers() (map[int]struct{}, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetFSCDisabledPublishers") - ret0, _ := ret[0].(map[int]struct{}) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetFSCDisabledPublishers indicates an expected call of GetFSCDisabledPublishers. -func (mr *MockCacheMockRecorder) GetFSCDisabledPublishers() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFSCDisabledPublishers", reflect.TypeOf((*MockCache)(nil).GetFSCDisabledPublishers)) -} - -// GetFSCThresholdPerDSP mocks base method. +// GetFSCThresholdPerDSP mocks base method func (m *MockCache) GetFSCThresholdPerDSP() (map[int]int, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetFSCThresholdPerDSP") @@ -89,13 +73,13 @@ func (m *MockCache) GetFSCThresholdPerDSP() (map[int]int, error) { return ret0, ret1 } -// GetFSCThresholdPerDSP indicates an expected call of GetFSCThresholdPerDSP. +// GetFSCThresholdPerDSP indicates an expected call of GetFSCThresholdPerDSP func (mr *MockCacheMockRecorder) GetFSCThresholdPerDSP() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFSCThresholdPerDSP", reflect.TypeOf((*MockCache)(nil).GetFSCThresholdPerDSP)) } -// GetMappingsFromCacheV25 mocks base method. +// GetMappingsFromCacheV25 mocks base method func (m *MockCache) GetMappingsFromCacheV25(arg0 models.RequestCtx, arg1 int) map[string]models.SlotMapping { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetMappingsFromCacheV25", arg0, arg1) @@ -103,13 +87,13 @@ func (m *MockCache) GetMappingsFromCacheV25(arg0 models.RequestCtx, arg1 int) ma return ret0 } -// GetMappingsFromCacheV25 indicates an expected call of GetMappingsFromCacheV25. +// GetMappingsFromCacheV25 indicates an expected call of GetMappingsFromCacheV25 func (mr *MockCacheMockRecorder) GetMappingsFromCacheV25(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMappingsFromCacheV25", reflect.TypeOf((*MockCache)(nil).GetMappingsFromCacheV25), arg0, arg1) } -// GetPartnerConfigMap mocks base method. +// GetPartnerConfigMap mocks base method func (m *MockCache) GetPartnerConfigMap(arg0, arg1, arg2 int, arg3 string) (map[int]map[string]string, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetPartnerConfigMap", arg0, arg1, arg2, arg3) @@ -118,13 +102,28 @@ func (m *MockCache) GetPartnerConfigMap(arg0, arg1, arg2 int, arg3 string) (map[ return ret0, ret1 } -// GetPartnerConfigMap indicates an expected call of GetPartnerConfigMap. +// GetPartnerConfigMap indicates an expected call of GetPartnerConfigMap func (mr *MockCacheMockRecorder) GetPartnerConfigMap(arg0, arg1, arg2, arg3 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) } -// GetPublisherVASTTagsFromCache mocks base method. +// GetPublisherFeatureMap mocks base method +func (m *MockCache) GetPublisherFeatureMap() (map[int]map[int]models.FeatureData, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPublisherFeatureMap") + ret0, _ := ret[0].(map[int]map[int]models.FeatureData) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPublisherFeatureMap indicates an expected call of GetPublisherFeatureMap +func (mr *MockCacheMockRecorder) GetPublisherFeatureMap() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPublisherFeatureMap", reflect.TypeOf((*MockCache)(nil).GetPublisherFeatureMap)) +} + +// GetPublisherVASTTagsFromCache mocks base method func (m *MockCache) GetPublisherVASTTagsFromCache(arg0 int) map[int]*models.VASTTag { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetPublisherVASTTagsFromCache", arg0) @@ -132,13 +131,13 @@ func (m *MockCache) GetPublisherVASTTagsFromCache(arg0 int) map[int]*models.VAST return ret0 } -// GetPublisherVASTTagsFromCache indicates an expected call of GetPublisherVASTTagsFromCache. +// GetPublisherVASTTagsFromCache indicates an expected call of GetPublisherVASTTagsFromCache func (mr *MockCacheMockRecorder) GetPublisherVASTTagsFromCache(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPublisherVASTTagsFromCache", reflect.TypeOf((*MockCache)(nil).GetPublisherVASTTagsFromCache), arg0) } -// GetSlotToHashValueMapFromCacheV25 mocks base method. +// GetSlotToHashValueMapFromCacheV25 mocks base method func (m *MockCache) GetSlotToHashValueMapFromCacheV25(arg0 models.RequestCtx, arg1 int) models.SlotMappingInfo { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetSlotToHashValueMapFromCacheV25", arg0, arg1) @@ -146,34 +145,19 @@ func (m *MockCache) GetSlotToHashValueMapFromCacheV25(arg0 models.RequestCtx, ar return ret0 } -// GetSlotToHashValueMapFromCacheV25 indicates an expected call of GetSlotToHashValueMapFromCacheV25. +// GetSlotToHashValueMapFromCacheV25 indicates an expected call of GetSlotToHashValueMapFromCacheV25 func (mr *MockCacheMockRecorder) GetSlotToHashValueMapFromCacheV25(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSlotToHashValueMapFromCacheV25", reflect.TypeOf((*MockCache)(nil).GetSlotToHashValueMapFromCacheV25), arg0, arg1) } -// GetTBFTrafficForPublishers mocks base method. -func (m *MockCache) GetTBFTrafficForPublishers() (map[int]map[int]int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTBFTrafficForPublishers") - ret0, _ := ret[0].(map[int]map[int]int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetTBFTrafficForPublishers indicates an expected call of GetTBFTrafficForPublishers. -func (mr *MockCacheMockRecorder) GetTBFTrafficForPublishers() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTBFTrafficForPublishers", reflect.TypeOf((*MockCache)(nil).GetTBFTrafficForPublishers)) -} - -// Set mocks base method. +// Set mocks base method func (m *MockCache) Set(arg0 string, arg1 interface{}) { m.ctrl.T.Helper() m.ctrl.Call(m, "Set", arg0, arg1) } -// Set indicates an expected call of Set. +// Set indicates an expected call of Set func (mr *MockCacheMockRecorder) Set(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockCache)(nil).Set), arg0, arg1) diff --git a/modules/pubmatic/openwrap/config/config.go b/modules/pubmatic/openwrap/config/config.go index b26d90fd2c5..d3c11b92501 100755 --- a/modules/pubmatic/openwrap/config/config.go +++ b/modules/pubmatic/openwrap/config/config.go @@ -53,9 +53,8 @@ type Queries struct { GetAdunitConfigForLiveVersion string GetSlotNameHash string GetPublisherVASTTagsQuery string - GetAllFscDisabledPublishersQuery string GetAllDspFscPcntQuery string - GetTBFRateQuery string + GetPublisherFeatureMapQuery string } type Cache struct { diff --git a/modules/pubmatic/openwrap/database/database.go b/modules/pubmatic/openwrap/database/database.go index 5a4a67ad812..11f1d1ec569 100644 --- a/modules/pubmatic/openwrap/database/database.go +++ b/modules/pubmatic/openwrap/database/database.go @@ -12,7 +12,6 @@ type Database interface { GetWrapperSlotMappings(partnerConfigMap map[int]map[string]string, profileID, displayVersion int) (map[int][]models.SlotMapping, error) GetPublisherVASTTags(pubID int) (models.PublisherVASTTags, error) GetMappings(slotKey string, slotMap map[string]models.SlotMapping) (map[string]interface{}, error) - GetFSCDisabledPublishers() (map[int]struct{}, error) GetFSCThresholdPerDSP() (map[int]int, error) - GetTBFTrafficForPublishers() (map[int]map[int]int, error) + GetPublisherFeatureMap() (map[int]map[int]models.FeatureData, error) } diff --git a/modules/pubmatic/openwrap/database/mock/mock.go b/modules/pubmatic/openwrap/database/mock/mock.go index 8d55ac4b723..fa60e0143c7 100644 --- a/modules/pubmatic/openwrap/database/mock/mock.go +++ b/modules/pubmatic/openwrap/database/mock/mock.go @@ -5,37 +5,36 @@ package mock_database import ( - reflect "reflect" - gomock "github.com/golang/mock/gomock" models "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" adunitconfig "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models/adunitconfig" + reflect "reflect" ) -// MockDatabase is a mock of Database interface. +// MockDatabase is a mock of Database interface type MockDatabase struct { ctrl *gomock.Controller recorder *MockDatabaseMockRecorder } -// MockDatabaseMockRecorder is the mock recorder for MockDatabase. +// MockDatabaseMockRecorder is the mock recorder for MockDatabase type MockDatabaseMockRecorder struct { mock *MockDatabase } -// NewMockDatabase creates a new mock instance. +// NewMockDatabase creates a new mock instance func NewMockDatabase(ctrl *gomock.Controller) *MockDatabase { mock := &MockDatabase{ctrl: ctrl} mock.recorder = &MockDatabaseMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. +// EXPECT returns an object that allows the caller to indicate expected use func (m *MockDatabase) EXPECT() *MockDatabaseMockRecorder { return m.recorder } -// GetActivePartnerConfigurations mocks base method. +// GetActivePartnerConfigurations mocks base method func (m *MockDatabase) GetActivePartnerConfigurations(arg0, arg1, arg2 int) (map[int]map[string]string, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetActivePartnerConfigurations", arg0, arg1, arg2) @@ -44,13 +43,13 @@ func (m *MockDatabase) GetActivePartnerConfigurations(arg0, arg1, arg2 int) (map return ret0, ret1 } -// GetActivePartnerConfigurations indicates an expected call of GetActivePartnerConfigurations. +// GetActivePartnerConfigurations indicates an expected call of GetActivePartnerConfigurations func (mr *MockDatabaseMockRecorder) GetActivePartnerConfigurations(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetActivePartnerConfigurations", reflect.TypeOf((*MockDatabase)(nil).GetActivePartnerConfigurations), arg0, arg1, arg2) } -// GetAdunitConfig mocks base method. +// GetAdunitConfig mocks base method func (m *MockDatabase) GetAdunitConfig(arg0, arg1 int) (*adunitconfig.AdUnitConfig, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetAdunitConfig", arg0, arg1) @@ -59,28 +58,13 @@ func (m *MockDatabase) GetAdunitConfig(arg0, arg1 int) (*adunitconfig.AdUnitConf return ret0, ret1 } -// GetAdunitConfig indicates an expected call of GetAdunitConfig. +// GetAdunitConfig indicates an expected call of GetAdunitConfig func (mr *MockDatabaseMockRecorder) GetAdunitConfig(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAdunitConfig", reflect.TypeOf((*MockDatabase)(nil).GetAdunitConfig), arg0, arg1) } -// GetFSCDisabledPublishers mocks base method. -func (m *MockDatabase) GetFSCDisabledPublishers() (map[int]struct{}, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetFSCDisabledPublishers") - ret0, _ := ret[0].(map[int]struct{}) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetFSCDisabledPublishers indicates an expected call of GetFSCDisabledPublishers. -func (mr *MockDatabaseMockRecorder) GetFSCDisabledPublishers() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFSCDisabledPublishers", reflect.TypeOf((*MockDatabase)(nil).GetFSCDisabledPublishers)) -} - -// GetFSCThresholdPerDSP mocks base method. +// GetFSCThresholdPerDSP mocks base method func (m *MockDatabase) GetFSCThresholdPerDSP() (map[int]int, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetFSCThresholdPerDSP") @@ -89,13 +73,13 @@ func (m *MockDatabase) GetFSCThresholdPerDSP() (map[int]int, error) { return ret0, ret1 } -// GetFSCThresholdPerDSP indicates an expected call of GetFSCThresholdPerDSP. +// GetFSCThresholdPerDSP indicates an expected call of GetFSCThresholdPerDSP func (mr *MockDatabaseMockRecorder) GetFSCThresholdPerDSP() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFSCThresholdPerDSP", reflect.TypeOf((*MockDatabase)(nil).GetFSCThresholdPerDSP)) } -// GetMappings mocks base method. +// GetMappings mocks base method func (m *MockDatabase) GetMappings(arg0 string, arg1 map[string]models.SlotMapping) (map[string]interface{}, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetMappings", arg0, arg1) @@ -104,13 +88,28 @@ func (m *MockDatabase) GetMappings(arg0 string, arg1 map[string]models.SlotMappi return ret0, ret1 } -// GetMappings indicates an expected call of GetMappings. +// GetMappings indicates an expected call of GetMappings func (mr *MockDatabaseMockRecorder) GetMappings(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMappings", reflect.TypeOf((*MockDatabase)(nil).GetMappings), arg0, arg1) } -// GetPublisherSlotNameHash mocks base method. +// GetPublisherFeatureMap mocks base method +func (m *MockDatabase) GetPublisherFeatureMap() (map[int]map[int]models.FeatureData, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPublisherFeatureMap") + ret0, _ := ret[0].(map[int]map[int]models.FeatureData) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPublisherFeatureMap indicates an expected call of GetPublisherFeatureMap +func (mr *MockDatabaseMockRecorder) GetPublisherFeatureMap() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPublisherFeatureMap", reflect.TypeOf((*MockDatabase)(nil).GetPublisherFeatureMap)) +} + +// GetPublisherSlotNameHash mocks base method func (m *MockDatabase) GetPublisherSlotNameHash(arg0 int) (map[string]string, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetPublisherSlotNameHash", arg0) @@ -119,13 +118,13 @@ func (m *MockDatabase) GetPublisherSlotNameHash(arg0 int) (map[string]string, er return ret0, ret1 } -// GetPublisherSlotNameHash indicates an expected call of GetPublisherSlotNameHash. +// GetPublisherSlotNameHash indicates an expected call of GetPublisherSlotNameHash func (mr *MockDatabaseMockRecorder) GetPublisherSlotNameHash(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPublisherSlotNameHash", reflect.TypeOf((*MockDatabase)(nil).GetPublisherSlotNameHash), arg0) } -// GetPublisherVASTTags mocks base method. +// GetPublisherVASTTags mocks base method func (m *MockDatabase) GetPublisherVASTTags(arg0 int) (map[int]*models.VASTTag, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetPublisherVASTTags", arg0) @@ -134,28 +133,13 @@ func (m *MockDatabase) GetPublisherVASTTags(arg0 int) (map[int]*models.VASTTag, return ret0, ret1 } -// GetPublisherVASTTags indicates an expected call of GetPublisherVASTTags. +// GetPublisherVASTTags indicates an expected call of GetPublisherVASTTags func (mr *MockDatabaseMockRecorder) GetPublisherVASTTags(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPublisherVASTTags", reflect.TypeOf((*MockDatabase)(nil).GetPublisherVASTTags), arg0) } -// GetTBFTrafficForPublishers mocks base method. -func (m *MockDatabase) GetTBFTrafficForPublishers() (map[int]map[int]int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTBFTrafficForPublishers") - ret0, _ := ret[0].(map[int]map[int]int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetTBFTrafficForPublishers indicates an expected call of GetTBFTrafficForPublishers. -func (mr *MockDatabaseMockRecorder) GetTBFTrafficForPublishers() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTBFTrafficForPublishers", reflect.TypeOf((*MockDatabase)(nil).GetTBFTrafficForPublishers)) -} - -// GetWrapperSlotMappings mocks base method. +// GetWrapperSlotMappings mocks base method func (m *MockDatabase) GetWrapperSlotMappings(arg0 map[int]map[string]string, arg1, arg2 int) (map[int][]models.SlotMapping, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetWrapperSlotMappings", arg0, arg1, arg2) @@ -164,7 +148,7 @@ func (m *MockDatabase) GetWrapperSlotMappings(arg0 map[int]map[string]string, ar return ret0, ret1 } -// GetWrapperSlotMappings indicates an expected call of GetWrapperSlotMappings. +// GetWrapperSlotMappings indicates an expected call of GetWrapperSlotMappings func (mr *MockDatabaseMockRecorder) GetWrapperSlotMappings(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWrapperSlotMappings", reflect.TypeOf((*MockDatabase)(nil).GetWrapperSlotMappings), arg0, arg1, arg2) diff --git a/modules/pubmatic/openwrap/database/mock_driver/mock.go b/modules/pubmatic/openwrap/database/mock_driver/mock.go index c5c653194ad..a8f6d808c95 100644 --- a/modules/pubmatic/openwrap/database/mock_driver/mock.go +++ b/modules/pubmatic/openwrap/database/mock_driver/mock.go @@ -7,35 +7,34 @@ package mock_driver import ( context "context" driver "database/sql/driver" - reflect "reflect" - gomock "github.com/golang/mock/gomock" + reflect "reflect" ) -// MockDriver is a mock of Driver interface. +// MockDriver is a mock of Driver interface type MockDriver struct { ctrl *gomock.Controller recorder *MockDriverMockRecorder } -// MockDriverMockRecorder is the mock recorder for MockDriver. +// MockDriverMockRecorder is the mock recorder for MockDriver type MockDriverMockRecorder struct { mock *MockDriver } -// NewMockDriver creates a new mock instance. +// NewMockDriver creates a new mock instance func NewMockDriver(ctrl *gomock.Controller) *MockDriver { mock := &MockDriver{ctrl: ctrl} mock.recorder = &MockDriverMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. +// EXPECT returns an object that allows the caller to indicate expected use func (m *MockDriver) EXPECT() *MockDriverMockRecorder { return m.recorder } -// Open mocks base method. +// Open mocks base method func (m *MockDriver) Open(arg0 string) (driver.Conn, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Open", arg0) @@ -44,36 +43,36 @@ func (m *MockDriver) Open(arg0 string) (driver.Conn, error) { return ret0, ret1 } -// Open indicates an expected call of Open. +// Open indicates an expected call of Open func (mr *MockDriverMockRecorder) Open(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Open", reflect.TypeOf((*MockDriver)(nil).Open), arg0) } -// MockConnector is a mock of Connector interface. +// MockConnector is a mock of Connector interface type MockConnector struct { ctrl *gomock.Controller recorder *MockConnectorMockRecorder } -// MockConnectorMockRecorder is the mock recorder for MockConnector. +// MockConnectorMockRecorder is the mock recorder for MockConnector type MockConnectorMockRecorder struct { mock *MockConnector } -// NewMockConnector creates a new mock instance. +// NewMockConnector creates a new mock instance func NewMockConnector(ctrl *gomock.Controller) *MockConnector { mock := &MockConnector{ctrl: ctrl} mock.recorder = &MockConnectorMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. +// EXPECT returns an object that allows the caller to indicate expected use func (m *MockConnector) EXPECT() *MockConnectorMockRecorder { return m.recorder } -// Connect mocks base method. +// Connect mocks base method func (m *MockConnector) Connect(arg0 context.Context) (driver.Conn, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Connect", arg0) @@ -82,13 +81,13 @@ func (m *MockConnector) Connect(arg0 context.Context) (driver.Conn, error) { return ret0, ret1 } -// Connect indicates an expected call of Connect. +// Connect indicates an expected call of Connect func (mr *MockConnectorMockRecorder) Connect(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Connect", reflect.TypeOf((*MockConnector)(nil).Connect), arg0) } -// Driver mocks base method. +// Driver mocks base method func (m *MockConnector) Driver() driver.Driver { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Driver") @@ -96,36 +95,36 @@ func (m *MockConnector) Driver() driver.Driver { return ret0 } -// Driver indicates an expected call of Driver. +// Driver indicates an expected call of Driver func (mr *MockConnectorMockRecorder) Driver() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Driver", reflect.TypeOf((*MockConnector)(nil).Driver)) } -// MockConn is a mock of Conn interface. +// MockConn is a mock of Conn interface type MockConn struct { ctrl *gomock.Controller recorder *MockConnMockRecorder } -// MockConnMockRecorder is the mock recorder for MockConn. +// MockConnMockRecorder is the mock recorder for MockConn type MockConnMockRecorder struct { mock *MockConn } -// NewMockConn creates a new mock instance. +// NewMockConn creates a new mock instance func NewMockConn(ctrl *gomock.Controller) *MockConn { mock := &MockConn{ctrl: ctrl} mock.recorder = &MockConnMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. +// EXPECT returns an object that allows the caller to indicate expected use func (m *MockConn) EXPECT() *MockConnMockRecorder { return m.recorder } -// Begin mocks base method. +// Begin mocks base method func (m *MockConn) Begin() (driver.Tx, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Begin") @@ -134,13 +133,13 @@ func (m *MockConn) Begin() (driver.Tx, error) { return ret0, ret1 } -// Begin indicates an expected call of Begin. +// Begin indicates an expected call of Begin func (mr *MockConnMockRecorder) Begin() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Begin", reflect.TypeOf((*MockConn)(nil).Begin)) } -// Close mocks base method. +// Close mocks base method func (m *MockConn) Close() error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Close") @@ -148,13 +147,13 @@ func (m *MockConn) Close() error { return ret0 } -// Close indicates an expected call of Close. +// Close indicates an expected call of Close func (mr *MockConnMockRecorder) Close() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockConn)(nil).Close)) } -// Prepare mocks base method. +// Prepare mocks base method func (m *MockConn) Prepare(arg0 string) (driver.Stmt, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Prepare", arg0) @@ -163,36 +162,36 @@ func (m *MockConn) Prepare(arg0 string) (driver.Stmt, error) { return ret0, ret1 } -// Prepare indicates an expected call of Prepare. +// Prepare indicates an expected call of Prepare func (mr *MockConnMockRecorder) Prepare(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Prepare", reflect.TypeOf((*MockConn)(nil).Prepare), arg0) } -// MockDriverContext is a mock of DriverContext interface. +// MockDriverContext is a mock of DriverContext interface type MockDriverContext struct { ctrl *gomock.Controller recorder *MockDriverContextMockRecorder } -// MockDriverContextMockRecorder is the mock recorder for MockDriverContext. +// MockDriverContextMockRecorder is the mock recorder for MockDriverContext type MockDriverContextMockRecorder struct { mock *MockDriverContext } -// NewMockDriverContext creates a new mock instance. +// NewMockDriverContext creates a new mock instance func NewMockDriverContext(ctrl *gomock.Controller) *MockDriverContext { mock := &MockDriverContext{ctrl: ctrl} mock.recorder = &MockDriverContextMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. +// EXPECT returns an object that allows the caller to indicate expected use func (m *MockDriverContext) EXPECT() *MockDriverContextMockRecorder { return m.recorder } -// OpenConnector mocks base method. +// OpenConnector mocks base method func (m *MockDriverContext) OpenConnector(arg0 string) (driver.Connector, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "OpenConnector", arg0) @@ -201,7 +200,7 @@ func (m *MockDriverContext) OpenConnector(arg0 string) (driver.Connector, error) return ret0, ret1 } -// OpenConnector indicates an expected call of OpenConnector. +// OpenConnector indicates an expected call of OpenConnector func (mr *MockDriverContextMockRecorder) OpenConnector(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OpenConnector", reflect.TypeOf((*MockDriverContext)(nil).OpenConnector), arg0) diff --git a/modules/pubmatic/openwrap/database/mysql/fullscreenclickability.go b/modules/pubmatic/openwrap/database/mysql/fullscreenclickability.go index 45b4f34a4ae..f0a1e8ecfb6 100644 --- a/modules/pubmatic/openwrap/database/mysql/fullscreenclickability.go +++ b/modules/pubmatic/openwrap/database/mysql/fullscreenclickability.go @@ -6,23 +6,6 @@ import ( "github.com/golang/glog" ) -func (db *mySqlDB) GetFSCDisabledPublishers() (map[int]struct{}, error) { - rows, err := db.conn.Query(db.cfg.Queries.GetAllFscDisabledPublishersQuery) - if err != nil { - return nil, err - } - defer rows.Close() - - fscDisabledPublishers := make(map[int]struct{}) - for rows.Next() { - var pubid int - if err := rows.Scan(&pubid); err == nil { - fscDisabledPublishers[pubid] = struct{}{} - } - } - return fscDisabledPublishers, nil -} - func (db *mySqlDB) GetFSCThresholdPerDSP() (map[int]int, error) { rows, err := db.conn.Query(db.cfg.Queries.GetAllDspFscPcntQuery) if err != nil { diff --git a/modules/pubmatic/openwrap/database/mysql/fullscreenclickability_test.go b/modules/pubmatic/openwrap/database/mysql/fullscreenclickability_test.go index bc73c9f2650..ea37a0decb3 100644 --- a/modules/pubmatic/openwrap/database/mysql/fullscreenclickability_test.go +++ b/modules/pubmatic/openwrap/database/mysql/fullscreenclickability_test.go @@ -10,95 +10,6 @@ import ( "github.com/stretchr/testify/assert" ) -func Test_mySqlDB_GetFSCDisabledPublishers(t *testing.T) { - type fields struct { - cfg config.Database - } - tests := []struct { - name string - fields fields - want map[int]struct{} - wantErr bool - setup func() *sql.DB - }{ - { - name: "empty query in config file", - want: nil, - wantErr: true, - setup: func() *sql.DB { - db, _, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - return db - }, - }, - { - name: "invalid pubid", - fields: fields{ - cfg: config.Database{ - Queries: config.Queries{ - GetAllFscDisabledPublishersQuery: "^SELECT (.+) FROM wrapper_publisher_feature_mapping (.+)", - }, - }, - }, - want: map[int]struct{}{}, - wantErr: false, - setup: func() *sql.DB { - db, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - rows := sqlmock.NewRows([]string{"pub_id"}).AddRow(`5890,5891,5892`) - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_publisher_feature_mapping (.+)")).WillReturnRows(rows) - return db - }, - }, - { - name: "Valid rows returned, setting invalid values to 1", - fields: fields{ - cfg: config.Database{ - Queries: config.Queries{ - GetAllFscDisabledPublishersQuery: "^SELECT (.+) FROM wrapper_publisher_feature_mapping (.+)", - }, - }, - }, - want: map[int]struct{}{ - 5890: {}, - 5891: {}, - 5892: {}, - }, - wantErr: false, - setup: func() *sql.DB { - db, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - rows := sqlmock.NewRows([]string{"pub_id"}). - AddRow(`5890`). - AddRow(`5891`). - AddRow(`5892`) - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_publisher_feature_mapping (.+)")).WillReturnRows(rows) - return db - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - db := &mySqlDB{ - conn: tt.setup(), - cfg: tt.fields.cfg, - } - got, err := db.GetFSCDisabledPublishers() - if (err != nil) != tt.wantErr { - t.Errorf("mySqlDB.GetFSCDisabledPublishers() error = %v, wantErr %v", err, tt.wantErr) - return - } - assert.Equal(t, tt.want, got) - }) - } -} - func Test_mySqlDB_GetFSCThresholdPerDSP(t *testing.T) { type fields struct { cfg config.Database diff --git a/modules/pubmatic/openwrap/database/mysql/publisher_feature.go b/modules/pubmatic/openwrap/database/mysql/publisher_feature.go new file mode 100644 index 00000000000..6169b203ab6 --- /dev/null +++ b/modules/pubmatic/openwrap/database/mysql/publisher_feature.go @@ -0,0 +1,34 @@ +package mysql + +import ( + "database/sql" + + "github.com/golang/glog" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" +) + +func (db *mySqlDB) GetPublisherFeatureMap() (map[int]map[int]models.FeatureData, error) { + rows, err := db.conn.Query(db.cfg.Queries.GetPublisherFeatureMapQuery) + if err != nil { + return nil, err + } + defer rows.Close() + + publisherFeatureMap := make(map[int]map[int]models.FeatureData) + for rows.Next() { + var pubId, featureId, enabled int + var value sql.NullString + if err := rows.Scan(&pubId, &featureId, &enabled, &value); err != nil { + glog.Error("ErrRowScanFailed GetPublisherFeatureMap pubid: ", pubId, " err: ", err.Error()) + continue + } + if _, ok := publisherFeatureMap[pubId]; !ok { + publisherFeatureMap[pubId] = make(map[int]models.FeatureData) + } + publisherFeatureMap[pubId][featureId] = models.FeatureData{ + Enabled: enabled, + Value: value.String, + } + } + return publisherFeatureMap, nil +} diff --git a/modules/pubmatic/openwrap/database/mysql/publisher_feature_test.go b/modules/pubmatic/openwrap/database/mysql/publisher_feature_test.go new file mode 100644 index 00000000000..1db4bcea8dc --- /dev/null +++ b/modules/pubmatic/openwrap/database/mysql/publisher_feature_test.go @@ -0,0 +1,132 @@ +package mysql + +import ( + "database/sql" + "regexp" + "testing" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/config" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" + "github.com/stretchr/testify/assert" +) + +func Test_mySqlDB_GetPublisherFeatureMap(t *testing.T) { + type fields struct { + cfg config.Database + } + tests := []struct { + name string + fields fields + setup func() *sql.DB + want map[int]map[int]models.FeatureData + wantErr bool + }{ + { + name: "empty query in config file", + want: nil, + wantErr: true, + setup: func() *sql.DB { + db, _, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + return db + }, + }, + { + name: "Invalid feature_id", + fields: fields{ + cfg: config.Database{ + Queries: config.Queries{ + GetPublisherFeatureMapQuery: "^SELECT (.+) FROM test_wrapper_table (.+)", + }, + }, + }, + want: map[int]map[int]models.FeatureData{}, + wantErr: false, + setup: func() *sql.DB { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + rows := sqlmock.NewRows([]string{"pub_id", "feature_id", "is_enabled", "value"}).AddRow(`5890`, `3.5`, `1`, `24`) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM test_wrapper_table (.+)")).WillReturnRows(rows) + return db + }, + }, + { + name: "Valid rows returned", + fields: fields{ + cfg: config.Database{ + Queries: config.Queries{ + GetPublisherFeatureMapQuery: "^SELECT (.+) FROM test_wrapper_table (.+)", + }, + }, + }, + want: map[int]map[int]models.FeatureData{ + 5890: { + 1: { + Enabled: 0, + }, + 2: { + Enabled: 1, + Value: `{"1234": 100}`, + }, + 3: { + Enabled: 1, + }, + }, + }, + wantErr: false, + setup: func() *sql.DB { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + rows := sqlmock.NewRows([]string{"pub_id", "feature_id", "is_enabled", "value"}). + AddRow(`5890`, `1`, `0`, sql.NullString{}). + AddRow(`5890`, `2`, `1`, `{"1234": 100}`). + AddRow(`5890`, `3`, `1`, sql.NullString{}) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM test_wrapper_table (.+)")).WillReturnRows(rows) + return db + }, + }, + { + name: "no rows returned from DB", + fields: fields{ + cfg: config.Database{ + Queries: config.Queries{ + GetPublisherFeatureMapQuery: "^SELECT (.+) FROM test_wrapper_table (.+)", + }, + }, + }, + want: map[int]map[int]models.FeatureData{}, + wantErr: false, + setup: func() *sql.DB { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + + rows := sqlmock.NewRows([]string{"pub_id", "feature_id", "is_enabled", "value"}) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM test_wrapper_table (.+)")).WillReturnRows(rows) + return db + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + db := &mySqlDB{ + conn: tt.setup(), + cfg: tt.fields.cfg, + } + got, err := db.GetPublisherFeatureMap() + if (err != nil) != tt.wantErr { + t.Errorf("mySqlDB.GetPublisherFeatureMap() error = %v, wantErr %v", err, tt.wantErr) + return + } + assert.Equal(t, tt.want, got, tt.name) + }) + } +} diff --git a/modules/pubmatic/openwrap/database/mysql/tracking_beacon_first.go b/modules/pubmatic/openwrap/database/mysql/tracking_beacon_first.go deleted file mode 100644 index 2d6e298fa57..00000000000 --- a/modules/pubmatic/openwrap/database/mysql/tracking_beacon_first.go +++ /dev/null @@ -1,40 +0,0 @@ -// Package mysql provides functionalities to interact with the giym database. -// This file is used for retrieving and managing data related to the tracking-beacon-first (TBF) feature for publishers. -// This includes methods to fetch and process tracking-beacon-first traffic details associated -// with publisher IDs from the giym database. -package mysql - -import ( - "encoding/json" - - "github.com/golang/glog" -) - -// GetTBFTrafficForPublishers function fetches the publisher data for TBF (tracking-beacon-first) feature from database -func (db *mySqlDB) GetTBFTrafficForPublishers() (map[int]map[int]int, error) { - rows, err := db.conn.Query(db.cfg.Queries.GetTBFRateQuery) - if err != nil { - return nil, err - } - defer rows.Close() - - pubProfileTrafficRate := make(map[int]map[int]int) - for rows.Next() { - var pubID int - var trafficDetails string - - if err := rows.Scan(&pubID, &trafficDetails); err != nil { - glog.Error("ErrRowScanFailed GetTBFRateQuery pubid: ", pubID, " err: ", err.Error()) - continue - } - - // convert trafficDetails into map[profileId]traffic - var profileTrafficRate map[int]int - if err := json.Unmarshal([]byte(trafficDetails), &profileTrafficRate); err != nil { - glog.Error("ErrJSONUnmarshalFailed TBFProfileTrafficRate pubid: ", pubID, " trafficDetails: ", trafficDetails, " err: ", err.Error()) - continue - } - pubProfileTrafficRate[pubID] = profileTrafficRate - } - return pubProfileTrafficRate, nil -} diff --git a/modules/pubmatic/openwrap/database/mysql/tracking_beacon_first_test.go b/modules/pubmatic/openwrap/database/mysql/tracking_beacon_first_test.go deleted file mode 100644 index a3147b7e530..00000000000 --- a/modules/pubmatic/openwrap/database/mysql/tracking_beacon_first_test.go +++ /dev/null @@ -1,167 +0,0 @@ -package mysql - -import ( - "database/sql" - "testing" - - "github.com/DATA-DOG/go-sqlmock" - "github.com/stretchr/testify/assert" -) - -func TestGetTBFTrafficForPublishers(t *testing.T) { - type want struct { - trafficDetails map[int]map[int]int - err error - } - - tests := []struct { - name string - setup func(db *mySqlDB) - want want - }{ - { - name: "db_query_fail", - setup: func(db *mySqlDB) { - conn, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - - rows := sqlmock.NewRows([]string{"value"}) - rows.AddRow("{'5890': 12}") - mock.ExpectQuery("").WillReturnError(sql.ErrConnDone) - db.conn = conn - }, - want: want{ - trafficDetails: nil, - err: sql.ErrConnDone, - }, - }, - { - name: "query_returns_empty_rows", - setup: func(db *mySqlDB) { - conn, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - - rows := sqlmock.NewRows([]string{"value"}) - mock.ExpectQuery("").WillReturnRows(rows) - db.conn = conn - }, - want: want{ - trafficDetails: map[int]map[int]int{}, - err: nil, - }, - }, - { - name: "row_scan_failure", - setup: func(db *mySqlDB) { - conn, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - - row := mock.NewRows([]string{"value"}).AddRow(nil) - mock.ExpectQuery("").WillReturnRows(row) - db.conn = conn - }, - want: want{ - trafficDetails: map[int]map[int]int{}, - err: nil, - }, - }, - { - name: "json_unmarshal_fail", - setup: func(db *mySqlDB) { - conn, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - - row := mock.NewRows([]string{"pubid", "value"}).AddRow("5890", "{1234:10}") - mock.ExpectQuery("").WillReturnRows(row) - db.conn = conn - }, - want: want{ - trafficDetails: map[int]map[int]int{}, - err: nil, - }, - }, - { - name: "valid_single_row", - setup: func(db *mySqlDB) { - conn, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - - row := mock.NewRows([]string{"pubid", "value"}).AddRow("5890", "{\"1234\":10}") - mock.ExpectQuery("").WillReturnRows(row) - db.conn = conn - }, - want: want{ - trafficDetails: map[int]map[int]int{ - 5890: {1234: 10}, - }, - err: nil, - }, - }, - { - name: "multi_row_response", - setup: func(db *mySqlDB) { - conn, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - - row := mock.NewRows([]string{"pubid", "value"}) - row.AddRow("5890", "{\"1234\":10 ,\"4321\": 90}") - row.AddRow("5891", "{\"5678\":20}") - mock.ExpectQuery("").WillReturnRows(row) - db.conn = conn - }, - want: want{ - trafficDetails: map[int]map[int]int{ - 5890: {1234: 10, 4321: 90}, - 5891: {5678: 20}, - }, - err: nil, - }, - }, - { - name: "one_invalid_row_in_multi_row_response", - setup: func(db *mySqlDB) { - conn, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - - row := mock.NewRows([]string{"pubid", "value"}) - row.AddRow("5890", "{\"1234\":10}") - row.AddRow("5890", "invalid_row") - row.AddRow("5890", "{\"5678\":20}") - - mock.ExpectQuery("").WillReturnRows(row) - db.conn = conn - }, - want: want{ - trafficDetails: map[int]map[int]int{ - 5890: {5678: 20}, - }, - err: nil, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - mySQLDB := mySqlDB{} - tt.setup(&mySQLDB) - - trafficDetails, err := mySQLDB.GetTBFTrafficForPublishers() - assert.Equalf(t, tt.want.trafficDetails, trafficDetails, tt.name) - assert.Equalf(t, tt.want.err, err, tt.name) - }) - } -} diff --git a/modules/pubmatic/openwrap/fullscreenclickability/fullscreenclickability.go b/modules/pubmatic/openwrap/fullscreenclickability/fullscreenclickability.go deleted file mode 100644 index f078a11d2d6..00000000000 --- a/modules/pubmatic/openwrap/fullscreenclickability/fullscreenclickability.go +++ /dev/null @@ -1,103 +0,0 @@ -package fullscreenclickability - -import ( - "math/rand" - - "sync" - - "github.com/golang/glog" - cache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache" - "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" -) - -type fsc struct { - cache cache.Cache - disabledPublishers map[int]struct{} - thresholdsPerDsp map[int]int - sync.RWMutex - serviceStop chan struct{} -} - -var fscConfigs fsc - -// Initializing reloader with cache-refresh default-expiry + 30 mins (to avoid DB load post cache refresh) -func Init(c cache.Cache, defaultExpiry int) { - //init fsc configs - fscConfigs = fsc{ - cache: c, - disabledPublishers: make(map[int]struct{}), - thresholdsPerDsp: make(map[int]int), - serviceStop: make(chan struct{}), - } - - go initiateReloader(c, defaultExpiry+1800) - glog.Info("Initialized FSC cache update reloaders for publisher and dsp fsc configuraitons") - -} - -// Exposed to access fsc object -func GetFscInstance() *fsc { - return &fscConfigs -} - -/* -IsUnderFSCThreshold:- returns fsc 1/0 based on: -1. When publisher has disabled FSC in DB, return 0 -2. If FSC is enabled for publisher(default), consider DSP-threshold , and predict value of fsc 0 or 1. -3. If dspId is not present return 0 -*/ -func (f *fsc) IsUnderFSCThreshold(pubid int, dspid int) int { - f.RLock() - defer f.RUnlock() - - if _, isPresent := f.disabledPublishers[pubid]; isPresent { - return 0 - } - - if dspThreshold, isPresent := f.thresholdsPerDsp[dspid]; isPresent && predictFscValue(dspThreshold) { - return 1 - } - return 0 -} - -func predictFscValue(threshold int) bool { - return (rand.Intn(100)) < threshold -} - -// fetch and update fsc config maps from DB -func updateFscConfigMapsFromCache(c cache.Cache) { - var err error - disabledPublishers, errPubFsc := c.GetFSCDisabledPublishers() - if errPubFsc != nil { - err = models.ErrorWrap(err, errPubFsc) - } - thresholdsPerDsp, errDspFsc := c.GetFSCThresholdPerDSP() - if errDspFsc != nil { - err = models.ErrorWrap(err, errDspFsc) - } - if err != nil { - glog.Error(err.Error()) - return - } - fscConfigs.Lock() - fscConfigs.disabledPublishers = disabledPublishers - fscConfigs.thresholdsPerDsp = thresholdsPerDsp - fscConfigs.Unlock() -} - -// IsFscApplicable returns true if fsc can be applied (fsc=1) -func IsFscApplicable(pubId int, seat string, dspId int) bool { - return models.IsPubmaticCorePartner(seat) && (fscConfigs.IsUnderFSCThreshold(pubId, dspId) != 0) -} - -// Exposed for test cases -func SetAndResetFscWithMockCache(mockDb cache.Cache, dspThresholdMap map[int]int) func() { - fscConfigs.cache = mockDb - //mockDspID entry for testing fsc=1 - fscConfigs.thresholdsPerDsp = dspThresholdMap - return func() { - fscConfigs.cache = nil - fscConfigs.thresholdsPerDsp = make(map[int]int) - fscConfigs.disabledPublishers = make(map[int]struct{}) - } -} diff --git a/modules/pubmatic/openwrap/fullscreenclickability/fullscreenclickability_test.go b/modules/pubmatic/openwrap/fullscreenclickability/fullscreenclickability_test.go deleted file mode 100644 index 6d39262d135..00000000000 --- a/modules/pubmatic/openwrap/fullscreenclickability/fullscreenclickability_test.go +++ /dev/null @@ -1,297 +0,0 @@ -package fullscreenclickability - -import ( - "errors" - - "reflect" - "testing" - - cache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache" - mock_dbcache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache/mock" - - "github.com/golang/mock/gomock" -) - -func TestPredictFscValue(t *testing.T) { - type args struct { - percentage int - } - tests := []struct { - name string - args args - want bool - }{ - { - name: "getting from predict output", - args: args{ - percentage: 100, - }, - want: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := predictFscValue(tt.args.percentage); got != tt.want { - t.Errorf("predictFscValue() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestInit(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - mockCache := mock_dbcache.NewMockCache(ctrl) - var defCpy = initiateReloader - initiateReloader = func(c cache.Cache, expiryTime int) {} - defer func() { - initiateReloader = defCpy - }() - type args struct { - defaultExpiry int - cache cache.Cache - } - tests := []struct { - name string - args args - }{ - {name: "test Init with valid args", - args: args{defaultExpiry: 1, - cache: mockCache, - }, - }, - } - for _, tt := range tests { - Init(tt.args.cache, tt.args.defaultExpiry) - } - -} - -func TestIsUnderFSCThreshold(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - mockCache := mock_dbcache.NewMockCache(ctrl) - type fields struct { - cache cache.Cache - disabledPublishers map[int]struct{} - thresholdsPerDsp map[int]int - } - type args struct { - pubid int - dspid int - } - tests := []struct { - name string - fields fields - args args - want int - setup func() - }{ - { - name: "When pubId,dspid and FSC maps are valid, pubID enabled(default) FSC return fsc with prediction algo", - args: args{ - pubid: 5890, - dspid: 6, - }, - setup: func() { - - }, - fields: fields{cache: mockCache, - disabledPublishers: map[int]struct{}{ - 58903: {}, - }, - thresholdsPerDsp: map[int]int{6: 100}, - }, - - want: 1, - }, - { - name: "When pubId,dspid and FSC maps are valid, pubID disabled FSC return fsc=0", - args: args{ - pubid: 5890, - dspid: 6, - }, - setup: func() { - - }, - fields: fields{cache: mockCache, - disabledPublishers: map[int]struct{}{ - 5890: {}, - }, - thresholdsPerDsp: map[int]int{6: 100}}, - want: 0, - }, - { - name: "When pubId,dspid are not present, pubID disabled FSC return fsc=0", - args: args{ - pubid: 58907, - dspid: 90, - }, - setup: func() { - - }, - fields: fields{cache: mockCache, - disabledPublishers: map[int]struct{}{ - 5890: {}, - }, - thresholdsPerDsp: map[int]int{6: 100}}, - want: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - f := fsc{ - cache: tt.fields.cache, - disabledPublishers: tt.fields.disabledPublishers, - thresholdsPerDsp: tt.fields.thresholdsPerDsp, - } - tt.setup() - if got := f.IsUnderFSCThreshold(tt.args.pubid, tt.args.dspid); got != tt.want { - t.Errorf("fsc.IsUnderFSCThreshold() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestUpdateFscConfigMapsFromCache(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - mockCache := mock_dbcache.NewMockCache(ctrl) - type args struct { - cache cache.Cache - } - type wantMaps struct { - fscDsp map[int]int - fscPub map[int]struct{} - } - tests := []struct { - name string - setup func() - args args - want wantMaps - }{ - { - name: "Cache returns valid values, set in fscConfigs Maps", - args: args{ - cache: mockCache, - }, - want: wantMaps{ - fscDsp: map[int]int{6: 70}, - fscPub: map[int]struct{}{ - 5890: {}}, - }, - setup: func() { - mockCache.EXPECT().GetFSCDisabledPublishers().Return(map[int]struct{}{5890: {}}, nil) - mockCache.EXPECT().GetFSCThresholdPerDSP().Return(map[int]int{6: 70}, nil) - }, - }, - { - name: "Cache returns DB error for both DSP and PUB fsc configs", - args: args{ - cache: mockCache, - }, - want: wantMaps{ - fscDsp: map[int]int{}, - fscPub: map[int]struct{}{}, - }, - setup: func() { - mockCache.EXPECT().GetFSCDisabledPublishers().Return(map[int]struct{}{}, errors.New("QUERY FAILED")) - mockCache.EXPECT().GetFSCThresholdPerDSP().Return(map[int]int{}, errors.New("QUERY FAILED")) - }, - }, - } - for _, tt := range tests { - - t.Run(tt.name, func(t *testing.T) { - tt.setup() - - updateFscConfigMapsFromCache(tt.args.cache) - if !reflect.DeepEqual(fscConfigs.disabledPublishers, tt.want.fscPub) { - t.Errorf("updateFscConfigMapsFromCache() for FscDisabledPublishers = %v, %v", fscConfigs.disabledPublishers, tt.want.fscPub) - } - if !reflect.DeepEqual(fscConfigs.thresholdsPerDsp, tt.want.fscDsp) { - t.Errorf("updateFscConfigMapsFromCache() for FscDspThresholds= %v, %v", fscConfigs.disabledPublishers, tt.want.fscDsp) - } - SetAndResetFscWithMockCache(mockCache, nil)() - }) - } -} - -func TestGetFscInstance(t *testing.T) { - tests := []struct { - name string - want *fsc - }{ - {name: "Return single FSC instance"}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := GetFscInstance(); reflect.TypeOf(got) == reflect.TypeOf(fsc{}) { - t.Errorf("GetFscInstance() gotType = %v, wantedType %v", reflect.TypeOf(got), reflect.TypeOf(fsc{})) - } - }) - } -} - -func TestIsFscApplicable(t *testing.T) { - ctrl := gomock.NewController(t) - mockCache := mock_dbcache.NewMockCache(ctrl) - defer ctrl.Finish() - defer SetAndResetFscWithMockCache(mockCache, map[int]int{6: 100})() - - type args struct { - pubId int - seat string - dspId int - } - tests := []struct { - name string - args args - want bool - }{ - { - name: "Valid Case1: All Params Correct", - args: args{ - pubId: 5890, - seat: "pubmatic", - dspId: 6, - }, - want: true, - }, - { - name: "Valid Case2: All Params Correct, seat is pubmatic alaias", - args: args{ - pubId: 5890, - seat: "pubmatic2", - dspId: 6, - }, - want: true, - }, - { - name: "Invalid Case1: DspId is 0", - args: args{ - pubId: 5890, - seat: "pubmatic", - dspId: 0, - }, - want: false, - }, - { - name: "Invalid Case2: different seat ", - args: args{ - pubId: 5890, - seat: "appnexus", - dspId: 6, - }, - want: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - if got := IsFscApplicable(tt.args.pubId, tt.args.seat, tt.args.dspId); got != tt.want { - t.Errorf("isFscApplicable() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/modules/pubmatic/openwrap/fullscreenclickability/reloader.go b/modules/pubmatic/openwrap/fullscreenclickability/reloader.go deleted file mode 100644 index 8e7649d75bc..00000000000 --- a/modules/pubmatic/openwrap/fullscreenclickability/reloader.go +++ /dev/null @@ -1,37 +0,0 @@ -package fullscreenclickability - -import ( - "time" - - "github.com/golang/glog" - "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache" -) - -// These reloaders will be called only to Forced-Write into Cache post timer based call. -var initiateReloader = func(c cache.Cache, expiryTime int) { - if expiryTime <= 0 { - return - } - glog.Info("FSC Reloader start") - ticker := time.NewTicker(time.Duration(expiryTime) * time.Second) - for { - //Populating FscConfigMaps - updateFscConfigMapsFromCache(c) - select { - case t := <-ticker.C: - glog.Info("FSC Reloader loads cache @", t) - case <-fscConfigs.serviceStop: - return - } - } -} - -func StopReloaderService() { - //updating serviceStop flag to true - close(fscConfigs.serviceStop) -} - -func ResetInitFscReloaderTest() { - //setting empty to mock routine - initiateReloader = func(c cache.Cache, expiryTime int) {} -} diff --git a/modules/pubmatic/openwrap/fullscreenclickability/reloader_test.go b/modules/pubmatic/openwrap/fullscreenclickability/reloader_test.go deleted file mode 100644 index f3ddf58a15c..00000000000 --- a/modules/pubmatic/openwrap/fullscreenclickability/reloader_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package fullscreenclickability - -import ( - "testing" - "time" - - "github.com/golang/mock/gomock" - cache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache" - mock_dbcache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache/mock" -) - -func TestInitiateReloader(t *testing.T) { - ctrl := gomock.NewController(t) - mockCache := mock_dbcache.NewMockCache(ctrl) - defer SetAndResetFscWithMockCache(mockCache, nil)() - currentChan := fscConfigs.serviceStop - defer func() { - ctrl.Finish() - fscConfigs.serviceStop = currentChan - }() - fscConfigs.serviceStop = make(chan struct{}) - type args struct { - defaultExpiry int - cache cache.Cache - } - - tests := []struct { - name string - args args - setup func() - }{ - { - name: "test InitateReloader with valid cache and invalid time, exit", - args: args{defaultExpiry: 0, - cache: mockCache, - }, - setup: func() {}, - }, - { - name: "test InitateReloader with valid cache and time, call once and exit", - args: args{defaultExpiry: 1000, - cache: mockCache, - }, - setup: func() { - mockCache.EXPECT().GetFSCDisabledPublishers().Return(map[int]struct{}{}, nil) - mockCache.EXPECT().GetFSCThresholdPerDSP().Return(map[int]int{}, nil) - }, - }, - } - for _, tt := range tests { - tt.setup() - fscConfigs.serviceStop = make(chan struct{}) - go initiateReloader(tt.args.cache, tt.args.defaultExpiry) - //closing channel to avoid infinite loop - StopReloaderService() - time.Sleep(1 * time.Millisecond) - } -} diff --git a/modules/pubmatic/openwrap/models/constants.go b/modules/pubmatic/openwrap/models/constants.go index fcaa546612a..fcadcbf8d6e 100755 --- a/modules/pubmatic/openwrap/models/constants.go +++ b/modules/pubmatic/openwrap/models/constants.go @@ -462,9 +462,9 @@ const ( AdunitConfigForLiveVersion = "GetAdunitConfigForLiveVersion" SlotNameHash = "GetSlotNameHash" PublisherVASTTagsQuery = "GetPublisherVASTTagsQuery" - AllFscDisabledPublishersQuery = "GetAllFscDisabledPublishersQuery" AllDspFscPcntQuery = "GetAllDspFscPcntQuery" AdUnitFailUnmarshal = "GetAdUnitUnmarshal" + PublisherFeatureMapQuery = "GetPublisherFeatureMapQuery" //DisplayVersionInnerQuery = "DisplayVersionInnerQuery" //LiveVersionInnerQuery = "LiveVersionInnerQuery" //PMSlotToMappings = "GetPMSlotToMappings" @@ -497,3 +497,11 @@ const ( Pbadslot = "pbadslot" GamAdServer = "gam" ) + +// constants for feature id + +const ( + FeatureFSC = 1 + FeatureTBF = 2 + FeatureAMPMultiFormat = 3 +) diff --git a/modules/pubmatic/openwrap/models/openwrap.go b/modules/pubmatic/openwrap/models/openwrap.go index 42e20b5d55f..e8be8c4d191 100644 --- a/modules/pubmatic/openwrap/models/openwrap.go +++ b/modules/pubmatic/openwrap/models/openwrap.go @@ -92,12 +92,13 @@ type RequestCtx struct { ReturnAllBidStatus bool // ReturnAllBidStatus stores the value of request.ext.prebid.returnallbidstatus Sshb string //Sshb query param to identify that the request executed heder-bidding or not, sshb=1(executed HB(8001)), sshb=2(reverse proxy set from HB(8001->8000)), sshb=""(direct request(8000)). - DCName string - CachePutMiss int // to be used in case of CTV JSON endpoint/amp/inapp-ott-video endpoint - CurrencyConversion func(from string, to string, value float64) (float64, error) `json:"-"` - MatchedImpression map[string]int - CustomDimensions map[string]CustomDimension - AmpVideoEnabled bool //AmpVideoEnabled indicates whether to include a Video object in an AMP request. + DCName string + CachePutMiss int // to be used in case of CTV JSON endpoint/amp/inapp-ott-video endpoint + CurrencyConversion func(from string, to string, value float64) (float64, error) `json:"-"` + MatchedImpression map[string]int + CustomDimensions map[string]CustomDimension + AmpVideoEnabled bool //AmpVideoEnabled indicates whether to include a Video object in an AMP request. + IsTBFFeatureEnabled bool } type OwBid struct { @@ -187,3 +188,9 @@ type CustomDimension struct { Value string `json:"value,omitempty"` SendToGAM *bool `json:"sendtoGAM,omitempty"` } + +// FeatureData struct to hold feature data from cache +type FeatureData struct { + Enabled int // feature enabled/disabled + Value string // feature value if any +} diff --git a/modules/pubmatic/openwrap/openwrap.go b/modules/pubmatic/openwrap/openwrap.go index 0193bb75ff0..115ef00d99c 100644 --- a/modules/pubmatic/openwrap/openwrap.go +++ b/modules/pubmatic/openwrap/openwrap.go @@ -19,11 +19,10 @@ import ( ow_gocache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache/gocache" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/config" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/database/mysql" - "github.com/prebid/prebid-server/modules/pubmatic/openwrap/fullscreenclickability" metrics "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics" metrics_cfg "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics/config" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" - "github.com/prebid/prebid-server/modules/pubmatic/openwrap/tbf" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/publisherfeature" ) const ( @@ -35,6 +34,7 @@ type OpenWrap struct { cache cache.Cache metricEngine metrics.MetricsEngine currencyConversion currency.Conversions + featureConfig publisherfeature.Feature } var ow *OpenWrap @@ -74,11 +74,9 @@ func initOpenWrap(rawCfg json.RawMessage, moduleDeps moduledeps.ModuleDeps) (Ope owCache := ow_gocache.New(cache, db, cfg.Cache, &metricEngine) - // Init FSC and related services - fullscreenclickability.Init(owCache, cfg.Cache.CacheDefaultExpiry) - - // Init TBF (tracking-beacon-first) feature related services - tbf.Init(cfg.Cache.CacheDefaultExpiry, owCache) + // Init Feature reloader service + featureConfig := publisherfeature.New(owCache, cfg.Cache.CacheDefaultExpiry) + featureConfig.Start() once.Do(func() { ow = &OpenWrap{ @@ -86,6 +84,7 @@ func initOpenWrap(rawCfg json.RawMessage, moduleDeps moduledeps.ModuleDeps) (Ope cache: owCache, metricEngine: &metricEngine, currencyConversion: moduleDeps.CurrencyConversion, + featureConfig: featureConfig, } }) return *ow, nil diff --git a/modules/pubmatic/openwrap/openwrap_sshb.go b/modules/pubmatic/openwrap/openwrap_sshb.go index fb1f9b122c3..5d9e8827b16 100644 --- a/modules/pubmatic/openwrap/openwrap_sshb.go +++ b/modules/pubmatic/openwrap/openwrap_sshb.go @@ -8,6 +8,7 @@ import ( "github.com/prebid/prebid-server/modules/pubmatic/openwrap/config" metrics "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/publisherfeature" vastmodels "github.com/prebid/prebid-server/modules/pubmatic/vastunwrap/models" ) @@ -46,6 +47,11 @@ func (ow *OpenWrap) SetMetricEngine(m metrics.MetricsEngine) { ow.metricEngine = m } +// GetFeature Temporary function to expose feature to SSHB +func (ow *OpenWrap) GetFeature() publisherfeature.Feature { + return ow.featureConfig +} + // GetVastUnwrapEnabled return whether to enable vastunwrap or not func GetVastUnwrapEnabled(rctx vastmodels.RequestCtx, VASTUnwrapTraffic int) bool { rCtx := models.RequestCtx{ diff --git a/modules/pubmatic/openwrap/publisherfeature/ampmultiformat.go b/modules/pubmatic/openwrap/publisherfeature/ampmultiformat.go new file mode 100644 index 00000000000..db26af75824 --- /dev/null +++ b/modules/pubmatic/openwrap/publisherfeature/ampmultiformat.go @@ -0,0 +1,36 @@ +package publisherfeature + +import ( + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" +) + +type ampMultiformat struct { + enabledPublishers map[int]struct{} +} + +// updateAmpMutiformatEnabledPublishers updates the ampMultiformat enabled publishers +func (fe *feature) updateAmpMutiformatEnabledPublishers() { + if fe.publisherFeature == nil { + return + } + + enabledPublishers := make(map[int]struct{}) + for pubID, feature := range fe.publisherFeature { + if feature[models.FeatureAMPMultiFormat].Enabled == 1 { + enabledPublishers[pubID] = struct{}{} + } + } + + fe.Lock() + fe.ampMultiformat.enabledPublishers = enabledPublishers + fe.Unlock() +} + +func (fe *feature) IsAmpMultiformatEnabled(pubid int) bool { + fe.RLock() + defer fe.RUnlock() + + _, isPresent := fe.ampMultiformat.enabledPublishers[pubid] + return isPresent + +} diff --git a/modules/pubmatic/openwrap/publisherfeature/ampmultiformat_test.go b/modules/pubmatic/openwrap/publisherfeature/ampmultiformat_test.go new file mode 100644 index 00000000000..f9cd45fce92 --- /dev/null +++ b/modules/pubmatic/openwrap/publisherfeature/ampmultiformat_test.go @@ -0,0 +1,129 @@ +package publisherfeature + +import ( + "testing" + + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" + "github.com/stretchr/testify/assert" +) + +func TestFeature_updateAmpMutiformatEnabledPublishers(t *testing.T) { + + type fields struct { + cache cache.Cache + publisherFeature map[int]map[int]models.FeatureData + ampMultiformat ampMultiformat + } + tests := []struct { + name string + fields fields + wantAmpMultiformatEnabledPublisher map[int]struct{} + }{ + { + name: "publisherFeature map is nil", + fields: fields{ + cache: nil, + publisherFeature: nil, + ampMultiformat: ampMultiformat{ + enabledPublishers: make(map[int]struct{}), + }, + }, + wantAmpMultiformatEnabledPublisher: map[int]struct{}{}, + }, + { + name: "update amp feature enabled pub", + fields: fields{ + cache: nil, + publisherFeature: map[int]map[int]models.FeatureData{ + 5890: { + 3: models.FeatureData{ + Enabled: 1, + }, + 1: models.FeatureData{ + Enabled: 1, + }, + }, + 5891: { + 3: models.FeatureData{ + Enabled: 1, + }, + 1: models.FeatureData{ + Enabled: 1, + }, + }, + }, + ampMultiformat: ampMultiformat{ + enabledPublishers: make(map[int]struct{}), + }, + }, + wantAmpMultiformatEnabledPublisher: map[int]struct{}{ + 5890: {}, + 5891: {}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fe := feature{ + publisherFeature: tt.fields.publisherFeature, + ampMultiformat: tt.fields.ampMultiformat, + } + fe.updateAmpMutiformatEnabledPublishers() + assert.Equal(t, tt.wantAmpMultiformatEnabledPublisher, fe.ampMultiformat.enabledPublishers) + }) + } +} + +func TestFeature_IsAmpMultiformatEnabled(t *testing.T) { + type fields struct { + ampMultiformat ampMultiformat + } + type args struct { + pubid int + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + { + name: "amp feature enabled pub", + args: args{ + pubid: 5890, + }, + fields: fields{ + ampMultiformat: ampMultiformat{ + enabledPublishers: map[int]struct{}{ + 5890: {}, + }, + }, + }, + want: true, + }, + { + name: "amp feature disabled pub", + args: args{ + pubid: 5891, + }, + fields: fields{ + ampMultiformat: ampMultiformat{ + enabledPublishers: map[int]struct{}{ + 5890: {}, + }, + }, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fe := &feature{ + ampMultiformat: tt.fields.ampMultiformat, + } + got := fe.IsAmpMultiformatEnabled(tt.args.pubid) + assert.Equal(t, tt.want, got, tt.name) + }) + } +} diff --git a/modules/pubmatic/openwrap/publisherfeature/feature.go b/modules/pubmatic/openwrap/publisherfeature/feature.go new file mode 100644 index 00000000000..8440f55b036 --- /dev/null +++ b/modules/pubmatic/openwrap/publisherfeature/feature.go @@ -0,0 +1,7 @@ +package publisherfeature + +type Feature interface { + IsFscApplicable(pubId int, seat string, dspId int) bool + IsAmpMultiformatEnabled(pubId int) bool + IsTBFFeatureEnabled(pubid int, profid int) bool +} diff --git a/modules/pubmatic/openwrap/publisherfeature/fullscreenclickability.go b/modules/pubmatic/openwrap/publisherfeature/fullscreenclickability.go new file mode 100644 index 00000000000..dd28c23f649 --- /dev/null +++ b/modules/pubmatic/openwrap/publisherfeature/fullscreenclickability.go @@ -0,0 +1,66 @@ +package publisherfeature + +import ( + "math/rand" + + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" +) + +type fsc struct { + disabledPublishers map[int]struct{} + thresholdsPerDsp map[int]int +} + +// updateFscConfigMapsFromCache update the fsc disabled publishers and thresholds per dsp +func (fe *feature) updateFscConfigMapsFromCache() error { + thresholdsPerDsp, err := fe.cache.GetFSCThresholdPerDSP() + if err != nil { + return err + } + + disabledPublishers := make(map[int]struct{}) + if fe.publisherFeature != nil { + for pubID, feature := range fe.publisherFeature { + if val, ok := feature[models.FeatureFSC]; ok && val.Enabled == 0 { + disabledPublishers[pubID] = struct{}{} + } + } + } + + fe.Lock() + fe.fsc.disabledPublishers = disabledPublishers + if thresholdsPerDsp != nil { + fe.fsc.thresholdsPerDsp = thresholdsPerDsp + } + fe.Unlock() + return nil +} + +/* +IsUnderFSCThreshold:- returns fsc 1/0 based on: +1. When publisher has disabled FSC in DB, return 0 +2. If FSC is enabled for publisher(default), consider DSP-threshold , and predict value of fsc 0 or 1. +3. If dspId is not present return 0 +*/ +func (fe *feature) isUnderFSCThreshold(pubid int, dspid int) int { + fe.RLock() + defer fe.RUnlock() + + if _, isPresent := fe.fsc.disabledPublishers[pubid]; isPresent { + return 0 + } + + if dspThreshold, isPresent := fe.fsc.thresholdsPerDsp[dspid]; isPresent && predictFscValue(dspThreshold) { + return 1 + } + return 0 +} + +func predictFscValue(threshold int) bool { + return (rand.Intn(100)) < threshold +} + +// IsFscApplicable returns true if fsc can be applied (fsc=1) +func (fe *feature) IsFscApplicable(pubId int, seat string, dspId int) bool { + return models.IsPubmaticCorePartner(seat) && (fe.isUnderFSCThreshold(pubId, dspId) != 0) +} diff --git a/modules/pubmatic/openwrap/publisherfeature/fullscreenclickability_test.go b/modules/pubmatic/openwrap/publisherfeature/fullscreenclickability_test.go new file mode 100644 index 00000000000..1628ab4f54f --- /dev/null +++ b/modules/pubmatic/openwrap/publisherfeature/fullscreenclickability_test.go @@ -0,0 +1,338 @@ +package publisherfeature + +import ( + "errors" + "testing" + + "github.com/golang/mock/gomock" + mock_cache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache/mock" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" + "github.com/stretchr/testify/assert" +) + +func TestFeature_updateFscConfigMapsFromCache(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mockCache := mock_cache.NewMockCache(ctrl) + type fields struct { + publisherFeature map[int]map[int]models.FeatureData + fsc fsc + } + type wantMaps struct { + disabledPublishers map[int]struct{} + thresholdsPerDsp map[int]int + } + tests := []struct { + name string + fields fields + setup func() + wantErr bool + want wantMaps + }{ + { + name: "Cache returns valid thresholdsPerDsp and disabled publishers updated from publisherFeature map", + fields: fields{ + publisherFeature: map[int]map[int]models.FeatureData{ + 5890: { + 1: models.FeatureData{ + Enabled: 0, + }, + }, + }, + fsc: fsc{ + disabledPublishers: make(map[int]struct{}), + thresholdsPerDsp: make(map[int]int), + }, + }, + setup: func() { + mockCache.EXPECT().GetFSCThresholdPerDSP().Return(map[int]int{6: 70}, nil) + }, + want: wantMaps{ + thresholdsPerDsp: map[int]int{6: 70}, + disabledPublishers: map[int]struct{}{ + 5890: {}, + }, + }, + wantErr: false, + }, + { + name: "Cache returns DB error for thresholdsPerDsp", + fields: fields{ + publisherFeature: map[int]map[int]models.FeatureData{}, + fsc: fsc{ + disabledPublishers: make(map[int]struct{}), + thresholdsPerDsp: make(map[int]int), + }, + }, + setup: func() { + mockCache.EXPECT().GetFSCThresholdPerDSP().Return(map[int]int{}, errors.New("QUERY FAILED")) + }, + wantErr: true, + want: wantMaps{ + disabledPublishers: map[int]struct{}{}, + thresholdsPerDsp: map[int]int{}, + }, + }, + { + name: "publisherFeature map is empty and cache returns valid thresholdsPerDsp", + fields: fields{ + publisherFeature: map[int]map[int]models.FeatureData{}, + fsc: fsc{ + disabledPublishers: make(map[int]struct{}), + thresholdsPerDsp: make(map[int]int), + }, + }, + setup: func() { + mockCache.EXPECT().GetFSCThresholdPerDSP().Return(map[int]int{ + 6: 70, + }, nil) + }, + wantErr: false, + want: wantMaps{ + disabledPublishers: map[int]struct{}{}, + thresholdsPerDsp: map[int]int{ + 6: 70, + }, + }, + }, + { + name: "cache returns nil thresholdsPerDsp and publisherFeature map is not empty", + fields: fields{ + publisherFeature: map[int]map[int]models.FeatureData{ + 5890: { + 1: models.FeatureData{ + Enabled: 0, + }, + }, + }, + fsc: fsc{ + disabledPublishers: make(map[int]struct{}), + thresholdsPerDsp: make(map[int]int), + }, + }, + setup: func() { + mockCache.EXPECT().GetFSCThresholdPerDSP().Return(nil, nil) + }, + wantErr: false, + want: wantMaps{ + disabledPublishers: map[int]struct{}{ + 5890: {}, + }, + thresholdsPerDsp: map[int]int{}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.setup != nil { + tt.setup() + } + fe := feature{ + cache: mockCache, + publisherFeature: tt.fields.publisherFeature, + fsc: tt.fields.fsc, + } + if err := fe.updateFscConfigMapsFromCache(); (err != nil) != tt.wantErr { + t.Errorf("feature.updateFscConfigMapsFromCache() error = %v, wantErr %v", err, tt.wantErr) + } + assert.Equal(t, tt.want.thresholdsPerDsp, fe.fsc.thresholdsPerDsp) + assert.Equal(t, tt.want.disabledPublishers, fe.fsc.disabledPublishers) + }) + } +} + +func TestPredictFscValue(t *testing.T) { + type args struct { + percentage int + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "getting from predict output", + args: args{ + percentage: 100, + }, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := predictFscValue(tt.args.percentage); got != tt.want { + t.Errorf("predictFscValue() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestIsUnderFSCThreshold(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mockCache := mock_cache.NewMockCache(ctrl) + type fields struct { + fsc fsc + } + type args struct { + pubid int + dspid int + } + tests := []struct { + name string + fields fields + args args + want int + }{ + { + name: "When pubId,dspid and FSC maps are valid, pubID enabled(default) FSC return fsc with prediction algo", + args: args{ + pubid: 5890, + dspid: 6, + }, + fields: fields{ + fsc: fsc{ + disabledPublishers: map[int]struct{}{ + 58903: {}, + }, + thresholdsPerDsp: map[int]int{6: 100}, + }, + }, + want: 1, + }, + { + name: "When pubId,dspid and FSC maps are valid, pubID disabled FSC return fsc=0", + args: args{ + pubid: 5890, + dspid: 6, + }, + fields: fields{ + fsc: fsc{ + disabledPublishers: map[int]struct{}{ + 5890: {}, + }, + thresholdsPerDsp: map[int]int{6: 100}}, + }, + want: 0, + }, + { + name: "When pubId,dspid are not present, pubID disabled FSC return fsc=0", + args: args{ + pubid: 58907, + dspid: 90, + }, + fields: fields{ + fsc: fsc{ + disabledPublishers: map[int]struct{}{ + 5890: {}, + }, + thresholdsPerDsp: map[int]int{6: 100}, + }, + }, + want: 0, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fe := feature{ + cache: mockCache, + fsc: tt.fields.fsc, + } + if got := fe.isUnderFSCThreshold(tt.args.pubid, tt.args.dspid); got != tt.want { + t.Errorf("fsc.IsUnderFSCThreshold() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestIsFscApplicable(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mockCache := mock_cache.NewMockCache(ctrl) + + type fields struct { + fsc fsc + } + type args struct { + pubId int + seat string + dspId int + } + tests := []struct { + name string + args args + want bool + fields fields + }{ + { + name: "Valid Case1: All Params Correct", + args: args{ + pubId: 5890, + seat: "pubmatic", + dspId: 6, + }, + fields: fields{ + fsc: fsc{ + disabledPublishers: map[int]struct{}{ + 58903: {}, + }, + thresholdsPerDsp: map[int]int{6: 100}, + }, + }, + want: true, + }, + { + name: "Valid Case2: All Params Correct, seat is pubmatic alaias", + args: args{ + pubId: 5890, + seat: "pubmatic2", + dspId: 6, + }, + fields: fields{ + fsc: fsc{ + disabledPublishers: map[int]struct{}{ + 58903: {}, + }, + thresholdsPerDsp: map[int]int{6: 100}, + }, + }, + want: true, + }, + { + name: "Invalid Case1: DspId is 0", + args: args{ + pubId: 5890, + seat: "pubmatic", + dspId: 0, + }, + fields: fields{ + fsc: fsc{ + disabledPublishers: map[int]struct{}{ + 58903: {}, + }, + thresholdsPerDsp: map[int]int{6: 100}, + }, + }, + want: false, + }, + { + name: "Invalid Case2: different seat ", + args: args{ + pubId: 5890, + seat: "appnexus", + dspId: 6, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fe := feature{ + cache: mockCache, + fsc: tt.fields.fsc, + } + got := fe.IsFscApplicable(tt.args.pubId, tt.args.seat, tt.args.dspId) + assert.Equal(t, tt.want, got, tt.name) + }) + } +} diff --git a/modules/pubmatic/openwrap/publisherfeature/mock/mock.go b/modules/pubmatic/openwrap/publisherfeature/mock/mock.go new file mode 100644 index 00000000000..d8930b19e56 --- /dev/null +++ b/modules/pubmatic/openwrap/publisherfeature/mock/mock.go @@ -0,0 +1,75 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/PubMatic-OpenWrap/prebid-server/modules/pubmatic/openwrap/publisherfeature (interfaces: Feature) + +// Package mock_publisherfeature is a generated GoMock package. +package mock_publisherfeature + +import ( + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockFeature is a mock of Feature interface +type MockFeature struct { + ctrl *gomock.Controller + recorder *MockFeatureMockRecorder +} + +// MockFeatureMockRecorder is the mock recorder for MockFeature +type MockFeatureMockRecorder struct { + mock *MockFeature +} + +// NewMockFeature creates a new mock instance +func NewMockFeature(ctrl *gomock.Controller) *MockFeature { + mock := &MockFeature{ctrl: ctrl} + mock.recorder = &MockFeatureMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockFeature) EXPECT() *MockFeatureMockRecorder { + return m.recorder +} + +// IsAmpMultiformatEnabled mocks base method +func (m *MockFeature) IsAmpMultiformatEnabled(arg0 int) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsAmpMultiformatEnabled", arg0) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsAmpMultiformatEnabled indicates an expected call of IsAmpMultiformatEnabled +func (mr *MockFeatureMockRecorder) IsAmpMultiformatEnabled(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsAmpMultiformatEnabled", reflect.TypeOf((*MockFeature)(nil).IsAmpMultiformatEnabled), arg0) +} + +// IsFscApplicable mocks base method +func (m *MockFeature) IsFscApplicable(arg0 int, arg1 string, arg2 int) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsFscApplicable", arg0, arg1, arg2) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsFscApplicable indicates an expected call of IsFscApplicable +func (mr *MockFeatureMockRecorder) IsFscApplicable(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsFscApplicable", reflect.TypeOf((*MockFeature)(nil).IsFscApplicable), arg0, arg1, arg2) +} + +// IsTBFFeatureEnabled mocks base method +func (m *MockFeature) IsTBFFeatureEnabled(arg0, arg1 int) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsTBFFeatureEnabled", arg0, arg1) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsTBFFeatureEnabled indicates an expected call of IsTBFFeatureEnabled +func (mr *MockFeatureMockRecorder) IsTBFFeatureEnabled(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsTBFFeatureEnabled", reflect.TypeOf((*MockFeature)(nil).IsTBFFeatureEnabled), arg0, arg1) +} diff --git a/modules/pubmatic/openwrap/publisherfeature/reloader.go b/modules/pubmatic/openwrap/publisherfeature/reloader.go new file mode 100644 index 00000000000..9f134ea9043 --- /dev/null +++ b/modules/pubmatic/openwrap/publisherfeature/reloader.go @@ -0,0 +1,100 @@ +package publisherfeature + +import ( + "sync" + "time" + + "github.com/golang/glog" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" +) + +type feature struct { + cache cache.Cache + serviceStop chan struct{} + sync.RWMutex + defaultExpiry int + publisherFeature map[int]map[int]models.FeatureData + fsc fsc + tbf tbf + ampMultiformat ampMultiformat +} + +var fe *feature +var fOnce sync.Once + +func New(c cache.Cache, defaultExpiry int) *feature { + fOnce.Do(func() { + fe = &feature{ + cache: c, + serviceStop: make(chan struct{}), + defaultExpiry: defaultExpiry, + publisherFeature: make(map[int]map[int]models.FeatureData), + fsc: fsc{ + disabledPublishers: make(map[int]struct{}), + thresholdsPerDsp: make(map[int]int), + }, + tbf: tbf{ + pubProfileTraffic: make(map[int]map[int]int), + }, + ampMultiformat: ampMultiformat{ + enabledPublishers: make(map[int]struct{}), + }, + } + }) + return fe +} + +func (fe *feature) Start() { + go initReloader(fe) + glog.Info("Initialized feature reloader") +} + +func (fe *feature) Stop() { + //updating serviceStop flag to true + close(fe.serviceStop) +} + +// Initializing reloader with cache-refresh default-expiry + 30 mins (to avoid DB load post cache refresh) +var initReloader = func(fe *feature) { + if fe.defaultExpiry <= 0 { + return + } + glog.Info("Feature reloader start") + ticker := time.NewTicker(time.Duration(fe.defaultExpiry+1800) * time.Second) + for { + //Populating feature config maps from cache + fe.updateFeatureConfigMaps() + select { + case t := <-ticker.C: + glog.Info("Feature Reloader loads cache @", t) + case <-fe.serviceStop: + return + } + } +} + +func (fe *feature) updateFeatureConfigMaps() { + var err error + var errFscUpdate error + + publisherFeatureMap, errPubFeature := fe.cache.GetPublisherFeatureMap() + if errPubFeature != nil { + err = models.ErrorWrap(err, errPubFeature) + } + + if publisherFeatureMap != nil { + fe.publisherFeature = publisherFeatureMap + } + + if errFscUpdate = fe.updateFscConfigMapsFromCache(); errFscUpdate != nil { + err = models.ErrorWrap(err, errFscUpdate) + } + + fe.updateTBFConfigMap() + fe.updateAmpMutiformatEnabledPublishers() + + if err != nil { + glog.Error(err.Error()) + } +} diff --git a/modules/pubmatic/openwrap/publisherfeature/reloader_test.go b/modules/pubmatic/openwrap/publisherfeature/reloader_test.go new file mode 100644 index 00000000000..8bb1028dd75 --- /dev/null +++ b/modules/pubmatic/openwrap/publisherfeature/reloader_test.go @@ -0,0 +1,266 @@ +package publisherfeature + +import ( + "errors" + "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache" + mock_cache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache/mock" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" + "github.com/stretchr/testify/assert" +) + +func TestNew(t *testing.T) { + type args struct { + c cache.Cache + defaultExpiry int + } + tests := []struct { + name string + args args + }{ + { + name: "test", + args: args{ + c: nil, + defaultExpiry: 0, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := New(tt.args.c, tt.args.defaultExpiry) + assert.Equal(t, fe, got) + }) + } +} + +func TestInitiateReloader(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mockCache := mock_cache.NewMockCache(ctrl) + + type args struct { + defaultExpiry int + cache cache.Cache + } + + tests := []struct { + name string + args args + setup func() + }{ + { + name: "test InitateReloader with valid cache and invalid time, exit", + args: args{ + defaultExpiry: 0, + cache: mockCache, + }, + setup: func() {}, + }, + { + name: "test InitateReloader with valid cache and time, call once and exit", + args: args{ + defaultExpiry: 1000, + cache: mockCache, + }, + setup: func() { + mockCache.EXPECT().GetPublisherFeatureMap().Return(map[int]map[int]models.FeatureData{}, nil) + mockCache.EXPECT().GetFSCThresholdPerDSP().Return(map[int]int{}, nil) + }, + }, + } + for _, tt := range tests { + tt.setup() + feature := &feature{ + cache: tt.args.cache, + defaultExpiry: tt.args.defaultExpiry, + serviceStop: make(chan struct{}), + } + go initReloader(feature) + //closing channel to avoid infinite loop + feature.Stop() + time.Sleep(1 * time.Millisecond) + } +} + +func Test_feature_Start(t *testing.T) { + + tests := []struct { + name string + setup func() + }{ + { + name: "test", + + setup: func() { + initReloader = func(fe *feature) {} + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setup() + fe := &feature{} + fe.Start() + }) + } +} + +func Test_feature_updateFeatureConfigMaps(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mockCache := mock_cache.NewMockCache(ctrl) + + type fields struct { + cache cache.Cache + } + type want struct { + fsc fsc + tbf tbf + ampMultiformat ampMultiformat + } + tests := []struct { + name string + fields fields + setup func() + want want + }{ + { + name: "publisher feature map query failed and fsc threshold per DSP query success", + fields: fields{ + cache: mockCache, + }, + setup: func() { + mockCache.EXPECT().GetPublisherFeatureMap().Return(nil, errors.New("QUERY FAILED")) + mockCache.EXPECT().GetFSCThresholdPerDSP().Return(map[int]int{ + 6: 100, + }, nil) + }, + want: want{ + fsc: fsc{ + disabledPublishers: map[int]struct{}{}, + thresholdsPerDsp: map[int]int{ + 6: 100, + }, + }, + ampMultiformat: ampMultiformat{ + enabledPublishers: map[int]struct{}{}, + }, + tbf: tbf{ + pubProfileTraffic: map[int]map[int]int{}, + }, + }, + }, + { + name: "publisher feature map query success but fsc threshold per DSP query failed", + fields: fields{ + cache: mockCache, + }, + setup: func() { + mockCache.EXPECT().GetPublisherFeatureMap().Return(map[int]map[int]models.FeatureData{ + 5890: { + models.FeatureFSC: { + Enabled: 0, + }, + models.FeatureTBF: { + Enabled: 1, + Value: `{"1234": 100}`, + }, + models.FeatureAMPMultiFormat: { + Enabled: 1, + }, + }, + }, nil) + mockCache.EXPECT().GetFSCThresholdPerDSP().Return(nil, errors.New("QUERY FAILED")) + }, + want: want{ + fsc: fsc{ + disabledPublishers: map[int]struct{}{}, + thresholdsPerDsp: map[int]int{}, + }, + ampMultiformat: ampMultiformat{ + enabledPublishers: map[int]struct{}{ + 5890: {}, + }, + }, + tbf: tbf{ + pubProfileTraffic: map[int]map[int]int{ + 5890: { + 1234: 100, + }, + }, + }, + }, + }, + { + name: "both queries success and all feature deatils updated successfully", + fields: fields{ + cache: mockCache, + }, + setup: func() { + mockCache.EXPECT().GetPublisherFeatureMap().Return(map[int]map[int]models.FeatureData{ + 5890: { + models.FeatureFSC: { + Enabled: 0, + }, + models.FeatureTBF: { + Enabled: 1, + Value: `{"1234": 100}`, + }, + models.FeatureAMPMultiFormat: { + Enabled: 1, + }, + }, + }, nil) + mockCache.EXPECT().GetFSCThresholdPerDSP().Return(map[int]int{6: 100}, nil) + }, + want: want{ + fsc: fsc{ + disabledPublishers: map[int]struct{}{ + 5890: {}, + }, + thresholdsPerDsp: map[int]int{ + 6: 100, + }, + }, + ampMultiformat: ampMultiformat{ + enabledPublishers: map[int]struct{}{ + 5890: {}, + }, + }, + tbf: tbf{ + pubProfileTraffic: map[int]map[int]int{ + 5890: { + 1234: 100, + }, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setup() + fe := &feature{ + cache: tt.fields.cache, + fsc: fsc{ + disabledPublishers: make(map[int]struct{}), + thresholdsPerDsp: make(map[int]int), + }, + tbf: tbf{ + pubProfileTraffic: make(map[int]map[int]int), + }, + ampMultiformat: ampMultiformat{ + enabledPublishers: make(map[int]struct{}), + }, + } + fe.updateFeatureConfigMaps() + assert.Equal(t, tt.want.fsc, fe.fsc, tt.name) + assert.Equal(t, tt.want.tbf, fe.tbf, tt.name) + assert.Equal(t, tt.want.ampMultiformat, fe.ampMultiformat, tt.name) + }) + } +} diff --git a/modules/pubmatic/openwrap/publisherfeature/tbf.go b/modules/pubmatic/openwrap/publisherfeature/tbf.go new file mode 100644 index 00000000000..9ba4514fb94 --- /dev/null +++ b/modules/pubmatic/openwrap/publisherfeature/tbf.go @@ -0,0 +1,87 @@ +// Package tbf provides functionalities related to the Tracking-Beacon-First (TBF) feature. +// The package manages the configuration of the TBF feature, which includes publisher-profile-level +// traffic data, caching, and service reloader functionality. +package publisherfeature + +import ( + "encoding/json" + "math/rand" + "sync" + + "github.com/golang/glog" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" +) + +// tbf structure holds the configuration of Tracking-Beacon-First feature +type tbf struct { + pubProfileTraffic map[int]map[int]int + *sync.RWMutex +} + +// limitTBFTrafficValues validates the traffic values from the given map of pub-prof-traffic +// to ensure they are constrained between 0 and 100 (inclusive). +// If a value is below 0 or above 100, it is set to 0. The original map is modified in place. +func limitTBFTrafficValues(pubProfTraffic map[int]map[int]int) { + for _, profTraffic := range pubProfTraffic { + for profID, traffic := range profTraffic { + if traffic < 0 || traffic > 100 { + profTraffic[profID] = 0 + } + } + } +} + +// updateTBFConfigMap updates the TBF configuration maps from the publisher-feature data. +func (fe *feature) updateTBFConfigMap() { + if fe.publisherFeature == nil { + return + } + + pubProfileTrafficRate := make(map[int]map[int]int) + + for pubID, feature := range fe.publisherFeature { + featureDetails, ok := feature[models.FeatureTBF] + if ok && featureDetails.Enabled == 1 && len(featureDetails.Value) > 0 { + var profileTrafficRate map[int]int + if err := json.Unmarshal([]byte(featureDetails.Value), &profileTrafficRate); err != nil { + glog.Error("ErrJSONUnmarshalFailed TBFProfileTrafficRate pubid: ", pubID, " trafficDetails: ", featureDetails.Value, " err: ", err.Error()) + continue + } + pubProfileTrafficRate[pubID] = profileTrafficRate + } + } + + limitTBFTrafficValues(pubProfileTrafficRate) + + fe.Lock() + fe.tbf.pubProfileTraffic = pubProfileTrafficRate + fe.Unlock() +} + +// IsEnabledTBFFeature returns false if TBF feature is disabled for pub-profile combination +// It makes use of predictTBFValue function to predict whether the request is eligible +// to track beacon first before adm based on the provided traffic percentage. +// This function is safe for concurrent access. +func (fe *feature) IsTBFFeatureEnabled(pubid int, profid int) bool { + + var trafficRate int + var present bool + + fe.RLock() + if fe.tbf.pubProfileTraffic != nil { + trafficRate, present = fe.tbf.pubProfileTraffic[pubid][profid] + } + fe.RUnlock() + + if !present { + return false + } + + return predictTBFValue(trafficRate) +} + +// predictTBFValue predicts whether a request is eligible for TBF feature +// based on the provided trafficRate value.“ +func predictTBFValue(trafficRate int) bool { + return rand.Intn(100) < trafficRate +} diff --git a/modules/pubmatic/openwrap/publisherfeature/tbf_test.go b/modules/pubmatic/openwrap/publisherfeature/tbf_test.go new file mode 100644 index 00000000000..79474e26245 --- /dev/null +++ b/modules/pubmatic/openwrap/publisherfeature/tbf_test.go @@ -0,0 +1,283 @@ +package publisherfeature + +import ( + "testing" + + "github.com/golang/mock/gomock" + mock_cache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache/mock" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" + "github.com/stretchr/testify/assert" +) + +func TestUpdateTBFConfigMapsFromCache(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mockCache := mock_cache.NewMockCache(ctrl) + + type feilds struct { + publisherFeature map[int]map[int]models.FeatureData + tbf tbf + } + type want struct { + err error + pubProfileTraffic map[int]map[int]int + } + + tests := []struct { + name string + want want + feilds feilds + }{ + { + name: "publisherFeature_map_is_nil", + feilds: feilds{ + publisherFeature: nil, + }, + want: want{ + err: nil, + pubProfileTraffic: nil, + }, + }, + { + name: "successfully_update_tbf_config_map", + feilds: feilds{ + publisherFeature: map[int]map[int]models.FeatureData{ + 5890: { + 2: { + Enabled: 1, + Value: `{"1234": 100}`, + }, + }, + }, + tbf: tbf{ + pubProfileTraffic: make(map[int]map[int]int), + }, + }, + want: want{ + pubProfileTraffic: map[int]map[int]int{5890: {1234: 100}}, + err: nil, + }, + }, + { + name: "failed_to_unmarshal_profile_traffic_rate", + feilds: feilds{ + publisherFeature: map[int]map[int]models.FeatureData{ + 5890: { + 2: { + Enabled: 1, + Value: `"1234": 100}`, + }, + }, + }, + tbf: tbf{ + pubProfileTraffic: make(map[int]map[int]int), + }, + }, + want: want{ + pubProfileTraffic: map[int]map[int]int{}, + err: nil, + }, + }, + { + name: "empty_profile_traffic_rate", + feilds: feilds{ + publisherFeature: map[int]map[int]models.FeatureData{ + 5890: { + 2: { + Enabled: 1, + Value: "", + }, + }, + }, + tbf: tbf{ + pubProfileTraffic: make(map[int]map[int]int), + }, + }, + want: want{ + pubProfileTraffic: map[int]map[int]int{}, + err: nil, + }, + }, + { + name: "limit_traffic_values", + feilds: feilds{ + publisherFeature: map[int]map[int]models.FeatureData{ + 5890: { + 2: { + Enabled: 1, + Value: `{"1234": 200}`, + }, + }, + 5891: { + 2: { + Enabled: 1, + Value: `{"222": -5}`, + }, + }, + }, + tbf: tbf{ + pubProfileTraffic: make(map[int]map[int]int), + }, + }, + want: want{ + pubProfileTraffic: map[int]map[int]int{5890: {1234: 0}, 5891: {222: 0}}, + err: nil, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fe := feature{ + cache: mockCache, + publisherFeature: tt.feilds.publisherFeature, + tbf: tt.feilds.tbf, + } + fe.updateTBFConfigMap() + assert.Equal(t, tt.want.pubProfileTraffic, fe.tbf.pubProfileTraffic, tt.name) + }) + } +} + +func TestPredictTBFValue(t *testing.T) { + type args struct { + percentage int + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "100_pct_traffic", + args: args{ + percentage: 100, + }, + want: true, + }, + { + name: "0_pct_traffic", + args: args{ + percentage: 0, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := predictTBFValue(tt.args.percentage) + assert.Equal(t, tt.want, got, tt.name) + }) + } +} + +func TestIsEnabledTBFFeature(t *testing.T) { + type feilds struct { + tbf tbf + } + type args struct { + pubidstr int + profid int + } + tests := []struct { + name string + args args + feilds feilds + want bool + }{ + { + name: "pubProfileTraffic_map_is_nil", + args: args{ + pubidstr: 5890, + profid: 1234, + }, + feilds: feilds{ + tbf: tbf{ + pubProfileTraffic: nil, + }, + }, + want: false, + }, + { + name: "pub_prof_absent_in_map", + args: args{ + pubidstr: 5890, + profid: 1234, + }, + feilds: feilds{ + tbf: tbf{ + pubProfileTraffic: map[int]map[int]int{ + 5891: {1234: 100}, + }, + }, + }, + want: false, + }, + { + name: "pub_prof_present_in_map", + args: args{ + pubidstr: 5890, + profid: 1234, + }, + feilds: feilds{ + tbf: tbf{ + pubProfileTraffic: map[int]map[int]int{ + 5890: {1234: 100}, + }, + }, + }, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fe := &feature{ + tbf: tt.feilds.tbf, + } + got := fe.IsTBFFeatureEnabled(tt.args.pubidstr, tt.args.profid) + assert.Equal(t, tt.want, got, tt.name) + }) + } +} + +func TestLimitTBFTrafficValues(t *testing.T) { + + tests := []struct { + name string + pubProfTraffic map[int]map[int]int + wantpubProfTraffic map[int]map[int]int + }{ + { + name: "pubProfTraffic_map_is_nil", + pubProfTraffic: nil, + wantpubProfTraffic: nil, + }, + { + name: "nil_prof_traffic_map", + pubProfTraffic: map[int]map[int]int{ + 1: nil, + }, + wantpubProfTraffic: map[int]map[int]int{ + 1: nil, + }, + }, + { + name: "negative_and_higher_than_100_values", + pubProfTraffic: map[int]map[int]int{ + 5890: {123: -100}, + 5891: {123: 50}, + 5892: {123: 200}, + }, + wantpubProfTraffic: map[int]map[int]int{ + 5890: {123: 0}, + 5891: {123: 50}, + 5892: {123: 0}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + limitTBFTrafficValues(tt.pubProfTraffic) + assert.Equal(t, tt.wantpubProfTraffic, tt.pubProfTraffic, tt.name) + }) + } +} diff --git a/modules/pubmatic/openwrap/targeting.go b/modules/pubmatic/openwrap/targeting.go index afb59fb5253..cc1216ac7e5 100644 --- a/modules/pubmatic/openwrap/targeting.go +++ b/modules/pubmatic/openwrap/targeting.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/prebid/openrtb/v19/openrtb2" - "github.com/prebid/prebid-server/modules/pubmatic/openwrap/fullscreenclickability" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/utils" "github.com/prebid/prebid-server/openrtb_ext" @@ -52,7 +51,7 @@ func addInAppTargettingKeys(targeting map[string]string, seat string, ecpm float } } -func addPWTTargetingForBid(rctx models.RequestCtx, bidResponse *openrtb2.BidResponse) (droppedBids map[string][]openrtb2.Bid, warnings []string) { +func (m OpenWrap) addPWTTargetingForBid(rctx models.RequestCtx, bidResponse *openrtb2.BidResponse) (droppedBids map[string][]openrtb2.Bid, warnings []string) { if !rctx.SendAllBids { droppedBids = make(map[string][]openrtb2.Bid) } @@ -108,7 +107,7 @@ func addPWTTargetingForBid(rctx models.RequestCtx, bidResponse *openrtb2.BidResp if rctx.SendAllBids { bidCtx.Winner = 1 } - if fullscreenclickability.IsFscApplicable(rctx.PubID, seatBid.Seat, bidCtx.DspId) { + if m.featureConfig.IsFscApplicable(rctx.PubID, seatBid.Seat, bidCtx.DspId) { bidCtx.Fsc = 1 } } else if !rctx.SendAllBids { diff --git a/modules/pubmatic/openwrap/tbf/tbf.go b/modules/pubmatic/openwrap/tbf/tbf.go deleted file mode 100644 index b4cddfa815a..00000000000 --- a/modules/pubmatic/openwrap/tbf/tbf.go +++ /dev/null @@ -1,133 +0,0 @@ -// Package tbf provides functionalities related to the Tracking-Beacon-First (TBF) feature. -// The package manages the configuration of the TBF feature, which includes publisher-profile-level -// traffic data, caching, and service reloader functionality. -package tbf - -import ( - "math/rand" - "sync" - "time" - - "github.com/golang/glog" - "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache" -) - -// tbf structure holds the configuration of Tracking-Beacon-First feature -type tbf struct { - pubProfileTraffic map[int]map[int]int - - cache cache.Cache - *sync.RWMutex - serviceStop chan (struct{}) -} - -var tbfConfigs tbf - -// initiateTBFReloader periodically update the TBF configuration from database -var initiateTBFReloader = func(c cache.Cache, expiryTime int) { - glog.Info("TBF Reloader start") - ticker := time.NewTicker(time.Duration(expiryTime) * time.Second) - - for { - updateTBFConfigMapsFromCache() - select { - case <-tbfConfigs.serviceStop: - return - case t := <-ticker.C: - glog.Infof("TBF Reloader loads cache @%v", t) - } - } -} - -// Init function initializes parameters of the tbfConfigs -// It starts the TBF reloader service in background -func Init(defaultExpiry int, cache cache.Cache) { - - tbfConfigs.cache = cache - tbfConfigs.pubProfileTraffic = make(map[int]map[int]int) - tbfConfigs.serviceStop = make(chan struct{}) - tbfConfigs.RWMutex = &sync.RWMutex{} - - go initiateTBFReloader(cache, defaultExpiry) - glog.Info("Initialized TBF cache reloaders to update publishers TBF configurations") -} - -// StopTBFReloaderService sends signal to stop the reloader service -func StopTBFReloaderService() { - tbfConfigs.serviceStop <- struct{}{} -} - -// limitTBFTrafficValues validates the traffic values from the given map of pub-prof-traffic -// to ensure they are constrained between 0 and 100 (inclusive). -// If a value is below 0 or above 100, it is set to 0. The original map is modified in place. -func limitTBFTrafficValues(pubProfTraffic map[int]map[int]int) { - for _, profTraffic := range pubProfTraffic { - for profID, traffic := range profTraffic { - if traffic < 0 || traffic > 100 { - profTraffic[profID] = 0 - } - } - } -} - -// updateTBFConfigMapsFromCache loads the TBF traffic data from cache/database and updates the configuration map. -// If execution of db-query-fails then this function will not update the old config-values. -// This function is safe for concurrent access. -func updateTBFConfigMapsFromCache() error { - - pubProfileTrafficRate, err := tbfConfigs.cache.GetTBFTrafficForPublishers() - if err != nil { - return err - } - limitTBFTrafficValues(pubProfileTrafficRate) - - tbfConfigs.Lock() - tbfConfigs.pubProfileTraffic = pubProfileTrafficRate - tbfConfigs.Unlock() - - return nil -} - -// IsEnabledTBFFeature returns false if TBF feature is disabled for pub-profile combination -// It makes use of predictTBFValue function to predict whether the request is eligible -// to track beacon first before adm based on the provided traffic percentage. -// This function is safe for concurrent access. -func IsEnabledTBFFeature(pubid int, profid int) bool { - - var trafficRate int - var present bool - - tbfConfigs.RLock() - if tbfConfigs.pubProfileTraffic != nil { - trafficRate, present = tbfConfigs.pubProfileTraffic[pubid][profid] - } - tbfConfigs.RUnlock() - - if !present { - return false - } - - return predictTBFValue(trafficRate) -} - -// predictTBFValue predicts whether a request is eligible for TBF feature -// based on the provided trafficRate value. -func predictTBFValue(trafficRate int) bool { - return rand.Intn(100) < trafficRate -} - -// SetAndResetTBFConfig is exposed for test cases -func SetAndResetTBFConfig(mockDb cache.Cache, pubProfileTraffic map[int]map[int]int) func() { - tbfConfigs.RWMutex = &sync.RWMutex{} - tbfConfigs.cache = mockDb - tbfConfigs.pubProfileTraffic = pubProfileTraffic - return func() { - tbfConfigs.cache = nil - tbfConfigs.pubProfileTraffic = make(map[int]map[int]int) - } -} - -// ResetTBFReloader is exposed for test cases -func ResetTBFReloader() { - initiateTBFReloader = func(c cache.Cache, expiryTime int) {} -} diff --git a/modules/pubmatic/openwrap/tbf/tbf_test.go b/modules/pubmatic/openwrap/tbf/tbf_test.go deleted file mode 100644 index dbbfe1938b2..00000000000 --- a/modules/pubmatic/openwrap/tbf/tbf_test.go +++ /dev/null @@ -1,232 +0,0 @@ -package tbf - -import ( - "fmt" - "testing" - "time" - - "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache" - mock_cache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache/mock" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" -) - -func TestInitAndReloader(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - mockCache := mock_cache.NewMockCache(ctrl) - defer SetAndResetTBFConfig(mockCache, nil)() - - type args struct { - defaultExpiry int - cache cache.Cache - } - - tests := []struct { - name string - args args - runBefore func() - }{ - { - name: "test_cache_call_through_init", - args: args{ - defaultExpiry: 1, - cache: mockCache, - }, - runBefore: func() { - mockCache.EXPECT().GetTBFTrafficForPublishers().Return(map[int]map[int]int{}, nil).AnyTimes() - }, - }, - } - for _, tt := range tests { - tt.runBefore() - Init(tt.args.defaultExpiry, tt.args.cache) - time.Sleep(2 * time.Second) - StopTBFReloaderService() - time.Sleep(250 * time.Millisecond) - } -} - -func TestPredictTBFValue(t *testing.T) { - type args struct { - percentage int - } - tests := []struct { - name string - args args - want bool - }{ - { - name: "100_pct_traffic", - args: args{ - percentage: 100, - }, - want: true, - }, - { - name: "0_pct_traffic", - args: args{ - percentage: 0, - }, - want: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := predictTBFValue(tt.args.percentage) - assert.Equal(t, tt.want, got, tt.name) - }) - } -} - -func TestIsEnabledTBFFeature(t *testing.T) { - - type args struct { - pubidstr int - profid int - pubProfTraffic map[int]map[int]int - } - tests := []struct { - name string - args args - want bool - }{ - { - name: "nil_map", - args: args{ - pubidstr: 5890, - profid: 1234, - pubProfTraffic: nil, - }, - want: false, - }, - { - name: "pub_prof_absent_in_map", - args: args{ - pubidstr: 5890, - profid: 1234, - pubProfTraffic: make(map[int]map[int]int), - }, - want: false, - }, - { - name: "pub_prof_present_in_map", - args: args{ - pubidstr: 5890, - profid: 1234, - pubProfTraffic: map[int]map[int]int{ - 5890: {1234: 100}, - }, - }, - want: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - SetAndResetTBFConfig(nil, tt.args.pubProfTraffic) - got := IsEnabledTBFFeature(tt.args.pubidstr, tt.args.profid) - assert.Equal(t, tt.want, got, tt.name) - }) - } -} - -func TestUpdateTBFConfigMapsFromCache(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - mockCache := mock_cache.NewMockCache(ctrl) - - defer SetAndResetTBFConfig(mockCache, map[int]map[int]int{})() - type want struct { - err error - pubProfileTraffic map[int]map[int]int - } - - tests := []struct { - name string - setup func() - want want - }{ - { - name: "cache_returns_error", - setup: func() { - mockCache.EXPECT().GetTBFTrafficForPublishers().Return(nil, fmt.Errorf("error")) - }, - want: want{ - pubProfileTraffic: map[int]map[int]int{}, - err: fmt.Errorf("error"), - }, - }, - { - name: "cache_returns_success", - setup: func() { - mockCache.EXPECT().GetTBFTrafficForPublishers().Return(map[int]map[int]int{5890: {1234: 100}}, nil) - }, - want: want{ - pubProfileTraffic: map[int]map[int]int{5890: {1234: 100}}, - err: nil, - }, - }, - { - name: "limit_traffic_values", - setup: func() { - mockCache.EXPECT().GetTBFTrafficForPublishers().Return(map[int]map[int]int{5890: {1234: 200}, 5891: {222: -5}}, nil) - }, - want: want{ - pubProfileTraffic: map[int]map[int]int{5890: {1234: 0}, 5891: {222: 0}}, - err: nil, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.setup() - err := updateTBFConfigMapsFromCache() - assert.Equal(t, tt.want.err, err, tt.name) - assert.Equal(t, tt.want.pubProfileTraffic, tbfConfigs.pubProfileTraffic, tt.name) - }) - } -} - -func TestLimitTBFTrafficValues(t *testing.T) { - - tests := []struct { - name string - inputMap map[int]map[int]int - outputMap map[int]map[int]int - }{ - { - name: "nil_map", - inputMap: nil, - outputMap: nil, - }, - { - name: "nil_prof_traffic_map", - inputMap: map[int]map[int]int{ - 1: nil, - }, - outputMap: map[int]map[int]int{ - 1: nil, - }, - }, - { - name: "negative_and_higher_than_100_values", - inputMap: map[int]map[int]int{ - 5890: {123: -100}, - 5891: {123: 50}, - 5892: {123: 200}, - }, - outputMap: map[int]map[int]int{ - 5890: {123: 0}, - 5891: {123: 50}, - 5892: {123: 0}, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - limitTBFTrafficValues(tt.inputMap) - assert.Equal(t, tt.outputMap, tt.inputMap, tt.name) - }) - } -} diff --git a/modules/pubmatic/openwrap/tracker/banner.go b/modules/pubmatic/openwrap/tracker/banner.go index 90691a084da..f3abe36faec 100644 --- a/modules/pubmatic/openwrap/tracker/banner.go +++ b/modules/pubmatic/openwrap/tracker/banner.go @@ -6,7 +6,6 @@ import ( "github.com/prebid/openrtb/v19/openrtb2" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models/adunitconfig" - "github.com/prebid/prebid-server/modules/pubmatic/openwrap/tbf" "github.com/prebid/prebid-server/openrtb_ext" ) @@ -52,7 +51,7 @@ func trackerWithOM(tracker models.OWTracker, platform, bidderCode string) bool { // given pub-prof combination then injects the tracker before adm // else injects the tracker after adm. func applyTBFFeature(rctx models.RequestCtx, bid openrtb2.Bid, tracker string) string { - if tbf.IsEnabledTBFFeature(rctx.PubID, rctx.ProfileID) { + if rctx.IsTBFFeatureEnabled { return tracker + bid.AdM } return bid.AdM + tracker diff --git a/modules/pubmatic/openwrap/tracker/banner_test.go b/modules/pubmatic/openwrap/tracker/banner_test.go index 1ee8e8659f2..c5eb36b3fcd 100644 --- a/modules/pubmatic/openwrap/tracker/banner_test.go +++ b/modules/pubmatic/openwrap/tracker/banner_test.go @@ -4,17 +4,12 @@ import ( "testing" "github.com/prebid/openrtb/v19/openrtb2" - mock_cache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache/mock" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models/adunitconfig" - "github.com/prebid/prebid-server/modules/pubmatic/openwrap/tbf" "github.com/stretchr/testify/assert" ) func Test_injectBannerTracker(t *testing.T) { - tbf.SetAndResetTBFConfig(&mock_cache.MockCache{}, map[int]map[int]int{ - 5890: {1234: 100}, - }) type args struct { rctx models.RequestCtx tracker models.OWTracker @@ -81,8 +76,9 @@ func Test_injectBannerTracker(t *testing.T) { name: "tbf_feature_enabled", args: args{ rctx: models.RequestCtx{ - PubID: 5890, - ProfileID: 1234, + PubID: 5890, + ProfileID: 1234, + IsTBFFeatureEnabled: true, }, tracker: models.OWTracker{ TrackerURL: `Tracking URL`, @@ -169,10 +165,6 @@ func Test_trackerWithOM(t *testing.T) { } func Test_applyTBFFeature(t *testing.T) { - tbf.SetAndResetTBFConfig(&mock_cache.MockCache{}, map[int]map[int]int{ - 5890: {1234: 100}, - }) - type args struct { rctx models.RequestCtx bid openrtb2.Bid @@ -187,8 +179,9 @@ func Test_applyTBFFeature(t *testing.T) { name: "tbf_feature_disabled", args: args{ rctx: models.RequestCtx{ - PubID: 5890, - ProfileID: 100, + PubID: 5890, + ProfileID: 100, + IsTBFFeatureEnabled: false, }, bid: openrtb2.Bid{ AdM: "bid_AdM", @@ -201,8 +194,9 @@ func Test_applyTBFFeature(t *testing.T) { name: "tbf_feature_enabled", args: args{ rctx: models.RequestCtx{ - PubID: 5890, - ProfileID: 1234, + PubID: 5890, + ProfileID: 1234, + IsTBFFeatureEnabled: true, }, bid: openrtb2.Bid{ AdM: "bid_AdM", @@ -211,20 +205,6 @@ func Test_applyTBFFeature(t *testing.T) { }, want: "tracker_urlbid_AdM", }, - { - name: "invalid_pubid", - args: args{ - rctx: models.RequestCtx{ - PubID: -1, - ProfileID: 1234, - }, - bid: openrtb2.Bid{ - AdM: "bid_AdM", - }, - tracker: "tracker_url", - }, - want: "bid_AdMtracker_url", - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/modules/pubmatic/openwrap/tracker/inject_test.go b/modules/pubmatic/openwrap/tracker/inject_test.go index d1af134739d..6a19e9b27d2 100644 --- a/modules/pubmatic/openwrap/tracker/inject_test.go +++ b/modules/pubmatic/openwrap/tracker/inject_test.go @@ -7,21 +7,16 @@ import ( "github.com/golang/mock/gomock" "github.com/magiconair/properties/assert" "github.com/prebid/openrtb/v19/openrtb2" - mock_cache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache/mock" mock_metrics "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics/mock" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models/adunitconfig" - "github.com/prebid/prebid-server/modules/pubmatic/openwrap/tbf" ) func TestInjectTrackers(t *testing.T) { ctrl := gomock.NewController(t) mockEngine := mock_metrics.NewMockMetricsEngine(ctrl) - mockCache := mock_cache.NewMockCache(ctrl) defer ctrl.Finish() - tbf.SetAndResetTBFConfig(mockCache, map[int]map[int]int{ - 5890: {1234: 100}, - }) + models.TrackerCallWrapOMActive = `` type args struct { From c0423b846fe8c28c7216224b39fce9f3dfb6ac23 Mon Sep 17 00:00:00 2001 From: pm-priyanka-bagade <156899734+pm-priyanka-bagade@users.noreply.github.com> Date: Mon, 8 Apr 2024 15:36:45 +0530 Subject: [PATCH 2/5] UOE-10137: Fetch platform type from wrapper profile table (#727) --- .../openwrap/database/mysql/partner_config.go | 15 +- .../database/mysql/partner_config_test.go | 190 +++++++++++++----- modules/pubmatic/openwrap/models/constants.go | 1 + 3 files changed, 149 insertions(+), 57 deletions(-) diff --git a/modules/pubmatic/openwrap/database/mysql/partner_config.go b/modules/pubmatic/openwrap/database/mysql/partner_config.go index 8a423f0a407..3f978cfad7c 100644 --- a/modules/pubmatic/openwrap/database/mysql/partner_config.go +++ b/modules/pubmatic/openwrap/database/mysql/partner_config.go @@ -14,7 +14,7 @@ import ( // return the list of active server side header bidding partners // with their configurations at publisher-profile-version level func (db *mySqlDB) GetActivePartnerConfigurations(pubID, profileID int, displayVersion int) (map[int]map[string]string, error) { - versionID, displayVersionID, err := db.getVersionID(profileID, displayVersion, pubID) + versionID, displayVersionID, platform, err := db.getVersionID(profileID, displayVersion, pubID) if err != nil { return nil, err } @@ -22,6 +22,10 @@ func (db *mySqlDB) GetActivePartnerConfigurations(pubID, profileID int, displayV partnerConfigMap, err := db.getActivePartnerConfigurations(versionID) if err == nil && partnerConfigMap[-1] != nil { partnerConfigMap[-1][models.DisplayVersionID] = strconv.Itoa(displayVersionID) + // check for SDK new UI + if platform != "" { + partnerConfigMap[-1][models.PLATFORM_KEY] = platform + } } return partnerConfigMap, err } @@ -76,7 +80,7 @@ func (db *mySqlDB) getActivePartnerConfigurations(versionID int) (map[int]map[st return partnerConfigMap, nil } -func (db *mySqlDB) getVersionID(profileID, displayVersion, pubID int) (int, int, error) { +func (db *mySqlDB) getVersionID(profileID, displayVersion, pubID int) (int, int, string, error) { var row *sql.Row if displayVersion == 0 { row = db.conn.QueryRow(db.cfg.Queries.LiveVersionInnerQuery, profileID, pubID) @@ -84,10 +88,11 @@ func (db *mySqlDB) getVersionID(profileID, displayVersion, pubID int) (int, int, row = db.conn.QueryRow(db.cfg.Queries.DisplayVersionInnerQuery, profileID, displayVersion, pubID) } + var platform sql.NullString var versionID, displayVersionIDFromDB int - err := row.Scan(&versionID, &displayVersionIDFromDB) + err := row.Scan(&versionID, &displayVersionIDFromDB, &platform) if err != nil { - return versionID, displayVersionIDFromDB, err + return versionID, displayVersionIDFromDB, platform.String, err } - return versionID, displayVersionIDFromDB, nil + return versionID, displayVersionIDFromDB, platform.String, nil } diff --git a/modules/pubmatic/openwrap/database/mysql/partner_config_test.go b/modules/pubmatic/openwrap/database/mysql/partner_config_test.go index ea9f5e57159..6647c9e384b 100644 --- a/modules/pubmatic/openwrap/database/mysql/partner_config_test.go +++ b/modules/pubmatic/openwrap/database/mysql/partner_config_test.go @@ -7,6 +7,7 @@ import ( "github.com/DATA-DOG/go-sqlmock" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/config" + "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" "github.com/stretchr/testify/assert" ) @@ -32,7 +33,7 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE", + LiveVersionInnerQuery: models.TestQuery, }, }, }, @@ -50,8 +51,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("25_1", "9") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("25_1", "9", models.PLATFORM_DISPLAY) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) return db }, @@ -61,7 +62,7 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE", + LiveVersionInnerQuery: models.TestQuery, }, }, }, @@ -79,8 +80,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_DISPLAY) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) return db }, @@ -90,8 +91,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE", - GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", + LiveVersionInnerQuery: models.TestQuery, + GetParterConfig: models.TestQuery, }, MaxDbContextTimeout: 1000, }, @@ -131,8 +132,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_DISPLAY) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) rowsPartnerConfig := sqlmock.NewRows([]string{"partnerId", "prebidPartnerName", "bidderCode", "isAlias", "entityTypeID", "testConfig", "vendorId", "keyName", "value"}). AddRow("-1", "ALL", "ALL", 0, -1, 0, -1, "platform", "display"). @@ -140,7 +141,7 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "kgp", "_AU_@_W_x_H_"). AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "timeout", "200"). AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "serverSideEnabled", "1") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rowsPartnerConfig) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rowsPartnerConfig) return db }, }, @@ -149,8 +150,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - DisplayVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+)", - GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", + DisplayVersionInnerQuery: models.TestQuery, + GetParterConfig: models.TestQuery, }, MaxDbContextTimeout: 1000, }, @@ -190,8 +191,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+)")).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_DISPLAY) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion) rowsPartnerConfig := sqlmock.NewRows([]string{"partnerId", "prebidPartnerName", "bidderCode", "isAlias", "entityTypeID", "testConfig", "vendorId", "keyName", "value"}). AddRow("-1", "ALL", "ALL", 0, -1, 0, -1, "platform", "display"). @@ -199,7 +200,7 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "kgp", "_AU_@_W_x_H_"). AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "timeout", "200"). AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "serverSideEnabled", "1") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rowsPartnerConfig) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rowsPartnerConfig) return db }, }, @@ -208,8 +209,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - DisplayVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+)", - GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", + DisplayVersionInnerQuery: models.TestQuery, + GetParterConfig: models.TestQuery, }, MaxDbContextTimeout: 1000, }, @@ -257,8 +258,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+)")).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_DISPLAY) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion) rowsPartnerConfig := sqlmock.NewRows([]string{"partnerId", "prebidPartnerName", "bidderCode", "isAlias", "entityTypeID", "testConfig", "vendorId", "keyName", "value"}). AddRow("-1", "ALL", "ALL", 0, -1, 0, -1, "platform", "display"). @@ -279,12 +280,12 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { conn: tt.setup(), cfg: tt.fields.cfg, } - got, err := db.GetActivePartnerConfigurations(tt.args.pubID, tt.args.profileID, tt.args.displayVersion) + gotPartnerConfigMap, err := db.GetActivePartnerConfigurations(tt.args.pubID, tt.args.profileID, tt.args.displayVersion) if (err != nil) != tt.wantErr { t.Errorf("mySqlDB.GetActivePartnerConfigurations() error = %v, wantErr %v", err, tt.wantErr) return } - assert.Equal(t, tt.want, got) + assert.Equal(t, tt.want, gotPartnerConfigMap) }) } } @@ -321,7 +322,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", + GetParterConfig: models.TestQuery, }, MaxDbContextTimeout: 1000, }, @@ -338,7 +339,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { } rows := sqlmock.NewRows([]string{"partnerId", "prebidPartnerName", "bidderCode", "isAlias", "entityTypeID", "testConfig", "vendorId", "keyName", "value"}). AddRow("11_11", "openx", "openx", 0, -1, 0, -1, "k1", "v1") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows) return db }, }, @@ -347,7 +348,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", + GetParterConfig: models.TestQuery, }, MaxDbContextTimeout: 1000, }, @@ -384,7 +385,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { AddRow(101, "openx", "openx", 0, -1, 0, 152, "k1", "v1"). AddRow(101, "openx", "openx", 0, -1, 0, 152, "k2", "v2"). AddRow(102, "pubmatic", "pubmatic", 0, -1, 0, 76, "k1", "v2") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows) return db }, }, @@ -393,7 +394,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", + GetParterConfig: models.TestQuery, }, MaxDbContextTimeout: 1000, }, @@ -436,7 +437,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { AddRow(101, "FirstPartnerName", "FirstBidder", 0, 3, 0, 152, "rev_share", "10"). AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k1", "v1"). AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k2", "v2") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows) return db }, }, @@ -445,7 +446,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", + GetParterConfig: models.TestQuery, }, MaxDbContextTimeout: 1000, }, @@ -491,7 +492,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { AddRow(101, "FirstPartnerName", "FirstBidder", 0, 3, 0, 76, "rev_share", "10"). AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k1", "v1"). AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k2", "v2") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows) return db }, }, @@ -500,7 +501,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", + GetParterConfig: models.TestQuery, }, MaxDbContextTimeout: 1000, }, @@ -544,7 +545,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { AddRow(101, "FirstPartnerName", "FirstBidder", 0, 3, 0, 76, "rev_share", "10"). AddRow(102, "SecondPartnerName", "SecondBidder", 1, -1, 0, 100, "k1", "v1"). AddRow(102, "SecondPartnerName", "SecondBidder", 1, -1, 0, 100, "k2", "v2") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows) return db }, }, @@ -553,7 +554,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", + GetParterConfig: models.TestQuery, }, MaxDbContextTimeout: 1000, }, @@ -597,7 +598,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { AddRow(101, "FirstPartnerName", "FirstBidder", 0, 3, 0, 76, "rev_share", "10"). AddRow(102, "-", "-", 0, -1, 0, 100, "k1", "v1"). AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k2", "v2") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows) return db }, }, @@ -608,12 +609,12 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { conn: tt.setup(), cfg: tt.fields.cfg, } - got, err := db.getActivePartnerConfigurations(tt.args.versionID) + gotPartnerConfigMap, err := db.getActivePartnerConfigurations(tt.args.versionID) if (err != nil) != tt.wantErr { t.Errorf("mySqlDB.getActivePartnerConfigurations() error = %v, wantErr %v", err, tt.wantErr) return } - assert.Equal(t, tt.want, got) + assert.Equal(t, tt.want, gotPartnerConfigMap) }) } } @@ -633,6 +634,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) { args args expectedVersionID int expectedDisplayVersionIDFromDB int + expectedPlatform string wantErr bool setup func() *sql.DB }{ @@ -641,7 +643,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE", + LiveVersionInnerQuery: models.TestQuery, }, }, }, @@ -652,6 +654,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) { }, expectedVersionID: 0, expectedDisplayVersionIDFromDB: 0, + expectedPlatform: "", wantErr: true, setup: func() *sql.DB { db, mock, err := sqlmock.New() @@ -659,8 +662,8 @@ func Test_mySqlDB_getVersionID(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("25_1", "9") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("25_1", "9", models.PLATFORM_APP) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) return db }, @@ -670,7 +673,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE", + LiveVersionInnerQuery: models.TestQuery, }, }, }, @@ -682,6 +685,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) { expectedVersionID: 251, expectedDisplayVersionIDFromDB: 9, + expectedPlatform: "in-app", wantErr: false, setup: func() *sql.DB { db, mock, err := sqlmock.New() @@ -689,8 +693,8 @@ func Test_mySqlDB_getVersionID(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_APP) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) return db }, @@ -700,7 +704,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - DisplayVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+)", + DisplayVersionInnerQuery: models.TestQuery, }, }, }, @@ -712,6 +716,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) { expectedVersionID: 251, expectedDisplayVersionIDFromDB: 9, + expectedPlatform: "in-app", wantErr: false, setup: func() *sql.DB { db, mock, err := sqlmock.New() @@ -719,12 +724,96 @@ func Test_mySqlDB_getVersionID(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+)")).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_APP) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion) return db }, }, + { + name: "Platform is null", + fields: fields{ + cfg: config.Database{ + Queries: config.Queries{ + DisplayVersionInnerQuery: models.TestQuery, + }, + }, + }, + args: args{ + profileID: 19109, + displayVersion: 2, + pubID: 5890, + }, + expectedVersionID: 123, + expectedDisplayVersionIDFromDB: 12, + expectedPlatform: "", + wantErr: false, + setup: func() *sql.DB { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("123", "12", nil) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 2, 5890).WillReturnRows(rowsWrapperVersion) + return db + }, + }, + { + name: "Platform is empty string", + fields: fields{ + cfg: config.Database{ + Queries: config.Queries{ + LiveVersionInnerQuery: models.TestQuery, + }, + }, + }, + args: args{ + profileID: 19109, + displayVersion: 0, + pubID: 5890, + }, + expectedVersionID: 251, + expectedDisplayVersionIDFromDB: 9, + expectedPlatform: "", + wantErr: false, + setup: func() *sql.DB { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", "") + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) + return db + }, + }, + { + name: "Platform is not null", + fields: fields{ + cfg: config.Database{ + Queries: config.Queries{ + LiveVersionInnerQuery: models.TestQuery, + }, + }, + }, + args: args{ + profileID: 19109, + displayVersion: 0, + pubID: 5890, + }, + expectedVersionID: 251, + expectedDisplayVersionIDFromDB: 9, + expectedPlatform: "in-app", + wantErr: false, + setup: func() *sql.DB { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_APP) + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) + return db + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -732,17 +821,14 @@ func Test_mySqlDB_getVersionID(t *testing.T) { conn: tt.setup(), cfg: tt.fields.cfg, } - got, got1, err := db.getVersionID(tt.args.profileID, tt.args.displayVersion, tt.args.pubID) + gotVersionID, gotDisplayVersionID, gotPlatform, err := db.getVersionID(tt.args.profileID, tt.args.displayVersion, tt.args.pubID) if (err != nil) != tt.wantErr { t.Errorf("mySqlDB.getVersionID() error = %v, wantErr %v", err, tt.wantErr) return } - if got != tt.expectedVersionID { - t.Errorf("mySqlDB.getVersionID() got = %v, want %v", got, tt.expectedVersionID) - } - if got1 != tt.expectedDisplayVersionIDFromDB { - t.Errorf("mySqlDB.getVersionID() got1 = %v, want %v", got1, tt.expectedDisplayVersionIDFromDB) - } + assert.Equal(t, tt.expectedVersionID, gotVersionID) + assert.Equal(t, tt.expectedDisplayVersionIDFromDB, gotDisplayVersionID) + assert.Equal(t, tt.expectedPlatform, gotPlatform) }) } } diff --git a/modules/pubmatic/openwrap/models/constants.go b/modules/pubmatic/openwrap/models/constants.go index fcadcbf8d6e..26609822d75 100755 --- a/modules/pubmatic/openwrap/models/constants.go +++ b/modules/pubmatic/openwrap/models/constants.go @@ -468,6 +468,7 @@ const ( //DisplayVersionInnerQuery = "DisplayVersionInnerQuery" //LiveVersionInnerQuery = "LiveVersionInnerQuery" //PMSlotToMappings = "GetPMSlotToMappings" + TestQuery = "TestQuery" ) // constants for owlogger Integration Type From 0988a948473fb4cb4ad593f54a2861f00d981d01 Mon Sep 17 00:00:00 2001 From: pm-priyanka-bagade <156899734+pm-priyanka-bagade@users.noreply.github.com> Date: Mon, 8 Apr 2024 18:07:40 +0530 Subject: [PATCH 3/5] UOE-10137: fix UT related to (#746) (#747) --- .../pubmatic/openwrap/database/mysql/partner_config_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/pubmatic/openwrap/database/mysql/partner_config_test.go b/modules/pubmatic/openwrap/database/mysql/partner_config_test.go index 6647c9e384b..e201bfda03d 100644 --- a/modules/pubmatic/openwrap/database/mysql/partner_config_test.go +++ b/modules/pubmatic/openwrap/database/mysql/partner_config_test.go @@ -267,9 +267,9 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "kgp", "_AU_@_W_x_H_"). AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "timeout", "200"). AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "serverSideEnabled", "1"). - AddRow("234", "vastbidder", "test-vastbidder", 0, 3, 0, 546, "vendorId", "999"). - AddRow("234", "vastbidder", "test-vastbidder", 0, 3, 0, 546, "serverSideEnabled", "1") - mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rowsPartnerConfig) + AddRow("234", "vastbidder", "test-vastbidder", 0, 3, 0, -1, "serverSideEnabled", "1"). + AddRow("234", "vastbidder", "test-vastbidder", 0, 3, 0, -1, "vendorId", "546") + mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rowsPartnerConfig) return db }, }, From 767d0cbc76b21ecab44b31f92b383b8aab1cf24c Mon Sep 17 00:00:00 2001 From: pm-priyanka-bagade <156899734+pm-priyanka-bagade@users.noreply.github.com> Date: Thu, 11 Apr 2024 11:42:17 +0530 Subject: [PATCH 4/5] Revert "UOE-10137: Fetch platform type from wrapper profile table (#727)" (#749) * Revert "UOE-10137: fix UT related to (#746) (#747)" This reverts commit 0988a948473fb4cb4ad593f54a2861f00d981d01. * Revert "UOE-10137: Fetch platform type from wrapper profile table (#727)" This reverts commit c0423b846fe8c28c7216224b39fce9f3dfb6ac23. --- .../openwrap/database/mysql/partner_config.go | 15 +- .../database/mysql/partner_config_test.go | 196 +++++------------- modules/pubmatic/openwrap/models/constants.go | 1 - 3 files changed, 60 insertions(+), 152 deletions(-) diff --git a/modules/pubmatic/openwrap/database/mysql/partner_config.go b/modules/pubmatic/openwrap/database/mysql/partner_config.go index 3f978cfad7c..8a423f0a407 100644 --- a/modules/pubmatic/openwrap/database/mysql/partner_config.go +++ b/modules/pubmatic/openwrap/database/mysql/partner_config.go @@ -14,7 +14,7 @@ import ( // return the list of active server side header bidding partners // with their configurations at publisher-profile-version level func (db *mySqlDB) GetActivePartnerConfigurations(pubID, profileID int, displayVersion int) (map[int]map[string]string, error) { - versionID, displayVersionID, platform, err := db.getVersionID(profileID, displayVersion, pubID) + versionID, displayVersionID, err := db.getVersionID(profileID, displayVersion, pubID) if err != nil { return nil, err } @@ -22,10 +22,6 @@ func (db *mySqlDB) GetActivePartnerConfigurations(pubID, profileID int, displayV partnerConfigMap, err := db.getActivePartnerConfigurations(versionID) if err == nil && partnerConfigMap[-1] != nil { partnerConfigMap[-1][models.DisplayVersionID] = strconv.Itoa(displayVersionID) - // check for SDK new UI - if platform != "" { - partnerConfigMap[-1][models.PLATFORM_KEY] = platform - } } return partnerConfigMap, err } @@ -80,7 +76,7 @@ func (db *mySqlDB) getActivePartnerConfigurations(versionID int) (map[int]map[st return partnerConfigMap, nil } -func (db *mySqlDB) getVersionID(profileID, displayVersion, pubID int) (int, int, string, error) { +func (db *mySqlDB) getVersionID(profileID, displayVersion, pubID int) (int, int, error) { var row *sql.Row if displayVersion == 0 { row = db.conn.QueryRow(db.cfg.Queries.LiveVersionInnerQuery, profileID, pubID) @@ -88,11 +84,10 @@ func (db *mySqlDB) getVersionID(profileID, displayVersion, pubID int) (int, int, row = db.conn.QueryRow(db.cfg.Queries.DisplayVersionInnerQuery, profileID, displayVersion, pubID) } - var platform sql.NullString var versionID, displayVersionIDFromDB int - err := row.Scan(&versionID, &displayVersionIDFromDB, &platform) + err := row.Scan(&versionID, &displayVersionIDFromDB) if err != nil { - return versionID, displayVersionIDFromDB, platform.String, err + return versionID, displayVersionIDFromDB, err } - return versionID, displayVersionIDFromDB, platform.String, nil + return versionID, displayVersionIDFromDB, nil } diff --git a/modules/pubmatic/openwrap/database/mysql/partner_config_test.go b/modules/pubmatic/openwrap/database/mysql/partner_config_test.go index e201bfda03d..ea9f5e57159 100644 --- a/modules/pubmatic/openwrap/database/mysql/partner_config_test.go +++ b/modules/pubmatic/openwrap/database/mysql/partner_config_test.go @@ -7,7 +7,6 @@ import ( "github.com/DATA-DOG/go-sqlmock" "github.com/prebid/prebid-server/modules/pubmatic/openwrap/config" - "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models" "github.com/stretchr/testify/assert" ) @@ -33,7 +32,7 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - LiveVersionInnerQuery: models.TestQuery, + LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE", }, }, }, @@ -51,8 +50,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("25_1", "9", models.PLATFORM_DISPLAY) - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("25_1", "9") + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) return db }, @@ -62,7 +61,7 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - LiveVersionInnerQuery: models.TestQuery, + LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE", }, }, }, @@ -80,8 +79,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_DISPLAY) - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9") + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) return db }, @@ -91,8 +90,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - LiveVersionInnerQuery: models.TestQuery, - GetParterConfig: models.TestQuery, + LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE", + GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", }, MaxDbContextTimeout: 1000, }, @@ -132,8 +131,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_DISPLAY) - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9") + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) rowsPartnerConfig := sqlmock.NewRows([]string{"partnerId", "prebidPartnerName", "bidderCode", "isAlias", "entityTypeID", "testConfig", "vendorId", "keyName", "value"}). AddRow("-1", "ALL", "ALL", 0, -1, 0, -1, "platform", "display"). @@ -141,7 +140,7 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "kgp", "_AU_@_W_x_H_"). AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "timeout", "200"). AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "serverSideEnabled", "1") - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rowsPartnerConfig) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rowsPartnerConfig) return db }, }, @@ -150,8 +149,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - DisplayVersionInnerQuery: models.TestQuery, - GetParterConfig: models.TestQuery, + DisplayVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+)", + GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", }, MaxDbContextTimeout: 1000, }, @@ -191,8 +190,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_DISPLAY) - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9") + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+)")).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion) rowsPartnerConfig := sqlmock.NewRows([]string{"partnerId", "prebidPartnerName", "bidderCode", "isAlias", "entityTypeID", "testConfig", "vendorId", "keyName", "value"}). AddRow("-1", "ALL", "ALL", 0, -1, 0, -1, "platform", "display"). @@ -200,7 +199,7 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "kgp", "_AU_@_W_x_H_"). AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "timeout", "200"). AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "serverSideEnabled", "1") - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rowsPartnerConfig) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rowsPartnerConfig) return db }, }, @@ -209,8 +208,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - DisplayVersionInnerQuery: models.TestQuery, - GetParterConfig: models.TestQuery, + DisplayVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+)", + GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", }, MaxDbContextTimeout: 1000, }, @@ -258,8 +257,8 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_DISPLAY) - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9") + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+)")).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion) rowsPartnerConfig := sqlmock.NewRows([]string{"partnerId", "prebidPartnerName", "bidderCode", "isAlias", "entityTypeID", "testConfig", "vendorId", "keyName", "value"}). AddRow("-1", "ALL", "ALL", 0, -1, 0, -1, "platform", "display"). @@ -267,9 +266,9 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "kgp", "_AU_@_W_x_H_"). AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "timeout", "200"). AddRow("101", "pubmatic", "pubmatic", 0, 3, 0, 76, "serverSideEnabled", "1"). - AddRow("234", "vastbidder", "test-vastbidder", 0, 3, 0, -1, "serverSideEnabled", "1"). - AddRow("234", "vastbidder", "test-vastbidder", 0, 3, 0, -1, "vendorId", "546") - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rowsPartnerConfig) + AddRow("234", "vastbidder", "test-vastbidder", 0, 3, 0, 546, "vendorId", "999"). + AddRow("234", "vastbidder", "test-vastbidder", 0, 3, 0, 546, "serverSideEnabled", "1") + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rowsPartnerConfig) return db }, }, @@ -280,12 +279,12 @@ func Test_mySqlDB_GetActivePartnerConfigurations(t *testing.T) { conn: tt.setup(), cfg: tt.fields.cfg, } - gotPartnerConfigMap, err := db.GetActivePartnerConfigurations(tt.args.pubID, tt.args.profileID, tt.args.displayVersion) + got, err := db.GetActivePartnerConfigurations(tt.args.pubID, tt.args.profileID, tt.args.displayVersion) if (err != nil) != tt.wantErr { t.Errorf("mySqlDB.GetActivePartnerConfigurations() error = %v, wantErr %v", err, tt.wantErr) return } - assert.Equal(t, tt.want, gotPartnerConfigMap) + assert.Equal(t, tt.want, got) }) } } @@ -322,7 +321,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - GetParterConfig: models.TestQuery, + GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", }, MaxDbContextTimeout: 1000, }, @@ -339,7 +338,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { } rows := sqlmock.NewRows([]string{"partnerId", "prebidPartnerName", "bidderCode", "isAlias", "entityTypeID", "testConfig", "vendorId", "keyName", "value"}). AddRow("11_11", "openx", "openx", 0, -1, 0, -1, "k1", "v1") - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows) return db }, }, @@ -348,7 +347,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - GetParterConfig: models.TestQuery, + GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", }, MaxDbContextTimeout: 1000, }, @@ -385,7 +384,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { AddRow(101, "openx", "openx", 0, -1, 0, 152, "k1", "v1"). AddRow(101, "openx", "openx", 0, -1, 0, 152, "k2", "v2"). AddRow(102, "pubmatic", "pubmatic", 0, -1, 0, 76, "k1", "v2") - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows) return db }, }, @@ -394,7 +393,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - GetParterConfig: models.TestQuery, + GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", }, MaxDbContextTimeout: 1000, }, @@ -437,7 +436,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { AddRow(101, "FirstPartnerName", "FirstBidder", 0, 3, 0, 152, "rev_share", "10"). AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k1", "v1"). AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k2", "v2") - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows) return db }, }, @@ -446,7 +445,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - GetParterConfig: models.TestQuery, + GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", }, MaxDbContextTimeout: 1000, }, @@ -492,7 +491,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { AddRow(101, "FirstPartnerName", "FirstBidder", 0, 3, 0, 76, "rev_share", "10"). AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k1", "v1"). AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k2", "v2") - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows) return db }, }, @@ -501,7 +500,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - GetParterConfig: models.TestQuery, + GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", }, MaxDbContextTimeout: 1000, }, @@ -545,7 +544,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { AddRow(101, "FirstPartnerName", "FirstBidder", 0, 3, 0, 76, "rev_share", "10"). AddRow(102, "SecondPartnerName", "SecondBidder", 1, -1, 0, 100, "k1", "v1"). AddRow(102, "SecondPartnerName", "SecondBidder", 1, -1, 0, 100, "k2", "v2") - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows) return db }, }, @@ -554,7 +553,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - GetParterConfig: models.TestQuery, + GetParterConfig: "^SELECT (.+) FROM wrapper_config_map (.+)", }, MaxDbContextTimeout: 1000, }, @@ -598,7 +597,7 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { AddRow(101, "FirstPartnerName", "FirstBidder", 0, 3, 0, 76, "rev_share", "10"). AddRow(102, "-", "-", 0, -1, 0, 100, "k1", "v1"). AddRow(102, "SecondPartnerName", "SecondBidder", 0, -1, 0, 100, "k2", "v2") - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WillReturnRows(rows) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_config_map (.+)")).WillReturnRows(rows) return db }, }, @@ -609,12 +608,12 @@ func Test_mySqlDB_getActivePartnerConfigurations(t *testing.T) { conn: tt.setup(), cfg: tt.fields.cfg, } - gotPartnerConfigMap, err := db.getActivePartnerConfigurations(tt.args.versionID) + got, err := db.getActivePartnerConfigurations(tt.args.versionID) if (err != nil) != tt.wantErr { t.Errorf("mySqlDB.getActivePartnerConfigurations() error = %v, wantErr %v", err, tt.wantErr) return } - assert.Equal(t, tt.want, gotPartnerConfigMap) + assert.Equal(t, tt.want, got) }) } } @@ -634,7 +633,6 @@ func Test_mySqlDB_getVersionID(t *testing.T) { args args expectedVersionID int expectedDisplayVersionIDFromDB int - expectedPlatform string wantErr bool setup func() *sql.DB }{ @@ -643,7 +641,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - LiveVersionInnerQuery: models.TestQuery, + LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE", }, }, }, @@ -654,7 +652,6 @@ func Test_mySqlDB_getVersionID(t *testing.T) { }, expectedVersionID: 0, expectedDisplayVersionIDFromDB: 0, - expectedPlatform: "", wantErr: true, setup: func() *sql.DB { db, mock, err := sqlmock.New() @@ -662,8 +659,8 @@ func Test_mySqlDB_getVersionID(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("25_1", "9", models.PLATFORM_APP) - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("25_1", "9") + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) return db }, @@ -673,7 +670,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - LiveVersionInnerQuery: models.TestQuery, + LiveVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+) LIVE", }, }, }, @@ -685,7 +682,6 @@ func Test_mySqlDB_getVersionID(t *testing.T) { expectedVersionID: 251, expectedDisplayVersionIDFromDB: 9, - expectedPlatform: "in-app", wantErr: false, setup: func() *sql.DB { db, mock, err := sqlmock.New() @@ -693,8 +689,8 @@ func Test_mySqlDB_getVersionID(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_APP) - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9") + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+) LIVE")).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) return db }, @@ -704,7 +700,7 @@ func Test_mySqlDB_getVersionID(t *testing.T) { fields: fields{ cfg: config.Database{ Queries: config.Queries{ - DisplayVersionInnerQuery: models.TestQuery, + DisplayVersionInnerQuery: "^SELECT (.+) FROM wrapper_version (.+)", }, }, }, @@ -716,7 +712,6 @@ func Test_mySqlDB_getVersionID(t *testing.T) { expectedVersionID: 251, expectedDisplayVersionIDFromDB: 9, - expectedPlatform: "in-app", wantErr: false, setup: func() *sql.DB { db, mock, err := sqlmock.New() @@ -724,96 +719,12 @@ func Test_mySqlDB_getVersionID(t *testing.T) { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } - rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_APP) - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion) + rowsWrapperVersion := sqlmock.NewRows([]string{"versionId", "displayVersionId"}).AddRow("251", "9") + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM wrapper_version (.+)")).WithArgs(19109, 3, 5890).WillReturnRows(rowsWrapperVersion) return db }, }, - { - name: "Platform is null", - fields: fields{ - cfg: config.Database{ - Queries: config.Queries{ - DisplayVersionInnerQuery: models.TestQuery, - }, - }, - }, - args: args{ - profileID: 19109, - displayVersion: 2, - pubID: 5890, - }, - expectedVersionID: 123, - expectedDisplayVersionIDFromDB: 12, - expectedPlatform: "", - wantErr: false, - setup: func() *sql.DB { - db, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("123", "12", nil) - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 2, 5890).WillReturnRows(rowsWrapperVersion) - return db - }, - }, - { - name: "Platform is empty string", - fields: fields{ - cfg: config.Database{ - Queries: config.Queries{ - LiveVersionInnerQuery: models.TestQuery, - }, - }, - }, - args: args{ - profileID: 19109, - displayVersion: 0, - pubID: 5890, - }, - expectedVersionID: 251, - expectedDisplayVersionIDFromDB: 9, - expectedPlatform: "", - wantErr: false, - setup: func() *sql.DB { - db, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", "") - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) - return db - }, - }, - { - name: "Platform is not null", - fields: fields{ - cfg: config.Database{ - Queries: config.Queries{ - LiveVersionInnerQuery: models.TestQuery, - }, - }, - }, - args: args{ - profileID: 19109, - displayVersion: 0, - pubID: 5890, - }, - expectedVersionID: 251, - expectedDisplayVersionIDFromDB: 9, - expectedPlatform: "in-app", - wantErr: false, - setup: func() *sql.DB { - db, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - rowsWrapperVersion := sqlmock.NewRows([]string{models.VersionID, models.DisplayVersionID, models.PLATFORM_KEY}).AddRow("251", "9", models.PLATFORM_APP) - mock.ExpectQuery(regexp.QuoteMeta(models.TestQuery)).WithArgs(19109, 5890).WillReturnRows(rowsWrapperVersion) - return db - }, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -821,14 +732,17 @@ func Test_mySqlDB_getVersionID(t *testing.T) { conn: tt.setup(), cfg: tt.fields.cfg, } - gotVersionID, gotDisplayVersionID, gotPlatform, err := db.getVersionID(tt.args.profileID, tt.args.displayVersion, tt.args.pubID) + got, got1, err := db.getVersionID(tt.args.profileID, tt.args.displayVersion, tt.args.pubID) if (err != nil) != tt.wantErr { t.Errorf("mySqlDB.getVersionID() error = %v, wantErr %v", err, tt.wantErr) return } - assert.Equal(t, tt.expectedVersionID, gotVersionID) - assert.Equal(t, tt.expectedDisplayVersionIDFromDB, gotDisplayVersionID) - assert.Equal(t, tt.expectedPlatform, gotPlatform) + if got != tt.expectedVersionID { + t.Errorf("mySqlDB.getVersionID() got = %v, want %v", got, tt.expectedVersionID) + } + if got1 != tt.expectedDisplayVersionIDFromDB { + t.Errorf("mySqlDB.getVersionID() got1 = %v, want %v", got1, tt.expectedDisplayVersionIDFromDB) + } }) } } diff --git a/modules/pubmatic/openwrap/models/constants.go b/modules/pubmatic/openwrap/models/constants.go index 26609822d75..fcadcbf8d6e 100755 --- a/modules/pubmatic/openwrap/models/constants.go +++ b/modules/pubmatic/openwrap/models/constants.go @@ -468,7 +468,6 @@ const ( //DisplayVersionInnerQuery = "DisplayVersionInnerQuery" //LiveVersionInnerQuery = "LiveVersionInnerQuery" //PMSlotToMappings = "GetPMSlotToMappings" - TestQuery = "TestQuery" ) // constants for owlogger Integration Type From 19134d55670cc3274972a3df3bfa9338f3b2d4ff Mon Sep 17 00:00:00 2001 From: pm-avinash-kapre <112699665+AvinashKapre@users.noreply.github.com> Date: Fri, 12 Apr 2024 10:20:56 +0530 Subject: [PATCH 5/5] UOE-10385: minor refactor for readability (#752) --- modules/pubmatic/openwrap/publisherfeature/ampmultiformat.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pubmatic/openwrap/publisherfeature/ampmultiformat.go b/modules/pubmatic/openwrap/publisherfeature/ampmultiformat.go index db26af75824..72d0a7af728 100644 --- a/modules/pubmatic/openwrap/publisherfeature/ampmultiformat.go +++ b/modules/pubmatic/openwrap/publisherfeature/ampmultiformat.go @@ -16,7 +16,7 @@ func (fe *feature) updateAmpMutiformatEnabledPublishers() { enabledPublishers := make(map[int]struct{}) for pubID, feature := range fe.publisherFeature { - if feature[models.FeatureAMPMultiFormat].Enabled == 1 { + if val, ok := feature[models.FeatureAMPMultiFormat]; ok && val.Enabled == 1 { enabledPublishers[pubID] = struct{}{} } }