Repository: prebid/prebid-server
Pull request #3324 (2023-11-28 06:18:45)

HuaweiAds: add popular sizes for video native
Popular sizes have been added to video native ad request. If the requested ad size is given in the request, it is also added, if it is not in popular sizes.

github-actions[bot]: ## Code coverage summary 
Note: 
- Prebid team doesn't anticipate tests covering code paths that might result in marshal and unmarshal errors 
- Coverage summary encompasses all commits leading up to the latest one, 89c2e9914dafdc7a644ed17132c21c6c99553a98 
#### huaweiads 
Refer [here](https://htmlpreview.github.io/?https://github.com/prebid/prebid-server/coverage-preview/.github/preview/7014978062_1701152371/huaweiads.html) for heat map coverage report 
``` 
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:267:		MakeRequests				93.3%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:325:		getFinalEndPoint			85.7%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:355:		MakeBids				91.7%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:382:		Builder					100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:395:		getExtraInfo				94.1%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:430:		getHeaders				88.9%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:446:		getReqJson				90.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:461:		getReqAdslot30				100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:483:		checkAndExtractOpenrtbFormat		100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:511:		getBannerFormat				100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:527:		getNativeFormat				95.1%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:597:		filterPopularSizes			100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:617:		isSizeInArray				0.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:627:		getVideoFormat				100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:640:		convertAdtypeStringToInteger		60.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:664:		getReqAppInfo				93.8%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:698:		getFinalPkgName				93.8%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:733:		getClientTime				75.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:753:		getReqDeviceInfo			96.6%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:796:		getCountryCode				100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:809:		convertCountryCode			75.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:830:		getCountryCodeFromMCC			100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:847:		getDeviceIDFromUserExt			100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:892:		getReqNetWorkInfo			85.7%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:928:		getReqRegsInfo				100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:937:		getReqGeoInfo				100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:949:		getReqConsentInfo			80.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:959:		unmarshalExtImpHuaweiAds		88.2%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:986:		checkRespStatusCode			77.8%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1009:	checkHuaweiAdsResponseRetcode		71.4%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1027:	convertHuaweiAdsRespToBidderResp	90.2%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1096:	getNurl					66.7%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1109:	handleHuaweiAdsContent			87.5%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1129:	extractAdmBanner			60.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1151:	extractAdmNative			90.9%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1274:	getDecodeValue				80.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1285:	jsonEncode				100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1294:	extractAdmPicture			90.9%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1357:	getClickUrl				100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1374:	getDspImpClickTrackings			100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1388:	getStrings				87.5%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1403:	getDuration				100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1410:	extractAdmVideo				85.4%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1573:	getVastImpClickErrorTrackingUrls	100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1593:	getVastEventTrackingUrls		100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1613:	computeHmacSha256			100.0%
github.com/prebid/prebid-server/v2/adapters/huaweiads/huaweiads.go:1620:	getDigestAuthorization			100.0%
total:										(statements)				90.3%

 ``` 


Patch:
diff --git a/adapters/adhese/adhese.go b/adapters/adhese/adhese.go
index 56d60be2..29c21ef3 100644
--- a/adapters/adhese/adhese.go
+++ b/adapters/adhese/adhese.go
@@ -141,6 +141,9 @@ func (a *AdheseAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalR
 		return nil, []error{err, WrapServerError(fmt.Sprintf("Response %v could not be parsed as generic Adhese bid.", string(response.Body)))}
 	}
 
+	if len(adheseBidResponseArray) == 0 {
+		return nil, nil
+	}
 	var adheseBid = adheseBidResponseArray[0]
 
 	if adheseBid.Origin == "JERLICIA" {
diff --git a/adapters/adhese/adhesetest/supplemental/res-no_bids.json b/adapters/adhese/adhesetest/supplemental/res-no_bids_204.json
similarity index 100%
rename from adapters/adhese/adhesetest/supplemental/res-no_bids.json
rename to adapters/adhese/adhesetest/supplemental/res-no_bids_204.json
diff --git a/adapters/huaweiads/huaweiads.go b/adapters/huaweiads/huaweiads.go
index 0d4f43e1..06ad88f4 100644
--- a/adapters/huaweiads/huaweiads.go
+++ b/adapters/huaweiads/huaweiads.go
@@ -535,7 +535,7 @@ func getNativeFormat(adslot30 *adslot30, openRTBImp *openrtb2.Imp) error {
 	}
 
 	//popular size for native ads
-	popularSizes := []map[string]int64{{"w": 225, "h": 150}, {"w": 300, "h": 250}, {"w": 320, "h": 250}, {"w": 640, "h": 360}, {"w": 1080, "h": 170}, {"w": 1080, "h": 430}, {"w": 1080, "h": 432}, {"w": 1080, "h": 504}, {"w": 1080, "h": 607}, {"w": 1080, "h": 1620}, {"w": 1200, "h": 627}, {"w": 1280, "h": 720}, {"w": 1312, "h": 768}, {"w": 1920, "h": 1080}}
+	popularSizes := []format{{W: 225, H: 150}, {W: 1080, H: 607}, {W: 300, H: 250}, {W: 1080, H: 1620}, {W: 1280, H: 720}, {W: 640, H: 360}, {W: 1080, H: 1920}, {W: 720, H: 1280}}
 
 	// only compute the main image number, type = native1.ImageAssetTypeMain
 	var numMainImage = 0
@@ -555,11 +555,21 @@ func getNativeFormat(adslot30 *adslot30, openRTBImp *openrtb2.Imp) error {
 			}
 		}
 	}
+
+	sizeMap := make(map[format]struct{})
+	for _, size := range popularSizes {
+		sizeMap[size] = struct{}{}
+	}
+
 	for _, asset := range nativePayload.Assets {
 		// Only one of the {title,img,video,data} objects should be present in each object.
 		if asset.Video != nil {
 			numVideo++
-			continue
+			formats = popularSizes
+			_, ok := sizeMap[format{W: asset.Video.W, H: asset.Video.H}]
+			if (asset.Video.W != 0 && asset.Video.H != 0) && !ok {
+				formats = append(formats, format{asset.Video.W, asset.Video.H})
+			}
 		}
 		// every image has the same W, H.
 		if asset.Img != nil {
@@ -570,37 +580,38 @@ func getNativeFormat(adslot30 *adslot30, openRTBImp *openrtb2.Imp) error {
 				}
 				if numFormat == 1 && asset.Img.H != 0 && asset.Img.W != 0 && asset.Img.WMin != 0 && asset.Img.HMin != 0 {
 					result := filterPopularSizes(popularSizes, asset.Img.W, asset.Img.H, "ratio")
-					for i := 0; i < len(result); i++ {
-						formats = append(formats, format{result[i]["w"], result[i]["h"]})
-					}
+					formats = append(formats, result...)
 				}
 				if numFormat == 1 && asset.Img.H == 0 && asset.Img.W == 0 && asset.Img.WMin != 0 && asset.Img.HMin != 0 {
-					result := filterPopularSizes(popularSizes, asset.Img.W, asset.Img.H, "range")
-					for i := 0; i < len(result); i++ {
-						formats = append(formats, format{result[i]["w"], result[i]["h"]})
-					}
+					result := filterPopularSizes(popularSizes, asset.Img.WMin, asset.Img.HMin, "range")
+					formats = append(formats, result...)
 				}
 			}
 		}
 		adslot30.Format = formats
 	}
