From 24c9176ad349ab120b6950c95fc386dfaa1ad8bc Mon Sep 17 00:00:00 2001 From: Sergii Chernysh Date: Tue, 11 May 2021 16:39:24 +0300 Subject: [PATCH] Basic integration tests for hooks framework (#1250) * Sample module for integration testing * Integration test specifically for hooks invocation * Add sample raw auction request hook to integration test * Add sample processed auction request hook to integration test * Add sample bidder request hook to integration test * Add sample raw bidder response hook to integration test * Add sample processed bidder response hook to integration test * Add sample auction response hook to integration test * Simplify integration test for hooks framework by using a separate account * Add tests for rejection scenarios at different stages --- .../requestfactory/AmpRequestFactory.java | 7 +- .../Ortb2ImplicitParametersResolver.java | 5 +- .../requestfactory/Ortb2RequestFactory.java | 11 +- .../execution/HookStageExecutorTest.java | 55 ------- .../hooks/execution/InvocationResultImpl.java | 63 ++++++++ .../org/prebid/server/it/IntegrationTest.java | 11 +- .../org/prebid/server/it/hooks/HooksTest.java | 147 ++++++++++++++++++ .../it/hooks/SampleItAuctionResponseHook.java | 50 ++++++ .../it/hooks/SampleItBidderRequestHook.java | 48 ++++++ .../it/hooks/SampleItEntrypointHook.java | 58 +++++++ .../server/it/hooks/SampleItModule.java | 41 +++++ .../SampleItProcessedAuctionRequestHook.java | 66 ++++++++ .../SampleItProcessedBidderResponseHook.java | 46 ++++++ .../hooks/SampleItRawAuctionRequestHook.java | 66 ++++++++ .../hooks/SampleItRawBidderResponseHook.java | 45 ++++++ .../SampleItRejectingBidderRequestHook.java | 23 +++ ...tRejectingProcessedAuctionRequestHook.java | 24 +++ ...tRejectingProcessedBidderResponseHook.java | 24 +++ ...ampleItRejectingRawAuctionRequestHook.java | 23 +++ ...ampleItRejectingRawBidderResponseHook.java | 23 +++ .../it/hooks/TestHooksConfiguration.java | 15 ++ ...auction-bidder-request-reject-request.json | 60 +++++++ ...uction-bidder-request-reject-response.json | 14 ++ ...cessed-auction-request-reject-request.json | 38 +++++ ...cessed-bidder-response-reject-request.json | 60 +++++++ ...essed-bidder-response-reject-response.json | 14 ++ ...on-raw-auction-request-reject-request.json | 38 +++++ ...on-raw-bidder-response-reject-request.json | 60 +++++++ ...n-raw-bidder-response-reject-response.json | 14 ++ .../reject/test-rubicon-bid-request-1.json | 76 +++++++++ .../reject/test-rubicon-bid-response-1.json | 19 +++ .../test-auction-sample-module-request.json | 61 ++++++++ .../test-auction-sample-module-response.json | 106 +++++++++++++ .../test-rubicon-bid-request-1.json | 77 +++++++++ .../test-rubicon-bid-response-1.json | 19 +++ .../prebid/server/it/test-app-settings.yaml | 113 ++++++++++++++ .../it/test-application-hooks.properties | 22 +++ 37 files changed, 1578 insertions(+), 64 deletions(-) create mode 100644 src/test/java/org/prebid/server/hooks/execution/InvocationResultImpl.java create mode 100644 src/test/java/org/prebid/server/it/hooks/HooksTest.java create mode 100644 src/test/java/org/prebid/server/it/hooks/SampleItAuctionResponseHook.java create mode 100644 src/test/java/org/prebid/server/it/hooks/SampleItBidderRequestHook.java create mode 100644 src/test/java/org/prebid/server/it/hooks/SampleItEntrypointHook.java create mode 100644 src/test/java/org/prebid/server/it/hooks/SampleItModule.java create mode 100644 src/test/java/org/prebid/server/it/hooks/SampleItProcessedAuctionRequestHook.java create mode 100644 src/test/java/org/prebid/server/it/hooks/SampleItProcessedBidderResponseHook.java create mode 100644 src/test/java/org/prebid/server/it/hooks/SampleItRawAuctionRequestHook.java create mode 100644 src/test/java/org/prebid/server/it/hooks/SampleItRawBidderResponseHook.java create mode 100644 src/test/java/org/prebid/server/it/hooks/SampleItRejectingBidderRequestHook.java create mode 100644 src/test/java/org/prebid/server/it/hooks/SampleItRejectingProcessedAuctionRequestHook.java create mode 100644 src/test/java/org/prebid/server/it/hooks/SampleItRejectingProcessedBidderResponseHook.java create mode 100644 src/test/java/org/prebid/server/it/hooks/SampleItRejectingRawAuctionRequestHook.java create mode 100644 src/test/java/org/prebid/server/it/hooks/SampleItRejectingRawBidderResponseHook.java create mode 100644 src/test/java/org/prebid/server/it/hooks/TestHooksConfiguration.java create mode 100644 src/test/resources/org/prebid/server/it/hooks/reject/test-auction-bidder-request-reject-request.json create mode 100644 src/test/resources/org/prebid/server/it/hooks/reject/test-auction-bidder-request-reject-response.json create mode 100644 src/test/resources/org/prebid/server/it/hooks/reject/test-auction-processed-auction-request-reject-request.json create mode 100644 src/test/resources/org/prebid/server/it/hooks/reject/test-auction-processed-bidder-response-reject-request.json create mode 100644 src/test/resources/org/prebid/server/it/hooks/reject/test-auction-processed-bidder-response-reject-response.json create mode 100644 src/test/resources/org/prebid/server/it/hooks/reject/test-auction-raw-auction-request-reject-request.json create mode 100644 src/test/resources/org/prebid/server/it/hooks/reject/test-auction-raw-bidder-response-reject-request.json create mode 100644 src/test/resources/org/prebid/server/it/hooks/reject/test-auction-raw-bidder-response-reject-response.json create mode 100644 src/test/resources/org/prebid/server/it/hooks/reject/test-rubicon-bid-request-1.json create mode 100644 src/test/resources/org/prebid/server/it/hooks/reject/test-rubicon-bid-response-1.json create mode 100644 src/test/resources/org/prebid/server/it/hooks/sample-module/test-auction-sample-module-request.json create mode 100644 src/test/resources/org/prebid/server/it/hooks/sample-module/test-auction-sample-module-response.json create mode 100644 src/test/resources/org/prebid/server/it/hooks/sample-module/test-rubicon-bid-request-1.json create mode 100644 src/test/resources/org/prebid/server/it/hooks/sample-module/test-rubicon-bid-response-1.json create mode 100644 src/test/resources/org/prebid/server/it/test-application-hooks.properties diff --git a/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java index eaf85231364..cc8868c248e 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java @@ -643,7 +643,12 @@ private ExtRequest extRequest(BidRequest bidRequest, prebidBuilder.amp(ExtRequestPrebidAmp.of(updatedAmpData)); } - result = ExtRequest.of(prebidBuilder.build()); + final ExtRequest updatedExt = ExtRequest.of(prebidBuilder.build()); + if (requestExt != null) { + updatedExt.addProperties(requestExt.getProperties()); + } + + result = updatedExt; } else { result = bidRequest.getExt(); } diff --git a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java index bbd33d77ad7..e2fcdd4dca4 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java @@ -493,7 +493,7 @@ private ExtRequest populateRequestExt(ExtRequest ext, BidRequest bidRequest, Lis ? prebid.toBuilder() : ExtRequestPrebid.builder(); - return ExtRequest.of(prebidBuilder + final ExtRequest updatedExt = ExtRequest.of(prebidBuilder .targeting(ObjectUtils.defaultIfNull(updatedTargeting, getIfNotNull(prebid, ExtRequestPrebid::getTargeting))) .cache(ObjectUtils.defaultIfNull(updatedCache, @@ -501,6 +501,9 @@ private ExtRequest populateRequestExt(ExtRequest ext, BidRequest bidRequest, Lis .channel(ObjectUtils.defaultIfNull(updatedChannel, getIfNotNull(prebid, ExtRequestPrebid::getChannel))) .build()); + updatedExt.addProperties(ext.getProperties()); + + return updatedExt; } return null; diff --git a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java index 4230f6f0f3f..a538451f4e5 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java @@ -221,8 +221,8 @@ private Future accountFrom(BidRequest bidRequest, Timeout timeout, Http return isAccountIdBlank ? responseForEmptyAccount(httpRequest) : applicationSettings.getAccountById(accountId, timeout) - .compose(this::ensureAccountActive, - exception -> accountFallback(exception, accountId, httpRequest)); + .compose(this::ensureAccountActive, + exception -> accountFallback(exception, accountId, httpRequest)); } /** @@ -312,7 +312,12 @@ private ExtRequest enrichExtRequest(ExtRequest ext, Account account) { prebidExtBuilder.integration(accountDefaultIntegration); - return ExtRequest.of(prebidExtBuilder.build()); + final ExtRequest updatedExt = ExtRequest.of(prebidExtBuilder.build()); + if (ext != null) { + updatedExt.addProperties(ext.getProperties()); + } + + return updatedExt; } return null; diff --git a/src/test/java/org/prebid/server/hooks/execution/HookStageExecutorTest.java b/src/test/java/org/prebid/server/hooks/execution/HookStageExecutorTest.java index cac3035d90b..55225d48efd 100644 --- a/src/test/java/org/prebid/server/hooks/execution/HookStageExecutorTest.java +++ b/src/test/java/org/prebid/server/hooks/execution/HookStageExecutorTest.java @@ -11,9 +11,7 @@ import io.vertx.ext.unit.Async; import io.vertx.ext.unit.TestContext; import io.vertx.ext.unit.junit.VertxUnitRunner; -import lombok.Builder; import lombok.Value; -import lombok.experimental.Accessors; import lombok.experimental.NonFinal; import org.apache.commons.lang3.StringUtils; import org.assertj.core.api.Assertions; @@ -54,7 +52,6 @@ import org.prebid.server.hooks.v1.InvocationContext; import org.prebid.server.hooks.v1.InvocationResult; import org.prebid.server.hooks.v1.InvocationStatus; -import org.prebid.server.hooks.v1.PayloadUpdate; import org.prebid.server.hooks.v1.auction.AuctionInvocationContext; import org.prebid.server.hooks.v1.auction.AuctionRequestPayload; import org.prebid.server.hooks.v1.auction.AuctionResponseHook; @@ -2550,56 +2547,4 @@ public String code() { return code; } } - - @Accessors(fluent = true) - @Builder - @Value - private static class InvocationResultImpl implements InvocationResult { - - InvocationStatus status; - - String message; - - InvocationAction action; - - PayloadUpdate payloadUpdate; - - List errors; - - List warnings; - - List debugMessages; - - Object moduleContext; - - public static InvocationResult succeeded(PayloadUpdate payloadUpdate) { - return InvocationResultImpl.builder() - .status(InvocationStatus.success) - .action(InvocationAction.update) - .payloadUpdate(payloadUpdate) - .build(); - } - - public static InvocationResult failed(String message) { - return InvocationResultImpl.builder() - .status(InvocationStatus.failure) - .message(message) - .build(); - } - - public static InvocationResult noAction() { - return InvocationResultImpl.builder() - .status(InvocationStatus.success) - .action(InvocationAction.no_action) - .build(); - } - - public static InvocationResult rejected(String message) { - return InvocationResultImpl.builder() - .status(InvocationStatus.success) - .action(InvocationAction.reject) - .message(message) - .build(); - } - } } diff --git a/src/test/java/org/prebid/server/hooks/execution/InvocationResultImpl.java b/src/test/java/org/prebid/server/hooks/execution/InvocationResultImpl.java new file mode 100644 index 00000000000..e86fabe668b --- /dev/null +++ b/src/test/java/org/prebid/server/hooks/execution/InvocationResultImpl.java @@ -0,0 +1,63 @@ +package org.prebid.server.hooks.execution; + +import lombok.Builder; +import lombok.Value; +import lombok.experimental.Accessors; +import org.prebid.server.hooks.v1.InvocationAction; +import org.prebid.server.hooks.v1.InvocationResult; +import org.prebid.server.hooks.v1.InvocationStatus; +import org.prebid.server.hooks.v1.PayloadUpdate; + +import java.util.List; + +@Accessors(fluent = true) +@Builder +@Value +public class InvocationResultImpl implements InvocationResult { + + InvocationStatus status; + + String message; + + InvocationAction action; + + PayloadUpdate payloadUpdate; + + List errors; + + List warnings; + + List debugMessages; + + Object moduleContext; + + public static InvocationResult succeeded(PayloadUpdate payloadUpdate) { + return InvocationResultImpl.builder() + .status(InvocationStatus.success) + .action(InvocationAction.update) + .payloadUpdate(payloadUpdate) + .build(); + } + + public static InvocationResult failed(String message) { + return InvocationResultImpl.builder() + .status(InvocationStatus.failure) + .message(message) + .build(); + } + + public static InvocationResult noAction() { + return InvocationResultImpl.builder() + .status(InvocationStatus.success) + .action(InvocationAction.no_action) + .build(); + } + + public static InvocationResult rejected(String message) { + return InvocationResultImpl.builder() + .status(InvocationStatus.success) + .action(InvocationAction.reject) + .message(message) + .build(); + } +} diff --git a/src/test/java/org/prebid/server/it/IntegrationTest.java b/src/test/java/org/prebid/server/it/IntegrationTest.java index 50562374cc7..359968d7ee8 100644 --- a/src/test/java/org/prebid/server/it/IntegrationTest.java +++ b/src/test/java/org/prebid/server/it/IntegrationTest.java @@ -21,6 +21,7 @@ import org.prebid.server.cache.proto.request.PutObject; import org.prebid.server.cache.proto.response.BidCacheResponse; import org.prebid.server.cache.proto.response.CacheObject; +import org.prebid.server.it.hooks.TestHooksConfiguration; import org.prebid.server.it.util.BidCacheRequestPattern; import org.skyscreamer.jsonassert.ArrayValueMatcher; import org.skyscreamer.jsonassert.Customization; @@ -29,6 +30,7 @@ import org.skyscreamer.jsonassert.ValueMatcher; import org.skyscreamer.jsonassert.comparator.CustomComparator; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; import org.springframework.test.context.TestPropertySource; import java.io.IOException; @@ -42,7 +44,8 @@ import static java.lang.String.format; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) -@TestPropertySource("test-application.properties") +@TestPropertySource({"test-application.properties", "test-application-hooks.properties"}) +@Import(TestHooksConfiguration.class) public abstract class IntegrationTest extends VertxTest { private static final int APP_PORT = 8080; @@ -59,7 +62,7 @@ public abstract class IntegrationTest extends VertxTest { @Rule public WireMockClassRule instanceRule = WIRE_MOCK_RULE; - static final RequestSpecification SPEC = spec(APP_PORT); + protected static final RequestSpecification SPEC = spec(APP_PORT); @BeforeClass public static void setUp() throws IOException { @@ -78,12 +81,12 @@ static RequestSpecification spec(int port) { .build(); } - static String jsonFrom(String file) throws IOException { + protected static String jsonFrom(String file) throws IOException { // workaround to clear formatting return mapper.writeValueAsString(mapper.readTree(IntegrationTest.class.getResourceAsStream(file))); } - static String openrtbAuctionResponseFrom(String templatePath, Response response, List bidders) + protected static String openrtbAuctionResponseFrom(String templatePath, Response response, List bidders) throws IOException { return auctionResponseFrom(templatePath, response, "ext.responsetimemillis.%s", bidders); diff --git a/src/test/java/org/prebid/server/it/hooks/HooksTest.java b/src/test/java/org/prebid/server/it/hooks/HooksTest.java new file mode 100644 index 00000000000..e191f4207d4 --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/HooksTest.java @@ -0,0 +1,147 @@ +package org.prebid.server.it.hooks; + +import io.restassured.response.Response; +import org.json.JSONException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.prebid.server.it.IntegrationTest; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static io.restassured.RestAssured.given; +import static java.util.Collections.singletonList; +import static org.hamcrest.Matchers.empty; + +@RunWith(SpringRunner.class) +public class HooksTest extends IntegrationTest { + + private static final String RUBICON = "rubicon"; + + @Test + public void openrtb2AuctionShouldRunHooksAtEachStage() throws IOException, JSONException { + // given + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/rubicon-exchange")) + .withRequestBody(equalToJson(jsonFrom("hooks/sample-module/test-rubicon-bid-request-1.json"))) + .willReturn(aResponse().withBody(jsonFrom("hooks/sample-module/test-rubicon-bid-response-1.json")))); + + // when + final Response response = given(SPEC) + .queryParam("sample-it-module-update", "headers,body") + .header("User-Agent", "userAgent") + .body(jsonFrom("hooks/sample-module/test-auction-sample-module-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "hooks/sample-module/test-auction-sample-module-response.json", response, singletonList(RUBICON)); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.LENIENT); + } + + @Test + public void openrtb2AuctionShouldBeRejectedByEntrypointHook() throws IOException { + given(SPEC) + .queryParam("sample-it-module-reject", "true") + .header("User-Agent", "userAgent") + .body(jsonFrom("hooks/sample-module/test-auction-sample-module-request.json")) + .post("/openrtb2/auction") + .then() + .statusCode(200) + .body("seatbid", empty()); + } + + @Test + public void openrtb2AuctionShouldBeRejectedByRawAuctionRequestHook() throws IOException { + given(SPEC) + .header("User-Agent", "userAgent") + .body(jsonFrom("hooks/reject/test-auction-raw-auction-request-reject-request.json")) + .post("/openrtb2/auction") + .then() + .statusCode(200) + .body("seatbid", empty()); + } + + @Test + public void openrtb2AuctionShouldBeRejectedByProcessedAuctionRequestHook() throws IOException { + given(SPEC) + .header("User-Agent", "userAgent") + .body(jsonFrom("hooks/reject/test-auction-processed-auction-request-reject-request.json")) + .post("/openrtb2/auction") + .then() + .statusCode(200) + .body("seatbid", empty()); + } + + @Test + public void openrtb2AuctionShouldRejectRubiconBidderByBidderRequestHook() throws IOException, JSONException { + // when + final Response response = given(SPEC) + .header("User-Agent", "userAgent") + .body(jsonFrom("hooks/reject/test-auction-bidder-request-reject-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "hooks/reject/test-auction-bidder-request-reject-response.json", response, singletonList(RUBICON)); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.LENIENT); + + WIRE_MOCK_RULE.verify(0, postRequestedFor(urlPathEqualTo("/rubicon-exchange"))); + } + + @Test + public void openrtb2AuctionShouldRejectRubiconBidderByRawBidderResponseHook() throws IOException, JSONException { + // given + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/rubicon-exchange")) + .willReturn(aResponse().withBody(jsonFrom("hooks/reject/test-rubicon-bid-response-1.json")))); + + // when + final Response response = given(SPEC) + .header("User-Agent", "userAgent") + .body(jsonFrom("hooks/reject/test-auction-raw-bidder-response-reject-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "hooks/reject/test-auction-raw-bidder-response-reject-response.json", response, singletonList(RUBICON)); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.LENIENT); + + WIRE_MOCK_RULE.verify(1, postRequestedFor(urlPathEqualTo("/rubicon-exchange")) + .withRequestBody(equalToJson(jsonFrom("hooks/reject/test-rubicon-bid-request-1.json")))); + } + + @Test + public void openrtb2AuctionShouldRejectRubiconBidderByProcessedBidderResponseHook() + throws IOException, JSONException { + + // given + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/rubicon-exchange")) + .willReturn(aResponse().withBody(jsonFrom("hooks/reject/test-rubicon-bid-response-1.json")))); + + // when + final Response response = given(SPEC) + .header("User-Agent", "userAgent") + .body(jsonFrom("hooks/reject/test-auction-processed-bidder-response-reject-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "hooks/reject/test-auction-processed-bidder-response-reject-response.json", + response, + singletonList(RUBICON)); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.LENIENT); + + WIRE_MOCK_RULE.verify(1, postRequestedFor(urlPathEqualTo("/rubicon-exchange")) + .withRequestBody(equalToJson(jsonFrom("hooks/reject/test-rubicon-bid-request-1.json")))); + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItAuctionResponseHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItAuctionResponseHook.java new file mode 100644 index 00000000000..f78b5e2f98e --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/SampleItAuctionResponseHook.java @@ -0,0 +1,50 @@ +package org.prebid.server.it.hooks; + +import com.iab.openrtb.response.BidResponse; +import io.vertx.core.Future; +import org.prebid.server.hooks.execution.InvocationResultImpl; +import org.prebid.server.hooks.execution.v1.auction.AuctionResponsePayloadImpl; +import org.prebid.server.hooks.v1.InvocationResult; +import org.prebid.server.hooks.v1.auction.AuctionInvocationContext; +import org.prebid.server.hooks.v1.auction.AuctionResponseHook; +import org.prebid.server.hooks.v1.auction.AuctionResponsePayload; + +import java.util.stream.Collectors; + +public class SampleItAuctionResponseHook implements AuctionResponseHook { + + @Override + public Future> call( + AuctionResponsePayload auctionResponsePayload, AuctionInvocationContext invocationContext) { + + final BidResponse originalBidResponse = auctionResponsePayload.bidResponse(); + + final BidResponse updatedBidResponse = updateBidResponse(originalBidResponse); + + return Future.succeededFuture(InvocationResultImpl.succeeded(payload -> + AuctionResponsePayloadImpl.of(payload.bidResponse().toBuilder() + .seatbid(updatedBidResponse.getSeatbid()) + .build()))); + } + + @Override + public String code() { + return "auction-response"; + } + + private BidResponse updateBidResponse(BidResponse originalBidResponse) { + return originalBidResponse.toBuilder() + .seatbid(originalBidResponse.getSeatbid().stream() + .map(seatBid -> seatBid.toBuilder() + .bid(seatBid.getBid().stream() + .map(bid -> bid.toBuilder() + .adm(bid.getAdm() + + "") + .build()) + .collect(Collectors.toList())) + .build()) + .collect(Collectors.toList())) + .build(); + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItBidderRequestHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItBidderRequestHook.java new file mode 100644 index 00000000000..d3baf9e0d10 --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/SampleItBidderRequestHook.java @@ -0,0 +1,48 @@ +package org.prebid.server.it.hooks; + +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import io.vertx.core.Future; +import org.prebid.server.hooks.execution.InvocationResultImpl; +import org.prebid.server.hooks.execution.v1.bidder.BidderRequestPayloadImpl; +import org.prebid.server.hooks.v1.InvocationResult; +import org.prebid.server.hooks.v1.bidder.BidderInvocationContext; +import org.prebid.server.hooks.v1.bidder.BidderRequestHook; +import org.prebid.server.hooks.v1.bidder.BidderRequestPayload; + +import java.util.List; +import java.util.stream.Collectors; + +public class SampleItBidderRequestHook implements BidderRequestHook { + + @Override + public Future> call( + BidderRequestPayload bidderRequestPayload, BidderInvocationContext invocationContext) { + + final BidRequest originalBidRequest = bidderRequestPayload.bidRequest(); + + final BidRequest updatedBidRequest = updateBidRequest(originalBidRequest, invocationContext); + + return Future.succeededFuture(InvocationResultImpl.succeeded(payload -> + BidderRequestPayloadImpl.of(payload.bidRequest().toBuilder() + .imp(updatedBidRequest.getImp()) + .build()))); + } + + @Override + public String code() { + return "bidder-request"; + } + + private BidRequest updateBidRequest( + BidRequest originalBidRequest, BidderInvocationContext bidderInvocationContext) { + + final List updatedImps = originalBidRequest.getImp().stream() + .map(imp -> imp.toBuilder().id(imp.getId() + "-rubicon").build()) + .collect(Collectors.toList()); + + return originalBidRequest.toBuilder() + .imp(updatedImps) + .build(); + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItEntrypointHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItEntrypointHook.java new file mode 100644 index 00000000000..e45bba7566f --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/SampleItEntrypointHook.java @@ -0,0 +1,58 @@ +package org.prebid.server.it.hooks; + +import io.vertx.core.Future; +import io.vertx.core.MultiMap; +import org.apache.commons.lang3.StringUtils; +import org.prebid.server.hooks.execution.InvocationResultImpl; +import org.prebid.server.hooks.execution.v1.entrypoint.EntrypointPayloadImpl; +import org.prebid.server.hooks.v1.InvocationContext; +import org.prebid.server.hooks.v1.InvocationResult; +import org.prebid.server.hooks.v1.entrypoint.EntrypointHook; +import org.prebid.server.hooks.v1.entrypoint.EntrypointPayload; + +public class SampleItEntrypointHook implements EntrypointHook { + + @Override + public Future> call( + EntrypointPayload entrypointPayload, InvocationContext invocationContext) { + + final boolean rejectFlag = Boolean.parseBoolean(entrypointPayload.queryParams().get("sample-it-module-reject")); + if (rejectFlag) { + return Future.succeededFuture(InvocationResultImpl.rejected("Rejected by sample entrypoint hook")); + } + + return maybeUpdate(entrypointPayload); + } + + private Future> maybeUpdate(EntrypointPayload entrypointPayload) { + final String updateSelector = entrypointPayload.queryParams().get("sample-it-module-update"); + + final MultiMap updatedHeaders = StringUtils.contains(updateSelector, "headers") + ? updateHeaders(entrypointPayload.headers()) + : entrypointPayload.headers(); + + final String updatedBody = StringUtils.contains(updateSelector, "body") + ? updateBody(entrypointPayload.body()) + : entrypointPayload.body(); + + return Future.succeededFuture(InvocationResultImpl.succeeded(payload -> EntrypointPayloadImpl.of( + payload.queryParams(), + updatedHeaders, + updatedBody))); + } + + private static MultiMap updateHeaders(MultiMap headers) { + return MultiMap.caseInsensitiveMultiMap() + .addAll(headers) + .set("X-Forwarded-For", "222.111.222.111"); + } + + private static String updateBody(String body) { + return body.replaceAll("\"language\":\"en\"", "\"language\":\"fr\""); + } + + @Override + public String code() { + return "entrypoint"; + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItModule.java b/src/test/java/org/prebid/server/it/hooks/SampleItModule.java new file mode 100644 index 00000000000..e2806f8c87f --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/SampleItModule.java @@ -0,0 +1,41 @@ +package org.prebid.server.it.hooks; + +import org.prebid.server.hooks.v1.Hook; +import org.prebid.server.hooks.v1.Module; +import org.prebid.server.json.JacksonMapper; + +import java.util.Arrays; +import java.util.Collection; + +public class SampleItModule implements Module { + + static final String MODULE_EXT = "sample-it-module"; + + private final JacksonMapper mapper; + + public SampleItModule(JacksonMapper mapper) { + this.mapper = mapper; + } + + @Override + public Collection> hooks() { + return Arrays.asList( + new SampleItEntrypointHook(), + new SampleItRawAuctionRequestHook(mapper), + new SampleItProcessedAuctionRequestHook(mapper), + new SampleItBidderRequestHook(), + new SampleItRawBidderResponseHook(), + new SampleItProcessedBidderResponseHook(), + new SampleItAuctionResponseHook(), + new SampleItRejectingRawAuctionRequestHook(), + new SampleItRejectingProcessedAuctionRequestHook(), + new SampleItRejectingBidderRequestHook(), + new SampleItRejectingRawBidderResponseHook(), + new SampleItRejectingProcessedBidderResponseHook()); + } + + @Override + public String code() { + return "sample-it-module"; + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItProcessedAuctionRequestHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItProcessedAuctionRequestHook.java new file mode 100644 index 00000000000..cc3dff5b600 --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/SampleItProcessedAuctionRequestHook.java @@ -0,0 +1,66 @@ +package org.prebid.server.it.hooks; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.iab.openrtb.request.BidRequest; +import io.vertx.core.Future; +import org.prebid.server.hooks.execution.InvocationResultImpl; +import org.prebid.server.hooks.execution.v1.auction.AuctionRequestPayloadImpl; +import org.prebid.server.hooks.v1.InvocationResult; +import org.prebid.server.hooks.v1.auction.AuctionInvocationContext; +import org.prebid.server.hooks.v1.auction.AuctionRequestPayload; +import org.prebid.server.hooks.v1.auction.ProcessedAuctionRequestHook; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.proto.openrtb.ext.request.ExtRequest; + +public class SampleItProcessedAuctionRequestHook implements ProcessedAuctionRequestHook { + + private final JacksonMapper mapper; + + public SampleItProcessedAuctionRequestHook(JacksonMapper mapper) { + this.mapper = mapper; + } + + @Override + public Future> call( + AuctionRequestPayload auctionRequestPayload, AuctionInvocationContext invocationContext) { + + final BidRequest originalBidRequest = auctionRequestPayload.bidRequest(); + + final BidRequest updatedBidRequest = updateBidRequest(originalBidRequest); + + return Future.succeededFuture(InvocationResultImpl.succeeded(payload -> + AuctionRequestPayloadImpl.of(payload.bidRequest().toBuilder() + .ext(updatedBidRequest.getExt()) + .build()))); + } + + @Override + public String code() { + return "processed-auction-request"; + } + + private BidRequest updateBidRequest(BidRequest originalBidRequest) { + final ExtRequest originalExt = originalBidRequest.getExt(); + + final JsonNode moduleExt = originalExt != null ? originalExt.getProperty(SampleItModule.MODULE_EXT) : null; + final ObjectNode updatedModuleExt = + moduleExt != null ? moduleExt.deepCopy() : mapper.mapper().createObjectNode(); + updatedModuleExt.put(code() + "-trace", "I've been here"); + + final ExtRequest updatedExt = copyExt(originalExt); + updatedExt.addProperty(SampleItModule.MODULE_EXT, updatedModuleExt); + + return originalBidRequest.toBuilder() + .ext(updatedExt) + .build(); + } + + private ExtRequest copyExt(ExtRequest originalExt) { + final ExtRequest updatedExt = originalExt != null ? ExtRequest.of(originalExt.getPrebid()) : ExtRequest.empty(); + if (originalExt != null) { + updatedExt.addProperties(originalExt.getProperties()); + } + return updatedExt; + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItProcessedBidderResponseHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItProcessedBidderResponseHook.java new file mode 100644 index 00000000000..e8103cb71c2 --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/SampleItProcessedBidderResponseHook.java @@ -0,0 +1,46 @@ +package org.prebid.server.it.hooks; + +import io.vertx.core.Future; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.hooks.execution.InvocationResultImpl; +import org.prebid.server.hooks.execution.v1.bidder.BidderResponsePayloadImpl; +import org.prebid.server.hooks.v1.InvocationResult; +import org.prebid.server.hooks.v1.bidder.BidderInvocationContext; +import org.prebid.server.hooks.v1.bidder.BidderResponsePayload; +import org.prebid.server.hooks.v1.bidder.ProcessedBidderResponseHook; + +import java.util.List; +import java.util.stream.Collectors; + +public class SampleItProcessedBidderResponseHook implements ProcessedBidderResponseHook { + + @Override + public Future> call( + BidderResponsePayload bidderResponsePayload, BidderInvocationContext invocationContext) { + + final List originalBids = bidderResponsePayload.bids(); + + final List updatedBids = updateBids(originalBids); + + return Future.succeededFuture(InvocationResultImpl.succeeded(payload -> + BidderResponsePayloadImpl.of(updatedBids))); + } + + @Override + public String code() { + return "processed-bidder-response"; + } + + private List updateBids(List originalBids) { + return originalBids.stream() + .map(bidderBid -> BidderBid.of( + bidderBid.getBid().toBuilder() + .adm(bidderBid.getBid().getAdm() + + "" + + "") + .build(), + bidderBid.getType(), + bidderBid.getBidCurrency())) + .collect(Collectors.toList()); + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItRawAuctionRequestHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItRawAuctionRequestHook.java new file mode 100644 index 00000000000..307f829e61a --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/SampleItRawAuctionRequestHook.java @@ -0,0 +1,66 @@ +package org.prebid.server.it.hooks; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.iab.openrtb.request.BidRequest; +import io.vertx.core.Future; +import org.prebid.server.hooks.execution.InvocationResultImpl; +import org.prebid.server.hooks.execution.v1.auction.AuctionRequestPayloadImpl; +import org.prebid.server.hooks.v1.InvocationResult; +import org.prebid.server.hooks.v1.auction.AuctionInvocationContext; +import org.prebid.server.hooks.v1.auction.AuctionRequestPayload; +import org.prebid.server.hooks.v1.auction.RawAuctionRequestHook; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.proto.openrtb.ext.request.ExtRequest; + +public class SampleItRawAuctionRequestHook implements RawAuctionRequestHook { + + private final JacksonMapper mapper; + + public SampleItRawAuctionRequestHook(JacksonMapper mapper) { + this.mapper = mapper; + } + + @Override + public Future> call( + AuctionRequestPayload auctionRequestPayload, AuctionInvocationContext invocationContext) { + + final BidRequest originalBidRequest = auctionRequestPayload.bidRequest(); + + final BidRequest updatedBidRequest = updateBidRequest(originalBidRequest); + + return Future.succeededFuture(InvocationResultImpl.succeeded(payload -> + AuctionRequestPayloadImpl.of(payload.bidRequest().toBuilder() + .ext(updatedBidRequest.getExt()) + .build()))); + } + + @Override + public String code() { + return "raw-auction-request"; + } + + private BidRequest updateBidRequest(BidRequest originalBidRequest) { + final ExtRequest originalExt = originalBidRequest.getExt(); + + final JsonNode moduleExt = originalExt != null ? originalExt.getProperty(SampleItModule.MODULE_EXT) : null; + final ObjectNode updatedModuleExt = + moduleExt != null ? moduleExt.deepCopy() : mapper.mapper().createObjectNode(); + updatedModuleExt.put(code() + "-trace", "I've been here"); + + final ExtRequest updatedExt = copyExt(originalExt); + updatedExt.addProperty(SampleItModule.MODULE_EXT, updatedModuleExt); + + return originalBidRequest.toBuilder() + .ext(updatedExt) + .build(); + } + + private ExtRequest copyExt(ExtRequest originalExt) { + final ExtRequest updatedExt = originalExt != null ? ExtRequest.of(originalExt.getPrebid()) : ExtRequest.empty(); + if (originalExt != null) { + updatedExt.addProperties(originalExt.getProperties()); + } + return updatedExt; + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItRawBidderResponseHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItRawBidderResponseHook.java new file mode 100644 index 00000000000..d74b13aa032 --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/SampleItRawBidderResponseHook.java @@ -0,0 +1,45 @@ +package org.prebid.server.it.hooks; + +import io.vertx.core.Future; +import org.apache.commons.lang3.StringUtils; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.hooks.execution.InvocationResultImpl; +import org.prebid.server.hooks.execution.v1.bidder.BidderResponsePayloadImpl; +import org.prebid.server.hooks.v1.InvocationResult; +import org.prebid.server.hooks.v1.bidder.BidderInvocationContext; +import org.prebid.server.hooks.v1.bidder.BidderResponsePayload; +import org.prebid.server.hooks.v1.bidder.RawBidderResponseHook; + +import java.util.List; +import java.util.stream.Collectors; + +public class SampleItRawBidderResponseHook implements RawBidderResponseHook { + + @Override + public Future> call( + BidderResponsePayload bidderResponsePayload, BidderInvocationContext invocationContext) { + + final List originalBids = bidderResponsePayload.bids(); + + final List updatedBids = updateBids(originalBids); + + return Future.succeededFuture(InvocationResultImpl.succeeded(payload -> + BidderResponsePayloadImpl.of(updatedBids))); + } + + @Override + public String code() { + return "raw-bidder-response"; + } + + private List updateBids(List originalBids) { + return originalBids.stream() + .map(bidderBid -> BidderBid.of( + bidderBid.getBid().toBuilder() + .impid(bidderBid.getBid().getImpid().replace("-rubicon", StringUtils.EMPTY)) + .build(), + bidderBid.getType(), + bidderBid.getBidCurrency())) + .collect(Collectors.toList()); + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItRejectingBidderRequestHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItRejectingBidderRequestHook.java new file mode 100644 index 00000000000..23a0d51f9f1 --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/SampleItRejectingBidderRequestHook.java @@ -0,0 +1,23 @@ +package org.prebid.server.it.hooks; + +import io.vertx.core.Future; +import org.prebid.server.hooks.execution.InvocationResultImpl; +import org.prebid.server.hooks.v1.InvocationResult; +import org.prebid.server.hooks.v1.bidder.BidderInvocationContext; +import org.prebid.server.hooks.v1.bidder.BidderRequestHook; +import org.prebid.server.hooks.v1.bidder.BidderRequestPayload; + +public class SampleItRejectingBidderRequestHook implements BidderRequestHook { + + @Override + public Future> call( + BidderRequestPayload bidderRequestPayload, BidderInvocationContext invocationContext) { + + return Future.succeededFuture(InvocationResultImpl.rejected("Rejected by rejecting bidder request hook")); + } + + @Override + public String code() { + return "rejecting-bidder-request"; + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItRejectingProcessedAuctionRequestHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItRejectingProcessedAuctionRequestHook.java new file mode 100644 index 00000000000..5458987db1d --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/SampleItRejectingProcessedAuctionRequestHook.java @@ -0,0 +1,24 @@ +package org.prebid.server.it.hooks; + +import io.vertx.core.Future; +import org.prebid.server.hooks.execution.InvocationResultImpl; +import org.prebid.server.hooks.v1.InvocationResult; +import org.prebid.server.hooks.v1.auction.AuctionInvocationContext; +import org.prebid.server.hooks.v1.auction.AuctionRequestPayload; +import org.prebid.server.hooks.v1.auction.ProcessedAuctionRequestHook; + +public class SampleItRejectingProcessedAuctionRequestHook implements ProcessedAuctionRequestHook { + + @Override + public Future> call( + AuctionRequestPayload auctionRequestPayload, AuctionInvocationContext invocationContext) { + + return Future.succeededFuture(InvocationResultImpl.rejected( + "Rejected by rejecting processed auction request hook")); + } + + @Override + public String code() { + return "rejecting-processed-auction-request"; + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItRejectingProcessedBidderResponseHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItRejectingProcessedBidderResponseHook.java new file mode 100644 index 00000000000..547c6bea0aa --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/SampleItRejectingProcessedBidderResponseHook.java @@ -0,0 +1,24 @@ +package org.prebid.server.it.hooks; + +import io.vertx.core.Future; +import org.prebid.server.hooks.execution.InvocationResultImpl; +import org.prebid.server.hooks.v1.InvocationResult; +import org.prebid.server.hooks.v1.bidder.BidderInvocationContext; +import org.prebid.server.hooks.v1.bidder.BidderResponsePayload; +import org.prebid.server.hooks.v1.bidder.ProcessedBidderResponseHook; + +public class SampleItRejectingProcessedBidderResponseHook implements ProcessedBidderResponseHook { + + @Override + public Future> call( + BidderResponsePayload bidderResponsePayload, BidderInvocationContext invocationContext) { + + return Future.succeededFuture(InvocationResultImpl.rejected( + "Rejected by rejecting processed bidder response hook")); + } + + @Override + public String code() { + return "rejecting-processed-bidder-response"; + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItRejectingRawAuctionRequestHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItRejectingRawAuctionRequestHook.java new file mode 100644 index 00000000000..ed7d84b7cf9 --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/SampleItRejectingRawAuctionRequestHook.java @@ -0,0 +1,23 @@ +package org.prebid.server.it.hooks; + +import io.vertx.core.Future; +import org.prebid.server.hooks.execution.InvocationResultImpl; +import org.prebid.server.hooks.v1.InvocationResult; +import org.prebid.server.hooks.v1.auction.AuctionInvocationContext; +import org.prebid.server.hooks.v1.auction.AuctionRequestPayload; +import org.prebid.server.hooks.v1.auction.RawAuctionRequestHook; + +public class SampleItRejectingRawAuctionRequestHook implements RawAuctionRequestHook { + + @Override + public Future> call( + AuctionRequestPayload auctionRequestPayload, AuctionInvocationContext invocationContext) { + + return Future.succeededFuture(InvocationResultImpl.rejected("Rejected by rejecting raw auction request hook")); + } + + @Override + public String code() { + return "rejecting-raw-auction-request"; + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItRejectingRawBidderResponseHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItRejectingRawBidderResponseHook.java new file mode 100644 index 00000000000..3c251c80555 --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/SampleItRejectingRawBidderResponseHook.java @@ -0,0 +1,23 @@ +package org.prebid.server.it.hooks; + +import io.vertx.core.Future; +import org.prebid.server.hooks.execution.InvocationResultImpl; +import org.prebid.server.hooks.v1.InvocationResult; +import org.prebid.server.hooks.v1.bidder.BidderInvocationContext; +import org.prebid.server.hooks.v1.bidder.BidderResponsePayload; +import org.prebid.server.hooks.v1.bidder.RawBidderResponseHook; + +public class SampleItRejectingRawBidderResponseHook implements RawBidderResponseHook { + + @Override + public Future> call( + BidderResponsePayload bidderResponsePayload, BidderInvocationContext invocationContext) { + + return Future.succeededFuture(InvocationResultImpl.rejected("Rejected by rejecting raw bidder response hook")); + } + + @Override + public String code() { + return "rejecting-raw-bidder-response"; + } +} diff --git a/src/test/java/org/prebid/server/it/hooks/TestHooksConfiguration.java b/src/test/java/org/prebid/server/it/hooks/TestHooksConfiguration.java new file mode 100644 index 00000000000..a08845f9c19 --- /dev/null +++ b/src/test/java/org/prebid/server/it/hooks/TestHooksConfiguration.java @@ -0,0 +1,15 @@ +package org.prebid.server.it.hooks; + +import org.prebid.server.hooks.v1.Module; +import org.prebid.server.json.JacksonMapper; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; + +@TestConfiguration +public class TestHooksConfiguration { + + @Bean + Module sampleItModule(JacksonMapper mapper) { + return new SampleItModule(mapper); + } +} diff --git a/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-bidder-request-reject-request.json b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-bidder-request-reject-request.json new file mode 100644 index 00000000000..4d60afed848 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-bidder-request-reject-request.json @@ -0,0 +1,60 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "prebid": { + "bidder": { + "rubicon": { + "accountId": 2001, + "siteId": 3001, + "zoneId": 4001 + } + } + } + } + } + ], + "device": { + "language": "en" + }, + "site": { + "page": "http://www.example.com", + "publisher": { + "id": "9001" + } + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "user": { + "ext": { + "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA" + }, + "regs": { + "ext": { + "us_privacy": "1YNN" + } + } + }, + "ext": { + "prebid": { + "auctiontimestamp": 1000 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-bidder-request-reject-response.json b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-bidder-request-reject-response.json new file mode 100644 index 00000000000..fc03a1405e2 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-bidder-request-reject-response.json @@ -0,0 +1,14 @@ +{ + "id": "tid", + "seatbid": [], + "cur": "USD", + "ext": { + "responsetimemillis": { + "rubicon": 0 + }, + "tmaxrequest": 5000, + "prebid": { + "auctiontimestamp": 1000 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-processed-auction-request-reject-request.json b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-processed-auction-request-reject-request.json new file mode 100644 index 00000000000..48c0f472517 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-processed-auction-request-reject-request.json @@ -0,0 +1,38 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "prebid": { + "bidder": { + "rubicon": { + "accountId": 2001, + "siteId": 3001, + "zoneId": 4001 + } + } + } + } + } + ], + "site": { + "page": "http://www.example.com", + "publisher": { + "id": "8001" + } + }, + "tmax": 5000 +} diff --git a/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-processed-bidder-response-reject-request.json b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-processed-bidder-response-reject-request.json new file mode 100644 index 00000000000..f87e126cdcf --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-processed-bidder-response-reject-request.json @@ -0,0 +1,60 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "prebid": { + "bidder": { + "rubicon": { + "accountId": 2001, + "siteId": 3001, + "zoneId": 4001 + } + } + } + } + } + ], + "device": { + "language": "en" + }, + "site": { + "page": "http://www.example.com", + "publisher": { + "id": "11001" + } + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "user": { + "ext": { + "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA" + }, + "regs": { + "ext": { + "us_privacy": "1YNN" + } + } + }, + "ext": { + "prebid": { + "auctiontimestamp": 1000 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-processed-bidder-response-reject-response.json b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-processed-bidder-response-reject-response.json new file mode 100644 index 00000000000..5dd19bd6e07 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-processed-bidder-response-reject-response.json @@ -0,0 +1,14 @@ +{ + "id": "tid", + "seatbid": [], + "cur": "USD", + "ext": { + "responsetimemillis": { + "rubicon": "{{ rubicon.response_time_ms }}" + }, + "tmaxrequest": 5000, + "prebid": { + "auctiontimestamp": 1000 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-raw-auction-request-reject-request.json b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-raw-auction-request-reject-request.json new file mode 100644 index 00000000000..80922d5800b --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-raw-auction-request-reject-request.json @@ -0,0 +1,38 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "prebid": { + "bidder": { + "rubicon": { + "accountId": 2001, + "siteId": 3001, + "zoneId": 4001 + } + } + } + } + } + ], + "site": { + "page": "http://www.example.com", + "publisher": { + "id": "7001" + } + }, + "tmax": 5000 +} diff --git a/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-raw-bidder-response-reject-request.json b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-raw-bidder-response-reject-request.json new file mode 100644 index 00000000000..b69f7dba5fb --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-raw-bidder-response-reject-request.json @@ -0,0 +1,60 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "prebid": { + "bidder": { + "rubicon": { + "accountId": 2001, + "siteId": 3001, + "zoneId": 4001 + } + } + } + } + } + ], + "device": { + "language": "en" + }, + "site": { + "page": "http://www.example.com", + "publisher": { + "id": "10001" + } + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "user": { + "ext": { + "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA" + }, + "regs": { + "ext": { + "us_privacy": "1YNN" + } + } + }, + "ext": { + "prebid": { + "auctiontimestamp": 1000 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-raw-bidder-response-reject-response.json b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-raw-bidder-response-reject-response.json new file mode 100644 index 00000000000..5dd19bd6e07 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/reject/test-auction-raw-bidder-response-reject-response.json @@ -0,0 +1,14 @@ +{ + "id": "tid", + "seatbid": [], + "cur": "USD", + "ext": { + "responsetimemillis": { + "rubicon": "{{ rubicon.response_time_ms }}" + }, + "tmaxrequest": 5000, + "prebid": { + "auctiontimestamp": 1000 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/hooks/reject/test-rubicon-bid-request-1.json b/src/test/resources/org/prebid/server/it/hooks/reject/test-rubicon-bid-request-1.json new file mode 100644 index 00000000000..b875f12b204 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/reject/test-rubicon-bid-request-1.json @@ -0,0 +1,76 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ], + "ext": { + "rp": { + "size_id": 15, + "alt_size_ids": [ + 10 + ], + "mime": "text/html" + } + } + }, + "ext": { + "rp": { + "zone_id": 4001, + "target": { + "page": [ + "http://www.example.com" + ] + }, + "track": { + "mint": "", + "mint_version": "" + } + }, + "maxbids": 1 + } + } + ], + "site": { + "domain": "example.com", + "page": "http://www.example.com", + "publisher": { + "ext": { + "rp": { + "account_id": 2001 + } + } + }, + "ext": { + "rp": { + "site_id": 3001 + }, + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "language": "en", + "ext": { + "rp": { + } + } + }, + "user": { + "ext": { + "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA" + } + }, + "at": 1, + "tmax": 5000 +} diff --git a/src/test/resources/org/prebid/server/it/hooks/reject/test-rubicon-bid-response-1.json b/src/test/resources/org/prebid/server/it/hooks/reject/test-rubicon-bid-response-1.json new file mode 100644 index 00000000000..c717d63849c --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/reject/test-rubicon-bid-response-1.json @@ -0,0 +1,19 @@ +{ + "id": "bidResponseId1", + "seatbid": [ + { + "bid": [ + { + "id": "880290288", + "impid": "impId1", + "price": 8.43, + "adm": "", + "crid": "crid1", + "w": 300, + "h": 250 + } + ], + "seat": "seatId1" + } + ] +} diff --git a/src/test/resources/org/prebid/server/it/hooks/sample-module/test-auction-sample-module-request.json b/src/test/resources/org/prebid/server/it/hooks/sample-module/test-auction-sample-module-request.json new file mode 100644 index 00000000000..8b330c79b0b --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/sample-module/test-auction-sample-module-request.json @@ -0,0 +1,61 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "prebid": { + "bidder": { + "rubicon": { + "accountId": 2001, + "siteId": 3001, + "zoneId": 4001 + } + } + } + } + } + ], + "device": { + "language": "en" + }, + "site": { + "page": "http://www.example.com", + "publisher": { + "id": "6001" + } + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "user": { + "ext": { + "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA" + }, + "regs": { + "ext": { + "us_privacy": "1YNN" + } + } + }, + "ext": { + "prebid": { + "debug": 1, + "auctiontimestamp": 1000 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/hooks/sample-module/test-auction-sample-module-response.json b/src/test/resources/org/prebid/server/it/hooks/sample-module/test-auction-sample-module-response.json new file mode 100644 index 00000000000..f4ab69ab049 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/sample-module/test-auction-sample-module-response.json @@ -0,0 +1,106 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "880290288", + "impid": "impId1", + "price": 8.43, + "adm": "", + "crid": "crid1", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner" + } + } + } + ], + "seat": "rubicon", + "group": 0 + } + ], + "cur": "USD", + "ext": { + "debug": { + "resolvedrequest": { + "id": "tid", + "imp": [ + { + "id": "impId1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "prebid": { + "bidder": { + "rubicon": { + "accountId": 2001, + "siteId": 3001, + "zoneId": 4001 + } + } + } + } + } + ], + "site": { + "domain": "example.com", + "page": "http://www.example.com", + "publisher": { + "id": "6001" + }, + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "ip": "222.111.222.111", + "language": "fr" + }, + "user": { + "ext": { + "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA" + } + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "ext": { + "prebid": { + "debug": 1, + "auctiontimestamp": 1000, + "channel": { + "name": "web" + } + }, + "sample-it-module": { + "raw-auction-request-trace": "I've been here", + "processed-auction-request-trace": "I've been here" + } + } + } + }, + "responsetimemillis": { + "rubicon": "{{ rubicon.response_time_ms }}" + }, + "tmaxrequest": 5000, + "prebid": { + "auctiontimestamp": 1000 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/hooks/sample-module/test-rubicon-bid-request-1.json b/src/test/resources/org/prebid/server/it/hooks/sample-module/test-rubicon-bid-request-1.json new file mode 100644 index 00000000000..9a590fdb2bc --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/sample-module/test-rubicon-bid-request-1.json @@ -0,0 +1,77 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId1-rubicon", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ], + "ext": { + "rp": { + "size_id": 15, + "alt_size_ids": [ + 10 + ], + "mime": "text/html" + } + } + }, + "ext": { + "rp": { + "zone_id": 4001, + "target": { + "page": [ + "http://www.example.com" + ] + }, + "track": { + "mint": "", + "mint_version": "" + } + }, + "maxbids": 1 + } + } + ], + "site": { + "domain": "example.com", + "page": "http://www.example.com", + "publisher": { + "ext": { + "rp": { + "account_id": 2001 + } + } + }, + "ext": { + "rp": { + "site_id": 3001 + }, + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "ip": "222.111.222.0", + "language": "fr", + "ext": { + "rp": { + } + } + }, + "user": { + "ext": { + "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA" + } + }, + "at": 1, + "tmax": 5000 +} diff --git a/src/test/resources/org/prebid/server/it/hooks/sample-module/test-rubicon-bid-response-1.json b/src/test/resources/org/prebid/server/it/hooks/sample-module/test-rubicon-bid-response-1.json new file mode 100644 index 00000000000..ca6a7caccc6 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/hooks/sample-module/test-rubicon-bid-response-1.json @@ -0,0 +1,19 @@ +{ + "id": "bidResponseId1", + "seatbid": [ + { + "bid": [ + { + "id": "880290288", + "impid": "impId1-rubicon", + "price": 8.43, + "adm": "", + "crid": "crid1", + "w": 300, + "h": 250 + } + ], + "seat": "seatId1" + } + ] +} diff --git a/src/test/resources/org/prebid/server/it/test-app-settings.yaml b/src/test/resources/org/prebid/server/it/test-app-settings.yaml index 11fecd164ff..77d078d5da6 100644 --- a/src/test/resources/org/prebid/server/it/test-app-settings.yaml +++ b/src/test/resources/org/prebid/server/it/test-app-settings.yaml @@ -9,6 +9,119 @@ accounts: - id: 2763 - id: 5001 eventsEnabled: true + - id: 6001 + hooks: + execution-plan: + endpoints: + /openrtb2/auction: + stages: + raw-auction-request: + groups: + - synchronous: true + timeout: 5 + hook-sequence: + - module-code: sample-it-module + hook-impl-code: raw-auction-request + processed-auction-request: + groups: + - synchronous: true + timeout: 5 + hook-sequence: + - module-code: sample-it-module + hook-impl-code: processed-auction-request + bidder-request: + groups: + - synchronous: true + timeout: 5 + hook-sequence: + - module-code: sample-it-module + hook-impl-code: bidder-request + raw-bidder-response: + groups: + - synchronous: true + timeout: 5 + hook-sequence: + - module-code: sample-it-module + hook-impl-code: raw-bidder-response + processed-bidder-response: + groups: + - synchronous: true + timeout: 5 + hook-sequence: + - module-code: sample-it-module + hook-impl-code: processed-bidder-response + auction-response: + groups: + - synchronous: true + timeout: 5 + hook-sequence: + - module-code: sample-it-module + hook-impl-code: auction-response + - id: 7001 + hooks: + execution-plan: + endpoints: + /openrtb2/auction: + stages: + raw-auction-request: + groups: + - synchronous: true + timeout: 5 + hook-sequence: + - module-code: sample-it-module + hook-impl-code: rejecting-raw-auction-request + - id: 8001 + hooks: + execution-plan: + endpoints: + /openrtb2/auction: + stages: + processed-auction-request: + groups: + - synchronous: true + timeout: 5 + hook-sequence: + - module-code: sample-it-module + hook-impl-code: rejecting-processed-auction-request + - id: 9001 + hooks: + execution-plan: + endpoints: + /openrtb2/auction: + stages: + bidder-request: + groups: + - synchronous: true + timeout: 5 + hook-sequence: + - module-code: sample-it-module + hook-impl-code: rejecting-bidder-request + - id: 10001 + hooks: + execution-plan: + endpoints: + /openrtb2/auction: + stages: + raw-bidder-response: + groups: + - synchronous: true + timeout: 5 + hook-sequence: + - module-code: sample-it-module + hook-impl-code: rejecting-raw-bidder-response + - id: 11001 + hooks: + execution-plan: + endpoints: + /openrtb2/auction: + stages: + processed-bidder-response: + groups: + - synchronous: true + timeout: 5 + hook-sequence: + - module-code: sample-it-module + hook-impl-code: rejecting-processed-bidder-response domains: - rubiconproject.com - www.rubiconproject.com diff --git a/src/test/resources/org/prebid/server/it/test-application-hooks.properties b/src/test/resources/org/prebid/server/it/test-application-hooks.properties new file mode 100644 index 00000000000..41e63d2c681 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/test-application-hooks.properties @@ -0,0 +1,22 @@ +hooks.execution-plan={ \ + "endpoints": { \ + "/openrtb2/auction": { \ + "stages": { \ + "entrypoint": { \ + "groups": [ \ + { \ + "synchronous": true, \ + "timeout": 5000, \ + "hook-sequence": [ \ + { \ + "module-code": "sample-it-module", \ + "hook-impl-code": "entrypoint" \ + } \ + ] \ + } \ + ] \ + } \ + } \ + } \ + } \ +} \ No newline at end of file