Skip to content

Commit

Permalink
Response correction: Fix VAST matching (prebid#3493)
Browse files Browse the repository at this point in the history
  • Loading branch information
And1sS authored and sergseven committed Dec 23, 2024
1 parent 80111c5 commit 45f2a27
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;

Expand All @@ -29,7 +30,7 @@ public class AppVideoHtmlCorrection implements Correction {
private static final ConditionalLogger conditionalLogger = new ConditionalLogger(
LoggerFactory.getLogger(AppVideoHtmlCorrection.class));

private static final Pattern VAST_XML_PATTERN = Pattern.compile("<\\w*VAST\\w+", Pattern.CASE_INSENSITIVE);
private static final Pattern VAST_XML_PATTERN = Pattern.compile(".*<\\s*VAST\\s+.*", Pattern.CASE_INSENSITIVE);
private static final TypeReference<ExtPrebid<ExtBidPrebid, ObjectNode>> EXT_BID_PREBID_TYPE_REFERENCE =
new TypeReference<>() {
};
Expand All @@ -42,7 +43,7 @@ public class AppVideoHtmlCorrection implements Correction {
private final double logSamplingRate;

public AppVideoHtmlCorrection(ObjectMapper mapper, double logSamplingRate) {
this.mapper = mapper;
this.mapper = Objects.requireNonNull(mapper);
this.logSamplingRate = logSamplingRate;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public void applyShouldNotChangeBidResponsesWhenBidIsVideoAndHasVastXmlInAdm() {
final List<BidderResponse> givenResponses = List.of(
BidderResponse.of("bidderA", null, 100),
BidderResponse.of("bidderB", BidderSeatBid.of(
List.of(givenBid("<anythingvAstanything", BidType.video))), 100));
List.of(givenBid("< \tVAST anything>", BidType.video))), 100));

// when
final List<BidderResponse> actual = target.apply(givenConfig, givenResponses);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class ResponseCorrectionSpec extends ModuleBaseSpec {
"adapters.generic.modifying-vast-xml-allowed": "false"] +
responseCorrectionConfig)

private final static int OPTIMAL_MAX_LENGTH = 20

def "PBS shouldn't modify response when in account correction module disabled"() {
given: "Start up time"
def start = Instant.now()
Expand Down Expand Up @@ -326,7 +328,7 @@ class ResponseCorrectionSpec extends ModuleBaseSpec {

and: "Set bidder response"
def bidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap {
seatbid[0].bid[0].setAdm(PBSUtils.getRandomCase("<${PBSUtils.randomString}VAST${PBSUtils.randomString}"))
seatbid[0].bid[0].setAdm(PBSUtils.getRandomCase(admValue))
}
bidder.setResponse(bidRequest.id, bidResponse)

Expand All @@ -352,6 +354,69 @@ class ResponseCorrectionSpec extends ModuleBaseSpec {

and: "Response shouldn't contain warnings"
assert !response.ext.warnings

where:
admValue << [
"${PBSUtils.randomString}<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST ${PBSUtils.randomString}",
"${PBSUtils.randomString}<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST ${PBSUtils.randomString}>",
"${PBSUtils.randomString}${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST ${PBSUtils.randomString}>",
"<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST${' ' * PBSUtils.getRandomNumber(1, OPTIMAL_MAX_LENGTH)}",
"<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST${' ' * PBSUtils.getRandomNumber(1, OPTIMAL_MAX_LENGTH)}>",
"<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST${' ' * PBSUtils.getRandomNumber(1, OPTIMAL_MAX_LENGTH)}${PBSUtils.randomString}>"
]
}

def "PBS should modify response when requested video impression respond with invalid adm VAST keyword"() {
given: "Start up time"
def start = Instant.now()

and: "Default bid request with APP and Video imp"
def bidRequest = getDefaultVideoRequest(APP)

and: "Set bidder response"
def bidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap {
seatbid[0].bid[0].setAdm(PBSUtils.getRandomCase(admValue))
}
bidder.setResponse(bidRequest.id, bidResponse)

and: "Save account with enabled response correction module"
def accountWithResponseCorrectionModule = accountConfigWithResponseCorrectionModule(bidRequest)
accountDao.save(accountWithResponseCorrectionModule)

when: "PBS processes auction request"
def response = pbsServiceWithResponseCorrectionModule.sendAuctionRequest(bidRequest)

then: "PBS should emit log"
def logsByTime = pbsServiceWithResponseCorrectionModule.getLogsByTime(start)
def bidId = bidResponse.seatbid[0].bid[0].id
def responseCorrection = getLogsByText(logsByTime, bidId)
assert responseCorrection.size() == 1
assert responseCorrection.any {
it.contains("Bid $bidId of bidder generic: changing media type to banner" as String)
}

and: "Response should contain seatBid"
assert response.seatbid.size() == 1

and: "Response should contain single seatBid with proper media type"
assert response.seatbid.bid.ext.prebid.type.flatten() == [BANNER]

and: "Response should contain single seatBid with proper meta media type"
assert response.seatbid.bid.ext.prebid.meta.mediaType.flatten() == [VIDEO.value]

and: "Response shouldn't contain errors"
assert !response.ext.errors

and: "Response shouldn't contain warnings"
assert !response.ext.warnings

where:
admValue << [
"<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST${PBSUtils.randomString}",
"<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST",
"<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST>",
"<${PBSUtils.randomString}VAST${' ' * PBSUtils.getRandomNumber(1, OPTIMAL_MAX_LENGTH)}"
]
}

def "PBS should modify response when requested #mediaType impression respond with adm VAST keyword"() {
Expand All @@ -365,7 +430,7 @@ class ResponseCorrectionSpec extends ModuleBaseSpec {

and: "Set bidder response"
def bidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap {
seatbid[0].bid[0].setAdm(PBSUtils.getRandomCase("<${PBSUtils.randomString}VAST${PBSUtils.randomString}"))
seatbid[0].bid[0].setAdm(PBSUtils.getRandomCase(admValue))
}
bidder.setResponse(bidRequest.id, bidResponse)

Expand All @@ -376,7 +441,7 @@ class ResponseCorrectionSpec extends ModuleBaseSpec {
when: "PBS processes auction request"
def response = pbsServiceWithResponseCorrectionModule.sendAuctionRequest(bidRequest)

then: "PBS shouldn't emit log"
then: "PBS should emit log"
def logsByTime = pbsServiceWithResponseCorrectionModule.getLogsByTime(start)
def bidId = bidResponse.seatbid[0].bid[0].id
def responseCorrection = getLogsByText(logsByTime, bidId)
Expand All @@ -401,7 +466,16 @@ class ResponseCorrectionSpec extends ModuleBaseSpec {
assert !response.ext.warnings

where:
mediaType << [BANNER, AUDIO, NATIVE]
mediaType | admValue
BANNER | "${PBSUtils.randomString}<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST${PBSUtils.randomString}"
BANNER | "<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST${' ' * PBSUtils.getRandomNumber(1, OPTIMAL_MAX_LENGTH)}"
BANNER | "<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}}VAST${' ' * PBSUtils.getRandomNumber(1, OPTIMAL_MAX_LENGTH)}${PBSUtils.randomString}"
AUDIO | "${PBSUtils.randomString}<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST${PBSUtils.randomString}"
AUDIO | "<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST${' ' * PBSUtils.getRandomNumber(1, OPTIMAL_MAX_LENGTH)}"
AUDIO | "<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}}VAST${' ' * PBSUtils.getRandomNumber(1, OPTIMAL_MAX_LENGTH)}${PBSUtils.randomString}"
NATIVE | "${PBSUtils.randomString}<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST${PBSUtils.randomString}"
NATIVE | "<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST${' ' * PBSUtils.getRandomNumber(1, OPTIMAL_MAX_LENGTH)}"
NATIVE | "<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}}VAST${' ' * PBSUtils.getRandomNumber(1, OPTIMAL_MAX_LENGTH)}${PBSUtils.randomString}"
}

def "PBS shouldn't modify response meta.mediaType to video and emit logs when requested impression with video and adm obj with asset"() {
Expand Down

0 comments on commit 45f2a27

Please sign in to comment.