-	detailedCreativeTypeList = append(detailedCreativeTypeList, "901", "905")
+	if numVideo >= 1 {
+		detailedCreativeTypeList = append(detailedCreativeTypeList, "903")
+	}
+	if numMainImage >= 1 {
+		detailedCreativeTypeList = append(detailedCreativeTypeList, "901", "904", "905")
+	}
 	adslot30.DetailedCreativeTypeList = detailedCreativeTypeList
 	return nil
 }
 
 // filter popular size by range or ratio to append format array
-func filterPopularSizes(sizes []map[string]int64, width int64, height int64, byWhat string) []map[string]int64 {
+func filterPopularSizes(sizes []format, width int64, height int64, byWhat string) []format {
 
-	filtered := []map[string]int64{}
+	filtered := []format{}
 	for _, size := range sizes {
-		w := size["w"]
-		h := size["h"]
+		w := size.W
+		h := size.H
 
 		if byWhat == "ratio" {
 			ratio := float64(width) / float64(height)
 			diff := math.Abs(float64(w)/float64(h) - ratio)
-			if diff <= 0.3 {
+			if diff <= 0.5 {
 				filtered = append(filtered, size)
 			}
 		}
diff --git a/adapters/yieldmo/yieldmo.go b/adapters/yieldmo/yieldmo.go
index 795d32b8..69841e88 100644
--- a/adapters/yieldmo/yieldmo.go
+++ b/adapters/yieldmo/yieldmo.go
@@ -30,6 +30,10 @@ type Ext struct {
 	Gpid        string `json:"gpid,omitempty"`
 }
 
+type ExtBid struct {
+	MediaType string `json:"mediatype,omitempty"`
+}
+
 func (a *YieldmoAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
 	var errs []error
 	var adapterRequests []*adapters.RequestData
@@ -138,14 +142,18 @@ func (a *YieldmoAdapter) MakeBids(internalRequest *openrtb2.BidRequest, external
 
 	for _, sb := range bidResp.SeatBid {
 		for i := range sb.Bid {
+			bidType, err := getMediaTypeForImp(sb.Bid[i])
+			if err != nil {
+				continue
+			}
+
 			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
 				Bid:     &sb.Bid[i],
-				BidType: getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp),
+				BidType: bidType,
 			})
 		}
 	}
 	return bidResponse, nil
-
 }
 
 // Builder builds a new instance of the Yieldmo adapter for the given bidder with the given config.
@@ -156,12 +164,21 @@ func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server co
 	return bidder, nil
 }
 
-func getMediaTypeForImp(impId string, imps []openrtb2.Imp) openrtb_ext.BidType {
-	//default to video unless banner exists in impression
-	for _, imp := range imps {
-		if imp.ID == impId && imp.Banner != nil {
-			return openrtb_ext.BidTypeBanner
-		}
+// Retrieve the media type corresponding to the bid from the bid.ext object
+func getMediaTypeForImp(bid openrtb2.Bid) (openrtb_ext.BidType, error) {
+	var bidExt ExtBid
+	if err := json.Unmarshal(bid.Ext, &bidExt); err != nil {
+		return "", &errortypes.BadInput{Message: err.Error()}
+	}
+
+	switch bidExt.MediaType {
+	case "banner":
+		return openrtb_ext.BidTypeBanner, nil
+	case "video":
+		return openrtb_ext.BidTypeVideo, nil
+	case "native":
+		return openrtb_ext.BidTypeNative, nil
+	default:
+		return "", fmt.Errorf("invalid BidType: %s", bidExt.MediaType)
 	}
-	return openrtb_ext.BidTypeVideo
 }
diff --git a/endpoints/setuid.go b/endpoints/setuid.go
index f9c55fc8..aae31f10 100644
--- a/endpoints/setuid.go
+++ b/endpoints/setuid.go
@@ -126,7 +126,6 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
 				handleBadStatus(w, http.StatusBadRequest, metrics.SetUidBadRequest, err, metricsEngine, &so)
 				return
 			}
-			w.Write([]byte("Warning: " + err.Error()))
 		}
 
 		tcf2Cfg := tcf2CfgBuilder(cfg.GDPR.TCF2, account.GDPR)
diff --git a/exchange/exchange.go b/exchange/exchange.go
index 211d82fc..446dfaf9 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -762,6 +762,7 @@ func (e *exchange) getAllBids(
 					} else {
 						adapterBids[bidderName] = seatBid
 					}
+					extraRespInfo.bidsFound = true
 				}
 				// collect fledgeAuctionConfigs separately from bids, as empty seatBids may be discarded
 				extraRespInfo.fledge = collectFledgeFromSeatBid(extraRespInfo.fledge, bidderName, brw.adapter, seatBid)
@@ -769,10 +770,6 @@ func (e *exchange) getAllBids(
 		}
 		//but we need to add all bidders data to adapterExtra to have metrics and other metadata
 		adapterExtra[brw.bidder] = brw.adapterExtra
-
-		if !extraRespInfo.bidsFound && adapterBids[brw.bidder] != nil && len(adapterBids[brw.bidder].Bids) > 0 {
-			extraRespInfo.bidsFound = true
-		}
 	}
 
 	return adapterBids, adapterExtra, extraRespInfo
diff --git a/static/bidder-info/boldwin.yaml b/static/bidder-info/boldwin.yaml
index 39c1caf3..f35d08ca 100644
--- a/static/bidder-info/boldwin.yaml
+++ b/static/bidder-info/boldwin.yaml
@@ -13,3 +13,7 @@ capabilities:
     - banner
     - video
     - native
+userSync:
+  redirect:
+    url: "https://sync.videowalldirect.com/pbserver?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&ccpa={{.USPrivacy}}&redir={{.RedirectURL}}"
+    userMacro: "[UID]"
\ No newline at end of file


