Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PG targeting update. #1747

Merged
merged 5 commits into from
Feb 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,7 @@ public String lookupString(TargetingCategory category) {
case siteFirstPartyData:
return getSiteFirstPartyData(category, RequestContext::nodeToString);
default:
throw new TargetingSyntaxException(
String.format("Unexpected category for fetching string value for: %s", type));
return null;
}
}

Expand All @@ -124,6 +123,8 @@ public Integer lookupInteger(TargetingCategory category) {
return getIntegerFromUserExt("time.userdow");
case hour:
return getIntegerFromUserExt("time.userhour");
case deviceGeoExt:
return getValueFrom(geoExt, category, RequestContext::nodeToInteger);
case bidderParam:
return impBidderAttributeReader.readFromExt(imp, category, RequestContext::nodeToInteger);
case userFirstPartyData:
Expand All @@ -132,8 +133,7 @@ public Integer lookupInteger(TargetingCategory category) {
case siteFirstPartyData:
return getSiteFirstPartyData(category, RequestContext::nodeToInteger);
default:
throw new TargetingSyntaxException(
String.format("Unexpected category for fetching integer value for: %s", type));
return null;
}
}

Expand All @@ -152,8 +152,7 @@ public List<String> lookupStrings(TargetingCategory category) {
case siteFirstPartyData:
return getSiteFirstPartyData(category, RequestContext::nodeToListOfStrings);
default:
throw new TargetingSyntaxException(
String.format("Unexpected category for fetching string values for: %s", type));
return null;
}
}

