Repository: prebid/prebid-server
Pull request #3049 (2023-08-23 13:31:58)

Remove tmax feature development flag check
Changes planned for tmax are implemented. So tmax feature development flag check is no longer needed.


Patch:
diff --git a/adapters/flipp/flipp.go b/adapters/flipp/flipp.go
index 9705fa57..14f31a91 100644
--- a/adapters/flipp/flipp.go
+++ b/adapters/flipp/flipp.go
@@ -114,9 +114,7 @@ func (a *adapter) processImp(request *openrtb2.BidRequest, imp openrtb2.Imp) (*a
 	}
 
 	var userIP string
-	if flippExtParams.IP != "" {
-		userIP = flippExtParams.IP
-	} else if request.Device != nil && request.Device.IP != "" {
+	if request.Device != nil && request.Device.IP != "" {
 		userIP = request.Device.IP
 	} else {
 		return nil, fmt.Errorf("no IP set in flipp bidder params or request device")
diff --git a/config/bidderinfo.go b/config/bidderinfo.go
index c0d89841..df9e9d5a 100644
--- a/config/bidderinfo.go
+++ b/config/bidderinfo.go
@@ -350,7 +350,7 @@ func (infos BidderInfos) validate(errs []error) []error {
 		if bidder.IsEnabled() {
 			errs = validateAdapterEndpoint(bidder.Endpoint, bidderName, errs)
 
-			if err := validateInfo(bidder, bidderName); err != nil {
+			if err := validateInfo(bidder, infos, bidderName); err != nil {
 				errs = append(errs, err)
 			}
 
@@ -417,14 +417,18 @@ func validateAdapterEndpoint(endpoint string, bidderName string, errs []error) [
 	return errs
 }
 
-func validateInfo(info BidderInfo, bidderName string) error {
-	if err := validateMaintainer(info.Maintainer, bidderName); err != nil {
+func validateInfo(bidder BidderInfo, infos BidderInfos, bidderName string) error {
+	if err := validateMaintainer(bidder.Maintainer, bidderName); err != nil {
 		return err
 	}
-	if err := validateCapabilities(info.Capabilities, bidderName); err != nil {
+	if err := validateCapabilities(bidder.Capabilities, bidderName); err != nil {
 		return err
 	}
-
+	if len(bidder.AliasOf) > 0 {
+		if err := validateAliasCapabilities(bidder, infos, bidderName); err != nil {
+			return err
+		}
+	}
 	return nil
 }
 
@@ -435,6 +439,52 @@ func validateMaintainer(info *MaintainerInfo, bidderName string) error {
 	return nil
 }
 
+func validateAliasCapabilities(aliasBidderInfo BidderInfo, infos BidderInfos, bidderName string) error {
+	parentBidder, parentFound := infos[aliasBidderInfo.AliasOf]
+	if !parentFound {
+		return fmt.Errorf("parent bidder: %s not found for an alias: %s", aliasBidderInfo.AliasOf, bidderName)
+	}
+
+	if aliasBidderInfo.Capabilities != nil {
+		if parentBidder.Capabilities == nil {
+			return fmt.Errorf("capabilities for alias: %s should be a subset of capabilities for parent bidder: %s", bidderName, aliasBidderInfo.AliasOf)
+		}
+
+		if (aliasBidderInfo.Capabilities.App != nil && parentBidder.Capabilities.App == nil) || (aliasBidderInfo.Capabilities.Site != nil && parentBidder.Capabilities.Site == nil) {
+			return fmt.Errorf("capabilities for alias: %s should be a subset of capabilities for parent bidder: %s", bidderName, aliasBidderInfo.AliasOf)
+		}
+
+		if aliasBidderInfo.Capabilities.Site != nil && parentBidder.Capabilities.Site != nil {
+			if err := isAliasPlatformInfoSubsetOfParent(*parentBidder.Capabilities.Site, *aliasBidderInfo.Capabilities.Site, bidderName, aliasBidderInfo.AliasOf); err != nil {
+				return err
+			}
+		}
+
+		if aliasBidderInfo.Capabilities.App != nil && parentBidder.Capabilities.App != nil {
+			if err := isAliasPlatformInfoSubsetOfParent(*parentBidder.Capabilities.App, *aliasBidderInfo.Capabilities.App, bidderName, aliasBidderInfo.AliasOf); err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+func isAliasPlatformInfoSubsetOfParent(parentInfo PlatformInfo, aliasInfo PlatformInfo, bidderName string, parentBidderName string) error {
+	parentMediaTypes := make(map[openrtb_ext.BidType]struct{})
+	for _, info := range parentInfo.MediaTypes {
+		parentMediaTypes[info] = struct{}{}
+	}
+
+	for _, info := range aliasInfo.MediaTypes {
+		if _, found := parentMediaTypes[info]; !found {
+			return fmt.Errorf("mediaTypes for alias: %s should be a subset of MediaTypes for parent bidder: %s", bidderName, parentBidderName)
+		}
+	}
+
+	return nil
+}
+
 func validateCapabilities(info *CapabilitiesInfo, bidderName string) error {
 	if info == nil {
 		return fmt.Errorf("missing required field: capabilities for adapter: %s", bidderName)
diff --git a/config/config.go b/config/config.go
index 353787aa..2b539c57 100644
--- a/config/config.go
+++ b/config/config.go
@@ -149,11 +149,6 @@ func (cfg *Configuration) validate(v *viper.Viper) []error {
 		errs = append(errs, errors.New("account_defaults.Events.VASTEvents has no effect as the feature is under development."))
 	}
 
-	if cfg.TmaxAdjustments.Enabled {
-		glog.Warning(`cfg.TmaxAdjustments.Enabled will currently not do anything as tmax adjustment feature is still under development.`)
-		cfg.TmaxAdjustments.Enabled = false
-	}
-
 	if cfg.AccountDefaults.Privacy != nil {
 		glog.Warning("account_defaults.Privacy has no effect as the feature is under development.")
 	}
diff --git a/exchange/adapter_util.go b/exchange/adapter_util.go
index c863f52a..ee9a066a 100644
--- a/exchange/adapter_util.go
+++ b/exchange/adapter_util.go
@@ -43,6 +43,13 @@ func buildBidders(infos config.BidderInfos, builders map[openrtb_ext.BidderName]
 			continue
 		}
 
+		if len(info.AliasOf) > 0 {
+			if err := setAliasBuilder(info, builders, bidderName); err != nil {
+				errs = append(errs, fmt.Errorf("%v: failed to set alias builder: %v", bidder, err))
+				continue
+			}
+		}
+
 		builder, builderFound := builders[bidderName]
 		if !builderFound {
 			errs = append(errs, fmt.Errorf("%v: builder not registered", bidder))
@@ -63,6 +70,20 @@ func buildBidders(infos config.BidderInfos, builders map[openrtb_ext.BidderName]
 	return bidders, errs
 }
 
+func setAliasBuilder(info config.BidderInfo, builders map[openrtb_ext.BidderName]adapters.Builder, bidderName openrtb_ext.BidderName) error {
+	parentBidderName, parentBidderFound := openrtb_ext.NormalizeBidderName(info.AliasOf)
+	if !parentBidderFound {
+		return fmt.Errorf("unknown parent bidder: %v for alias: %v", info.AliasOf, bidderName)
+	}
+
+	builder, builderFound := builders[parentBidderName]
+	if !builderFound {
+		return fmt.Errorf("%v: parent builder not registered", parentBidderName)
+	}
+	builders[bidderName] = builder
+	return nil
+}
+
 func buildAdapterInfo(bidderInfo config.BidderInfo) config.Adapter {
 	adapter := config.Adapter{}
 	adapter.Endpoint = bidderInfo.Endpoint
diff --git a/openrtb_ext/imp_flipp.go b/openrtb_ext/imp_flipp.go
index 029e2882..56874c02 100644
--- a/openrtb_ext/imp_flipp.go
+++ b/openrtb_ext/imp_flipp.go
@@ -6,7 +6,6 @@ type ImpExtFlipp struct {
 	SiteID                  int64              `json:"siteId"`
 	ZoneIds                 []int64            `json:"zoneIds,omitempty"`
 	UserKey                 string             `json:"userKey,omitempty"`
-	IP                      string             `json:"ip,omitempty"`
 	Options                 ImpExtFlippOptions `json:"options,omitempty"`
 }
 


Test patch:
diff --git a/adapters/flipp/flipptest/exemplary/simple-banner-native.json b/adapters/flipp/flipptest/exemplary/simple-banner-native.json
index c242c323..d8a24131 100644
--- a/adapters/flipp/flipptest/exemplary/simple-banner-native.json
+++ b/adapters/flipp/flipptest/exemplary/simple-banner-native.json
@@ -30,7 +30,6 @@
                                 "creativeType": "NativeX",
                                 "siteId": 1243066,
                                 "zoneIds": [285431],
-                                "ip": "123.123.123.124",
                                 "options": {
                                    "startCompact": true,
                                    "contentCode": "publisher-test-2"
@@ -46,7 +45,7 @@
             "expectedRequest": {
                 "uri": "http://example.com/pserver",
                 "body": {
-                    "ip":"123.123.123.124",
+                    "ip":"123.123.123.123",
                     "keywords":[
                        ""
                     ],
diff --git a/config/bidderinfo_test.go b/config/bidderinfo_test.go
index 60221da2..e505d2f8 100644
--- a/config/bidderinfo_test.go
+++ b/config/bidderinfo_test.go
@@ -905,6 +905,332 @@ func TestBidderInfoValidationNegative(t *testing.T) {
 				errors.New("The endpoint: incorrect for bidderB is not a valid URL"),
 			},
 		},
+		{
+			"Invalid alias Site capabilities",
+			BidderInfos{
+				"bidderA": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						Site: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeVideo,
+							},
+						},
+					},
+				},
+				"bidderB": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						App: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeVideo,
+							},
+						},
+					},
+					AliasOf: "bidderA",
+				},
+			},
+			[]error{
+				errors.New("capabilities for alias: bidderB should be a subset of capabilities for parent bidder: bidderA"),
+			},
+		},
+		{
+			"Invalid alias App capabilities",
+			BidderInfos{
+				"bidderA": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						App: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeVideo,
+							},
+						},
+					},
+				},
+				"bidderB": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						Site: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeVideo,
+							},
+						},
+					},
+					AliasOf: "bidderA",
+				},
+			},
+			[]error{
+				errors.New("capabilities for alias: bidderB should be a subset of capabilities for parent bidder: bidderA"),
+			},
+		},
+		{
+			"Invalid alias capabilities",
+			BidderInfos{
+				"bidderA": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{},
+				},
+				"bidderB": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						App: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeVideo,
+							},
+						},
+					},
+					AliasOf: "bidderA",
+				},
+			},
+			[]error{
+				errors.New("at least one of capabilities.site or capabilities.app must exist for adapter: bidderA"),
+				errors.New("capabilities for alias: bidderB should be a subset of capabilities for parent bidder: bidderA"),
+			},
+		},
+		{
+			"Invalid alias MediaTypes for site",
+			BidderInfos{
+				"bidderA": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						Site: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeVideo,
+							},
+						},
+					},
+				},
+				"bidderB": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						Site: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeBanner,
+								openrtb_ext.BidTypeNative,
+							},
+						},
+					},
+					AliasOf: "bidderA",
+				},
+			},
+			[]error{
+				errors.New("mediaTypes for alias: bidderB should be a subset of MediaTypes for parent bidder: bidderA"),
+			},
+		},
+		{
+			"Invalid alias MediaTypes for app",
+			BidderInfos{
+				"bidderA": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						App: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeVideo,
+							},
+						},
+					},
+				},
+				"bidderB": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						App: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeBanner,
+								openrtb_ext.BidTypeNative,
+							},
+						},
+					},
+					AliasOf: "bidderA",
+				},
+			},
+			[]error{
+				errors.New("mediaTypes for alias: bidderB should be a subset of MediaTypes for parent bidder: bidderA"),
+			},
+		},
+		{
+			"Invalid parent bidder capabilities",
+			BidderInfos{
+				"bidderA": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+				},
+				"bidderB": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						App: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeBanner,
+							},
+						},
+					},
+					AliasOf: "bidderA",
+				},
+			},
+			[]error{
+				errors.New("missing required field: capabilities for adapter: bidderA"),
+				errors.New("capabilities for alias: bidderB should be a subset of capabilities for parent bidder: bidderA"),
+			},
+		},
+		{
+			"Invalid site alias capabilities with both site and app",
+			BidderInfos{
+				"bidderA": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						App: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeBanner,
+								openrtb_ext.BidTypeNative,
+							},
+						},
+						Site: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeNative,
+							},
+						},
+					},
+				},
+				"bidderB": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						App: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeBanner,
+								openrtb_ext.BidTypeNative,
+							},
+						},
+						Site: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeBanner,
+								openrtb_ext.BidTypeNative,
+							},
+						},
+					},
+					AliasOf: "bidderA",
+				},
+			},
+			[]error{
+				errors.New("mediaTypes for alias: bidderB should be a subset of MediaTypes for parent bidder: bidderA"),
+			},
+		},
+		{
+			"Invalid app alias capabilities with both site and app",
+			BidderInfos{
+				"bidderA": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						App: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeBanner,
+								openrtb_ext.BidTypeNative,
+							},
+						},
+						Site: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeNative,
+							},
+						},
+					},
+				},
+				"bidderB": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						App: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeBanner,
+								openrtb_ext.BidTypeNative,
+							},
+						},
+						Site: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeBanner,
+								openrtb_ext.BidTypeNative,
+							},
+						},
+					},
+					AliasOf: "bidderA",
+				},
+			},
+			[]error{
+				errors.New("mediaTypes for alias: bidderB should be a subset of MediaTypes for parent bidder: bidderA"),
+			},
+		},
+		{
+			"Invalid parent bidder for alias",
+			BidderInfos{
+				"bidderB": BidderInfo{
+					Endpoint: "http://bidderA.com/openrtb2",
+					Maintainer: &MaintainerInfo{
+						Email: "maintainer@bidderA.com",
+					},
+					Capabilities: &CapabilitiesInfo{
+						App: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeBanner,
+								openrtb_ext.BidTypeNative,
+							},
+						},
+						Site: &PlatformInfo{
+							MediaTypes: []openrtb_ext.BidType{
+								openrtb_ext.BidTypeBanner,
+								openrtb_ext.BidTypeNative,
+							},
+						},
+					},
+					AliasOf: "bidderC",
+				},
+			},
+			[]error{
+				errors.New("parent bidder: bidderC not found for an alias: bidderB"),
+			},
+		},
 	}
 
 	for _, test := range testCases {
diff --git a/config/config_test.go b/config/config_test.go
index 30733372..a35891ba 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -566,7 +566,7 @@ func TestFullConfig(t *testing.T) {
 	cmpStrings(t, "validations.secure_markup", "skip", cfg.Validations.SecureMarkup)
 	cmpInts(t, "validations.max_creative_width", 0, int(cfg.Validations.MaxCreativeWidth))
 	cmpInts(t, "validations.max_creative_height", 0, int(cfg.Validations.MaxCreativeHeight))
-	cmpBools(t, "tmax_adjustments.enabled", false, cfg.TmaxAdjustments.Enabled) // Tmax adjustment feature is still under development. Therefore enabled flag is set to false
+	cmpBools(t, "tmax_adjustments.enabled", true, cfg.TmaxAdjustments.Enabled)
 	cmpUnsignedInts(t, "tmax_adjustments.bidder_response_duration_min_ms", 700, cfg.TmaxAdjustments.BidderResponseDurationMin)
 	cmpUnsignedInts(t, "tmax_adjustments.bidder_network_latency_buffer_ms", 100, cfg.TmaxAdjustments.BidderNetworkLatencyBuffer)
 	cmpUnsignedInts(t, "tmax_adjustments.pbs_response_preparation_duration_ms", 100, cfg.TmaxAdjustments.PBSResponsePreparationDuration)
diff --git a/exchange/adapter_util_test.go b/exchange/adapter_util_test.go
index f860a1df..611498fe 100644
--- a/exchange/adapter_util_test.go
+++ b/exchange/adapter_util_test.go
@@ -171,6 +171,55 @@ func TestBuildBidders(t *testing.T) {
 	}
 }
 
+func TestSetAliasBuilder(t *testing.T) {
+	rubiconBidder := fakeBidder{"b"}
+	ixBidder := fakeBidder{"ix"}
+	rubiconBuilder := fakeBuilder{rubiconBidder, nil}.Builder
+	ixBuilder := fakeBuilder{ixBidder, nil}.Builder
+
+	testCases := []struct {
+		description      string
+		bidderInfo       config.BidderInfo
+		builders         map[openrtb_ext.BidderName]adapters.Builder
+		bidderName       openrtb_ext.BidderName
+		expectedBuilders map[openrtb_ext.BidderName]adapters.Builder
+		expectedError    error
+	}{
+		{
+			description:      "Success - Alias builder",
+			bidderInfo:       config.BidderInfo{Disabled: false, AliasOf: "rubicon"},
+			bidderName:       openrtb_ext.BidderName("appnexus"),
+			builders:         map[openrtb_ext.BidderName]adapters.Builder{openrtb_ext.BidderRubicon: rubiconBuilder},
+			expectedBuilders: map[openrtb_ext.BidderName]adapters.Builder{openrtb_ext.BidderRubicon: rubiconBuilder, openrtb_ext.BidderAppnexus: rubiconBuilder},
+		},
+		{
+			description:   "Failure - Invalid parent bidder builder",
+			bidderInfo:    config.BidderInfo{Disabled: false, AliasOf: "rubicon"},
+			bidderName:    openrtb_ext.BidderName("appnexus"),
+			builders:      map[openrtb_ext.BidderName]adapters.Builder{openrtb_ext.BidderIx: ixBuilder},
+			expectedError: errors.New("rubicon: parent builder not registered"),
+		},
+		{
+			description:   "Failure - Invalid parent for alias",
+			bidderInfo:    config.BidderInfo{Disabled: false, AliasOf: "unknown"},
+			bidderName:    openrtb_ext.BidderName("appnexus"),
+			builders:      map[openrtb_ext.BidderName]adapters.Builder{openrtb_ext.BidderIx: ixBuilder},
+			expectedError: errors.New("unknown parent bidder: unknown for alias: appnexus"),
+		},
+	}
+
+	for _, test := range testCases {
+		err := setAliasBuilder(test.bidderInfo, test.builders, test.bidderName)
+
+		if test.expectedBuilders != nil {
+			assert.ObjectsAreEqual(test.builders, test.expectedBuilders)
+		}
+		if test.expectedError != nil {
+			assert.EqualError(t, test.expectedError, err.Error(), test.description+":errors")
+		}
+	}
+}
+
 func TestGetActiveBidders(t *testing.T) {
 	testCases := []struct {
 		description string