Test patch:
diff --git a/adapters/adhese/adhesetest/supplemental/res-no_bids_200.json b/adapters/adhese/adhesetest/supplemental/res-no_bids_200.json
new file mode 100644
index 00000000..2a778bdf
--- /dev/null
+++ b/adapters/adhese/adhesetest/supplemental/res-no_bids_200.json
@@ -0,0 +1,54 @@
+{
+  "mockBidRequest": {
+    "id": "test-req",
+    "user": {
+      "ext": {
+        "consent" : "dummy"
+      }
+    },
+    "imp": [
+      {
+        "id": "test-req",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "account": "demo",
+            "location": "_adhese_prebid_demo_",
+            "format": "leaderboard",
+            "targets": 
+            {
+              "ci": ["gent", "brussels"],
+              "ag": ["55"],
+              "tl": ["all"]
+            }
+          }
+        }
+      }
+    ],
+    "site": {
+      "id": "test",
+      "publisher": {
+        "id": "123"
+      }
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels/tlall/xtdummy"
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": []
+      }
+    }
+  ],
+  "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/nativeIncludeVideo.json b/adapters/huaweiads/huaweiadstest/exemplary/nativeIncludeVideo.json
index 49562dac..c38c4124 100644
--- a/adapters/huaweiads/huaweiadstest/exemplary/nativeIncludeVideo.json
+++ b/adapters/huaweiads/huaweiadstest/exemplary/nativeIncludeVideo.json
@@ -5,7 +5,7 @@
       {
         "id": "test-imp-id",
         "native": {
-          "request": "{\"context\":2,\"contextsubtype\":20,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"aurlsupport\":0,\"durlsupport\":0,\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}],\"privacy\":0,\"assets\":[{\"id\":100,\"title\":{\"len\":90},\"required\":1},{\"id\":101,\"img\":{\"type\":3,\"w\":200,\"h\":300,\"wmin\":300,\"hmin\":200},\"required\":1},{\"id\":102,\"img\":{\"type\":3,\"w\":400,\"h\":500,\"wmin\":400,\"hmin\":500},\"required\":1},{\"id\":103,\"img\":{\"type\":3,\"w\":300,\"h\":250,\"wmin\":300,\"hmin\":250},\"required\":1},{\"id\":105,\"data\":{\"type\":2,\"len\":90},\"required\":1}],\"ver\":\"1.2\"}",
+          "request": "{\"context\":2,\"contextsubtype\":20,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"aurlsupport\":0,\"durlsupport\":0,\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}],\"privacy\":0,\"assets\":[{\"id\":100,\"title\":{\"len\":90},\"required\":1},{\"id\":101,\"img\":{\"type\":3,\"wmin\":1080,\"hmin\":607},\"required\":1},{\"id\":107,\"video\":{\"mimes\":[\"mp4\"],\"minduration\":100,\"maxduration\":100,\"protocols\":[1,2]},\"required\":1},{\"id\":105,\"data\":{\"type\":2,\"len\":90},\"required\":1}],\"ver\":\"1.2\"}",
           "ver": "1.2"
         },
         "ext": {
@@ -21,14 +21,15 @@
       }
     ],
     "app": {
-      "bundle": "com.huawei.p11",
+      "bundle": "com.huawei.browser",
       "name": "Huawei Browser",
       "ver": "9.1.0.301"
     },
     "device": {
       "ua": "useragent",
       "h": 1920,
-      "language": "en",
+      "language": "zh",
+      "geoCountry": "CH",
       "model": "COL-TEST",
       "os": "android",
       "osv": "10.0.0",
@@ -38,10 +39,12 @@
       "ip": "152.193.6.74",
       "pxratio": 23.01,
       "geo": {
-        "country": "ARG"
+        "country": ""
       }
     },
     "user": {
+      "id": "db089de9-a62e-4861-a881-0ff15e052516",
+      "buyeruid": "v4_bidder_token",
       "ext": {
         "data": {
           "gaid": [
@@ -80,44 +83,28 @@
         "body": {
           "app": {
             "lang": "en",
-            "country": "AR",
+            "country": "ZA",
             "name": "Huawei Browser",
-            "pkgname": "com.example.pkgname2",
+            "pkgname": "com.huawei.browser",
             "version": "9.1.0.301"
           },
           "multislot": [
             {
               "adtype": 3,
               "slotid": "u42ohmaufh",
-              "detailedCreativeTypeList": [
-                "901",
-                "905"
-              ],
-              "format": [
-                {
-                    "w": 200,
-                    "h": 300
-                },
-                {
-                    "w": 400,
-                    "h": 500
-                },
-                {
-                    "w": 300,
-                    "h": 250
-                }
-            ],
+              "detailedCreativeTypeList":["903","901","904","905"],
+              "format":[{"w":225,"h":150},{"w":1080,"h":607},{"w":300,"h":250},{"w":1080,"h":1620},{"w":1280,"h":720},{"w":640,"h":360},{"w":1080,"h":1920},{"w":720,"h":1280}],
               "test": 1
             }
           ],
           "device": {
             "height": 1920,
-            "language": "en",
+            "language": "zh",
             "oaid": "oaid",
             "os": "android",
             "type": 4,
             "ip": "152.193.6.74",
-            "localeCountry": "AR",
+            "localeCountry": "ZA",
             "pxratio": 23.01,
             "model": "COL-TEST",
             "width": 1080,
@@ -126,7 +113,7 @@
             "useragent": "useragent",
             "version": "10.0.0",
             "maker": "huawei",
-            "belongCountry": "AR"
+            "belongCountry": "ZA"
           },
           "geo": {
           },
@@ -156,7 +143,7 @@
                   "metaData": {
                     "adSign": "2",
                     "apkInfo": {
-                      "appIcon": "https://icon.png",
+                      "appIcon": "https://pps-icon.png",
                       "appName": "%E6%89%8B%E6%9C%BA%E6%B7%98%E5%AE%9D",
                       "fileSize": 118902470,
                       "packageName": "com.demo.package",
@@ -181,80 +168,61 @@
                         "height": 160,
                         "imageType": "img",
                         "sha256": "042479eccbda9a8d7d3aa3da73c42486854407835623a30ffff875cb578242d0",
-                        "url": "https://icon1.png",
-                        "width": 160
-                      },
-                      {
-                        "checkSha256Flag": 1,
-                        "fileSize": 10797,
-                        "height": 320,
-                        "imageType": "img",
-                        "sha256": "042479eccbda9a8d7d3aa3da73c42486854407835623a30ffff875cb578242d0",
-                        "url": "https://icon2.png",
+                        "url": "https://pps-icon.png",
                         "width": 160
                       }
                     ],
                     "imageInfo": [
                       {
                         "checkSha256Flag": 0,
-                        "height": 350,
+                        "height": 607,
                         "imageType": "img",
                         "sha256": "8baa56fdb2702b9fb044d95b328936160cd245764375cdb25a4ab504f4ae2e19",
                         "url": "http://image1.jpg",
-                        "width": 400
-                      },
-                      {
-                        "checkSha256Flag": 0,
-                        "height": 300,
-                        "imageType": "img",
-                        "sha256": "8baa56fdb2702b9fb044d95b328936160cd245764375cdb25a4ab504f4ae2e19",
-                        "url": "http://image2.jpg",
-                        "width": 400
-                      },
-                      {
-                        "checkSha256Flag": 0,
-                        "height": 300,
-                        "imageType": "img",
-                        "sha256": "8baa56fdb2702b9fb044d95b328936160cd245764375cdb25a4ab504f4ae2e19",
-                        "url": "http://image3.jpg",
-                        "width": 400
+                        "width": 1080
                       }
                     ],
                     "label": "%E6%89%8B%E6%9C%BA%E6%B7%98%E5%AE%9D",
                     "landingPageType": "3",
                     "marketAppId": "C101219405",
                     "title": "%2Ftest%2F",
-                    "description": "this is a test ad"
+                    "description": "this is a test ad",
+                    "videoInfo": {
+                      "autoPlayAreaRatio": 100,
+                      "autoStopPlayAreaRatio": 10,
+                      "checkSha256Flag": 1,
+                      "sha256": "aa08c8ffce82bbcd37cabefd6c8972b407de48f0b4e332e06d4cc18d25377d77",
+                      "timeBeforeVideoAutoPlay": 50,
+                      "videoAutoPlayOnWifi": "y",
+                      "videoAutoPlayWithSound": "n",
+                      "videoDownloadUrl": "https://video.mp4",
+                      "videoDuration": 6038,
+                      "videoFileSize": 949951,
+                      "videoPlayMode": 2,
+                      "videoRatio": 0.5625,
+                      "width": 600,
+                      "height": 500
+                    }
                   },
                   "monitor": [
                     {
-                      "eventType": "click",
-                      "url": [
-                        "http://test/click"
-                      ]
-                    },
-                    {
-                      "eventType": "imp",
-                      "url": [
-                        "http://test/imp"
-                      ]
-                    },
-                    {
-                      "eventType": "download",
+                      "eventType": "vastError",
                       "url": [
-                        "http://test/download"
+                        "http://test/vastError"
                       ]
                     },
                     {
-                      "eventType": "install",
+                      "eventType": "click",
                       "url": [
-                        "http://test/install"
+                        "http://test/click",
+                        "http://test/dspclick"
                       ]
                     },
                     {
-                      "eventType": "downloadstart",
+                      "eventType": "imp",
                       "url": [
-                        "http://test/downloadstart"
+                        "http://test/imp",
+                        "http://test/dspimp"
                       ]
                     },
                     {
@@ -272,7 +240,8 @@
                     {
                       "eventType": "playEnd",
                       "url": [
-                        "http://test/playEnd"
+                        "http://test/playEnd1",
+                        "http://test/playEnd2"
                       ]
                     },
                     {
@@ -332,12 +301,12 @@
               "huaweiads"
             ],
             "crid": "58022259",
-            "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":100,\"title\":{\"text\":\"/test/\",\"len\":6}},{\"id\":101,\"img\":{\"type\":3,\"url\":\"http://image1.jpg\",\"w\":400,\"h\":350}},{\"id\":102,\"img\":{\"type\":3,\"url\":\"http://image2.jpg\",\"w\":400,\"h\":300}},{\"id\":103,\"img\":{\"type\":3,\"url\":\"http://image3.jpg\",\"w\":400,\"h\":300}},{\"id\":105,\"data\":{\"label\":\"desc\",\"value\":\"this is a test ad\"}}],\"link\":{\"url\":\"https://ads.huawei.com/usermgtportal/home/index.html#/\",\"clicktrackers\":[\"http://test/click\"]},\"eventtrackers\":[{\"event\":1,\"method\":1,\"url\":\"http://test/imp\"}]}",
+            "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":100,\"title\":{\"text\":\"/test/\",\"len\":6}},{\"id\":101,\"img\":{\"type\":3,\"url\":\"http://image1.jpg\",\"w\":1080,\"h\":607}},{\"id\":107,\"video\":{\"vasttag\":\"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?><VAST version=\\\"3.0\\\"><Ad id=\\\"58022259\\\"><InLine><AdSystem>HuaweiAds</AdSystem><AdTitle>/test/</AdTitle><Error><![CDATA[http://test/vastError&et=[ERRORCODE]]]></Error><Impression><![CDATA[http://test/imp]]></Impression><Impression><![CDATA[http://test/dspimp]]></Impression><Creatives><Creative adId=\\\"58022259\\\" id=\\\"58022259\\\"><Linear><Duration>00:00:06.038</Duration><TrackingEvents><Tracking event=\\\"skip\\\"><![CDATA[http://test/userclose]]></Tracking><Tracking event=\\\"closeLinear\\\"><![CDATA[http://test/userclose]]></Tracking><Tracking event=\\\"start\\\"><![CDATA[http://test/playStart]]></Tracking><Tracking event=\\\"complete\\\"><![CDATA[http://test/playEnd1]]></Tracking><Tracking event=\\\"complete\\\"><![CDATA[http://test/playEnd2]]></Tracking><Tracking event=\\\"resume\\\"><![CDATA[http://test/playResume]]></Tracking><Tracking event=\\\"pause\\\"><![CDATA[http://test/playPause]]></Tracking></TrackingEvents><VideoClicks><ClickThrough><![CDATA[https://ads.huawei.com/usermgtportal/home/index.html#/]]></ClickThrough><ClickTracking><![CDATA[http://test/click]]></ClickTracking><ClickTracking><![CDATA[http://test/dspclick]]></ClickTracking></VideoClicks><MediaFiles><MediaFile delivery=\\\"progressive\\\" type=\\\"video/mp4\\\" width=\\\"600\\\" height=\\\"500\\\" scalable=\\\"true\\\" maintainAspectRatio=\\\"true\\\"> <![CDATA[https://video.mp4]]></MediaFile></MediaFiles></Linear></Creative></Creatives></InLine></Ad></VAST>\"}},{\"id\":105,\"data\":{\"label\":\"desc\",\"value\":\"this is a test ad\"}}],\"link\":{\"url\":\"https://ads.huawei.com/usermgtportal/home/index.html#/\",\"clicktrackers\":[\"http://test/click\",\"http://test/dspclick\"]},\"eventtrackers\":[{\"event\":1,\"method\":1,\"url\":\"http://test/imp\"},{\"event\":1,\"method\":1,\"url\":\"http://test/dspimp\"}]}",
             "id": "test-imp-id",
             "impid": "test-imp-id",
             "price": 2.8,
-            "h": 350,
-            "w": 400
+            "h": 500,
+            "w": 600
           },
           "type": "native"
         }
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/nativeMultiSizesByRange.json b/adapters/huaweiads/huaweiadstest/exemplary/nativeMultiSizesByRange.json
index 92d62bac..97679a3b 100644
--- a/adapters/huaweiads/huaweiadstest/exemplary/nativeMultiSizesByRange.json
+++ b/adapters/huaweiads/huaweiadstest/exemplary/nativeMultiSizesByRange.json
@@ -92,9 +92,10 @@
                 "slotid": "u42ohmaufh",
                 "detailedCreativeTypeList": [
                   "901",
+                  "904",
                   "905"
                 ],
-                "format":[{"w":225,"h":150},{"w":300,"h":250},{"w":320,"h":250},{"w":640,"h":360},{"w":1080,"h":170},{"w":1080,"h":430},{"w":1080,"h":432},{"w":1080,"h":504},{"w":1080,"h":607},{"w":1080,"h":1620},{"w":1200,"h":627},{"w":1280,"h":720},{"w":1312,"h":768},{"w":1920,"h":1080}],
+                "format":[{"w":1080,"h":607},{"w":300,"h":250},{"w":1080,"h":1620},{"w":1280,"h":720},{"w":640,"h":360},{"w":1080,"h":1920},{"w":720,"h":1280}],
                 "test": 1
               }
             ],
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/nativeMultiSizesByRatio.json b/adapters/huaweiads/huaweiadstest/exemplary/nativeMultiSizesByRatio.json
index cd21f40e..e9c50bae 100644
--- a/adapters/huaweiads/huaweiadstest/exemplary/nativeMultiSizesByRatio.json
+++ b/adapters/huaweiads/huaweiadstest/exemplary/nativeMultiSizesByRatio.json
@@ -92,9 +92,10 @@
                 "slotid": "u42ohmaufh",
                 "detailedCreativeTypeList": [
                   "901",
+                  "904",
                   "905"
                 ],
-              "format": [{"w":225,"h":150},{"w":320,"h":250},{"w":640,"h":360},{"w":1080,"h":607},{"w":1280,"h":720},{"w":1312,"h":768},{"w":1920,"h":1080}],
+                "format":[{"w":225,"h":150},{"w":1080,"h":607},{"w":300,"h":250},{"w":1280,"h":720},{"w":640,"h":360}],
                 "test": 1
               }
             ],
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/nativeSingleImage.json b/adapters/huaweiads/huaweiadstest/exemplary/nativeSingleImage.json
index 4faec81d..4ba3adce 100644
--- a/adapters/huaweiads/huaweiadstest/exemplary/nativeSingleImage.json
+++ b/adapters/huaweiads/huaweiadstest/exemplary/nativeSingleImage.json
@@ -92,66 +92,10 @@
               "slotid": "u42ohmaufh",
               "detailedCreativeTypeList": [
                 "901",
+                "904",
                 "905"
               ],
