@@ -32,6 +32,7 @@ import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST
3232import static org.prebid.server.functional.model.Currency.EUR
3333import static org.prebid.server.functional.model.Currency.GBP
3434import static org.prebid.server.functional.model.Currency.USD
35+ import static org.prebid.server.functional.model.bidder.BidderName.ACUITYADS
3536import static org.prebid.server.functional.model.bidder.BidderName.ALIAS
3637import static org.prebid.server.functional.model.bidder.BidderName.AMX
3738import static org.prebid.server.functional.model.bidder.BidderName.APPNEXUS
@@ -79,6 +80,11 @@ class BidAdjustmentSpec extends BaseSpec {
7980 " adapters.amx.endpoint" : " $networkServiceContainer . rootUri /auction" . toString()]
8081 private static final PrebidServerService pbsService = pbsServiceFactory. getService(externalCurrencyConverterConfig + AMX_CONFIG )
8182
83+ @Override
84+ def cleanupSpec () {
85+ pbsServiceFactory. removeContainer(externalCurrencyConverterConfig + AMX_CONFIG )
86+ }
87+
8288 def " PBS should adjust bid price for matching bidder when request has per-bidder bid adjustment factors" () {
8389 given : " Default bid request with bid adjustment"
8490 def bidRequest = BidRequest . getDefaultBidRequest(SITE ). tap {
@@ -1193,6 +1199,325 @@ class BidAdjustmentSpec extends BaseSpec {
11931199 bidAdjustmentFactor << [0.9 , 1.1 ]
11941200 }
11951201
1202+ def " PBS shouldn't adjust bid price when bid adjustment rule doesn't match with bidder code" () {
1203+ given : " Bid request with ext.prebid.bidAdjustments and ext.prebid.alternateBidderCode"
1204+ def exactRulePrice = PBSUtils . randomPrice
1205+ def currency = USD
1206+ def adjustmentRule = new AdjustmentRule (adjustmentType : STATIC , value : exactRulePrice, currency : currency)
1207+ def bidAdjustmentRule = new BidAdjustmentRule ((bidAdjustmentRuleBidder): [(WILDCARD ): [adjustmentRule]])
1208+ def bidRequest = BidRequest . defaultBidRequest. tap {
1209+ cur = [currency]
1210+ imp[0 ]. ext. prebid. bidder. generic = null
1211+ imp[0 ]. ext. prebid. bidder. amx = new Amx ()
1212+ ext. prebid. tap {
1213+ bidAdjustments = new BidAdjustment (mediaType : [(BANNER ): bidAdjustmentRule])
1214+ alternateBidderCodes = new AlternateBidderCodes (). tap {
1215+ enabled = true
1216+ bidders = [(AMX ): new BidderConfig (enabled : true , allowedBidderCodes : [AMX ])]
1217+ }
1218+ }
1219+ }
1220+
1221+ and : " Default bid response with price and bidder code"
1222+ def originalPrice = PBSUtils . randomPrice
1223+ def bidResponse = BidResponse . getDefaultBidResponse(bidRequest, AMX ). tap {
1224+ cur = currency
1225+ seatbid. first. bid. first. price = originalPrice
1226+ seatbid. first. bid. first. ext = new BidExt (bidderCode : ACUITYADS )
1227+ }
1228+ bidder. setResponse(bidRequest. id, bidResponse)
1229+
1230+ when : " PBS processes auction request"
1231+ def response = pbsService. sendAuctionRequest(bidRequest)
1232+
1233+ then : " Final bid price should be adjusted according to exact rule"
1234+ assert response. seatbid. first. bid. first. price == originalPrice
1235+ assert response. cur == bidResponse. cur
1236+
1237+ and : " Original bid price and currency should be presented in bid.ext"
1238+ verifyAll(response. seatbid. first. bid. first. ext) {
1239+ origbidcpm == originalPrice
1240+ origbidcur == bidResponse. cur
1241+ }
1242+
1243+ and : " Bidder request should contain currency from request"
1244+ def bidderRequest = bidder. getBidderRequest(bidRequest. id)
1245+ assert bidderRequest. cur == [currency]
1246+
1247+ and : " Response should contain adapter code"
1248+ assert response. seatbid. bid. ext. prebid. meta. adapterCode. flatten() == [AMX ]
1249+
1250+ and : " Response should contain seatbid.seat"
1251+ assert response. seatbid[0 ]. seat == ACUITYADS
1252+
1253+ where :
1254+ bidAdjustmentRuleBidder << [" alias" , " aliasUpperCase" , " aliasCamelCase" ]
1255+ }
1256+
1257+ def " PBS should adjust bid price when two bid adjustment rules are compatible" () {
1258+ given : " Bid request with ext.prebid.bidAdjustments and ext.prebid.alternateBidderCode"
1259+ def exactRulePrice = PBSUtils . randomPrice
1260+ def currency = USD
1261+ def dealId = PBSUtils . randomString
1262+ def adjustmentRule = new AdjustmentRule (adjustmentType : STATIC , value : exactRulePrice, currency : currency)
1263+ def firstBidAdjustmentRule = new BidAdjustmentRule (amx : [(dealId): [adjustmentRule]])
1264+ def secondBidAdjustmentRule = new BidAdjustmentRule (amx : [(WILDCARD ): [adjustmentRule]])
1265+ def bidRequest = BidRequest . defaultBidRequest. tap {
1266+ cur = [currency]
1267+ imp[0 ]. ext. prebid. bidder. generic = null
1268+ imp[0 ]. ext. prebid. bidder. amx = new Amx ()
1269+ ext. prebid. tap {
1270+ bidAdjustments = new BidAdjustment (mediaType : [(BANNER ): firstBidAdjustmentRule,
1271+ (ANY ) : secondBidAdjustmentRule])
1272+ alternateBidderCodes = new AlternateBidderCodes (). tap {
1273+ enabled = true
1274+ bidders = [(AMX ): new BidderConfig (enabled : true , allowedBidderCodes : [AMX ])]
1275+ }
1276+ }
1277+ }
1278+
1279+ and : " Default bid response with price and bidder code and dealId"
1280+ def originalPrice = PBSUtils . randomPrice
1281+ def bidResponse = BidResponse . getDefaultBidResponse(bidRequest, AMX ). tap {
1282+ cur = currency
1283+ seatbid. first. bid. first. price = originalPrice
1284+ seatbid. first. bid. first. ext = new BidExt (bidderCode : AMX )
1285+ seatbid. first. bid. first. dealid = dealId
1286+ }
1287+ bidder. setResponse(bidRequest. id, bidResponse)
1288+
1289+ when : " PBS processes auction request"
1290+ def response = pbsService. sendAuctionRequest(bidRequest)
1291+
1292+ then : " Final bid price should be adjusted according to exact rule"
1293+ assert response. seatbid. first. bid. first. price == getAdjustedPrice(originalPrice, exactRulePrice, STATIC )
1294+ assert response. cur == bidResponse. cur
1295+
1296+ and : " Original bid price and currency should be presented in bid.ext"
1297+ verifyAll(response. seatbid. first. bid. first. ext) {
1298+ origbidcpm == originalPrice
1299+ origbidcur == bidResponse. cur
1300+ }
1301+
1302+ and : " Bidder request should contain currency from request"
1303+ def bidderRequest = bidder. getBidderRequest(bidRequest. id)
1304+ assert bidderRequest. cur == [currency]
1305+
1306+ and : " Response should contain adapter code"
1307+ assert response. seatbid. bid. ext. prebid. meta. adapterCode. flatten() == [AMX ]
1308+
1309+ and : " Response should contain seatbid.seat"
1310+ assert response. seatbid[0 ]. seat == AMX
1311+ }
1312+
1313+ def " PBS should adjust bid price when bid adjustment bidder and bidder code different" () {
1314+ given : " Bid request with ext.prebid.bidAdjustments and ext.prebid.alternateBidderCode"
1315+ def exactRulePrice = PBSUtils . randomPrice
1316+ def currency = USD
1317+ def adjustmentRule = new AdjustmentRule (adjustmentType : STATIC , value : exactRulePrice, currency : currency)
1318+ def bidAdjustmentRule = new BidAdjustmentRule ((bidAdjustmentRuleBidder): [(WILDCARD ): [adjustmentRule]])
1319+ def bidRequest = BidRequest . defaultBidRequest. tap {
1320+ cur = [currency]
1321+ imp[0 ]. ext. prebid. bidder. generic = null
1322+ imp[0 ]. ext. prebid. bidder. amx = new Amx ()
1323+ ext. prebid. tap {
1324+ bidAdjustments = new BidAdjustment (mediaType : [(BANNER ): bidAdjustmentRule])
1325+ alternateBidderCodes = new AlternateBidderCodes (). tap {
1326+ enabled = true
1327+ bidders = [(AMX ): new BidderConfig (enabled : true , allowedBidderCodes : [AMX ])]
1328+ }
1329+ }
1330+ }
1331+
1332+ and : " Default bid response with price and bidder code"
1333+ def originalPrice = PBSUtils . randomPrice
1334+ def bidResponse = BidResponse . getDefaultBidResponse(bidRequest, AMX ). tap {
1335+ cur = currency
1336+ seatbid. first. bid. first. price = originalPrice
1337+ seatbid. first. bid. first. ext = new BidExt (bidderCode : ALIAS )
1338+ }
1339+ bidder. setResponse(bidRequest. id, bidResponse)
1340+
1341+ when : " PBS processes auction request"
1342+ def response = pbsService. sendAuctionRequest(bidRequest)
1343+
1344+ then : " Final bid price should be adjusted according to exact rule"
1345+ assert response. seatbid. first. bid. first. price == getAdjustedPrice(originalPrice, exactRulePrice, STATIC )
1346+ assert response. cur == bidResponse. cur
1347+
1348+ and : " Original bid price and currency should be presented in bid.ext"
1349+ verifyAll(response. seatbid. first. bid. first. ext) {
1350+ origbidcpm == originalPrice
1351+ origbidcur == bidResponse. cur
1352+ }
1353+
1354+ and : " Bidder request should contain currency from request"
1355+ def bidderRequest = bidder. getBidderRequest(bidRequest. id)
1356+ assert bidderRequest. cur == [currency]
1357+
1358+ and : " Response should contain adapter code"
1359+ assert response. seatbid. bid. ext. prebid. meta. adapterCode. flatten() == [AMX ]
1360+
1361+ and : " Response should contain seatbid.seat"
1362+ assert response. seatbid[0 ]. seat == ALIAS
1363+
1364+ where :
1365+ bidAdjustmentRuleBidder << [" alias" , " aliasUpperCase" , " aliasCamelCase" ]
1366+ }
1367+
1368+ def " PBS should adjust bid price when bid adjustment bidder and bidder code same as requested" () {
1369+ given : " Bid request with ext.prebid.bidAdjustments and ext.prebid.alternateBidderCode"
1370+ def exactRulePrice = PBSUtils . randomPrice
1371+ def currency = USD
1372+ def exactRule = new BidAdjustmentRule (amx : [(WILDCARD ): [new AdjustmentRule (adjustmentType : STATIC , value : exactRulePrice, currency : currency)]])
1373+ def bidRequest = BidRequest . defaultBidRequest. tap {
1374+ cur = [currency]
1375+ imp[0 ]. ext. prebid. bidder. generic = null
1376+ imp[0 ]. ext. prebid. bidder. amx = new Amx ()
1377+ ext. prebid. tap {
1378+ bidAdjustments = new BidAdjustment (mediaType : [(BANNER ): exactRule])
1379+ alternateBidderCodes = new AlternateBidderCodes (). tap {
1380+ enabled = true
1381+ bidders = [(AMX ): new BidderConfig (enabled : true , allowedBidderCodes : [AMX ])]
1382+ }
1383+ }
1384+ }
1385+
1386+ and : " Default bid response with price and bidder code"
1387+ def originalPrice = PBSUtils . randomPrice
1388+ def bidResponse = BidResponse . getDefaultBidResponse(bidRequest, AMX ). tap {
1389+ cur = currency
1390+ seatbid. first. bid. first. price = originalPrice
1391+ seatbid. first. bid. first. ext = new BidExt (bidderCode : AMX )
1392+ }
1393+ bidder. setResponse(bidRequest. id, bidResponse)
1394+
1395+ when : " PBS processes auction request"
1396+ def response = pbsService. sendAuctionRequest(bidRequest)
1397+
1398+ then : " Final bid price should be adjusted according to exact rule"
1399+ assert response. seatbid. first. bid. first. price == getAdjustedPrice(originalPrice, exactRulePrice, STATIC )
1400+ assert response. cur == bidResponse. cur
1401+
1402+ and : " Original bid price and currency should be presented in bid.ext"
1403+ verifyAll(response. seatbid. first. bid. first. ext) {
1404+ origbidcpm == originalPrice
1405+ origbidcur == bidResponse. cur
1406+ }
1407+
1408+ and : " Bidder request should contain currency from request"
1409+ def bidderRequest = bidder. getBidderRequest(bidRequest. id)
1410+ assert bidderRequest. cur == [currency]
1411+
1412+ and : " Response should contain adapter code"
1413+ assert response. seatbid. bid. ext. prebid. meta. adapterCode. flatten() == [AMX ]
1414+
1415+ and : " Response should contain seatbid.seat"
1416+ assert response. seatbid[0 ]. seat == AMX
1417+ }
1418+
1419+ def " PBS should adjust bid price when bid adjustment bidder is the same as bidder code" () {
1420+ given : " Bid request with ext.prebid.bidAdjustments and ext.prebid.alternateBidderCode"
1421+ def exactRulePrice = PBSUtils . randomPrice
1422+ def currency = USD
1423+ def exactRule = new BidAdjustmentRule (alias : [(WILDCARD ): [new AdjustmentRule (adjustmentType : STATIC , value : exactRulePrice, currency : currency)]])
1424+ def bidRequest = BidRequest . defaultBidRequest. tap {
1425+ cur = [currency]
1426+ imp[0 ]. ext. prebid. bidder. generic = null
1427+ imp[0 ]. ext. prebid. bidder. amx = new Amx ()
1428+ ext. prebid. tap {
1429+ bidAdjustments = new BidAdjustment (mediaType : [(BANNER ): exactRule])
1430+ alternateBidderCodes = new AlternateBidderCodes (). tap {
1431+ enabled = true
1432+ bidders = [(AMX ): new BidderConfig (enabled : true , allowedBidderCodes : [AMX ])]
1433+ }
1434+ }
1435+ }
1436+
1437+ and : " Default bid response with price and bidder code"
1438+ def originalPrice = PBSUtils . randomPrice
1439+ def bidResponse = BidResponse . getDefaultBidResponse(bidRequest, AMX ). tap {
1440+ cur = currency
1441+ seatbid. first. bid. first. price = originalPrice
1442+ seatbid. first. bid. first. ext = new BidExt (bidderCode : ALIAS )
1443+ }
1444+ bidder. setResponse(bidRequest. id, bidResponse)
1445+
1446+ when : " PBS processes auction request"
1447+ def response = pbsService. sendAuctionRequest(bidRequest)
1448+
1449+ then : " Final bid price should be adjusted according to exact rule"
1450+ assert response. seatbid. first. bid. first. price == getAdjustedPrice(originalPrice, exactRulePrice, STATIC )
1451+ assert response. cur == bidResponse. cur
1452+
1453+ and : " Original bid price and currency should be presented in bid.ext"
1454+ verifyAll(response. seatbid. first. bid. first. ext) {
1455+ origbidcpm == originalPrice
1456+ origbidcur == bidResponse. cur
1457+ }
1458+
1459+ and : " Bidder request should contain currency from request"
1460+ def bidderRequest = bidder. getBidderRequest(bidRequest. id)
1461+ assert bidderRequest. cur == [currency]
1462+
1463+ and : " Response should contain adapter code"
1464+ assert response. seatbid. bid. ext. prebid. meta. adapterCode. flatten() == [AMX ]
1465+
1466+ and : " Response should contain seatbid.seat"
1467+ assert response. seatbid[0 ]. seat == ALIAS
1468+ }
1469+
1470+ def " PBS should adjust bid price when bid adjustment wildcard bidder and bidder code specified" () {
1471+ given : " Bid request with ext.prebid.bidAdjustments and ext.prebid.alternateBidderCode"
1472+ def exactRulePrice = PBSUtils . randomPrice
1473+ def currency = USD
1474+ def exactRule = new BidAdjustmentRule (wildcardBidder : [(WILDCARD ): [new AdjustmentRule (adjustmentType : STATIC , value : exactRulePrice, currency : currency)]])
1475+ def bidRequest = BidRequest . defaultBidRequest. tap {
1476+ cur = [currency]
1477+ imp[0 ]. ext. prebid. bidder. generic = null
1478+ imp[0 ]. ext. prebid. bidder. amx = new Amx ()
1479+ ext. prebid. tap {
1480+ bidAdjustments = new BidAdjustment (mediaType : [(BANNER ): exactRule])
1481+ alternateBidderCodes = new AlternateBidderCodes (). tap {
1482+ enabled = true
1483+ bidders = [(AMX ): new BidderConfig (enabled : true , allowedBidderCodes : [AMX ])]
1484+ }
1485+ }
1486+ }
1487+
1488+ and : " Default bid response with price and bidder code"
1489+ def originalPrice = PBSUtils . randomPrice
1490+ def bidResponse = BidResponse . getDefaultBidResponse(bidRequest, AMX ). tap {
1491+ cur = currency
1492+ seatbid. first. bid. first. price = originalPrice
1493+ seatbid. first. bid. first. ext = new BidExt (bidderCode : ALIAS )
1494+ }
1495+ bidder. setResponse(bidRequest. id, bidResponse)
1496+
1497+ when : " PBS processes auction request"
1498+ def response = pbsService. sendAuctionRequest(bidRequest)
1499+
1500+ then : " Final bid price should be adjusted according to exact rule"
1501+ assert response. seatbid. first. bid. first. price == getAdjustedPrice(originalPrice, exactRulePrice, STATIC )
1502+ assert response. cur == bidResponse. cur
1503+
1504+ and : " Original bid price and currency should be presented in bid.ext"
1505+ verifyAll(response. seatbid. first. bid. first. ext) {
1506+ origbidcpm == originalPrice
1507+ origbidcur == bidResponse. cur
1508+ }
1509+
1510+ and : " Bidder request should contain currency from request"
1511+ def bidderRequest = bidder. getBidderRequest(bidRequest. id)
1512+ assert bidderRequest. cur == [currency]
1513+
1514+ and : " Response should contain adapter code"
1515+ assert response. seatbid. bid. ext. prebid. meta. adapterCode. flatten() == [AMX ]
1516+
1517+ and : " Response should contain seatbid.seat"
1518+ assert response. seatbid[0 ]. seat == ALIAS
1519+ }
1520+
11961521 private static Map<String , String > getExternalCurrencyConverterConfig () {
11971522 [" auction.ad-server-currency" : DEFAULT_CURRENCY as String ,
11981523 " currency-converter.external-rates.enabled" : " true" ,
0 commit comments