Expand All @@ -168,8 +167,7 @@ public List<Integer> lookupIntegers(TargetingCategory category) {
case siteFirstPartyData:
return getSiteFirstPartyData(category, RequestContext::nodeToListOfIntegers);
default:
throw new TargetingSyntaxException(
String.format("Unexpected category for fetching integer values for: %s", type));
return null;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import lombok.EqualsAndHashCode;
import org.prebid.server.deals.targeting.RequestContext;
import org.prebid.server.deals.targeting.syntax.TargetingCategory;
import org.prebid.server.util.ObjectUtil;

import java.util.List;
import java.util.stream.Collectors;
Expand All @@ -16,11 +17,18 @@ public InStrings(TargetingCategory category, List<String> values) {

@Override
public String lookupActualValue(RequestContext context) {
final String actualValue = context.lookupString(category);
final String actualValue = ObjectUtil.firstNonNull(
() -> context.lookupString(category),
() -> lookupIntegerAsString(context));

return actualValue != null ? actualValue.toLowerCase() : null;
}

private String lookupIntegerAsString(RequestContext context) {
final Integer actualValue = context.lookupInteger(category);
return actualValue != null ? actualValue.toString() : null;
}

private static List<String> toLowerCase(List<String> values) {
return values.stream().map(String::toLowerCase).collect(Collectors.toList());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ enum TargetingType {
DEVICE_TYPE("device.ext.deviceatlas.type"),
DEVICE_OS("device.ext.deviceatlas.osfamily"),
DEVICE_REGION("device.geo.ext.netacuity.region"),
DEVICE_METRO("device.geo.ext.netacuity.metro"),
PAGE_POSITION("pos"),
LOCATION("geo.distance"),
BIDP("bidp."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ class Geo {
String city
String zip
Integer utcoffset
GeoExt ext
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.prebid.server.functional.model.request.auction

import com.fasterxml.jackson.annotation.JsonProperty
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString

@EqualsAndHashCode
@ToString(includeNames = true, ignoreNulls = true)
class GeoExt {

@JsonProperty("netacuity")
GeoExtNetAcuity netAcuity
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.prebid.server.functional.model.request.auction

class GeoExtNetAcuity {

String country
Object region
Object metro
String city
String zip
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRe
import org.prebid.server.functional.model.response.auction.BidResponse
import org.prebid.server.functional.service.PrebidServerService
import org.prebid.server.functional.testcontainers.scaffolding.CurrencyConversion
import org.prebid.server.functional.util.PBSUtils
import spock.lang.Shared

import static org.prebid.server.functional.model.bidder.BidderName.GENERIC
Expand Down Expand Up @@ -47,7 +48,9 @@ class CurrencySpec extends BasePgSpec {
def nonDefaultCurrencyLineItemIds = nonDefaultCurrencyLineItems.collect { it.lineItemId }

and: "Line items are fetched by PBS"
def initialPlansRequestCount = generalPlanner.recordedPlansRequestCount
pgCurrencyConverterPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.updateLineItemsRequest)
PBSUtils.waitUntil { generalPlanner.recordedPlansRequestCount == initialPlansRequestCount + 1 }

when: "Auction is requested"
def auctionResponse = pgCurrencyConverterPbsService.sendAuctionRequest(bidRequest)
Expand All @@ -72,7 +75,9 @@ class CurrencySpec extends BasePgSpec {
def defaultCurrencyLineItemId = defaultCurrencyLineItem.collect { it.lineItemId }

and: "Line items are fetched by PBS"
def initialPlansRequestCount = generalPlanner.recordedPlansRequestCount
pgCurrencyConverterPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.updateLineItemsRequest)
PBSUtils.waitUntil { generalPlanner.recordedPlansRequestCount == initialPlansRequestCount + 1 }

when: "Auction is requested"
def auctionResponse = pgCurrencyConverterPbsService.sendAuctionRequest(bidRequest)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import org.prebid.server.functional.model.request.auction.AppExtData
import org.prebid.server.functional.model.request.auction.Banner
import org.prebid.server.functional.model.request.auction.BidRequest
import org.prebid.server.functional.model.request.auction.Bidder
import org.prebid.server.functional.model.request.auction.Device
import org.prebid.server.functional.model.request.auction.Geo
import org.prebid.server.functional.model.request.auction.GeoExt
import org.prebid.server.functional.model.request.auction.GeoExtNetAcuity
import org.prebid.server.functional.model.request.auction.Imp
import org.prebid.server.functional.model.request.auction.ImpExt
import org.prebid.server.functional.model.request.auction.ImpExtContext
Expand Down Expand Up @@ -48,6 +52,8 @@ import static org.prebid.server.functional.model.deals.lineitem.targeting.Target
import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.AD_UNIT_SIZE
import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.APP_BUNDLE
import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.BIDP_ACCOUNT_ID
import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.DEVICE_METRO
import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.DEVICE_REGION
import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.DOW
import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.HOUR
import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.INVALID
Expand Down Expand Up @@ -680,4 +686,36 @@ class TargetingSpec extends BasePgSpec {
.build(),
new Targeting.Builder(NOT).buildNotBooleanOperatorTargeting(AD_UNIT_SIZE, INTERSECTS, [LineItemSize.defaultLineItemSize])]
}

def "PBS should support line item targeting by device geo region, metro when request region, metro as int or str value are given"() {
given: "Bid request"
def bidRequest = BidRequest.defaultBidRequest.tap {
device = new Device(geo: new Geo(ext: new GeoExt(netAcuity: new GeoExtNetAcuity(region: requestValue,
metro: requestValue))))
}

and: "Planner response"
def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap {
lineItems[0].targeting = Targeting.defaultTargetingBuilder
.addTargeting(DEVICE_REGION, IN, [lineItemValue])
.addTargeting(DEVICE_METRO, IN, [lineItemValue])
.build()
}
generalPlanner.initPlansResponse(plansResponse)

and: "Line items are fetched by PBS"
updateLineItemsAndWait()

when: "Auction is happened"
def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest)

then: "PBS had PG auction"
assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size()
assert auctionResponse.ext.debug.pgmetrics.matchedWholeTargeting.first() == plansResponse.lineItems.first().lineItemId

where:
requestValue | lineItemValue
stringTargetingValue | stringTargetingValue
integerTargetingValue | integerTargetingValue as String
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -597,22 +597,6 @@ public void lookupStringShouldReturnSiteFirstPartyDataFromAppExt() {
assertThat(context.lookupString(category)).isEqualTo("hockey");
}

@Test
public void lookupStringShouldThrowExceptionWhenUnexpectedCategory() {
// given
final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.location);
final RequestContext context = new RequestContext(
request(identity()),
imp(identity()),
txnLog,
jacksonMapper);

// when and then
assertThatThrownBy(() -> context.lookupString(category))
.isInstanceOf(TargetingSyntaxException.class)
.hasMessage("Unexpected category for fetching string value for: location");
}

@Test
public void lookupIntegerShouldReturnDowFromUserExt() {
// given
Expand Down Expand Up @@ -717,20 +701,6 @@ public void lookupIntegerShouldReturnSiteFirstPartyData() {
assertThat(context.lookupInteger(category)).isEqualTo(123);
}

@Test
public void lookupIntegerShouldThrowExceptionWhenUnexpectedCategory() {
// given
final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.domain);
final RequestContext context = new RequestContext(request(identity()), imp(identity()),
txnLog,
jacksonMapper);

// when and then
assertThatThrownBy(() -> context.lookupInteger(category))
.isInstanceOf(TargetingSyntaxException.class)
.hasMessage("Unexpected category for fetching integer value for: domain");
}

@Test
public void lookupStringsShouldReturnMediaTypeBannerAndVideo() {
// given
Expand Down Expand Up @@ -968,22 +938,6 @@ public void lookupStringsShouldReturnEmptyListWhenUserIsMissing() {
assertThat(context.lookupStrings(category)).isEmpty();
}

@Test
public void lookupStringsShouldThrowExceptionWhenUnexpectedCategory() {
// given
final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.domain);
final RequestContext context = new RequestContext(
request(identity()),
imp(identity()),
txnLog,
jacksonMapper);

// when and then
assertThatThrownBy(() -> context.lookupStrings(category))
.isInstanceOf(TargetingSyntaxException.class)
.hasMessage("Unexpected category for fetching string values for: domain");
}

@Test
public void lookupIntegersShouldReturnBidderParam() {
// given
Expand Down Expand Up @@ -1089,18 +1043,6 @@ public void lookupIntegersShouldReturnSiteFirstPartyData() {
assertThat(context.lookupIntegers(category)).containsOnly(123, 456);
}

@Test
public void lookupIntegersShouldThrowExceptionWhenUnexpectedCategory() {
// given
final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.domain);
final RequestContext context = new RequestContext(request(identity()), imp(identity()), txnLog, jacksonMapper);

// when and then
assertThatThrownBy(() -> context.lookupIntegers(category))
.isInstanceOf(TargetingSyntaxException.class)
.hasMessage("Unexpected category for fetching integer values for: domain");
}

@Test
public void lookupSizesShouldReturnSizes() {
// given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class InStringsTest {
public void setUp() {
// given
category = new TargetingCategory(TargetingCategory.Type.referrer);
expression = new InStrings(category, asList("Munich", "Berlin", "Stuttgart"));
expression = new InStrings(category, asList("Munich", "Berlin", "Stuttgart", "123"));
}

@Test
Expand Down Expand Up @@ -70,4 +70,13 @@ public void matchesShouldReturnFalseWhenActualValueIsMissing() {
// when and then
assertThat(expression.matches(context)).isFalse();
}

@Test
public void matchesShouldReturnTrueWhenActualValueIsInteger() {
// given
willReturn(123).given(context).lookupInteger(any());

// when and then
assertThat(expression.matches(context)).isTrue();
}
}