-              "format": [
-                {
-                    "w": 225,
-                    "h": 150
-                },
-                {
-                    "w": 300,
-                    "h": 250
-                },
-                {
-                    "w": 320,
-                    "h": 250
-                },
-                {
-                    "w": 640,
-                    "h": 360
-                },
-                {
-                    "w": 1080,
-                    "h": 170
-                },
-                {
-                    "w": 1080,
-                    "h": 430
-                },
-                {
-                    "w": 1080,
-                    "h": 432
-                },
-                {
-                    "w": 1080,
-                    "h": 504
-                },
-                {
-                    "w": 1080,
-                    "h": 607
-                },
-                {
-                    "w": 1080,
-                    "h": 1620
-                },
-                {
-                    "w": 1200,
-                    "h": 627
-                },
-                {
-                    "w": 1280,
-                    "h": 720
-                },
-                {
-                    "w": 1312,
-                    "h": 768
-                },
-                {
-                    "w": 1920,
-                    "h": 1080
-                }
-            ],
+              "format":[{"w":1080,"h":607},{"w":300,"h":250},{"w":1080,"h":1620},{"w":1280,"h":720},{"w":640,"h":360},{"w":1080,"h":1920},{"w":720,"h":1280}],
               "test": 1
             }
           ],
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImage.json b/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImage.json
index 49562dac..240dee2d 100644
--- a/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImage.json
+++ b/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImage.json
@@ -91,6 +91,7 @@
               "slotid": "u42ohmaufh",
               "detailedCreativeTypeList": [
                 "901",
+                "904",
                 "905"
               ],
               "format": [
diff --git a/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImageIncludeIcon.json b/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImageIncludeIcon.json
index 6c33294b..3f4222c2 100644
--- a/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImageIncludeIcon.json
+++ b/adapters/huaweiads/huaweiadstest/exemplary/nativeThreeImageIncludeIcon.json
@@ -92,66 +92,10 @@
               "slotid": "u42ohmaufh",
               "detailedCreativeTypeList": [
                 "901",
+                "904",
                 "905"
               ],
-              "format": [
-                {
-                    "w": 225,
-                    "h": 150
-                },
-                {
-                    "w": 300,
-                    "h": 250
-                },
-                {
-                    "w": 320,
-                    "h": 250
-                },
-                {
-                    "w": 640,
-                    "h": 360
-                },
-                {
-                    "w": 1080,
-                    "h": 170
-                },
-                {
-                    "w": 1080,
-                    "h": 430
-                },
-                {
-                    "w": 1080,
-                    "h": 432
-                },
-                {
-                    "w": 1080,
-                    "h": 504
-                },
-                {
-                    "w": 1080,
-                    "h": 607
-                },
-                {
-                    "w": 1080,
-                    "h": 1620
-                },
-                {
-                    "w": 1200,
-                    "h": 627
-                },
-                {
-                    "w": 1280,
-                    "h": 720
-                },
-                {
-                    "w": 1312,
-                    "h": 768
-                },
-                {
-                    "w": 1920,
-                    "h": 1080
-                }
-            ],
+              "format":[{"w":1080,"h":607},{"w":300,"h":250},{"w":1080,"h":1620},{"w":1280,"h":720},{"w":640,"h":360},{"w":1080,"h":1920},{"w":720,"h":1280}],
               "test": 1
             }
           ],
diff --git a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_not_native.json b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_not_native.json
index 75bf3f25..10814d7e 100644
--- a/adapters/huaweiads/huaweiadstest/supplemental/bad_response_not_native.json
+++ b/adapters/huaweiads/huaweiadstest/supplemental/bad_response_not_native.json
@@ -5,7 +5,7 @@
       {
         "id": "test-imp-id",
         "native": {
-          "request": "{\"context\":2,\"contextsubtype\":20,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"aurlsupport\":0,\"durlsupport\":0,\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}],\"privacy\":0,\"assets\":[{\"id\":100,\"title\":{\"len\":90},\"required\":1},{\"id\":101,\"img\":{\"type\":3,\"wmin\":200,\"hmin\":200},\"required\":1},{\"id\":107,\"video\":{\"mimes\":[\"mp4\"],\"minduration\":100,\"maxduration\":100,\"protocols\":[1,2]},\"required\":1},{\"id\":105,\"data\":{\"type\":2,\"len\":90},\"required\":1}],\"ver\":\"1.2\"}",
+          "request": "{\"context\":2,\"contextsubtype\":20,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"aurlsupport\":0,\"durlsupport\":0,\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}],\"privacy\":0,\"assets\":[{\"id\":100,\"title\":{\"len\":90},\"required\":1},{\"id\":107,\"video\":{\"mimes\":[\"mp4\"],\"minduration\":100,\"maxduration\":100,\"protocols\":[1,2]},\"required\":1},{\"id\":105,\"data\":{\"type\":2,\"len\":90},\"required\":1}],\"ver\":\"1.2\"}",
           "ver": "1.2"
         },
         "ext": {
@@ -91,68 +91,43 @@
               "adtype": 3,
               "slotid": "m8x9x3rzff",
               "test": 1,
-              "detailedCreativeTypeList": [
-                "901",
-                "905"
-              ],
               "format": [
                 {
                     "w": 225,
                     "h": 150
                 },
-                {
-                    "w": 300,
-                    "h": 250
-                },
-                {
-                    "w": 320,
-                    "h": 250
-                },
-                {
-                    "w": 640,
-                    "h": 360
-                },
                 {
                     "w": 1080,
-                    "h": 170
-                },
-                {
-                    "w": 1080,
-                    "h": 430
-                },
-                {
-                    "w": 1080,
-                    "h": 432
-                },
-                {
-                    "w": 1080,
-                    "h": 504
+                    "h": 607
                 },
                 {
-                    "w": 1080,
-                    "h": 607
+                    "w": 300,
+                    "h": 250
                 },
                 {
                     "w": 1080,
                     "h": 1620
                 },
-                {
-                    "w": 1200,
-                    "h": 627
-                },
                 {
                     "w": 1280,
                     "h": 720
                 },
                 {
-                    "w": 1312,
-                    "h": 768
+                    "w": 640,
+                    "h": 360
+                },
+                {
+                    "w": 1080,
+                    "h": 1920
                 },
                 {
-                    "w": 1920,
-                    "h": 1080
+                    "w": 720,
+                    "h": 1280
                 }
-            ]
+            ],
+              "detailedCreativeTypeList": [
+                "903"
+              ]
             }
           ],
           "device": {
diff --git a/adapters/yieldmo/yieldmotest/exemplary/app-banner.json b/adapters/yieldmo/yieldmotest/exemplary/app-banner.json
index e674cf11..92609cae 100644
--- a/adapters/yieldmo/yieldmotest/exemplary/app-banner.json
+++ b/adapters/yieldmo/yieldmotest/exemplary/app-banner.json
@@ -65,7 +65,11 @@
                   "adm": "some-test-ad",
                   "crid": "crid_10",
                   "h": 250,
-                  "w": 300
+                  "w": 300,
+                  "ext":
+                  {
+                    "mediatype": "banner"
+                  }
                 }
               ]
             }
@@ -87,7 +91,11 @@
             "adm": "some-test-ad",
             "crid": "crid_10",
             "w": 300,
-            "h": 250
+            "h": 250,
+            "ext":
+            {
+              "mediatype": "banner"
+            }
           },
           "type": "banner"
         }
diff --git a/adapters/yieldmo/yieldmotest/exemplary/app_video.json b/adapters/yieldmo/yieldmotest/exemplary/app_video.json
index e33c37f6..6f94a30b 100644
--- a/adapters/yieldmo/yieldmotest/exemplary/app_video.json
+++ b/adapters/yieldmo/yieldmotest/exemplary/app_video.json
@@ -63,7 +63,11 @@
                   "adm": "some-test-ad",
                   "crid": "crid_10",
                   "h": 250,
-                  "w": 300
+                  "w": 300,
+                  "ext":
+                  {
+                    "mediatype": "video"
+                  }
                 }
               ]
             }
@@ -85,7 +89,11 @@
             "adm": "some-test-ad",
             "crid": "crid_10",
             "w": 300,
-            "h": 250
+            "h": 250,
+            "ext":
+            {
+              "mediatype": "video"
+            }
           },
           "type": "video"
         }
diff --git a/adapters/yieldmo/yieldmotest/exemplary/simple-banner.json b/adapters/yieldmo/yieldmotest/exemplary/simple-banner.json
index 11739ca1..ba243500 100644
--- a/adapters/yieldmo/yieldmotest/exemplary/simple-banner.json
+++ b/adapters/yieldmo/yieldmotest/exemplary/simple-banner.json
@@ -65,7 +65,11 @@
                   "adm": "some-test-ad",
                   "crid": "crid_10",
                   "h": 250,
-                  "w": 300
+                  "w": 300,
+                  "ext":
+                    {
+                      "mediatype": "banner"
+                    }
                 }
               ]
             }
@@ -87,7 +91,11 @@
             "adm": "some-test-ad",
             "crid": "crid_10",
             "w": 300,
-            "h": 250
+            "h": 250,
+            "ext":
+            {
+              "mediatype": "banner"
+            }
           },
           "type": "banner"
         }
diff --git a/adapters/yieldmo/yieldmotest/exemplary/simple_video.json b/adapters/yieldmo/yieldmotest/exemplary/simple_video.json
index aaf53124..ec65bc98 100644
--- a/adapters/yieldmo/yieldmotest/exemplary/simple_video.json
+++ b/adapters/yieldmo/yieldmotest/exemplary/simple_video.json
@@ -63,7 +63,11 @@
                   "adm": "some-test-ad",
                   "crid": "crid_10",
                   "h": 250,
-                  "w": 300
+                  "w": 300,
+                  "ext":
+                  {
+                    "mediatype": "video"
+                  }
                 }
               ]
             }
@@ -85,7 +89,11 @@
             "adm": "some-test-ad",
             "crid": "crid_10",
             "w": 300,
-            "h": 250
+            "h": 250,
+            "ext":
+            {
+              "mediatype": "video"
+            }
           },
           "type": "video"
         }
diff --git a/adapters/yieldmo/yieldmotest/exemplary/with_gpid.json b/adapters/yieldmo/yieldmotest/exemplary/with_gpid.json
index bd9e9110..d155f5db 100644
--- a/adapters/yieldmo/yieldmotest/exemplary/with_gpid.json
+++ b/adapters/yieldmo/yieldmotest/exemplary/with_gpid.json
@@ -73,7 +73,11 @@
                   "adm": "some-test-ad",
                   "crid": "crid_10",
                   "h": 250,
-                  "w": 300
+                  "w": 300,
+                  "ext":
+                  {
+                    "mediatype": "banner"
+                  }
                 }
               ]
             }
@@ -95,7 +99,11 @@
             "adm": "some-test-ad",
             "crid": "crid_10",
             "w": 300,
-            "h": 250
+            "h": 250,
+            "ext":
+            {
+              "mediatype": "banner"
+            }
           },
           "type": "banner"
         }
diff --git a/endpoints/setuid_test.go b/endpoints/setuid_test.go
index fe663797..145be3d3 100644
--- a/endpoints/setuid_test.go
+++ b/endpoints/setuid_test.go
@@ -217,15 +217,25 @@ func TestSetUIDEndpoint(t *testing.T) {
 		},
 		{
 			uri: "/setuid?bidder=pubmatic&uid=123&gpp_sid=2,4&gpp=DBABMA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA" +
-				"gdpr=1&gdpr_consent=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw",
+				"&gdpr=1&gdpr_consent=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw",
 			syncersBidderNameToKey: map[string]string{"pubmatic": "pubmatic"},
 			gdprAllowsHostCookies:  true,
 			existingSyncs:          nil,
 			expectedSyncs:          map[string]string{"pubmatic": "123"},
 			expectedStatusCode:     http.StatusOK,
-			expectedBody:           "Warning: 'gpp' value will be used over the one found in the deprecated 'gdpr_consent' field.",
-			expectedHeaders:        map[string]string{"Content-Type": "text/plain; charset=utf-8"},
-			description:            "Sets uid for a bidder allowed by GDPR in GPP, throws warning because GDPR legacy values weren't used",
+			expectedHeaders:        map[string]string{"Content-Type": "text/html", "Content-Length": "0"},
+			description:            "GPP value will be used over the one found in the deprecated GDPR consent field for iframe format",
+		},
+		{
+			uri: "/setuid?f=i&bidder=pubmatic&uid=123&gpp_sid=2,4&gpp=DBABMA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA" +
+				"&gdpr=1&gdpr_consent=BONciguONcjGKADACHENAOLS1rAHDAFAAEAASABQAMwAeACEAFw",
+			syncersBidderNameToKey: map[string]string{"pubmatic": "pubmatic"},
+			gdprAllowsHostCookies:  true,
+			existingSyncs:          nil,
+			expectedSyncs:          map[string]string{"pubmatic": "123"},
+			expectedStatusCode:     http.StatusOK,
+			expectedHeaders:        map[string]string{"Content-Type": "image/png", "Content-Length": "86"},
+			description:            "GPP value will be used over the one found in the deprecated GDPR consent field for redirect format",
 		},
 		{
 			uri:                    "/setuid?bidder=pubmatic&uid=123&gdpr=1&gdpr_consent=malformed",
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index cc5c7ac0..aa354ea2 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -5037,6 +5037,325 @@ func TestOverrideConfigAlternateBidderCodesWithRequestValues(t *testing.T) {
 	}
 }
 
+func TestGetAllBids(t *testing.T) {
+	noBidServer := func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) }
+	server := httptest.NewServer(http.HandlerFunc(noBidServer))
+	defer server.Close()
+
+	type testIn struct {
+		bidderRequests             []BidderRequest
+		bidAdjustments             map[string]float64
+		conversions                currency.Conversions
+		accountDebugAllowed        bool
+		globalPrivacyControlHeader string
+		headerDebugAllowed         bool
+		alternateBidderCodes       openrtb_ext.ExtAlternateBidderCodes
+		experiment                 *openrtb_ext.Experiment
+		hookExecutor               hookexecution.StageExecutor
+		pbsRequestStartTime        time.Time
+		bidAdjustmentRules         map[string][]openrtb_ext.Adjustment
+		tmaxAdjustments            *TmaxAdjustmentsPreprocessed
+		adapterMap                 map[openrtb_ext.BidderName]AdaptedBidder
+	}
+	type testResults struct {
+		adapterBids   map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid
+		adapterExtra  map[openrtb_ext.BidderName]*seatResponseExtra
+		extraRespInfo extraAuctionResponseInfo
+	}
+	testCases := []struct {
+		desc     string
+		in       testIn
+		expected testResults
+	}{
+		{
+			desc: "alternateBidderCodes-config-absent: pubmatic bidder returns bids with 'pubmatic' and 'groupm' seats",
+			in: testIn{
+				bidderRequests: []BidderRequest{
+					{
+						BidderName:     "pubmatic",
+						BidderCoreName: "pubmatic",
+						BidRequest: &openrtb2.BidRequest{
+							ID: "some-request-id",
+							Imp: []openrtb2.Imp{{
+								ID: "some-impression-id",
+							}},
+						},
+					},
+				},
+				conversions:         &currency.ConstantRates{},
+				hookExecutor:        hookexecution.EmptyHookExecutor{},
+				pbsRequestStartTime: time.Now(),
+				adapterMap: map[openrtb_ext.BidderName]AdaptedBidder{
+					openrtb_ext.BidderPubmatic: AdaptBidder(&goodSingleBidder{
+						httpRequest: &adapters.RequestData{
+							Method: "POST",
+							Uri:    server.URL,
+						},
+						bidResponse: &adapters.BidderResponse{
+							Bids: []*adapters.TypedBid{
+								{Bid: &openrtb2.Bid{ID: "1"}, Seat: "pubmatic"},
+								{Bid: &openrtb2.Bid{ID: "2"}, Seat: "groupm"},
+							},
+						},
+					}, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderPubmatic, nil, ""),
+				},
+			},
+			expected: testResults{
+				extraRespInfo: extraAuctionResponseInfo{
+					bidsFound: true,
+				},
+				adapterExtra: map[openrtb_ext.BidderName]*seatResponseExtra{
+					"pubmatic": {
+						Warnings: []openrtb_ext.ExtBidderMessage{
+							{
+								Code:    errortypes.AlternateBidderCodeWarningCode,
+								Message: `alternateBidderCodes disabled for "pubmatic", rejecting bids for "groupm"`,
+							},
+						},
+					},
+				},
+				adapterBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{
+					"pubmatic": {
+						Bids: []*entities.PbsOrtbBid{
+							{
+								Bid: &openrtb2.Bid{
+									ID: "1",
+								},
+								OriginalBidCur: "USD",
+							},
+						},
+						Currency:  "USD",
+						Seat:      "pubmatic",
+						HttpCalls: []*openrtb_ext.ExtHttpCall{},
+					},
+				},
+			},
+		},
+		{
+			desc: "alternateBidderCodes-enabled: pubmatic bidder returns bids with 'pubmatic' and 'groupm' seats",
+			in: testIn{
+				bidderRequests: []BidderRequest{
+					{
+						BidderName:     "pubmatic",
+						BidderCoreName: "pubmatic",
+						BidRequest: &openrtb2.BidRequest{
+							ID: "some-request-id",
+							Imp: []openrtb2.Imp{{
+								ID: "some-impression-id",
+							}},
+						},
+					},
+				},
+				conversions: &currency.ConstantRates{},
+				alternateBidderCodes: openrtb_ext.ExtAlternateBidderCodes{
+					Enabled: true,
+					Bidders: map[string]openrtb_ext.ExtAdapterAlternateBidderCodes{
+						"pubmatic": {
+							Enabled:            true,
+							AllowedBidderCodes: []string{"groupm"},
+						},
+					},
+				},
+				hookExecutor:        hookexecution.EmptyHookExecutor{},
+				pbsRequestStartTime: time.Now(),
+				adapterMap: map[openrtb_ext.BidderName]AdaptedBidder{
+					openrtb_ext.BidderPubmatic: AdaptBidder(&goodSingleBidder{
+						httpRequest: &adapters.RequestData{
+							Method: "POST",
+							Uri:    server.URL,
+						},
+						bidResponse: &adapters.BidderResponse{
+							Bids: []*adapters.TypedBid{
+								{Bid: &openrtb2.Bid{ID: "1"}, Seat: "pubmatic"},
+								{Bid: &openrtb2.Bid{ID: "2"}, Seat: "groupm"},
+							},
+						},
+					}, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderPubmatic, nil, ""),
+				},
+			},
+			expected: testResults{
+				extraRespInfo: extraAuctionResponseInfo{
+					bidsFound: true,
+				},
+				adapterExtra: map[openrtb_ext.BidderName]*seatResponseExtra{
+					"pubmatic": {
+						Warnings: []openrtb_ext.ExtBidderMessage{},
+					},
+				},
+				adapterBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{
+					"pubmatic": {
+						Bids: []*entities.PbsOrtbBid{
+							{
+								Bid: &openrtb2.Bid{
+									ID: "1",
+								},
+								OriginalBidCur: "USD",
+							},
+						},
+						Currency:  "USD",
+						Seat:      "pubmatic",
+						HttpCalls: []*openrtb_ext.ExtHttpCall{},
+					},
+					"groupm": {
+						Bids: []*entities.PbsOrtbBid{
+							{
+								Bid: &openrtb2.Bid{
+									ID: "2",
+								},
+								OriginalBidCur: "USD",
+							},
+						},
+						Currency:  "USD",
+						Seat:      "groupm",
+						HttpCalls: []*openrtb_ext.ExtHttpCall{},
+					},
+				},
+			},
+		},
+		{
+			desc: "alternateBidderCodes-enabled: pubmatic bidder returns bids with only 'groupm' seat",
+			in: testIn{
+				bidderRequests: []BidderRequest{
+					{
+						BidderName:     "pubmatic",
+						BidderCoreName: "pubmatic",
+						BidRequest: &openrtb2.BidRequest{
+							ID: "some-request-id",
+							Imp: []openrtb2.Imp{{
+								ID: "some-impression-id",
+							}},
+						},
+					},
+				},
+				conversions: &currency.ConstantRates{},
+				alternateBidderCodes: openrtb_ext.ExtAlternateBidderCodes{
+					Enabled: true,
+					Bidders: map[string]openrtb_ext.ExtAdapterAlternateBidderCodes{
+						"pubmatic": {
+							Enabled:            true,
+							AllowedBidderCodes: []string{"groupm"},
+						},
+					},
+				},
+				hookExecutor:        hookexecution.EmptyHookExecutor{},
+				pbsRequestStartTime: time.Now(),
+				adapterMap: map[openrtb_ext.BidderName]AdaptedBidder{
+					openrtb_ext.BidderPubmatic: AdaptBidder(&goodSingleBidder{
+						httpRequest: &adapters.RequestData{
+							Method: "POST",
+							Uri:    server.URL,
+						},
+						bidResponse: &adapters.BidderResponse{
+							Bids: []*adapters.TypedBid{
+								{Bid: &openrtb2.Bid{ID: "2"}, Seat: "groupm"},
+							},
+						},
+					}, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderPubmatic, nil, ""),
+				},
+			},
+			expected: testResults{
+				extraRespInfo: extraAuctionResponseInfo{
+					bidsFound: true,
+				},
+				adapterExtra: map[openrtb_ext.BidderName]*seatResponseExtra{
+					"pubmatic": {
+						Warnings: []openrtb_ext.ExtBidderMessage{},
+					},
+				},
+				adapterBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{
+					"groupm": {
+						Bids: []*entities.PbsOrtbBid{
+							{
+								Bid: &openrtb2.Bid{
+									ID: "2",
+								},
+								OriginalBidCur: "USD",
+							},
+						},
+						Currency:  "USD",
+						Seat:      "groupm",
+						HttpCalls: []*openrtb_ext.ExtHttpCall{},
+					},
+				},
+			},
+		},
+		{
+			desc: "bidder responded with empty bid",
+			in: testIn{
+				bidderRequests: []BidderRequest{
+					{
+						BidderName:     "pubmatic",
+						BidderCoreName: "pubmatic",
+						BidRequest: &openrtb2.BidRequest{
+							ID: "some-request-id",
+							Imp: []openrtb2.Imp{{
+								ID: "some-impression-id",
+							}},
+						},
+					},
+				},
+				conversions: &currency.ConstantRates{},
+				alternateBidderCodes: openrtb_ext.ExtAlternateBidderCodes{
+					Enabled: true,
+					Bidders: map[string]openrtb_ext.ExtAdapterAlternateBidderCodes{
+						"pubmatic": {
+							Enabled:            true,
+							AllowedBidderCodes: []string{"groupm"},
+						},
+					},
+				},
+				hookExecutor:        hookexecution.EmptyHookExecutor{},
+				pbsRequestStartTime: time.Now(),
+				adapterMap: map[openrtb_ext.BidderName]AdaptedBidder{
+					openrtb_ext.BidderPubmatic: AdaptBidder(&goodSingleBidder{
+						httpRequest: &adapters.RequestData{
+							Method: "POST",
+							Uri:    server.URL,
+						},
+						bidResponse: &adapters.BidderResponse{},
+					}, server.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderPubmatic, nil, ""),
+				},
+			},
+			expected: testResults{
+				extraRespInfo: extraAuctionResponseInfo{
+					bidsFound: false,
+				},
+				adapterExtra: map[openrtb_ext.BidderName]*seatResponseExtra{
+					"pubmatic": {
+						Warnings: []openrtb_ext.ExtBidderMessage{},
+					},
+				},
+				adapterBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{},
+			},
+		},
+	}
+	for _, test := range testCases {
+		t.Run(test.desc, func(t *testing.T) {
+			e := exchange{
+				cache: &wellBehavedCache{},
+				me:    &metricsConf.NilMetricsEngine{},
+				gdprPermsBuilder: fakePermissionsBuilder{
+					permissions: &permissionsMock{
+						allowAllBidders: true,
+					},
+				}.Builder,
+				adapterMap: test.in.adapterMap,
+			}
+
+			adapterBids, adapterExtra, extraRespInfo := e.getAllBids(context.Background(), test.in.bidderRequests, test.in.bidAdjustments,
+				test.in.conversions, test.in.accountDebugAllowed, test.in.globalPrivacyControlHeader, test.in.headerDebugAllowed, test.in.alternateBidderCodes, test.in.experiment,
+				test.in.hookExecutor, test.in.pbsRequestStartTime, test.in.bidAdjustmentRules, test.in.tmaxAdjustments)
+
+			assert.Equalf(t, test.expected.extraRespInfo.bidsFound, extraRespInfo.bidsFound, "extraRespInfo.bidsFound mismatch")
+			assert.Equalf(t, test.expected.adapterBids, adapterBids, "adapterBids mismatch")
+			assert.Equalf(t, len(test.expected.adapterExtra), len(adapterExtra), "adapterExtra length mismatch")
+			for adapter, extra := range test.expected.adapterExtra {
+				assert.Equalf(t, extra.Warnings, adapterExtra[adapter].Warnings, "adapterExtra.Warnings mismatch for adapter [%s]", adapter)
+			}
+		})
+	}
+}
+
 type MockSigner struct {
 	data string
 }