diff --git a/extra/bundle/pom.xml b/extra/bundle/pom.xml index e8b835f7400..ea7e8d30f5a 100644 --- a/extra/bundle/pom.xml +++ b/extra/bundle/pom.xml @@ -5,7 +5,11 @@ org.prebid prebid-server-aggregator +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) ../../extra/pom.xml diff --git a/extra/modules/confiant-ad-quality/pom.xml b/extra/modules/confiant-ad-quality/pom.xml index ccfeb526806..a9e83df218d 100644 --- a/extra/modules/confiant-ad-quality/pom.xml +++ b/extra/modules/confiant-ad-quality/pom.xml @@ -5,7 +5,11 @@ org.prebid.server.hooks.modules all-modules +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) confiant-ad-quality diff --git a/extra/modules/fiftyone-devicedetection/pom.xml b/extra/modules/fiftyone-devicedetection/pom.xml index d3fe4db34a1..762a62cfcfc 100644 --- a/extra/modules/fiftyone-devicedetection/pom.xml +++ b/extra/modules/fiftyone-devicedetection/pom.xml @@ -5,7 +5,11 @@ org.prebid.server.hooks.modules all-modules +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) fiftyone-devicedetection diff --git a/extra/modules/greenbids-real-time-data/pom.xml b/extra/modules/greenbids-real-time-data/pom.xml index 42a147aa40d..957063df634 100644 --- a/extra/modules/greenbids-real-time-data/pom.xml +++ b/extra/modules/greenbids-real-time-data/pom.xml @@ -4,7 +4,11 @@ org.prebid.server.hooks.modules all-modules +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) greenbids-real-time-data diff --git a/extra/modules/live-intent-omni-channel-identity/pom.xml b/extra/modules/live-intent-omni-channel-identity/pom.xml index 01acfc756d9..fc3a03e6526 100644 --- a/extra/modules/live-intent-omni-channel-identity/pom.xml +++ b/extra/modules/live-intent-omni-channel-identity/pom.xml @@ -4,7 +4,11 @@ org.prebid.server.hooks.modules all-modules +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) live-intent-omni-channel-identity diff --git a/extra/modules/optable-targeting/pom.xml b/extra/modules/optable-targeting/pom.xml index 37e24d92e0f..23127001be2 100644 --- a/extra/modules/optable-targeting/pom.xml +++ b/extra/modules/optable-targeting/pom.xml @@ -5,7 +5,11 @@ org.prebid.server.hooks.modules all-modules +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) optable-targeting diff --git a/extra/modules/ortb2-blocking/pom.xml b/extra/modules/ortb2-blocking/pom.xml index 0bc6f9a53cd..2bb2b3f57d9 100644 --- a/extra/modules/ortb2-blocking/pom.xml +++ b/extra/modules/ortb2-blocking/pom.xml @@ -5,7 +5,11 @@ org.prebid.server.hooks.modules all-modules +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) ortb2-blocking diff --git a/extra/modules/pb-request-correction/pom.xml b/extra/modules/pb-request-correction/pom.xml index c9b01a77b38..d489ebb6b96 100644 --- a/extra/modules/pb-request-correction/pom.xml +++ b/extra/modules/pb-request-correction/pom.xml @@ -5,7 +5,11 @@ org.prebid.server.hooks.modules all-modules +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) pb-request-correction diff --git a/extra/modules/pb-response-correction/pom.xml b/extra/modules/pb-response-correction/pom.xml index b450186eaf9..c49b9aa51d2 100644 --- a/extra/modules/pb-response-correction/pom.xml +++ b/extra/modules/pb-response-correction/pom.xml @@ -5,7 +5,11 @@ org.prebid.server.hooks.modules all-modules +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) pb-response-correction diff --git a/extra/modules/pb-richmedia-filter/pom.xml b/extra/modules/pb-richmedia-filter/pom.xml index 11826a69364..bc55cec48dc 100644 --- a/extra/modules/pb-richmedia-filter/pom.xml +++ b/extra/modules/pb-richmedia-filter/pom.xml @@ -5,7 +5,11 @@ org.prebid.server.hooks.modules all-modules +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) pb-richmedia-filter diff --git a/extra/modules/pom.xml b/extra/modules/pom.xml index 228580c9b4e..31d9649ff0e 100644 --- a/extra/modules/pom.xml +++ b/extra/modules/pom.xml @@ -5,7 +5,11 @@ org.prebid prebid-server-aggregator +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) ../../extra/pom.xml diff --git a/extra/modules/wurfl-devicedetection/pom.xml b/extra/modules/wurfl-devicedetection/pom.xml index 30444ffce20..0a1786d5fc8 100644 --- a/extra/modules/wurfl-devicedetection/pom.xml +++ b/extra/modules/wurfl-devicedetection/pom.xml @@ -5,7 +5,11 @@ org.prebid.server.hooks.modules all-modules +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) wurfl-devicedetection diff --git a/extra/pom.xml b/extra/pom.xml index cfee5b70987..06e9a9bcf7f 100644 --- a/extra/pom.xml +++ b/extra/pom.xml @@ -4,7 +4,11 @@ org.prebid prebid-server-aggregator +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) pom @@ -33,8 +37,13 @@ 10.17.0 +<<<<<<< HEAD 3.5.5 4.5.20 +======= + 3.4.5 + 4.5.14 +>>>>>>> 04d9d4a13 (Initial commit) 2.0.1.Final 4.4 1.27.1 @@ -50,7 +59,11 @@ 1.3.4 0.16.0 2.0.10 +<<<<<<< HEAD 3.2.4 +======= + 3.2.3 +>>>>>>> 04d9d4a13 (Initial commit) 4.2.1 3.25.6 ${protobuf.version} diff --git a/mvnw.cmd b/mvnw.cmd index b150b91ed50..cd647dfaf52 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -1,3 +1,4 @@ +<<<<<<< HEAD <# : batch portion @REM ---------------------------------------------------------------------------- @REM Licensed to the Apache Software Foundation (ASF) under one @@ -147,3 +148,154 @@ try { } Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" +======= +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" +>>>>>>> 04d9d4a13 (Initial commit) diff --git a/out/artifacts/prebid_server_jar/prebid-server.jar b/out/artifacts/prebid_server_jar/prebid-server.jar new file mode 100644 index 00000000000..e356851d552 Binary files /dev/null and b/out/artifacts/prebid_server_jar/prebid-server.jar differ diff --git a/pom.xml b/pom.xml index 5d682c15576..b4953af7865 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,11 @@ org.prebid prebid-server-aggregator +<<<<<<< HEAD 3.33.0-SNAPSHOT +======= + 3.32.0-SNAPSHOT +>>>>>>> 04d9d4a13 (Initial commit) extra/pom.xml diff --git a/sample/configs/prebid-config.yaml b/sample/configs/prebid-config.yaml index 0d8b5c90ff2..3ada6c8b760 100644 --- a/sample/configs/prebid-config.yaml +++ b/sample/configs/prebid-config.yaml @@ -1,4 +1,200 @@ status-response: "ok" +<<<<<<< HEAD +======= + +spring: + main: + banner-mode: "off" + +# Configuración de valores por defecto para adaptadores +adapter-defaults: + enabled: false + ortb-version: "2.5" + ortb: + multiformat-supported: true + pbs-enforces-ccpa: true + modifying-vast-xml-allowed: true + debug: + allow: true + +# Configuración de Vert.x +vertx: + worker-pool-size: 20 + uploads-dir: file-uploads + init-timeout-ms: 5000 + enable-per-client-endpoint-metrics: false + +# Configuración de métricas +metrics: + prefix: prebid + jmx: + enabled: false + +# URL externa (requerida por algunos bidders) +external-url: http://localhost:8080 + +# Configuración de identificación del servidor +host-id: localhost +datacenter-region: local +vendor: local +system: system +sub-system: subSystem +infra: infra +data-center: dataCenter +profile: profile + +# Configuración de host-cookie (IMPORTANTE: esta configuración faltaba) +host-cookie: + opt-out-url: http://prebid.org/optout + opt-in-url: http://prebid.org/optin + ttl-days: 90 + max-cookie-size-bytes: 4096 + +# Configuración de IPv6 (requerida para ipAddressHelper) +ipv6: + always-mask-right: 56 + anon-left-mask-bits: 56 + private-networks: "fc00::/7,fe80::/10,::1/128" + +# Configuración de CCPA (California Consumer Privacy Act) +ccpa: + enforce: true + +# Configuración completa de GDPR +gdpr: + enabled: true + default-value: 0 + eea-countries: "at,bg,be,cy,cz,dk,ee,fi,fr,de,gr,hu,ie,it,lv,lt,lu,mt,nl,pl,pt,ro,sk,si,es,se,gb,is,no,li" + vendorlist: + default-timeout-ms: 2000 + v2: + http-endpoint-template: "https://vendor-list.consensu.org/v2/archives/vendor-list-v{VERSION}.json" + refresh-missing-list-period-ms: 3600000 + cache-dir: /var/tmp/vendor2 + deprecated: false + retry-policy: + exponential-backoff: + delay-millis: 100 + max-delay-millis: 1000 + factor: 2.0 + jitter: 0.1 + v3: + http-endpoint-template: "https://vendor-list.consensu.org/v3/archives/vendor-list-v{VERSION}.json" + refresh-missing-list-period-ms: 3600000 + cache-dir: /var/tmp/vendor3 + deprecated: false + retry-policy: + exponential-backoff: + delay-millis: 100 + max-delay-millis: 1000 + factor: 2.0 + jitter: 0.1 + purposes: + p1: + enforce-purpose: full + enforce-vendors: true + p2: + enforce-purpose: full + enforce-vendors: true + p3: + enforce-purpose: full + enforce-vendors: true + p4: + enforce-purpose: full + enforce-vendors: true + p5: + enforce-purpose: full + enforce-vendors: true + p6: + enforce-purpose: full + enforce-vendors: true + p7: + enforce-purpose: full + enforce-vendors: true + p8: + enforce-purpose: full + enforce-vendors: true + p9: + enforce-purpose: full + enforce-vendors: true + p10: + enforce-purpose: full + enforce-vendors: true + special-features: + sf1: + enforce: true + sf2: + enforce: true + +# Configuración de LMT (Limit Ad Tracking) +lmt: + enforce: true + +# Configuración completa de auction +auction: + ad-server-currency: USD + blocklisted-accounts: [] + blocklisted-apps: [] + biddertmax: + min: 50 + max: 5000 + percent: 100 + tmax-upstream-response-time: 30 + stored-requests-timeout-ms: 100 + timeout-notification: + timeout-ms: 200 + log-result: false + log-failure-only: false + log-sampling-rate: 0.0 + max-request-size: 262144 + generate-bid-id: false + cache: + expected-request-time-ms: 10 + only-winning-bids: false + validations: + banner-creative-max-size: skip + secure-markup: skip + host-schain-node: [] + category-mapping-enabled: false + strict-app-site-dooh: true + +# Configuración de video +video: + stored-request-required: false + stored-requests-timeout-ms: 90 + +# Configuración de eventos +event: + default-timeout-ms: 1000 + +# Configuración de setuid +setuid: + default-timeout-ms: 2000 + number-of-uid-cookies: 1 + +# Configuración de vtrack +vtrack: + default-timeout-ms: 2000 + allow-unknown-bidder: true + modify-vast-for-unknown-bidder: true + +# Configuración de cookie-sync +cookie-sync: + default-limit: 8 + coop-sync: + default: true + default-timeout-ms: 2000 + +# Configuración de logging (necesaria para sampling-rate) +logging: + sampling-rate: 0.01 + http-interaction: + max-limit: 10000 + change-level: + max-duration-ms: 60000 + +# Configuración de adaptadores +>>>>>>> 04d9d4a13 (Initial commit) adapters: appnexus: enabled: true @@ -8,22 +204,45 @@ adapters: enabled: true pubmatic: enabled: true +<<<<<<< HEAD rubicon: enabled: true metrics: prefix: prebid +======= + bidmatic: + enabled: true + rubicon: + enabled: true + mockbider: + enabled: true + alvads: + enabled: true +# Configuración de cache +>>>>>>> 04d9d4a13 (Initial commit) cache: scheme: http host: localhost path: /cache query: uuid= +<<<<<<< HEAD settings: enforce-valid-account: false generate-storedrequest-bidrequest-id: true +======= + +# Configuración de settings (IMPORTANTE: faltaba targeting.truncate-attr-chars) +settings: + enforce-valid-account: false + generate-storedrequest-bidrequest-id: true + targeting: + truncate-attr-chars: 20 +>>>>>>> 04d9d4a13 (Initial commit) filesystem: settings-filename: sample/configs/sample-app-settings.yaml stored-requests-dir: sample stored-imps-dir: sample +<<<<<<< HEAD profiles-dir: sample stored-responses-dir: sample categories-dir: @@ -34,9 +253,149 @@ gdpr: cache-dir: /var/tmp/vendor2 v3: cache-dir: /var/tmp/vendor3 +======= + stored-responses-dir: sample + categories-dir: + in-memory-cache: + notification-endpoints-enabled: false + default-account-config: > + { + "auction": { + "price-floors": { + "enabled": true, + "fetch": { + "enabled": false, + "timeout-ms": 5000, + "max-rules": 0, + "max-schema-dims": 5, + "max-file-size-kb": 200, + "max-age-sec": 86400, + "period-sec": 3600 + }, + "enforce-floors-rate": 100, + "adjust-for-bid-adjustment": true, + "enforce-deal-floors": true, + "use-dynamic-data": true, + "max-rules": 100, + "max-schema-dims": 3 + } + } + } + +# Configuración del convertidor de monedas +currency-converter: + external-rates: + enabled: false + url: https://currencies.prebid.org + default-timeout-ms: 4000 + refresh-period-ms: 900000 + +# Configuración completa de admin endpoints +>>>>>>> 04d9d4a13 (Initial commit) admin-endpoints: logging-changelevel: enabled: true path: /logging/changelevel on-application-port: true protected: false +<<<<<<< HEAD +======= + version: + enabled: true + path: /version + on-application-port: true + protected: false + collected-metrics: + enabled: false + path: /collected-metrics + on-application-port: true + protected: false + currency-rates: + enabled: false + path: /currency-rates + on-application-port: true + protected: false + storedrequest: + enabled: false + path: /storedrequest + on-application-port: true + protected: false + storedrequest-amp: + enabled: false + path: /storedrequest-amp + on-application-port: true + protected: false + cache-invalidation: + enabled: false + path: /cache-invalidation + on-application-port: true + protected: false + logging-httpinteraction: + enabled: false + path: /logging-httpinteraction + on-application-port: true + protected: false + tracelog: + enabled: false + path: /tracelog + on-application-port: true + protected: false + +# Configuración del puerto admin +admin: + port: 8060 + +# Configuración de geolocalización +geolocation: + enabled: false + +# Configuración de health checks +health-check: + geolocation: + enabled: false + refresh-period-ms: 30000 + database: + enabled: false + refresh-period-ms: 30000 + +# Configuración básica del servidor +server: + max-initial-line-length: 8092 + max-headers-size: 16384 + ssl: false + jks-path: + jks-password: + unix-socket: + enabled: false + path: + server-instances: 1 + http: + enabled: true + port: 8080 + server-instances: 1 + cpu-load-monitoring: + enabled: false + measurement-interval-ms: 60000 + idle-timeout: 10 + +# Configuración de HTTP client +http-client: + max-pool-size: 4000 + idle-timeout-ms: 0 + pool-cleaner-period-ms: 1000 + connect-timeout-ms: 2500 + use-compression: true + max-redirects: 0 + ssl: false + jks-path: + jks-password: + +# reCAPTCHA (para algunos endpoints específicos) +recaptcha-url: https://www.google.com/recaptcha/api/siteverify +recaptcha-secret: secret_value + +# Configuración de analytics (opcional) +analytics: + global: + adapters: logAnalytics +>>>>>>> 04d9d4a13 (Initial commit) diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index aec0c82831b..4bec4a0cc2b 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -25,7 +25,10 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.prebid.server.auction.categorymapping.CategoryMappingService; +<<<<<<< HEAD import org.prebid.server.auction.externalortb.StoredRequestProcessor; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.AuctionParticipation; import org.prebid.server.auction.model.BidInfo; diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java index d9561ccc868..489f6a353b4 100644 --- a/src/main/java/org/prebid/server/auction/ExchangeService.java +++ b/src/main/java/org/prebid/server/auction/ExchangeService.java @@ -23,7 +23,10 @@ import org.apache.commons.collections4.map.CaseInsensitiveMap; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +<<<<<<< HEAD import org.apache.commons.lang3.tuple.Pair; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.activity.Activity; import org.prebid.server.activity.ComponentType; import org.prebid.server.activity.infrastructure.ActivityInfrastructure; @@ -32,7 +35,10 @@ import org.prebid.server.activity.infrastructure.payload.impl.BidRequestActivityInvocationPayload; import org.prebid.server.auction.aliases.AlternateBidderCodesConfig; import org.prebid.server.auction.aliases.BidderAliases; +<<<<<<< HEAD import org.prebid.server.auction.externalortb.StoredResponseProcessor; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.mediatypeprocessor.MediaTypeProcessingResult; import org.prebid.server.auction.mediatypeprocessor.MediaTypeProcessor; import org.prebid.server.auction.model.AuctionContext; @@ -103,6 +109,10 @@ import org.prebid.server.util.ListUtil; import org.prebid.server.util.PbsUtil; import org.prebid.server.util.StreamUtil; +<<<<<<< HEAD +======= +import org.apache.commons.lang3.tuple.Pair; +>>>>>>> 04d9d4a13 (Initial commit) import java.math.BigDecimal; import java.time.Clock; @@ -571,10 +581,17 @@ private static List firstPartyDataBidders(ExtRequest requestExt) { } private Map> prepareUsersAndDevices(List bidders, +<<<<<<< HEAD AuctionContext context, BidderAliases aliases, Map biddersToConfigs, Map> eidPermissions) { +======= + AuctionContext context, + BidderAliases aliases, + Map biddersToConfigs, + Map> eidPermissions) { +>>>>>>> 04d9d4a13 (Initial commit) final BidRequest bidRequest = context.getBidRequest(); final List firstPartyDataBidders = firstPartyDataBidders(bidRequest.getExt()); diff --git a/src/main/java/org/prebid/server/auction/SkippedAuctionService.java b/src/main/java/org/prebid/server/auction/SkippedAuctionService.java index 78e87a44799..51a2dc823ed 100644 --- a/src/main/java/org/prebid/server/auction/SkippedAuctionService.java +++ b/src/main/java/org/prebid/server/auction/SkippedAuctionService.java @@ -7,7 +7,10 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.StringUtils; +<<<<<<< HEAD import org.prebid.server.auction.externalortb.StoredResponseProcessor; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.StoredResponseResult; import org.prebid.server.bidder.model.BidderError; diff --git a/src/main/java/org/prebid/server/auction/StoredRequestProcessor.java b/src/main/java/org/prebid/server/auction/StoredRequestProcessor.java new file mode 100644 index 00000000000..3729c5da661 --- /dev/null +++ b/src/main/java/org/prebid/server/auction/StoredRequestProcessor.java @@ -0,0 +1,395 @@ +package org.prebid.server.auction; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Video; +import io.vertx.core.Future; +import io.vertx.core.file.FileSystem; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.prebid.server.auction.model.AuctionStoredResult; +import org.prebid.server.exception.InvalidRequestException; +import org.prebid.server.exception.InvalidStoredImpException; +import org.prebid.server.exception.InvalidStoredRequestException; +import org.prebid.server.execution.timeout.Timeout; +import org.prebid.server.execution.timeout.TimeoutFactory; +import org.prebid.server.identity.IdGenerator; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.json.JsonMerger; +import org.prebid.server.metric.Metrics; +import org.prebid.server.proto.openrtb.ext.request.ExtImp; +import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtStoredRequest; +import org.prebid.server.settings.ApplicationSettings; +import org.prebid.server.settings.model.StoredDataResult; +import org.prebid.server.settings.model.VideoStoredDataResult; +import org.prebid.server.util.ObjectUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Executes stored request processing. + */ +public class StoredRequestProcessor { + + private static final String OVERRIDE_BID_REQUEST_ID_TEMPLATE = "{{UUID}}"; + + private final long defaultTimeout; + private final BidRequest defaultBidRequest; + private final boolean generateBidRequestId; + private final ApplicationSettings applicationSettings; + private final IdGenerator idGenerator; + private final Metrics metrics; + private final TimeoutFactory timeoutFactory; + private final JacksonMapper mapper; + private final JsonMerger jsonMerger; + + public StoredRequestProcessor(long defaultTimeout, + String defaultBidRequestPath, + boolean generateBidRequestId, + FileSystem fileSystem, + ApplicationSettings applicationSettings, + IdGenerator idGenerator, + Metrics metrics, + TimeoutFactory timeoutFactory, + JacksonMapper mapper, + JsonMerger jsonMerger) { + + this.defaultTimeout = defaultTimeout; + this.defaultBidRequest = readBidRequest( + defaultBidRequestPath, Objects.requireNonNull(fileSystem), Objects.requireNonNull(mapper)); + this.generateBidRequestId = generateBidRequestId; + this.applicationSettings = Objects.requireNonNull(applicationSettings); + this.idGenerator = Objects.requireNonNull(idGenerator); + this.metrics = Objects.requireNonNull(metrics); + this.timeoutFactory = Objects.requireNonNull(timeoutFactory); + this.mapper = Objects.requireNonNull(mapper); + this.jsonMerger = Objects.requireNonNull(jsonMerger); + } + + public Future processAuctionRequest(String accountId, BidRequest bidRequest) { + return processAuctionStoredRequest(accountId, bidRequest) + .onFailure(cause -> updateInvalidStoredResultMetrics(accountId, cause)) + .recover(StoredRequestProcessor::stripToInvalidRequestException); + } + + private Future processAuctionStoredRequest(String accountId, BidRequest bidRequest) { + final Map bidRequestToStoredRequestId; + final Map impToStoredRequestId; + try { + bidRequestToStoredRequestId = mapStoredRequestHolderToStoredRequestId( + Collections.singletonList(bidRequest), StoredRequestProcessor::getStoredRequestIdFromBidRequest); + + impToStoredRequestId = mapStoredRequestHolderToStoredRequestId( + bidRequest.getImp(), this::getStoredRequestIdFromImp); + } catch (InvalidStoredRequestException | InvalidStoredImpException e) { + return Future.failedFuture(e); + } + + final Set requestIds = new HashSet<>(bidRequestToStoredRequestId.values()); + final Set impIds = new HashSet<>(impToStoredRequestId.values()); + if (requestIds.isEmpty() && impIds.isEmpty()) { + return Future.succeededFuture(AuctionStoredResult.of(false, bidRequest)); + } + + final Future storedDataFuture = + applicationSettings.getStoredData(accountId, requestIds, impIds, timeout(bidRequest)) + .onSuccess(storedDataResult -> updateStoredResultMetrics(storedDataResult, requestIds, impIds)); + + return storedRequestsToBidRequest( + storedDataFuture, bidRequest, bidRequestToStoredRequestId.get(bidRequest), impToStoredRequestId) + .map(this::generateBidRequestIdForApp) + .map(resolvedRequest -> AuctionStoredResult.of(true, resolvedRequest)); + } + + public Future processAmpRequest(String accountId, String ampRequestId, BidRequest bidRequest) { + return processAmpStoredRequest(accountId, ampRequestId, bidRequest) + .onFailure(cause -> updateInvalidStoredResultMetrics(accountId, cause)) + .recover(StoredRequestProcessor::stripToInvalidRequestException); + } + + private Future processAmpStoredRequest(String accountId, String ampRequestId, BidRequest bidRequest) { + final Future ampStoredDataFuture = applicationSettings.getAmpStoredData( + accountId, Collections.singleton(ampRequestId), Collections.emptySet(), timeout(bidRequest)) + .onSuccess(storedDataResult -> updateStoredResultMetrics( + storedDataResult, Collections.singleton(ampRequestId), Collections.emptySet())); + + return storedRequestsToBidRequest(ampStoredDataFuture, bidRequest, ampRequestId, Collections.emptyMap()) + .map(this::generateBidRequestId); + } + + Future videoStoredDataResult(String accountId, + List imps, + List errors, + Timeout timeout) { + + return videoStoredDataResultInternal(accountId, imps, errors, timeout) + .onFailure(cause -> updateInvalidStoredResultMetrics(accountId, cause)) + .recover(StoredRequestProcessor::stripToInvalidRequestException); + } + + private Future videoStoredDataResultInternal(String accountId, + List imps, + List errors, + Timeout timeout) { + + final Map impToStoredRequestId; + try { + impToStoredRequestId = mapStoredRequestHolderToStoredRequestId(imps, this::getStoredRequestIdFromImp); + } catch (InvalidStoredImpException e) { + return Future.failedFuture(e); + } + + final Map storedIdToImpId = impToStoredRequestId.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getValue, impIdToStoredId -> impIdToStoredId.getKey().getId())); + + return applicationSettings.getStoredData(accountId, Collections.emptySet(), storedIdToImpId.keySet(), timeout) + .map(storedDataResult -> makeVideoStoredDataResult(storedDataResult, storedIdToImpId, errors)); + } + + private void updateInvalidStoredResultMetrics(String accountId, Throwable cause) { + if (cause instanceof InvalidStoredRequestException) { + metrics.updateAccountRequestRejectedByInvalidStoredRequestMetrics(accountId); + } else if (cause instanceof InvalidStoredImpException) { + metrics.updateAccountRequestRejectedByInvalidStoredImpMetrics(accountId); + } + } + + private static Future stripToInvalidRequestException(Throwable cause) { + return Future.failedFuture(new InvalidRequestException( + "Stored request processing failed: " + cause.getMessage())); + } + + private void updateStoredResultMetrics(StoredDataResult storedDataResult, + Set requestIds, + Set impIds) { + + requestIds.forEach( + id -> metrics.updateStoredRequestMetric(storedDataResult.getStoredIdToRequest().containsKey(id))); + + impIds.forEach( + id -> metrics.updateStoredImpsMetric(storedDataResult.getStoredIdToImp().containsKey(id))); + } + + private static BidRequest readBidRequest(String defaultBidRequestPath, + FileSystem fileSystem, + JacksonMapper mapper) { + + return StringUtils.isNotBlank(defaultBidRequestPath) + ? mapper.decodeValue(fileSystem.readFileBlocking(defaultBidRequestPath), BidRequest.class) + : null; + } + + private VideoStoredDataResult makeVideoStoredDataResult(StoredDataResult storedDataResult, + Map storedIdToImpId, + List errors) { + + final Map storedIdToStoredImp = storedDataResult.getStoredIdToImp(); + final Map impIdToStoredVideo = new HashMap<>(); + + for (Map.Entry storedIdToImpIdEntry : storedIdToImpId.entrySet()) { + final String storedId = storedIdToImpIdEntry.getKey(); + final String storedImp = storedIdToStoredImp.get(storedId); + if (storedImp == null) { + errors.add("No stored Imp for stored id " + storedId); + continue; + } + + final String impId = storedIdToImpIdEntry.getValue(); + final Video video = parseVideoFromImp(storedImp); + if (video == null) { + errors.add("No stored video found for Imp with id " + impId); + continue; + } + + impIdToStoredVideo.put(impId, video); + } + + return VideoStoredDataResult.of(impIdToStoredVideo, errors); + } + + private Video parseVideoFromImp(String storedJson) { + if (StringUtils.isNotBlank(storedJson)) { + try { + final Imp imp = mapper.mapper().readValue(storedJson, Imp.class); + return imp.getVideo(); + } catch (JsonProcessingException e) { + return null; + } + } + return null; + } + + private Future storedRequestsToBidRequest(Future storedDataFuture, + BidRequest bidRequest, + String storedBidRequestId, + Map impsToStoredRequestId) { + + return storedDataFuture + .compose(result -> !result.getErrors().isEmpty() + ? Future.failedFuture(new InvalidStoredRequestException(result.getErrors())) + : Future.succeededFuture(result)) + .map(result -> mergeBidRequestAndImps( + bidRequest, storedBidRequestId, impsToStoredRequestId, result)); + } + + /** + * Runs {@link BidRequest} and {@link Imp}s merge processes. + *

+ * The merging priority is: original request > stored request > default request + */ + private BidRequest mergeBidRequestAndImps(BidRequest bidRequest, + String storedRequestId, + Map impToStoredId, + StoredDataResult storedDataResult) { + + final BidRequest mergedWithStoredRequest = mergeBidRequest(bidRequest, storedRequestId, storedDataResult); + + final BidRequest mergedWithDefaultRequest = mergeDefaultRequest(mergedWithStoredRequest); + + return mergeImps(mergedWithDefaultRequest, impToStoredId, storedDataResult); + } + + private BidRequest mergeDefaultRequest(BidRequest bidRequest) { + return jsonMerger.merge(bidRequest, defaultBidRequest, BidRequest.class); + } + + /** + * Merges original request with request from stored request source. Values from original request + * has higher priority than stored request values. + */ + private BidRequest mergeBidRequest(BidRequest originalRequest, + String storedRequestId, + StoredDataResult storedDataResult) { + + final String storedRequest = storedDataResult.getStoredIdToRequest().get(storedRequestId); + return StringUtils.isNotBlank(storedRequestId) + ? jsonMerger.merge(originalRequest, storedRequest, storedRequestId, BidRequest.class) + : originalRequest; + } + + /** + * Merges {@link Imp}s from original request with Imps from stored request source. Values from original request + * has higher priority than stored request values. + */ + private BidRequest mergeImps(BidRequest bidRequest, + Map impToStoredId, + StoredDataResult storedDataResult) { + + if (impToStoredId.isEmpty()) { + return bidRequest; + } + final List mergedImps = new ArrayList<>(bidRequest.getImp()); + for (int i = 0; i < mergedImps.size(); i++) { + final Imp imp = mergedImps.get(i); + final String storedRequestId = impToStoredId.get(imp); + if (storedRequestId != null) { + final String storedImp = storedDataResult.getStoredIdToImp().get(storedRequestId); + final Imp mergedImp = jsonMerger.merge(imp, storedImp, storedRequestId, Imp.class); + mergedImps.set(i, mergedImp); + } + } + return bidRequest.toBuilder().imp(mergedImps).build(); + } + + private BidRequest generateBidRequestIdForApp(BidRequest bidRequest) { + return bidRequest.getApp() != null + ? generateBidRequestId(bidRequest) + : bidRequest; + } + + private BidRequest generateBidRequestId(BidRequest bidRequest) { + return generateBidRequestId || Objects.equals(bidRequest.getId(), OVERRIDE_BID_REQUEST_ID_TEMPLATE) + ? bidRequest.toBuilder().id(idGenerator.generateId()).build() + : bidRequest; + } + + /** + * Maps object to its StoredRequestId if exists. If object's extension contains storedRequest field, expected + * that it includes id too, in another case error about missed id in stored request will be added to error list. + * Gathers all errors into list, and in case if it is not empty, throws {@link InvalidRequestException} with list + * of errors. + */ + private static Map mapStoredRequestHolderToStoredRequestId( + List storedRequestHolders, + Function storedRequestIdExtractor) { + + if (CollectionUtils.isEmpty(storedRequestHolders)) { + return Collections.emptyMap(); + } + + final Map holderToPreBidRequest = new HashMap<>(); + + for (K storedRequestHolder : storedRequestHolders) { + final String storedRequestId = storedRequestIdExtractor.apply(storedRequestHolder); + if (storedRequestId != null) { + holderToPreBidRequest.put(storedRequestHolder, storedRequestId); + } + } + + return holderToPreBidRequest; + } + + private static String getStoredRequestIdFromBidRequest(BidRequest bidRequest) { + final ExtRequestPrebid prebid = ObjectUtil.getIfNotNull(bidRequest.getExt(), ExtRequest::getPrebid); + final ExtStoredRequest extStoredRequest = ObjectUtil.getIfNotNull(prebid, ExtRequestPrebid::getStoredrequest); + + if (extStoredRequest == null) { + return null; + } + + final String storedRequestId = extStoredRequest.getId(); + if (storedRequestId == null) { + throw new InvalidStoredRequestException("Id is not found in storedRequest"); + } + + return storedRequestId; + } + + private String getStoredRequestIdFromImp(Imp imp) { + if (imp.getExt() == null) { + return null; + } + + final ExtImp extImp; + try { + extImp = mapper.mapper().treeToValue(imp.getExt(), ExtImp.class); + } catch (JsonProcessingException e) { + throw new InvalidStoredImpException( + "Incorrect Imp extension format for Imp with id " + imp.getId() + ": " + e.getMessage()); + } + + final ExtStoredRequest extStoredRequest = ObjectUtil.getIfNotNull( + extImp.getPrebid(), ExtImpPrebid::getStoredrequest); + if (extStoredRequest == null) { + return null; + } + + final String storedRequestId = extStoredRequest.getId(); + if (storedRequestId == null) { + throw new InvalidStoredImpException("Id is not found in storedRequest"); + } + + return storedRequestId; + } + + /** + * If the request defines tmax explicitly, then it is returned as is. Otherwise, default timeout is returned. + */ + private Timeout timeout(BidRequest bidRequest) { + final Long tmax = bidRequest.getTmax(); + return timeoutFactory.create(tmax != null && tmax > 0 ? tmax : defaultTimeout); + } +} diff --git a/src/main/java/org/prebid/server/auction/StoredResponseProcessor.java b/src/main/java/org/prebid/server/auction/StoredResponseProcessor.java new file mode 100644 index 00000000000..2257320ef69 --- /dev/null +++ b/src/main/java/org/prebid/server/auction/StoredResponseProcessor.java @@ -0,0 +1,484 @@ +package org.prebid.server.auction; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.response.Bid; +import com.iab.openrtb.response.SeatBid; +import io.vertx.core.Future; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.map.CaseInsensitiveMap; +import org.apache.commons.lang3.StringUtils; +import org.prebid.server.auction.model.AuctionParticipation; +import org.prebid.server.auction.model.BidRejectionTracker; +import org.prebid.server.auction.model.BidderRequest; +import org.prebid.server.auction.model.BidderResponse; +import org.prebid.server.auction.model.StoredResponseResult; +import org.prebid.server.auction.model.Tuple2; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderSeatBid; +import org.prebid.server.exception.InvalidRequestException; +import org.prebid.server.exception.PreBidException; +import org.prebid.server.execution.timeout.Timeout; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.proto.openrtb.ext.request.ExtImp; +import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtStoredAuctionResponse; +import org.prebid.server.proto.openrtb.ext.request.ExtStoredBidResponse; +import org.prebid.server.proto.openrtb.ext.response.BidType; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; +import org.prebid.server.settings.ApplicationSettings; +import org.prebid.server.settings.model.StoredResponseDataResult; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Resolves stored response data retrieving and BidderResponse merging processes. + */ +public class StoredResponseProcessor { + + private static final String PREBID_EXT = "prebid"; + private static final String DEFAULT_BID_CURRENCY = "USD"; + private static final String PBS_IMPID_MACRO = "##PBSIMPID##"; + + private static final TypeReference> SEATBID_LIST_TYPE = + new TypeReference<>() { + }; + + private final ApplicationSettings applicationSettings; + private final JacksonMapper mapper; + + public StoredResponseProcessor(ApplicationSettings applicationSettings, + JacksonMapper mapper) { + + this.applicationSettings = Objects.requireNonNull(applicationSettings); + this.mapper = Objects.requireNonNull(mapper); + } + + Future getStoredResponseResult(List imps, Timeout timeout) { + final Map impExtPrebids = getImpsExtPrebid(imps); + final Map impIdsToStoredResponses = getAuctionStoredResponses(impExtPrebids); + final List requiredRequestImps = excludeStoredAuctionResponseImps(imps, impIdsToStoredResponses); + + final Map> impToBidderToStoredBidResponseId = + getStoredBidResponses(impExtPrebids, requiredRequestImps); + + final Set storedResponses = new HashSet<>(impIdsToStoredResponses.values()); + + impToBidderToStoredBidResponseId.values() + .forEach(bidderToStoredResponse -> storedResponses.addAll(bidderToStoredResponse.values())); + + if (storedResponses.isEmpty()) { + return Future.succeededFuture( + StoredResponseResult.of(imps, Collections.emptyList(), Collections.emptyMap())); + } + + return getStoredResponses(storedResponses, timeout) + .recover(exception -> Future.failedFuture(new InvalidRequestException( + "Stored response fetching failed with reason: " + exception.getMessage()))) + .map(storedResponseDataResult -> StoredResponseResult.of( + requiredRequestImps, + convertToSeatBid(storedResponseDataResult, impIdsToStoredResponses), + mapStoredBidResponseIdsToValues( + storedResponseDataResult.getIdToStoredResponses(), + impToBidderToStoredBidResponseId))); + } + + Future getStoredResponseResult(String storedId, Timeout timeout) { + return applicationSettings.getStoredResponses(Collections.singleton(storedId), timeout) + .recover(exception -> Future.failedFuture(new InvalidRequestException( + "Stored response fetching failed with reason: " + exception.getMessage()))) + .map(storedResponseDataResult -> StoredResponseResult.of( + Collections.emptyList(), + convertToSeatBid(storedResponseDataResult), + Collections.emptyMap())); + } + + private Map getImpsExtPrebid(List imps) { + return imps.stream() + .collect(Collectors.toMap(Imp::getId, imp -> getExtImp(imp.getExt(), imp.getId()).getPrebid())); + } + + private ExtImp getExtImp(ObjectNode extImpNode, String impId) { + try { + return mapper.mapper().treeToValue(extImpNode, ExtImp.class); + } catch (JsonProcessingException e) { + throw new InvalidRequestException( + "Error decoding bidRequest.imp.ext for impId = %s : %s".formatted(impId, e.getMessage())); + } + } + + private Map getAuctionStoredResponses(Map extImpPrebids) { + return extImpPrebids.entrySet().stream() + .map(impIdToExtPrebid -> Tuple2.of( + impIdToExtPrebid.getKey(), + extractAuctionStoredResponseId(impIdToExtPrebid.getValue()))) + .filter(impIdToStoredResponseId -> impIdToStoredResponseId.getRight() != null) + .collect(Collectors.toMap(Tuple2::getLeft, Tuple2::getRight)); + } + + private StoredResponse extractAuctionStoredResponseId(ExtImpPrebid extImpPrebid) { + final ExtStoredAuctionResponse storedAuctionResponse = extImpPrebid.getStoredAuctionResponse(); + return Optional.ofNullable(storedAuctionResponse) + .map(ExtStoredAuctionResponse::getSeatBid) + .map(StoredResponse.StoredResponseObject::new) + .or(() -> Optional.ofNullable(storedAuctionResponse) + .map(ExtStoredAuctionResponse::getId) + .map(StoredResponse.StoredResponseId::new)) + .orElse(null); + } + + private List excludeStoredAuctionResponseImps(List imps, + Map impIdToStoredResponse) { + + return imps.stream() + .filter(imp -> !impIdToStoredResponse.containsKey(imp.getId())) + .toList(); + } + + private Map> getStoredBidResponses( + Map extImpPrebids, + List imps) { + + // PBS supports stored bid response only for requests with single impression, but it can be changed in future + if (imps.size() != 1) { + return Collections.emptyMap(); + } + + return extImpPrebids.entrySet().stream() + .filter(impIdToExtPrebid -> + CollectionUtils.isNotEmpty(impIdToExtPrebid.getValue().getStoredBidResponse())) + .collect(Collectors.toMap( + Map.Entry::getKey, + impIdToStoredResponses -> + resolveStoredBidResponse(impIdToStoredResponses.getValue().getStoredBidResponse()))); + } + + private Map resolveStoredBidResponse( + List storedBidResponse) { + + return storedBidResponse.stream() + .collect(Collectors.toMap( + ExtStoredBidResponse::getBidder, + extStoredBidResponse -> new StoredResponse.StoredResponseId(extStoredBidResponse.getId()))); + } + + private Future getStoredResponses(Set storedResponses, Timeout timeout) { + return applicationSettings.getStoredResponses( + storedResponses.stream() + .filter(StoredResponse.StoredResponseId.class::isInstance) + .map(StoredResponse.StoredResponseId.class::cast) + .map(StoredResponse.StoredResponseId::id) + .collect(Collectors.toSet()), + timeout); + } + + private List convertToSeatBid(StoredResponseDataResult storedResponseDataResult, + Map impIdsToStoredResponses) { + + final List resolvedSeatBids = new ArrayList<>(); + final Map idToStoredResponses = storedResponseDataResult.getIdToStoredResponses(); + for (Map.Entry impIdToStoredResponse : impIdsToStoredResponses.entrySet()) { + final String impId = impIdToStoredResponse.getKey(); + final StoredResponse storedResponse = impIdToStoredResponse.getValue(); + final List seatBids = resolveSeatBids(storedResponse, idToStoredResponses, impId); + + validateStoredSeatBid(seatBids); + resolvedSeatBids.addAll(seatBids.stream() + .map(seatBid -> updateSeatBidBids(seatBid, impId)) + .toList()); + } + return mergeSameBidderSeatBid(resolvedSeatBids); + } + + private List convertToSeatBid(StoredResponseDataResult storedResponseDataResult) { + final List resolvedSeatBids = new ArrayList<>(); + final Map idToStoredResponses = storedResponseDataResult.getIdToStoredResponses(); + for (Map.Entry storedIdToImpId : idToStoredResponses.entrySet()) { + final String id = storedIdToImpId.getKey(); + final String rowSeatBid = storedIdToImpId.getValue(); + if (rowSeatBid == null) { + throw new InvalidRequestException( + "Failed to fetch stored auction response for storedAuctionResponse id = %s.".formatted(id)); + } + final List seatBids = parseSeatBid(id, rowSeatBid); + validateStoredSeatBid(seatBids); + resolvedSeatBids.addAll(seatBids); + } + return mergeSameBidderSeatBid(resolvedSeatBids); + } + + private List resolveSeatBids(StoredResponse storedResponse, + Map idToStoredResponses, + String impId) { + + if (storedResponse instanceof StoredResponse.StoredResponseObject storedResponseObject) { + return Collections.singletonList(storedResponseObject.seatBid()); + } + + final String storedResponseId = ((StoredResponse.StoredResponseId) storedResponse).id(); + final String rowSeatBid = idToStoredResponses.get(storedResponseId); + if (rowSeatBid == null) { + throw new InvalidRequestException( + "Failed to fetch stored auction response for impId = %s and storedAuctionResponse id = %s." + .formatted(impId, storedResponseId)); + } + + return parseSeatBid(storedResponseId, rowSeatBid); + } + + private List parseSeatBid(String id, String rowSeatBid) { + try { + return mapper.mapper().readValue(rowSeatBid, SEATBID_LIST_TYPE); + } catch (IOException e) { + throw new InvalidRequestException("Can't parse Json for stored response with id " + id); + } + } + + private void validateStoredSeatBid(List seatBids) { + for (final SeatBid seatBid : seatBids) { + if (StringUtils.isEmpty(seatBid.getSeat())) { + throw new InvalidRequestException("Seat can't be empty in stored response seatBid"); + } + + if (CollectionUtils.isEmpty(seatBid.getBid())) { + throw new InvalidRequestException("There must be at least one bid in stored response seatBid"); + } + } + } + + private SeatBid updateSeatBidBids(SeatBid seatBid, String impId) { + return seatBid.toBuilder().bid(updateBidsWithImpId(seatBid.getBid(), impId)).build(); + } + + private List updateBidsWithImpId(List bids, String impId) { + return bids.stream().map(bid -> updateBidWithImpId(bid, impId)).toList(); + } + + private static Bid updateBidWithImpId(Bid bid, String impId) { + return bid.toBuilder().impid(impId).build(); + } + + private List mergeSameBidderSeatBid(List seatBids) { + return seatBids.stream().collect(Collectors.groupingBy(SeatBid::getSeat, Collectors.toList())) + .entrySet().stream() + .map(bidderToSeatBid -> makeMergedSeatBid(bidderToSeatBid.getKey(), bidderToSeatBid.getValue())) + .toList(); + } + + private SeatBid makeMergedSeatBid(String seat, List storedSeatBids) { + return SeatBid.builder() + .bid(storedSeatBids.stream().map(SeatBid::getBid).flatMap(List::stream).toList()) + .seat(seat) + .ext(storedSeatBids.stream().map(SeatBid::getExt).filter(Objects::nonNull).findFirst().orElse(null)) + .build(); + } + + private Map> mapStoredBidResponseIdsToValues( + Map idToStoredResponses, + Map> impToBidderToStoredBidResponseId) { + + return impToBidderToStoredBidResponseId.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> entry.getValue().entrySet().stream() + .filter(bidderToId -> idToStoredResponses.containsKey(bidderToId.getValue().id())) + .collect(Collectors.toMap( + Map.Entry::getKey, + bidderToId -> idToStoredResponses.get(bidderToId.getValue().id()), + (first, second) -> second, + CaseInsensitiveMap::new)))); + } + + public List updateStoredBidResponse(List auctionParticipations) { + return auctionParticipations.stream() + .map(StoredResponseProcessor::updateStoredBidResponse) + .collect(Collectors.toList()); + } + + private static AuctionParticipation updateStoredBidResponse(AuctionParticipation auctionParticipation) { + final BidderRequest bidderRequest = auctionParticipation.getBidderRequest(); + final BidRequest bidRequest = bidderRequest.getBidRequest(); + + final List imps = bidRequest.getImp(); + // Аor now, Stored Bid Response works only for bid requests with single imp + if (imps.size() > 1 || StringUtils.isEmpty(bidderRequest.getStoredResponse())) { + return auctionParticipation; + } + + final BidderResponse bidderResponse = auctionParticipation.getBidderResponse(); + final BidderSeatBid initialSeatBid = bidderResponse.getSeatBid(); + final BidderSeatBid adjustedSeatBid = updateSeatBid(initialSeatBid, imps.getFirst().getId()); + + return auctionParticipation.with(bidderResponse.with(adjustedSeatBid)); + } + + private static BidderSeatBid updateSeatBid(BidderSeatBid bidderSeatBid, String impId) { + final List bids = bidderSeatBid.getBids().stream() + .map(bidderBid -> resolveBidImpId(bidderBid, impId)) + .collect(Collectors.toList()); + + return bidderSeatBid.with(bids); + } + + private static BidderBid resolveBidImpId(BidderBid bidderBid, String impId) { + final Bid bid = bidderBid.getBid(); + final String bidImpId = bid.getImpid(); + if (!StringUtils.contains(bidImpId, PBS_IMPID_MACRO)) { + return bidderBid; + } + + return bidderBid.toBuilder() + .bid(bid.toBuilder().impid(bidImpId.replace(PBS_IMPID_MACRO, impId)).build()) + .build(); + } + + List mergeWithBidderResponses(List auctionParticipations, + List storedAuctionResponses, + List imps, + Map bidRejectionTrackers) { + + if (CollectionUtils.isEmpty(storedAuctionResponses)) { + return auctionParticipations; + } + + final Map bidderToAuctionParticipation = auctionParticipations.stream() + .collect(Collectors.toMap(AuctionParticipation::getBidder, Function.identity())); + final Map bidderToSeatBid = storedAuctionResponses.stream() + .collect(Collectors.toMap(SeatBid::getSeat, Function.identity())); + final Map impIdToBidType = imps.stream() + .collect(Collectors.toMap(Imp::getId, this::resolveBidType)); + final Set responseBidders = new HashSet<>(bidderToAuctionParticipation.keySet()); + responseBidders.addAll(bidderToSeatBid.keySet()); + + return responseBidders.stream() + .map(bidder -> updateBidderResponse( + bidderToAuctionParticipation.get(bidder), + bidderToSeatBid.get(bidder), + impIdToBidType)) + .map(auctionParticipation -> restoreStoredBidsFromRejection(bidRejectionTrackers, auctionParticipation)) + .toList(); + } + + private BidType resolveBidType(Imp imp) { + BidType bidType = BidType.banner; + if (imp.getBanner() != null) { + return bidType; + } else if (imp.getVideo() != null) { + bidType = BidType.video; + } else if (imp.getXNative() != null) { + bidType = BidType.xNative; + } else if (imp.getAudio() != null) { + bidType = BidType.audio; + } + return bidType; + } + + private AuctionParticipation updateBidderResponse(AuctionParticipation auctionParticipation, + SeatBid storedSeatBid, + Map impIdToBidType) { + + if (auctionParticipation != null) { + if (auctionParticipation.isRequestBlocked()) { + return auctionParticipation; + } + + final BidderResponse bidderResponse = auctionParticipation.getBidderResponse(); + final BidderSeatBid bidderSeatBid = bidderResponse.getSeatBid(); + final BidderSeatBid updatedSeatBid = storedSeatBid == null + ? bidderSeatBid + : makeBidderSeatBid(bidderSeatBid, storedSeatBid, impIdToBidType); + final BidderResponse updatedBidderResponse = BidderResponse.of(bidderResponse.getBidder(), + updatedSeatBid, bidderResponse.getResponseTime()); + return auctionParticipation.with(updatedBidderResponse); + } else { + final String bidder = storedSeatBid != null ? storedSeatBid.getSeat() : null; + final BidderSeatBid updatedSeatBid = makeBidderSeatBid(null, storedSeatBid, impIdToBidType); + final BidderResponse updatedBidderResponse = BidderResponse.of(bidder, updatedSeatBid, 0); + return AuctionParticipation.builder() + .bidder(bidder) + .bidderResponse(updatedBidderResponse) + .build(); + } + } + + private BidderSeatBid makeBidderSeatBid(BidderSeatBid bidderSeatBid, + SeatBid seatBid, + Map impIdToBidType) { + + final boolean nonNullBidderSeatBid = bidderSeatBid != null; + final String bidCurrency = nonNullBidderSeatBid + ? bidderSeatBid.getBids().stream() + .map(BidderBid::getBidCurrency) + .filter(Objects::nonNull) + .findAny() + .orElse(DEFAULT_BID_CURRENCY) + : DEFAULT_BID_CURRENCY; + final List bidderBids = seatBid != null + ? seatBid.getBid().stream() + .map(bid -> makeBidderBid(bid, bidCurrency, seatBid.getSeat(), impIdToBidType)) + .collect(Collectors.toCollection(ArrayList::new)) + : new ArrayList<>(); + if (nonNullBidderSeatBid) { + bidderBids.addAll(bidderSeatBid.getBids()); + } + return nonNullBidderSeatBid + ? bidderSeatBid.with(bidderBids) + : BidderSeatBid.of(bidderBids); + } + + private BidderBid makeBidderBid(Bid bid, String bidCurrency, String seat, Map impIdToBidType) { + return BidderBid.of(bid, getBidType(bid.getExt(), impIdToBidType.get(bid.getImpid())), seat, bidCurrency); + } + + private BidType getBidType(ObjectNode bidExt, BidType bidType) { + final ObjectNode bidExtPrebid = bidExt != null ? (ObjectNode) bidExt.get(PREBID_EXT) : null; + final ExtBidPrebid extBidPrebid = bidExtPrebid != null ? parseExtBidPrebid(bidExtPrebid) : null; + return extBidPrebid != null ? extBidPrebid.getType() : bidType; + } + + private ExtBidPrebid parseExtBidPrebid(ObjectNode bidExtPrebid) { + try { + return mapper.mapper().treeToValue(bidExtPrebid, ExtBidPrebid.class); + } catch (JsonProcessingException e) { + throw new PreBidException("Error decoding stored response bid.ext.prebid"); + } + } + + private static AuctionParticipation restoreStoredBidsFromRejection( + Map bidRejectionTrackers, + AuctionParticipation auctionParticipation) { + + final BidRejectionTracker bidRejectionTracker = bidRejectionTrackers.get(auctionParticipation.getBidder()); + + if (bidRejectionTracker != null) { + Optional.ofNullable(auctionParticipation.getBidderResponse()) + .map(BidderResponse::getSeatBid) + .map(BidderSeatBid::getBids) + .ifPresent(bidRejectionTracker::restoreFromRejection); + } + + return auctionParticipation; + } + + private sealed interface StoredResponse { + + record StoredResponseId(String id) implements StoredResponse { + } + + record StoredResponseObject(SeatBid seatBid) implements StoredResponse { + } + } +} diff --git a/src/main/java/org/prebid/server/auction/VideoStoredRequestProcessor.java b/src/main/java/org/prebid/server/auction/VideoStoredRequestProcessor.java index f3beeb57e6c..aa136016aae 100644 --- a/src/main/java/org/prebid/server/auction/VideoStoredRequestProcessor.java +++ b/src/main/java/org/prebid/server/auction/VideoStoredRequestProcessor.java @@ -129,9 +129,15 @@ private static BidRequest readBidRequest(String defaultBidRequestPath, : null; } +<<<<<<< HEAD private StoredDataResult updateMetrics(StoredDataResult storedDataResult, Set requestIds, Set impIds) { +======= + private StoredDataResult updateMetrics(StoredDataResult storedDataResult, + Set requestIds, + Set impIds) { +>>>>>>> 04d9d4a13 (Initial commit) requestIds.forEach( id -> metrics.updateStoredRequestMetric(storedDataResult.getStoredIdToRequest().containsKey(id))); @@ -142,7 +148,11 @@ private StoredDataResult updateMetrics(StoredDataResult storedDa return storedDataResult; } +<<<<<<< HEAD private WithPodErrors toBidRequestWithPodErrors(StoredDataResult storedResult, +======= + private WithPodErrors toBidRequestWithPodErrors(StoredDataResult storedResult, +>>>>>>> 04d9d4a13 (Initial commit) BidRequestVideo videoRequest, String storedBidRequestId) { @@ -161,7 +171,11 @@ private WithPodErrors toBidRequestWithPodErrors(StoredDataResult storedDataResult) { +======= + StoredDataResult storedDataResult) { +>>>>>>> 04d9d4a13 (Initial commit) final String storedRequest = storedDataResult.getStoredIdToRequest().get(storedRequestId); if (enforceStoredRequest && StringUtils.isBlank(storedRequest)) { 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 e1c5e4240ce..1940e157c82 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java @@ -23,8 +23,12 @@ import org.prebid.server.auction.ImplicitParametersExtractor; import org.prebid.server.auction.OrtbTypesResolver; import org.prebid.server.auction.PriceGranularity; +<<<<<<< HEAD import org.prebid.server.auction.externalortb.ProfilesProcessor; import org.prebid.server.auction.externalortb.StoredRequestProcessor; +======= +import org.prebid.server.auction.StoredRequestProcessor; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.gpp.AmpGppService; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.ConsentType; @@ -91,7 +95,10 @@ public class AmpRequestFactory { private final Ortb2RequestFactory ortb2RequestFactory; private final StoredRequestProcessor storedRequestProcessor; +<<<<<<< HEAD private final ProfilesProcessor profilesProcessor; +======= +>>>>>>> 04d9d4a13 (Initial commit) private final BidRequestOrtbVersionConversionManager ortbVersionConversionManager; private final AmpGppService gppService; private final OrtbTypesResolver ortbTypesResolver; @@ -105,7 +112,10 @@ public class AmpRequestFactory { public AmpRequestFactory(Ortb2RequestFactory ortb2RequestFactory, StoredRequestProcessor storedRequestProcessor, +<<<<<<< HEAD ProfilesProcessor profilesProcessor, +======= +>>>>>>> 04d9d4a13 (Initial commit) BidRequestOrtbVersionConversionManager ortbVersionConversionManager, AmpGppService gppService, OrtbTypesResolver ortbTypesResolver, @@ -119,7 +129,10 @@ public AmpRequestFactory(Ortb2RequestFactory ortb2RequestFactory, this.ortb2RequestFactory = Objects.requireNonNull(ortb2RequestFactory); this.storedRequestProcessor = Objects.requireNonNull(storedRequestProcessor); +<<<<<<< HEAD this.profilesProcessor = Objects.requireNonNull(profilesProcessor); +======= +>>>>>>> 04d9d4a13 (Initial commit) this.ortbVersionConversionManager = Objects.requireNonNull(ortbVersionConversionManager); this.gppService = Objects.requireNonNull(gppService); this.ortbTypesResolver = Objects.requireNonNull(ortbTypesResolver); @@ -411,7 +424,10 @@ private Future updateBidRequest(AuctionContext auctionContext) { final HttpRequestContext httpRequest = auctionContext.getHttpRequest(); return storedRequestProcessor.processAmpRequest(accountId, storedRequestId, receivedBidRequest) +<<<<<<< HEAD .compose(bidRequest -> profilesProcessor.process(auctionContext, bidRequest)) +======= +>>>>>>> 04d9d4a13 (Initial commit) .map(ortbVersionConversionManager::convertToAuctionSupportedVersion) .map(bidRequest -> gppService.updateBidRequest(bidRequest, auctionContext)) .map(bidRequest -> validateStoredBidRequest(storedRequestId, bidRequest)) diff --git a/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java index d873af3e696..6a32d4913fa 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java @@ -11,8 +11,12 @@ import org.prebid.server.auction.ImplicitParametersExtractor; import org.prebid.server.auction.InterstitialProcessor; import org.prebid.server.auction.OrtbTypesResolver; +<<<<<<< HEAD import org.prebid.server.auction.externalortb.ProfilesProcessor; import org.prebid.server.auction.externalortb.StoredRequestProcessor; +======= +import org.prebid.server.auction.StoredRequestProcessor; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.gpp.AuctionGppService; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.AuctionStoredResult; @@ -41,7 +45,10 @@ public class AuctionRequestFactory { private final long maxRequestSize; private final Ortb2RequestFactory ortb2RequestFactory; private final StoredRequestProcessor storedRequestProcessor; +<<<<<<< HEAD private final ProfilesProcessor profilesProcessor; +======= +>>>>>>> 04d9d4a13 (Initial commit) private final BidRequestOrtbVersionConversionManager ortbVersionConversionManager; private final AuctionGppService gppService; private final CookieDeprecationService cookieDeprecationService; @@ -60,7 +67,10 @@ public class AuctionRequestFactory { public AuctionRequestFactory(long maxRequestSize, Ortb2RequestFactory ortb2RequestFactory, StoredRequestProcessor storedRequestProcessor, +<<<<<<< HEAD ProfilesProcessor profilesProcessor, +======= +>>>>>>> 04d9d4a13 (Initial commit) BidRequestOrtbVersionConversionManager ortbVersionConversionManager, AuctionGppService gppService, CookieDeprecationService cookieDeprecationService, @@ -77,7 +87,10 @@ public AuctionRequestFactory(long maxRequestSize, this.maxRequestSize = maxRequestSize; this.ortb2RequestFactory = Objects.requireNonNull(ortb2RequestFactory); this.storedRequestProcessor = Objects.requireNonNull(storedRequestProcessor); +<<<<<<< HEAD this.profilesProcessor = Objects.requireNonNull(profilesProcessor); +======= +>>>>>>> 04d9d4a13 (Initial commit) this.ortbVersionConversionManager = Objects.requireNonNull(ortbVersionConversionManager); this.gppService = Objects.requireNonNull(gppService); this.cookieDeprecationService = Objects.requireNonNull(cookieDeprecationService); @@ -256,7 +269,11 @@ private Future updateBidRequest(AuctionStoredResult auctionStoredRes final boolean hasStoredBidRequest = auctionStoredResult.hasStoredBidRequest(); +<<<<<<< HEAD return profilesProcessor.process(auctionContext, auctionStoredResult.bidRequest()) +======= + return Future.succeededFuture(auctionStoredResult.bidRequest()) +>>>>>>> 04d9d4a13 (Initial commit) .map(ortbVersionConversionManager::convertToAuctionSupportedVersion) .map(bidRequest -> gppService.updateBidRequest(bidRequest, auctionContext)) .map(bidRequest -> paramsResolver.resolve(bidRequest, auctionContext, ENDPOINT, hasStoredBidRequest)) 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 ac9619f6b83..707fb954ef2 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java @@ -23,11 +23,17 @@ import org.prebid.server.activity.infrastructure.ActivityInfrastructure; import org.prebid.server.activity.infrastructure.creator.ActivityInfrastructureCreator; import org.prebid.server.auction.IpAddressHelper; +<<<<<<< HEAD import org.prebid.server.auction.TimeoutResolver; import org.prebid.server.auction.externalortb.ProfilesProcessor; import org.prebid.server.auction.externalortb.StoredRequestProcessor; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.AuctionStoredResult; +======= +import org.prebid.server.auction.StoredRequestProcessor; +import org.prebid.server.auction.TimeoutResolver; +import org.prebid.server.auction.model.AuctionContext; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.model.IpAddress; import org.prebid.server.auction.model.TimeoutContext; import org.prebid.server.auction.model.debug.DebugContext; @@ -103,7 +109,10 @@ public class Ortb2RequestFactory { private final TimeoutResolver timeoutResolver; private final TimeoutFactory timeoutFactory; private final StoredRequestProcessor storedRequestProcessor; +<<<<<<< HEAD private final ProfilesProcessor profilesProcessor; +======= +>>>>>>> 04d9d4a13 (Initial commit) private final ApplicationSettings applicationSettings; private final IpAddressHelper ipAddressHelper; private final HookStageExecutor hookStageExecutor; @@ -119,7 +128,10 @@ public Ortb2RequestFactory(int timeoutAdjustmentFactor, TimeoutResolver timeoutResolver, TimeoutFactory timeoutFactory, StoredRequestProcessor storedRequestProcessor, +<<<<<<< HEAD ProfilesProcessor profilesProcessor, +======= +>>>>>>> 04d9d4a13 (Initial commit) ApplicationSettings applicationSettings, IpAddressHelper ipAddressHelper, HookStageExecutor hookStageExecutor, @@ -139,7 +151,10 @@ public Ortb2RequestFactory(int timeoutAdjustmentFactor, this.timeoutResolver = Objects.requireNonNull(timeoutResolver); this.timeoutFactory = Objects.requireNonNull(timeoutFactory); this.storedRequestProcessor = Objects.requireNonNull(storedRequestProcessor); +<<<<<<< HEAD this.profilesProcessor = Objects.requireNonNull(profilesProcessor); +======= +>>>>>>> 04d9d4a13 (Initial commit) this.applicationSettings = Objects.requireNonNull(applicationSettings); this.ipAddressHelper = Objects.requireNonNull(ipAddressHelper); this.hookStageExecutor = Objects.requireNonNull(hookStageExecutor); @@ -186,7 +201,11 @@ private Future fetchAccount(AuctionContext auctionContext, boolean isLo final Timeout timeout = auctionContext.getTimeoutContext().getTimeout(); final HttpRequestContext httpRequest = auctionContext.getHttpRequest(); +<<<<<<< HEAD return findAccountIdFrom(auctionContext, bidRequest, isLookupStoredRequest) +======= + return findAccountIdFrom(bidRequest, isLookupStoredRequest) +>>>>>>> 04d9d4a13 (Initial commit) .map(this::validateIfAccountBlocklisted) .compose(accountId -> loadAccount(timeout, httpRequest, accountId)); } @@ -473,6 +492,7 @@ private Timeout timeout(BidRequest bidRequest, long startTime) { return timeoutFactory.create(startTime, timeout); } +<<<<<<< HEAD private Future findAccountIdFrom(AuctionContext auctionContext, BidRequest bidRequest, boolean isLookupStoredRequest) { @@ -520,6 +540,14 @@ private Future accountIdFromStoredRequest(BidRequest bidRequest) { private Future accountIdFromProfiles(AuctionContext auctionContext, BidRequest bidRequest) { return profilesProcessor.process(auctionContext, bidRequest) .map(this::accountIdFromBidRequest); +======= + private Future findAccountIdFrom(BidRequest bidRequest, boolean isLookupStoredRequest) { + final String accountId = accountIdFrom(bidRequest); + return StringUtils.isNotBlank(accountId) || !isLookupStoredRequest + ? Future.succeededFuture(accountId) + : storedRequestProcessor.processAuctionRequest(accountId, bidRequest) + .map(storedAuctionResult -> accountIdFrom(storedAuctionResult.bidRequest())); +>>>>>>> 04d9d4a13 (Initial commit) } private String validateIfAccountBlocklisted(String accountId) { @@ -554,6 +582,43 @@ private Future ensureAccountActive(Account account) { : Future.succeededFuture(account); } +<<<<<<< HEAD +======= + /** + * Extracts publisher id either from {@link BidRequest}.app.publisher or {@link BidRequest}.site.publisher. + * If neither is present returns empty string. + */ + private String accountIdFrom(BidRequest bidRequest) { + final App app = bidRequest.getApp(); + final Publisher appPublisher = app != null ? app.getPublisher() : null; + final Site site = bidRequest.getSite(); + final Publisher sitePublisher = site != null ? site.getPublisher() : null; + final Dooh dooh = bidRequest.getDooh(); + final Publisher doohPublisher = dooh != null ? dooh.getPublisher() : null; + + final Publisher publisher = ObjectUtils.firstNonNull(appPublisher, doohPublisher, sitePublisher); + final String publisherId = publisher != null ? resolvePublisherId(publisher) : null; + return ObjectUtils.defaultIfNull(publisherId, StringUtils.EMPTY); + } + + /** + * Resolves what value should be used as a publisher id - either taken from publisher.ext.parentAccount + * or publisher.id in this respective priority. + */ + private String resolvePublisherId(Publisher publisher) { + final String parentAccountId = parentAccountIdFromExtPublisher(publisher.getExt()); + return ObjectUtils.defaultIfNull(parentAccountId, publisher.getId()); + } + + /** + * Parses publisher.ext and returns parentAccount value from it. Returns null if any parsing error occurs. + */ + private String parentAccountIdFromExtPublisher(ExtPublisher extPublisher) { + final ExtPublisherPrebid extPublisherPrebid = extPublisher != null ? extPublisher.getPrebid() : null; + return extPublisherPrebid != null ? StringUtils.stripToNull(extPublisherPrebid.getParentAccount()) : null; + } + +>>>>>>> 04d9d4a13 (Initial commit) private Future wrapFailure(Throwable exception, String accountId, HttpRequestContext httpRequest) { if (exception instanceof UnauthorizedAccountException) { return Future.failedFuture(exception); diff --git a/src/main/java/org/prebid/server/bidder/alvads/AlvadsBidder.java b/src/main/java/org/prebid/server/bidder/alvads/AlvadsBidder.java new file mode 100644 index 00000000000..b41756a29b6 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/alvads/AlvadsBidder.java @@ -0,0 +1,194 @@ +package org.prebid.server.bidder.alvads; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.response.Bid; +import com.iab.openrtb.response.BidResponse; +import io.vertx.core.http.HttpMethod; +import org.apache.commons.collections4.CollectionUtils; +import org.prebid.server.bidder.Bidder; +import org.prebid.server.bidder.alvads.model.AlvaAdsImp; +import org.prebid.server.bidder.alvads.model.AlvaAdsSite; +import org.prebid.server.bidder.alvads.model.AlvadsRequestORTB; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderCall; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpRequest; +import org.prebid.server.bidder.model.Result; +import org.prebid.server.exception.PreBidException; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.proto.openrtb.ext.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.alvads.AlvadsImpExt; +import org.prebid.server.proto.openrtb.ext.response.BidType; +import org.prebid.server.util.HttpUtil; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class AlvadsBidder implements Bidder { + + private final String endpointUrl; + private final JacksonMapper mapper; + private static final TypeReference> ALVADS_EXT_TYPE_REFERENCE = + new TypeReference<>() { }; + + public AlvadsBidder(String endpointUrl, JacksonMapper mapper) { + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.mapper = Objects.requireNonNull(mapper); + } + + @Override + public final Result>> makeHttpRequests(BidRequest bidRequest) { + final List errors = new ArrayList<>(); + final List> httpRequests = new ArrayList<>(); + + for (Imp imp : bidRequest.getImp()) { + try { + final AlvadsImpExt impExt = parseImpExt(imp); + final HttpRequest request = makeHttpRequest(bidRequest, imp, impExt); + httpRequests.add(request); + } catch (PreBidException e) { + errors.add(BidderError.badInput(e.getMessage())); + } + } + + if (httpRequests.isEmpty()) { + errors.add(BidderError.badInput("found no valid impressions")); + return Result.withErrors(errors); + } + + return Result.of(httpRequests, errors); + } + + private HttpRequest makeHttpRequest(BidRequest request, Imp imp, AlvadsImpExt impExt) { + final String resolvedUrl = impExt.getEndPointUrl() != null ? impExt.getEndPointUrl() : endpointUrl; + try { + URI.create(resolvedUrl); + } catch (IllegalArgumentException e) { + throw new PreBidException("Invalid endpoint URL: " + resolvedUrl, e); + } + + Map bannerMap = null; + if (imp.getBanner() != null) { + bannerMap = new HashMap<>(); + if (imp.getBanner().getW() != null) { + bannerMap.put("w", imp.getBanner().getW()); + } + if (imp.getBanner().getH() != null) { + bannerMap.put("h", imp.getBanner().getH()); + } + } + + // Build video map safely + Map videoMap = null; + if (imp.getVideo() != null) { + videoMap = new HashMap<>(); + if (imp.getVideo().getW() != null) { + videoMap.put("w", imp.getVideo().getW()); + } + if (imp.getVideo().getH() != null) { + videoMap.put("h", imp.getVideo().getH()); + } + } + + final AlvaAdsImp impObj = AlvaAdsImp.builder() + .id(imp.getId()) + .tagid(imp.getTagid()) + .bidfloor(imp.getBidfloor()) + .banner(bannerMap) + .video(videoMap) + .build(); + + final AlvaAdsSite siteObj = AlvaAdsSite.builder() + .page(request.getSite() != null ? request.getSite().getPage() : null) + .ref(request.getSite() != null ? request.getSite().getPage() : null) + .publisher(Map.of("id", impExt.getPublisherUniqueId())) + .build(); + + final AlvadsRequestORTB alvadsRequest = AlvadsRequestORTB.builder() + .id(request.getId()) + .imp(List.of(impObj)) + .device(request.getDevice()) + .user(request.getUser()) + .regs(request.getRegs()) + .site(siteObj) + .build(); + + return HttpRequest.builder() + .method(HttpMethod.POST) + .uri(resolvedUrl) + .headers(HttpUtil.headers()) + .payload(alvadsRequest) + .body(mapper.encodeToBytes(alvadsRequest)) + .impIds(alvadsRequest.getImp().stream() + .map(AlvaAdsImp::getId) + .collect(Collectors.toSet())) + .build(); + } + + private AlvadsImpExt parseImpExt(Imp imp) { + try { + return mapper.mapper().convertValue(imp.getExt(), ALVADS_EXT_TYPE_REFERENCE).getBidder(); + } catch (IllegalArgumentException e) { + throw new PreBidException("Missing or invalid bidder ext in impression with id: " + imp.getId()); + } + } + + @Override + public final Result> makeBids(BidderCall httpCall, + BidRequest bidRequest) { + try { + final BidResponse bidResponse = mapper.decodeValue( + httpCall.getResponse().getBody(), + BidResponse.class + ); + return Result.withValues(extractBids(bidResponse, httpCall.getRequest().getPayload())); + } catch (org.prebid.server.json.DecodeException e) { + return Result.withError(BidderError.badServerResponse( + "Failed to decode BidResponse: " + e.getMessage() + )); + } + } + + private List extractBids(BidResponse bidResponse, AlvadsRequestORTB request) { + if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { + return Collections.emptyList(); + } + return bidsFromResponse(bidResponse, request); + } + + private List bidsFromResponse(BidResponse bidResponse, AlvadsRequestORTB request) { + return bidResponse.getSeatbid().stream() + .flatMap(seatBid -> seatBid == null || seatBid.getBid() == null + ? Stream.empty() + : seatBid.getBid().stream()) + .map(bid -> BidderBid.of(bid, getBidType(bid, request), bidResponse.getCur())) + .toList(); + } + + private BidType getBidType(Bid bid, AlvadsRequestORTB request) { + final ExtBidAlvads bidExt = getBidExt(bid); + if (bidExt == null) { + return BidType.banner; + } + final BidType crtype = bidExt.getCrtype(); + return request.getImp().get(0).getVideo() != null ? BidType.video : crtype == null ? BidType.banner : crtype; + } + + private ExtBidAlvads getBidExt(Bid bid) { + try { + return mapper.mapper().convertValue(bid.getExt(), ExtBidAlvads.class); + } catch (IllegalArgumentException e) { + return null; + } + } + +} diff --git a/src/main/java/org/prebid/server/bidder/alvads/ExtBidAlvads.java b/src/main/java/org/prebid/server/bidder/alvads/ExtBidAlvads.java new file mode 100644 index 00000000000..ad20e1f6415 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/alvads/ExtBidAlvads.java @@ -0,0 +1,14 @@ +package org.prebid.server.bidder.alvads; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Data; +import org.prebid.server.proto.openrtb.ext.response.BidType; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +@Data +public class ExtBidAlvads { + + private BidType crtype; +} diff --git a/src/main/java/org/prebid/server/bidder/alvads/model/AlvaAdsImp.java b/src/main/java/org/prebid/server/bidder/alvads/model/AlvaAdsImp.java new file mode 100644 index 00000000000..de791cf7b9b --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/alvads/model/AlvaAdsImp.java @@ -0,0 +1,20 @@ +package org.prebid.server.bidder.alvads.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Builder; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@Data +@Builder +public class AlvaAdsImp { + + private String id; + private Map banner; + private Map video; + private String tagid; + private BigDecimal bidfloor; +} diff --git a/src/main/java/org/prebid/server/bidder/alvads/model/AlvaAdsSite.java b/src/main/java/org/prebid/server/bidder/alvads/model/AlvaAdsSite.java new file mode 100644 index 00000000000..a0d46fc615f --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/alvads/model/AlvaAdsSite.java @@ -0,0 +1,17 @@ +package org.prebid.server.bidder.alvads.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Builder; +import lombok.Data; + +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@Data +@Builder +public class AlvaAdsSite { + + private String page; + private String ref; + private Map publisher; +} diff --git a/src/main/java/org/prebid/server/bidder/alvads/model/AlvadsRequestORTB.java b/src/main/java/org/prebid/server/bidder/alvads/model/AlvadsRequestORTB.java new file mode 100644 index 00000000000..4c5855855fe --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/alvads/model/AlvadsRequestORTB.java @@ -0,0 +1,22 @@ +package org.prebid.server.bidder.alvads.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.iab.openrtb.request.Device; +import com.iab.openrtb.request.Regs; +import com.iab.openrtb.request.User; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@Data +@Builder +public class AlvadsRequestORTB { + private String id; + private List imp; + private Device device; + private User user; + private Regs regs; + private AlvaAdsSite site; +} diff --git a/src/main/java/org/prebid/server/bidder/ix/IxBidder.java b/src/main/java/org/prebid/server/bidder/ix/IxBidder.java index 5770772c1bd..093d9e14c17 100644 --- a/src/main/java/org/prebid/server/bidder/ix/IxBidder.java +++ b/src/main/java/org/prebid/server/bidder/ix/IxBidder.java @@ -21,6 +21,10 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidder.Bidder; +<<<<<<< HEAD +======= +import org.prebid.server.bidder.ix.model.request.IxDiag; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.bidder.ix.model.response.IxBidResponse; import org.prebid.server.bidder.ix.model.response.IxExtBidResponse; import org.prebid.server.bidder.ix.model.response.NativeV11Wrapper; @@ -64,8 +68,11 @@ public class IxBidder implements Bidder { private static final TypeReference> IX_EXT_TYPE_REFERENCE = new TypeReference<>() { }; +<<<<<<< HEAD private static final String PBSP_JAVA = "java"; private static final String PBS_VERSION_UNKNOWN = "unknown"; +======= +>>>>>>> 04d9d4a13 (Initial commit) private final String endpointUrl; private final PrebidVersionProvider prebidVersionProvider; @@ -205,11 +212,19 @@ private ExtRequest modifyRequestExt(ExtRequest extRequest, Set siteIds) modifiedExt = ExtRequest.empty(); } +<<<<<<< HEAD modifiedExt.addProperty("ixdiag", makeDiagData(extRequest, siteIds)); return modifiedExt; } private ObjectNode makeDiagData(ExtRequest extRequest, Set siteIds) { +======= + modifiedExt.addProperty("ixdiag", mapper.mapper().valueToTree(makeDiagData(extRequest, siteIds))); + return modifiedExt; + } + + private IxDiag makeDiagData(ExtRequest extRequest, Set siteIds) { +>>>>>>> 04d9d4a13 (Initial commit) final String pbjsv = Optional.ofNullable(extRequest) .map(ExtRequest::getPrebid) .map(ExtRequestPrebid::getChannel) @@ -222,6 +237,7 @@ private ObjectNode makeDiagData(ExtRequest extRequest, Set siteIds) { ? siteIds.stream().sorted().collect(Collectors.joining(", ")) : null; +<<<<<<< HEAD final ObjectNode ixdiag = Optional.ofNullable(extRequest) .map(ext -> ext.getProperty("ixdiag")) .filter(JsonNode::isObject) @@ -239,6 +255,9 @@ private ObjectNode makeDiagData(ExtRequest extRequest, Set siteIds) { } return ixdiag; +======= + return IxDiag.of(pbsv, pbjsv, multipleSiteIds); +>>>>>>> 04d9d4a13 (Initial commit) } @Override diff --git a/src/main/java/org/prebid/server/bidder/ix/model/request/IxDiag.java b/src/main/java/org/prebid/server/bidder/ix/model/request/IxDiag.java new file mode 100644 index 00000000000..b3323edb849 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/ix/model/request/IxDiag.java @@ -0,0 +1,15 @@ +package org.prebid.server.bidder.ix.model.request; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Value; + +@Value(staticConstructor = "of") +public class IxDiag { + + String pbsv; + + String pbjsv; + + @JsonProperty("multipleSiteIds") + String multipleSiteIds; +} diff --git a/src/main/java/org/prebid/server/bidder/onetag/OnetagBidder.java b/src/main/java/org/prebid/server/bidder/onetag/OnetagBidder.java index ec6c9718ea5..a2cba856d74 100644 --- a/src/main/java/org/prebid/server/bidder/onetag/OnetagBidder.java +++ b/src/main/java/org/prebid/server/bidder/onetag/OnetagBidder.java @@ -22,6 +22,10 @@ import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; +<<<<<<< HEAD +======= +import java.util.ArrayList; +>>>>>>> 04d9d4a13 (Initial commit) import java.util.Collection; import java.util.Collections; import java.util.List; @@ -44,18 +48,31 @@ public OnetagBidder(String endpointUrl, JacksonMapper mapper) { @Override public Result>> makeHttpRequests(BidRequest request) { +<<<<<<< HEAD +======= + final List modifiedImps = new ArrayList<>(); +>>>>>>> 04d9d4a13 (Initial commit) String requestPubId = null; for (Imp imp : request.getImp()) { try { final ExtImpOnetag impExt = parseImpExt(imp); requestPubId = resolveAndValidatePubId(impExt.getPubId(), requestPubId); +<<<<<<< HEAD +======= + + modifiedImps.add(imp.toBuilder().ext(impExt.getExt()).build()); +>>>>>>> 04d9d4a13 (Initial commit) } catch (PreBidException e) { return Result.withError(BidderError.badInput(e.getMessage())); } } +<<<<<<< HEAD final String url = endpointUrl.replace(URL_PUBLISHER_ID_MACRO, StringUtils.defaultString(requestPubId)); return Result.withValue(BidderUtil.defaultRequest(request, url, mapper)); +======= + return Result.withValue(createRequest(request, modifiedImps, requestPubId)); +>>>>>>> 04d9d4a13 (Initial commit) } private ExtImpOnetag parseImpExt(Imp imp) { @@ -66,8 +83,13 @@ private ExtImpOnetag parseImpExt(Imp imp) { } } +<<<<<<< HEAD private static String resolveAndValidatePubId(String impExtPubId, String requestPubId) { if (StringUtils.isBlank(impExtPubId)) { +======= + private String resolveAndValidatePubId(String impExtPubId, String requestPubId) { + if (StringUtils.isEmpty(impExtPubId)) { +>>>>>>> 04d9d4a13 (Initial commit) throw new PreBidException("The publisher ID must not be empty"); } if (requestPubId != null && !impExtPubId.equals(requestPubId)) { @@ -76,6 +98,16 @@ private static String resolveAndValidatePubId(String impExtPubId, String request return impExtPubId; } +<<<<<<< HEAD +======= + private HttpRequest createRequest(BidRequest request, List imps, String pubId) { + final String url = endpointUrl.replace(URL_PUBLISHER_ID_MACRO, pubId); + final BidRequest outgoingRequest = request.toBuilder().imp(imps).build(); + + return BidderUtil.defaultRequest(outgoingRequest, url, mapper); + } + +>>>>>>> 04d9d4a13 (Initial commit) @Override public final Result> makeBids(BidderCall httpCall, BidRequest bidRequest) { try { diff --git a/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java b/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java index 150c37fd255..a4db210a7ed 100644 --- a/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java +++ b/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java @@ -1,7 +1,10 @@ package org.prebid.server.bidder.smartadserver; import com.fasterxml.jackson.core.type.TypeReference; +<<<<<<< HEAD import com.fasterxml.jackson.databind.node.ObjectNode; +======= +>>>>>>> 04d9d4a13 (Initial commit) import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Imp; import com.iab.openrtb.request.Publisher; @@ -31,7 +34,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +<<<<<<< HEAD import java.util.LinkedHashMap; +======= +>>>>>>> 04d9d4a13 (Initial commit) import java.util.List; import java.util.Objects; @@ -42,18 +48,26 @@ public class SmartadserverBidder implements Bidder { }; private final String endpointUrl; +<<<<<<< HEAD private final String secondaryEndpointUrl; private final JacksonMapper mapper; public SmartadserverBidder(String endpointUrl, String secondaryEndpointUrl, JacksonMapper mapper) { this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); this.secondaryEndpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(secondaryEndpointUrl)); +======= + private final JacksonMapper mapper; + + public SmartadserverBidder(String endpointUrl, JacksonMapper mapper) { + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); +>>>>>>> 04d9d4a13 (Initial commit) this.mapper = Objects.requireNonNull(mapper); } @Override public Result>> makeHttpRequests(BidRequest request) { final List errors = new ArrayList<>(); +<<<<<<< HEAD final List modifiedImps = new ArrayList<>(); final LinkedHashMap impToExtImpMap = new LinkedHashMap<>(); @@ -64,11 +78,21 @@ public Result>> makeHttpRequests(BidRequest request final ExtImpSmartadserver extImp = parseImpExt(imp); isProgrammaticGuaranteed |= extImp.isProgrammaticGuaranteed(); impToExtImpMap.put(imp, extImp); +======= + final List imps = new ArrayList<>(); + ExtImpSmartadserver extImp = null; + + for (Imp imp : request.getImp()) { + try { + extImp = parseImpExt(imp); + imps.add(imp); +>>>>>>> 04d9d4a13 (Initial commit) } catch (PreBidException e) { errors.add(BidderError.badInput(e.getMessage())); } } +<<<<<<< HEAD if (impToExtImpMap.isEmpty()) { return Result.withErrors(errors); } @@ -86,6 +110,18 @@ public Result>> makeHttpRequests(BidRequest request outgoingRequest, makeUrl(isProgrammaticGuaranteed), mapper); +======= + if (imps.isEmpty()) { + return Result.withErrors(errors); + } + + final BidRequest outgoingRequest = request.toBuilder() + .imp(imps) + .site(modifySite(request.getSite(), extImp.getNetworkId())) + .build(); + + final HttpRequest httpRequest = BidderUtil.defaultRequest(outgoingRequest, makeUrl(), mapper); +>>>>>>> 04d9d4a13 (Initial commit) return Result.of(Collections.singletonList(httpRequest), errors); } @@ -97,6 +133,7 @@ private ExtImpSmartadserver parseImpExt(Imp imp) { } } +<<<<<<< HEAD private Imp modifyImp(Imp imp, ExtImpSmartadserver extImp, String impExtKey) { final ObjectNode impExt = imp.getExt().deepCopy(); impExt.remove("bidder"); @@ -104,6 +141,8 @@ private Imp modifyImp(Imp imp, ExtImpSmartadserver extImp, String impExtKey) { return imp.toBuilder().ext(impExt).build(); } +======= +>>>>>>> 04d9d4a13 (Initial commit) private static Site modifySite(Site site, Integer networkId) { final Site.SiteBuilder siteBuilder = site != null ? site.toBuilder() : Site.builder(); final Publisher sitePublisher = site != null ? site.getPublisher() : null; @@ -119,6 +158,7 @@ private static Publisher modifyPublisher(Publisher publisher, Integer networkId) return publisherBuilder.id(String.valueOf(networkId)).build(); } +<<<<<<< HEAD private String makeUrl(boolean isProgrammaticGuaranteed) { final String url = isProgrammaticGuaranteed ? secondaryEndpointUrl : endpointUrl; try { @@ -135,6 +175,19 @@ private String makeUrl(boolean isProgrammaticGuaranteed) { } catch (URISyntaxException e) { throw new PreBidException("Malformed URL: %s.".formatted(url)); } +======= + private String makeUrl() { + final URI uri; + try { + uri = new URI(endpointUrl); + } catch (URISyntaxException e) { + throw new PreBidException("Malformed URL: %s.".formatted(endpointUrl)); + } + return new URIBuilder(uri) + .setPath(StringUtils.removeEnd(uri.getPath(), "/") + "/api/bid") + .addParameter("callerId", "5") + .toString(); +>>>>>>> 04d9d4a13 (Initial commit) } @Override diff --git a/src/main/java/org/prebid/server/handler/admin/SettingsCacheNotificationHandler.java b/src/main/java/org/prebid/server/handler/admin/SettingsCacheNotificationHandler.java index fd652ebb8ff..7a310156c90 100644 --- a/src/main/java/org/prebid/server/handler/admin/SettingsCacheNotificationHandler.java +++ b/src/main/java/org/prebid/server/handler/admin/SettingsCacheNotificationHandler.java @@ -19,6 +19,7 @@ */ public class SettingsCacheNotificationHandler implements Handler { +<<<<<<< HEAD private final String endpoint; private final CacheNotificationListener cacheNotificationListener; private final JacksonMapper mapper; @@ -30,6 +31,17 @@ public SettingsCacheNotificationHandler(String endpoint, this.endpoint = Objects.requireNonNull(endpoint); this.cacheNotificationListener = Objects.requireNonNull(cacheNotificationListener); this.mapper = Objects.requireNonNull(mapper); +======= + private final CacheNotificationListener cacheNotificationListener; + private final JacksonMapper mapper; + private final String endpoint; + + public SettingsCacheNotificationHandler(CacheNotificationListener cacheNotificationListener, JacksonMapper mapper, + String endpoint) { + this.cacheNotificationListener = Objects.requireNonNull(cacheNotificationListener); + this.mapper = Objects.requireNonNull(mapper); + this.endpoint = Objects.requireNonNull(endpoint); +>>>>>>> 04d9d4a13 (Initial commit) } @Override @@ -96,18 +108,26 @@ private void doFail(RoutingContext routingContext) { } private void respondWithBadRequest(RoutingContext routingContext, String body) { +<<<<<<< HEAD HttpUtil.executeSafely( routingContext, endpoint, +======= + HttpUtil.executeSafely(routingContext, endpoint, +>>>>>>> 04d9d4a13 (Initial commit) response -> response .setStatusCode(HttpResponseStatus.BAD_REQUEST.code()) .end(body)); } private void respondWith(RoutingContext routingContext, HttpResponseStatus status) { +<<<<<<< HEAD HttpUtil.executeSafely( routingContext, endpoint, +======= + HttpUtil.executeSafely(routingContext, endpoint, +>>>>>>> 04d9d4a13 (Initial commit) response -> response .setStatusCode(status.code()) .end()); diff --git a/src/main/java/org/prebid/server/metric/AccountMetrics.java b/src/main/java/org/prebid/server/metric/AccountMetrics.java index 6bd479b7ea3..669bc1622d8 100644 --- a/src/main/java/org/prebid/server/metric/AccountMetrics.java +++ b/src/main/java/org/prebid/server/metric/AccountMetrics.java @@ -23,7 +23,10 @@ class AccountMetrics extends UpdatableMetrics { private final ResponseMetrics responseMetrics; private final HooksMetrics hooksMetrics; private final ActivitiesMetrics activitiesMetrics; +<<<<<<< HEAD private final ProfileMetrics profileMetrics; +======= +>>>>>>> 04d9d4a13 (Initial commit) AccountMetrics(MetricRegistry metricRegistry, CounterType counterType, String account) { super(Objects.requireNonNull(metricRegistry), Objects.requireNonNull(counterType), @@ -37,7 +40,10 @@ class AccountMetrics extends UpdatableMetrics { responseMetrics = new ResponseMetrics(metricRegistry, counterType, createPrefix(account)); hooksMetrics = new HooksMetrics(metricRegistry, counterType, createPrefix(account)); activitiesMetrics = new ActivitiesMetrics(metricRegistry, counterType, createPrefix(account)); +<<<<<<< HEAD profileMetrics = new ProfileMetrics(metricRegistry, counterType, createPrefix(account)); +======= +>>>>>>> 04d9d4a13 (Initial commit) } private static String createPrefix(String account) { @@ -75,8 +81,11 @@ HooksMetrics hooks() { ActivitiesMetrics activities() { return activitiesMetrics; } +<<<<<<< HEAD ProfileMetrics profiles() { return profileMetrics; } +======= +>>>>>>> 04d9d4a13 (Initial commit) } diff --git a/src/main/java/org/prebid/server/metric/MetricName.java b/src/main/java/org/prebid/server/metric/MetricName.java index 4d562aa4122..55e79ea432f 100644 --- a/src/main/java/org/prebid/server/metric/MetricName.java +++ b/src/main/java/org/prebid/server/metric/MetricName.java @@ -156,10 +156,14 @@ public enum MetricName { // activity disallowed_count("disallowed.count"), +<<<<<<< HEAD processed_rules_count("processedrules.count"), // profiles limit_exceeded; +======= + processed_rules_count("processedrules.count"); +>>>>>>> 04d9d4a13 (Initial commit) private final String name; diff --git a/src/main/java/org/prebid/server/metric/Metrics.java b/src/main/java/org/prebid/server/metric/Metrics.java index c10d3301391..11867c577f8 100644 --- a/src/main/java/org/prebid/server/metric/Metrics.java +++ b/src/main/java/org/prebid/server/metric/Metrics.java @@ -59,7 +59,10 @@ public class Metrics extends UpdatableMetrics { private final CurrencyRatesMetrics currencyRatesMetrics; private final Map settingsCacheMetrics; private final HooksMetrics hooksMetrics; +<<<<<<< HEAD private final ProfileMetrics profileMetrics; +======= +>>>>>>> 04d9d4a13 (Initial commit) public Metrics(MetricRegistry metricRegistry, CounterType counterType, @@ -98,7 +101,10 @@ public Metrics(MetricRegistry metricRegistry, currencyRatesMetrics = new CurrencyRatesMetrics(metricRegistry, counterType); settingsCacheMetrics = new HashMap<>(); hooksMetrics = new HooksMetrics(metricRegistry, counterType); +<<<<<<< HEAD profileMetrics = new ProfileMetrics(metricRegistry, counterType); +======= +>>>>>>> 04d9d4a13 (Initial commit) } RequestsMetrics requests() { @@ -729,6 +735,7 @@ public void updateAccountActivityProcessedRulesCount(String account) { forAccount(account).activities().incCounter(MetricName.processed_rules_count); } +<<<<<<< HEAD public void updateProfileMetric(MetricName metricName) { profileMetrics.incCounter(metricName); } @@ -737,6 +744,8 @@ public void updateAccountProfileMetric(String account, MetricName metricName) { forAccount(account).profiles().incCounter(metricName); } +======= +>>>>>>> 04d9d4a13 (Initial commit) private static class HookMetricMapper { private static final EnumMap STATUS_TO_METRIC = diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtImpPrebid.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtImpPrebid.java index 33ac57c13c0..dd18d64f7da 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtImpPrebid.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtImpPrebid.java @@ -21,11 +21,14 @@ public class ExtImpPrebid { ExtStoredRequest storedrequest; /** +<<<<<<< HEAD * Defines the contract for bidrequest.imp[i].ext.prebid.profiles */ List profiles; /** +======= +>>>>>>> 04d9d4a13 (Initial commit) * Defines the contract for bidrequest.imp[i].ext.prebid.storedauctionresponse */ @JsonProperty("storedauctionresponse") diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java index 25dffdc486c..c8f8a119049 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java @@ -77,11 +77,14 @@ public class ExtRequestPrebid { ExtStoredRequest storedrequest; /** +<<<<<<< HEAD * Defines the contract for bidrequest.ext.prebid.profiles */ List profiles; /** +======= +>>>>>>> 04d9d4a13 (Initial commit) * Defines the contract for bidrequest.ext.prebid.storedauctionresponse */ @JsonProperty("storedauctionresponse") diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/alvads/AlvadsImpExt.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/alvads/AlvadsImpExt.java new file mode 100644 index 00000000000..eb4c0c5eea9 --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/alvads/AlvadsImpExt.java @@ -0,0 +1,13 @@ +package org.prebid.server.proto.openrtb.ext.request.alvads; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Value; + +@Value(staticConstructor = "of") +public class AlvadsImpExt { + @JsonProperty("publisherUniqueId") + String publisherUniqueId; + + @JsonProperty("endPointUrl") + String endPointUrl; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/smartadserver/ExtImpSmartadserver.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/smartadserver/ExtImpSmartadserver.java index efc8de91a5f..2bb20837075 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/smartadserver/ExtImpSmartadserver.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/smartadserver/ExtImpSmartadserver.java @@ -3,6 +3,12 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Value; +<<<<<<< HEAD +======= +/** + * Defines the contract for bidrequest.imp[i].ext.smartadserver + */ +>>>>>>> 04d9d4a13 (Initial commit) @Value(staticConstructor = "of") public class ExtImpSmartadserver { @@ -17,7 +23,10 @@ public class ExtImpSmartadserver { @JsonProperty("networkId") Integer networkId; +<<<<<<< HEAD @JsonProperty(value = "programmaticGuaranteed", access = JsonProperty.Access.WRITE_ONLY) boolean programmaticGuaranteed; +======= +>>>>>>> 04d9d4a13 (Initial commit) } diff --git a/src/main/java/org/prebid/server/settings/ApplicationSettings.java b/src/main/java/org/prebid/server/settings/ApplicationSettings.java index 2f3ca855668..50b62173570 100644 --- a/src/main/java/org/prebid/server/settings/ApplicationSettings.java +++ b/src/main/java/org/prebid/server/settings/ApplicationSettings.java @@ -3,13 +3,17 @@ import io.vertx.core.Future; import org.prebid.server.execution.timeout.Timeout; import org.prebid.server.settings.model.Account; +<<<<<<< HEAD import org.prebid.server.settings.model.Profile; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.settings.model.StoredDataResult; import org.prebid.server.settings.model.StoredResponseDataResult; import java.util.Map; import java.util.Set; +<<<<<<< HEAD public interface ApplicationSettings { Future getAccountById(String accountId, Timeout timeout); @@ -36,5 +40,51 @@ Future> getProfiles(String accountId, Future getStoredResponses(Set responseIds, Timeout timeout); +======= +/** + * Defines the contract of getting application settings (account, stored ad unit configurations and + * stored requests and imps) from the source. + * + * @see FileApplicationSettings + * @see DatabaseApplicationSettings + * @see HttpApplicationSettings + * @see CachingApplicationSettings + * @see CompositeApplicationSettings + */ +public interface ApplicationSettings { + + /** + * Returns {@link Account} for the given account ID. + */ + Future getAccountById(String accountId, Timeout timeout); + + /** + * Fetches stored requests and imps by IDs. + */ + Future getStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout); + + /** + * Fetches AMP stored requests and imps by IDs. + */ + Future getAmpStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout); + + /** + * Fetches Video stored requests and imps by IDs. + */ + Future getVideoStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout); + + /** + * Fetches stored response by IDs. + */ + Future getStoredResponses(Set responseIds, Timeout timeout); + + + /** + * Fetches video category + */ +>>>>>>> 04d9d4a13 (Initial commit) Future> getCategories(String primaryAdServer, String publisher, Timeout timeout); } diff --git a/src/main/java/org/prebid/server/settings/CacheNotificationListener.java b/src/main/java/org/prebid/server/settings/CacheNotificationListener.java index 5a5e8e88d75..4a1ebcce6d3 100644 --- a/src/main/java/org/prebid/server/settings/CacheNotificationListener.java +++ b/src/main/java/org/prebid/server/settings/CacheNotificationListener.java @@ -3,9 +3,15 @@ import java.util.List; import java.util.Map; +<<<<<<< HEAD public interface CacheNotificationListener { void save(Map requests, Map imps); +======= +public interface CacheNotificationListener { + + void save(Map requests, Map imps); +>>>>>>> 04d9d4a13 (Initial commit) void invalidate(List requests, List imps); } diff --git a/src/main/java/org/prebid/server/settings/CachingApplicationSettings.java b/src/main/java/org/prebid/server/settings/CachingApplicationSettings.java index 3a39d9eae40..9dba3c851ef 100644 --- a/src/main/java/org/prebid/server/settings/CachingApplicationSettings.java +++ b/src/main/java/org/prebid/server/settings/CachingApplicationSettings.java @@ -11,7 +11,10 @@ import org.prebid.server.settings.helper.StoredDataFetcher; import org.prebid.server.settings.helper.StoredItemResolver; import org.prebid.server.settings.model.Account; +<<<<<<< HEAD import org.prebid.server.settings.model.Profile; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.settings.model.StoredDataResult; import org.prebid.server.settings.model.StoredItem; import org.prebid.server.settings.model.StoredResponseDataResult; @@ -25,6 +28,12 @@ import java.util.function.BiFunction; import java.util.function.Consumer; +<<<<<<< HEAD +======= +/** + * Adds caching functionality for {@link ApplicationSettings} implementation. + */ +>>>>>>> 04d9d4a13 (Initial commit) public class CachingApplicationSettings implements ApplicationSettings { private static final Logger logger = LoggerFactory.getLogger(CachingApplicationSettings.class); @@ -35,6 +44,7 @@ public class CachingApplicationSettings implements ApplicationSettings { private final Map accountToErrorCache; private final Map adServerPublisherToErrorCache; private final Map> categoryConfigCache; +<<<<<<< HEAD private final SettingsCache cache; private final SettingsCache ampCache; private final SettingsCache videoCache; @@ -46,6 +56,17 @@ public CachingApplicationSettings(ApplicationSettings delegate, SettingsCache ampCache, SettingsCache videoCache, SettingsCache profileCache, +======= + private final SettingsCache cache; + private final SettingsCache ampCache; + private final SettingsCache videoCache; + private final Metrics metrics; + + public CachingApplicationSettings(ApplicationSettings delegate, + SettingsCache cache, + SettingsCache ampCache, + SettingsCache videoCache, +>>>>>>> 04d9d4a13 (Initial commit) Metrics metrics, int ttl, int size, @@ -66,10 +87,19 @@ public CachingApplicationSettings(ApplicationSettings delegate, this.cache = Objects.requireNonNull(cache); this.ampCache = Objects.requireNonNull(ampCache); this.videoCache = Objects.requireNonNull(videoCache); +<<<<<<< HEAD this.profileCache = Objects.requireNonNull(profileCache); this.metrics = Objects.requireNonNull(metrics); } +======= + this.metrics = Objects.requireNonNull(metrics); + } + + /** + * Retrieves account from cache or delegates it to original fetcher. + */ +>>>>>>> 04d9d4a13 (Initial commit) @Override public Future getAccountById(String accountId, Timeout timeout) { return getFromCacheOrDelegate( @@ -81,6 +111,61 @@ public Future getAccountById(String accountId, Timeout timeout) { event -> metrics.updateSettingsCacheEventMetric(MetricName.account, event)); } +<<<<<<< HEAD +======= + /** + * Retrieves stored data from cache or delegates it to original fetcher. + */ + @Override + public Future getStoredData(String accountId, + Set requestIds, + Set impIds, + Timeout timeout) { + + return getFromCacheOrDelegate(cache, accountId, requestIds, impIds, timeout, delegate::getStoredData); + } + + /** + * Retrieves amp stored data from cache or delegates it to original fetcher. + */ + @Override + public Future getAmpStoredData(String accountId, + Set requestIds, + Set impIds, + Timeout timeout) { + + return getFromCacheOrDelegate(ampCache, accountId, requestIds, impIds, timeout, delegate::getAmpStoredData); + } + + @Override + public Future getVideoStoredData(String accountId, + Set requestIds, + Set impIds, + Timeout timeout) { + + return getFromCacheOrDelegate(videoCache, accountId, requestIds, impIds, timeout, delegate::getVideoStoredData); + } + + /** + * Delegates stored response retrieve to original fetcher, as caching is not supported fot stored response. + */ + @Override + public Future getStoredResponses(Set responseIds, Timeout timeout) { + return delegate.getStoredResponses(responseIds, timeout); + } + + @Override + public Future> getCategories(String primaryAdServer, String publisher, Timeout timeout) { + final String compoundKey = StringUtils.isNotBlank(publisher) + ? "%s_%s".formatted(primaryAdServer, publisher) + : primaryAdServer; + + return getFromCacheOrDelegate(categoryConfigCache, adServerPublisherToErrorCache, compoundKey, timeout, + (key, timeoutParam) -> delegate.getCategories(primaryAdServer, publisher, timeout), + CachingApplicationSettings::noOp); + } + +>>>>>>> 04d9d4a13 (Initial commit) private static Future getFromCacheOrDelegate(Map cache, Map accountToErrorCache, String key, @@ -110,6 +195,61 @@ private static Future getFromCacheOrDelegate(Map cache, .recover(throwable -> cacheAndReturnFailedFuture(throwable, key, accountToErrorCache)); } +<<<<<<< HEAD +======= + /** + * Retrieves stored data from cache and collects ids which were absent. For absent ids makes look up to original + * source, combines results and updates cache with missed stored item. In case when origin source returns failed + * {@link Future} propagates its result to caller. In successive call return {@link Future<StoredDataResult>} + * with all found stored items and error from origin source id call was made. + */ + private static Future getFromCacheOrDelegate( + SettingsCache cache, + String accountId, + Set requestIds, + Set impIds, + Timeout timeout, + StoredDataFetcher, Set, Timeout, Future> retriever) { + + // empty string account ID doesn't make sense + final String normalizedAccountId = StringUtils.stripToNull(accountId); + + // search in cache + final Map> requestCache = cache.getRequestCache(); + final Map> impCache = cache.getImpCache(); + + final Set missedRequestIds = new HashSet<>(); + final Map storedIdToRequest = getFromCacheOrAddMissedIds(normalizedAccountId, requestIds, + requestCache, missedRequestIds); + + final Set missedImpIds = new HashSet<>(); + final Map storedIdToImp = getFromCacheOrAddMissedIds(normalizedAccountId, impIds, impCache, + missedImpIds); + + if (missedRequestIds.isEmpty() && missedImpIds.isEmpty()) { + return Future.succeededFuture( + StoredDataResult.of(storedIdToRequest, storedIdToImp, Collections.emptyList())); + } + + // delegate call to original source for missed ids and update cache with it + return retriever.apply(normalizedAccountId, missedRequestIds, missedImpIds, timeout).map(result -> { + final Map storedIdToRequestFromDelegate = result.getStoredIdToRequest(); + storedIdToRequest.putAll(storedIdToRequestFromDelegate); + for (Map.Entry entry : storedIdToRequestFromDelegate.entrySet()) { + cache.saveRequestCache(normalizedAccountId, entry.getKey(), entry.getValue()); + } + + final Map storedIdToImpFromDelegate = result.getStoredIdToImp(); + storedIdToImp.putAll(storedIdToImpFromDelegate); + for (Map.Entry entry : storedIdToImpFromDelegate.entrySet()) { + cache.saveImpCache(normalizedAccountId, entry.getKey(), entry.getValue()); + } + + return StoredDataResult.of(storedIdToRequest, storedIdToImp, result.getErrors()); + }); + } + +>>>>>>> 04d9d4a13 (Initial commit) private static Future cacheAndReturnFailedFuture(Throwable throwable, String key, Map cache) { @@ -121,6 +261,7 @@ private static Future cacheAndReturnFailedFuture(Throwable throwable, return Future.failedFuture(throwable); } +<<<<<<< HEAD @Override public Future> getStoredData(String accountId, Set requestIds, @@ -219,6 +360,18 @@ private static Map getFromCacheOrAddMissedIds(String accountId, for (String id : ids) { try { final StoredItem resolvedStoredItem = StoredItemResolver.resolve(null, accountId, id, cache.get(id)); +======= + private static Map getFromCacheOrAddMissedIds(String accountId, + Set ids, + Map> cache, + Set missedIds) { + + final Map idToStoredItem = new HashMap<>(ids.size()); + + for (String id : ids) { + try { + final StoredItem resolvedStoredItem = StoredItemResolver.resolve(null, accountId, id, cache.get(id)); +>>>>>>> 04d9d4a13 (Initial commit) idToStoredItem.put(id, resolvedStoredItem.getData()); } catch (PreBidException e) { missedIds.add(id); @@ -228,6 +381,7 @@ private static Map getFromCacheOrAddMissedIds(String accountId, return idToStoredItem; } +<<<<<<< HEAD @Override public Future getStoredResponses(Set responseIds, Timeout timeout) { return delegate.getStoredResponses(responseIds, timeout); @@ -248,6 +402,8 @@ public Future> getCategories(String primaryAdServer, String CachingApplicationSettings::noOp); } +======= +>>>>>>> 04d9d4a13 (Initial commit) public void invalidateAccountCache(String accountId) { accountCache.remove(accountId); accountToErrorCache.remove(accountId); diff --git a/src/main/java/org/prebid/server/settings/CompositeApplicationSettings.java b/src/main/java/org/prebid/server/settings/CompositeApplicationSettings.java index 225171508b4..9c30a8d9bff 100644 --- a/src/main/java/org/prebid/server/settings/CompositeApplicationSettings.java +++ b/src/main/java/org/prebid/server/settings/CompositeApplicationSettings.java @@ -4,10 +4,17 @@ import org.prebid.server.execution.timeout.Timeout; import org.prebid.server.settings.helper.StoredDataFetcher; import org.prebid.server.settings.model.Account; +<<<<<<< HEAD import org.prebid.server.settings.model.Profile; import org.prebid.server.settings.model.StoredDataResult; import org.prebid.server.settings.model.StoredResponseDataResult; +======= +import org.prebid.server.settings.model.StoredDataResult; +import org.prebid.server.settings.model.StoredResponseDataResult; + +import java.util.Collections; +>>>>>>> 04d9d4a13 (Initial commit) import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -15,7 +22,15 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +<<<<<<< HEAD + +======= +import java.util.function.BiFunction; +/** + * Implements composite pattern for a list of {@link ApplicationSettings}. + */ +>>>>>>> 04d9d4a13 (Initial commit) public class CompositeApplicationSettings implements ApplicationSettings { private final Proxy proxy; @@ -38,11 +53,19 @@ private static Proxy createProxy(List delegates) { return proxy; } +<<<<<<< HEAD +======= + /** + * Runs a process to get account by id from a chain of retrievers + * and returns {@link Future<{@link Account}>}. + */ +>>>>>>> 04d9d4a13 (Initial commit) @Override public Future getAccountById(String accountId, Timeout timeout) { return proxy.getAccountById(accountId, timeout); } +<<<<<<< HEAD @Override public Future> getStoredData(String accountId, Set requestIds, @@ -67,10 +90,36 @@ public Future> getVideoStoredData(String accountId, Set impIds, Timeout timeout) { +======= + /** + * Runs a process to get stored requests by a collection of ids from a chain of retrievers + * and returns {@link Future<{@link StoredDataResult }>}. + */ + @Override + public Future getStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout) { + return proxy.getStoredData(accountId, requestIds, impIds, timeout); + } + + /** + * Runs a process to get stored requests by a collection of amp ids from a chain of retrievers + * and returns {@link Future<{@link StoredDataResult }>}. + */ + @Override + public Future getAmpStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout) { + return proxy.getAmpStoredData(accountId, requestIds, Collections.emptySet(), timeout); + } + + @Override + public Future getVideoStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout) { +>>>>>>> 04d9d4a13 (Initial commit) return proxy.getVideoStoredData(accountId, requestIds, impIds, timeout); } @Override +<<<<<<< HEAD public Future> getProfiles(String accountId, Set requestIds, Set impIds, @@ -85,10 +134,27 @@ public Future getStoredResponses(Set responseI } @Override +======= +>>>>>>> 04d9d4a13 (Initial commit) public Future> getCategories(String primaryAdServer, String publisher, Timeout timeout) { return proxy.getCategories(primaryAdServer, publisher, timeout); } +<<<<<<< HEAD +======= + /** + * Runs a process to get stored responses by a collection of ids from a chain of retrievers + * and returns {@link Future<{@link StoredResponseDataResult }>}. + */ + @Override + public Future getStoredResponses(Set responseIds, Timeout timeout) { + return proxy.getStoredResponses(responseIds, timeout); + } + + /** + * Decorates {@link ApplicationSettings} for a chain of retrievers. + */ +>>>>>>> 04d9d4a13 (Initial commit) private static class Proxy implements ApplicationSettings { private final ApplicationSettings applicationSettings; @@ -101,13 +167,27 @@ private Proxy(ApplicationSettings applicationSettings, Proxy next) { @Override public Future getAccountById(String accountId, Timeout timeout) { +<<<<<<< HEAD return applicationSettings.getAccountById(accountId, timeout) .recover(throwable -> next != null ? next.getAccountById(accountId, timeout) +======= + return getConfig(accountId, timeout, applicationSettings::getAccountById, + next != null ? next::getAccountById : null); + } + + private static Future getConfig(String key, Timeout timeout, + BiFunction> retriever, + BiFunction> nextRetriever) { + return retriever.apply(key, timeout) + .recover(throwable -> nextRetriever != null + ? nextRetriever.apply(key, timeout) +>>>>>>> 04d9d4a13 (Initial commit) : Future.failedFuture(throwable)); } @Override +<<<<<<< HEAD public Future> getStoredData(String accountId, Set requestIds, Set impIds, @@ -226,6 +306,8 @@ private Future getRemainingStoredResponses( } @Override +======= +>>>>>>> 04d9d4a13 (Initial commit) public Future> getCategories(String primaryAdServer, String publisher, Timeout timeout) { return applicationSettings.getCategories(primaryAdServer, publisher, timeout) .recover(throwable -> next != null @@ -233,6 +315,87 @@ public Future> getCategories(String primaryAdServer, String : Future.failedFuture(throwable)); } +<<<<<<< HEAD +======= + @Override + public Future getStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout) { + return getStoredRequests(accountId, requestIds, impIds, timeout, applicationSettings::getStoredData, + next != null ? next::getStoredData : null); + } + + @Override + public Future getAmpStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout) { + return getStoredRequests(accountId, requestIds, Collections.emptySet(), timeout, + applicationSettings::getAmpStoredData, + next != null ? next::getAmpStoredData : null); + } + + @Override + public Future getVideoStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout) { + return getStoredRequests(accountId, requestIds, impIds, timeout, + applicationSettings::getVideoStoredData, next != null ? next::getVideoStoredData : null); + } + + @Override + public Future getStoredResponses(Set responseIds, Timeout timeout) { + return getStoredResponses(responseIds, timeout, applicationSettings::getStoredResponses, + next != null ? next::getStoredResponses : null); + } + + private static Future getStoredResponses( + Set responseIds, Timeout timeout, + BiFunction, Timeout, Future> retriever, + BiFunction, Timeout, Future> nextRetriever) { + + return retriever.apply(responseIds, timeout) + .compose(retrieverResult -> + nextRetriever == null || retrieverResult.getErrors().isEmpty() + ? Future.succeededFuture(retrieverResult) + : getRemainingStoredResponses(responseIds, timeout, + retrieverResult.getIdToStoredResponses(), nextRetriever)); + } + + private static Future getStoredRequests( + String accountId, Set requestIds, Set impIds, Timeout timeout, + StoredDataFetcher, Set, Timeout, Future> retriever, + StoredDataFetcher, Set, Timeout, Future> nextRetriever) { + + return retriever.apply(accountId, requestIds, impIds, timeout) + .compose(retrieverResult -> + nextRetriever == null || retrieverResult.getErrors().isEmpty() + ? Future.succeededFuture(retrieverResult) + : getRemainingStoredRequests(accountId, requestIds, impIds, timeout, + retrieverResult.getStoredIdToRequest(), retrieverResult.getStoredIdToImp(), + nextRetriever)); + } + + private static Future getRemainingStoredRequests( + String accountId, Set requestIds, Set impIds, Timeout timeout, + Map storedIdToRequest, Map storedIdToImp, + StoredDataFetcher, Set, Timeout, Future> retriever) { + + return retriever.apply(accountId, subtractSets(requestIds, storedIdToRequest.keySet()), + subtractSets(impIds, storedIdToImp.keySet()), timeout) + .map(result -> StoredDataResult.of( + combineMaps(storedIdToRequest, result.getStoredIdToRequest()), + combineMaps(storedIdToImp, result.getStoredIdToImp()), + result.getErrors())); + } + + private static Future getRemainingStoredResponses( + Set responseIds, Timeout timeout, Map storedSeatBids, + BiFunction, Timeout, Future> retriever) { + + return retriever.apply(subtractSets(responseIds, storedSeatBids.keySet()), timeout) + .map(result -> StoredResponseDataResult.of( + combineMaps(storedSeatBids, result.getIdToStoredResponses()), + result.getErrors())); + } + +>>>>>>> 04d9d4a13 (Initial commit) private static Set subtractSets(Set first, Set second) { final Set remaining = new HashSet<>(first); remaining.removeAll(second); diff --git a/src/main/java/org/prebid/server/settings/DatabaseApplicationSettings.java b/src/main/java/org/prebid/server/settings/DatabaseApplicationSettings.java index 54ffc7a425c..b7d8f7d8190 100644 --- a/src/main/java/org/prebid/server/settings/DatabaseApplicationSettings.java +++ b/src/main/java/org/prebid/server/settings/DatabaseApplicationSettings.java @@ -10,12 +10,18 @@ import org.prebid.server.execution.timeout.Timeout; import org.prebid.server.json.DecodeException; import org.prebid.server.json.JacksonMapper; +<<<<<<< HEAD import org.prebid.server.settings.helper.DatabaseProfilesResultMapper; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.settings.helper.DatabaseStoredDataResultMapper; import org.prebid.server.settings.helper.DatabaseStoredResponseResultMapper; import org.prebid.server.settings.helper.ParametrizedQueryHelper; import org.prebid.server.settings.model.Account; +<<<<<<< HEAD import org.prebid.server.settings.model.Profile; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.settings.model.StoredDataResult; import org.prebid.server.settings.model.StoredResponseDataResult; import org.prebid.server.util.ObjectUtil; @@ -31,6 +37,17 @@ import java.util.function.Function; import java.util.stream.IntStream; +<<<<<<< HEAD +======= +/** + * Implementation of {@link ApplicationSettings}. + *

+ * Reads an application settings from the database source. + *

+ * In order to enable caching and reduce latency for read operations {@link DatabaseApplicationSettings} + * can be decorated by {@link CachingApplicationSettings}. + */ +>>>>>>> 04d9d4a13 (Initial commit) public class DatabaseApplicationSettings implements ApplicationSettings { private final DatabaseClient databaseClient; @@ -67,6 +84,7 @@ public class DatabaseApplicationSettings implements ApplicationSettings { private final String selectAmpStoredRequestsQuery; /** +<<<<<<< HEAD * Query to select profiles by ids, for example: *

      * SELECT accountId, profileId, profile, mergePrecedence, type
@@ -77,6 +95,8 @@ public class DatabaseApplicationSettings implements ApplicationSettings {
     private final String selectProfilesQuery;
 
     /**
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
      * Query to select stored responses by ids, for example:
      * 
      * SELECT respid, responseData
@@ -92,7 +112,10 @@ public DatabaseApplicationSettings(DatabaseClient databaseClient,
                                        String selectAccountQuery,
                                        String selectStoredRequestsQuery,
                                        String selectAmpStoredRequestsQuery,
+<<<<<<< HEAD
                                        String selectProfilesQuery,
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
                                        String selectStoredResponsesQuery) {
 
         this.databaseClient = Objects.requireNonNull(databaseClient);
@@ -102,10 +125,20 @@ public DatabaseApplicationSettings(DatabaseClient databaseClient,
                 Objects.requireNonNull(selectAccountQuery));
         this.selectStoredRequestsQuery = Objects.requireNonNull(selectStoredRequestsQuery);
         this.selectAmpStoredRequestsQuery = Objects.requireNonNull(selectAmpStoredRequestsQuery);
+<<<<<<< HEAD
         this.selectProfilesQuery = selectProfilesQuery;
         this.selectStoredResponsesQuery = Objects.requireNonNull(selectStoredResponsesQuery);
     }
 
+=======
+        this.selectStoredResponsesQuery = Objects.requireNonNull(selectStoredResponsesQuery);
+    }
+
+    /**
+     * Runs a process to get account by id from database
+     * and returns {@link Future}<{@link Account}>.
+     */
+>>>>>>> 04d9d4a13 (Initial commit)
     @Override
     public Future getAccountById(String accountId, Timeout timeout) {
         return databaseClient.executeQuery(
@@ -113,12 +146,26 @@ public Future getAccountById(String accountId, Timeout timeout) {
                         Collections.singletonList(accountId),
                         result -> mapToModelOrError(result, this::toAccount),
                         timeout)
+<<<<<<< HEAD
                 .compose(result -> result != null
                         ? Future.succeededFuture(result)
                         : Future.failedFuture(new PreBidException("Account not found: " + accountId)));
     }
 
     /**
+=======
+                .compose(result -> failedIfNull(result, accountId, "Account"));
+    }
+
+    @Override
+    public Future> getCategories(String primaryAdServer, String publisher, Timeout timeout) {
+        return Future.failedFuture(new PreBidException("Not supported"));
+    }
+
+    /**
+     * Transforms the first row of {@link RowSet} to required object or returns null.
+     * 

+>>>>>>> 04d9d4a13 (Initial commit) * Note: mapper should never throw exception in case of using * {@link CircuitBreakerSecuredDatabaseClient}. */ @@ -129,6 +176,19 @@ private T mapToModelOrError(RowSet rowSet, Function mapper) { : null; } +<<<<<<< HEAD +======= + /** + * Returns succeeded {@link Future} if given value is not equal to NULL, + * otherwise failed {@link Future} with {@link PreBidException}. + */ + private static Future failedIfNull(T value, String id, String errorPrefix) { + return value != null + ? Future.succeededFuture(value) + : Future.failedFuture(new PreBidException("%s not found: %s".formatted(errorPrefix, id))); + } + +>>>>>>> 04d9d4a13 (Initial commit) private Account toAccount(Row row) { final String source = ObjectUtil.getIfNotNull(row.getValue(0), Object::toString); try { @@ -138,6 +198,7 @@ private Account toAccount(Row row) { } } +<<<<<<< HEAD @Override public Future> getStoredData(String accountId, Set requestIds, @@ -228,6 +289,47 @@ private Future> fetchStoredData(String query, public Future getStoredResponses(Set responseIds, Timeout timeout) { final String queryResolvedWithParameters = parametrizedQueryHelper .replaceStoredResponseIdPlaceholders(selectStoredResponsesQuery, responseIds.size()); +======= + /** + * Runs a process to get stored requests by a collection of ids from database + * and returns {@link Future}<{@link StoredDataResult}>. + */ + @Override + public Future getStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout) { + return fetchStoredData(selectStoredRequestsQuery, accountId, requestIds, impIds, timeout); + } + + /** + * Runs a process to get stored requests by a collection of amp ids from database + * and returns {@link Future}<{@link StoredDataResult}>. + */ + @Override + public Future getAmpStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout) { + return fetchStoredData(selectAmpStoredRequestsQuery, accountId, requestIds, Collections.emptySet(), timeout); + } + + /** + * Runs a process to get stored requests by a collection of video ids from database + * and returns {@link Future}<{@link StoredDataResult}>. + */ + @Override + public Future getVideoStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout) { + return fetchStoredData(selectStoredRequestsQuery, accountId, requestIds, impIds, timeout); + } + + /** + * Runs a process to get stored responses by a collection of ids from database + * and returns {@link Future}<{@link StoredResponseDataResult}>. + */ + @Override + public Future getStoredResponses(Set responseIds, Timeout timeout) { + final String queryResolvedWithParameters = parametrizedQueryHelper.replaceStoredResponseIdPlaceholders( + selectStoredResponsesQuery, + responseIds.size()); +>>>>>>> 04d9d4a13 (Initial commit) final List idsQueryParameters = new ArrayList<>(); final int responseIdPlaceholderCount = StringUtils.countMatches( @@ -236,6 +338,7 @@ public Future getStoredResponses(Set responseI IntStream.rangeClosed(1, responseIdPlaceholderCount) .forEach(i -> idsQueryParameters.addAll(responseIds)); +<<<<<<< HEAD return databaseClient.executeQuery( queryResolvedWithParameters, idsQueryParameters, @@ -246,5 +349,39 @@ public Future getStoredResponses(Set responseI @Override public Future> getCategories(String primaryAdServer, String publisher, Timeout timeout) { return Future.failedFuture(new PreBidException("Not supported")); +======= + return databaseClient.executeQuery(queryResolvedWithParameters, idsQueryParameters, + result -> DatabaseStoredResponseResultMapper.map(result, responseIds), timeout); + } + + /** + * Fetches stored requests from database for the given query. + */ + private Future fetchStoredData(String query, String accountId, Set requestIds, + Set impIds, Timeout timeout) { + final Future future; + + if (CollectionUtils.isEmpty(requestIds) && CollectionUtils.isEmpty(impIds)) { + future = Future.succeededFuture( + StoredDataResult.of(Collections.emptyMap(), Collections.emptyMap(), Collections.emptyList())); + } else { + final List idsQueryParameters = new ArrayList<>(); + IntStream.rangeClosed(1, StringUtils.countMatches(query, ParametrizedQueryHelper.REQUEST_ID_PLACEHOLDER)) + .forEach(i -> idsQueryParameters.addAll(requestIds)); + IntStream.rangeClosed(1, StringUtils.countMatches(query, ParametrizedQueryHelper.IMP_ID_PLACEHOLDER)) + .forEach(i -> idsQueryParameters.addAll(impIds)); + + final String parametrizedQuery = parametrizedQueryHelper.replaceRequestAndImpIdPlaceholders( + query, + requestIds.size(), + impIds.size()); + + future = databaseClient.executeQuery(parametrizedQuery, idsQueryParameters, + result -> DatabaseStoredDataResultMapper.map(result, accountId, requestIds, impIds), + timeout); + } + + return future; +>>>>>>> 04d9d4a13 (Initial commit) } } diff --git a/src/main/java/org/prebid/server/settings/EnrichingApplicationSettings.java b/src/main/java/org/prebid/server/settings/EnrichingApplicationSettings.java index 5d1875c742c..759a837699d 100644 --- a/src/main/java/org/prebid/server/settings/EnrichingApplicationSettings.java +++ b/src/main/java/org/prebid/server/settings/EnrichingApplicationSettings.java @@ -12,7 +12,10 @@ import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.AccountAuctionConfig; import org.prebid.server.settings.model.AccountPriceFloorsConfig; +<<<<<<< HEAD import org.prebid.server.settings.model.Profile; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.settings.model.StoredDataResult; import org.prebid.server.settings.model.StoredResponseDataResult; @@ -47,6 +50,7 @@ public EnrichingApplicationSettings(boolean enforceValidAccount, this.defaultAccount = parseAccount(defaultAccountConfig, mapper); } +<<<<<<< HEAD private static Account parseAccount(String accountConfig, JacksonMapper mapper) { try { return StringUtils.isNotBlank(accountConfig) @@ -57,6 +61,8 @@ private static Account parseAccount(String accountConfig, JacksonMapper mapper) } } +======= +>>>>>>> 04d9d4a13 (Initial commit) @Override public Future getAccountById(String accountId, Timeout timeout) { if (StringUtils.isNotBlank(accountId)) { @@ -70,12 +76,15 @@ public Future getAccountById(String accountId, Timeout timeout) { return recoverIfNeeded(new PreBidException("Unauthorized account: account id is empty"), StringUtils.EMPTY); } +<<<<<<< HEAD private Account mergeAccounts(Account account) { return defaultAccount == null ? account : jsonMerger.merge(account, defaultAccount, Account.class); } +======= +>>>>>>> 04d9d4a13 (Initial commit) private AccountPriceFloorsConfig extractDefaultPriceFloors() { return Optional.ofNullable(defaultAccount) .map(Account::getAuction) @@ -83,6 +92,7 @@ private AccountPriceFloorsConfig extractDefaultPriceFloors() { .orElse(null); } +<<<<<<< HEAD private Future recoverIfNeeded(Throwable throwable, String accountId) { // In case of invalid account return failed future return enforceValidAccount @@ -95,11 +105,29 @@ public Future> getStoredData(String accountId, Set requestIds, Set impIds, Timeout timeout) { +======= + private static Account parseAccount(String accountConfig, JacksonMapper mapper) { + try { + return StringUtils.isNotBlank(accountConfig) + ? mapper.decodeValue(accountConfig, Account.class) + : null; + } catch (DecodeException e) { + throw new IllegalArgumentException("Could not parse default account configuration", e); + } + } + + @Override + public Future getStoredData(String accountId, + Set requestIds, + Set impIds, + Timeout timeout) { +>>>>>>> 04d9d4a13 (Initial commit) return delegate.getStoredData(accountId, requestIds, impIds, timeout); } @Override +<<<<<<< HEAD public Future> getAmpStoredData(String accountId, Set requestIds, Set impIds, @@ -127,6 +155,8 @@ public Future> getProfiles(String accountId, } @Override +======= +>>>>>>> 04d9d4a13 (Initial commit) public Future getStoredResponses(Set responseIds, Timeout timeout) { return delegate.getStoredResponses(responseIds, timeout); } @@ -135,4 +165,38 @@ public Future getStoredResponses(Set responseI public Future> getCategories(String primaryAdServer, String publisher, Timeout timeout) { return delegate.getCategories(primaryAdServer, publisher, timeout); } +<<<<<<< HEAD +======= + + @Override + public Future getAmpStoredData(String accountId, + Set requestIds, + Set impIds, + Timeout timeout) { + + return delegate.getAmpStoredData(accountId, requestIds, impIds, timeout); + } + + @Override + public Future getVideoStoredData(String accountId, + Set requestIds, + Set impIds, + Timeout timeout) { + + return delegate.getVideoStoredData(accountId, requestIds, impIds, timeout); + } + + private Account mergeAccounts(Account account) { + return defaultAccount == null + ? account + : jsonMerger.merge(account, defaultAccount, Account.class); + } + + private Future recoverIfNeeded(Throwable throwable, String accountId) { + // In case of invalid account return failed future + return enforceValidAccount + ? Future.failedFuture(throwable) + : Future.succeededFuture(mergeAccounts(Account.empty(accountId))); + } +>>>>>>> 04d9d4a13 (Initial commit) } diff --git a/src/main/java/org/prebid/server/settings/FileApplicationSettings.java b/src/main/java/org/prebid/server/settings/FileApplicationSettings.java index b5930b0123f..e4dbb8ea65f 100644 --- a/src/main/java/org/prebid/server/settings/FileApplicationSettings.java +++ b/src/main/java/org/prebid/server/settings/FileApplicationSettings.java @@ -6,12 +6,16 @@ import io.vertx.core.buffer.Buffer; import io.vertx.core.file.FileSystem; import org.apache.commons.collections4.CollectionUtils; +<<<<<<< HEAD import org.apache.commons.collections4.SetUtils; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.apache.commons.lang3.StringUtils; import org.prebid.server.exception.PreBidException; import org.prebid.server.execution.timeout.Timeout; import org.prebid.server.json.DecodeException; import org.prebid.server.json.JacksonMapper; +<<<<<<< HEAD import org.prebid.server.settings.helper.StoredItemResolver; import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.Category; @@ -20,13 +24,25 @@ import org.prebid.server.settings.model.StoredDataResult; import org.prebid.server.settings.model.StoredDataType; import org.prebid.server.settings.model.StoredItem; +======= +import org.prebid.server.settings.model.Account; +import org.prebid.server.settings.model.Category; +import org.prebid.server.settings.model.SettingsFile; +import org.prebid.server.settings.model.StoredDataResult; +import org.prebid.server.settings.model.StoredDataType; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.settings.model.StoredResponseDataResult; import java.io.File; import java.io.IOException; +<<<<<<< HEAD import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +======= +import java.util.Collection; +import java.util.Collections; +>>>>>>> 04d9d4a13 (Initial commit) import java.util.List; import java.util.Map; import java.util.Objects; @@ -53,6 +69,7 @@ public class FileApplicationSettings implements ApplicationSettings { private final Map accounts; private final Map storedIdToRequest; private final Map storedIdToImp; +<<<<<<< HEAD private final Map>> profileIdToProfile; private final Map storedIdToSeatBid; private final Map> fileToCategories; @@ -155,10 +172,31 @@ private static Map parseCategories(String filepath, } catch (DecodeException e) { throw new PreBidException("Failed to decode categories for file " + filepath); } +======= + private final Map storedIdToSeatBid; + private final Map> fileToCategories; + + public FileApplicationSettings(FileSystem fileSystem, String settingsFileName, String storedRequestsDir, + String storedImpsDir, String storedResponsesDir, String categoriesDir, + JacksonMapper jacksonMapper) { + + final SettingsFile settingsFile = readSettingsFile(Objects.requireNonNull(fileSystem), + Objects.requireNonNull(settingsFileName)); + + accounts = toMap(settingsFile.getAccounts(), + Account::getId, + Function.identity()); + + this.storedIdToRequest = readStoredData(fileSystem, Objects.requireNonNull(storedRequestsDir)); + this.storedIdToImp = readStoredData(fileSystem, Objects.requireNonNull(storedImpsDir)); + this.storedIdToSeatBid = readStoredData(fileSystem, Objects.requireNonNull(storedResponsesDir)); + this.fileToCategories = readCategories(fileSystem, Objects.requireNonNull(categoriesDir), jacksonMapper); +>>>>>>> 04d9d4a13 (Initial commit) } @Override public Future getAccountById(String accountId, Timeout timeout) { +<<<<<<< HEAD final Account account = accounts.get(accountId); return account != null ? Future.succeededFuture(account) @@ -187,19 +225,53 @@ public Future> getStoredData(String accountId, Stream.concat( errorsForMissedIds(requestIds, storedRequests.keySet(), StoredDataType.request.name()), errorsForMissedIds(impIds, storedImps.keySet(), StoredDataType.imp.name())) +======= + return mapValueToFuture(accounts, accountId, "Account"); + } + + /** + * Creates {@link StoredDataResult} by checking if any ids are missed in storedRequest map + * and adding an error to list for each missed Id + * and returns {@link Future<{@link StoredDataResult }>} with all loaded files and errors list. + */ + @Override + public Future getStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout) { + return Future.succeededFuture(CollectionUtils.isEmpty(requestIds) && CollectionUtils.isEmpty(impIds) + ? StoredDataResult.of(Collections.emptyMap(), Collections.emptyMap(), Collections.emptyList()) + : StoredDataResult.of( + existingStoredIdToJson(requestIds, storedIdToRequest), + existingStoredIdToJson(impIds, storedIdToImp), + Stream.of( + errorsForMissedIds(requestIds, storedIdToRequest, StoredDataType.request), + errorsForMissedIds(impIds, storedIdToImp, StoredDataType.imp)) + .flatMap(Collection::stream) +>>>>>>> 04d9d4a13 (Initial commit) .toList())); } @Override +<<<<<<< HEAD public Future> getAmpStoredData(String accountId, Set requestIds, Set impIds, Timeout timeout) { +======= + public Future getAmpStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout) { + return getStoredData(accountId, requestIds, Collections.emptySet(), timeout); + } + + @Override + public Future getVideoStoredData(String accountId, Set requestIds, Set impIds, + Timeout timeout) { +>>>>>>> 04d9d4a13 (Initial commit) return getStoredData(accountId, requestIds, impIds, timeout); } @Override +<<<<<<< HEAD public Future> getVideoStoredData(String accountId, Set requestIds, Set impIds, @@ -279,11 +351,16 @@ public Future getStoredResponses(Set responseI } @Override +======= +>>>>>>> 04d9d4a13 (Initial commit) public Future> getCategories(String primaryAdServer, String publisher, Timeout timeout) { final String filename = StringUtils.isNotBlank(publisher) ? "%s_%s".formatted(primaryAdServer, publisher) : primaryAdServer; +<<<<<<< HEAD +======= +>>>>>>> 04d9d4a13 (Initial commit) final Map categoryToId = fileToCategories.get(filename); return categoryToId != null ? Future.succeededFuture(extractCategoriesIds(categoryToId)) @@ -294,6 +371,7 @@ public Future> getCategories(String primaryAdServer, String private static Map extractCategoriesIds(Map categoryToId) { return categoryToId.entrySet().stream() .filter(catToCategory -> catToCategory.getValue() != null) +<<<<<<< HEAD .collect(Collectors.toMap( Map.Entry::getKey, catToCategory -> catToCategory.getValue().getId())); @@ -302,13 +380,112 @@ private static Map extractCategoriesIds(Map ca private static Map existingStoredIdToJson(Set requestedIds, Map storedIdToJson) { +======= + .collect(Collectors.toMap(Map.Entry::getKey, + catToCategory -> catToCategory.getValue().getId())); + } + + /** + * Creates {@link StoredResponseDataResult} by checking if any ids are missed in storedResponse map + * and adding an error to list for each missed Id + * and returns {@link Future<{@link StoredResponseDataResult }>} with all loaded files and errors list. + */ + @Override + public Future getStoredResponses(Set responseIds, Timeout timeout) { + return Future.succeededFuture(CollectionUtils.isEmpty(responseIds) + ? StoredResponseDataResult.of(Collections.emptyMap(), Collections.emptyList()) + : StoredResponseDataResult.of( + existingStoredIdToJson(responseIds, storedIdToSeatBid), + errorsForMissedIds(responseIds, storedIdToSeatBid, StoredDataType.seatbid))); + } + + private static Map toMap(List list, Function keyMapper, Function valueMapper) { + return list != null ? list.stream().collect(Collectors.toMap(keyMapper, valueMapper)) : Collections.emptyMap(); + } + + /** + * Reading YAML settings file. + */ + private static SettingsFile readSettingsFile(FileSystem fileSystem, String fileName) { + final Buffer buf = fileSystem.readFileBlocking(fileName); + try { + return new YAMLMapper().readValue(buf.getBytes(), SettingsFile.class); + } catch (IOException e) { + throw new IllegalArgumentException("Couldn't read file settings", e); + } + } + + /** + * Reads files with .json extension in configured directory and creates {@link Map} where key is a file name + * without .json extension and value is file content. + */ + private static Map readStoredData(FileSystem fileSystem, String dir) { + return fileSystem.readDirBlocking(dir).stream() + .filter(filepath -> filepath.endsWith(JSON_SUFFIX)) + .collect(Collectors.toMap(filepath -> StringUtils.removeEnd(new File(filepath).getName(), JSON_SUFFIX), + filename -> fileSystem.readFileBlocking(filename).toString())); + } + + /** + * Reads files with .json extension in configured directory and creates {@link Map} where key is a file name + * without .json and value is file content parsed to a {@link Map} where key is category and value is + * {@link Category}. + */ + private static Map> readCategories(FileSystem fileSystem, String dir, + JacksonMapper jacksonMapper) { + return fileSystem.readDirBlocking(dir).stream() + .filter(filepath -> filepath.endsWith(JSON_SUFFIX)) + .collect(Collectors.toMap(filepath -> StringUtils.removeEnd(new File(filepath).getName(), JSON_SUFFIX), + filename -> parseCategories(filename, fileSystem.readFileBlocking(filename), jacksonMapper))); + } + + /** + * Parses {@link Buffer} to a {@link Map} where key is category and value {@link Category}. + */ + private static Map parseCategories(String fileName, Buffer categoriesBuffer, + JacksonMapper jacksonMapper) { + try { + return jacksonMapper.decodeValue(categoriesBuffer, CATEGORY_FORMAT_REFERENCE); + } catch (DecodeException e) { + throw new PreBidException("Failed to decode categories for file " + fileName); + } + } + + private static Future mapValueToFuture(Map map, String id, String errorPrefix) { + final T value = map.get(id); + return value != null + ? Future.succeededFuture(value) + : Future.failedFuture(new PreBidException("%s not found: %s".formatted(errorPrefix, id))); + } + + /** + * Returns corresponding stored id with json. + */ + private static Map existingStoredIdToJson(Set requestedIds, + Map storedIdToJson) { +>>>>>>> 04d9d4a13 (Initial commit) return requestedIds.stream() .filter(storedIdToJson::containsKey) .collect(Collectors.toMap(Function.identity(), storedIdToJson::get)); } +<<<<<<< HEAD private static Stream errorsForMissedIds(Set requestedIds, Set foundIds, String type) { return SetUtils.difference(requestedIds, foundIds).stream() .map(id -> "No stored %s found for id: %s".formatted(type, id)); +======= + /** + * Returns errors for missed IDs. + */ + private static List errorsForMissedIds(Set ids, Map storedIdToJson, + StoredDataType type) { + final List missedIds = ids.stream() + .filter(id -> !storedIdToJson.containsKey(id)) + .toList(); + + return missedIds.isEmpty() ? Collections.emptyList() : missedIds.stream() + .map(id -> "No stored %s found for id: %s".formatted(type, id)) + .toList(); +>>>>>>> 04d9d4a13 (Initial commit) } } diff --git a/src/main/java/org/prebid/server/settings/HttpApplicationSettings.java b/src/main/java/org/prebid/server/settings/HttpApplicationSettings.java index c0d899508c4..58f70749443 100644 --- a/src/main/java/org/prebid/server/settings/HttpApplicationSettings.java +++ b/src/main/java/org/prebid/server/settings/HttpApplicationSettings.java @@ -17,7 +17,10 @@ import org.prebid.server.log.LoggerFactory; import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.Category; +<<<<<<< HEAD import org.prebid.server.settings.model.Profile; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.settings.model.StoredDataResult; import org.prebid.server.settings.model.StoredDataType; import org.prebid.server.settings.model.StoredResponseDataResult; @@ -38,7 +41,10 @@ import java.util.Set; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; +<<<<<<< HEAD import java.util.stream.Stream; +======= +>>>>>>> 04d9d4a13 (Initial commit) /** * Implementation of {@link ApplicationSettings}. @@ -54,8 +60,13 @@ *

* or settings.http.rfc3986-compatible is set to true *

+<<<<<<< HEAD * * GET {endpoint}?request-id=req1&request-id=req2&imp-id=imp1&imp-id=imp2&imp-id=imp3 * *

+======= + * * GET {endpoint}?request-id=req1&request-id=req2&imp-id=imp1&imp-id=imp2&imp-id=imp3 + * *

+>>>>>>> 04d9d4a13 (Initial commit) * This endpoint should return a payload like: *

  * {
@@ -78,29 +89,50 @@ public class HttpApplicationSettings implements ApplicationSettings {
             new TypeReference<>() {
             };
 
+<<<<<<< HEAD
     private final boolean isRfc3986Compatible;
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
     private final String endpoint;
     private final String ampEndpoint;
     private final String videoEndpoint;
     private final String categoryEndpoint;
     private final HttpClient httpClient;
     private final JacksonMapper mapper;
+<<<<<<< HEAD
 
     public HttpApplicationSettings(boolean isRfc3986Compatible,
+=======
+    private final boolean isRfc3986Compatible;
+
+    public HttpApplicationSettings(HttpClient httpClient,
+                                   JacksonMapper mapper,
+>>>>>>> 04d9d4a13 (Initial commit)
                                    String endpoint,
                                    String ampEndpoint,
                                    String videoEndpoint,
                                    String categoryEndpoint,
+<<<<<<< HEAD
                                    HttpClient httpClient,
                                    JacksonMapper mapper) {
 
         this.isRfc3986Compatible = isRfc3986Compatible;
+=======
+                                   boolean isRfc3986Compatible) {
+
+        this.httpClient = Objects.requireNonNull(httpClient);
+        this.mapper = Objects.requireNonNull(mapper);
+>>>>>>> 04d9d4a13 (Initial commit)
         this.endpoint = HttpUtil.validateUrlSyntax(Objects.requireNonNull(endpoint));
         this.ampEndpoint = HttpUtil.validateUrlSyntax(Objects.requireNonNull(ampEndpoint));
         this.videoEndpoint = HttpUtil.validateUrlSyntax(Objects.requireNonNull(videoEndpoint));
         this.categoryEndpoint = HttpUtil.validateUrlSyntax(Objects.requireNonNull(categoryEndpoint));
+<<<<<<< HEAD
         this.httpClient = Objects.requireNonNull(httpClient);
         this.mapper = Objects.requireNonNull(mapper);
+=======
+        this.isRfc3986Compatible = isRfc3986Compatible;
+>>>>>>> 04d9d4a13 (Initial commit)
     }
 
     @Override
@@ -116,14 +148,22 @@ private Future> fetchAccountsByIds(Set accountIds, Timeout
         if (CollectionUtils.isEmpty(accountIds)) {
             return Future.succeededFuture(Collections.emptySet());
         }
+<<<<<<< HEAD
 
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
         final long remainingTimeout = timeout.remaining();
         if (timeout.remaining() <= 0) {
             return Future.failedFuture(new TimeoutException("Timeout has been exceeded"));
         }
 
         return httpClient.get(accountsRequestUrlFrom(endpoint, accountIds), HttpUtil.headers(), remainingTimeout)
+<<<<<<< HEAD
                 .map(response -> processAccountsResponse(response, accountIds));
+=======
+                .compose(response -> processAccountsResponse(response, accountIds))
+                .recover(Future::failedFuture);
+>>>>>>> 04d9d4a13 (Initial commit)
     }
 
     private String accountsRequestUrlFrom(String endpoint, Set accountIds) {
@@ -142,8 +182,17 @@ private String accountsRequestUrlFrom(String endpoint, Set accountIds) {
         }
     }
 
+<<<<<<< HEAD
     private Set processAccountsResponse(HttpClientResponse httpClientResponse, Set accountIds) {
         final int statusCode = httpClientResponse.getStatusCode();
+=======
+    private Future> processAccountsResponse(HttpClientResponse response, Set accountIds) {
+        return Future.succeededFuture(
+                toAccountsResult(response.getStatusCode(), response.getBody(), accountIds));
+    }
+
+    private Set toAccountsResult(int statusCode, String body, Set accountIds) {
+>>>>>>> 04d9d4a13 (Initial commit)
         if (statusCode != HttpResponseStatus.OK.code()) {
             throw new PreBidException("Error fetching accounts %s via http: unexpected response status %d"
                     .formatted(accountIds, statusCode));
@@ -151,7 +200,11 @@ private Set processAccountsResponse(HttpClientResponse httpClientRespon
 
         final HttpAccountsResponse response;
         try {
+<<<<<<< HEAD
             response = mapper.decodeValue(httpClientResponse.getBody(), HttpAccountsResponse.class);
+=======
+            response = mapper.decodeValue(body, HttpAccountsResponse.class);
+>>>>>>> 04d9d4a13 (Initial commit)
         } catch (DecodeException e) {
             throw new PreBidException("Error fetching accounts %s via http: failed to parse response: %s"
                     .formatted(accountIds, e.getMessage()));
@@ -161,6 +214,7 @@ private Set processAccountsResponse(HttpClientResponse httpClientRespon
         return MapUtils.isNotEmpty(accounts) ? new HashSet<>(accounts.values()) : Collections.emptySet();
     }
 
+<<<<<<< HEAD
     @Override
     public Future> getStoredData(String accountId,
                                                           Set requestIds,
@@ -176,10 +230,30 @@ public Future> getAmpStoredData(String accountId,
                                                              Set impIds,
                                                              Timeout timeout) {
 
+=======
+    /**
+     * Runs a process to get stored requests by a collection of ids from http service
+     * and returns {@link Future<{@link StoredDataResult }>}
+     */
+    @Override
+    public Future getStoredData(String accountId, Set requestIds, Set impIds,
+                                                  Timeout timeout) {
+        return fetchStoredData(endpoint, requestIds, impIds, timeout);
+    }
+
+    /**
+     * Runs a process to get stored requests by a collection of amp ids from http service
+     * and returns {@link Future<{@link StoredDataResult }>}
+     */
+    @Override
+    public Future getAmpStoredData(String accountId, Set requestIds, Set impIds,
+                                                     Timeout timeout) {
+>>>>>>> 04d9d4a13 (Initial commit)
         return fetchStoredData(ampEndpoint, requestIds, Collections.emptySet(), timeout);
     }
 
     @Override
+<<<<<<< HEAD
     public Future> getVideoStoredData(String accountId,
                                                                Set requestIds,
                                                                Set impIds,
@@ -193,6 +267,64 @@ private Future> fetchStoredData(String endpoint,
                                                              Set impIds,
                                                              Timeout timeout) {
 
+=======
+    public Future getVideoStoredData(String accountId, Set requestIds, Set impIds,
+                                                       Timeout timeout) {
+        return fetchStoredData(videoEndpoint, requestIds, impIds, timeout);
+    }
+
+    /**
+     * Not supported and returns failed result.
+     */
+    @Override
+    public Future getStoredResponses(Set responseIds, Timeout timeout) {
+        return Future.failedFuture(new PreBidException("Not supported"));
+    }
+
+    @Override
+    public Future> getCategories(String primaryAdServer, String publisher, Timeout timeout) {
+        final String url = StringUtils.isNotEmpty(publisher)
+                ? "%s/%s/%s.json".formatted(categoryEndpoint, primaryAdServer, publisher)
+                : "%s/%s.json".formatted(categoryEndpoint, primaryAdServer);
+        final long remainingTimeout = timeout.remaining();
+        if (remainingTimeout <= 0) {
+            return Future.failedFuture(new TimeoutException(
+                    "Failed to fetch categories from url '%s'. Reason: Timeout exceeded".formatted(url)));
+        }
+        return httpClient.get(url, remainingTimeout)
+                .map(httpClientResponse -> processCategoryResponse(httpClientResponse, url));
+    }
+
+    private Map processCategoryResponse(HttpClientResponse httpClientResponse, String url) {
+        final int statusCode = httpClientResponse.getStatusCode();
+        if (statusCode != 200) {
+            throw makeFailedCategoryFetchException(url, "Response status code is '%d'".formatted(statusCode));
+        }
+
+        final String body = httpClientResponse.getBody();
+        if (StringUtils.isEmpty(body)) {
+            throw makeFailedCategoryFetchException(url, "Response body is null or empty");
+        }
+
+        final Map categories;
+        try {
+            categories = mapper.decodeValue(body, CATEGORY_RESPONSE_REFERENCE);
+        } catch (DecodeException e) {
+            throw makeFailedCategoryFetchException(url, "Failed to decode response body with error " + e.getMessage());
+        }
+        return categories.entrySet().stream()
+                .filter(catToCategory -> catToCategory.getValue() != null)
+                .collect(Collectors.toMap(Map.Entry::getKey,
+                        catToCategory -> catToCategory.getValue().getId()));
+    }
+
+    private PreBidException makeFailedCategoryFetchException(String url, String reason) {
+        return new PreBidException("Failed to fetch categories from url '%s'. Reason: %s".formatted(url, reason));
+    }
+
+    private Future fetchStoredData(String endpoint, Set requestIds, Set impIds,
+                                                     Timeout timeout) {
+>>>>>>> 04d9d4a13 (Initial commit)
         if (CollectionUtils.isEmpty(requestIds) && CollectionUtils.isEmpty(impIds)) {
             return Future.succeededFuture(
                     StoredDataResult.of(Collections.emptyMap(), Collections.emptyMap(), Collections.emptyList()));
@@ -204,6 +336,7 @@ private Future> fetchStoredData(String endpoint,
         }
 
         return httpClient.get(storeRequestUrlFrom(endpoint, requestIds, impIds), HttpUtil.headers(), remainingTimeout)
+<<<<<<< HEAD
                 .map(response -> processStoredDataResponse(response, requestIds, impIds))
                 .recover(exception -> failStoredDataResponse(exception, requestIds, impIds));
     }
@@ -231,6 +364,12 @@ private static StoredDataResult toFailedStoredDataResult(Set req
         return StoredDataResult.of(Collections.emptyMap(), Collections.emptyMap(), Collections.singletonList(error));
     }
 
+=======
+                .compose(response -> processStoredDataResponse(response, requestIds, impIds))
+                .recover(exception -> failStoredDataResponse(exception, requestIds, impIds));
+    }
+
+>>>>>>> 04d9d4a13 (Initial commit)
     private String storeRequestUrlFrom(String endpoint, Set requestIds, Set impIds) {
         try {
             final URIBuilder uriBuilder = new URIBuilder(endpoint);
@@ -254,16 +393,54 @@ private String storeRequestUrlFrom(String endpoint, Set requestIds, Set<
         }
     }
 
+<<<<<<< HEAD
     private StoredDataResult processStoredDataResponse(HttpClientResponse httpClientResponse,
                                                                Set requestIds,
                                                                Set impIds) {
 
         final int statusCode = httpClientResponse.getStatusCode();
+=======
+    private static String joinIds(Set ids) {
+        return String.join("\",\"", ids);
+    }
+
+    private static Future failStoredDataResponse(Throwable throwable, Set requestIds,
+                                                                   Set impIds) {
+        return Future.succeededFuture(
+                toFailedStoredDataResult(requestIds, impIds, throwable.getMessage()));
+    }
+
+    private Future processStoredDataResponse(HttpClientResponse response, Set requestIds,
+                                                               Set impIds) {
+        return Future.succeededFuture(
+                toStoredDataResult(requestIds, impIds, response.getStatusCode(), response.getBody()));
+    }
+
+    private static StoredDataResult toFailedStoredDataResult(Set requestIds, Set impIds,
+                                                             String errorMessageFormat, Object... args) {
+        final String errorRequests = requestIds.isEmpty() ? ""
+                : "stored requests for ids " + requestIds;
+        final String separator = requestIds.isEmpty() || impIds.isEmpty() ? "" : " and ";
+        final String errorImps = impIds.isEmpty() ? "" : "stored imps for ids " + impIds;
+
+        final String error = "Error fetching %s%s%s via HTTP: %s"
+                .formatted(errorRequests, separator, errorImps, errorMessageFormat.formatted(args));
+
+        logger.info(error);
+        return StoredDataResult.of(Collections.emptyMap(), Collections.emptyMap(), Collections.singletonList(error));
+    }
+
+    private StoredDataResult toStoredDataResult(Set requestIds, Set impIds,
+                                                int statusCode, String body) {
+>>>>>>> 04d9d4a13 (Initial commit)
         if (statusCode != HttpResponseStatus.OK.code()) {
             return toFailedStoredDataResult(requestIds, impIds, "HTTP status code %d", statusCode);
         }
 
+<<<<<<< HEAD
         final String body = httpClientResponse.getBody();
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
         final HttpFetcherResponse response;
         try {
             response = mapper.decodeValue(body, HttpFetcherResponse.class);
@@ -275,10 +452,15 @@ private StoredDataResult processStoredDataResponse(HttpClientResponse ht
         return parseResponse(requestIds, impIds, response);
     }
 
+<<<<<<< HEAD
     private StoredDataResult parseResponse(Set requestIds,
                                                    Set impIds,
                                                    HttpFetcherResponse response) {
 
+=======
+    private StoredDataResult parseResponse(Set requestIds, Set impIds,
+                                           HttpFetcherResponse response) {
+>>>>>>> 04d9d4a13 (Initial commit)
         final List errors = new ArrayList<>();
 
         final Map storedIdToRequest =
@@ -290,12 +472,19 @@ private StoredDataResult parseResponse(Set requestIds,
         return StoredDataResult.of(storedIdToRequest, storedIdToImp, errors);
     }
 
+<<<<<<< HEAD
     private Map parseStoredDataOrAddError(Set ids,
                                                           Map storedData,
                                                           StoredDataType type,
                                                           List errors) {
 
         final Map result = new HashMap<>(ids.size());
+=======
+    private Map parseStoredDataOrAddError(Set ids, Map storedData,
+                                                          StoredDataType type, List errors) {
+        final Map result = new HashMap<>(ids.size());
+        final Set notParsedIds = new HashSet<>();
+>>>>>>> 04d9d4a13 (Initial commit)
 
         if (storedData != null) {
             for (Map.Entry entry : storedData.entrySet()) {
@@ -306,6 +495,10 @@ private Map parseStoredDataOrAddError(Set ids,
                     jsonAsString = mapper.mapper().writeValueAsString(entry.getValue());
                 } catch (JsonProcessingException e) {
                     errors.add("Error parsing %s json for id: %s with message: %s".formatted(type, id, e.getMessage()));
+<<<<<<< HEAD
+=======
+                    notParsedIds.add(id);
+>>>>>>> 04d9d4a13 (Initial commit)
                     continue;
                 }
 
@@ -316,12 +509,21 @@ private Map parseStoredDataOrAddError(Set ids,
         if (result.size() < ids.size()) {
             final Set missedIds = new HashSet<>(ids);
             missedIds.removeAll(result.keySet());
+<<<<<<< HEAD
 
             missedIds.forEach(id -> errors.add("Stored %s not found for id: %s".formatted(type, id)));
+=======
+            missedIds.removeAll(notParsedIds);
+
+            errors.addAll(missedIds.stream()
+                    .map(id -> "Stored %s not found for id: %s".formatted(type, id))
+                    .toList());
+>>>>>>> 04d9d4a13 (Initial commit)
         }
 
         return result;
     }
+<<<<<<< HEAD
 
     @Override
     public Future> getProfiles(String accountId,
@@ -390,4 +592,6 @@ private PreBidException makeFailedCategoryFetchException(String url, String reas
     private static String joinIds(Set ids) {
         return String.join("\",\"", ids);
     }
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
 }
diff --git a/src/main/java/org/prebid/server/settings/S3ApplicationSettings.java b/src/main/java/org/prebid/server/settings/S3ApplicationSettings.java
index c9b71c6e7ad..008c138ac91 100644
--- a/src/main/java/org/prebid/server/settings/S3ApplicationSettings.java
+++ b/src/main/java/org/prebid/server/settings/S3ApplicationSettings.java
@@ -12,7 +12,10 @@
 import org.prebid.server.json.DecodeException;
 import org.prebid.server.json.JacksonMapper;
 import org.prebid.server.settings.model.Account;
+<<<<<<< HEAD
 import org.prebid.server.settings.model.Profile;
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
 import org.prebid.server.settings.model.StoredDataResult;
 import org.prebid.server.settings.model.StoredResponseDataResult;
 import software.amazon.awssdk.core.BytesWrapper;
@@ -101,10 +104,17 @@ private static void validateAccount(Account account, String requestedAccountId)
     }
 
     @Override
+<<<<<<< HEAD
     public Future> getStoredData(String accountId,
                                                           Set requestIds,
                                                           Set impIds,
                                                           Timeout timeout) {
+=======
+    public Future getStoredData(String accountId,
+                                                  Set requestIds,
+                                                  Set impIds,
+                                                  Timeout timeout) {
+>>>>>>> 04d9d4a13 (Initial commit)
 
         return withTimeout(
                 () -> Future.all(
@@ -118,10 +128,17 @@ public Future> getStoredData(String accountId,
                         impIds));
     }
 
+<<<<<<< HEAD
     private StoredDataResult buildStoredDataResult(Map storedIdToRequest,
                                                            Map storedIdToImp,
                                                            Set requestIds,
                                                            Set impIds) {
+=======
+    private StoredDataResult buildStoredDataResult(Map storedIdToRequest,
+                                                   Map storedIdToImp,
+                                                   Set requestIds,
+                                                   Set impIds) {
+>>>>>>> 04d9d4a13 (Initial commit)
 
         final List errors = Stream.concat(
                         missingStoredDataIds(storedIdToImp, impIds).stream()
@@ -133,6 +150,7 @@ private StoredDataResult buildStoredDataResult(Map store
         return StoredDataResult.of(storedIdToRequest, storedIdToImp, errors);
     }
 
+<<<<<<< HEAD
     @Override
     public Future> getAmpStoredData(String accountId,
                                                              Set requestIds,
@@ -163,6 +181,28 @@ public Future> getProfiles(String accountId,
                 Stream.concat(requestIds.stream(), impIds.stream())
                         .map(id -> "Profile not found for id: " + id)
                         .toList()));
+=======
+    private Set missingStoredDataIds(Map fileContents, Set responseIds) {
+        return SetUtils.difference(responseIds, fileContents.keySet());
+    }
+
+    @Override
+    public Future getAmpStoredData(String accountId,
+                                                     Set requestIds,
+                                                     Set impIds,
+                                                     Timeout timeout) {
+
+        return getStoredData(accountId, requestIds, Collections.emptySet(), timeout);
+    }
+
+    @Override
+    public Future getVideoStoredData(String accountId,
+                                                       Set requestIds,
+                                                       Set impIds,
+                                                       Timeout timeout) {
+
+        return getStoredData(accountId, requestIds, impIds, timeout);
+>>>>>>> 04d9d4a13 (Initial commit)
     }
 
     @Override
@@ -235,8 +275,11 @@ private  Future withTimeout(Supplier> futureFactory, Timeout tim
 
         return promise.future();
     }
+<<<<<<< HEAD
 
     private Set missingStoredDataIds(Map fileContents, Set requestedIds) {
         return SetUtils.difference(requestedIds, fileContents.keySet());
     }
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
 }
diff --git a/src/main/java/org/prebid/server/settings/SettingsCache.java b/src/main/java/org/prebid/server/settings/SettingsCache.java
index 1066d0a121c..a994521e671 100644
--- a/src/main/java/org/prebid/server/settings/SettingsCache.java
+++ b/src/main/java/org/prebid/server/settings/SettingsCache.java
@@ -17,10 +17,17 @@
 /**
  * Just a simple wrapper over in-memory caches for requests and imps.
  */
+<<<<<<< HEAD
 public class SettingsCache implements CacheNotificationListener {
 
     private final Map>> requestCache;
     private final Map>> impCache;
+=======
+public class SettingsCache implements CacheNotificationListener {
+
+    private final Map> requestCache;
+    private final Map> impCache;
+>>>>>>> 04d9d4a13 (Initial commit)
 
     public SettingsCache(int ttl, int size, int jitter) {
         if (ttl <= 0 || size <= 0) {
@@ -47,6 +54,7 @@ public static  Map createCache(int ttlSeconds, int size, int jitte
                 .asMap();
     }
 
+<<<<<<< HEAD
     Map>> getRequestCache() {
         return requestCache;
     }
@@ -69,6 +77,30 @@ private static  void saveCachedValue(Map>> cache,
                                             T value) {
 
         final Set> values = ObjectUtils.defaultIfNull(cache.get(id), new HashSet<>());
+=======
+    Map> getRequestCache() {
+        return requestCache;
+    }
+
+    Map> getImpCache() {
+        return impCache;
+    }
+
+    void saveRequestCache(String accountId, String requestId, String requestValue) {
+        saveCachedValue(requestCache, accountId, requestId, requestValue);
+    }
+
+    void saveImpCache(String accountId, String impId, String impValue) {
+        saveCachedValue(impCache, accountId, impId, impValue);
+    }
+
+    private static void saveCachedValue(Map> cache,
+                                        String accountId,
+                                        String id,
+                                        String value) {
+
+        final Set values = ObjectUtils.defaultIfNull(cache.get(id), new HashSet<>());
+>>>>>>> 04d9d4a13 (Initial commit)
         values.add(StoredItem.of(accountId, value));
         cache.put(id, values);
     }
@@ -79,7 +111,11 @@ private static  void saveCachedValue(Map>> cache,
      * TODO: account should be added to all services uses this method
      */
     @Override
+<<<<<<< HEAD
     public void save(Map requests, Map imps) {
+=======
+    public void save(Map requests, Map imps) {
+>>>>>>> 04d9d4a13 (Initial commit)
         if (MapUtils.isNotEmpty(requests)) {
             requests.forEach((key, value) -> requestCache.put(key, Collections.singleton(StoredItem.of(null, value))));
         }
diff --git a/src/main/java/org/prebid/server/settings/helper/DatabaseStoredDataResultMapper.java b/src/main/java/org/prebid/server/settings/helper/DatabaseStoredDataResultMapper.java
index 6e37850a903..2970e5eb369 100644
--- a/src/main/java/org/prebid/server/settings/helper/DatabaseStoredDataResultMapper.java
+++ b/src/main/java/org/prebid/server/settings/helper/DatabaseStoredDataResultMapper.java
@@ -9,6 +9,10 @@
 import org.prebid.server.settings.model.StoredDataResult;
 import org.prebid.server.settings.model.StoredDataType;
 import org.prebid.server.settings.model.StoredItem;
+<<<<<<< HEAD
+=======
+import org.prebid.server.util.ObjectUtil;
+>>>>>>> 04d9d4a13 (Initial commit)
 import org.prebid.server.vertx.database.CircuitBreakerSecuredDatabaseClient;
 
 import java.util.ArrayList;
@@ -17,9 +21,17 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+<<<<<<< HEAD
 import java.util.Objects;
 import java.util.Set;
 
+=======
+import java.util.Set;
+
+/**
+ * Utility class for mapping {@link RowSet} to {@link StoredDataResult}.
+ */
+>>>>>>> 04d9d4a13 (Initial commit)
 public class DatabaseStoredDataResultMapper {
 
     private static final Logger logger = LoggerFactory.getLogger(DatabaseStoredDataResultMapper.class);
@@ -28,6 +40,7 @@ private DatabaseStoredDataResultMapper() {
     }
 
     /**
+<<<<<<< HEAD
      * Overloaded method for cases when no specific IDs are required, e.g. fetching all records.
      */
     public static StoredDataResult map(RowSet resultSet) {
@@ -160,5 +173,144 @@ private static Map storedItemsOrAddError(StoredDataType type,
         }
 
         return Collections.unmodifiableMap(result);
+=======
+     * Maps {@link RowSet} to {@link StoredDataResult} and creates an error for each missing ID and add it to result.
+     *
+     * @param rowSet     - incoming Row Set representing a result of SQL query
+     * @param accountId  - an account ID extracted from request
+     * @param requestIds - a specified set of stored requests' IDs. Adds error for each ID missing in result set
+     * @param impIds     - a specified set of stored imps' IDs. Adds error for each ID missing in result set
+     * @return - a {@link StoredDataResult} object
+     * 

+ * Note: mapper should never throw exception in case of using + * {@link CircuitBreakerSecuredDatabaseClient}. + */ + public static StoredDataResult map(RowSet rowSet, + String accountId, + Set requestIds, + Set impIds) { + final Map storedIdToRequest; + final Map storedIdToImp; + final List errors = new ArrayList<>(); + + final RowIterator rowIterator = rowSet != null ? rowSet.iterator() : null; + + if (rowIterator == null || !rowIterator.hasNext()) { + storedIdToRequest = Collections.emptyMap(); + storedIdToImp = Collections.emptyMap(); + + if (requestIds.isEmpty() && impIds.isEmpty()) { + errors.add("No stored requests or imps were found"); + } else { + final String errorRequests = requestIds.isEmpty() ? "" + : "stored requests for ids " + requestIds; + final String separator = requestIds.isEmpty() || impIds.isEmpty() ? "" : " and "; + final String errorImps = impIds.isEmpty() ? "" : "stored imps for ids " + impIds; + + errors.add("No %s%s%s were found".formatted(errorRequests, separator, errorImps)); + } + } else { + final Map> requestIdToStoredItems = new HashMap<>(); + final Map> impIdToStoredItems = new HashMap<>(); + + while (rowIterator.hasNext()) { + final Row row = rowIterator.next(); + if (row.toJson().size() < 4) { + final String message = "Error occurred while mapping stored request data: some columns are missing"; + logger.error(message); + errors.add(message); + return StoredDataResult.of(Collections.emptyMap(), Collections.emptyMap(), errors); + } + final String fetchedAccountId; + final String id; + final String data; + final String typeAsString; + try { + fetchedAccountId = ObjectUtil.getIfNotNull(row.getValue(0), Object::toString); + id = ObjectUtil.getIfNotNull(row.getValue(1), Object::toString); + data = ObjectUtil.getIfNotNull(row.getValue(2), Object::toString); + typeAsString = ObjectUtil.getIfNotNull(row.getValue(3), Object::toString); + } catch (ClassCastException e) { + final String message = "Error occurred while mapping stored request data"; + logger.error(message, e); + errors.add(message); + return StoredDataResult.of(Collections.emptyMap(), Collections.emptyMap(), errors); + } + + final StoredDataType type; + try { + type = StoredDataType.valueOf(typeAsString); + } catch (IllegalArgumentException e) { + logger.error("Stored request data with id={} has invalid type: ''{}'' and will be ignored.", e, + id, typeAsString); + continue; + } + + if (type == StoredDataType.request) { + addStoredItem(fetchedAccountId, id, data, requestIdToStoredItems); + } else { + addStoredItem(fetchedAccountId, id, data, impIdToStoredItems); + } + } + + storedIdToRequest = storedItemsOrAddError(StoredDataType.request, accountId, requestIds, + requestIdToStoredItems, errors); + storedIdToImp = storedItemsOrAddError(StoredDataType.imp, accountId, impIds, + impIdToStoredItems, errors); + } + + return StoredDataResult.of(storedIdToRequest, storedIdToImp, errors); + } + + /** + * Overloaded method for cases when no specific IDs are required, e.g. fetching all records. + * + * @param resultSet - incoming {@link RowSet} representing a result of SQL query. + * @return - a {@link StoredDataResult} object. + */ + public static StoredDataResult map(RowSet resultSet) { + return map(resultSet, null, Collections.emptySet(), Collections.emptySet()); + } + + private static void addStoredItem(String accountId, String id, String data, + Map> idToStoredItems) { + final StoredItem storedItem = StoredItem.of(accountId, data); + + final Set storedItems = idToStoredItems.get(id); + if (storedItems == null) { + idToStoredItems.put(id, new HashSet<>(Collections.singleton(storedItem))); + } else { + storedItems.add(storedItem); + } + } + + /** + * Returns map of stored ID -> value or populates error. + */ + private static Map storedItemsOrAddError(StoredDataType type, + String accountId, + Set searchIds, + Map> foundIdToStoredItems, + List errors) { + final Map result = new HashMap<>(); + + if (searchIds.isEmpty()) { + for (Map.Entry> entry : foundIdToStoredItems.entrySet()) { + entry.getValue().forEach(storedItem -> result.put(entry.getKey(), storedItem.getData())); + } + } else { + for (String id : searchIds) { + try { + final StoredItem resolvedStoredItem = StoredItemResolver.resolve(type, accountId, id, + foundIdToStoredItems.get(id)); + result.put(id, resolvedStoredItem.getData()); + } catch (PreBidException e) { + errors.add(e.getMessage()); + } + } + } + + return result; +>>>>>>> 04d9d4a13 (Initial commit) } } diff --git a/src/main/java/org/prebid/server/settings/helper/DatabaseStoredResponseResultMapper.java b/src/main/java/org/prebid/server/settings/helper/DatabaseStoredResponseResultMapper.java index b3812804cfb..b7f09bd503a 100644 --- a/src/main/java/org/prebid/server/settings/helper/DatabaseStoredResponseResultMapper.java +++ b/src/main/java/org/prebid/server/settings/helper/DatabaseStoredResponseResultMapper.java @@ -3,15 +3,23 @@ import io.vertx.sqlclient.Row; import io.vertx.sqlclient.RowIterator; import io.vertx.sqlclient.RowSet; +<<<<<<< HEAD import org.apache.commons.collections4.SetUtils; import org.prebid.server.settings.model.StoredResponseDataResult; +======= +import org.prebid.server.settings.model.StoredResponseDataResult; +import org.prebid.server.util.ObjectUtil; +>>>>>>> 04d9d4a13 (Initial commit) import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +<<<<<<< HEAD import java.util.Objects; +======= +>>>>>>> 04d9d4a13 (Initial commit) import java.util.Set; public class DatabaseStoredResponseResultMapper { @@ -20,6 +28,7 @@ private DatabaseStoredResponseResultMapper() { } public static StoredResponseDataResult map(RowSet rowSet, Set responseIds) { +<<<<<<< HEAD final RowIterator rowIterator = rowSet != null ? rowSet.iterator() : null; final List errors = new ArrayList<>(); @@ -51,6 +60,36 @@ public static StoredResponseDataResult map(RowSet rowSet, Set respo } private static void handleEmptyResult(Set responseIds, List errors) { +======= + final Map storedIdToResponse = new HashMap<>(responseIds.size()); + final List errors = new ArrayList<>(); + + final RowIterator rowIterator = rowSet != null ? rowSet.iterator() : null; + if (rowIterator == null || !rowIterator.hasNext()) { + handleEmptyResultError(responseIds, errors); + return StoredResponseDataResult.of(storedIdToResponse, errors); + } + + while (rowIterator.hasNext()) { + final Row row = rowIterator.next(); + if (row.toJson().size() < 2) { + errors.add("Result set column number is less than expected"); + return StoredResponseDataResult.of(Collections.emptyMap(), errors); + } + final String key = ObjectUtil.getIfNotNull(row.getValue(0), Object::toString); + final String value = ObjectUtil.getIfNotNull(row.getValue(1), Object::toString); + storedIdToResponse.put(key, value); + } + + errors.addAll(responseIds.stream().filter(id -> !storedIdToResponse.containsKey(id)) + .map(id -> "No stored response found for id: " + id) + .toList()); + + return StoredResponseDataResult.of(storedIdToResponse, errors); + } + + private static void handleEmptyResultError(Set responseIds, List errors) { +>>>>>>> 04d9d4a13 (Initial commit) if (responseIds.isEmpty()) { errors.add("No stored responses found"); } else { diff --git a/src/main/java/org/prebid/server/settings/helper/ParametrizedQueryHelper.java b/src/main/java/org/prebid/server/settings/helper/ParametrizedQueryHelper.java index 64d79db1663..f39855de8e0 100644 --- a/src/main/java/org/prebid/server/settings/helper/ParametrizedQueryHelper.java +++ b/src/main/java/org/prebid/server/settings/helper/ParametrizedQueryHelper.java @@ -9,7 +9,14 @@ public interface ParametrizedQueryHelper { String replaceAccountIdPlaceholder(String query); +<<<<<<< HEAD String replaceRequestAndImpIdPlaceholders(String query, int requestIdNumber, int impIdNumber); String replaceStoredResponseIdPlaceholders(String query, int idsNumber); +======= + String replaceStoredResponseIdPlaceholders(String query, int idsNumber); + + String replaceRequestAndImpIdPlaceholders(String query, int requestIdNumber, int impIdNumber); + +>>>>>>> 04d9d4a13 (Initial commit) } diff --git a/src/main/java/org/prebid/server/settings/helper/ParametrizedQueryMySqlHelper.java b/src/main/java/org/prebid/server/settings/helper/ParametrizedQueryMySqlHelper.java index e492b1ce385..515e842cf1f 100644 --- a/src/main/java/org/prebid/server/settings/helper/ParametrizedQueryMySqlHelper.java +++ b/src/main/java/org/prebid/server/settings/helper/ParametrizedQueryMySqlHelper.java @@ -13,17 +13,28 @@ public String replaceAccountIdPlaceholder(String query) { } @Override +<<<<<<< HEAD +======= + public String replaceStoredResponseIdPlaceholders(String query, int idsNumber) { + return query.replaceAll(RESPONSE_ID_PLACEHOLDER, parameterHolders(idsNumber)); + } + + @Override +>>>>>>> 04d9d4a13 (Initial commit) public String replaceRequestAndImpIdPlaceholders(String query, int requestIdNumber, int impIdNumber) { return query .replace(REQUEST_ID_PLACEHOLDER, parameterHolders(requestIdNumber)) .replace(IMP_ID_PLACEHOLDER, parameterHolders(impIdNumber)); } +<<<<<<< HEAD @Override public String replaceStoredResponseIdPlaceholders(String query, int idsNumber) { return query.replace(RESPONSE_ID_PLACEHOLDER, parameterHolders(idsNumber)); } +======= +>>>>>>> 04d9d4a13 (Initial commit) private static String parameterHolders(int paramsSize) { return paramsSize == 0 ? "NULL" diff --git a/src/main/java/org/prebid/server/settings/helper/ParametrizedQueryPostgresHelper.java b/src/main/java/org/prebid/server/settings/helper/ParametrizedQueryPostgresHelper.java index 69388e3423c..40060540491 100644 --- a/src/main/java/org/prebid/server/settings/helper/ParametrizedQueryPostgresHelper.java +++ b/src/main/java/org/prebid/server/settings/helper/ParametrizedQueryPostgresHelper.java @@ -16,6 +16,14 @@ public String replaceAccountIdPlaceholder(String query) { } @Override +<<<<<<< HEAD +======= + public String replaceStoredResponseIdPlaceholders(String query, int idsNumber) { + return query.replaceAll(RESPONSE_ID_PLACEHOLDER, parameterHolders(idsNumber, 0)); + } + + @Override +>>>>>>> 04d9d4a13 (Initial commit) public String replaceRequestAndImpIdPlaceholders(String query, int requestIdNumber, int impIdNumber) { final Matcher matcher = PLACEHOLDER_PATTERN.matcher(query); @@ -27,6 +35,7 @@ public String replaceRequestAndImpIdPlaceholders(String query, int requestIdNumb i += paramsNumber; } matcher.appendTail(queryBuilder); +<<<<<<< HEAD return queryBuilder.toString(); } @@ -36,6 +45,11 @@ public String replaceStoredResponseIdPlaceholders(String query, int idsNumber) { return query.replaceAll(RESPONSE_ID_PLACEHOLDER, parameterHolders(idsNumber, 0)); } +======= + return queryBuilder.toString(); + } + +>>>>>>> 04d9d4a13 (Initial commit) private static String parameterHolders(int paramsSize, int start) { return paramsSize == 0 ? "NULL" diff --git a/src/main/java/org/prebid/server/settings/helper/StoredDataFetcher.java b/src/main/java/org/prebid/server/settings/helper/StoredDataFetcher.java index 4a0feeeb2bb..5dfaa456e1a 100644 --- a/src/main/java/org/prebid/server/settings/helper/StoredDataFetcher.java +++ b/src/main/java/org/prebid/server/settings/helper/StoredDataFetcher.java @@ -1,5 +1,6 @@ package org.prebid.server.settings.helper; +<<<<<<< HEAD import io.vertx.core.Future; import org.prebid.server.execution.timeout.Timeout; import org.prebid.server.settings.model.StoredDataResult; @@ -10,4 +11,21 @@ public interface StoredDataFetcher { Future> apply(String account, Set reqIds, Set impIds, Timeout timeout); +======= +import org.prebid.server.settings.model.StoredDataResult; + +/** + * Interface to satisfy obtaining of {@link StoredDataResult}. + * + * @param account ID + * @param set of stored request IDs + * @param set of stored imp IDs + * @param processing timeout + * @param result of fetching stored data + */ +@FunctionalInterface +public interface StoredDataFetcher { + + R apply(ACC account, REQS reqIds, IMPS impIds, T timeout); +>>>>>>> 04d9d4a13 (Initial commit) } diff --git a/src/main/java/org/prebid/server/settings/helper/StoredItemResolver.java b/src/main/java/org/prebid/server/settings/helper/StoredItemResolver.java index d0797a4772f..748291153ed 100644 --- a/src/main/java/org/prebid/server/settings/helper/StoredItemResolver.java +++ b/src/main/java/org/prebid/server/settings/helper/StoredItemResolver.java @@ -3,6 +3,10 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.exception.PreBidException; +<<<<<<< HEAD +======= +import org.prebid.server.settings.model.StoredDataType; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.settings.model.StoredItem; import java.util.Objects; @@ -31,9 +35,15 @@ private StoredItemResolver() { *

* - Otherwise, reject stored item as if there hadn't been match. */ +<<<<<<< HEAD public static StoredItem resolve(String type, String accountId, String id, Set> storedItems) { if (CollectionUtils.isEmpty(storedItems)) { throw new PreBidException("No %s found for id: %s".formatted(type, id)); +======= + public static StoredItem resolve(StoredDataType type, String accountId, String id, Set storedItems) { + if (CollectionUtils.isEmpty(storedItems)) { + throw new PreBidException("No stored %s found for id: %s".formatted(type, id)); +>>>>>>> 04d9d4a13 (Initial commit) } // at least one stored item has account @@ -41,13 +51,19 @@ public static StoredItem resolve(String type, String accountId, String id if (StringUtils.isEmpty(accountId)) { // we cannot choose stored item among multiple without account throw new PreBidException( +<<<<<<< HEAD "Multiple %ss found for id: %s but no account was specified".formatted(type, id)); } +======= + "Multiple stored %ss found for id: %s but no account was specified".formatted(type, id)); + } +>>>>>>> 04d9d4a13 (Initial commit) return storedItems.stream() .filter(storedItem -> Objects.equals(storedItem.getAccountId(), accountId)) .findAny() .orElseThrow(() -> new PreBidException( +<<<<<<< HEAD "No %s found among multiple id: %s for account: %s".formatted(type, id, accountId))); } @@ -61,5 +77,17 @@ public static StoredItem resolve(String type, String accountId, String id } throw new PreBidException("No %s found for id: %s for account: %s".formatted(type, id, accountId)); +======= + "No stored %s found among multiple id: %s for account: %s".formatted(type, id, accountId))); + } + + // only one stored item found + final StoredItem storedItem = storedItems.iterator().next(); + if (StringUtils.isBlank(accountId) || storedItem.getAccountId() == null + || Objects.equals(accountId, storedItem.getAccountId())) { + return storedItem; + } + throw new PreBidException("No stored %s found for id: %s for account: %s".formatted(type, id, accountId)); +>>>>>>> 04d9d4a13 (Initial commit) } } diff --git a/src/main/java/org/prebid/server/settings/model/AccountAuctionConfig.java b/src/main/java/org/prebid/server/settings/model/AccountAuctionConfig.java index c78bd14770c..9af756b241b 100644 --- a/src/main/java/org/prebid/server/settings/model/AccountAuctionConfig.java +++ b/src/main/java/org/prebid/server/settings/model/AccountAuctionConfig.java @@ -63,6 +63,9 @@ public class AccountAuctionConfig { @JsonAlias("impression-limit") Integer impressionLimit; +<<<<<<< HEAD AccountProfilesConfig profiles; +======= +>>>>>>> 04d9d4a13 (Initial commit) } diff --git a/src/main/java/org/prebid/server/settings/model/StoredDataResult.java b/src/main/java/org/prebid/server/settings/model/StoredDataResult.java index 19840586be1..c6abb9e383f 100644 --- a/src/main/java/org/prebid/server/settings/model/StoredDataResult.java +++ b/src/main/java/org/prebid/server/settings/model/StoredDataResult.java @@ -6,11 +6,19 @@ import java.util.Map; @Value(staticConstructor = "of") +<<<<<<< HEAD public class StoredDataResult { Map storedIdToRequest; Map storedIdToImp; +======= +public class StoredDataResult { + + Map storedIdToRequest; + + Map storedIdToImp; +>>>>>>> 04d9d4a13 (Initial commit) List errors; } diff --git a/src/main/java/org/prebid/server/settings/model/StoredItem.java b/src/main/java/org/prebid/server/settings/model/StoredItem.java index dd7ee8095ff..a59d57d43f0 100644 --- a/src/main/java/org/prebid/server/settings/model/StoredItem.java +++ b/src/main/java/org/prebid/server/settings/model/StoredItem.java @@ -6,9 +6,17 @@ * The model helps to reduce multiple rows found for single stored request/imp ID. */ @Value(staticConstructor = "of") +<<<<<<< HEAD public class StoredItem { String accountId; T data; +======= +public class StoredItem { + + String accountId; + + String data; +>>>>>>> 04d9d4a13 (Initial commit) } diff --git a/src/main/java/org/prebid/server/settings/service/DatabasePeriodicRefreshService.java b/src/main/java/org/prebid/server/settings/service/DatabasePeriodicRefreshService.java index 7714243954d..fefb9738c0e 100644 --- a/src/main/java/org/prebid/server/settings/service/DatabasePeriodicRefreshService.java +++ b/src/main/java/org/prebid/server/settings/service/DatabasePeriodicRefreshService.java @@ -69,7 +69,11 @@ public class DatabasePeriodicRefreshService implements Initializable { private final long refreshPeriod; private final long timeout; private final MetricName cacheType; +<<<<<<< HEAD private final CacheNotificationListener cacheNotificationListener; +======= + private final CacheNotificationListener cacheNotificationListener; +>>>>>>> 04d9d4a13 (Initial commit) private final Vertx vertx; private final DatabaseClient databaseClient; private final TimeoutFactory timeoutFactory; @@ -83,7 +87,11 @@ public DatabasePeriodicRefreshService(String initQuery, long refreshPeriod, long timeout, MetricName cacheType, +<<<<<<< HEAD CacheNotificationListener cacheNotificationListener, +======= + CacheNotificationListener cacheNotificationListener, +>>>>>>> 04d9d4a13 (Initial commit) Vertx vertx, DatabaseClient databaseClient, TimeoutFactory timeoutFactory, @@ -125,7 +133,11 @@ private void getAll() { .recover(exception -> handleFailure(exception, startTime, MetricName.initialize)); } +<<<<<<< HEAD private Void handleResult(StoredDataResult storedDataResult, +======= + private Void handleResult(StoredDataResult storedDataResult, +>>>>>>> 04d9d4a13 (Initial commit) Instant updateTime, long startTime, MetricName refreshType) { @@ -161,7 +173,11 @@ private void refresh() { .recover(exception -> handleFailure(exception, startTime, MetricName.update)); } +<<<<<<< HEAD private StoredDataResult invalidate(StoredDataResult storedDataResult) { +======= + private StoredDataResult invalidate(StoredDataResult storedDataResult) { +>>>>>>> 04d9d4a13 (Initial commit) final List invalidatedRequests = getInvalidatedKeys(storedDataResult.getStoredIdToRequest()); final List invalidatedImps = getInvalidatedKeys(storedDataResult.getStoredIdToImp()); diff --git a/src/main/java/org/prebid/server/settings/service/HttpPeriodicRefreshService.java b/src/main/java/org/prebid/server/settings/service/HttpPeriodicRefreshService.java index 7669074d455..32aec438df6 100644 --- a/src/main/java/org/prebid/server/settings/service/HttpPeriodicRefreshService.java +++ b/src/main/java/org/prebid/server/settings/service/HttpPeriodicRefreshService.java @@ -66,7 +66,11 @@ public class HttpPeriodicRefreshService implements Initializable { private final String refreshUrl; private final long refreshPeriod; private final long timeout; +<<<<<<< HEAD private final CacheNotificationListener cacheNotificationListener; +======= + private final CacheNotificationListener cacheNotificationListener; +>>>>>>> 04d9d4a13 (Initial commit) private final Vertx vertx; private final HttpClient httpClient; private final JacksonMapper mapper; @@ -76,7 +80,11 @@ public class HttpPeriodicRefreshService implements Initializable { public HttpPeriodicRefreshService(String refreshUrl, long refreshPeriod, long timeout, +<<<<<<< HEAD CacheNotificationListener cacheNotificationListener, +======= + CacheNotificationListener cacheNotificationListener, +>>>>>>> 04d9d4a13 (Initial commit) Vertx vertx, HttpClient httpClient, JacksonMapper mapper) { diff --git a/src/main/java/org/prebid/server/settings/service/S3PeriodicRefreshService.java b/src/main/java/org/prebid/server/settings/service/S3PeriodicRefreshService.java index 35ff2a6f55a..095462ec0ee 100644 --- a/src/main/java/org/prebid/server/settings/service/S3PeriodicRefreshService.java +++ b/src/main/java/org/prebid/server/settings/service/S3PeriodicRefreshService.java @@ -43,7 +43,11 @@ public class S3PeriodicRefreshService implements Initializable { private final String storedRequestsDirectory; private final String storedImpressionsDirectory; private final long refreshPeriod; +<<<<<<< HEAD private final CacheNotificationListener cacheNotificationListener; +======= + private final CacheNotificationListener cacheNotificationListener; +>>>>>>> 04d9d4a13 (Initial commit) private final MetricName cacheType; private final Clock clock; private final Metrics metrics; @@ -54,7 +58,11 @@ public S3PeriodicRefreshService(S3AsyncClient asyncClient, String storedRequestsDirectory, String storedImpressionsDirectory, long refreshPeriod, +<<<<<<< HEAD CacheNotificationListener cacheNotificationListener, +======= + CacheNotificationListener cacheNotificationListener, +>>>>>>> 04d9d4a13 (Initial commit) MetricName cacheType, Clock clock, Metrics metrics, @@ -84,7 +92,11 @@ public void initialize(Promise initializePromise) { } } +<<<<<<< HEAD private Future> fetchStoredDataResult(long startTime, MetricName metricName) { +======= + private Future fetchStoredDataResult(long startTime, MetricName metricName) { +>>>>>>> 04d9d4a13 (Initial commit) return Future.all( getFileContentsForDirectory(storedRequestsDirectory), getFileContentsForDirectory(storedImpressionsDirectory)) @@ -132,7 +144,11 @@ private static String stripFileName(String directory, String name) { .replace(JSON_SUFFIX, ""); } +<<<<<<< HEAD private void handleResult(StoredDataResult storedDataResult, long startTime, MetricName refreshType) { +======= + private void handleResult(StoredDataResult storedDataResult, long startTime, MetricName refreshType) { +>>>>>>> 04d9d4a13 (Initial commit) cacheNotificationListener.save(storedDataResult.getStoredIdToRequest(), storedDataResult.getStoredIdToImp()); metrics.updateSettingsCacheRefreshTime(cacheType, refreshType, clock.millis() - startTime); } diff --git a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java index 9021beab946..daeb01f65d2 100644 --- a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java @@ -27,18 +27,30 @@ import org.prebid.server.auction.OrtbTypesResolver; import org.prebid.server.auction.SecBrowsingTopicsResolver; import org.prebid.server.auction.SkippedAuctionService; +<<<<<<< HEAD +======= +import org.prebid.server.auction.StoredRequestProcessor; +import org.prebid.server.auction.StoredResponseProcessor; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.SupplyChainResolver; import org.prebid.server.auction.TimeoutResolver; import org.prebid.server.auction.UidUpdater; import org.prebid.server.auction.VideoResponseFactory; import org.prebid.server.auction.VideoStoredRequestProcessor; import org.prebid.server.auction.WinningBidComparatorFactory; +<<<<<<< HEAD import org.prebid.server.auction.categorymapping.BasicCategoryMappingService; import org.prebid.server.auction.categorymapping.CategoryMappingService; import org.prebid.server.auction.categorymapping.NoOpCategoryMappingService; import org.prebid.server.auction.externalortb.ProfilesProcessor; import org.prebid.server.auction.externalortb.StoredRequestProcessor; import org.prebid.server.auction.externalortb.StoredResponseProcessor; +======= +import org.prebid.server.bidadjustments.BidAdjustmentFactorResolver; +import org.prebid.server.auction.categorymapping.BasicCategoryMappingService; +import org.prebid.server.auction.categorymapping.CategoryMappingService; +import org.prebid.server.auction.categorymapping.NoOpCategoryMappingService; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.gpp.AmpGppService; import org.prebid.server.auction.gpp.AuctionGppService; import org.prebid.server.auction.gpp.CookieSyncGppService; @@ -65,10 +77,16 @@ import org.prebid.server.auction.requestfactory.VideoRequestFactory; import org.prebid.server.auction.versionconverter.BidRequestOrtbVersionConversionManager; import org.prebid.server.auction.versionconverter.BidRequestOrtbVersionConverterFactory; +<<<<<<< HEAD import org.prebid.server.bidadjustments.BidAdjustmentFactorResolver; import org.prebid.server.bidadjustments.BidAdjustmentsEnricher; import org.prebid.server.bidadjustments.BidAdjustmentsProcessor; import org.prebid.server.bidadjustments.BidAdjustmentsResolver; +======= +import org.prebid.server.bidadjustments.BidAdjustmentsProcessor; +import org.prebid.server.bidadjustments.BidAdjustmentsResolver; +import org.prebid.server.bidadjustments.BidAdjustmentsEnricher; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.bidadjustments.BidAdjustmentsRulesResolver; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.bidder.BidderDeps; @@ -434,7 +452,10 @@ Ortb2RequestFactory openRtb2RequestFactory( TimeoutResolver auctionTimeoutResolver, TimeoutFactory timeoutFactory, StoredRequestProcessor storedRequestProcessor, +<<<<<<< HEAD ProfilesProcessor profilesProcessor, +======= +>>>>>>> 04d9d4a13 (Initial commit) ApplicationSettings applicationSettings, IpAddressHelper ipAddressHelper, HookStageExecutor hookStageExecutor, @@ -453,7 +474,10 @@ Ortb2RequestFactory openRtb2RequestFactory( auctionTimeoutResolver, timeoutFactory, storedRequestProcessor, +<<<<<<< HEAD profilesProcessor, +======= +>>>>>>> 04d9d4a13 (Initial commit) applicationSettings, ipAddressHelper, hookStageExecutor, @@ -466,7 +490,10 @@ AuctionRequestFactory auctionRequestFactory( @Value("${auction.max-request-size}") @Min(0) int maxRequestSize, Ortb2RequestFactory ortb2RequestFactory, StoredRequestProcessor storedRequestProcessor, +<<<<<<< HEAD ProfilesProcessor profilesProcessor, +======= +>>>>>>> 04d9d4a13 (Initial commit) BidRequestOrtbVersionConversionManager bidRequestOrtbVersionConversionManager, AuctionGppService auctionGppService, CookieDeprecationService cookieDeprecationService, @@ -483,7 +510,10 @@ AuctionRequestFactory auctionRequestFactory( maxRequestSize, ortb2RequestFactory, storedRequestProcessor, +<<<<<<< HEAD profilesProcessor, +======= +>>>>>>> 04d9d4a13 (Initial commit) bidRequestOrtbVersionConversionManager, auctionGppService, cookieDeprecationService, @@ -518,7 +548,10 @@ IdGenerator sourceIdGenerator() { @Bean AmpRequestFactory ampRequestFactory(Ortb2RequestFactory ortb2RequestFactory, StoredRequestProcessor storedRequestProcessor, +<<<<<<< HEAD ProfilesProcessor profilesProcessor, +======= +>>>>>>> 04d9d4a13 (Initial commit) BidRequestOrtbVersionConversionManager bidRequestOrtbVersionConversionManager, AmpGppService ampGppService, OrtbTypesResolver ortbTypesResolver, @@ -533,7 +566,10 @@ AmpRequestFactory ampRequestFactory(Ortb2RequestFactory ortb2RequestFactory, return new AmpRequestFactory( ortb2RequestFactory, storedRequestProcessor, +<<<<<<< HEAD profilesProcessor, +======= +>>>>>>> 04d9d4a13 (Initial commit) bidRequestOrtbVersionConversionManager, ampGppService, ortbTypesResolver, @@ -995,6 +1031,7 @@ StoredRequestProcessor storedRequestProcessor( } @Bean +<<<<<<< HEAD ProfilesProcessor profilesProcessor(@Value("${auction.profiles.limit}") int maxProfiles, @Value("${auction.profiles.timeout-ms}") long defaultTimeoutMillis, @Value("${auction.profiles.fail-on-unknown:true}") boolean failOnUnknown, @@ -1018,6 +1055,8 @@ ProfilesProcessor profilesProcessor(@Value("${auction.profiles.limit}") int maxP } @Bean +======= +>>>>>>> 04d9d4a13 (Initial commit) WinningBidComparatorFactory winningBidComparatorFactory() { return new WinningBidComparatorFactory(); } diff --git a/src/main/java/org/prebid/server/spring/config/SettingsConfiguration.java b/src/main/java/org/prebid/server/spring/config/SettingsConfiguration.java index 79517afcc6d..2b2ea5a8bf6 100644 --- a/src/main/java/org/prebid/server/spring/config/SettingsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/SettingsConfiguration.java @@ -1,19 +1,31 @@ package org.prebid.server.spring.config; +<<<<<<< HEAD +======= +import org.apache.commons.lang3.StringUtils; +import org.prebid.server.log.Logger; +import org.prebid.server.log.LoggerFactory; +>>>>>>> 04d9d4a13 (Initial commit) import io.vertx.core.Vertx; import io.vertx.core.file.FileSystem; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.UtilityClass; import org.apache.commons.lang3.ObjectUtils; +<<<<<<< HEAD import org.apache.commons.lang3.StringUtils; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.activity.ActivitiesConfigResolver; import org.prebid.server.execution.timeout.TimeoutFactory; import org.prebid.server.floors.PriceFloorsConfigResolver; import org.prebid.server.json.JacksonMapper; import org.prebid.server.json.JsonMerger; +<<<<<<< HEAD import org.prebid.server.log.Logger; import org.prebid.server.log.LoggerFactory; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; import org.prebid.server.settings.ApplicationSettings; @@ -26,7 +38,10 @@ import org.prebid.server.settings.S3ApplicationSettings; import org.prebid.server.settings.SettingsCache; import org.prebid.server.settings.helper.ParametrizedQueryHelper; +<<<<<<< HEAD import org.prebid.server.settings.model.Profile; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.settings.service.DatabasePeriodicRefreshService; import org.prebid.server.settings.service.HttpPeriodicRefreshService; import org.prebid.server.settings.service.S3PeriodicRefreshService; @@ -44,12 +59,21 @@ import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +<<<<<<< HEAD import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3AsyncClient; +======= +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.core.exception.SdkClientException; +>>>>>>> 04d9d4a13 (Initial commit) import javax.validation.constraints.Min; import javax.validation.constraints.NotBlank; @@ -77,12 +101,16 @@ FileApplicationSettings fileApplicationSettings( @Value("${settings.filesystem.settings-filename}") String settingsFileName, @Value("${settings.filesystem.stored-requests-dir}") String storedRequestsDir, @Value("${settings.filesystem.stored-imps-dir}") String storedImpsDir, +<<<<<<< HEAD @Value("${settings.filesystem.profiles-dir:#{null}}") String profilesDir, +======= +>>>>>>> 04d9d4a13 (Initial commit) @Value("${settings.filesystem.stored-responses-dir}") String storedResponsesDir, @Value("${settings.filesystem.categories-dir}") String categoriesDir, FileSystem fileSystem, JacksonMapper jacksonMapper) { +<<<<<<< HEAD return new FileApplicationSettings( fileSystem, settingsFileName, @@ -92,6 +120,10 @@ FileApplicationSettings fileApplicationSettings( storedResponsesDir, categoriesDir, jacksonMapper); +======= + return new FileApplicationSettings(fileSystem, settingsFileName, storedRequestsDir, storedImpsDir, + storedResponsesDir, categoriesDir, jacksonMapper); +>>>>>>> 04d9d4a13 (Initial commit) } } @@ -104,7 +136,10 @@ DatabaseApplicationSettings databaseApplicationSettings( @Value("${settings.database.account-query}") String accountQuery, @Value("${settings.database.stored-requests-query}") String storedRequestsQuery, @Value("${settings.database.amp-stored-requests-query}") String ampStoredRequestsQuery, +<<<<<<< HEAD @Value("${settings.database.profiles-query:#{null}}") String profilesQuery, +======= +>>>>>>> 04d9d4a13 (Initial commit) @Value("${settings.database.stored-responses-query}") String storedResponsesQuery, ParametrizedQueryHelper parametrizedQueryHelper, DatabaseClient databaseClient, @@ -117,7 +152,10 @@ DatabaseApplicationSettings databaseApplicationSettings( accountQuery, storedRequestsQuery, ampStoredRequestsQuery, +<<<<<<< HEAD profilesQuery, +======= +>>>>>>> 04d9d4a13 (Initial commit) storedResponsesQuery); } } @@ -128,22 +166,38 @@ static class HttpSettingsConfiguration { @Bean HttpApplicationSettings httpApplicationSettings( +<<<<<<< HEAD @Value("${settings.http.rfc3986-compatible:false}") boolean isRfc3986Compatible, +======= +>>>>>>> 04d9d4a13 (Initial commit) HttpClient httpClient, JacksonMapper mapper, @Value("${settings.http.endpoint}") String endpoint, @Value("${settings.http.amp-endpoint}") String ampEndpoint, @Value("${settings.http.video-endpoint}") String videoEndpoint, +<<<<<<< HEAD @Value("${settings.http.category-endpoint}") String categoryEndpoint) { return new HttpApplicationSettings( isRfc3986Compatible, +======= + @Value("${settings.http.category-endpoint}") String categoryEndpoint, + @Value("${settings.http.rfc3986-compatible:false}") boolean isRfc3986Compatible) { + + return new HttpApplicationSettings( + httpClient, + mapper, +>>>>>>> 04d9d4a13 (Initial commit) endpoint, ampEndpoint, videoEndpoint, categoryEndpoint, +<<<<<<< HEAD httpClient, mapper); +======= + isRfc3986Compatible); +>>>>>>> 04d9d4a13 (Initial commit) } } @@ -167,7 +221,11 @@ static class HttpPeriodicRefreshServiceConfiguration { @Bean public HttpPeriodicRefreshService httpPeriodicRefreshService( @Value("${settings.in-memory-cache.http-update.endpoint}") String endpoint, +<<<<<<< HEAD SettingsCache settingsCache, +======= + SettingsCache settingsCache, +>>>>>>> 04d9d4a13 (Initial commit) JacksonMapper mapper) { return new HttpPeriodicRefreshService( @@ -177,7 +235,11 @@ public HttpPeriodicRefreshService httpPeriodicRefreshService( @Bean public HttpPeriodicRefreshService ampHttpPeriodicRefreshService( @Value("${settings.in-memory-cache.http-update.amp-endpoint}") String ampEndpoint, +<<<<<<< HEAD SettingsCache ampSettingsCache, +======= + SettingsCache ampSettingsCache, +>>>>>>> 04d9d4a13 (Initial commit) JacksonMapper mapper) { return new HttpPeriodicRefreshService( @@ -214,7 +276,11 @@ static class DatabasePeriodicRefreshServiceConfiguration { @Bean public DatabasePeriodicRefreshService databasePeriodicRefreshService( +<<<<<<< HEAD @Qualifier("settingsCache") SettingsCache settingsCache, +======= + @Qualifier("settingsCache") SettingsCache settingsCache, +>>>>>>> 04d9d4a13 (Initial commit) @Value("${settings.in-memory-cache.database-update.init-query}") String initQuery, @Value("${settings.in-memory-cache.database-update.update-query}") String updateQuery) { @@ -234,7 +300,11 @@ public DatabasePeriodicRefreshService databasePeriodicRefreshService( @Bean public DatabasePeriodicRefreshService ampDatabasePeriodicRefreshService( +<<<<<<< HEAD @Qualifier("ampSettingsCache") SettingsCache ampSettingsCache, +======= + @Qualifier("ampSettingsCache") SettingsCache ampSettingsCache, +>>>>>>> 04d9d4a13 (Initial commit) @Value("${settings.in-memory-cache.database-update.amp-init-query}") String ampInitQuery, @Value("${settings.in-memory-cache.database-update.amp-update-query}") String ampUpdateQuery) { @@ -268,7 +338,11 @@ protected static class S3ConfigurationProperties { * If accessKeyId and secretAccessKey are provided in the * configuration file then they will be used. Otherwise, the * DefaultCredentialsProvider will look for credentials in this order: +<<<<<<< HEAD *

+======= + * +>>>>>>> 04d9d4a13 (Initial commit) * - Java System Properties * - Environment Variables * - Web Identity Token @@ -327,7 +401,11 @@ S3AsyncClient s3AsyncClient(S3ConfigurationProperties s3ConfigurationProperties) private static AwsCredentialsProvider awsCredentialsProvider(S3ConfigurationProperties config) { final AwsCredentialsProvider credentialsProvider = config.useStaticCredentials() ? StaticCredentialsProvider.create( +<<<<<<< HEAD AwsBasicCredentials.create(config.getAccessKeyId(), config.getSecretAccessKey())) +======= + AwsBasicCredentials.create(config.getAccessKeyId(), config.getSecretAccessKey())) +>>>>>>> 04d9d4a13 (Initial commit) : DefaultCredentialsProvider.create(); try { @@ -366,7 +444,11 @@ public S3PeriodicRefreshService s3PeriodicRefreshService( S3AsyncClient s3AsyncClient, S3SettingsConfiguration.S3ConfigurationProperties s3ConfigurationProperties, @Value("${settings.in-memory-cache.s3-update.refresh-rate}") long refreshPeriod, +<<<<<<< HEAD SettingsCache settingsCache, +======= + SettingsCache settingsCache, +>>>>>>> 04d9d4a13 (Initial commit) Clock clock, Metrics metrics, Vertx vertx) { @@ -442,10 +524,16 @@ static class CachingSettingsConfiguration { CachingApplicationSettings cachingApplicationSettings( EnrichingApplicationSettings enrichingApplicationSettings, ApplicationSettingsCacheProperties cacheProperties, +<<<<<<< HEAD @Qualifier("settingsCache") SettingsCache cache, @Qualifier("ampSettingsCache") SettingsCache ampCache, @Qualifier("videoSettingCache") SettingsCache videoCache, @Qualifier("profileSettingCache") SettingsCache profilesCache, +======= + @Qualifier("settingsCache") SettingsCache cache, + @Qualifier("ampSettingsCache") SettingsCache ampCache, + @Qualifier("videoSettingCache") SettingsCache videoCache, +>>>>>>> 04d9d4a13 (Initial commit) Metrics metrics) { return new CachingApplicationSettings( @@ -453,7 +541,10 @@ CachingApplicationSettings cachingApplicationSettings( cache, ampCache, videoCache, +<<<<<<< HEAD profilesCache, +======= +>>>>>>> 04d9d4a13 (Initial commit) metrics, cacheProperties.getTtlSeconds(), cacheProperties.getCacheSize(), @@ -478,8 +569,13 @@ static class CacheConfiguration { @Bean @Qualifier("settingsCache") +<<<<<<< HEAD SettingsCache settingsCache(ApplicationSettingsCacheProperties cacheProperties) { return new SettingsCache<>( +======= + SettingsCache settingsCache(ApplicationSettingsCacheProperties cacheProperties) { + return new SettingsCache( +>>>>>>> 04d9d4a13 (Initial commit) cacheProperties.getTtlSeconds(), cacheProperties.getCacheSize(), cacheProperties.getJitterSeconds()); @@ -487,8 +583,13 @@ SettingsCache settingsCache(ApplicationSettingsCacheProperties cacheProp @Bean @Qualifier("ampSettingsCache") +<<<<<<< HEAD SettingsCache ampSettingsCache(ApplicationSettingsCacheProperties cacheProperties) { return new SettingsCache<>( +======= + SettingsCache ampSettingsCache(ApplicationSettingsCacheProperties cacheProperties) { + return new SettingsCache( +>>>>>>> 04d9d4a13 (Initial commit) cacheProperties.getTtlSeconds(), cacheProperties.getCacheSize(), cacheProperties.getJitterSeconds()); @@ -496,6 +597,7 @@ SettingsCache ampSettingsCache(ApplicationSettingsCacheProperties cacheP @Bean @Qualifier("videoSettingCache") +<<<<<<< HEAD SettingsCache videoSettingCache(ApplicationSettingsCacheProperties cacheProperties) { return new SettingsCache<>( cacheProperties.getTtlSeconds(), @@ -507,6 +609,10 @@ SettingsCache videoSettingCache(ApplicationSettingsCacheProperties cache @Qualifier("profileSettingCache") SettingsCache profileSettingCache(ApplicationSettingsCacheProperties cacheProperties) { return new SettingsCache<>( +======= + SettingsCache videoSettingCache(ApplicationSettingsCacheProperties cacheProperties) { + return new SettingsCache( +>>>>>>> 04d9d4a13 (Initial commit) cacheProperties.getTtlSeconds(), cacheProperties.getCacheSize(), cacheProperties.getJitterSeconds()); diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AlvadsConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AlvadsConfiguration.java new file mode 100644 index 00000000000..c30b1379a55 --- /dev/null +++ b/src/main/java/org/prebid/server/spring/config/bidder/AlvadsConfiguration.java @@ -0,0 +1,41 @@ +package org.prebid.server.spring.config.bidder; + +import org.prebid.server.bidder.BidderDeps; +import org.prebid.server.bidder.alvads.AlvadsBidder; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; +import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; +import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; +import org.prebid.server.spring.env.YamlPropertySourceFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import jakarta.validation.constraints.NotBlank; + +@Configuration +@PropertySource(value = "classpath:/bidder-config/alvads.yaml", factory = YamlPropertySourceFactory.class) +public class AlvadsConfiguration { + + private static final String BIDDER_NAME = "alvads"; + + @Bean("alvadsConfigurationProperties") + @ConfigurationProperties("adapters.alvads") + BidderConfigurationProperties configurationProperties() { + return new BidderConfigurationProperties(); + } + + @Bean + BidderDeps alvadsBidderDeps(BidderConfigurationProperties alvadsConfigurationProperties, + @NotBlank @Value("${external-url}") String externalUrl, + JacksonMapper mapper) { + + return BidderDepsAssembler.forBidder(BIDDER_NAME) + .withConfig(alvadsConfigurationProperties) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AlvadsBidder(config.getEndpoint(), mapper)) + .assemble(); + } +} diff --git a/src/main/java/org/prebid/server/spring/config/bidder/SmartadserverConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/SmartadserverConfiguration.java index 3d831685aff..ac1b24889a1 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/SmartadserverConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/SmartadserverConfiguration.java @@ -1,8 +1,11 @@ package org.prebid.server.spring.config.bidder; +<<<<<<< HEAD import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.bidder.BidderDeps; import org.prebid.server.bidder.smartadserver.SmartadserverBidder; import org.prebid.server.json.JacksonMapper; @@ -26,6 +29,7 @@ public class SmartadserverConfiguration { @Bean("smartadserverConfigurationProperties") @ConfigurationProperties("adapters.smartadserver") +<<<<<<< HEAD SmartadserverConfigurationProperties configurationProperties() { return new SmartadserverConfigurationProperties(); } @@ -50,4 +54,21 @@ private static class SmartadserverConfigurationProperties extends BidderConfigur private String secondaryEndpoint; } +======= + BidderConfigurationProperties configurationProperties() { + return new BidderConfigurationProperties(); + } + + @Bean + BidderDeps smartadserverBidderDeps(BidderConfigurationProperties smartadserverConfigurationProperties, + @NotBlank @Value("${external-url}") String externalUrl, + JacksonMapper mapper) { + + return BidderDepsAssembler.forBidder(BIDDER_NAME) + .withConfig(smartadserverConfigurationProperties) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new SmartadserverBidder(config.getEndpoint(), mapper)) + .assemble(); + } +>>>>>>> 04d9d4a13 (Initial commit) } diff --git a/src/main/java/org/prebid/server/spring/config/server/admin/AdminEndpointsConfiguration.java b/src/main/java/org/prebid/server/spring/config/server/admin/AdminEndpointsConfiguration.java index a5938aab396..53542e7bb70 100644 --- a/src/main/java/org/prebid/server/spring/config/server/admin/AdminEndpointsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/server/admin/AdminEndpointsConfiguration.java @@ -76,34 +76,58 @@ AdminResource currencyConversionRatesEndpoint( @ConditionalOnExpression("${settings.in-memory-cache.notification-endpoints-enabled:false}" + " and ${admin-endpoints.storedrequest.enabled} == true") AdminResource cacheNotificationEndpoint( +<<<<<<< HEAD @Value("${admin-endpoints.storedrequest.path}") String path, @Value("${admin-endpoints.storedrequest.on-application-port}") boolean isOnApplicationPort, @Value("${admin-endpoints.storedrequest.protected}") boolean isProtected, SettingsCache settingsCache, JacksonMapper mapper) { +======= + SettingsCache settingsCache, + JacksonMapper mapper, + @Value("${admin-endpoints.storedrequest.path}") String path, + @Value("${admin-endpoints.storedrequest.on-application-port}") boolean isOnApplicationPort, + @Value("${admin-endpoints.storedrequest.protected}") boolean isProtected) { +>>>>>>> 04d9d4a13 (Initial commit) return new AdminResourceWrapper( path, isOnApplicationPort, isProtected, +<<<<<<< HEAD new SettingsCacheNotificationHandler(path, settingsCache, mapper)); +======= + new SettingsCacheNotificationHandler(settingsCache, mapper, path)); +>>>>>>> 04d9d4a13 (Initial commit) } @Bean @ConditionalOnExpression("${settings.in-memory-cache.notification-endpoints-enabled:false}" + " and ${admin-endpoints.storedrequest-amp.enabled} == true") AdminResource ampCacheNotificationEndpoint( +<<<<<<< HEAD @Value("${admin-endpoints.storedrequest-amp.path}") String path, @Value("${admin-endpoints.storedrequest-amp.on-application-port}") boolean isOnApplicationPort, @Value("${admin-endpoints.storedrequest-amp.protected}") boolean isProtected, SettingsCache ampSettingsCache, JacksonMapper mapper) { +======= + SettingsCache ampSettingsCache, + JacksonMapper mapper, + @Value("${admin-endpoints.storedrequest-amp.path}") String path, + @Value("${admin-endpoints.storedrequest-amp.on-application-port}") boolean isOnApplicationPort, + @Value("${admin-endpoints.storedrequest-amp.protected}") boolean isProtected) { +>>>>>>> 04d9d4a13 (Initial commit) return new AdminResourceWrapper( path, isOnApplicationPort, isProtected, +<<<<<<< HEAD new SettingsCacheNotificationHandler(path, ampSettingsCache, mapper)); +======= + new SettingsCacheNotificationHandler(ampSettingsCache, mapper, path)); +>>>>>>> 04d9d4a13 (Initial commit) } @Bean diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..02835a66034 --- /dev/null +++ b/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: org.prebid.server.Application + diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 55822047954..b78f46da537 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -111,9 +111,12 @@ auction: percent: 100 tmax-upstream-response-time: 30 stored-requests-timeout-ms: 100 +<<<<<<< HEAD profiles: limit: 4 timeout-ms: 100 +======= +>>>>>>> 04d9d4a13 (Initial commit) timeout-notification: timeout-ms: 200 log-result: false diff --git a/src/main/resources/bidder-config/alvads.yaml b/src/main/resources/bidder-config/alvads.yaml new file mode 100644 index 00000000000..2fddd965a67 --- /dev/null +++ b/src/main/resources/bidder-config/alvads.yaml @@ -0,0 +1,14 @@ +adapters: + alvads: + endpoint: https://helios-ads-qa-core.ssidevops.com/decision/openrtb + meta-info: + maintainer-email: alvads@oyealva.com + app-media-types: + - banner + - video + site-media-types: + - banner + - video + supported-vendors: + vendor-id: 0 + diff --git a/src/main/resources/bidder-config/copper6ssp.yaml b/src/main/resources/bidder-config/copper6ssp.yaml index 692697b6ea3..5de11494081 100644 --- a/src/main/resources/bidder-config/copper6ssp.yaml +++ b/src/main/resources/bidder-config/copper6ssp.yaml @@ -12,7 +12,11 @@ adapters: - video - native supported-vendors: +<<<<<<< HEAD vendor-id: 1356 +======= + vendor-id: 0 +>>>>>>> 04d9d4a13 (Initial commit) usersync: cookie-family-name: copper6ssp redirect: diff --git a/src/main/resources/bidder-config/kobler.yaml b/src/main/resources/bidder-config/kobler.yaml index cd49ef2ea75..5221a65d569 100644 --- a/src/main/resources/bidder-config/kobler.yaml +++ b/src/main/resources/bidder-config/kobler.yaml @@ -11,6 +11,9 @@ adapters: maintainer-email: bidding-support@kobler.no site-media-types: - banner +<<<<<<< HEAD app-media-types: - banner +======= +>>>>>>> 04d9d4a13 (Initial commit) vendor-id: 0 diff --git a/src/main/resources/bidder-config/seedtag.yaml b/src/main/resources/bidder-config/seedtag.yaml index 44eed6fd01b..bb24ff8f388 100644 --- a/src/main/resources/bidder-config/seedtag.yaml +++ b/src/main/resources/bidder-config/seedtag.yaml @@ -12,6 +12,10 @@ adapters: usersync: cookie-family-name: seedtag iframe: +<<<<<<< HEAD url: https://s.seedtag.com/cs/cookiesync/prebid?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&usp_consent={{us_privacy}}&gpp={{gpp}}&gpp_sid={{gpp_sid}}&redirect={{redirect_url}} +======= + url: https://s.seedtag.com/cs/cookiesync/prebid?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&usp_consent={{us_privacy}}&redirect={{redirect_url}} +>>>>>>> 04d9d4a13 (Initial commit) support-cors: false uid-macro: '$UID' diff --git a/src/main/resources/bidder-config/smartadserver.yaml b/src/main/resources/bidder-config/smartadserver.yaml index 343bec392de..5a9a12bbbb3 100644 --- a/src/main/resources/bidder-config/smartadserver.yaml +++ b/src/main/resources/bidder-config/smartadserver.yaml @@ -1,7 +1,10 @@ adapters: smartadserver: endpoint: https://ssb-global.smartadserver.com +<<<<<<< HEAD secondary-endpoint: https://prebid-global.smartadserver.com +======= +>>>>>>> 04d9d4a13 (Initial commit) endpoint-compression: gzip aliases: equativ: diff --git a/src/main/resources/bidder-config/xeworks.yaml b/src/main/resources/bidder-config/xeworks.yaml index 6464a99c8ae..b076e601613 100644 --- a/src/main/resources/bidder-config/xeworks.yaml +++ b/src/main/resources/bidder-config/xeworks.yaml @@ -7,6 +7,7 @@ adapters: endpoint: http://rtb.connektai.live/?pid={{SourceId}}&host={{Host}}&s=pbs meta-info: maintainer-email: adops@connekt.ai +<<<<<<< HEAD adipolo: enabled: false endpoint: http://rtb.adipolo.live?pid={{SourceId}}&host={{Host}}&pbs=1 @@ -23,6 +24,8 @@ adapters: url: https://sync.adipolo.live/static/adisync.html?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&gpp={{gpp}}&gpp_sid={{gpp_sid}}&cb={{redirect_url}} support-cors: false uid-macro: '$UID' +======= +>>>>>>> 04d9d4a13 (Initial commit) meta-info: maintainer-email: team@xe.works app-media-types: diff --git a/src/main/resources/bidder-config/zmaticoo.yaml b/src/main/resources/bidder-config/zmaticoo.yaml index 51da390a37d..aed37c4db33 100644 --- a/src/main/resources/bidder-config/zmaticoo.yaml +++ b/src/main/resources/bidder-config/zmaticoo.yaml @@ -1,6 +1,10 @@ adapters: zmaticoo: +<<<<<<< HEAD endpoint: https://rtbbid.zmaticoo.com/prebid/bid +======= + endpoint: https://bid.zmaticoo.com/prebid/bid +>>>>>>> 04d9d4a13 (Initial commit) meta-info: maintainer-email: adam.li@eclicktech.com.cn app-media-types: diff --git a/src/main/resources/metrics-config/prometheus-labels.yaml b/src/main/resources/metrics-config/prometheus-labels.yaml index b40139d6a8a..800dab1b315 100644 --- a/src/main/resources/metrics-config/prometheus-labels.yaml +++ b/src/main/resources/metrics-config/prometheus-labels.yaml @@ -202,9 +202,12 @@ mappers: labels: adapter: ${0} action: ${1} +<<<<<<< HEAD - match: adapter.*.activity.*.*.count name: adapter.activity labels: adapter: ${0} activity: ${1} action: ${2} +======= +>>>>>>> 04d9d4a13 (Initial commit) diff --git a/src/main/resources/static/bidder-params/alvads.json b/src/main/resources/static/bidder-params/alvads.json new file mode 100644 index 00000000000..ae822c18ae5 --- /dev/null +++ b/src/main/resources/static/bidder-params/alvads.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Alvads Adapter Params", + "description": "A schema which validates params accepted by the Alvads adapter", + "type": "object", + + "properties": { + "publisherUniqueId": { + "type": "string", + "description": "Publisher Unique Id" + }, + "endPointUrl": { + "type": "string", + "description": "Url ads openrtb" + } + }, + + "required": ["publisherUniqueId"] +} diff --git a/src/test/groovy/org/prebid/server/functional/model/config/AccountAuctionConfig.groovy b/src/test/groovy/org/prebid/server/functional/model/config/AccountAuctionConfig.groovy index 2dc5ff7c77b..383a521c704 100644 --- a/src/test/groovy/org/prebid/server/functional/model/config/AccountAuctionConfig.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/config/AccountAuctionConfig.groovy @@ -26,7 +26,10 @@ class AccountAuctionConfig { AccountCacheConfig cache AccountRankingConfig ranking AccountPriceFloorsConfig priceFloors +<<<<<<< HEAD AccountProfilesConfigs profiles +======= +>>>>>>> 04d9d4a13 (Initial commit) Targeting targeting PaaFormat paaformat @JsonProperty("preferredmediatype") diff --git a/src/test/groovy/org/prebid/server/functional/model/db/StoredRequest.groovy b/src/test/groovy/org/prebid/server/functional/model/db/StoredRequest.groovy index 5bf47b830fc..b4f058dfb32 100644 --- a/src/test/groovy/org/prebid/server/functional/model/db/StoredRequest.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/db/StoredRequest.groovy @@ -7,7 +7,11 @@ import jakarta.persistence.Entity import jakarta.persistence.GeneratedValue import jakarta.persistence.Id import jakarta.persistence.Table +<<<<<<< HEAD import org.prebid.server.functional.model.db.typeconverter.BidRequestConfigTypeConverter +======= +import org.prebid.server.functional.model.db.typeconverter.StoredRequestConfigTypeConverter +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.functional.model.request.amp.AmpRequest import org.prebid.server.functional.model.request.auction.BidRequest @@ -27,7 +31,11 @@ class StoredRequest { @Column(name = "reqId") String requestId @Column(name = "requestData") +<<<<<<< HEAD @Convert(converter = BidRequestConfigTypeConverter) +======= + @Convert(converter = StoredRequestConfigTypeConverter) +>>>>>>> 04d9d4a13 (Initial commit) BidRequest requestData static StoredRequest getStoredRequest(AmpRequest ampRequest, BidRequest storedRequest) { diff --git a/src/test/groovy/org/prebid/server/functional/model/db/StoredResponse.groovy b/src/test/groovy/org/prebid/server/functional/model/db/StoredResponse.groovy index ebfc31f3c6d..b4c3cfc65c9 100644 --- a/src/test/groovy/org/prebid/server/functional/model/db/StoredResponse.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/db/StoredResponse.groovy @@ -8,7 +8,11 @@ import jakarta.persistence.GeneratedValue import jakarta.persistence.Id import jakarta.persistence.Table import org.prebid.server.functional.model.db.typeconverter.StoredAuctionResponseConfigTypeConverter +<<<<<<< HEAD import org.prebid.server.functional.model.db.typeconverter.BidResponseConfigTypeConverter +======= +import org.prebid.server.functional.model.db.typeconverter.StoredBidResponseConfigTypeConverter +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.model.response.auction.SeatBid @@ -29,6 +33,10 @@ class StoredResponse { @Convert(converter = StoredAuctionResponseConfigTypeConverter) SeatBid storedAuctionResponse @Column(name = "storedBidResponse") +<<<<<<< HEAD @Convert(converter = BidResponseConfigTypeConverter) +======= + @Convert(converter = StoredBidResponseConfigTypeConverter) +>>>>>>> 04d9d4a13 (Initial commit) BidResponse storedBidResponse } diff --git a/src/test/groovy/org/prebid/server/functional/model/db/typeconverter/StoredBidResponseConfigTypeConverter.groovy b/src/test/groovy/org/prebid/server/functional/model/db/typeconverter/StoredBidResponseConfigTypeConverter.groovy new file mode 100644 index 00000000000..43120fcad65 --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/model/db/typeconverter/StoredBidResponseConfigTypeConverter.groovy @@ -0,0 +1,18 @@ +package org.prebid.server.functional.model.db.typeconverter + +import jakarta.persistence.AttributeConverter +import org.prebid.server.functional.model.response.auction.BidResponse +import org.prebid.server.functional.util.ObjectMapperWrapper + +class StoredBidResponseConfigTypeConverter implements AttributeConverter, ObjectMapperWrapper { + + @Override + String convertToDatabaseColumn(BidResponse bidResponse) { + bidResponse ? encode(bidResponse) : null + } + + @Override + BidResponse convertToEntityAttribute(String value) { + value ? decode(value, BidResponse) : null + } +} diff --git a/src/test/groovy/org/prebid/server/functional/model/db/typeconverter/StoredRequestConfigTypeConverter.groovy b/src/test/groovy/org/prebid/server/functional/model/db/typeconverter/StoredRequestConfigTypeConverter.groovy new file mode 100644 index 00000000000..3e968d39565 --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/model/db/typeconverter/StoredRequestConfigTypeConverter.groovy @@ -0,0 +1,18 @@ +package org.prebid.server.functional.model.db.typeconverter + +import jakarta.persistence.AttributeConverter +import org.prebid.server.functional.model.request.auction.BidRequest +import org.prebid.server.functional.util.ObjectMapperWrapper + +class StoredRequestConfigTypeConverter implements AttributeConverter, ObjectMapperWrapper { + + @Override + String convertToDatabaseColumn(BidRequest bidRequest) { + bidRequest ? encode(bidRequest) : null + } + + @Override + BidRequest convertToEntityAttribute(String value) { + value ? decode(value, BidRequest) : null + } +} diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Banner.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Banner.groovy index 97461b79d78..3d7f77f38d8 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Banner.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Banner.groovy @@ -1,16 +1,25 @@ package org.prebid.server.functional.model.request.auction import com.fasterxml.jackson.annotation.JsonProperty +<<<<<<< HEAD import groovy.transform.EqualsAndHashCode import groovy.transform.ToString @EqualsAndHashCode +======= +import groovy.transform.ToString + +>>>>>>> 04d9d4a13 (Initial commit) @ToString(includeNames = true, ignoreNulls = true) class Banner { List format @JsonProperty("w") +<<<<<<< HEAD Integer width +======= + Integer weight +>>>>>>> 04d9d4a13 (Initial commit) @JsonProperty("h") Integer height List btype diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/BidRequestExt.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/BidRequestExt.groovy index 3c39de5781e..245fc442a35 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/BidRequestExt.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/BidRequestExt.groovy @@ -1,10 +1,16 @@ package org.prebid.server.functional.model.request.auction +<<<<<<< HEAD import groovy.transform.EqualsAndHashCode import groovy.transform.ToString import org.prebid.server.functional.model.bidder.AppNexus @EqualsAndHashCode +======= +import groovy.transform.ToString +import org.prebid.server.functional.model.bidder.AppNexus + +>>>>>>> 04d9d4a13 (Initial commit) @ToString(includeNames = true, ignoreNulls = true) class BidRequestExt { diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Device.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Device.groovy index 91a7e54dc37..0d329f1af1c 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Device.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Device.groovy @@ -1,7 +1,10 @@ package org.prebid.server.functional.model.request.auction import groovy.transform.ToString +<<<<<<< HEAD import org.prebid.server.functional.util.PBSUtils +======= +>>>>>>> 04d9d4a13 (Initial commit) @ToString(includeNames = true, ignoreNulls = true) class Device { @@ -39,6 +42,7 @@ class Device { String macsha1 String macmd5 DeviceExt ext +<<<<<<< HEAD static Device getDefault() { new Device().tap { @@ -51,4 +55,6 @@ class Device { dpidmd5 = PBSUtils.randomString } } +======= +>>>>>>> 04d9d4a13 (Initial commit) } diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Format.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Format.groovy index 67215776579..7f2424b783b 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Format.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Format.groovy @@ -3,13 +3,17 @@ package org.prebid.server.functional.model.request.auction import com.fasterxml.jackson.annotation.JsonProperty import groovy.transform.EqualsAndHashCode import groovy.transform.ToString +<<<<<<< HEAD import org.prebid.server.functional.util.PBSUtils +======= +>>>>>>> 04d9d4a13 (Initial commit) @EqualsAndHashCode @ToString(includeNames = true, ignoreNulls = true) class Format { @JsonProperty("w") +<<<<<<< HEAD Integer width @JsonProperty("h") Integer height @@ -33,4 +37,22 @@ class Format { height = PBSUtils.randomNumber } } +======= + Integer weight + @JsonProperty("h") + Integer height + @JsonProperty("wratio") + Integer weightRatio + @JsonProperty("hratio") + Integer heightRatio + @JsonProperty("wmin") + Integer weightMin + + static Format getDefaultFormat() { + new Format().tap { + weight = 300 + height = 250 + } + } +>>>>>>> 04d9d4a13 (Initial commit) } diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/ImpExtPrebid.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/ImpExtPrebid.groovy index a20e3ea894d..c9fc1c77846 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/ImpExtPrebid.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/ImpExtPrebid.groovy @@ -21,8 +21,12 @@ class ImpExtPrebid { Map imp String adUnitCode PrebidOptions options +<<<<<<< HEAD @JsonProperty("profiles") List profileNames +======= + +>>>>>>> 04d9d4a13 (Initial commit) static ImpExtPrebid getDefaultImpExtPrebid() { new ImpExtPrebid().tap { diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/IxDiag.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/IxDiag.groovy index d68075b6668..ef97b92e82a 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/IxDiag.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/IxDiag.groovy @@ -6,7 +6,10 @@ import groovy.transform.ToString class IxDiag { String pbsv +<<<<<<< HEAD String pbsp +======= +>>>>>>> 04d9d4a13 (Initial commit) String pbjsv String multipleSiteIds } diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy index 3ab6e7a6dbf..d7cb3fc9afe 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy @@ -45,8 +45,11 @@ class Prebid { PaaFormat paaFormat @JsonProperty("alternatebiddercodes") AlternateBidderCodes alternateBidderCodes +<<<<<<< HEAD @JsonProperty("profiles") List profileNames +======= +>>>>>>> 04d9d4a13 (Initial commit) static class Channel { diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Site.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Site.groovy index c8dfcbdbe79..4229fb69836 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Site.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Site.groovy @@ -2,11 +2,17 @@ package org.prebid.server.functional.model.request.auction import com.fasterxml.jackson.databind.PropertyNamingStrategies import com.fasterxml.jackson.databind.annotation.JsonNaming +<<<<<<< HEAD import groovy.transform.EqualsAndHashCode import groovy.transform.ToString import org.prebid.server.functional.util.PBSUtils @EqualsAndHashCode +======= +import groovy.transform.ToString +import org.prebid.server.functional.util.PBSUtils + +>>>>>>> 04d9d4a13 (Initial commit) @ToString(includeNames = true, ignoreNulls = true) @JsonNaming(PropertyNamingStrategies.LowerCaseStrategy) class Site { diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/SiteExtData.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/SiteExtData.groovy index 7e8ecd556fa..40be2520630 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/SiteExtData.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/SiteExtData.groovy @@ -1,10 +1,16 @@ package org.prebid.server.functional.model.request.auction +<<<<<<< HEAD import groovy.transform.EqualsAndHashCode import groovy.transform.ToString import org.prebid.server.functional.util.PBSUtils @EqualsAndHashCode +======= +import groovy.transform.ToString +import org.prebid.server.functional.util.PBSUtils + +>>>>>>> 04d9d4a13 (Initial commit) @ToString(includeNames = true, ignoreNulls = true) class SiteExtData { diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Video.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Video.groovy index 53e86c5ed28..95b90204a90 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Video.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Video.groovy @@ -16,7 +16,11 @@ class Video { Integer poddur List protocols @JsonProperty("w") +<<<<<<< HEAD Integer width +======= + Integer weight +>>>>>>> 04d9d4a13 (Initial commit) @JsonProperty("h") Integer height Integer podid @@ -47,6 +51,10 @@ class Video { List podDeduplication static Video getDefaultVideo() { +<<<<<<< HEAD new Video(mimes: ["video/mp4"], width: 300, height: 200) +======= + new Video(mimes: ["video/mp4"], weight: 300, height: 200) +>>>>>>> 04d9d4a13 (Initial commit) } } diff --git a/src/test/groovy/org/prebid/server/functional/model/response/auction/Bid.groovy b/src/test/groovy/org/prebid/server/functional/model/response/auction/Bid.groovy index 49beb80792f..19aeb6590f3 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/auction/Bid.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/auction/Bid.groovy @@ -40,11 +40,19 @@ class Bid implements ObjectMapperWrapper { String langb String dealid @JsonProperty("w") +<<<<<<< HEAD Integer width @JsonProperty("h") Integer height @JsonProperty("wratio") Integer widthRatio +======= + Integer weight + @JsonProperty("h") + Integer height + @JsonProperty("wratio") + Integer weightRatio +>>>>>>> 04d9d4a13 (Initial commit) @JsonProperty("hratio") Integer heightRatio Integer exp @@ -65,7 +73,11 @@ class Bid implements ObjectMapperWrapper { price = imp.bidFloor != null ? imp.bidFloor : PBSUtils.getRandomPrice() crid = 1 height = imp.banner && imp.banner.format ? imp.banner.format.first().height : null +<<<<<<< HEAD width = imp.banner && imp.banner.format ? imp.banner.format.first().width : null +======= + weight = imp.banner && imp.banner.format ? imp.banner.format.first().weight : null +>>>>>>> 04d9d4a13 (Initial commit) if (imp.nativeObj || imp.video) { adm = new Adm(assets: [Asset.defaultAsset]) } diff --git a/src/test/groovy/org/prebid/server/functional/model/response/auction/BidResponse.groovy b/src/test/groovy/org/prebid/server/functional/model/response/auction/BidResponse.groovy index 353f89c454e..d4b877a6290 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/auction/BidResponse.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/auction/BidResponse.groovy @@ -1,6 +1,9 @@ package org.prebid.server.functional.model.response.auction +<<<<<<< HEAD import com.fasterxml.jackson.annotation.JsonProperty +======= +>>>>>>> 04d9d4a13 (Initial commit) import groovy.transform.EqualsAndHashCode import groovy.transform.ToString import org.prebid.server.functional.model.Currency @@ -19,8 +22,12 @@ class BidResponse implements ResponseModel { String bidid Currency cur String customdata +<<<<<<< HEAD @JsonProperty("nbr") NoBidResponse noBidResponse +======= + NoBidResponse nbr +>>>>>>> 04d9d4a13 (Initial commit) BidResponseExt ext static BidResponse getDefaultBidResponse(BidRequest bidRequest, BidderName bidderName = GENERIC) { diff --git a/src/test/groovy/org/prebid/server/functional/repository/HibernateRepositoryService.groovy b/src/test/groovy/org/prebid/server/functional/repository/HibernateRepositoryService.groovy index cd1b9706f79..a8fa3134261 100644 --- a/src/test/groovy/org/prebid/server/functional/repository/HibernateRepositoryService.groovy +++ b/src/test/groovy/org/prebid/server/functional/repository/HibernateRepositoryService.groovy @@ -3,14 +3,20 @@ package org.prebid.server.functional.repository import org.hibernate.SessionFactory import org.hibernate.cfg.Configuration import org.prebid.server.functional.model.db.Account +<<<<<<< HEAD import org.prebid.server.functional.model.db.StoredProfileImp import org.prebid.server.functional.model.db.StoredProfileRequest +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.functional.model.db.StoredImp import org.prebid.server.functional.model.db.StoredRequest import org.prebid.server.functional.model.db.StoredResponse import org.prebid.server.functional.repository.dao.AccountDao +<<<<<<< HEAD import org.prebid.server.functional.repository.dao.ProfileImpDao import org.prebid.server.functional.repository.dao.ProfileRequestDao +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.functional.repository.dao.StoredImpDao import org.prebid.server.functional.repository.dao.StoredRequestDao import org.prebid.server.functional.repository.dao.StoredResponseDao @@ -27,8 +33,11 @@ class HibernateRepositoryService { StoredImpDao storedImpDao StoredRequestDao storedRequestDao StoredResponseDao storedResponseDao +<<<<<<< HEAD ProfileImpDao profileImpDao ProfileRequestDao profileRequestDao +======= +>>>>>>> 04d9d4a13 (Initial commit) HibernateRepositoryService(JdbcDatabaseContainer container) { def jdbcUrl = container.jdbcUrl @@ -44,8 +53,11 @@ class HibernateRepositoryService { storedImpDao = new StoredImpDao(entityManagerUtil) storedRequestDao = new StoredRequestDao(entityManagerUtil) storedResponseDao = new StoredResponseDao(entityManagerUtil) +<<<<<<< HEAD profileImpDao = new ProfileImpDao(entityManagerUtil) profileRequestDao = new ProfileRequestDao(entityManagerUtil) +======= +>>>>>>> 04d9d4a13 (Initial commit) } private static SessionFactory configureHibernate(String jdbcUrl, @@ -67,8 +79,11 @@ class HibernateRepositoryService { configuration.addAnnotatedClass(StoredImp) configuration.addAnnotatedClass(StoredRequest) configuration.addAnnotatedClass(StoredResponse) +<<<<<<< HEAD configuration.addAnnotatedClass(StoredProfileImp) configuration.addAnnotatedClass(StoredProfileRequest) +======= +>>>>>>> 04d9d4a13 (Initial commit) SessionFactory sessionFactory = configuration.addProperties(properties).buildSessionFactory() sessionFactory @@ -79,7 +94,10 @@ class HibernateRepositoryService { storedImpDao.removeAll() storedRequestDao.removeAll() storedResponseDao.removeAll() +<<<<<<< HEAD profileImpDao.removeAll() profileRequestDao.removeAll() +======= +>>>>>>> 04d9d4a13 (Initial commit) } } diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/container/PrebidServerContainer.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/container/PrebidServerContainer.groovy index e13fcae3764..aa6b0befa56 100644 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/container/PrebidServerContainer.groovy +++ b/src/test/groovy/org/prebid/server/functional/testcontainers/container/PrebidServerContainer.groovy @@ -5,7 +5,10 @@ import org.prebid.server.functional.testcontainers.PbsConfig import org.prebid.server.functional.util.SystemProperties import org.testcontainers.containers.GenericContainer import org.testcontainers.containers.wait.strategy.Wait +<<<<<<< HEAD import org.testcontainers.images.builder.Transferable +======= +>>>>>>> 04d9d4a13 (Initial commit) import static org.prebid.server.functional.testcontainers.PbsConfig.DEFAULT_ENV @@ -96,6 +99,7 @@ class PrebidServerContainer extends GenericContainer { .replace("]", "_") } +<<<<<<< HEAD PrebidServerContainer withFolder(String containerPath) { this.withCopyToContainer( Transferable.of(new byte[0], 010755), @@ -104,6 +108,8 @@ class PrebidServerContainer extends GenericContainer { return this } +======= +>>>>>>> 04d9d4a13 (Initial commit) // This is a workaround for cases when container is killed mid-test due to OOM void refresh() { if (!running) { diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/Bidder.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/Bidder.groovy index 05d6fcfa3d7..16e18199e41 100644 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/Bidder.groovy +++ b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/Bidder.groovy @@ -75,7 +75,11 @@ class Bidder extends NetworkScaffolding { def formatNode = it.get("banner") != null ? it.get("banner").get("format") : null new Imp(id: it.get("id").asText(), banner: formatNode != null +<<<<<<< HEAD ? new Banner(format: [new Format(width: formatNode.first().get("w").asInt(), height: formatNode.first().get("h").asInt())]) +======= + ? new Banner(format: [new Format(weight: formatNode.first().get("w").asInt(), height: formatNode.first().get("h").asInt())]) +>>>>>>> 04d9d4a13 (Initial commit) : null)} def bidRequest = new BidRequest(id: id, imp: imps) def response = BidResponse.getDefaultBidResponse(bidRequest) diff --git a/src/test/groovy/org/prebid/server/functional/tests/AmpSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/AmpSpec.groovy index 47e08555828..99805915179 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/AmpSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/AmpSpec.groovy @@ -87,7 +87,11 @@ class AmpSpec extends BaseSpec { then: "Response should contain information from stored response" def price = storedAuctionResponse.bid[0].price assert response.targeting["hb_pb"] == getRoundedTargetingValueWithDownPrecision(price) +<<<<<<< HEAD assert response.targeting["hb_size"] == "${storedAuctionResponse.bid[0].width}x${storedAuctionResponse.bid[0].height}" +======= + assert response.targeting["hb_size"] == "${storedAuctionResponse.bid[0].weight}x${storedAuctionResponse.bid[0].height}" +>>>>>>> 04d9d4a13 (Initial commit) and: "PBS not send request to bidder" assert bidder.getRequestCount(ampStoredRequest.id) == 0 @@ -126,7 +130,11 @@ class AmpSpec extends BaseSpec { assert bidderRequest.site?.publisher?.id == ampRequest.account.toString() assert bidderRequest.imp[0]?.tagId == ampRequest.slot assert bidderRequest.imp[0]?.banner?.format*.height == [ampRequest.h, msH] +<<<<<<< HEAD assert bidderRequest.imp[0]?.banner?.format*.width == [ampRequest.w, msW] +======= + assert bidderRequest.imp[0]?.banner?.format*.weight == [ampRequest.w, msW] +>>>>>>> 04d9d4a13 (Initial commit) assert bidderRequest.regs?.gdpr == (ampRequest.gdprApplies ? 1 : 0) } @@ -154,7 +162,11 @@ class AmpSpec extends BaseSpec { def bidderRequest = bidder.getBidderRequest(ampStoredRequest.id) assert bidderRequest.imp[0]?.banner?.format*.height == [ampRequest.oh] +<<<<<<< HEAD assert bidderRequest.imp[0]?.banner?.format*.width == [ampRequest.ow] +======= + assert bidderRequest.imp[0]?.banner?.format*.weight == [ampRequest.ow] +>>>>>>> 04d9d4a13 (Initial commit) } def "PBS should take parameters from the stored request when it's not specified in the request"() { @@ -180,7 +192,11 @@ class AmpSpec extends BaseSpec { assert bidderRequest.site?.publisher?.id == ampStoredRequest.site.publisher.id assert !bidderRequest.imp[0]?.tagId assert bidderRequest.imp[0]?.banner?.format[0]?.height == ampStoredRequest.imp[0].banner.format[0].height +<<<<<<< HEAD assert bidderRequest.imp[0]?.banner?.format[0]?.width == ampStoredRequest.imp[0].banner.format[0].width +======= + assert bidderRequest.imp[0]?.banner?.format[0]?.weight == ampStoredRequest.imp[0].banner.format[0].weight +>>>>>>> 04d9d4a13 (Initial commit) assert bidderRequest.regs?.gdpr == ampStoredRequest.regs.gdpr } diff --git a/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy index b47a2e47ddf..9e17852ab0c 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy @@ -35,10 +35,17 @@ class BidderFormatSpec extends BaseSpec { @Shared private static final RANDOM_NUMBER = PBSUtils.randomNumber +<<<<<<< HEAD def "PBS should successfully pass when banner.format width and height is valid"() { given: "Default bid request with banner format" def bidRequest = BidRequest.defaultBidRequest.tap { imp[0].banner.format = [new Format(width: bannerFormatWidth, height: bannerFormatHeight)] +======= + def "PBS should successfully pass when banner.format weight and height is valid"() { + given: "Default bid request with banner format" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner.format = [new Format(weight: bannerFormatWeight, height: bannerFormatHeight)] +>>>>>>> 04d9d4a13 (Initial commit) } when: "Requesting PBS auction" @@ -46,19 +53,34 @@ class BidderFormatSpec extends BaseSpec { then: "BidResponse should contain the same banner format as on request" def bidderRequest = bidder.getBidderRequest(bidRequest.id) +<<<<<<< HEAD assert bidderRequest?.imp[0]?.banner?.format[0].width == bannerFormatWidth assert bidderRequest?.imp[0]?.banner?.format[0].height == bannerFormatHeight where: bannerFormatWidth | bannerFormatHeight +======= + assert bidderRequest?.imp[0]?.banner?.format[0].weight == bannerFormatWeight + assert bidderRequest?.imp[0]?.banner?.format[0].height == bannerFormatHeight + + where: + bannerFormatWeight | bannerFormatHeight +>>>>>>> 04d9d4a13 (Initial commit) 1 | 1 PBSUtils.randomNumber | PBSUtils.randomNumber } +<<<<<<< HEAD def "PBS should unsuccessfully pass and throw error due to validation banner.format{w.h} when banner.format width or height is invalid"() { given: "Default bid request with banner format" def bidRequest = BidRequest.defaultBidRequest.tap { imp[0].banner.format = [new Format(width: bannerFormatWidth, height: bannerFormatHeight)] +======= + def "PBS should unsuccessfully pass and throw error due to validation banner.format{w.h} when banner.format weight or height is invalid"() { + given: "Default bid request with banner format" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner.format = [new Format(weight: bannerFormatWeight, height: bannerFormatHeight)] +>>>>>>> 04d9d4a13 (Initial commit) } when: "Requesting PBS auction" @@ -71,7 +93,11 @@ class BidderFormatSpec extends BaseSpec { "request.imp[0].banner.format[0] must define a valid \"h\" and \"w\" properties" where: +<<<<<<< HEAD bannerFormatWidth | bannerFormatHeight +======= + bannerFormatWeight | bannerFormatHeight +>>>>>>> 04d9d4a13 (Initial commit) 0 | PBSUtils.randomNumber PBSUtils.randomNumber | 0 null | PBSUtils.randomNumber @@ -80,10 +106,17 @@ class BidderFormatSpec extends BaseSpec { PBSUtils.randomNumber | PBSUtils.randomNegativeNumber } +<<<<<<< HEAD def "PBS should unsuccessfully pass and throw error due to validation banner.format{w.h} when banner.format width and height is invalid"() { given: "Default bid request with banner format" def bidRequest = BidRequest.defaultBidRequest.tap { imp[0].banner.format = [new Format(width: bannerFormatWidth, height: bannerFormatHeight)] +======= + def "PBS should unsuccessfully pass and throw error due to validation banner.format{w.h} when banner.format weight and height is invalid"() { + given: "Default bid request with banner format" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner.format = [new Format(weight: bannerFormatWeight, height: bannerFormatHeight)] +>>>>>>> 04d9d4a13 (Initial commit) } when: "Requesting PBS auction" @@ -97,7 +130,11 @@ class BidderFormatSpec extends BaseSpec { "*or* {wmin, wratio, hratio} (for flexible sizes) to be non-zero positive" where: +<<<<<<< HEAD bannerFormatWidth | bannerFormatHeight +======= + bannerFormatWeight | bannerFormatHeight +>>>>>>> 04d9d4a13 (Initial commit) 0 | 0 0 | null 0 | PBSUtils.randomNegativeNumber @@ -106,10 +143,17 @@ class BidderFormatSpec extends BaseSpec { PBSUtils.randomNegativeNumber | PBSUtils.randomNegativeNumber } +<<<<<<< HEAD def "PBS should successfully pass when banner width and height is valid"() { given: "Default bid request with banner format" def bidRequest = BidRequest.defaultBidRequest.tap { imp[0].banner = new Banner(width: bannerFormatWidth, height: bannerFormatHeight) +======= + def "PBS should successfully pass when banner weight and height is valid"() { + given: "Default bid request with banner format" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner = new Banner(weight: bannerFormatWeight, height: bannerFormatHeight) +>>>>>>> 04d9d4a13 (Initial commit) } when: "Requesting PBS auction" @@ -117,11 +161,19 @@ class BidderFormatSpec extends BaseSpec { then: "BidResponse should contain the same banner{w.h} as on request" def bidderRequest = bidder.getBidderRequest(bidRequest.id) +<<<<<<< HEAD assert bidderRequest?.imp[0]?.banner?.width == bannerFormatWidth assert bidderRequest?.imp[0]?.banner?.height == bannerFormatHeight where: bannerFormatWidth | bannerFormatHeight +======= + assert bidderRequest?.imp[0]?.banner?.weight == bannerFormatWeight + assert bidderRequest?.imp[0]?.banner?.height == bannerFormatHeight + + where: + bannerFormatWeight | bannerFormatHeight +>>>>>>> 04d9d4a13 (Initial commit) 1 | 1 PBSUtils.randomNumber | PBSUtils.randomNumber } @@ -129,7 +181,11 @@ class BidderFormatSpec extends BaseSpec { def "PBS should unsuccessfully pass and throw error due to validation banner{w.h} when banner{w.h} is invalid"() { given: "Default bid request with banner{w.h}" def bidRequest = BidRequest.defaultBidRequest.tap { +<<<<<<< HEAD imp[0].banner = new Banner(width: bannerFormatWidth, height: bannerFormatHeight) +======= + imp[0].banner = new Banner(weight: bannerFormatWeight, height: bannerFormatHeight) +>>>>>>> 04d9d4a13 (Initial commit) } when: "Requesting PBS auction" @@ -142,7 +198,11 @@ class BidderFormatSpec extends BaseSpec { "request.imp[0].banner has no sizes. Define \"w\" and \"h\", or include \"format\" elements" where: +<<<<<<< HEAD bannerFormatWidth | bannerFormatHeight +======= + bannerFormatWeight | bannerFormatHeight +>>>>>>> 04d9d4a13 (Initial commit) 0 | 0 0 | PBSUtils.randomNumber PBSUtils.randomNumber | 0 @@ -162,7 +222,11 @@ class BidderFormatSpec extends BaseSpec { def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { imp[0].tap { +<<<<<<< HEAD banner = new Banner(format: [new Format(width: RANDOM_NUMBER, height: RANDOM_NUMBER)]) +======= + banner = new Banner(format: [new Format(weight: RANDOM_NUMBER, height: RANDOM_NUMBER)]) +>>>>>>> 04d9d4a13 (Initial commit) ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } } @@ -172,7 +236,11 @@ class BidderFormatSpec extends BaseSpec { def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { it.seatbid[0].bid[0].tap { it.id = storedBidId +<<<<<<< HEAD it.width = responseWidth +======= + it.weight = responseWeight +>>>>>>> 04d9d4a13 (Initial commit) it.height = responseHeight } } @@ -201,18 +269,30 @@ class BidderFormatSpec extends BaseSpec { "Warning: BidResponse validation `warn`: bidder `${GENERIC}` response triggers creative size " + "validation for bid ${storedBidId}, account=${bidRequest.accountId}, " + "referrer=${bidRequest.site.page}, max imp size='${RANDOM_NUMBER}x${RANDOM_NUMBER}', " + +<<<<<<< HEAD "bid response size='${responseWidth}x${responseHeight}'" and: "Bid response should contain width and height from stored response" def bid = bidResponse.seatbid[0].bid[0] assert bid.width == responseWidth +======= + "bid response size='${responseWeight}x${responseHeight}'" + + and: "Bid response should contain weight and height from stored response" + def bid = bidResponse.seatbid[0].bid[0] + assert bid.weight == responseWeight +>>>>>>> 04d9d4a13 (Initial commit) assert bid.height == responseHeight and: "PBs shouldn't perform a bidder request due to stored bid response" assert !bidder.getBidderRequests(bidRequest.id) where: +<<<<<<< HEAD accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight +======= + accountCretiveMaxSize | configCreativeMaxSize | responseWeight | responseHeight +>>>>>>> 04d9d4a13 (Initial commit) null | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 null | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER null | WARN.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 @@ -229,7 +309,11 @@ class BidderFormatSpec extends BaseSpec { def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { imp[0].tap { +<<<<<<< HEAD banner = new Banner(format: [new Format(width: RANDOM_NUMBER, height: RANDOM_NUMBER)]) +======= + banner = new Banner(format: [new Format(weight: RANDOM_NUMBER, height: RANDOM_NUMBER)]) +>>>>>>> 04d9d4a13 (Initial commit) ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } } @@ -237,7 +321,11 @@ class BidderFormatSpec extends BaseSpec { and: "Stored bid response with biggest W and H than in bidRequest in DB" def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { it.seatbid[0].bid[0].tap { +<<<<<<< HEAD it.width = responseWidth +======= + it.weight = responseWeight +>>>>>>> 04d9d4a13 (Initial commit) it.height = responseHeight } } @@ -261,16 +349,26 @@ class BidderFormatSpec extends BaseSpec { and: "Response should contain error" assert !bidResponse.ext?.errors +<<<<<<< HEAD and: "Bid response should contain width and height from stored response" def bid = bidResponse.seatbid[0].bid[0] assert bid.width == responseWidth +======= + and: "Bid response should contain weight and height from stored response" + def bid = bidResponse.seatbid[0].bid[0] + assert bid.weight == responseWeight +>>>>>>> 04d9d4a13 (Initial commit) assert bid.height == responseHeight and: "PBs shouldn't perform a bidder request due to stored bid response" assert !bidder.getBidderRequests(bidRequest.id) where: +<<<<<<< HEAD accountCretiveMaxSizeSnakeCase | accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight +======= + accountCretiveMaxSizeSnakeCase | accountCretiveMaxSize | configCreativeMaxSize | responseWeight | responseHeight +>>>>>>> 04d9d4a13 (Initial commit) null | null | SKIP.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 null | null | SKIP.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER null | null | SKIP.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 @@ -293,7 +391,11 @@ class BidderFormatSpec extends BaseSpec { def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { imp[0].tap { +<<<<<<< HEAD banner = new Banner(format: [new Format(width: RANDOM_NUMBER, height: RANDOM_NUMBER)]) +======= + banner = new Banner(format: [new Format(weight: RANDOM_NUMBER, height: RANDOM_NUMBER)]) +>>>>>>> 04d9d4a13 (Initial commit) ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } } @@ -303,7 +405,11 @@ class BidderFormatSpec extends BaseSpec { def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { it.seatbid[0].bid[0].tap { it.id = storedBidId +<<<<<<< HEAD it.width = responseWidth +======= + it.weight = responseWeight +>>>>>>> 04d9d4a13 (Initial commit) it.height = responseHeight } } @@ -332,7 +438,11 @@ class BidderFormatSpec extends BaseSpec { "Error: BidResponse validation `enforce`: bidder `${GENERIC.value}` response triggers creative size " + "validation for bid ${storedBidId}, account=${bidRequest.accountId}, " + "referrer=${bidRequest.site.page}, max imp size='${RANDOM_NUMBER}x${RANDOM_NUMBER}', " + +<<<<<<< HEAD "bid response size='${responseWidth}x${responseHeight}'" +======= + "bid response size='${responseWeight}x${responseHeight}'" +>>>>>>> 04d9d4a13 (Initial commit) and: "Pbs should discard seatBid due to validation" assert !bidResponse.seatbid @@ -341,7 +451,11 @@ class BidderFormatSpec extends BaseSpec { assert !bidder.getBidderRequests(bidRequest.id) where: +<<<<<<< HEAD accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight +======= + accountCretiveMaxSize | configCreativeMaxSize | responseWeight | responseHeight +>>>>>>> 04d9d4a13 (Initial commit) null | ENFORCE.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 null | ENFORCE.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER null | ENFORCE.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 @@ -358,7 +472,11 @@ class BidderFormatSpec extends BaseSpec { def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { imp[0].tap { +<<<<<<< HEAD banner = new Banner(format: [new Format(width: RANDOM_NUMBER, height: RANDOM_NUMBER)]) +======= + banner = new Banner(format: [new Format(weight: RANDOM_NUMBER, height: RANDOM_NUMBER)]) +>>>>>>> 04d9d4a13 (Initial commit) ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } } @@ -366,7 +484,11 @@ class BidderFormatSpec extends BaseSpec { and: "Stored bid response with biggest W and H than in bidRequest in DB" def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { it.seatbid[0].bid[0].tap { +<<<<<<< HEAD width = RANDOM_NUMBER +======= + weight = RANDOM_NUMBER +>>>>>>> 04d9d4a13 (Initial commit) height = RANDOM_NUMBER } } @@ -388,9 +510,15 @@ class BidderFormatSpec extends BaseSpec { and: "Response should contain error" assert !bidResponse.ext?.errors +<<<<<<< HEAD and: "Bid response should contain width and height from stored response" def bid = bidResponse.seatbid[0].bid[0] assert bid.width == RANDOM_NUMBER +======= + and: "Bid response should contain weight and height from stored response" + def bid = bidResponse.seatbid[0].bid[0] + assert bid.weight == RANDOM_NUMBER +>>>>>>> 04d9d4a13 (Initial commit) assert bid.height == RANDOM_NUMBER and: "PBs shouldn't perform a bidder request due to stored bid response" @@ -414,7 +542,11 @@ class BidderFormatSpec extends BaseSpec { def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.getDefaultVideoRequest().tap { imp[0].tap { +<<<<<<< HEAD video = new Video(width: RANDOM_NUMBER, height: RANDOM_NUMBER, mimes: [PBSUtils.randomString]) +======= + video = new Video(weight: RANDOM_NUMBER, height: RANDOM_NUMBER, mimes: [PBSUtils.randomString]) +>>>>>>> 04d9d4a13 (Initial commit) ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } } @@ -422,7 +554,11 @@ class BidderFormatSpec extends BaseSpec { and: "Stored bid response with biggest W and H than in bidRequest in DB" def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { it.seatbid[0].bid[0].tap { +<<<<<<< HEAD width = responseWidth +======= + weight = responseWeight +>>>>>>> 04d9d4a13 (Initial commit) height = responseHeight } } @@ -451,7 +587,11 @@ class BidderFormatSpec extends BaseSpec { assert !bidder.getBidderRequests(bidRequest.id) where: +<<<<<<< HEAD accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight +======= + accountCretiveMaxSize | configCreativeMaxSize | responseWeight | responseHeight +>>>>>>> 04d9d4a13 (Initial commit) null | ENFORCE.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 null | ENFORCE.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER null | ENFORCE.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 @@ -480,7 +620,11 @@ class BidderFormatSpec extends BaseSpec { def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { imp[0].tap { +<<<<<<< HEAD banner = new Banner(format: [new Format(width: RANDOM_NUMBER, height: RANDOM_NUMBER)]) +======= + banner = new Banner(format: [new Format(weight: RANDOM_NUMBER, height: RANDOM_NUMBER)]) +>>>>>>> 04d9d4a13 (Initial commit) ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } } @@ -490,7 +634,11 @@ class BidderFormatSpec extends BaseSpec { def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { it.seatbid[0].bid[0].tap { it.id = storedBidId +<<<<<<< HEAD it.width = responseWidth +======= + it.weight = responseWeight +>>>>>>> 04d9d4a13 (Initial commit) it.height = responseHeight } } @@ -519,7 +667,11 @@ class BidderFormatSpec extends BaseSpec { "Error: BidResponse validation `enforce`: bidder `generic` response triggers creative size " + "validation for bid ${storedBidId}, account=${bidRequest.accountId}, " + "referrer=${bidRequest.site.page}, max imp size='${RANDOM_NUMBER}x${RANDOM_NUMBER}', " + +<<<<<<< HEAD "bid response size='${responseWidth}x${responseHeight}'" +======= + "bid response size='${responseWeight}x${responseHeight}'" +>>>>>>> 04d9d4a13 (Initial commit) and: "Pbs should discard seatBid due to validation" assert !bidResponse.seatbid @@ -528,7 +680,11 @@ class BidderFormatSpec extends BaseSpec { assert !bidder.getBidderRequests(bidRequest.id) where: +<<<<<<< HEAD accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight +======= + accountCretiveMaxSize | configCreativeMaxSize | responseWeight | responseHeight +>>>>>>> 04d9d4a13 (Initial commit) ENFORCE | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 ENFORCE | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER ENFORCE | WARN.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 diff --git a/src/test/groovy/org/prebid/server/functional/tests/SeatNonBidSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/SeatNonBidSpec.groovy index bd636e9ccea..dca7d589c98 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/SeatNonBidSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/SeatNonBidSpec.groovy @@ -118,7 +118,11 @@ class SeatNonBidSpec extends BaseSpec { def bidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { seatbid.first.tap { bid.first.height = bidRequest.imp.first.banner.format.first.height + 1 +<<<<<<< HEAD bid.first.width = bidRequest.imp.first.banner.format.first.width + 1 +======= + bid.first.weight = bidRequest.imp.first.banner.format.first.weight + 1 +>>>>>>> 04d9d4a13 (Initial commit) } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsRulesSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsRulesSpec.groovy index 4e9bc40b590..70281b12efb 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsRulesSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsRulesSpec.groovy @@ -306,8 +306,13 @@ class PriceFloorsRulesSpec extends PriceFloorsBaseSpec { def higherWidth = lowerWidth + 1 def higherHigh = lowerHigh + 1 def bidRequest = BidRequest.defaultBidRequest.tap { +<<<<<<< HEAD imp[0].banner.format = [new Format(width: lowerWidth, height: lowerHigh), new Format(width: higherWidth, height: higherHigh)] +======= + imp[0].banner.format = [new Format(weight: lowerWidth, height: lowerHigh), + new Format(weight: higherWidth, height: higherHigh)] +>>>>>>> 04d9d4a13 (Initial commit) } and: "Account with enabled fetch, fetch.url in the DB" @@ -374,19 +379,31 @@ class PriceFloorsRulesSpec extends PriceFloorsBaseSpec { mediaType | impClosure org.prebid.server.functional.model.response.auction.MediaType.BANNER | { int widthVal, int heightVal -> Imp.getDefaultImpression(mediaType).tap { +<<<<<<< HEAD banner.format = [new Format(width: widthVal, height: heightVal)] +======= + banner.format = [new Format(weight: widthVal, height: heightVal)] +>>>>>>> 04d9d4a13 (Initial commit) } } org.prebid.server.functional.model.response.auction.MediaType.BANNER | { int widthVal, int heightVal -> Imp.getDefaultImpression(mediaType).tap { banner.format = null +<<<<<<< HEAD banner.width = widthVal +======= + banner.weight = widthVal +>>>>>>> 04d9d4a13 (Initial commit) banner.height = heightVal } } org.prebid.server.functional.model.response.auction.MediaType.VIDEO | { int widthVal, int heightVal -> Imp.getDefaultImpression(mediaType).tap { +<<<<<<< HEAD video.width = widthVal +======= + video.weight = widthVal +>>>>>>> 04d9d4a13 (Initial commit) video.height = heightVal } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/storage/AmpS3Spec.groovy b/src/test/groovy/org/prebid/server/functional/tests/storage/AmpS3Spec.groovy index cf5e68bbc90..bcb5cb4009a 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/storage/AmpS3Spec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/storage/AmpS3Spec.groovy @@ -39,7 +39,11 @@ class AmpS3Spec extends StorageBaseSpec { assert bidderRequest.site?.publisher?.id == ampStoredRequest.site.publisher.id assert !bidderRequest.imp[0]?.tagId assert bidderRequest.imp[0]?.banner?.format[0]?.height == ampStoredRequest.imp[0].banner.format[0].height +<<<<<<< HEAD assert bidderRequest.imp[0]?.banner?.format[0]?.width == ampStoredRequest.imp[0].banner.format[0].width +======= + assert bidderRequest.imp[0]?.banner?.format[0]?.weight == ampStoredRequest.imp[0].banner.format[0].weight +>>>>>>> 04d9d4a13 (Initial commit) assert bidderRequest.regs?.gdpr == ampStoredRequest.regs.gdpr } diff --git a/src/test/groovy/org/prebid/server/functional/util/ObjectMapperWrapper.groovy b/src/test/groovy/org/prebid/server/functional/util/ObjectMapperWrapper.groovy index 15106b6a55f..a63dfdf7022 100644 --- a/src/test/groovy/org/prebid/server/functional/util/ObjectMapperWrapper.groovy +++ b/src/test/groovy/org/prebid/server/functional/util/ObjectMapperWrapper.groovy @@ -4,7 +4,10 @@ import com.fasterxml.jackson.core.type.TypeReference import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.dataformat.xml.XmlMapper +<<<<<<< HEAD import com.fasterxml.jackson.dataformat.yaml.YAMLMapper +======= +>>>>>>> 04d9d4a13 (Initial commit) import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL @@ -12,7 +15,10 @@ trait ObjectMapperWrapper { private static final ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(NON_NULL) .registerModule(new ZonedDateTimeModule()) +<<<<<<< HEAD private static final YAMLMapper yamlMapper = new YAMLMapper().setSerializationInclusion(NON_NULL) as YAMLMapper +======= +>>>>>>> 04d9d4a13 (Initial commit) private static final XmlMapper xmlMapper = new XmlMapper() final static String encode(Object object) { @@ -46,8 +52,11 @@ trait ObjectMapperWrapper { final static String encodeXml(Object object) { xmlMapper.writeValueAsString(object) } +<<<<<<< HEAD final static String encodeYaml(Object object) { yamlMapper.writeValueAsString(object) } +======= +>>>>>>> 04d9d4a13 (Initial commit) } diff --git a/src/test/groovy/org/prebid/server/functional/util/PBSUtils.groovy b/src/test/groovy/org/prebid/server/functional/util/PBSUtils.groovy index 748071dd10f..983fb723fcc 100644 --- a/src/test/groovy/org/prebid/server/functional/util/PBSUtils.groovy +++ b/src/test/groovy/org/prebid/server/functional/util/PBSUtils.groovy @@ -50,6 +50,7 @@ class PBSUtils implements ObjectMapperWrapper { RandomStringUtils.randomAlphanumeric(stringLength) } +<<<<<<< HEAD static String getRandomSpecialChars(int stringLength = 20) { RandomStringUtils.random(stringLength, "!@#\$%^&*()-_=+[]{}|;:'\",.<>/?") } @@ -58,6 +59,8 @@ class PBSUtils implements ObjectMapperWrapper { RandomStringUtils.randomAscii(stringLength) } +======= +>>>>>>> 04d9d4a13 (Initial commit) static Boolean getRandomBoolean() { new Random().nextBoolean() } @@ -115,7 +118,11 @@ class PBSUtils implements ObjectMapperWrapper { } } +<<<<<<< HEAD static BigDecimal getRandomPrice(int min = 1, int max = 10, int scale = 3) { +======= + static BigDecimal getRandomPrice(int min = 0, int max = 10, int scale = 3) { +>>>>>>> 04d9d4a13 (Initial commit) getRandomDecimal(min, max).setScale(scale, HALF_UP) } diff --git a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java index d956beae62f..836dc048f5f 100644 --- a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java +++ b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java @@ -35,7 +35,10 @@ import org.prebid.server.activity.infrastructure.ActivityInfrastructure; import org.prebid.server.activity.infrastructure.rule.Rule; import org.prebid.server.auction.categorymapping.CategoryMappingService; +<<<<<<< HEAD import org.prebid.server.auction.externalortb.StoredRequestProcessor; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.AuctionParticipation; import org.prebid.server.auction.model.BidInfo; @@ -1107,8 +1110,12 @@ public void shouldSetExpectedBidsWithRanksWhenBidRankingEnabled() { contextBuilder -> contextBuilder .auctionParticipations(toAuctionParticipant(bidderResponses)) .account(Account.builder().auction(AccountAuctionConfig.builder() +<<<<<<< HEAD .ranking(AccountBidRankingConfig.of(true)) .build()) +======= + .ranking(AccountBidRankingConfig.of(true)).build()) +>>>>>>> 04d9d4a13 (Initial commit) .build())); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder().doCaching(true).build(); diff --git a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java index 92523904e2e..748f428fb25 100644 --- a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java +++ b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java @@ -43,7 +43,10 @@ import org.prebid.server.activity.Activity; import org.prebid.server.activity.ComponentType; import org.prebid.server.activity.infrastructure.ActivityInfrastructure; +<<<<<<< HEAD import org.prebid.server.auction.externalortb.StoredResponseProcessor; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.mediatypeprocessor.MediaTypeProcessingResult; import org.prebid.server.auction.mediatypeprocessor.MediaTypeProcessor; import org.prebid.server.auction.model.AuctionContext; diff --git a/src/test/java/org/prebid/server/auction/SkippedAuctionServiceTest.java b/src/test/java/org/prebid/server/auction/SkippedAuctionServiceTest.java index 854fef12ac8..d25796372fd 100644 --- a/src/test/java/org/prebid/server/auction/SkippedAuctionServiceTest.java +++ b/src/test/java/org/prebid/server/auction/SkippedAuctionServiceTest.java @@ -10,7 +10,10 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +<<<<<<< HEAD import org.prebid.server.auction.externalortb.StoredResponseProcessor; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.StoredResponseResult; import org.prebid.server.auction.model.TimeoutContext; diff --git a/src/test/java/org/prebid/server/auction/StoredRequestProcessorTest.java b/src/test/java/org/prebid/server/auction/StoredRequestProcessorTest.java new file mode 100644 index 00000000000..9b9aa5aba48 --- /dev/null +++ b/src/test/java/org/prebid/server/auction/StoredRequestProcessorTest.java @@ -0,0 +1,1039 @@ +package org.prebid.server.auction; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.iab.openrtb.request.App; +import com.iab.openrtb.request.Banner; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Format; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Video; +import io.vertx.core.Future; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.file.FileSystem; +import org.assertj.core.api.InstanceOfAssertFactories; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.prebid.server.VertxTest; +import org.prebid.server.auction.model.AuctionStoredResult; +import org.prebid.server.exception.InvalidRequestException; +import org.prebid.server.execution.timeout.TimeoutFactory; +import org.prebid.server.identity.IdGenerator; +import org.prebid.server.json.JsonMerger; +import org.prebid.server.metric.Metrics; +import org.prebid.server.proto.openrtb.ext.request.ExtImp; +import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtStoredRequest; +import org.prebid.server.settings.ApplicationSettings; +import org.prebid.server.settings.model.StoredDataResult; +import org.prebid.server.settings.model.VideoStoredDataResult; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.function.UnaryOperator; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; +import static java.util.function.UnaryOperator.identity; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anySet; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mock.Strictness.LENIENT; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; + +@ExtendWith(MockitoExtension.class) +public class StoredRequestProcessorTest extends VertxTest { + + private static final int DEFAULT_TIMEOUT = 500; + + @Mock + private FileSystem fileSystem; + @Mock + private ApplicationSettings applicationSettings; + @Mock(strictness = LENIENT) + private IdGenerator idGenerator; + @Mock + private Metrics metrics; + @Mock + private TimeoutFactory timeoutFactory; + + private StoredRequestProcessor storedRequestProcessor; + + @BeforeEach + public void setUp() { + given(idGenerator.generateId()).willReturn("generated-stored-id"); + + storedRequestProcessor = new StoredRequestProcessor( + DEFAULT_TIMEOUT, + null, + false, + fileSystem, + applicationSettings, + idGenerator, + metrics, + timeoutFactory, + jacksonMapper, + new JsonMerger(jacksonMapper)); + } + + @Test + public void shouldReturnMergedBidRequestAndImps() throws IOException { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .storedrequest(ExtStoredRequest.of("bidRequest")) + .build())) + .imp(singletonList(givenImp(impBuilder -> impBuilder + .ext(mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("imp")).build(), + null))))))); + + final String storedRequestImpJson = mapper.writeValueAsString(Imp.builder().banner(Banner.builder() + .format(singletonList(Format.builder().w(300).h(250).build())).build()).build()); + + final String storedRequestBidRequestJson = mapper.writeValueAsString(givenBidRequest(builder -> builder + .id("test-request-id") + .tmax(1000L))); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(singletonMap("bidRequest", storedRequestBidRequestJson), + singletonMap("imp", storedRequestImpJson), emptyList()))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.succeeded()).isTrue(); + assertThat(bidRequestFuture.result().hasStoredBidRequest()).isTrue(); + assertThat(bidRequestFuture.result().bidRequest()).isEqualTo( + BidRequest.builder() + .id("test-request-id") + .tmax(1000L) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .storedrequest(ExtStoredRequest.of("bidRequest")) + .build())) + .imp(singletonList(Imp.builder() + .ext(mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest( + ExtStoredRequest.of("imp")).build(), null))) + .banner(Banner.builder() + .format(singletonList(Format.builder().w(300).h(250).build())) + .build()) + .build())) + .build()); + } + + @Test + public void shouldReturnMergedBidRequest() throws IOException { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .storedrequest(ExtStoredRequest.of("123")) + .build()))); + + final String storedRequestBidRequestJson = mapper.writeValueAsString(givenBidRequest(builder -> builder + .id("test-request-id") + .tmax(1000L))); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(singletonMap("123", storedRequestBidRequestJson), emptyMap(), + emptyList()))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.succeeded()).isTrue(); + assertThat(bidRequestFuture.result().hasStoredBidRequest()).isTrue(); + assertThat(bidRequestFuture.result().bidRequest()).isEqualTo(BidRequest.builder() + .id("test-request-id") + .tmax(1000L) + .ext(ExtRequest.of(ExtRequestPrebid.builder().storedrequest(ExtStoredRequest.of("123")).build())) + .build()); + } + + @Test + public void shouldReturnMergedDefaultAndBidRequest() throws IOException { + // given + given(fileSystem.readFileBlocking(anyString())) + .willReturn(Buffer.buffer(mapper.writeValueAsString(givenBidRequest(builder -> builder + .id("default-request-id") + .at(1) + .test(0) + .tmax(2500L))))); + + storedRequestProcessor = new StoredRequestProcessor( + DEFAULT_TIMEOUT, + "path/to/default/request.json", + false, + fileSystem, + applicationSettings, + idGenerator, + metrics, + timeoutFactory, + jacksonMapper, + new JsonMerger(jacksonMapper)); + + final BidRequest bidRequest = givenBidRequest(builder -> builder + .id("request-id") + .test(1) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .storedrequest(ExtStoredRequest.of("123")) + .build()))); + + final String storedRequestBidRequestJson = mapper.writeValueAsString(givenBidRequest(builder -> builder + .id("stored-request-id") + .tmax(1000L) + .imp(singletonList(Imp.builder().build())))); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(singletonMap("123", storedRequestBidRequestJson), emptyMap(), + emptyList()))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.succeeded()).isTrue(); + assertThat(bidRequestFuture.result().hasStoredBidRequest()).isTrue(); + assertThat(bidRequestFuture.result().bidRequest()).isEqualTo(BidRequest.builder() + .id("request-id") + .at(1) + .test(1) + .tmax(1000L) + .imp(singletonList(Imp.builder().build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder().storedrequest(ExtStoredRequest.of("123")).build())) + .build()); + } + + @Test + public void processStoredRequestsShouldGenerateIdWhenAppAndFlagIsTrue() throws IOException { + // given + storedRequestProcessor = new StoredRequestProcessor( + 500, + null, + true, + fileSystem, + applicationSettings, + idGenerator, + metrics, + timeoutFactory, + jacksonMapper, + new JsonMerger(jacksonMapper)); + + final BidRequest bidRequest = givenBidRequest(builder -> builder + .app(App.builder().build()) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .storedrequest(ExtStoredRequest.of("123")) + .build()))); + + final String storedRequestBidRequestJson = mapper.writeValueAsString(givenBidRequest(builder -> builder + .id("stored-bid-request"))); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(singletonMap("123", storedRequestBidRequestJson), emptyMap(), + emptyList()))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.succeeded()).isTrue(); + assertThat(bidRequestFuture.result().hasStoredBidRequest()).isTrue(); + assertThat(bidRequestFuture.result().bidRequest()).isEqualTo(givenBidRequest(builder -> builder + .id("generated-stored-id") + .app(App.builder().build()) + .ext(ExtRequest.of(ExtRequestPrebid.builder().storedrequest(ExtStoredRequest.of("123")).build())))); + } + + @Test + public void processStoredRequestsShouldGenerateIdWhenAppAndGenerateTemplateInStoredBidRequest() throws IOException { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder + .app(App.builder().build()) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .storedrequest(ExtStoredRequest.of("123")) + .build()))); + + final String storedRequestBidRequestJson = mapper.writeValueAsString(givenBidRequest(builder -> builder + .id("{{UUID}}"))); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(singletonMap("123", storedRequestBidRequestJson), + emptyMap(), + emptyList()))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.succeeded()).isTrue(); + assertThat(bidRequestFuture.result().hasStoredBidRequest()).isTrue(); + assertThat(bidRequestFuture.result().bidRequest()).isEqualTo(givenBidRequest(builder -> builder + .app(App.builder().build()) + .id("generated-stored-id") + .ext(ExtRequest.of(ExtRequestPrebid.builder().storedrequest(ExtStoredRequest.of("123")).build())))); + } + + @Test + public void processAmpRequestShouldReturnAmpRequest() throws IOException { + // given + given(applicationSettings.getAmpStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture(StoredDataResult.of( + singletonMap("123", mapper.writeValueAsString(givenBidRequest(builder -> builder + .id("test-request-id")))), + emptyMap(), + emptyList()))); + + // when + final Future bidRequestFuture = storedRequestProcessor.processAmpRequest(null, "123", + givenBidRequest(identity())); + + // then + assertThat(bidRequestFuture.succeeded()).isTrue(); + assertThat(bidRequestFuture.result()).isEqualTo(BidRequest.builder() + .id("test-request-id") + .build()); + } + + @Test + public void shouldReturnMergedDefaultAndAmpRequest() throws IOException { + // given + given(fileSystem.readFileBlocking(anyString())) + .willReturn(Buffer.buffer(mapper.writeValueAsString(givenBidRequest(builder -> builder.at(1))))); + + storedRequestProcessor = new StoredRequestProcessor( + DEFAULT_TIMEOUT, + "path/to/default/request.json", + false, + fileSystem, + applicationSettings, + idGenerator, + metrics, + timeoutFactory, + jacksonMapper, + new JsonMerger(jacksonMapper)); + + given(applicationSettings.getAmpStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture(StoredDataResult.of( + singletonMap("123", mapper.writeValueAsString( + givenBidRequest(builder -> builder.id("test-request-id")))), + emptyMap(), + emptyList()))); + + // when + final Future bidRequestFuture = storedRequestProcessor.processAmpRequest(null, "123", + givenBidRequest(identity())); + + // then + assertThat(bidRequestFuture.succeeded()).isTrue(); + assertThat(bidRequestFuture.result()).isEqualTo(BidRequest.builder() + .id("test-request-id") + .at(1) + .build()); + } + + @Test + public void processAmpRequestShouldReplaceBidIdWhenGenerateIdFlagIsTrue() throws IOException { + // given + storedRequestProcessor = new StoredRequestProcessor( + 500, + null, + true, + fileSystem, + applicationSettings, + idGenerator, + metrics, + timeoutFactory, + jacksonMapper, + new JsonMerger(jacksonMapper)); + + given(applicationSettings.getAmpStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture(StoredDataResult.of( + singletonMap("123", mapper.writeValueAsString( + givenBidRequest(builder -> builder.id("origin-stored-id")))), + emptyMap(), + emptyList()))); + + // when + final Future bidRequestFuture = storedRequestProcessor.processAmpRequest(null, "123", + givenBidRequest(identity())); + + // then + assertThat(bidRequestFuture.succeeded()).isTrue(); + assertThat(bidRequestFuture.result()).isEqualTo(BidRequest.builder() + .id("generated-stored-id") + .build()); + } + + @Test + public void processAmpRequestShouldReplaceBidIdGenerateTemplateIsInStoredRequestId() throws IOException { + // given + given(applicationSettings.getAmpStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture(StoredDataResult.of( + singletonMap("123", mapper.writeValueAsString( + givenBidRequest(builder -> builder.id("{{UUID}}")))), emptyMap(), emptyList()))); + + // when + final Future bidRequestFuture = storedRequestProcessor.processAmpRequest(null, "123", + givenBidRequest(identity())); + + // then + assertThat(bidRequestFuture.succeeded()).isTrue(); + assertThat(bidRequestFuture.result()).isEqualTo(BidRequest.builder() + .id("generated-stored-id") + .build()); + } + + @Test + public void shouldReturnFailedFutureWhenStoredBidRequestJsonIsNotValid() { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .storedrequest(ExtStoredRequest.of("123")) + .build()))); + + final Map storedRequestFetchResult = singletonMap("123", "{{}"); + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(storedRequestFetchResult, emptyMap(), emptyList()))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.failed()).isTrue(); + assertThat(bidRequestFuture.cause()) + .isInstanceOf(InvalidRequestException.class) + .hasMessage("Stored request processing failed: Can't parse Json for stored request with id 123"); + } + + @Test + public void shouldReturnFailedFutureWhenMergedResultCouldNotBeConvertedToBidRequest() throws IOException { + final BidRequest bidRequest = givenBidRequest(builder -> builder + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .storedrequest(ExtStoredRequest.of("123")) + .build()))); + + final Map storedRequestFetchResult = singletonMap("123", mapper.writeValueAsString( + mapper.createObjectNode().put("tmax", "stringValue"))); + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(storedRequestFetchResult, emptyMap(), emptyList()))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.failed()).isTrue(); + assertThat(bidRequestFuture.cause()) + .isInstanceOf(InvalidRequestException.class) + .hasMessageStartingWith("Stored request processing failed: " + + "Can't convert merging result for id 123: Cannot deserialize"); + } + + @Test + public void shouldReturnFailedFutureIfIdWasNotPresentInStoredRequest() { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .storedrequest(ExtStoredRequest.of(null)) + .build()))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.failed()).isTrue(); + assertThat(bidRequestFuture.cause()) + .isInstanceOf(InvalidRequestException.class) + .hasMessage("Stored request processing failed: Id is not found in storedRequest"); + } + + @Test + public void shouldReturnBidRequestWithMergedImp() throws IOException { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder + .imp(singletonList(givenImp(impBuilder -> impBuilder + .ext(mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("123")).build(), + null))))))); + + final String storedRequestImpJson = mapper.writeValueAsString( + Imp.builder() + .banner(Banner.builder() + .format(singletonList(Format.builder().w(300).h(250).build())) + .build()) + .build()); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(emptyMap(), singletonMap("123", storedRequestImpJson), emptyList()))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.succeeded()).isTrue(); + assertThat(bidRequestFuture.result().hasStoredBidRequest()).isTrue(); + assertThat(bidRequestFuture.result().bidRequest().getImp().getFirst()).isEqualTo(Imp.builder() + .banner(Banner.builder().format(singletonList(Format.builder().w(300).h(250).build())).build()) + .ext(mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("123")).build(), null))) + .build()); + } + + @Test + public void shouldReturnFailedFutureWhenIdIsMissedInPrebidRequest() { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder + .imp(singletonList(givenImp(impBuilder -> impBuilder + .ext(mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of(null)).build(), + null))))))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.failed()).isTrue(); + assertThat(bidRequestFuture.cause()) + .isInstanceOf(InvalidRequestException.class) + .hasMessage("Stored request processing failed: Id is not found in storedRequest"); + } + + @Test + public void shouldReturnFailedFutureWhenJsonBodyWasNotFoundByFetcher() { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder + .imp(singletonList(givenImp(impBuilder -> impBuilder + .ext(mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("123")).build(), + null))))))); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(emptyMap(), emptyMap(), singletonList("No config found for id: 123")))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.failed()).isTrue(); + assertThat(bidRequestFuture.cause()) + .isInstanceOf(InvalidRequestException.class) + .hasMessage("Stored request processing failed: No config found for id: 123"); + } + + @Test + public void shouldReturnImpAndBidRequestWithoutChangesIfStoredRequestIsAbsentInPrebid() { + // given + final Imp imp = givenImp(impBuilder -> impBuilder + .ext(mapper.valueToTree(ExtImp.of(ExtImpPrebid.builder().storedrequest(null).build(), null)))); + final BidRequest bidRequest = givenBidRequest(builder -> builder.imp(singletonList(imp))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + verifyNoInteractions(applicationSettings, metrics); + assertThat(bidRequestFuture.succeeded()).isTrue(); + assertThat(bidRequestFuture.result().hasStoredBidRequest()).isFalse(); + assertThat(bidRequestFuture.result().bidRequest().getImp().getFirst()).isSameAs(imp); + assertThat(bidRequestFuture.result().bidRequest()).isSameAs(bidRequest); + } + + @Test + public void shouldReturnChangedImpWithStoredRequestAndNotModifiedImpWithoutStoreRequest() throws IOException { + // given + final Imp impWithoutStoredRequest = givenImp(impBuilder -> impBuilder.ext( + mapper.valueToTree(ExtImp.of(ExtImpPrebid.builder().storedrequest(null).build(), null)))); + final BidRequest bidRequest = givenBidRequest(builder -> builder + .imp(asList(impWithoutStoredRequest, givenImp(impBuilder -> impBuilder + .ext(mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("123")).build(), + null))))))); + + final String storedRequestImpJson = mapper.writeValueAsString(Imp.builder().banner(Banner.builder() + .format(singletonList(Format.builder().w(300).h(250).build())).build()).build()); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(emptyMap(), singletonMap("123", storedRequestImpJson), emptyList()))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.succeeded()).isTrue(); + assertThat(bidRequestFuture.result().hasStoredBidRequest()).isTrue(); + assertThat(bidRequestFuture.result().bidRequest().getImp().get(0)).isSameAs(impWithoutStoredRequest); + assertThat(bidRequestFuture.result().bidRequest().getImp().get(1)).isEqualTo(Imp.builder() + .banner(Banner.builder().format(singletonList(Format.builder().w(300).h(250).build())).build()) + .ext(mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("123")).build(), null))) + .build()); + } + + @Test + public void shouldReturnFailedFutureIfOneImpWithValidStoredRequestAndAnotherWithMissedId() { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder.imp(asList( + givenImp(impBuilder -> impBuilder.ext( + mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of(null)).build(), + null)))), + givenImp(impBuilder -> impBuilder.ext( + mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("123")).build(), + null))))))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.failed()).isTrue(); + assertThat(bidRequestFuture.cause()) + .isInstanceOf(InvalidRequestException.class) + .hasMessage("Stored request processing failed: Id is not found in storedRequest"); + } + + @Test + public void shouldReturnFailedFutureIfImpsStoredRequestIdHasIncorrectType() { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder.imp(singletonList(givenImp( + impBuilder -> impBuilder.ext(mapper.createObjectNode() + .set("prebid", mapper.createObjectNode() + .set("storedrequest", mapper.createObjectNode() + .set("id", mapper.createObjectNode().putArray("id") + .add("id"))))).id("imp-test"))))); + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // when + assertThat(bidRequestFuture.failed()).isTrue(); + assertThat(bidRequestFuture.cause()) + .isInstanceOf(InvalidRequestException.class) + .hasMessageStartingWith("Stored request processing failed: " + + "Incorrect Imp extension format for Imp with id imp-test: Cannot deserialize"); + } + + @Test + public void shouldReturnFailedFutureIfStoredRequestFetcherReturnsFailedFuture() { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder.imp(singletonList(givenImp( + impBuilder -> impBuilder.ext( + mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("123")).build(), + null))))))); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.failedFuture(new Exception("Error during file fetching"))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.failed()).isTrue(); + assertThat(bidRequestFuture.cause()) + .isInstanceOf(InvalidRequestException.class) + .hasMessage("Stored request processing failed: Error during file fetching"); + } + + @Test + public void shouldReturnFailedFutureWhenStoredImpJsonIsNotValid() { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder.imp(singletonList(givenImp( + impBuilder -> impBuilder.ext( + mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("123")).build(), + null))))))); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(emptyMap(), singletonMap("123", "{{}"), emptyList()))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.failed()).isTrue(); + assertThat(bidRequestFuture.cause()) + .isInstanceOf(InvalidRequestException.class) + .hasMessage("Stored request processing failed: Can't parse Json for stored request with id 123"); + } + + @Test + public void shouldReturnFailedFutureWhenMergedResultCantBeConvertedToImp() throws IOException { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder.imp(singletonList(givenImp( + impBuilder -> impBuilder.ext( + mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("123")).build(), + null))))))); + + final Map storedImpFetchResult = singletonMap("123", mapper.writeValueAsString( + mapper.createObjectNode().put("secure", "stringValue"))); + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture(StoredDataResult.of(emptyMap(), storedImpFetchResult, emptyList()))); + + // when + final Future bidRequestFuture = + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.failed()).isTrue(); + assertThat(bidRequestFuture.cause()) + .isInstanceOf(InvalidRequestException.class) + .hasMessageStartingWith("Stored request processing failed: " + + "Can't convert merging result for id 123: Cannot deserialize"); + } + + @Test + public void shouldUseTimeoutFromRequest() { + // given + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.failedFuture((String) null)); + + // when + storedRequestProcessor.processAuctionRequest(null, givenBidRequest(builder -> builder + .ext(ExtRequest.of(ExtRequestPrebid.builder().storedrequest(ExtStoredRequest.of("bidRequest")).build())) + .tmax(1000L))); + + // then + verify(timeoutFactory).create(eq(1000L)); + } + + @Test + public void shouldUseDefaultTimeoutIfMissingInRequest() { + // given + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.failedFuture((String) null)); + + // when + storedRequestProcessor.processAuctionRequest(null, givenBidRequest(builder -> builder + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .storedrequest(ExtStoredRequest.of("bidRequest")) + .build())))); + + // then + verify(timeoutFactory).create(eq(500L)); + } + + @Test + public void processStoredRequestsShouldNotUpdateMetricsIfApplicationSettingsFailed() { + // given + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.failedFuture("failed")); + + // when + storedRequestProcessor.processAuctionRequest(null, givenBidRequest(builder -> builder + .ext(ExtRequest.of( + ExtRequestPrebid.builder().storedrequest(ExtStoredRequest.of("bidRequest")).build())))); + + // then + verifyNoInteractions(metrics); + } + + @Test + public void processAmpRequestShouldNotUpdateMetricsIfApplicationSettingsFailed() { + // given + given(applicationSettings.getAmpStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.failedFuture("failed")); + + // when + storedRequestProcessor.processAmpRequest(null, "123", givenBidRequest(identity())); + + // then + verifyNoInteractions(metrics); + } + + @Test + public void processStoredRequestsShouldUpdateRequestAndImpMetricsAsExpected() { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .storedrequest(ExtStoredRequest.of("123")) + .build())) + .imp(asList(givenImp(impBuilder -> impBuilder.ext(mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest( + ExtStoredRequest.of("321")).build(), null)))), + givenImp(impBuilder -> impBuilder.ext(mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest( + ExtStoredRequest.of("not_found")).build(), null))))))); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture(StoredDataResult.of( + singletonMap("123", "stored_request"), singletonMap("321", "stored_imp"), emptyList()))); + + // when + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + verify(metrics).updateStoredRequestMetric(eq(true)); + verify(metrics).updateStoredImpsMetric(eq(true)); + verify(metrics).updateStoredImpsMetric(eq(false)); + } + + @Test + public void processStoredRequestsShouldUpdateRequestMissingMetrics() { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .storedrequest(ExtStoredRequest.of("123")) + .build()))); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture(StoredDataResult.of(emptyMap(), emptyMap(), emptyList()))); + + // when + storedRequestProcessor.processAuctionRequest(null, bidRequest); + + // then + verify(metrics).updateStoredRequestMetric(eq(false)); + } + + @Test + public void processAmpRequestShouldUpdateRequestFoundMetric() { + // given + given(applicationSettings.getAmpStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(singletonMap("123", "amp"), emptyMap(), emptyList()))); + + // when + storedRequestProcessor.processAmpRequest(null, "123", givenBidRequest(identity())); + + // then + verify(metrics).updateStoredRequestMetric(true); + } + + @Test + public void processAmpRequestShouldUpdateRequestMissingMetrics() { + // given + given(applicationSettings.getAmpStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(emptyMap(), emptyMap(), emptyList()))); + + // when + storedRequestProcessor.processAmpRequest(null, "123", givenBidRequest(identity())); + + // then + verify(metrics).updateStoredRequestMetric(false); + } + + @Test + public void processStoredRequestsShouldUpdateAccountRequestRejectedByInvalidStoredRequestMetrics() { + // when + storedRequestProcessor.processAuctionRequest("accountId", givenBidRequest(request -> request.ext( + ExtRequest.of(ExtRequestPrebid.builder().storedrequest(ExtStoredRequest.of(null)).build())))); + + // then + verify(metrics).updateAccountRequestRejectedByInvalidStoredRequestMetrics("accountId"); + } + + @Test + public void processStoredRequestsShouldUpdateAccountRequestRejectedByInvalidStoredImpMetrics() { + // when + storedRequestProcessor.processAuctionRequest("accountId", givenBidRequest(request -> request.imp( + singletonList( + Imp.builder() + .ext(mapper.valueToTree(ExtImp.of( + ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of(null)).build(), + null))) + .build())))); + + // then + verify(metrics).updateAccountRequestRejectedByInvalidStoredImpMetrics("accountId"); + } + + @Test + public void processAmpRequestsShouldUpdateAccountRequestRejectedByInvalidStoredRequestMetrics() { + // given + given(applicationSettings.getAmpStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(emptyMap(), emptyMap(), singletonList("Error.")))); + + // when + storedRequestProcessor.processAmpRequest("accountId", "123", givenBidRequest(request -> request.ext( + ExtRequest.of(ExtRequestPrebid.builder().storedrequest(ExtStoredRequest.of(null)).build())))); + + // then + verify(metrics).updateAccountRequestRejectedByInvalidStoredRequestMetrics("accountId"); + } + + @Test + public void videoStoredDataResultShouldUpdateAccountRequestRejectedByInvalidStoredImpMetrics() { + // when + storedRequestProcessor.videoStoredDataResult( + "accountId", + singletonList( + Imp.builder() + .ext(mapper.valueToTree(ExtImp.of( + ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of(null)).build(), + null))) + .build()), + emptyList(), + null); + + // then + verify(metrics).updateAccountRequestRejectedByInvalidStoredImpMetrics("accountId"); + } + + @Test + public void impToStoredVideoJsonShouldReturnExpectedVideoStoredDataResult() throws JsonProcessingException { + // given + final Imp imp1 = givenImp(impBuilder -> impBuilder.id("id1").ext( + mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("st1")).build(), null)))); + final Imp imp2 = givenImp(impBuilder -> impBuilder.id("id2").ext( + mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("st2")).build(), null)))); + + final Video storedVideo = Video.builder().maxduration(100).h(2).w(2).build(); + final Imp storedImp1 = Imp.builder().video(storedVideo).build(); + final Imp storedImp2 = Imp.builder().video(storedVideo).build(); + + final Map storedIdToJson = new HashMap<>(); + storedIdToJson.put("st1", mapper.writeValueAsString(storedImp1)); + storedIdToJson.put("st2", mapper.writeValueAsString(storedImp2)); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture(StoredDataResult.of(emptyMap(), storedIdToJson, emptyList()))); + + // when + final Future result = storedRequestProcessor.videoStoredDataResult(null, + Arrays.asList(imp1, imp2), emptyList(), null); + + // then + verify(applicationSettings).getStoredData(any(), anySet(), eq(new HashSet<>(Arrays.asList("st1", "st2"))), + any()); + + assertThat(result.result().getImpIdToStoredVideo()) + .containsOnly(entry("id2", storedVideo), entry("id1", storedVideo)); + assertThat(result.result().getErrors()).isEmpty(); + } + + @Test + public void impToStoredVideoJsonShouldReturnExpectedVideoStoredDataResultErrors() throws JsonProcessingException { + // given + final Imp imp1 = givenImp(impBuilder -> impBuilder.id("id1").ext( + mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("st1")).build(), null)))); + final Imp imp2 = givenImp(impBuilder -> impBuilder.id("id2").ext( + mapper.valueToTree( + ExtImp.of(ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("st2")).build(), null)))); + + final Imp storedImp1 = Imp.builder().build(); + + final Map storedIdToJson = new HashMap<>(); + storedIdToJson.put("st1", mapper.writeValueAsString(storedImp1)); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture(StoredDataResult.of(emptyMap(), storedIdToJson, emptyList()))); + + // when + final Future result = storedRequestProcessor.videoStoredDataResult(null, + Arrays.asList(imp1, imp2), new ArrayList<>(), null); + + // then + verify(applicationSettings).getStoredData(any(), anySet(), eq(new HashSet<>(Arrays.asList("st1", "st2"))), + any()); + + assertThat(result.result().getErrors()).containsOnly( + "No stored Imp for stored id st2", + "No stored video found for Imp with id id1"); + } + + @Test + public void shouldProperlyCompareBigDecimalsAsKeysInHashMap() throws IOException { + // given + given(fileSystem.readFileBlocking(anyString())) + .willReturn(Buffer.buffer("{}")); + + storedRequestProcessor = new StoredRequestProcessor( + DEFAULT_TIMEOUT, + "path/to/default/request.json", + false, + fileSystem, + applicationSettings, + idGenerator, + metrics, + timeoutFactory, + jacksonMapper, + new JsonMerger(jacksonMapper)); + + final Video storedImpVideo = Video.builder().mimes(singletonList("video/mp4")).w(640).h(480).build(); + final String storedImpJson = mapper.writeValueAsString(givenImp(builder -> builder.video(storedImpVideo))); + + given(applicationSettings.getStoredData(any(), anySet(), anySet(), any())) + .willReturn(Future.succeededFuture( + StoredDataResult.of(emptyMap(), singletonMap("storedImpId", storedImpJson), emptyList()))); + + final BidRequest bidRequest = givenBidRequest(bidRequestBuilder -> bidRequestBuilder + .imp(singletonList(givenImp(impBuilder -> impBuilder + .bidfloor(BigDecimal.TEN) + .ext(mapper.valueToTree(ExtImp.of( + ExtImpPrebid.builder().storedrequest(ExtStoredRequest.of("storedImpId")).build(), + null))))))); + + // when + final Future bidRequestFuture = storedRequestProcessor + .processAuctionRequest(null, bidRequest); + + // then + assertThat(bidRequestFuture.succeeded()).isTrue(); + assertThat(bidRequestFuture.result()) + .extracting(AuctionStoredResult::bidRequest) + .extracting(BidRequest::getImp) + .asInstanceOf(InstanceOfAssertFactories.list(Imp.class)) + .extracting(Imp::getVideo) + .containsExactly(storedImpVideo); + } + + private static BidRequest givenBidRequest(UnaryOperator bidRequestCustomizer) { + return bidRequestCustomizer.apply(BidRequest.builder()).build(); + } + + private static Imp givenImp(UnaryOperator impCustomizer) { + return impCustomizer.apply(Imp.builder()).build(); + } +} diff --git a/src/test/java/org/prebid/server/auction/StoredResponseProcessorTest.java b/src/test/java/org/prebid/server/auction/StoredResponseProcessorTest.java new file mode 100644 index 00000000000..dc57b3c1f11 --- /dev/null +++ b/src/test/java/org/prebid/server/auction/StoredResponseProcessorTest.java @@ -0,0 +1,945 @@ +package org.prebid.server.auction; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.iab.openrtb.request.Banner; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.response.Bid; +import com.iab.openrtb.response.SeatBid; +import io.vertx.core.Future; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.prebid.server.VertxTest; +import org.prebid.server.auction.model.AuctionParticipation; +import org.prebid.server.auction.model.BidRejectionTracker; +import org.prebid.server.auction.model.BidderRequest; +import org.prebid.server.auction.model.BidderResponse; +import org.prebid.server.auction.model.StoredResponseResult; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderSeatBid; +import org.prebid.server.exception.InvalidRequestException; +import org.prebid.server.exception.PreBidException; +import org.prebid.server.execution.timeout.Timeout; +import org.prebid.server.execution.timeout.TimeoutFactory; +import org.prebid.server.proto.openrtb.ext.request.ExtImp; +import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtStoredAuctionResponse; +import org.prebid.server.proto.openrtb.ext.request.ExtStoredBidResponse; +import org.prebid.server.proto.openrtb.ext.response.BidType; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; +import org.prebid.server.settings.ApplicationSettings; +import org.prebid.server.settings.model.StoredResponseDataResult; + +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singleton; +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; + +@ExtendWith(MockitoExtension.class) +public class StoredResponseProcessorTest extends VertxTest { + + @Mock + private ApplicationSettings applicationSettings; + + @Mock + private BidRejectionTracker rubiconBidRejectionTracker; + + @Mock + private BidRejectionTracker appnexusBidRejectionTracker; + + private StoredResponseProcessor target; + + private Timeout timeout; + + @BeforeEach + public void setUp() { + final TimeoutFactory timeoutFactory = new TimeoutFactory(Clock.fixed(Instant.now(), ZoneId.systemDefault())); + timeout = timeoutFactory.create(500L); + + target = new StoredResponseProcessor(applicationSettings, jacksonMapper); + } + + @Test + public void getStoredResponseResultShouldReturnSeatBidsForAuctionResponseId() throws JsonProcessingException { + // given + final List imps = singletonList(givenImp("impId", ExtStoredAuctionResponse.of("1", null, null), null)); + + given(applicationSettings.getStoredResponses(any(), any())) + .willReturn(Future.succeededFuture(StoredResponseDataResult.of(singletonMap("1", + mapper.writeValueAsString(singletonList(SeatBid.builder().seat("rubicon") + .bid(singletonList(Bid.builder().id("id").build())).build()))), + emptyList()))); + + // when + final Future result = target.getStoredResponseResult(imps, timeout); + + // then + assertThat(result.result()).isEqualTo(StoredResponseResult.of( + emptyList(), + singletonList(SeatBid.builder() + .seat("rubicon") + .bid(singletonList(Bid.builder().id("id").impid("impId").build())) + .build()), + emptyMap())); + } + + @Test + public void getStoredResponseResultShouldNotChangeImpsAndReturnSeatBidsWhenThereAreNoStoredIds() { + // given + final Imp imp = Imp.builder() + .ext(mapper.valueToTree(ExtImp.of( + ExtImpPrebid.builder().bidder(mapper.createObjectNode().put("rubicon", 1)).build(), + null))) + .build(); + // when + final Future result = + target.getStoredResponseResult(singletonList(imp), timeout); + + // then + assertThat(result.result()).isEqualTo(StoredResponseResult.of( + singletonList(imp), + emptyList(), + emptyMap())); + verifyNoInteractions(applicationSettings); + } + + @Test + public void getStoredResponseResultShouldAddImpToRequiredRequestWhenItsStoredAuctionResponseIsNull() { + // given + final List imps = singletonList(givenImp("impId1", null, null)); + + // when + final Future result = + target.getStoredResponseResult(imps, timeout); + + // then + assertThat(result.result()).isEqualTo(StoredResponseResult.of( + singletonList(Imp.builder() + .id("impId1") + .ext(mapper.valueToTree(ExtImp.of( + ExtImpPrebid.builder().storedAuctionResponse(null).build(), + null))) + .build()), + emptyList(), + emptyMap())); + verifyNoInteractions(applicationSettings); + } + + @Test + public void getStoredResponseResultShouldReturnFailedFutureWhenErrorHappenedDuringRetrievingStoredResponse() { + // given + final List imps = singletonList(givenImp("impId", ExtStoredAuctionResponse.of("1", null, null), null)); + + given(applicationSettings.getStoredResponses(any(), any())) + .willReturn(Future.failedFuture(new PreBidException("Failed."))); + + // when + final Future result = + target.getStoredResponseResult(imps, timeout); + + // then + assertThat(result.failed()).isTrue(); + assertThat(result.cause()) + .isInstanceOf(InvalidRequestException.class) + .hasMessage("Stored response fetching failed with reason: Failed."); + } + + @Test + public void getStoredResponseResultShouldReturnResultForBidStoredResponseId() { + // given + final Imp imp = givenImp("impId1", null, asList( + ExtStoredBidResponse.of("rubicon", "storedBidResponseId1"), + ExtStoredBidResponse.of("appnexus", "storedBidResponseId2"))); + + given(applicationSettings.getStoredResponses(any(), any())).willReturn( + Future.succeededFuture(StoredResponseDataResult.of( + doubleMap("storedBidResponseId1", "storedBidResponse1", + "storedBidResponseId2", "storedBidResponse2"), emptyList()))); + + // when + final Future result = + target.getStoredResponseResult(singletonList(imp), timeout); + + // then + assertThat(result.result()).isEqualTo(StoredResponseResult.of( + singletonList(imp), + emptyList(), + singletonMap("impId1", doubleMap("rubicon", "storedBidResponse1", "appnexus", "storedBidResponse2")))); + } + + @Test + public void getStoredResponseResultShouldReturnResultForBidAndAuctionStoredResponseId() + throws JsonProcessingException { + // given + final Imp imp1 = givenImp( + "impId1", + ExtStoredAuctionResponse.of("storedAuctionResponseId", Collections.emptyList(), null), + null); + final Imp imp2 = givenImp( + "impId2", + null, + singletonList(ExtStoredBidResponse.of("rubicon", "storedBidResponseId"))); + final List imps = asList(imp1, imp2); + + final Map storedResponse = new HashMap<>(); + storedResponse.put("storedAuctionResponseId", mapper.writeValueAsString(singletonList( + SeatBid.builder().seat("appnexus").bid(singletonList(Bid.builder().id("id1").build())).build()))); + storedResponse.put("storedBidResponseId", "storedBidResponse"); + + given(applicationSettings.getStoredResponses(any(), any())).willReturn( + Future.succeededFuture(StoredResponseDataResult.of(storedResponse, emptyList()))); + + // when + final Future result = + target.getStoredResponseResult(imps, timeout); + + // then + assertThat(result.result()).isEqualTo(StoredResponseResult.of( + singletonList(imp2), + singletonList( + SeatBid.builder() + .seat("appnexus") + .bid(singletonList(Bid.builder().id("id1").impid("impId1").build())) + .build()), + singletonMap("impId2", singletonMap("rubicon", "storedBidResponse")))); + } + + @Test + public void getStoredResponseResultShouldThrowInvalidRequestExceptionWhenStoredAuctionResponseWasNotFound() { + // given + final Imp imp1 = givenImp("impId1", ExtStoredAuctionResponse.of("storedAuctionResponseId", null, null), null); + given(applicationSettings.getStoredResponses(any(), any())).willReturn( + Future.succeededFuture(StoredResponseDataResult.of(emptyMap(), emptyList()))); + + // when + final Future result = + target.getStoredResponseResult(singletonList(imp1), timeout); + + // then + assertThat(result.failed()).isTrue(); + assertThat(result.cause()).isInstanceOf(InvalidRequestException.class) + .hasMessage("Failed to fetch stored auction response for impId = impId1 and storedAuctionResponse id " + + "= storedAuctionResponseId."); + } + + @Test + public void getStoredResponseResultShouldMergeStoredSeatBidsForTheSameBidder() throws JsonProcessingException { + // given + final List imps = asList( + givenImp("impId1", ExtStoredAuctionResponse.of("storedAuctionResponse1", null, null), null), + givenImp("impId2", ExtStoredAuctionResponse.of("storedAuctionResponse2", null, null), null)); + + final Map storedResponse = new HashMap<>(); + storedResponse.put("storedAuctionResponse1", mapper.writeValueAsString(asList( + SeatBid.builder().seat("appnexus").bid(singletonList(Bid.builder().id("id1").build())).build(), + SeatBid.builder().seat("rubicon").bid(singletonList(Bid.builder().id("id3").build())).build()))); + storedResponse.put("storedAuctionResponse2", mapper.writeValueAsString(singletonList( + SeatBid.builder().seat("rubicon").bid(singletonList(Bid.builder().id("id2").build())).build()))); + + given(applicationSettings.getStoredResponses(any(), any())).willReturn( + Future.succeededFuture(StoredResponseDataResult.of(storedResponse, emptyList()))); + + // when + final Future result = + target.getStoredResponseResult(imps, timeout); + + // then + assertThat(result.result()).isEqualTo(StoredResponseResult.of( + emptyList(), + asList( + SeatBid.builder() + .seat("appnexus") + .bid(singletonList(Bid.builder().id("id1").impid("impId1").build())) + .build(), + SeatBid.builder() + .seat("rubicon") + .bid(asList( + Bid.builder().id("id3").impid("impId1").build(), + Bid.builder().id("id2").impid("impId2").build())) + .build()), + emptyMap())); + } + + @Test + public void getStoredResponseResultShouldUseStoredSeatBidsFromRequest() throws JsonProcessingException { + // given + final List imps = asList( + givenImp( + "impId1", + ExtStoredAuctionResponse.of( + "storedAuctionResponse1", + null, + SeatBid.builder() + .seat("rubicon") + .bid(singletonList(Bid.builder().id("id4").build())) + .build()), + null), + givenImp("impId2", ExtStoredAuctionResponse.of("storedAuctionResponse2", null, null), null), + givenImp( + "impId3", + ExtStoredAuctionResponse.of( + null, + null, + SeatBid.builder() + .seat("appnexus") + .bid(singletonList(Bid.builder().id("id5").build())) + .build()), + null)); + + final Map storedResponse = new HashMap<>(); + storedResponse.put("storedAuctionResponse1", mapper.writeValueAsString(asList( + SeatBid.builder().seat("appnexus").bid(singletonList(Bid.builder().id("id1").build())).build(), + SeatBid.builder().seat("rubicon").bid(singletonList(Bid.builder().id("id3").build())).build()))); + storedResponse.put("storedAuctionResponse2", mapper.writeValueAsString(singletonList( + SeatBid.builder().seat("rubicon").bid(singletonList(Bid.builder().id("id2").build())).build()))); + + given(applicationSettings.getStoredResponses(any(), any())).willReturn( + Future.succeededFuture(StoredResponseDataResult.of(storedResponse, emptyList()))); + + // when + final Future result = + target.getStoredResponseResult(imps, timeout); + + // then + assertThat(result.result()).isEqualTo(StoredResponseResult.of( + emptyList(), + asList( + SeatBid.builder() + .seat("appnexus") + .bid(singletonList(Bid.builder().id("id5").impid("impId3").build())) + .build(), + SeatBid.builder() + .seat("rubicon") + .bid(asList( + Bid.builder().id("id4").impid("impId1").build(), + Bid.builder().id("id2").impid("impId2").build())) + .build()), + emptyMap())); + } + + @Test + public void getStoredResponseResultShouldThrowInvalidExceptionWhenImpExtIsNotValid() { + // given + final List imps = singletonList(Imp.builder() + .id("impId") + .ext(mapper.createObjectNode().put("prebid", 5)) + .build()); + + // when and then + assertThatThrownBy(() -> target.getStoredResponseResult(imps, timeout)) + .isInstanceOf(InvalidRequestException.class) + .hasMessageStartingWith("Error decoding bidRequest.imp.ext for impId = impId :"); + } + + @Test + public void getStoredResponseResultShouldReturnFailedFutureWhenSeatIsEmptyInStoredSeatBid() + throws JsonProcessingException { + + // given + final List imps = singletonList(givenImp("impId", ExtStoredAuctionResponse.of("1", null, null), null)); + + given(applicationSettings.getStoredResponses(any(), any())) + .willReturn(Future.succeededFuture(StoredResponseDataResult.of( + singletonMap( + "1", + mapper.writeValueAsString(singletonList(SeatBid.builder() + .bid(singletonList(Bid.builder().id("id").build())) + .build()))), + emptyList()))); + + // when + final Future result = + target.getStoredResponseResult(imps, timeout); + + // then + assertThat(result.failed()).isTrue(); + assertThat(result.cause()) + .hasMessage("Seat can't be empty in stored response seatBid"); + } + + @Test + public void getStoredResponseResultShouldReturnFailedFutureWhenBidsAreEmptyInStoredSeatBid() + throws JsonProcessingException { + + // given + final List imps = singletonList( + givenImp("impId", ExtStoredAuctionResponse.of("1", null, null), null)); + + given(applicationSettings.getStoredResponses(any(), any())) + .willReturn(Future.succeededFuture(StoredResponseDataResult.of( + singletonMap( + "1", + mapper.writeValueAsString(singletonList(SeatBid.builder() + .seat("seat") + .build()))), + emptyList()))); + + // when + final Future result = + target.getStoredResponseResult(imps, timeout); + + // then + assertThat(result.failed()).isTrue(); + assertThat(result.cause()) + .hasMessage("There must be at least one bid in stored response seatBid"); + } + + @Test + public void getStoredResponseResultShouldReturnFailedFutureSeatBidsCannotBeParsed() { + // given + final List imps = singletonList(givenImp("impId", ExtStoredAuctionResponse.of("1", null, null), null)); + + given(applicationSettings.getStoredResponses(any(), any())).willReturn(Future.succeededFuture( + StoredResponseDataResult.of(singletonMap("1", "{invalid"), emptyList()))); + + // when + final Future result = + target.getStoredResponseResult(imps, timeout); + + // then + assertThat(result.failed()).isTrue(); + assertThat(result.cause()) + .hasMessage("Can't parse Json for stored response with id 1"); + } + + @Test + public void updateStoredBidResponseShouldTolerateMissingBidImpId() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().id("imp1").build())) + .build(); + final BidderRequest bidderRequest = BidderRequest.builder() + .bidder("rubicon") + .storedResponse("storedresponse") + .bidRequest(bidRequest) + .build(); + + final BidderResponse bidderResponse = BidderResponse.of( + "rubicon", + BidderSeatBid.of( + singletonList(BidderBid.of(Bid.builder().id("bid1").build(), BidType.banner, "USD"))), + 100); + + final AuctionParticipation requestAuctionParticipation = AuctionParticipation.builder() + .bidder("rubicon") + .bidderRequest(bidderRequest) + .bidderResponse(bidderResponse) + .build(); + + // when + final List result = target + .updateStoredBidResponse(singletonList(requestAuctionParticipation)); + + // then + assertThat(result).containsExactly(requestAuctionParticipation); + } + + @Test + public void updateStoredBidResponseShouldNotModifyParticipationWithMoreThanOneImp() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(List.of(Imp.builder().build(), Imp.builder().build())) + .build(); + final BidderRequest bidderRequest = BidderRequest.builder() + .bidder("rubicon") + .storedResponse("storedresponse") + .bidRequest(bidRequest) + .build(); + + final BidderResponse bidderResponse = BidderResponse.of( + "rubicon", + BidderSeatBid.of( + singletonList(BidderBid.of(Bid.builder().id("bid1").build(), BidType.banner, "USD"))), + 100); + + final AuctionParticipation requestAuctionParticipation = AuctionParticipation.builder() + .bidder("rubicon") + .bidderRequest(bidderRequest) + .bidderResponse(bidderResponse) + .build(); + + // when + final List result = target + .updateStoredBidResponse(singletonList(requestAuctionParticipation)); + + // then + assertThat(result).containsExactly(requestAuctionParticipation); + } + + @Test + public void updateStoredBidResponseShouldReplaceAllBidImpIdMacrosForStoredResponseParticipation() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().id("impId").build())) + .build(); + final BidderRequest bidderRequest = BidderRequest.builder() + .bidder("rubicon") + .storedResponse("storedresponse") + .bidRequest(bidRequest) + .build(); + + final List bids = List.of( + BidderBid.of(Bid.builder().impid("##PBSIMPID##").build(), BidType.banner, "USD"), + BidderBid.of(Bid.builder().impid("##PBSIMPID##").build(), BidType.video, "USD")); + final BidderResponse bidderResponse = BidderResponse.of( + "rubicon", BidderSeatBid.of(bids), 100); + + final AuctionParticipation requestAuctionParticipation = AuctionParticipation.builder() + .bidder("rubicon") + .bidderRequest(bidderRequest) + .bidderResponse(bidderResponse) + .build(); + + // when + final List result = target + .updateStoredBidResponse(singletonList(requestAuctionParticipation)); + + // then + final List expectedBids = List.of( + BidderBid.of(Bid.builder().impid("impId").build(), BidType.banner, "USD"), + BidderBid.of(Bid.builder().impid("impId").build(), BidType.video, "USD")); + final BidderResponse expectedBidderResponse = BidderResponse.of( + "rubicon", BidderSeatBid.of(expectedBids), 100); + + assertThat(result).containsExactly(requestAuctionParticipation.with(expectedBidderResponse)); + } + + @Test + public void mergeWithBidderResponsesShouldReturnMergedStoredSeatWithResponseWithoutBlocked() { + // given + final BidderResponse bidderResponse = BidderResponse.of( + "rubicon", + BidderSeatBid.of(singletonList(BidderBid.of( + Bid.builder().id("bid1").build(), BidType.banner, "rubicon", "USD"))), + 100); + final AuctionParticipation requestAuctionParticipation = AuctionParticipation.builder() + .bidder("rubicon") + .bidderResponse(bidderResponse) + .build(); + final AuctionParticipation blockedRequestAuctionParticipation = AuctionParticipation.builder() + .bidder("appnexus") + .requestBlocked(true) + .build(); + final List auctionParticipations = Arrays.asList(requestAuctionParticipation, + blockedRequestAuctionParticipation); + + final List seatBid = singletonList(SeatBid.builder() + .seat("rubicon") + .bid(singletonList(Bid.builder().id("bid2").impid("storedImp").build())) + .build()); + + final List imps = singletonList(Imp.builder().id("storedImp").banner(Banner.builder().build()).build()); + + final Map bidRejectionTrackers = Map.of( + "rubicon", rubiconBidRejectionTracker, + "appnexus", appnexusBidRejectionTracker); + + // when + final List result = target.mergeWithBidderResponses( + auctionParticipations, seatBid, imps, bidRejectionTrackers); + + // then + final List expectedBids = asList( + BidderBid.of( + Bid.builder() + .id("bid2") + .impid("storedImp") + .build(), + BidType.banner, + "rubicon", + "USD"), + BidderBid.of( + Bid.builder() + .id("bid1") + .build(), + BidType.banner, + "rubicon", + "USD")); + + verifyNoInteractions(appnexusBidRejectionTracker); + verify(rubiconBidRejectionTracker).restoreFromRejection(expectedBids); + + assertThat(result) + .extracting(AuctionParticipation::getBidderResponse) + .containsOnly(BidderResponse.of("rubicon", BidderSeatBid.of(expectedBids), 100), null); + } + + @Test + public void mergeWithBidderResponsesShouldMergeBidderResponsesWithoutCorrespondingStoredSeatBid() { + // given + final List givenRubiconBids = singletonList(BidderBid.of( + Bid.builder().id("bid1").build(), BidType.banner, "USD")); + final BidderResponse bidderResponse = BidderResponse.of("rubicon", BidderSeatBid.of(givenRubiconBids), 100); + final AuctionParticipation requestAuctionParticipation = AuctionParticipation.builder() + .bidder("rubicon") + .bidderResponse(bidderResponse) + .build(); + final List auctionParticipations = singletonList(requestAuctionParticipation); + + final List seatBid = singletonList(SeatBid.builder() + .seat("appnexus") + .bid(singletonList(Bid.builder().id("bid2").impid("storedImp").build())) + .build()); + + final List imps = singletonList(Imp.builder().id("storedImp").banner(Banner.builder().build()).build()); + + final Map bidRejectionTrackers = Map.of( + "rubicon", rubiconBidRejectionTracker, + "appnexus", appnexusBidRejectionTracker); + + // when + final List result = target.mergeWithBidderResponses( + auctionParticipations, seatBid, imps, bidRejectionTrackers); + + // then + final List expectedAppnexusBids = singletonList( + BidderBid.of(Bid.builder().id("bid2").impid("storedImp").build(), BidType.banner, "appnexus", "USD")); + + verify(rubiconBidRejectionTracker).restoreFromRejection(givenRubiconBids); + verify(appnexusBidRejectionTracker).restoreFromRejection(expectedAppnexusBids); + + final BidderResponse secondExpectedBidResponse = BidderResponse.of( + "appnexus", + BidderSeatBid.of(expectedAppnexusBids), + 0); + assertThat(result) + .extracting(AuctionParticipation::getBidderResponse) + .contains(bidderResponse, secondExpectedBidResponse); + } + + @Test + public void mergeWithBidderResponsesShouldMergeStoredSeatBidsWithoutBidderResponses() { + // given + final List seatBid = singletonList(SeatBid.builder() + .seat("rubicon") + .bid(singletonList(Bid.builder().id("bid2").impid("storedImp").build())) + .build()); + + final List imps = singletonList(Imp.builder().id("storedImp").banner(Banner.builder().build()).build()); + + final Map bidRejectionTrackers = Map.of( + "rubicon", rubiconBidRejectionTracker, + "appnexus", rubiconBidRejectionTracker); + + // when + final List result = + target.mergeWithBidderResponses(emptyList(), seatBid, imps, bidRejectionTrackers); + + // then + final List expectedBids = singletonList(BidderBid.of( + Bid.builder().id("bid2").impid("storedImp").build(), + BidType.banner, + "rubicon", + "USD")); + + verify(rubiconBidRejectionTracker).restoreFromRejection(expectedBids); + verifyNoInteractions(appnexusBidRejectionTracker); + + assertThat(result) + .extracting(AuctionParticipation::getBidderResponse) + .contains(BidderResponse.of("rubicon", BidderSeatBid.of(expectedBids), 0)); + } + + @Test + public void mergeWithBidderResponsesShouldResolveCurrencyFromBidderResponse() { + // given + final BidderResponse bidderResponse = BidderResponse.of( + "rubicon", + BidderSeatBid.of( + singletonList(BidderBid.of( + Bid.builder().id("bid1").build(), BidType.banner, "rubicon", "EUR"))), + 100); + final AuctionParticipation requestAuctionParticipation = AuctionParticipation.builder() + .bidder("rubicon") + .bidderResponse(bidderResponse) + .build(); + final List auctionParticipations = singletonList(requestAuctionParticipation); + + final List seatBid = singletonList(SeatBid.builder() + .seat("rubicon") + .bid(singletonList(Bid.builder().id("bid2").impid("storedImp").build())) + .build()); + + final List imps = singletonList(Imp.builder().id("storedImp").banner(Banner.builder().build()).build()); + + final Map bidRejectionTrackers = Map.of( + "rubicon", rubiconBidRejectionTracker, + "appnexus", rubiconBidRejectionTracker); + + // when + final List result = target.mergeWithBidderResponses( + auctionParticipations, seatBid, imps, bidRejectionTrackers); + + // then + final List expectedBids = asList( + BidderBid.of( + Bid.builder().id("bid2").impid("storedImp").build(), + BidType.banner, + "rubicon", + "EUR"), + BidderBid.of( + Bid.builder().id("bid1").build(), + BidType.banner, + "rubicon", + "EUR")); + + verify(rubiconBidRejectionTracker).restoreFromRejection(expectedBids); + verifyNoInteractions(appnexusBidRejectionTracker); + + assertThat(result) + .extracting(AuctionParticipation::getBidderResponse) + .contains(BidderResponse.of("rubicon", BidderSeatBid.of(expectedBids), 100)); + } + + @Test + public void mergeWithBidderResponsesShouldResolveBidTypeFromStoredBidExt() { + // given + final BidderResponse bidderResponse = BidderResponse.of( + "rubicon", + BidderSeatBid.of( + singletonList(BidderBid.of( + Bid.builder().id("bid1").build(), BidType.banner, "rubicon", "USD"))), + 100); + final AuctionParticipation requestAuctionParticipation = AuctionParticipation.builder() + .bidder("rubicon") + .bidderResponse(bidderResponse) + .build(); + final List auctionParticipations = singletonList(requestAuctionParticipation); + + final ExtBidPrebid extBidPrebid = ExtBidPrebid.builder().type(BidType.video).build(); + + final List seatBid = singletonList(SeatBid.builder() + .seat("rubicon") + .bid(singletonList(Bid.builder() + .id("bid2") + .impid("storedImp") + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(extBidPrebid))) + .build())) + .build()); + + final List imps = singletonList(Imp.builder().id("storedImp").banner(Banner.builder().build()).build()); + + final Map bidRejectionTrackers = Map.of( + "rubicon", rubiconBidRejectionTracker, + "appnexus", rubiconBidRejectionTracker); + + // when + final List result = target.mergeWithBidderResponses( + auctionParticipations, seatBid, imps, bidRejectionTrackers); + + // then + final List expectedBids = asList( + BidderBid.of( + Bid.builder() + .id("bid2") + .impid("storedImp") + .ext(mapper.createObjectNode() + .set("prebid", mapper.valueToTree(extBidPrebid))).build(), + BidType.video, "rubicon", "USD"), + BidderBid.of(Bid.builder().id("bid1").build(), BidType.banner, "rubicon", "USD")); + + verify(rubiconBidRejectionTracker).restoreFromRejection(expectedBids); + verifyNoInteractions(appnexusBidRejectionTracker); + + assertThat(result) + .extracting(AuctionParticipation::getBidderResponse) + .contains(BidderResponse.of("rubicon", BidderSeatBid.of(expectedBids), 100)); + } + + @Test + public void mergeWithBidderResponsesShouldThrowPrebidExceptionWhenExtBidPrebidInStoredBidIsNotValid() { + // given + final ObjectNode extBidPrebid = mapper.createObjectNode().put("type", "invalid"); + + final List seatBid = singletonList(SeatBid.builder() + .seat("rubicon") + .bid(singletonList(Bid.builder() + .id("bid2") + .impid("storedImp") + .ext(mapper.createObjectNode().set("prebid", extBidPrebid)) + .build())) + .build()); + + final List imps = singletonList(Imp.builder().id("storedImp").banner(Banner.builder().build()).build()); + + final Map bidRejectionTrackers = Map.of( + "rubicon", rubiconBidRejectionTracker, + "appnexus", rubiconBidRejectionTracker); + + // when and then + assertThatThrownBy(() -> target.mergeWithBidderResponses(emptyList(), seatBid, imps, bidRejectionTrackers)) + .isInstanceOf(PreBidException.class).hasMessage("Error decoding stored response bid.ext.prebid"); + + verifyNoInteractions(appnexusBidRejectionTracker, rubiconBidRejectionTracker); + } + + @Test + public void mergeWithBidderResponsesShouldReturnSameResponseWhenThereAreNoStoredResponses() { + // given + final List givenBids = singletonList( + BidderBid.of(Bid.builder().id("bid1").build(), BidType.banner, "USD")); + final BidderResponse bidderResponse = BidderResponse.of("rubicon", BidderSeatBid.of(givenBids), 100); + final AuctionParticipation requestAuctionParticipation = AuctionParticipation.builder() + .bidder("rubicon") + .bidderResponse(bidderResponse) + .build(); + final List auctionParticipations = singletonList(requestAuctionParticipation); + + final List imps = singletonList(Imp.builder().banner(Banner.builder().build()).build()); + + final Map bidRejectionTrackers = Map.of( + "rubicon", rubiconBidRejectionTracker, + "appnexus", rubiconBidRejectionTracker); + + // when + final List result = target.mergeWithBidderResponses( + auctionParticipations, emptyList(), imps, bidRejectionTrackers); + + // then + assertThat(result) + .extracting(AuctionParticipation::getBidderResponse) + .containsOnly(bidderResponse); + + verifyNoInteractions(appnexusBidRejectionTracker, rubiconBidRejectionTracker); + } + + @Test + public void getStoredResponseResultShouldFailWhenGettingStoredResponseFailed() { + // given + given(applicationSettings.getStoredResponses(singleton("id"), timeout)) + .willReturn(Future.failedFuture("reason")); + + // when + final Future storedResponseResult = target.getStoredResponseResult("id", timeout); + + // then + assertThat(storedResponseResult.failed()).isTrue(); + assertThat(storedResponseResult.cause()).hasMessage("Stored response fetching failed with reason: reason"); + } + + @Test + public void getStoredResponseResultShouldReturnValidSeatBidsById() throws JsonProcessingException { + // given + final Map storedResponse = new HashMap<>(); + storedResponse.put("id", mapper.writeValueAsString(singletonList( + SeatBid.builder().seat("seat").bid(singletonList(Bid.builder().id("id1").build())).build()))); + + given(applicationSettings.getStoredResponses(any(), any())).willReturn( + Future.succeededFuture(StoredResponseDataResult.of(storedResponse, emptyList()))); + + // when + final Future result = target.getStoredResponseResult("id", timeout); + + // then + assertThat(result.succeeded()).isTrue(); + assertThat(result.result()).isEqualTo(StoredResponseResult.of( + emptyList(), + singletonList(SeatBid.builder() + .seat("seat") + .bid(singletonList(Bid.builder().id("id1").build())) + .build()), + emptyMap())); + } + + @Test + public void getStoredResponseResultShouldFailWhenReturnNullableStoredResponse() { + // given + final Map storedResponse = new HashMap<>(); + storedResponse.put("id", null); + + given(applicationSettings.getStoredResponses(any(), any())).willReturn( + Future.succeededFuture(StoredResponseDataResult.of(storedResponse, emptyList()))); + + // when + final Future result = target.getStoredResponseResult("id", timeout); + + // then + assertThat(result.succeeded()).isFalse(); + assertThat(result.cause()) + .hasMessage("Failed to fetch stored auction response for storedAuctionResponse id = id."); + } + + @Test + public void getStoredResponseResultShouldFailWhenStoredResponseHasEmptySeat() + throws JsonProcessingException { + + // given + final Map storedResponse = new HashMap<>(); + storedResponse.put("id", mapper.writeValueAsString(singletonList( + SeatBid.builder().seat(null).bid(singletonList(Bid.builder().id("id1").build())).build()))); + + given(applicationSettings.getStoredResponses(any(), any())).willReturn( + Future.succeededFuture(StoredResponseDataResult.of(storedResponse, emptyList()))); + + // when + final Future result = target.getStoredResponseResult("id", timeout); + + // then + assertThat(result.succeeded()).isFalse(); + assertThat(result.cause()) + .hasMessage("Seat can't be empty in stored response seatBid"); + } + + @Test + public void getStoredResponseResultShouldFailWhenStoredResponseHasEmptyBids() + throws JsonProcessingException { + + // given + final Map storedResponse = new HashMap<>(); + storedResponse.put("id", mapper.writeValueAsString(singletonList( + SeatBid.builder().seat("seat").bid(emptyList()).build()))); + + given(applicationSettings.getStoredResponses(any(), any())).willReturn( + Future.succeededFuture(StoredResponseDataResult.of(storedResponse, emptyList()))); + + // when + final Future result = target.getStoredResponseResult("id", timeout); + + // then + assertThat(result.succeeded()).isFalse(); + assertThat(result.cause()) + .hasMessage("There must be at least one bid in stored response seatBid"); + } + + private Map doubleMap(K key1, V value1, K key2, V value2) { + final Map map = new HashMap<>(); + map.put(key1, value1); + map.put(key2, value2); + return map; + } + + private Imp givenImp(String impId, + ExtStoredAuctionResponse storedAuctionResponse, + List extStoredBidResponse) { + return Imp.builder() + .id(impId) + .ext(mapper.valueToTree(ExtImp.of( + ExtImpPrebid.builder() + .storedAuctionResponse(storedAuctionResponse) + .storedBidResponse(extStoredBidResponse) + .build(), + null))) + .build(); + } +} diff --git a/src/test/java/org/prebid/server/auction/VideoStoredRequestProcessorTest.java b/src/test/java/org/prebid/server/auction/VideoStoredRequestProcessorTest.java index abe33a80df3..3080208ee8d 100644 --- a/src/test/java/org/prebid/server/auction/VideoStoredRequestProcessorTest.java +++ b/src/test/java/org/prebid/server/auction/VideoStoredRequestProcessorTest.java @@ -141,7 +141,11 @@ public void shouldReturnMergedStoredAndDefaultRequest() { identity(), builder -> builder.pods(pods)); +<<<<<<< HEAD final StoredDataResult storedDataResult = StoredDataResult.of( +======= + final StoredDataResult storedDataResult = StoredDataResult.of( +>>>>>>> 04d9d4a13 (Initial commit) singletonMap(STORED_REQUEST_ID, jacksonMapper.encodeToString(storedVideo)), singletonMap(STORED_POD_ID, "{}"), emptyList()); @@ -245,7 +249,11 @@ public void shouldFailWhenThereAreNoStoredImpsFound() { identity(), builder -> builder.pods(asList(pod1, pod2))); +<<<<<<< HEAD final StoredDataResult storedDataResult = StoredDataResult.of(emptyMap(), emptyMap(), emptyList()); +======= + final StoredDataResult storedDataResult = StoredDataResult.of(emptyMap(), emptyMap(), emptyList()); +>>>>>>> 04d9d4a13 (Initial commit) given(applicationSettings.getVideoStoredData(any(), anySet(), anySet(), any())) .willReturn(Future.succeededFuture(storedDataResult)); @@ -291,7 +299,11 @@ public void shouldReturnCorrectAdPodDurationIfRequireExactDurationIsTrue() { .durationRangeSec(asList(30, 60, 80)) .pods(singletonList(Pod.of(123, 30, STORED_POD_ID)))); +<<<<<<< HEAD final StoredDataResult storedDataResult = StoredDataResult.of( +======= + final StoredDataResult storedDataResult = StoredDataResult.of( +>>>>>>> 04d9d4a13 (Initial commit) singletonMap(STORED_REQUEST_ID, jacksonMapper.encodeToString(storedVideo)), singletonMap(STORED_POD_ID, "{}"), emptyList()); @@ -364,7 +376,11 @@ public void shouldReturnCorrectPriceGranularityInRequest() { bidRequestVideoBuilder -> bidRequestVideoBuilder.pricegranularity(priceGranularity), builder -> builder.pods(singletonList(Pod.of(123, 20, STORED_POD_ID)))); +<<<<<<< HEAD final StoredDataResult storedDataResult = StoredDataResult.of( +======= + final StoredDataResult storedDataResult = StoredDataResult.of( +>>>>>>> 04d9d4a13 (Initial commit) singletonMap(STORED_REQUEST_ID, jacksonMapper.encodeToString(storedVideo)), singletonMap(STORED_POD_ID, "{}"), emptyList()); diff --git a/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java index 32de14a2390..051469f0eab 100644 --- a/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java @@ -30,8 +30,12 @@ import org.prebid.server.auction.GeoLocationServiceWrapper; import org.prebid.server.auction.ImplicitParametersExtractor; import org.prebid.server.auction.OrtbTypesResolver; +<<<<<<< HEAD import org.prebid.server.auction.externalortb.ProfilesProcessor; import org.prebid.server.auction.externalortb.StoredRequestProcessor; +======= +import org.prebid.server.auction.StoredRequestProcessor; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.gpp.AmpGppService; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.debug.DebugContext; @@ -73,12 +77,20 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +<<<<<<< HEAD import java.util.function.UnaryOperator; +======= +import java.util.function.Function; +>>>>>>> 04d9d4a13 (Initial commit) import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; +<<<<<<< HEAD import static java.util.function.UnaryOperator.identity; +======= +import static java.util.function.Function.identity; +>>>>>>> 04d9d4a13 (Initial commit) import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; @@ -104,8 +116,11 @@ public class AmpRequestFactoryTest extends VertxTest { @Mock(strictness = LENIENT) private StoredRequestProcessor storedRequestProcessor; @Mock(strictness = LENIENT) +<<<<<<< HEAD private ProfilesProcessor profilesProcessor; @Mock(strictness = LENIENT) +======= +>>>>>>> 04d9d4a13 (Initial commit) private BidRequestOrtbVersionConversionManager ortbVersionConversionManager; @Mock(strictness = LENIENT) private AmpGppService ampGppService; @@ -142,9 +157,12 @@ public void setUp() { given(ortbVersionConversionManager.convertToAuctionSupportedVersion(any())) .willAnswer(invocation -> invocation.getArgument(0)); +<<<<<<< HEAD given(profilesProcessor.process(any(), any())) .willAnswer(invocation -> Future.succeededFuture(invocation.getArgument(1))); +======= +>>>>>>> 04d9d4a13 (Initial commit) given(ampGppService.contextFrom(any())).willReturn(Future.succeededFuture()); given(ampGppService.updateBidRequest(any(), any())) .willAnswer(invocation -> invocation.getArgument(0)); @@ -197,7 +215,10 @@ public void setUp() { target = new AmpRequestFactory( ortb2RequestFactory, storedRequestProcessor, +<<<<<<< HEAD profilesProcessor, +======= +>>>>>>> 04d9d4a13 (Initial commit) ortbVersionConversionManager, ampGppService, ortbTypesResolver, @@ -1743,6 +1764,7 @@ public void shouldUpdateTimeout() { .isEqualTo(10000L); } +<<<<<<< HEAD @Test public void shouldUseProfilesResult() { // given @@ -1767,6 +1789,11 @@ public void shouldUseProfilesResult() { private void givenBidRequest(UnaryOperator storedBidRequestBuilderCustomizer, Imp... imps) { +======= + private void givenBidRequest( + Function storedBidRequestBuilderCustomizer, + Imp... imps) { +>>>>>>> 04d9d4a13 (Initial commit) final List impList = imps.length > 0 ? asList(imps) : null; given(storedRequestProcessor.processAmpRequest(any(), anyString(), any())) diff --git a/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java index 2e30e8d1bc4..2bc02abd3a3 100644 --- a/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java @@ -30,8 +30,12 @@ import org.prebid.server.auction.ImplicitParametersExtractor; import org.prebid.server.auction.InterstitialProcessor; import org.prebid.server.auction.OrtbTypesResolver; +<<<<<<< HEAD import org.prebid.server.auction.externalortb.ProfilesProcessor; import org.prebid.server.auction.externalortb.StoredRequestProcessor; +======= +import org.prebid.server.auction.StoredRequestProcessor; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.gpp.AuctionGppService; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.AuctionStoredResult; @@ -40,7 +44,10 @@ import org.prebid.server.auction.versionconverter.BidRequestOrtbVersionConversionManager; import org.prebid.server.bidadjustments.BidAdjustmentsEnricher; import org.prebid.server.bidadjustments.model.BidAdjustmentType; +<<<<<<< HEAD import org.prebid.server.bidadjustments.model.BidAdjustmentsRule; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.cookie.CookieDeprecationService; import org.prebid.server.exception.InvalidRequestException; import org.prebid.server.geolocation.model.GeoInfo; @@ -54,6 +61,10 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRegs; import org.prebid.server.proto.openrtb.ext.request.ExtRegsDsa; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +<<<<<<< HEAD +======= +import org.prebid.server.bidadjustments.model.BidAdjustmentsRule; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidData; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidDataEidPermissions; @@ -90,8 +101,11 @@ public class AuctionRequestFactoryTest extends VertxTest { @Mock(strictness = LENIENT) private StoredRequestProcessor storedRequestProcessor; @Mock(strictness = LENIENT) +<<<<<<< HEAD private ProfilesProcessor profilesProcessor; @Mock(strictness = LENIENT) +======= +>>>>>>> 04d9d4a13 (Initial commit) private BidRequestOrtbVersionConversionManager ortbVersionConversionManager; @Mock(strictness = LENIENT) private AuctionGppService auctionGppService; @@ -149,9 +163,12 @@ public void setUp() { .debugContext(DebugContext.of(true, true, null)) .build(); +<<<<<<< HEAD given(profilesProcessor.process(any(), any())) .willAnswer(invocation -> Future.succeededFuture(invocation.getArgument(1))); +======= +>>>>>>> 04d9d4a13 (Initial commit) given(ortbVersionConversionManager.convertToAuctionSupportedVersion(any())) .willAnswer(invocation -> invocation.getArgument(0)); @@ -213,7 +230,10 @@ public void setUp() { Integer.MAX_VALUE, ortb2RequestFactory, storedRequestProcessor, +<<<<<<< HEAD profilesProcessor, +======= +>>>>>>> 04d9d4a13 (Initial commit) ortbVersionConversionManager, auctionGppService, cookieDeprecationService, @@ -250,7 +270,10 @@ public void shouldReturnFailedFutureIfRequestBodyExceedsMaxRequestSize() { 1, ortb2RequestFactory, storedRequestProcessor, +<<<<<<< HEAD profilesProcessor, +======= +>>>>>>> 04d9d4a13 (Initial commit) ortbVersionConversionManager, auctionGppService, cookieDeprecationService, @@ -812,6 +835,7 @@ public void shouldUpdateTimeout() { .isEqualTo(10000L); } +<<<<<<< HEAD @Test public void shouldUseProfilesResult() { // given @@ -833,6 +857,8 @@ public void shouldUseProfilesResult() { anyBoolean()); } +======= +>>>>>>> 04d9d4a13 (Initial commit) private void givenBidRequest(BidRequest bidRequest) { try { given(requestBody.asString()).willReturn(mapper.writeValueAsString(bidRequest)); diff --git a/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java index 37c3964b713..ec623d2789b 100644 --- a/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java @@ -27,9 +27,14 @@ import org.prebid.server.VertxTest; import org.prebid.server.activity.infrastructure.creator.ActivityInfrastructureCreator; import org.prebid.server.auction.IpAddressHelper; +<<<<<<< HEAD import org.prebid.server.auction.TimeoutResolver; import org.prebid.server.auction.externalortb.ProfilesProcessor; import org.prebid.server.auction.externalortb.StoredRequestProcessor; +======= +import org.prebid.server.auction.StoredRequestProcessor; +import org.prebid.server.auction.TimeoutResolver; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.AuctionStoredResult; import org.prebid.server.auction.model.IpAddress; @@ -124,8 +129,11 @@ public class Ortb2RequestFactoryTest extends VertxTest { @Mock private StoredRequestProcessor storedRequestProcessor; @Mock(strictness = LENIENT) +<<<<<<< HEAD private ProfilesProcessor profilesProcessor; @Mock(strictness = LENIENT) +======= +>>>>>>> 04d9d4a13 (Initial commit) private ApplicationSettings applicationSettings; @Mock private IpAddressHelper ipAddressHelper; @@ -153,9 +161,12 @@ public void setUp() { given(timeoutResolver.limitToMax(any())).willReturn(2000L); +<<<<<<< HEAD given(profilesProcessor.process(any(), any())) .willAnswer(invocation -> Future.succeededFuture(invocation.getArgument(1))); +======= +>>>>>>> 04d9d4a13 (Initial commit) given(hookStageExecutor.executeEntrypointStage(any(), any(), any(), any())) .willAnswer(invocation -> Future.succeededFuture(HookStageExecutionResult.of( false, @@ -547,6 +558,7 @@ public void shouldFetchAccountFromStoredAndReturnFailedFutureIfStoredLookupIsFai } @Test +<<<<<<< HEAD public void fetchAccountWithoutStoredRequestLookupShouldNeverCallStoredProcessor() { // when target.fetchAccountWithoutStoredRequestLookup( @@ -580,6 +592,13 @@ public void shouldFetchAccountFromProfileIfStoredLookupIsTrueAndAccountIsNotFoun final Account fetchedAccount = Account.builder().id(accountId).status(AccountStatus.active).build(); given(applicationSettings.getAccountById(eq(accountId), any())) .willReturn(Future.succeededFuture(fetchedAccount)); +======= + public void shouldFetchAccountFromStoredAndReturnEmptyAccountIfStoredLookupIsFailed() { + // given + final BidRequest receivedBidRequest = givenBidRequest(identity()); + given(storedRequestProcessor.processAuctionRequest(any(), any())) + .willReturn(Future.failedFuture(new RuntimeException("error"))); +>>>>>>> 04d9d4a13 (Initial commit) // when final Future result = target.fetchAccount( @@ -591,9 +610,30 @@ public void shouldFetchAccountFromProfileIfStoredLookupIsTrueAndAccountIsNotFoun // then verify(storedRequestProcessor).processAuctionRequest("", receivedBidRequest); +<<<<<<< HEAD verify(applicationSettings).getAccountById(eq(accountId), any()); assertThat(result.result()).isEqualTo(fetchedAccount); +======= + verifyNoInteractions(applicationSettings); + + assertThat(result.failed()).isTrue(); + assertThat(result.cause()).hasMessage("error"); + } + + @Test + public void fetchAccountWithoutStoredRequestLookupShouldNeverCallStoredProcessor() { + // when + target.fetchAccountWithoutStoredRequestLookup( + AuctionContext.builder() + .httpRequest(httpRequest) + .bidRequest(givenBidRequest(identity())) + .timeoutContext(TimeoutContext.of(0, null, 0)) + .build()); + + // then + verifyNoInteractions(storedRequestProcessor); +>>>>>>> 04d9d4a13 (Initial commit) } @Test @@ -1051,11 +1091,19 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldAddIpAddressV4FromPri // when final Future result = target.enrichBidRequestWithAccountAndPrivacyData( +<<<<<<< HEAD AuctionContext.builder() .bidRequest(bidRequest) .account(account) .privacyContext(privacyContext) .build()); +======= + AuctionContext.builder() + .bidRequest(bidRequest) + .account(account) + .privacyContext(privacyContext) + .build()); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(result).isSucceeded().unwrap() @@ -1084,11 +1132,19 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldAddIpAddressV6FromPri // when final Future result = target.enrichBidRequestWithAccountAndPrivacyData( +<<<<<<< HEAD AuctionContext.builder() .bidRequest(bidRequest) .account(account) .privacyContext(privacyContext) .build()); +======= + AuctionContext.builder() + .bidRequest(bidRequest) + .account(account) + .privacyContext(privacyContext) + .build()); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(result).isSucceeded().unwrap() @@ -1806,7 +1862,10 @@ private void givenTarget(int timeoutAdjustmentFactor) { timeoutResolver, timeoutFactory, storedRequestProcessor, +<<<<<<< HEAD profilesProcessor, +======= +>>>>>>> 04d9d4a13 (Initial commit) applicationSettings, ipAddressHelper, hookStageExecutor, diff --git a/src/test/java/org/prebid/server/bidder/alvads/AlvadsBidderTest.java b/src/test/java/org/prebid/server/bidder/alvads/AlvadsBidderTest.java new file mode 100644 index 00000000000..003cb34e6eb --- /dev/null +++ b/src/test/java/org/prebid/server/bidder/alvads/AlvadsBidderTest.java @@ -0,0 +1,233 @@ +package org.prebid.server.bidder.alvads; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.iab.openrtb.request.Banner; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Site; +import com.iab.openrtb.response.Bid; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import io.vertx.core.MultiMap; +import org.junit.jupiter.api.Test; +import org.prebid.server.VertxTest; +import org.prebid.server.bidder.alvads.model.AlvaAdsImp; +import org.prebid.server.bidder.alvads.model.AlvadsRequestORTB; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderCall; +import org.prebid.server.bidder.model.HttpRequest; +import org.prebid.server.bidder.model.HttpResponse; +import org.prebid.server.bidder.model.Result; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; + +class AlvadsBidderTest extends VertxTest { + + private static final String ENDPOINT_URL = "https://helios-ads-qa-core.ssidevops.com/decision/openrtb"; + + private final AlvadsBidder target = new AlvadsBidder(ENDPOINT_URL, jacksonMapper); + + @Test + void creationShouldFailOnInvalidEndpointUrl() { + assertThatIllegalArgumentException() + .isThrownBy(() -> new AlvadsBidder("invalid_url", jacksonMapper)); + } + + @Test + void makeHttpRequestsShouldReturnErrorForInvalidImpExt() { + + final ObjectNode extNode = new ObjectMapper().createObjectNode(); + extNode.put("bidder", "invalid"); + + final BidRequest bidRequest = BidRequest.builder() + .imp(List.of(Imp.builder().id("1").ext(extNode).build())) + .build(); + + final Result>> result = target.makeHttpRequests(bidRequest); + + assertThat(result.getErrors()).isNotEmpty(); + assertThat(result.getErrors().get(0).getMessage()) + .contains("Missing or invalid bidder ext"); + } + + @Test + void makeHttpRequestsShouldBuildValidHttpRequests() { + final ObjectMapper mapper = new ObjectMapper(); + + final ObjectNode bidderNode1 = mapper.createObjectNode(); + bidderNode1.put("publisherUniqueId", "pub-1"); + bidderNode1.put("endPointUrl", ENDPOINT_URL); + + final ObjectNode impExtNode1 = mapper.createObjectNode(); + impExtNode1.set("bidder", bidderNode1); + + final ObjectNode bidderNode2 = mapper.createObjectNode(); + bidderNode2.put("publisherUniqueId", "pub-2"); + bidderNode2.put("endPointUrl", ENDPOINT_URL); + + final ObjectNode impExtNode2 = mapper.createObjectNode(); + impExtNode2.set("bidder", bidderNode2); + + final Imp imp1 = Imp.builder() + .id("imp-1") + .banner(Banner.builder().w(300).h(250).build()) + .ext(impExtNode1) + .build(); + + final Imp imp2 = Imp.builder() + .id("imp-2") + .video(com.iab.openrtb.request.Video.builder().w(640).h(480).build()) + .ext(impExtNode2) + .build(); + + final Site site = Site.builder() + .page("https://example.com") + .build(); + + final BidRequest bidRequest = BidRequest.builder() + .id("req-123") + .imp(List.of(imp1, imp2)) + .site(site) + .device(com.iab.openrtb.request.Device.builder().build()) + .build(); + + final Result>> result = target.makeHttpRequests(bidRequest); + + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(2); + + final HttpRequest request1 = result.getValue().get(0); + final HttpRequest request2 = result.getValue().get(1); + + assertThat(request1.getUri()).isEqualTo(ENDPOINT_URL); + assertThat(request2.getUri()).isEqualTo(ENDPOINT_URL); + + assertThat(request1.getHeaders()).isNotEmpty(); + assertThat(request2.getHeaders()).isNotEmpty(); + + assertThat(request1.getImpIds()).contains("imp-1"); + assertThat(request2.getImpIds()).contains("imp-2"); + + assertThat(request1.getPayload().getImp().get(0).getBanner()).isNotNull(); + assertThat(request1.getPayload().getImp().get(0).getVideo()).isNull(); + + assertThat(request2.getPayload().getImp().get(0).getVideo()).isNotNull(); + assertThat(request2.getPayload().getImp().get(0).getBanner()).isNull(); + + assertThat(request1.getPayload().getId()).isEqualTo("req-123"); + assertThat(request2.getPayload().getId()).isEqualTo("req-123"); + } + + @Test + void makeBidsShouldReturnEmptyListForEmptyResponse() { + final BidResponse bidResponse = BidResponse.builder().build(); + final HttpResponse response = HttpResponse.of( + 200, + MultiMap.caseInsensitiveMultiMap(), + jacksonMapper.encodeToString(bidResponse) + ); + + final BidderCall call = BidderCall.succeededHttp( + HttpRequest.builder().payload(null).build(), + response, + null + ); + + final Result> result = target.makeBids(call, BidRequest.builder().build()); + + assertThat(result.getValue()).isEmpty(); + } + + @Test + void makeBidsShouldReturnBidderBids() { + // GIVEN + final String impId = "AE_AD_1748977459403"; + final String publisherId = "D7DACCE3-C23D-4AB9-8FE6-9FF41BF32F8F"; + + final Bid bid = createBid("bid1", impId, 1); + final SeatBid seatBid = createSeatBid(bid); + final BidResponse bidResponse = createBidResponse(List.of(seatBid), "USD"); + + final HttpResponse response = HttpResponse.of( + 200, + MultiMap.caseInsensitiveMultiMap(), + jacksonMapper.encodeToString(bidResponse) + ); + + final Imp imp = createImp(impId, publisherId, 320, 100); + final BidRequest bidRequest = createBidRequest(List.of(imp)); + + final AlvadsRequestORTB alvadsRequest = createAlvadsRequest(impId, 320, 100); + final HttpRequest httpRequest = HttpRequest.builder() + .payload(alvadsRequest) + .build(); + + final BidderCall call = BidderCall.succeededHttp(httpRequest, response, null); + + // WHEN + final Result> result = target.makeBids(call, bidRequest); + + // THEN + assertThat(result.getValue()).hasSize(1); + assertThat(result.getValue().get(0).getBid().getId()).isEqualTo("bid1"); + } + + private static Bid createBid(String id, String impId, double price) { + return Bid.builder() + .id(id) + .impid(impId) + .price(BigDecimal.valueOf(price)) + .build(); + } + + private static SeatBid createSeatBid(Bid... bids) { + return SeatBid.builder() + .bid(Arrays.asList(bids)) + .build(); + } + + private static BidResponse createBidResponse(List seatBids, String currency) { + return BidResponse.builder() + .seatbid(seatBids) + .cur(currency) + .build(); + } + + private static Imp createImp(String id, String publisherId, int width, int height) { + final ObjectNode extNode = new ObjectMapper().createObjectNode() + .putObject("bidder") + .put("publisherUniqueId", publisherId); + + return Imp.builder() + .id(id) + .banner(Banner.builder().w(width).h(height).build()) + .ext(extNode) + .build(); + } + + private static BidRequest createBidRequest(List imps) { + return BidRequest.builder() + .id("req-123") + .imp(imps) + .build(); + } + + private static AlvadsRequestORTB createAlvadsRequest(String impId, int width, int height) { + final AlvaAdsImp alvaImp = AlvaAdsImp.builder() + .id(impId) + .banner(Map.of("w", width, "h", height)) + .build(); + + return AlvadsRequestORTB.builder() + .imp(List.of(alvaImp)) + .build(); + } + +} diff --git a/src/test/java/org/prebid/server/bidder/ix/IxBidderTest.java b/src/test/java/org/prebid/server/bidder/ix/IxBidderTest.java index 051077ab03e..a72c54fec86 100644 --- a/src/test/java/org/prebid/server/bidder/ix/IxBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/ix/IxBidderTest.java @@ -26,6 +26,10 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.VertxTest; +<<<<<<< HEAD +======= +import org.prebid.server.bidder.ix.model.request.IxDiag; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.bidder.ix.model.response.AuctionConfigExtBidResponse; import org.prebid.server.bidder.ix.model.response.IxBidResponse; import org.prebid.server.bidder.ix.model.response.IxExtBidResponse; @@ -190,10 +194,15 @@ public void makeHttpRequestsShouldReturnIxDiagWithPbjsVersionIfRequestExtPrebidC .extracting(HttpRequest::getPayload) .extracting(BidRequest::getExt) .extracting(ext -> ext.getProperty("ixdiag")) +<<<<<<< HEAD .containsExactly(mapper.createObjectNode() .put("pbsv", "unknown") .put("pbjsv", "pbjsv") .put("pbsp", "java")); +======= + .extracting(diagNode -> mapper.treeToValue(diagNode, IxDiag.class)) + .containsExactly(IxDiag.of(null, "pbjsv", null)); +>>>>>>> 04d9d4a13 (Initial commit) } @Test @@ -211,9 +220,14 @@ public void makeHttpRequestsShouldReturnIxDiagWithPbsVersion() { .extracting(HttpRequest::getPayload) .extracting(BidRequest::getExt) .extracting(ext -> ext.getProperty("ixdiag")) +<<<<<<< HEAD .containsExactly(mapper.createObjectNode() .put("pbsv", "pbsv") .put("pbsp", "java")); +======= + .extracting(diagNode -> mapper.treeToValue(diagNode, IxDiag.class)) + .containsExactly(IxDiag.of("pbsv", null, null)); +>>>>>>> 04d9d4a13 (Initial commit) } @Test @@ -232,6 +246,7 @@ public void makeHttpRequestsShouldReturnIxDiagWithMultipleSiteIdsWhenMultipleImp .extracting(HttpRequest::getPayload) .extracting(BidRequest::getExt) .extracting(ext -> ext.getProperty("ixdiag")) +<<<<<<< HEAD .containsExactly(mapper.createObjectNode() .put("pbsv", "unknown") .put("pbsp", "java") @@ -277,6 +292,10 @@ public void makeHttpRequestsShouldPassThroughProvidedIxDiagFields() { .extracting(BidRequest::getExt) .extracting(ext -> ext.getProperty("ixdiag")) .containsExactly(expectedIxDiag); +======= + .extracting(diagNode -> mapper.treeToValue(diagNode, IxDiag.class)) + .containsExactly(IxDiag.of(null, null, "site1, site2")); +>>>>>>> 04d9d4a13 (Initial commit) } @Test @@ -931,12 +950,15 @@ private static ExtRequest givenExtRequest(String pbjsv) { .build()); } +<<<<<<< HEAD private static ExtRequest givenExtRequestWithIxDiag(String pbjsv, ObjectNode ixDiag) { final ExtRequest extRequest = givenExtRequest(pbjsv); extRequest.addProperty("ixdiag", ixDiag); return extRequest; } +======= +>>>>>>> 04d9d4a13 (Initial commit) private static ObjectNode givenImpExt(String siteId, String sid) { return mapper.valueToTree(ExtPrebid.of(null, ExtImpIx.of(siteId, null, sid))); } diff --git a/src/test/java/org/prebid/server/bidder/onetag/OnetagBidderTest.java b/src/test/java/org/prebid/server/bidder/onetag/OnetagBidderTest.java index 73d6035303d..115fd69fdcb 100644 --- a/src/test/java/org/prebid/server/bidder/onetag/OnetagBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/onetag/OnetagBidderTest.java @@ -104,6 +104,32 @@ public void makeHttpRequestsShouldReturnErrorIfImpExtCanNotBeParsed() { } @Test +<<<<<<< HEAD +======= + public void makeHttpRequestsShouldUpdateImpExt() { + // given + final ObjectNode oneTagExt = mapper.createObjectNode(); + oneTagExt.put("someField", "someName"); + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpOnetag.of("somePubId", oneTagExt)))) + .build())) + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getExt) + .containsExactly(oneTagExt); + } + + @Test +>>>>>>> 04d9d4a13 (Initial commit) public void makeHttpRequestsShouldReturnErrorIfPubIdNotPresent() { // given final ObjectNode oneTagExt = mapper.createObjectNode(); diff --git a/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java b/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java index c9f64cd8a0c..fb3bbcc27e3 100644 --- a/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java @@ -1,7 +1,10 @@ package org.prebid.server.bidder.smartadserver; import com.fasterxml.jackson.core.JsonProcessingException; +<<<<<<< HEAD import com.fasterxml.jackson.databind.node.ObjectNode; +======= +>>>>>>> 04d9d4a13 (Initial commit) import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Imp; @@ -38,6 +41,7 @@ public class SmartadserverBidderTest extends VertxTest { private static final String ENDPOINT_URL = "https://test.endpoint.com/path?testParam=testVal"; +<<<<<<< HEAD private static final String SECONDARY_URL = "https://test.endpoint2.com/path?testParam=testVal"; private final SmartadserverBidder target = new SmartadserverBidder(ENDPOINT_URL, SECONDARY_URL, jacksonMapper); @@ -52,6 +56,14 @@ public void creationShouldFailOnInvalidEndpointUrl() { public void creationShouldFailOnInvalidSecondaryEndpointUrl() { assertThatIllegalArgumentException() .isThrownBy(() -> new SmartadserverBidder(ENDPOINT_URL, "invalid_url", jacksonMapper)); +======= + + private final SmartadserverBidder target = new SmartadserverBidder(ENDPOINT_URL, jacksonMapper); + + @Test + public void creationShouldFailOnInvalidEndpointUrl() { + assertThatIllegalArgumentException().isThrownBy(() -> new SmartadserverBidder("invalid_url", jacksonMapper)); +>>>>>>> 04d9d4a13 (Initial commit) } @Test @@ -73,7 +85,11 @@ public void makeHttpRequestsShouldReturnErrorIfImpExtCouldNotBeParsed() { } @Test +<<<<<<< HEAD public void makeHttpRequestsShouldCreateCorrectPrimaryURLWhenProgrammaticGuaranteedIsAbsent() { +======= + public void makeHttpRequestsShouldCreateCorrectURL() { +>>>>>>> 04d9d4a13 (Initial commit) // given final BidRequest bidRequest = BidRequest.builder() .imp(singletonList(givenImp(identity()))) @@ -90,6 +106,7 @@ public void makeHttpRequestsShouldCreateCorrectPrimaryURLWhenProgrammaticGuarant } @Test +<<<<<<< HEAD public void makeHttpRequestsShouldCreateCorrectSecondaryURLWhenProgrammaticGuaranteedIsTrue() { // given final ObjectNode givenImpExt = mapper.createObjectNode() @@ -130,6 +147,8 @@ public void makeHttpRequestsShouldCreateCorrectPrimaryURLWhenProgrammaticGuarant } @Test +======= +>>>>>>> 04d9d4a13 (Initial commit) public void makeHttpRequestsShouldUpdateSiteObjectIfPresent() { // given final BidRequest bidRequest = BidRequest.builder() @@ -202,6 +221,7 @@ public void makeHttpRequestsShouldCreateSingleRequestWithValidImpsOnly() { } @Test +<<<<<<< HEAD public void makeHttpRequestsShouldModifyImpWhenProgrammaticGuaranteedIsTrueAtLeastInOneValidImp() { // given final ObjectNode givenImpExt1 = mapper.createObjectNode() @@ -252,6 +272,8 @@ public void makeHttpRequestsShouldModifyImpWhenProgrammaticGuaranteedIsTrueAtLea } @Test +======= +>>>>>>> 04d9d4a13 (Initial commit) public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { // given final BidderCall httpCall = givenHttpCall(null, "invalid"); @@ -398,12 +420,19 @@ public void makeBidsShouldReturnNativeBidIfMarkupTypeIsNative() throws JsonProce private static Imp givenImp(Function impCustomizer) { return impCustomizer.apply(Imp.builder() +<<<<<<< HEAD .id("123") .banner(Banner.builder().build()) .video(Video.builder().build()) .ext(mapper.valueToTree(ExtPrebid.of( null, ExtImpSmartadserver.of(1, 2, 3, 4, false))))) +======= + .id("123")) + .banner(Banner.builder().build()) + .video(Video.builder().build()) + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpSmartadserver.of(1, 2, 3, 4)))) +>>>>>>> 04d9d4a13 (Initial commit) .build(); } diff --git a/src/test/java/org/prebid/server/handler/SettingsCacheNotificationHandlerTest.java b/src/test/java/org/prebid/server/handler/SettingsCacheNotificationHandlerTest.java index 8379cf6de94..6ac8fee6c74 100644 --- a/src/test/java/org/prebid/server/handler/SettingsCacheNotificationHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/SettingsCacheNotificationHandlerTest.java @@ -31,7 +31,11 @@ public class SettingsCacheNotificationHandlerTest extends VertxTest { @Mock +<<<<<<< HEAD private CacheNotificationListener cacheNotificationListener; +======= + private CacheNotificationListener cacheNotificationListener; +>>>>>>> 04d9d4a13 (Initial commit) private SettingsCacheNotificationHandler handler; @Mock(strictness = LENIENT) @@ -45,7 +49,11 @@ public class SettingsCacheNotificationHandlerTest extends VertxTest { @BeforeEach public void setUp() { +<<<<<<< HEAD handler = new SettingsCacheNotificationHandler("endpoint", cacheNotificationListener, jacksonMapper); +======= + handler = new SettingsCacheNotificationHandler(cacheNotificationListener, jacksonMapper, "endpoint"); +>>>>>>> 04d9d4a13 (Initial commit) given(routingContext.request()).willReturn(httpRequest); given(routingContext.response()).willReturn(httpResponse); diff --git a/src/test/java/org/prebid/server/it/SmartadserverTest.java b/src/test/java/org/prebid/server/it/SmartadserverTest.java index 296883918e8..ec2e4ec8f05 100644 --- a/src/test/java/org/prebid/server/it/SmartadserverTest.java +++ b/src/test/java/org/prebid/server/it/SmartadserverTest.java @@ -18,7 +18,11 @@ public class SmartadserverTest extends IntegrationTest { @Test public void openrtb2AuctionShouldRespondWithBidsFromSmartadserver() throws IOException, JSONException { // given +<<<<<<< HEAD WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/smartadserver-secondary-exchange/ortb")) +======= + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/smartadserver-exchange/api/bid")) +>>>>>>> 04d9d4a13 (Initial commit) .withRequestBody(equalToJson(jsonFrom("openrtb2/smartadserver/test-smartadserver-bid-request.json"))) .willReturn(aResponse() .withBody(jsonFrom("openrtb2/smartadserver/test-smartadserver-bid-response.json")))); diff --git a/src/test/java/org/prebid/server/metric/MetricsTest.java b/src/test/java/org/prebid/server/metric/MetricsTest.java index fc6510e3529..c630c24418c 100644 --- a/src/test/java/org/prebid/server/metric/MetricsTest.java +++ b/src/test/java/org/prebid/server/metric/MetricsTest.java @@ -1571,6 +1571,7 @@ public void shouldIncrementPrebidCacheCreativeTtlHistogram() { .isEqualTo(1); } +<<<<<<< HEAD @Test public void shouldIncrementUpdateProfileMetric() { // when @@ -1591,6 +1592,8 @@ public void shouldIncrementUpdateAccountProfileMetric() { .isEqualTo(1); } +======= +>>>>>>> 04d9d4a13 (Initial commit) private void verifyCreatesConfiguredCounterType(Consumer metricsConsumer) { final EnumMap> counterTypeClasses = new EnumMap<>(CounterType.class); counterTypeClasses.put(CounterType.counter, Counter.class); diff --git a/src/test/java/org/prebid/server/settings/CachingApplicationSettingsTest.java b/src/test/java/org/prebid/server/settings/CachingApplicationSettingsTest.java index 125a15f49c8..de0b2877271 100644 --- a/src/test/java/org/prebid/server/settings/CachingApplicationSettingsTest.java +++ b/src/test/java/org/prebid/server/settings/CachingApplicationSettingsTest.java @@ -58,10 +58,16 @@ public void setUp() { target = new CachingApplicationSettings( delegateSettings, +<<<<<<< HEAD new SettingsCache<>(360, 100, 0), new SettingsCache<>(360, 100, 0), new SettingsCache<>(360, 100, 0), new SettingsCache<>(360, 100, 0), +======= + new SettingsCache(360, 100, 0), + new SettingsCache(360, 100, 0), + new SettingsCache(360, 100, 0), +>>>>>>> 04d9d4a13 (Initial commit) metrics, 360, 100, @@ -358,7 +364,11 @@ public void getStoredDataShouldReturnResultOnSuccessiveCalls() { singletonMap("reqid", "json"), singletonMap("impid", "json2"), emptyList()))); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) target.getStoredData("1001", singleton("reqid"), singleton("impid"), timeout); // second call target.getStoredData("1001", singleton("reqid"), singleton("impid"), timeout); @@ -379,7 +389,11 @@ public void getStoredDataShouldPropagateFailure() { .willReturn(Future.failedFuture(new InvalidRequestException("error"))); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) target.getStoredData(null, singleton("id"), emptySet(), timeout); // then @@ -397,7 +411,11 @@ public void getStoredDataShouldReturnResultWithErrorsOnNotSuccessiveCallToCacheA emptyMap(), emptyMap(), singletonList("error")))); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) target.getStoredData(null, singleton("id"), emptySet(), timeout); // then @@ -417,7 +435,11 @@ public void getStoredDataShouldReturnResultWithErrorIfAccountDiffers() { // when target.getStoredData("1001", singleton("reqid"), emptySet(), timeout); // second call +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) target.getStoredData("1002", singleton("reqid"), emptySet(), timeout); // then diff --git a/src/test/java/org/prebid/server/settings/CompositeApplicationSettingsTest.java b/src/test/java/org/prebid/server/settings/CompositeApplicationSettingsTest.java index f140a0428c6..d83d747be75 100644 --- a/src/test/java/org/prebid/server/settings/CompositeApplicationSettingsTest.java +++ b/src/test/java/org/prebid/server/settings/CompositeApplicationSettingsTest.java @@ -1,6 +1,9 @@ package org.prebid.server.settings; +<<<<<<< HEAD import com.fasterxml.jackson.databind.node.TextNode; +======= +>>>>>>> 04d9d4a13 (Initial commit) import io.vertx.core.Future; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -11,7 +14,10 @@ import org.prebid.server.exception.PreBidException; import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.AccountAuctionConfig; +<<<<<<< HEAD import org.prebid.server.settings.model.Profile; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.settings.model.StoredDataResult; import org.prebid.server.settings.model.StoredResponseDataResult; @@ -175,6 +181,7 @@ public void getStoredDataShouldReturnResultFromFirstDelegateIfPresent() { // given given(delegate1.getStoredData(any(), anySet(), anySet(), any())) .willReturn(Future.succeededFuture( +<<<<<<< HEAD StoredDataResult.of( singletonMap("key1", "value1"), singletonMap("key2", "value2"), @@ -182,6 +189,13 @@ public void getStoredDataShouldReturnResultFromFirstDelegateIfPresent() { // when final Future> future = +======= + StoredDataResult.of(singletonMap("key1", "value1"), singletonMap("key2", "value2"), + emptyList()))); + + // when + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) compositeApplicationSettings.getStoredData(null, singleton("key1"), singleton("key2"), null); // then @@ -204,6 +218,7 @@ public void getStoredDataShouldReturnResultFromFromSecondDelegateIfFirstDelegate given(delegate2.getStoredData(any(), anySet(), anySet(), any())) .willReturn(Future.succeededFuture( +<<<<<<< HEAD StoredDataResult.of( singletonMap("key1", "value1"), singletonMap("key2", "value2"), @@ -211,6 +226,13 @@ public void getStoredDataShouldReturnResultFromFromSecondDelegateIfFirstDelegate // when final Future> future = +======= + StoredDataResult.of(singletonMap("key1", "value1"), singletonMap("key2", "value2"), + emptyList()))); + + // when + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) compositeApplicationSettings.getStoredData(null, singleton("key1"), singleton("key2"), null); // then @@ -235,7 +257,11 @@ public void getStoredDataShouldReturnEmptyResultIfAllDelegatesFail() { StoredDataResult.of(emptyMap(), emptyMap(), singletonList("error2")))); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) compositeApplicationSettings.getStoredData(null, singleton("key1"), emptySet(), null); // then @@ -250,6 +276,7 @@ public void getStoredDataShouldPassOnlyMissingIdsToSecondDelegateIfFirstDelegate // given given(delegate1.getStoredData(any(), anySet(), anySet(), any())) .willReturn(Future.succeededFuture( +<<<<<<< HEAD StoredDataResult.of( singletonMap("key1", "value1"), singletonMap("key3", "value3"), @@ -261,6 +288,14 @@ public void getStoredDataShouldPassOnlyMissingIdsToSecondDelegateIfFirstDelegate new HashSet<>(asList("key1", "key2")), new HashSet<>(asList("key3", "key4")), null); +======= + StoredDataResult.of(singletonMap("key1", "value1"), singletonMap("key3", "value3"), + singletonList("error1")))); + + // when + compositeApplicationSettings.getStoredData(null, new HashSet<>(asList("key1", "key2")), + new HashSet<>(asList("key3", "key4")), null); +>>>>>>> 04d9d4a13 (Initial commit) // then @SuppressWarnings("unchecked") final ArgumentCaptor> requestCaptor = ArgumentCaptor.forClass( @@ -279,13 +314,18 @@ public void getStoredDataShouldReturnResultConsequentlyFromAllDelegates() { // given given(delegate1.getStoredData(any(), anySet(), anySet(), any())) .willReturn(Future.succeededFuture( +<<<<<<< HEAD StoredDataResult.of( singletonMap("key1", "value1"), singletonMap("key3", "value3"), +======= + StoredDataResult.of(singletonMap("key1", "value1"), singletonMap("key3", "value3"), +>>>>>>> 04d9d4a13 (Initial commit) asList("key2 not found", "key4 not found")))); given(delegate2.getStoredData(any(), anySet(), anySet(), any())) .willReturn(Future.succeededFuture( +<<<<<<< HEAD StoredDataResult.of( singletonMap("key2", "value2"), singletonMap("key4", "value4"), @@ -298,6 +338,15 @@ public void getStoredDataShouldReturnResultConsequentlyFromAllDelegates() { new HashSet<>(asList("key1", "key2")), new HashSet<>(asList("key3", "key4")), null); +======= + StoredDataResult.of(singletonMap("key2", "value2"), singletonMap("key4", "value4"), + emptyList()))); + + // when + final Future future = + compositeApplicationSettings.getStoredData(null, new HashSet<>(asList("key1", "key2")), + new HashSet<>(asList("key3", "key4")), null); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(future.succeeded()).isTrue(); @@ -320,7 +369,11 @@ public void getAmpStoredDataShouldReturnResultFromFirstDelegateIfPresent() { StoredDataResult.of(singletonMap("key1", "value1"), emptyMap(), emptyList()))); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) compositeApplicationSettings.getAmpStoredData(null, singleton("key1"), emptySet(), null); // then @@ -344,7 +397,11 @@ public void getAmpStoredDataShouldReturnResultFromFromSecondDelegateIfFirstDeleg StoredDataResult.of(singletonMap("key1", "value1"), emptyMap(), emptyList()))); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) compositeApplicationSettings.getAmpStoredData(null, singleton("key1"), emptySet(), null); // then @@ -367,7 +424,11 @@ public void getAmpStoredDataShouldReturnEmptyResultIfAllDelegatesFail() { StoredDataResult.of(emptyMap(), emptyMap(), singletonList("error2")))); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) compositeApplicationSettings.getAmpStoredData(null, singleton("key1"), emptySet(), null); // then @@ -385,8 +446,13 @@ public void getAmpStoredDataShouldPassOnlyMissingIdsToSecondDelegateIfFirstDeleg StoredDataResult.of(singletonMap("key1", "value1"), emptyMap(), singletonList("error1")))); // when +<<<<<<< HEAD compositeApplicationSettings.getAmpStoredData( null, new HashSet<>(asList("key1", "key2")), emptySet(), null); +======= + compositeApplicationSettings.getAmpStoredData(null, new HashSet<>(asList("key1", "key2")), emptySet(), + null); +>>>>>>> 04d9d4a13 (Initial commit) // then @SuppressWarnings("unchecked") final ArgumentCaptor> requestCaptor = ArgumentCaptor.forClass( @@ -402,9 +468,13 @@ public void getAmpStoredDataShouldReturnResultConsequentlyFromAllDelegates() { // given given(delegate1.getAmpStoredData(any(), anySet(), anySet(), any())) .willReturn(Future.succeededFuture( +<<<<<<< HEAD StoredDataResult.of( singletonMap("key1", "value1"), emptyMap(), +======= + StoredDataResult.of(singletonMap("key1", "value1"), emptyMap(), +>>>>>>> 04d9d4a13 (Initial commit) singletonList("key2 not found")))); given(delegate2.getAmpStoredData(any(), anySet(), anySet(), any())) @@ -412,8 +482,13 @@ public void getAmpStoredDataShouldReturnResultConsequentlyFromAllDelegates() { StoredDataResult.of(singletonMap("key2", "value2"), emptyMap(), emptyList()))); // when +<<<<<<< HEAD final Future> future = compositeApplicationSettings.getAmpStoredData( null, new HashSet<>(asList("key1", "key2")), emptySet(), null); +======= + final Future future = compositeApplicationSettings.getAmpStoredData(null, + new HashSet<>(asList("key1", "key2")), emptySet(), null); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(future.succeeded()).isTrue(); @@ -425,6 +500,7 @@ public void getAmpStoredDataShouldReturnResultConsequentlyFromAllDelegates() { } @Test +<<<<<<< HEAD public void getProfilesShouldReturnResultFromFirstDelegateIfPresent() { // given given(delegate1.getProfiles(any(), anySet(), anySet(), any())) @@ -566,6 +642,8 @@ public void getProfilesShouldReturnResultConsequentlyFromAllDelegates() { } @Test +======= +>>>>>>> 04d9d4a13 (Initial commit) public void getStoredResponsesShouldReturnResultFromFirstDelegateIfPresent() { // given given(delegate1.getStoredResponses(anySet(), any())) @@ -640,7 +718,12 @@ public void getStoredResponsesShouldPassOnlyMissingIdsToSecondDelegateIfFirstDel compositeApplicationSettings.getStoredResponses(new HashSet<>(asList("key1", "key2")), null); // then +<<<<<<< HEAD final ArgumentCaptor> responseCaptor = ArgumentCaptor.captor(); +======= + @SuppressWarnings("unchecked") final ArgumentCaptor> responseCaptor = ArgumentCaptor.forClass( + Set.class); +>>>>>>> 04d9d4a13 (Initial commit) verify(delegate2).getStoredResponses(responseCaptor.capture(), any()); assertThat(responseCaptor.getValue()).hasSize(1).containsOnly("key2"); @@ -669,6 +752,7 @@ public void getStoredResponsesShouldReturnResultConsequentlyFromAllDelegates() { entry("key1", "value1"), entry("key2", "value2")); } +<<<<<<< HEAD private static Profile givenProfile(String value) { return Profile.of( @@ -676,4 +760,6 @@ private static Profile givenProfile(String value) { Profile.MergePrecedence.PROFILE, TextNode.valueOf(value)); } +======= +>>>>>>> 04d9d4a13 (Initial commit) } diff --git a/src/test/java/org/prebid/server/settings/DatabaseApplicationSettingsTest.java b/src/test/java/org/prebid/server/settings/DatabaseApplicationSettingsTest.java index 7cfdb193461..5736703b335 100644 --- a/src/test/java/org/prebid/server/settings/DatabaseApplicationSettingsTest.java +++ b/src/test/java/org/prebid/server/settings/DatabaseApplicationSettingsTest.java @@ -1,6 +1,9 @@ package org.prebid.server.settings; +<<<<<<< HEAD import com.fasterxml.jackson.databind.node.TextNode; +======= +>>>>>>> 04d9d4a13 (Initial commit) import io.vertx.core.Future; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -13,7 +16,10 @@ import org.prebid.server.execution.timeout.TimeoutFactory; import org.prebid.server.settings.helper.ParametrizedQueryHelper; import org.prebid.server.settings.model.Account; +<<<<<<< HEAD import org.prebid.server.settings.model.Profile; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.settings.model.StoredDataResult; import org.prebid.server.settings.model.StoredResponseDataResult; import org.prebid.server.vertx.database.DatabaseClient; @@ -40,6 +46,7 @@ public class DatabaseApplicationSettingsTest extends VertxTest { private static final String SELECT_ACCOUNT_QUERY = "SELECT config FROM accounts_account where uuid = %ACCOUNT_ID% LIMIT 1"; +<<<<<<< HEAD private static final String SELECT_QUERY = """ SELECT accountId, reqid, requestData, 'request' as dataType FROM stored_requests \ WHERE reqid IN (%REQUEST_ID_LIST%) \ @@ -59,6 +66,17 @@ WHERE profileId in (%REQUEST_ID_LIST%, %IMP_ID_LIST%) FROM stored_responses \ WHERE responseId IN (%RESPONSE_ID_LIST%) """; +======= + private static final String SELECT_QUERY = + "SELECT accountId, reqid, requestData, 'request' as dataType FROM stored_requests " + + "WHERE reqid IN (%REQUEST_ID_LIST%) " + + "UNION ALL " + + "SELECT accountId, impid, impData, 'imp' as dataType FROM stored_imps " + + "WHERE impid IN (%IMP_ID_LIST%)"; + + private static final String SELECT_RESPONSE_QUERY = "SELECT responseId, responseData FROM stored_responses " + + "WHERE responseId IN (%RESPONSE_ID_LIST%)"; +>>>>>>> 04d9d4a13 (Initial commit) @Mock private ParametrizedQueryHelper parametrizedQueryHelper; @@ -81,7 +99,10 @@ public void setUp() { SELECT_ACCOUNT_QUERY, SELECT_QUERY, SELECT_QUERY, +<<<<<<< HEAD SELECT_PROFILES_QUERY, +======= +>>>>>>> 04d9d4a13 (Initial commit) SELECT_RESPONSE_QUERY); } @@ -128,7 +149,11 @@ public void getStoredDataShouldReturnExpectedResult() { given(parametrizedQueryHelper.replaceRequestAndImpIdPlaceholders(SELECT_QUERY, 2, 2)) .willReturn("query"); +<<<<<<< HEAD final StoredDataResult givenStoredDataResult = StoredDataResult.of( +======= + final StoredDataResult givenStoredDataResult = StoredDataResult.of( +>>>>>>> 04d9d4a13 (Initial commit) Map.of("1", "value1", "2", "value2"), Map.of("4", "value4", "5", "value5"), emptyList()); @@ -136,7 +161,11 @@ public void getStoredDataShouldReturnExpectedResult() { .willReturn(Future.succeededFuture(givenStoredDataResult)); // when +<<<<<<< HEAD final Future> future = target.getStoredData( +======= + final Future future = target.getStoredData( +>>>>>>> 04d9d4a13 (Initial commit) "1001", new HashSet<>(asList("1", "2")), new HashSet<>(asList("4", "5")), timeout); // then @@ -150,7 +179,11 @@ public void getAmpStoredDataShouldReturnExpectedResult() { given(parametrizedQueryHelper.replaceRequestAndImpIdPlaceholders(SELECT_QUERY, 2, 0)) .willReturn("query"); +<<<<<<< HEAD final StoredDataResult givenStoredDataResult = StoredDataResult.of( +======= + final StoredDataResult givenStoredDataResult = StoredDataResult.of( +>>>>>>> 04d9d4a13 (Initial commit) Map.of("1", "value1", "2", "value2"), Map.of(), emptyList()); @@ -158,7 +191,11 @@ public void getAmpStoredDataShouldReturnExpectedResult() { .willReturn(Future.succeededFuture(givenStoredDataResult)); // when +<<<<<<< HEAD final Future> future = target.getAmpStoredData( +======= + final Future future = target.getAmpStoredData( +>>>>>>> 04d9d4a13 (Initial commit) "1001", new HashSet<>(asList("1", "2")), new HashSet<>(asList("4", "5")), timeout); // then @@ -172,7 +209,11 @@ public void getVideoStoredDataShouldReturnExpectedResult() { given(parametrizedQueryHelper.replaceRequestAndImpIdPlaceholders(SELECT_QUERY, 2, 2)) .willReturn("query"); +<<<<<<< HEAD final StoredDataResult givenStoredDataResult = StoredDataResult.of( +======= + final StoredDataResult givenStoredDataResult = StoredDataResult.of( +>>>>>>> 04d9d4a13 (Initial commit) Map.of("1", "value1", "2", "value2"), Map.of("4", "value4", "5", "value5"), emptyList()); @@ -180,7 +221,11 @@ public void getVideoStoredDataShouldReturnExpectedResult() { .willReturn(Future.succeededFuture(givenStoredDataResult)); // when +<<<<<<< HEAD final Future> future = target.getVideoStoredData("1001", +======= + final Future future = target.getVideoStoredData("1001", +>>>>>>> 04d9d4a13 (Initial commit) new HashSet<>(asList("1", "2")), new HashSet<>(asList("4", "5")), timeout); // then @@ -189,6 +234,7 @@ public void getVideoStoredDataShouldReturnExpectedResult() { } @Test +<<<<<<< HEAD public void getProfilesShouldReturnExpectedResult() { // given given(parametrizedQueryHelper.replaceRequestAndImpIdPlaceholders(SELECT_PROFILES_QUERY, 2, 2)) @@ -211,12 +257,18 @@ public void getProfilesShouldReturnExpectedResult() { } @Test +======= +>>>>>>> 04d9d4a13 (Initial commit) public void getStoredDataShouldReturnResultWithError() { // given given(parametrizedQueryHelper.replaceRequestAndImpIdPlaceholders(SELECT_QUERY, 2, 0)) .willReturn("query"); +<<<<<<< HEAD final StoredDataResult givenStoredDataResult = StoredDataResult.of( +======= + final StoredDataResult givenStoredDataResult = StoredDataResult.of( +>>>>>>> 04d9d4a13 (Initial commit) Map.of("1", "value1"), Map.of(), List.of("No stored request found for id: 3")); @@ -224,7 +276,11 @@ public void getStoredDataShouldReturnResultWithError() { .willReturn(Future.succeededFuture(givenStoredDataResult)); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) target.getStoredData("1001", new HashSet<>(asList("1", "3")), emptySet(), timeout); // then @@ -238,7 +294,11 @@ public void getAmpStoredDataShouldReturnResultWithError() { given(parametrizedQueryHelper.replaceRequestAndImpIdPlaceholders(SELECT_QUERY, 2, 0)) .willReturn("query"); +<<<<<<< HEAD final StoredDataResult givenStoredDataResult = StoredDataResult.of( +======= + final StoredDataResult givenStoredDataResult = StoredDataResult.of( +>>>>>>> 04d9d4a13 (Initial commit) Map.of("1", "value1"), Map.of(), List.of("No stored request found for id: 3")); @@ -246,7 +306,11 @@ public void getAmpStoredDataShouldReturnResultWithError() { .willReturn(Future.succeededFuture(givenStoredDataResult)); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) target.getAmpStoredData("1001", new HashSet<>(asList("1", "3")), emptySet(), timeout); // then @@ -260,7 +324,11 @@ public void getVideoStoredDataShouldReturnResultWithError() { given(parametrizedQueryHelper.replaceRequestAndImpIdPlaceholders(SELECT_QUERY, 2, 0)) .willReturn("query"); +<<<<<<< HEAD final StoredDataResult givenStoredDataResult = StoredDataResult.of( +======= + final StoredDataResult givenStoredDataResult = StoredDataResult.of( +>>>>>>> 04d9d4a13 (Initial commit) Map.of("1", "value1"), Map.of(), List.of("No stored request found for id: 3")); @@ -268,7 +336,11 @@ public void getVideoStoredDataShouldReturnResultWithError() { .willReturn(Future.succeededFuture(givenStoredDataResult)); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) target.getVideoStoredData("1001", new HashSet<>(asList("1", "3")), emptySet(), timeout); // then @@ -277,6 +349,7 @@ public void getVideoStoredDataShouldReturnResultWithError() { } @Test +<<<<<<< HEAD public void getProfilesShouldReturnResultWithError() { // given given(parametrizedQueryHelper.replaceRequestAndImpIdPlaceholders(SELECT_PROFILES_QUERY, 2, 0)) @@ -299,6 +372,8 @@ public void getProfilesShouldReturnResultWithError() { } @Test +======= +>>>>>>> 04d9d4a13 (Initial commit) public void getStoredResponseShouldReturnExpectedResult() { // given given(parametrizedQueryHelper.replaceStoredResponseIdPlaceholders(SELECT_RESPONSE_QUERY, 2)) @@ -322,13 +397,19 @@ public void getStoredResponseShouldReturnExpectedResult() { @Test public void getCategoriesShouldReturnFailedFutureWithUnsupportedPrebidException() { // given and when +<<<<<<< HEAD final Future> result = target.getCategories("adServer", "publisher", timeout); +======= + final Future> result = target.getCategories("adServer", "publisher", + timeout); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(result.failed()).isTrue(); assertThat(result.cause()).isInstanceOf(PreBidException.class) .hasMessage("Not supported"); } +<<<<<<< HEAD private static Profile givenProfile(String value) { return Profile.of( @@ -336,4 +417,6 @@ private static Profile givenProfile(String value) { Profile.MergePrecedence.PROFILE, TextNode.valueOf(value)); } +======= +>>>>>>> 04d9d4a13 (Initial commit) } diff --git a/src/test/java/org/prebid/server/settings/FileApplicationSettingsTest.java b/src/test/java/org/prebid/server/settings/FileApplicationSettingsTest.java index 5c4bd81dff9..05924e7b5aa 100644 --- a/src/test/java/org/prebid/server/settings/FileApplicationSettingsTest.java +++ b/src/test/java/org/prebid/server/settings/FileApplicationSettingsTest.java @@ -1,7 +1,10 @@ package org.prebid.server.settings; +<<<<<<< HEAD import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.node.TextNode; +======= +>>>>>>> 04d9d4a13 (Initial commit) import io.vertx.core.Future; import io.vertx.core.buffer.Buffer; import io.vertx.core.file.FileSystem; @@ -25,7 +28,10 @@ import org.prebid.server.settings.model.BidValidationEnforcement; import org.prebid.server.settings.model.EnabledForRequestType; import org.prebid.server.settings.model.EnforcePurpose; +<<<<<<< HEAD import org.prebid.server.settings.model.Profile; +======= +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.settings.model.Purpose; import org.prebid.server.settings.model.PurposeOneTreatmentInterpretation; import org.prebid.server.settings.model.Purposes; @@ -38,7 +44,10 @@ import java.util.Map; import static java.util.Arrays.asList; +<<<<<<< HEAD import static java.util.Collections.emptyList; +======= +>>>>>>> 04d9d4a13 (Initial commit) import static java.util.Collections.emptySet; import static java.util.Collections.singleton; import static java.util.Collections.singletonList; @@ -65,6 +74,7 @@ public void creationShouldFailIfFileCouldNotBeParsed() { // when and then assertThatIllegalArgumentException() +<<<<<<< HEAD .isThrownBy(() -> new FileApplicationSettings( fileSystem, "ignore", @@ -74,6 +84,10 @@ public void creationShouldFailIfFileCouldNotBeParsed() { "ignore", "ignore", jacksonMapper)); +======= + .isThrownBy(() -> new FileApplicationSettings(fileSystem, "ignore", "ignore", "ignore", "ignore", + "ignore", jacksonMapper)); +>>>>>>> 04d9d4a13 (Initial commit) } @Test @@ -81,6 +95,7 @@ public void getAccountByIdShouldReturnEmptyWhenAccountsAreMissing() { // given given(fileSystem.readFileBlocking(anyString())).willReturn(Buffer.buffer("domains:")); +<<<<<<< HEAD final FileApplicationSettings applicationSettings = new FileApplicationSettings( fileSystem, "ignore", @@ -90,6 +105,11 @@ public void getAccountByIdShouldReturnEmptyWhenAccountsAreMissing() { "ignore", "ignore", jacksonMapper); +======= + final FileApplicationSettings applicationSettings = + new FileApplicationSettings(fileSystem, "ignore", "ignore", "ignore", "ignore", "ignore", + jacksonMapper); +>>>>>>> 04d9d4a13 (Initial commit) // when final Future account = applicationSettings.getAccountById("123", null); @@ -102,6 +122,7 @@ public void getAccountByIdShouldReturnEmptyWhenAccountsAreMissing() { public void getAccountByIdShouldReturnPresentAccount() { // given given(fileSystem.readFileBlocking(anyString())).willReturn(Buffer.buffer( +<<<<<<< HEAD """ accounts: [{ id: 123, @@ -182,6 +203,57 @@ public void getAccountByIdShouldReturnPresentAccount() { "ignore", "ignore", jacksonMapper); +======= + "accounts: [" + + "{" + + "id: 123," + + "status: active," + + "auction: {" + + "price-granularity: low," + + "banner-cache-ttl: 100," + + "video-cache-ttl : 100," + + "truncate-target-attr: 20," + + "default-integration: web," + + "bid-validations: {" + + "banner-creative-max-size: enforce" + + "}," + + "events: {" + + "enabled: true" + + "}" + + "}," + + "privacy: {" + + "gdpr: {" + + "enabled: true," + + "channel-enabled: {" + + "amp: true," + + "web: true," + + "video: true," + + "app: true," + + "dooh: true" + + "}," + + "purposes: {" + + "p1: {enforce-purpose: basic,enforce-vendors: false,vendor-exceptions: [rubicon, appnexus]}," + + "p2: {enforce-purpose: full,enforce-vendors: true,vendor-exceptions: [openx]}" + + "}," + + "special-features: {" + + "sf1: {enforce: true,vendor-exceptions: [rubicon, appnexus]}," + + "sf2: {enforce: false,vendor-exceptions: [openx]}" + + "}," + + "purpose-one-treatment-interpretation: access-allowed" + + "}" + + "}," + + "analytics: {" + + "auction-events: {amp: true}," + + "modules: {some-analytics: {supported-endpoints: [auction]}}" + + "}," + + "cookie-sync: {default-limit: 5,max-limit: 8, coop-sync: {default: true}}" + + "}" + + "]")); + + final FileApplicationSettings applicationSettings = + new FileApplicationSettings(fileSystem, "ignore", "ignore", "ignore", "ignore", "ignore", + jacksonMapper); +>>>>>>> 04d9d4a13 (Initial commit) // when final Future account = applicationSettings.getAccountById("123", null); @@ -238,6 +310,7 @@ public void getAccountByIdShouldReturnEmptyForUnknownAccount() { given(fileSystem.readFileBlocking(anyString())) .willReturn(Buffer.buffer("accounts: [ {id: '123'}, {id: '456'} ]")); +<<<<<<< HEAD final FileApplicationSettings applicationSettings = new FileApplicationSettings( fileSystem, "ignore", @@ -247,6 +320,11 @@ public void getAccountByIdShouldReturnEmptyForUnknownAccount() { "ignore", "ignore", jacksonMapper); +======= + final FileApplicationSettings applicationSettings = + new FileApplicationSettings(fileSystem, "ignore", "ignore", "ignore", "ignore", + "ignore", jacksonMapper); +>>>>>>> 04d9d4a13 (Initial commit) // when final Future account = applicationSettings.getAccountById("789", null); @@ -261,17 +339,24 @@ public void initializeCategoriesShouldThrowExceptionWhenFileCantBeParsed() { given(fileSystem.readDirBlocking(anyString())) .willReturn(singletonList("/home/user/requests/1.json")) .willReturn(singletonList("/home/user/imps/2.json")) +<<<<<<< HEAD .willReturn(singletonList("/home/user/profiles/3-3.json")) +======= +>>>>>>> 04d9d4a13 (Initial commit) .willReturn(singletonList("/home/user/categories/iab_1.json")); given(fileSystem.readFileBlocking(anyString())) .willReturn(Buffer.buffer("accounts:")) // settings file .willReturn(Buffer.buffer("value1")) // stored request .willReturn(Buffer.buffer("value2")) // stored imp +<<<<<<< HEAD .willReturn(Buffer.buffer("{}")) // profile +======= +>>>>>>> 04d9d4a13 (Initial commit) .willReturn(Buffer.buffer("value2")) // stored response .willReturn(Buffer.buffer("{\"iab-1\": 1}")); // categories // when and then +<<<<<<< HEAD assertThatThrownBy(() -> new FileApplicationSettings( fileSystem, "ignore", @@ -281,6 +366,10 @@ public void initializeCategoriesShouldThrowExceptionWhenFileCantBeParsed() { "ignore", "ignore", jacksonMapper)) +======= + assertThatThrownBy(() -> new FileApplicationSettings(fileSystem, "ignore", "ignore", "ignore", "ignore", + "ignore", jacksonMapper)) +>>>>>>> 04d9d4a13 (Initial commit) .isInstanceOf(PreBidException.class) .hasMessage("Failed to decode categories for file /home/user/categories/iab_1.json"); } @@ -291,12 +380,16 @@ public void getCategoriesShouldReturnResultFoundByAdServerAndPublisherSuccessful given(fileSystem.readDirBlocking(anyString())) .willReturn(singletonList("/home/user/requests/1.json")) .willReturn(singletonList("/home/user/imps/2.json")) +<<<<<<< HEAD .willReturn(singletonList("/home/user/profiles/3-3.json")) +======= +>>>>>>> 04d9d4a13 (Initial commit) .willReturn(singletonList("/home/user/categories/iab_1.json")); given(fileSystem.readFileBlocking(anyString())) .willReturn(Buffer.buffer("accounts:")) // settings file .willReturn(Buffer.buffer("value1")) // stored request .willReturn(Buffer.buffer("value2")) // stored imp +<<<<<<< HEAD .willReturn(Buffer.buffer("{}")) // profile .willReturn(Buffer.buffer("value2")) // stored response .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories @@ -310,6 +403,13 @@ public void getCategoriesShouldReturnResultFoundByAdServerAndPublisherSuccessful "ignore", "ignore", jacksonMapper); +======= + .willReturn(Buffer.buffer("value2")) // stored response + .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories + + final ApplicationSettings applicationSettings = new FileApplicationSettings(fileSystem, "ignore", "ignore", + "ignore", "ignore", "ignore", jacksonMapper); +>>>>>>> 04d9d4a13 (Initial commit) // when final Future> result = applicationSettings.getCategories("iab", "1", null); @@ -325,12 +425,16 @@ public void getCategoriesShouldReturnResultFoundByAdServerAndWithoutPublisherSuc given(fileSystem.readDirBlocking(anyString())) .willReturn(singletonList("/home/user/requests/1.json")) .willReturn(singletonList("/home/user/imps/2.json")) +<<<<<<< HEAD .willReturn(singletonList("/home/user/profiles/3-3.json")) +======= +>>>>>>> 04d9d4a13 (Initial commit) .willReturn(singletonList("/home/user/categories/iab.json")); given(fileSystem.readFileBlocking(anyString())) .willReturn(Buffer.buffer("accounts:")) // settings file .willReturn(Buffer.buffer("value1")) // stored request .willReturn(Buffer.buffer("value2")) // stored imp +<<<<<<< HEAD .willReturn(Buffer.buffer("{}")) // profile .willReturn(Buffer.buffer("value2")) // stored response .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories @@ -344,6 +448,13 @@ public void getCategoriesShouldReturnResultFoundByAdServerAndWithoutPublisherSuc "ignore", "ignore", jacksonMapper); +======= + .willReturn(Buffer.buffer("value2")) // stored response + .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories + + final ApplicationSettings applicationSettings = new FileApplicationSettings(fileSystem, "ignore", "ignore", + "ignore", "ignore", "ignore", jacksonMapper); +>>>>>>> 04d9d4a13 (Initial commit) // when final Future> result = applicationSettings.getCategories("iab", null, null); @@ -359,12 +470,16 @@ public void getCategoriesShouldReturnFailedFutureWhenFileWasNotFound() { given(fileSystem.readDirBlocking(anyString())) .willReturn(singletonList("/home/user/requests/1.json")) .willReturn(singletonList("/home/user/imps/2.json")) +<<<<<<< HEAD .willReturn(singletonList("/home/user/profiles/3-3.json")) +======= +>>>>>>> 04d9d4a13 (Initial commit) .willReturn(singletonList("/home/user/categories/iab_1.json")); given(fileSystem.readFileBlocking(anyString())) .willReturn(Buffer.buffer("accounts:")) // settings file .willReturn(Buffer.buffer("value1")) // stored request .willReturn(Buffer.buffer("value2")) // stored imp +<<<<<<< HEAD .willReturn(Buffer.buffer("{}")) // profile .willReturn(Buffer.buffer("value2")) // stored response .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories @@ -378,6 +493,13 @@ public void getCategoriesShouldReturnFailedFutureWhenFileWasNotFound() { "ignore", "ignore", jacksonMapper); +======= + .willReturn(Buffer.buffer("value2")) // stored response + .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories + + final ApplicationSettings applicationSettings = new FileApplicationSettings(fileSystem, "ignore", "ignore", + "ignore", "ignore", "ignore", jacksonMapper); +>>>>>>> 04d9d4a13 (Initial commit) // when final Future> result = applicationSettings.getCategories("iab", "2", null); @@ -394,12 +516,16 @@ public void getStoredDataShouldReturnResultWithNotFoundErrorForNonExistingReques given(fileSystem.readDirBlocking(anyString())) .willReturn(singletonList("/home/user/requests/1.json")) .willReturn(singletonList("/home/user/imps/2.json")) +<<<<<<< HEAD .willReturn(singletonList("/home/user/profiles/3-3.json")) +======= +>>>>>>> 04d9d4a13 (Initial commit) .willReturn(singletonList("/home/user/categories/iab_1.json")); given(fileSystem.readFileBlocking(anyString())) .willReturn(Buffer.buffer("accounts:")) // settings file .willReturn(Buffer.buffer("value1")) // stored request .willReturn(Buffer.buffer("value2")) // stored imp +<<<<<<< HEAD .willReturn(Buffer.buffer("{}")) // profile .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories @@ -415,6 +541,16 @@ public void getStoredDataShouldReturnResultWithNotFoundErrorForNonExistingReques // when final Future> storedRequestResult = +======= + .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories + + final FileApplicationSettings applicationSettings = + new FileApplicationSettings(fileSystem, "ignore", "ignore", "ignore", "ignore", "ignore", + jacksonMapper); + + // when + final Future storedRequestResult = +>>>>>>> 04d9d4a13 (Initial commit) applicationSettings.getStoredData(null, singleton("2"), emptySet(), null); // then @@ -430,13 +566,17 @@ public void getStoredDataShouldReturnResultWithNotFoundErrorForNonExistingImpId( given(fileSystem.readDirBlocking(anyString())) .willReturn(singletonList("/home/user/requests/1.json")) .willReturn(singletonList("/home/user/imps/1.json")) +<<<<<<< HEAD .willReturn(singletonList("/home/user/profiles/3-3.json")) +======= +>>>>>>> 04d9d4a13 (Initial commit) .willReturn(singletonList("/home/user/responses/3.json")); given(fileSystem.readFileBlocking(anyString())) .willReturn(Buffer.buffer("accounts:")) // settings file .willReturn(Buffer.buffer("value1")) // stored request .willReturn(Buffer.buffer("value2")) // stored imp +<<<<<<< HEAD .willReturn(Buffer.buffer("{}")) // profile .willReturn(Buffer.buffer("value3")) // stored response .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories @@ -453,6 +593,17 @@ public void getStoredDataShouldReturnResultWithNotFoundErrorForNonExistingImpId( // when final Future> storedRequestResult = +======= + .willReturn(Buffer.buffer("value3")) // stored response + .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories + + final FileApplicationSettings applicationSettings = + new FileApplicationSettings(fileSystem, "ignore", "ignore", "ignore", "ignore", "ignore", + jacksonMapper); + + // when + final Future storedRequestResult = +>>>>>>> 04d9d4a13 (Initial commit) applicationSettings.getStoredData(null, emptySet(), singleton("2"), null); // then @@ -468,13 +619,17 @@ public void getStoredDataShouldReturnResultWithNoErrorsIfAllIdsArePresent() { given(fileSystem.readDirBlocking(anyString())) .willReturn(singletonList("/home/user/requests/1.json")) .willReturn(singletonList("/home/user/imps/2.json")) +<<<<<<< HEAD .willReturn(singletonList("/home/user/profiles/3-3.json")) +======= +>>>>>>> 04d9d4a13 (Initial commit) .willReturn(singletonList("/home/user/responses/3.json")); given(fileSystem.readFileBlocking(anyString())) .willReturn(Buffer.buffer("accounts:")) // settings file .willReturn(Buffer.buffer("value1")) // stored request .willReturn(Buffer.buffer("value2")) // stored imp +<<<<<<< HEAD .willReturn(Buffer.buffer("{}")) // profile .willReturn(Buffer.buffer("value3")) // stored response .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories @@ -491,6 +646,17 @@ public void getStoredDataShouldReturnResultWithNoErrorsIfAllIdsArePresent() { // when final Future> storedRequestResult = +======= + .willReturn(Buffer.buffer("value3")) // stored response + .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories + + final FileApplicationSettings applicationSettings = + new FileApplicationSettings(fileSystem, "ignore", "ignore", "ignore", "ignore", "ignore", + jacksonMapper); + + // when + final Future storedRequestResult = +>>>>>>> 04d9d4a13 (Initial commit) applicationSettings.getStoredData(null, singleton("1"), singleton("2"), null); // then @@ -504,6 +670,7 @@ public void getStoredDataShouldReturnResultWithNoErrorsIfAllIdsArePresent() { } @Test +<<<<<<< HEAD public void getProfilesShouldReturnResultWithNotFoundErrorForNonExistingIds() throws JsonProcessingException { // given given(fileSystem.readDirBlocking(eq("ignore"))) @@ -604,6 +771,29 @@ public void getProfilesShouldFilterForAccountAndType() throws JsonProcessingExce assertThat(storedRequestResult.result().getStoredIdToRequest()).containsOnlyKeys("1"); assertThat(storedRequestResult.result().getStoredIdToImp()).containsOnlyKeys("2"); assertThat(storedRequestResult.result().getErrors()).isEmpty(); +======= + public void getAmpStoredDataShouldIgnoreImpIdsArgument() { + // given + given(fileSystem.readDirBlocking(anyString())) + .willReturn(singletonList("/home/user/requests/1.json")) + .willReturn(singletonList("/home/user/imps/2.json")); + given(fileSystem.readFileBlocking(anyString())) + .willReturn(Buffer.buffer("accounts:")) // settings file + .willReturn(Buffer.buffer("value1")) // stored request + .willReturn(Buffer.buffer("value2")) // stored imp + .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories + final FileApplicationSettings applicationSettings = + new FileApplicationSettings(fileSystem, "ignore", "ignore", "ignore", "ignore", "ignore", + jacksonMapper); + + // when + final Future storedRequestResult = + applicationSettings.getAmpStoredData(null, emptySet(), singleton("2"), null); + + // then + assertThat(storedRequestResult.result().getErrors()).isNotNull().isEmpty(); + assertThat(storedRequestResult.result().getStoredIdToImp()).isEmpty(); +>>>>>>> 04d9d4a13 (Initial commit) } @Test @@ -612,7 +802,10 @@ public void getStoredResponsesShouldReturnEmptyResultAndErrorsWhenResponseIdsAre given(fileSystem.readDirBlocking(anyString())) .willReturn(singletonList("/home/user/requests/3.json")) .willReturn(singletonList("/home/user/imps/2.json")) +<<<<<<< HEAD .willReturn(singletonList("/home/user/profiles/3-3.json")) +======= +>>>>>>> 04d9d4a13 (Initial commit) .willReturn(singletonList("/home/user/responses/1.json")) .willReturn(singletonList("/home/user/categories")); @@ -620,6 +813,7 @@ public void getStoredResponsesShouldReturnEmptyResultAndErrorsWhenResponseIdsAre .willReturn(Buffer.buffer("accounts:")) // settings file .willReturn(Buffer.buffer("value3")) // requests .willReturn(Buffer.buffer("value2")) // imps +<<<<<<< HEAD .willReturn(Buffer.buffer("{}")) // profile .willReturn(Buffer.buffer("value1")) // responses .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories @@ -632,6 +826,13 @@ public void getStoredResponsesShouldReturnEmptyResultAndErrorsWhenResponseIdsAre "ignore", "ignore", jacksonMapper); +======= + .willReturn(Buffer.buffer("value1")) // responses + .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories + final FileApplicationSettings applicationSettings = + new FileApplicationSettings(fileSystem, "ignore", "ignore", "ignore", "ignore", "ignore", + jacksonMapper); +>>>>>>> 04d9d4a13 (Initial commit) // when final Future storedResponsesResult = @@ -650,7 +851,10 @@ public void getStoredResponsesShouldReturnResultWithMissingIdsIfNotAllIdsArePres given(fileSystem.readDirBlocking(anyString())) .willReturn(singletonList("/home/user/requests/3.json")) .willReturn(singletonList("/home/user/imps/2.json")) +<<<<<<< HEAD .willReturn(singletonList("/home/user/profiles/3-3.json")) +======= +>>>>>>> 04d9d4a13 (Initial commit) .willReturn(singletonList("/home/user/responses/1.json")) .willReturn(singletonList("/home/user/categories/iab_1.json")); @@ -658,6 +862,7 @@ public void getStoredResponsesShouldReturnResultWithMissingIdsIfNotAllIdsArePres .willReturn(Buffer.buffer("accounts:")) // settings file .willReturn(Buffer.buffer("value3")) // requests .willReturn(Buffer.buffer("value2")) // imps +<<<<<<< HEAD .willReturn(Buffer.buffer("{}")) // profile .willReturn(Buffer.buffer("value1")) // responses .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories @@ -671,6 +876,14 @@ public void getStoredResponsesShouldReturnResultWithMissingIdsIfNotAllIdsArePres "ignore", "ignore", jacksonMapper); +======= + .willReturn(Buffer.buffer("value1")) // responses + .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories + + final FileApplicationSettings applicationSettings = + new FileApplicationSettings(fileSystem, "ignore", "ignore", "ignore", "ignore", "ignore", + jacksonMapper); +>>>>>>> 04d9d4a13 (Initial commit) // when final Future storedResponsesResult = @@ -691,7 +904,10 @@ public void getStoredResponsesShouldReturnResultWithoutErrorsIfAllIdsArePresent( given(fileSystem.readDirBlocking(anyString())) .willReturn(singletonList("/home/user/requests/3.json")) .willReturn(singletonList("/home/user/imps/2.json")) +<<<<<<< HEAD .willReturn(singletonList("/home/user/profiles/3-3.json")) +======= +>>>>>>> 04d9d4a13 (Initial commit) .willReturn(singletonList("/home/user/responses/1.json")) .willReturn(singletonList("/home/user/categories/iab_1.json")); @@ -699,6 +915,7 @@ public void getStoredResponsesShouldReturnResultWithoutErrorsIfAllIdsArePresent( .willReturn(Buffer.buffer("accounts:")) // settings file .willReturn(Buffer.buffer("value3")) // requests .willReturn(Buffer.buffer("value2")) // imps +<<<<<<< HEAD .willReturn(Buffer.buffer("{}")) // profile .willReturn(Buffer.buffer("value1")) // responses .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories @@ -712,6 +929,14 @@ public void getStoredResponsesShouldReturnResultWithoutErrorsIfAllIdsArePresent( "ignore", "ignore", jacksonMapper); +======= + .willReturn(Buffer.buffer("value1")) // responses + .willReturn(Buffer.buffer("{\"iab-1\": {\"id\": \"id\"}}")); // categories + + final FileApplicationSettings applicationSettings = + new FileApplicationSettings(fileSystem, "ignore", "ignore", "ignore", "ignore", "ignore", + jacksonMapper); +>>>>>>> 04d9d4a13 (Initial commit) // when final Future storedResponsesResult = @@ -732,6 +957,7 @@ public void storedDataInitializationShouldNotReadFromNonJsonFiles() { given(fileSystem.readFileBlocking(anyString())).willReturn(Buffer.buffer("accounts:")); // settings file // when +<<<<<<< HEAD new FileApplicationSettings( fileSystem, "ignore", @@ -761,6 +987,9 @@ public void profilesInitializationShouldNotReadFromNonJsonFiles() { "ignore", "ignore", "ignore", +======= + new FileApplicationSettings(fileSystem, "ignore", "ignore", "ignore", "ignore", "ignore", +>>>>>>> 04d9d4a13 (Initial commit) jacksonMapper); // then diff --git a/src/test/java/org/prebid/server/settings/HttpApplicationSettingsTest.java b/src/test/java/org/prebid/server/settings/HttpApplicationSettingsTest.java index 0a46bc83d16..fdf84d7c782 100644 --- a/src/test/java/org/prebid/server/settings/HttpApplicationSettingsTest.java +++ b/src/test/java/org/prebid/server/settings/HttpApplicationSettingsTest.java @@ -68,6 +68,7 @@ public class HttpApplicationSettingsTest extends VertxTest { @BeforeEach public void setUp() { +<<<<<<< HEAD httpApplicationSettings = new HttpApplicationSettings( false, ENDPOINT, @@ -76,6 +77,10 @@ public void setUp() { CATEGORY_ENDPOINT, httpClient, jacksonMapper); +======= + httpApplicationSettings = new HttpApplicationSettings(httpClient, jacksonMapper, ENDPOINT, AMP_ENDPOINT, + VIDEO_ENDPOINT, CATEGORY_ENDPOINT, false); +>>>>>>> 04d9d4a13 (Initial commit) final Clock clock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); final TimeoutFactory timeoutFactory = new TimeoutFactory(clock); @@ -86,6 +91,7 @@ public void setUp() { @Test public void creationShouldFailsOnInvalidEndpoint() { assertThatIllegalArgumentException() +<<<<<<< HEAD .isThrownBy(() -> new HttpApplicationSettings( false, "invalid_url", @@ -94,12 +100,17 @@ public void creationShouldFailsOnInvalidEndpoint() { CATEGORY_ENDPOINT, httpClient, jacksonMapper)) +======= + .isThrownBy(() -> new HttpApplicationSettings(httpClient, jacksonMapper, "invalid_url", AMP_ENDPOINT, + VIDEO_ENDPOINT, CATEGORY_ENDPOINT, false)) +>>>>>>> 04d9d4a13 (Initial commit) .withMessage("URL supplied is not valid: invalid_url"); } @Test public void creationShouldFailsOnInvalidAmpEndpoint() { assertThatIllegalArgumentException() +<<<<<<< HEAD .isThrownBy(() -> new HttpApplicationSettings( false, ENDPOINT, @@ -108,12 +119,17 @@ public void creationShouldFailsOnInvalidAmpEndpoint() { CATEGORY_ENDPOINT, httpClient, jacksonMapper)) +======= + .isThrownBy(() -> new HttpApplicationSettings(httpClient, jacksonMapper, ENDPOINT, "invalid_url", + VIDEO_ENDPOINT, CATEGORY_ENDPOINT, false)) +>>>>>>> 04d9d4a13 (Initial commit) .withMessage("URL supplied is not valid: invalid_url"); } @Test public void creationShouldFailsOnInvalidVideoEndpoint() { assertThatIllegalArgumentException() +<<<<<<< HEAD .isThrownBy(() -> new HttpApplicationSettings( false, ENDPOINT, @@ -122,6 +138,10 @@ public void creationShouldFailsOnInvalidVideoEndpoint() { CATEGORY_ENDPOINT, httpClient, jacksonMapper)) +======= + .isThrownBy(() -> new HttpApplicationSettings(httpClient, jacksonMapper, ENDPOINT, AMP_ENDPOINT, + "invalid_url", CATEGORY_ENDPOINT, false)) +>>>>>>> 04d9d4a13 (Initial commit) .withMessage("URL supplied is not valid: invalid_url"); } @@ -156,6 +176,7 @@ public void getAccountByIdShouldReturnFetchedAccount() throws JsonProcessingExce public void getAccountByIdShouldReturnFetchedAccountWithRfc3986CompatibleParams() throws JsonProcessingException { // given givenHttpClientReturnsResponse(200, null); +<<<<<<< HEAD httpApplicationSettings = new HttpApplicationSettings( true, ENDPOINT, @@ -164,6 +185,10 @@ public void getAccountByIdShouldReturnFetchedAccountWithRfc3986CompatibleParams( CATEGORY_ENDPOINT, httpClient, jacksonMapper); +======= + httpApplicationSettings = new HttpApplicationSettings(httpClient, jacksonMapper, + ENDPOINT, AMP_ENDPOINT, VIDEO_ENDPOINT, CATEGORY_ENDPOINT, true); +>>>>>>> 04d9d4a13 (Initial commit) final Account account = Account.builder() .id("someId") @@ -265,8 +290,13 @@ public void getStoredResponsesShouldReturnFailedFutureWithNotSupportedReason() { @Test public void getStoredDataShouldReturnEmptyResultIfEmptyRequestsIdsGiven() { // when +<<<<<<< HEAD final Future> future = httpApplicationSettings.getStoredData(null, emptySet(), emptySet(), null); +======= + final Future future = httpApplicationSettings.getStoredData(null, emptySet(), + emptySet(), null); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(future.succeeded()).isTrue(); @@ -279,7 +309,11 @@ public void getStoredDataShouldReturnEmptyResultIfEmptyRequestsIdsGiven() { @Test public void getStoredDataShouldReturnResultWithErrorIfTimeoutAlreadyExpired() { // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) httpApplicationSettings.getStoredData(null, singleton("id1"), emptySet(), expiredTimeout); // then @@ -312,6 +346,7 @@ public void getStoredDataShouldSendHttpRequestWithExpectedNewParams() { public void getStoredDataShouldSendHttpRequestWithExpectedAppendedParams() { // given givenHttpClientReturnsResponse(200, null); +<<<<<<< HEAD httpApplicationSettings = new HttpApplicationSettings( false, "http://some-domain.com?param1=value1", @@ -320,6 +355,10 @@ public void getStoredDataShouldSendHttpRequestWithExpectedAppendedParams() { CATEGORY_ENDPOINT, httpClient, jacksonMapper); +======= + httpApplicationSettings = new HttpApplicationSettings(httpClient, jacksonMapper, + "http://some-domain.com?param1=value1", AMP_ENDPOINT, VIDEO_ENDPOINT, CATEGORY_ENDPOINT, false); +>>>>>>> 04d9d4a13 (Initial commit) // when httpApplicationSettings.getStoredData(null, singleton("id1"), singleton("id2"), timeout); @@ -335,6 +374,7 @@ public void getStoredDataShouldSendHttpRequestWithExpectedAppendedParams() { public void getStoredDataShouldSendHttpRequestWithRfc3986CompatibleParams() throws URISyntaxException { // given givenHttpClientReturnsResponse(200, null); +<<<<<<< HEAD httpApplicationSettings = new HttpApplicationSettings( true, ENDPOINT, AMP_ENDPOINT, @@ -342,6 +382,10 @@ public void getStoredDataShouldSendHttpRequestWithRfc3986CompatibleParams() thro CATEGORY_ENDPOINT, httpClient, jacksonMapper); +======= + httpApplicationSettings = new HttpApplicationSettings(httpClient, jacksonMapper, + ENDPOINT, AMP_ENDPOINT, VIDEO_ENDPOINT, CATEGORY_ENDPOINT, true); +>>>>>>> 04d9d4a13 (Initial commit) // when httpApplicationSettings.getStoredData(null, Set.of("id1", "id2"), Set.of("id1", "id2"), timeout); @@ -369,7 +413,11 @@ public void getStoredDataShouldReturnResultWithErrorIfHttpClientFails() { givenHttpClientProducesException(new RuntimeException("Request exception")); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) httpApplicationSettings.getStoredData(null, singleton("id1"), emptySet(), timeout); // then @@ -386,7 +434,11 @@ public void getStoredDataShouldReturnResultWithErrorIfHttpClientRespondsNot200St givenHttpClientReturnsResponse(500, "ignored"); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) httpApplicationSettings.getStoredData(null, singleton("id1"), emptySet(), timeout); // then @@ -403,7 +455,11 @@ public void getStoredDataShouldReturnResultWithErrorIfHttpResponseIsMalformed() givenHttpClientReturnsResponse(200, "invalid-response"); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) httpApplicationSettings.getStoredData(null, singleton("id1"), emptySet(), timeout); // then @@ -422,7 +478,11 @@ public void getStoredDataShouldReturnResultWithErrorIfStoredRequestObjectIsMalfo givenHttpClientReturnsResponse(200, malformedStoredRequest); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) httpApplicationSettings.getStoredData(null, singleton("id1"), emptySet(), timeout); // then @@ -442,7 +502,11 @@ public void getStoredDataShouldReturnResultWithErrorIfStoredImpObjectIsMalformed givenHttpClientReturnsResponse(200, malformedStoredRequest); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) httpApplicationSettings.getStoredData(null, singleton("id1"), emptySet(), timeout); // then @@ -462,7 +526,11 @@ public void getStoredDataShouldTolerateMissedId() throws JsonProcessingException givenHttpClientReturnsResponse(200, mapper.writeValueAsString(response)); // when +<<<<<<< HEAD final Future> future = httpApplicationSettings.getStoredData( +======= + final Future future = httpApplicationSettings.getStoredData( +>>>>>>> 04d9d4a13 (Initial commit) null, new HashSet<>(asList("id1", "id2")), new HashSet<>(asList("id3", "id4")), timeout); // then @@ -486,7 +554,11 @@ public void getStoredDataShouldReturnExpectedResult() throws JsonProcessingExcep givenHttpClientReturnsResponse(200, mapper.writeValueAsString(response)); // when +<<<<<<< HEAD final Future> future = +======= + final Future future = +>>>>>>> 04d9d4a13 (Initial commit) httpApplicationSettings.getStoredData(null, singleton("id1"), singleton("id2"), timeout); // then diff --git a/src/test/java/org/prebid/server/settings/S3ApplicationSettingsTest.java b/src/test/java/org/prebid/server/settings/S3ApplicationSettingsTest.java index 13fda67839e..963430b2b60 100644 --- a/src/test/java/org/prebid/server/settings/S3ApplicationSettingsTest.java +++ b/src/test/java/org/prebid/server/settings/S3ApplicationSettingsTest.java @@ -209,7 +209,11 @@ public void getStoredDataShouldReturnFetchedStoredRequest(VertxTestContext conte "storedRequest".getBytes()))); // when +<<<<<<< HEAD final Future> result = target.getStoredData( +======= + final Future result = target.getStoredData( +>>>>>>> 04d9d4a13 (Initial commit) "accountId", Set.of("request"), emptySet(), timeout); // then @@ -237,7 +241,11 @@ public void getStoredDataShouldReturnFetchedStoredImpression(VertxTestContext co "storedImp".getBytes()))); // when +<<<<<<< HEAD final Future> result = target.getStoredData( +======= + final Future result = target.getStoredData( +>>>>>>> 04d9d4a13 (Initial commit) "accountId", emptySet(), Set.of("imp"), timeout); // then @@ -265,8 +273,12 @@ public void getStoredDataShouldReturnFetchedStoredImpressionWithAdUnitPath(Vertx "storedImp".getBytes()))); // when +<<<<<<< HEAD final Future> result = target.getStoredData( "accountId", emptySet(), Set.of("/imp"), timeout); +======= + final Future result = target.getStoredData("accountId", emptySet(), Set.of("/imp"), timeout); +>>>>>>> 04d9d4a13 (Initial commit) // then result.onComplete(context.succeeding(storedDataResult -> { @@ -303,7 +315,11 @@ public void getStoredDataShouldReturnFetchedStoredRequestAndStoredImpression(Ver "storedImp".getBytes()))); // when +<<<<<<< HEAD final Future> result = target.getStoredData( +======= + final Future result = target.getStoredData( +>>>>>>> 04d9d4a13 (Initial commit) "accountId", Set.of("request"), Set.of("imp"), timeout); // then @@ -326,7 +342,11 @@ public void getStoredDataShouldReturnErrorsForNotFoundRequests(VertxTestContext new IllegalStateException("error")))); // when +<<<<<<< HEAD final Future> result = target.getStoredData( +======= + final Future result = target.getStoredData( +>>>>>>> 04d9d4a13 (Initial commit) "accountId", Set.of("request"), emptySet(), timeout); // then @@ -350,7 +370,11 @@ public void getStoredDataShouldReturnErrorsForNotFoundImpressions(VertxTestConte new IllegalStateException("error")))); // when +<<<<<<< HEAD final Future> result = target.getStoredData( +======= + final Future result = target.getStoredData( +>>>>>>> 04d9d4a13 (Initial commit) "accountId", emptySet(), Set.of("imp"), timeout); // then diff --git a/src/test/java/org/prebid/server/settings/SettingsCacheTest.java b/src/test/java/org/prebid/server/settings/SettingsCacheTest.java index bcb23d6a949..fb20c242d57 100644 --- a/src/test/java/org/prebid/server/settings/SettingsCacheTest.java +++ b/src/test/java/org/prebid/server/settings/SettingsCacheTest.java @@ -11,11 +11,19 @@ public class SettingsCacheTest { +<<<<<<< HEAD private SettingsCache settingsCache; @BeforeEach public void setUp() { settingsCache = new SettingsCache<>(10, 10, 0); +======= + private SettingsCache settingsCache; + + @BeforeEach + public void setUp() { + settingsCache = new SettingsCache(10, 10, 0); +>>>>>>> 04d9d4a13 (Initial commit) } @Test diff --git a/src/test/java/org/prebid/server/settings/helper/DatabaseStoredDataResultMapperTest.java b/src/test/java/org/prebid/server/settings/helper/DatabaseStoredDataResultMapperTest.java index 622e5d549bd..640a1f1745d 100644 --- a/src/test/java/org/prebid/server/settings/helper/DatabaseStoredDataResultMapperTest.java +++ b/src/test/java/org/prebid/server/settings/helper/DatabaseStoredDataResultMapperTest.java @@ -1,5 +1,9 @@ package org.prebid.server.settings.helper; +<<<<<<< HEAD +======= +import io.vertx.core.json.JsonObject; +>>>>>>> 04d9d4a13 (Initial commit) import io.vertx.sqlclient.Row; import io.vertx.sqlclient.RowIterator; import io.vertx.sqlclient.RowSet; @@ -12,6 +16,10 @@ import java.util.Arrays; import java.util.Iterator; +<<<<<<< HEAD +======= +import java.util.stream.IntStream; +>>>>>>> 04d9d4a13 (Initial commit) import static java.util.Collections.emptySet; import static java.util.Collections.singleton; @@ -35,8 +43,12 @@ public void mapShouldReturnEmptyStoredResultWithErrorWhenResultSetHasEmptyResult givenRowSet(); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map( rowSet, null, emptySet(), emptySet()); +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map(rowSet, null, emptySet(), emptySet()); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(result.getStoredIdToRequest()).isEmpty(); @@ -51,7 +63,11 @@ public void mapShouldReturnEmptyStoredResultWithErrorWhenResultSetHasEmptyResult givenRowSet(); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map( +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map( +>>>>>>> 04d9d4a13 (Initial commit) rowSet, null, singleton("reqId"), @@ -70,7 +86,11 @@ public void mapShouldReturnEmptyStoredResultWithErrorWhenResultSetHasLessColumns givenRowSet(givenRow("accountId", "id1", "data")); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map( +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map( +>>>>>>> 04d9d4a13 (Initial commit) rowSet, "accountId", singleton("reqId"), @@ -89,7 +109,11 @@ public void mapShouldReturnEmptyStoredResultWithErrorWhenResultSetHasUnexpectedC givenRowSet(givenRow("accountId", "id1", "data", 123)); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map( +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map( +>>>>>>> 04d9d4a13 (Initial commit) rowSet, "accountId", singleton("reqId"), @@ -110,7 +134,11 @@ public void mapShouldSkipStoredResultWithInvalidType() { givenRow("accountId", "id1", "data2", "invalid")); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map( +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map( +>>>>>>> 04d9d4a13 (Initial commit) rowSet, "accountId", singleton("id1"), @@ -129,7 +157,11 @@ public void mapShouldReturnStoredResultWithErrorForMissingId() { givenRowSet(givenRow("accountId", "id1", "data1", "request")); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map( +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map( +>>>>>>> 04d9d4a13 (Initial commit) rowSet, "accountId", singleton("id1"), @@ -151,7 +183,11 @@ public void mapShouldReturnEmptyStoredResultWithErrorsForMissingIdsIfAccountDiff givenRow("accountId", "id2", "data2", "imp")); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map( +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map( +>>>>>>> 04d9d4a13 (Initial commit) rowSet, "otherAccountId", singleton("id1"), @@ -174,7 +210,11 @@ public void mapShouldReturnEmptyStoredResultWithErrorIfMultipleStoredItemsFoundB givenRow("accountId2", "id1", "data2", "request")); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map( +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map( +>>>>>>> 04d9d4a13 (Initial commit) rowSet, null, singleton("id1"), @@ -197,7 +237,11 @@ public void mapShouldReturnEmptyStoredResultWithErrorIfMultipleStoredItemsFoundB givenRow("accountId2", "id2", "data-otherAccountId", "imp")); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map( +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map( +>>>>>>> 04d9d4a13 (Initial commit) rowSet, "otherAccountId", singleton("id1"), @@ -222,7 +266,11 @@ public void mapShouldReturnExpectedStoredResultForGivenAccount() { givenRow("otherAccountId", "id2", "data-otherAccountId", "imp")); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map( +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map( +>>>>>>> 04d9d4a13 (Initial commit) rowSet, "accountId", singleton("id1"), @@ -242,7 +290,11 @@ public void mapWithoutParamsShouldReturnEmptyStoredResultWithErrorWhenResultSetH givenRowSet(); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map(rowSet); +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map(rowSet); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(result.getStoredIdToRequest()).isEmpty(); @@ -259,7 +311,11 @@ public void mapWithoutParamsShouldSkipStoredResultWithInvalidType() { givenRow("accountId", "id2", "data2", "invalid")); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map(rowSet); +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map(rowSet); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(result.getStoredIdToRequest()).hasSize(1) @@ -274,7 +330,11 @@ public void mapWithoutParamsShouldReturnEmptyStoredResultWithErrorWhenResultSetH givenRowSet(givenRow("accountId", "id1", "data")); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map(rowSet); +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map(rowSet); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(result.getStoredIdToRequest()).isEmpty(); @@ -289,7 +349,11 @@ public void mapWithoutParamsShouldReturnEmptyStoredResultWhenResultSetHasInvalid givenRowSet(givenRow("accountId", "id1", "data", 123)); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map(rowSet); +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map(rowSet); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(result.getStoredIdToRequest()).isEmpty(); @@ -305,7 +369,11 @@ public void mapWithoutParamsShouldReturnExpectedStoredResult() { givenRow("accountId", "id2", "data2", "imp")); // when +<<<<<<< HEAD final StoredDataResult result = DatabaseStoredDataResultMapper.map(rowSet); +======= + final StoredDataResult result = DatabaseStoredDataResultMapper.map(rowSet); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(result.getStoredIdToRequest()).hasSize(1) @@ -322,7 +390,13 @@ private void givenRowSet(Row... rows) { private Row givenRow(Object... values) { final Row row = mock(Row.class, withSettings().strictness(LENIENT)); given(row.getValue(anyInt())).willAnswer(invocation -> values[(Integer) invocation.getArgument(0)]); +<<<<<<< HEAD given(row.size()).willReturn(values.length); +======= + final JsonObject json = new JsonObject(); + IntStream.range(0, values.length).forEach(i -> json.put(String.valueOf(i), values[i])); + given(row.toJson()).willReturn(json); +>>>>>>> 04d9d4a13 (Initial commit) return row; } diff --git a/src/test/java/org/prebid/server/settings/helper/DatabaseStoredResponseResultMapperTest.java b/src/test/java/org/prebid/server/settings/helper/DatabaseStoredResponseResultMapperTest.java index 124f8638125..e6cf20d7aec 100644 --- a/src/test/java/org/prebid/server/settings/helper/DatabaseStoredResponseResultMapperTest.java +++ b/src/test/java/org/prebid/server/settings/helper/DatabaseStoredResponseResultMapperTest.java @@ -1,5 +1,9 @@ package org.prebid.server.settings.helper; +<<<<<<< HEAD +======= +import io.vertx.core.json.JsonObject; +>>>>>>> 04d9d4a13 (Initial commit) import io.vertx.sqlclient.Row; import io.vertx.sqlclient.RowIterator; import io.vertx.sqlclient.RowSet; @@ -14,6 +18,10 @@ import java.util.Arrays; import java.util.Iterator; import java.util.Set; +<<<<<<< HEAD +======= +import java.util.stream.IntStream; +>>>>>>> 04d9d4a13 (Initial commit) import static java.util.Collections.emptySet; import static java.util.Collections.singleton; @@ -108,7 +116,13 @@ private void givenRowSet(Row... rows) { private Row givenRow(Object... values) { final Row row = mock(Row.class, withSettings().strictness(LENIENT)); given(row.getValue(anyInt())).willAnswer(invocation -> values[(Integer) invocation.getArgument(0)]); +<<<<<<< HEAD given(row.size()).willReturn(values.length); +======= + final JsonObject json = new JsonObject(); + IntStream.range(0, values.length).forEach(i -> json.put(String.valueOf(i), values[i])); + given(row.toJson()).willReturn(json); +>>>>>>> 04d9d4a13 (Initial commit) return row; } diff --git a/src/test/java/org/prebid/server/settings/helper/StoredItemResolverTest.java b/src/test/java/org/prebid/server/settings/helper/StoredItemResolverTest.java index 039deac061b..fb360e10117 100644 --- a/src/test/java/org/prebid/server/settings/helper/StoredItemResolverTest.java +++ b/src/test/java/org/prebid/server/settings/helper/StoredItemResolverTest.java @@ -2,6 +2,10 @@ import org.junit.jupiter.api.Test; import org.prebid.server.exception.PreBidException; +<<<<<<< HEAD +======= +import org.prebid.server.settings.model.StoredDataType; +>>>>>>> 04d9d4a13 (Initial commit) import org.prebid.server.settings.model.StoredItem; import java.util.HashSet; @@ -17,39 +21,66 @@ public class StoredItemResolverTest { public void resolveShouldFailWhenNoStoredData() { // when and then assertThatExceptionOfType(PreBidException.class) +<<<<<<< HEAD .isThrownBy(() -> StoredItemResolver.resolve("stored imp", null, "id", emptySet())) +======= + .isThrownBy(() -> StoredItemResolver.resolve(StoredDataType.imp, null, "id", emptySet())) +>>>>>>> 04d9d4a13 (Initial commit) .withMessage("No stored imp found for id: id"); } @Test public void resolveShouldFailWhenMultipleStoredDataButNoAccountInRequest() { // given +<<<<<<< HEAD final Set> storedItems = givenMultipleStoredData(); // when and then assertThatExceptionOfType(PreBidException.class) .isThrownBy(() -> StoredItemResolver.resolve("stored imp", null, "id", storedItems)) +======= + final Set storedItems = givenMultipleStoredData(); + + // when and then + assertThatExceptionOfType(PreBidException.class) + .isThrownBy(() -> StoredItemResolver.resolve(StoredDataType.imp, null, "id", storedItems)) +>>>>>>> 04d9d4a13 (Initial commit) .withMessage("Multiple stored imps found for id: id but no account was specified"); } @Test public void resolveShouldFailWhenMultipleStoredDataButAccountDiffers() { // given +<<<<<<< HEAD final Set> storedItems = givenMultipleStoredData(); // when and then assertThatExceptionOfType(PreBidException.class) .isThrownBy(() -> StoredItemResolver.resolve("stored imp", "1003", "id", storedItems)) +======= + final Set storedItems = givenMultipleStoredData(); + + // when and then + assertThatExceptionOfType(PreBidException.class) + .isThrownBy(() -> StoredItemResolver.resolve(StoredDataType.imp, "1003", "id", storedItems)) +>>>>>>> 04d9d4a13 (Initial commit) .withMessage("No stored imp found among multiple id: id for account: 1003"); } @Test public void resolveShouldReturnResultWhenMultipleStoredDataForAppropriateAccount() { // given +<<<<<<< HEAD final Set> storedItems = givenMultipleStoredData(); // when final StoredItem storedItem = StoredItemResolver.resolve("stored imp", "1002", "id", storedItems); +======= + final Set storedItems = givenMultipleStoredData(); + + // when + final StoredItem storedItem = StoredItemResolver.resolve(StoredDataType.imp, "1002", "id", storedItems); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(storedItem).isEqualTo(StoredItem.of("1002", "data2")); @@ -58,11 +89,19 @@ public void resolveShouldReturnResultWhenMultipleStoredDataForAppropriateAccount @Test public void resolveShouldReturnResultWhenSingleStoredDataButNoAccountInRequest() { // given +<<<<<<< HEAD final Set> storedItems = new HashSet<>(); storedItems.add(StoredItem.of("1001", "data1")); // when final StoredItem storedItem = StoredItemResolver.resolve("stored imp", "1001", "", storedItems); +======= + final Set storedItems = new HashSet<>(); + storedItems.add(StoredItem.of("1001", "data1")); + + // when + final StoredItem storedItem = StoredItemResolver.resolve(StoredDataType.imp, "1001", "", storedItems); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(storedItem).isEqualTo(StoredItem.of("1001", "data1")); @@ -71,11 +110,19 @@ public void resolveShouldReturnResultWhenSingleStoredDataButNoAccountInRequest() @Test public void resolveShouldReturnResultWhenSingleStoredDataButNoAccountInStoredData() { // given +<<<<<<< HEAD final Set> storedItems = new HashSet<>(); storedItems.add(StoredItem.of(null, "data1")); // when final StoredItem storedItem = StoredItemResolver.resolve("stored imp", "1001", "id", storedItems); +======= + final Set storedItems = new HashSet<>(); + storedItems.add(StoredItem.of(null, "data1")); + + // when + final StoredItem storedItem = StoredItemResolver.resolve(StoredDataType.imp, "1001", "id", storedItems); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(storedItem).isEqualTo(StoredItem.of(null, "data1")); @@ -84,11 +131,19 @@ public void resolveShouldReturnResultWhenSingleStoredDataButNoAccountInStoredDat @Test public void resolveShouldReturnResultWhenSingleStoredDataButNoAccountBothInRequestAndStoredData() { // given +<<<<<<< HEAD final Set> storedItems = new HashSet<>(); storedItems.add(StoredItem.of(null, "data1")); // when final StoredItem storedItem = StoredItemResolver.resolve("stored imp", null, "id", storedItems); +======= + final Set storedItems = new HashSet<>(); + storedItems.add(StoredItem.of(null, "data1")); + + // when + final StoredItem storedItem = StoredItemResolver.resolve(StoredDataType.imp, null, "id", storedItems); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(storedItem).isEqualTo(StoredItem.of(null, "data1")); @@ -97,10 +152,17 @@ public void resolveShouldReturnResultWhenSingleStoredDataButNoAccountBothInReque @Test public void resolveShouldFailWhenSingleStoredDataForAppropriateAccount() { // given +<<<<<<< HEAD final Set> storedItems = givenSingleStoredData(); // when final StoredItem storedItem = StoredItemResolver.resolve("stored imp", "1001", "id", storedItems); +======= + final Set storedItems = givenSingleStoredData(); + + // when + final StoredItem storedItem = StoredItemResolver.resolve(StoredDataType.imp, "1001", "id", storedItems); +>>>>>>> 04d9d4a13 (Initial commit) // then assertThat(storedItem).isEqualTo(StoredItem.of("1001", "data1")); @@ -109,6 +171,7 @@ public void resolveShouldFailWhenSingleStoredDataForAppropriateAccount() { @Test public void resolveShouldFailWhenSingleStoredDataButAccountDiffers() { // given +<<<<<<< HEAD final Set> storedItems = givenSingleStoredData(); // when and then @@ -119,12 +182,29 @@ public void resolveShouldFailWhenSingleStoredDataButAccountDiffers() { private static Set> givenSingleStoredData() { final Set> storedItems = new HashSet<>(); +======= + final Set storedItems = givenSingleStoredData(); + + // when and then + assertThatExceptionOfType(PreBidException.class) + .isThrownBy(() -> StoredItemResolver.resolve(StoredDataType.imp, "1002", "id", storedItems)) + .withMessage("No stored imp found for id: id for account: 1002"); + } + + private static Set givenSingleStoredData() { + final Set storedItems = new HashSet<>(); +>>>>>>> 04d9d4a13 (Initial commit) storedItems.add(StoredItem.of("1001", "data1")); return storedItems; } +<<<<<<< HEAD private static Set> givenMultipleStoredData() { final Set> storedItems = new HashSet<>(); +======= + private static Set givenMultipleStoredData() { + final Set storedItems = new HashSet<>(); +>>>>>>> 04d9d4a13 (Initial commit) storedItems.add(StoredItem.of("1001", "data1")); storedItems.add(StoredItem.of("1002", "data2")); return storedItems; diff --git a/src/test/java/org/prebid/server/settings/service/DatabasePeriodicRefreshServiceTest.java b/src/test/java/org/prebid/server/settings/service/DatabasePeriodicRefreshServiceTest.java index bae78c111b4..a1b6f43bb92 100644 --- a/src/test/java/org/prebid/server/settings/service/DatabasePeriodicRefreshServiceTest.java +++ b/src/test/java/org/prebid/server/settings/service/DatabasePeriodicRefreshServiceTest.java @@ -41,7 +41,11 @@ public class DatabasePeriodicRefreshServiceTest { @Mock +<<<<<<< HEAD private CacheNotificationListener cacheNotificationListener; +======= + private CacheNotificationListener cacheNotificationListener; +>>>>>>> 04d9d4a13 (Initial commit) @Mock private Vertx vertx; @Mock(strictness = LENIENT) @@ -56,9 +60,15 @@ public class DatabasePeriodicRefreshServiceTest { @BeforeEach public void setUp() { +<<<<<<< HEAD final StoredDataResult initialResult = StoredDataResult.of(singletonMap("id1", "value1"), singletonMap("id2", "value2"), emptyList()); final StoredDataResult updateResult = StoredDataResult.of(singletonMap("id1", "null"), +======= + final StoredDataResult initialResult = StoredDataResult.of(singletonMap("id1", "value1"), + singletonMap("id2", "value2"), emptyList()); + final StoredDataResult updateResult = StoredDataResult.of(singletonMap("id1", "null"), +>>>>>>> 04d9d4a13 (Initial commit) singletonMap("id2", "changed_value"), emptyList()); given(databaseClient.executeQuery(eq("init_query"), anyList(), any(), any())) diff --git a/src/test/java/org/prebid/server/settings/service/HttpPeriodicRefreshServiceTest.java b/src/test/java/org/prebid/server/settings/service/HttpPeriodicRefreshServiceTest.java index 3cb36048ffb..0edd50234d8 100644 --- a/src/test/java/org/prebid/server/settings/service/HttpPeriodicRefreshServiceTest.java +++ b/src/test/java/org/prebid/server/settings/service/HttpPeriodicRefreshServiceTest.java @@ -42,7 +42,11 @@ public class HttpPeriodicRefreshServiceTest extends VertxTest { private static final String ENDPOINT_URL = "http://stored-requests.prebid.com"; @Mock +<<<<<<< HEAD private CacheNotificationListener cacheNotificationListener; +======= + private CacheNotificationListener cacheNotificationListener; +>>>>>>> 04d9d4a13 (Initial commit) @Mock(strictness = LENIENT) private HttpClient httpClient; @Mock @@ -165,6 +169,7 @@ public void shouldModifyEndpointUrlCorrectlyIfUrlHasParameters() { verify(httpClient).get(startsWith("http://stored-requests.prebid.com?amp=true&last-modified="), anyLong()); } +<<<<<<< HEAD private static void createAndInitService(CacheNotificationListener notificationListener, String url, long refreshPeriod, @@ -172,6 +177,11 @@ private static void createAndInitService(CacheNotificationListener notif Vertx vertx, HttpClient httpClient) { +======= + private static void createAndInitService(CacheNotificationListener notificationListener, + String url, long refreshPeriod, long timeout, + Vertx vertx, HttpClient httpClient) { +>>>>>>> 04d9d4a13 (Initial commit) final HttpPeriodicRefreshService httpPeriodicRefreshService = new HttpPeriodicRefreshService( url, refreshPeriod, timeout, notificationListener, vertx, httpClient, jacksonMapper); httpPeriodicRefreshService.initialize(Promise.promise()); diff --git a/src/test/java/org/prebid/server/settings/service/S3PeriodicRefreshServiceTest.java b/src/test/java/org/prebid/server/settings/service/S3PeriodicRefreshServiceTest.java index b46587f01a8..8b634c131b3 100644 --- a/src/test/java/org/prebid/server/settings/service/S3PeriodicRefreshServiceTest.java +++ b/src/test/java/org/prebid/server/settings/service/S3PeriodicRefreshServiceTest.java @@ -51,7 +51,11 @@ public class S3PeriodicRefreshServiceTest extends VertxTest { private S3AsyncClient s3AsyncClient; @Mock +<<<<<<< HEAD private CacheNotificationListener cacheNotificationListener; +======= + private CacheNotificationListener cacheNotificationListener; +>>>>>>> 04d9d4a13 (Initial commit) @Mock private Clock clock; diff --git a/src/test/resources/org/prebid/server/functional/db_mysql_schema.sql b/src/test/resources/org/prebid/server/functional/db_mysql_schema.sql index 0f4d026337f..227df13d596 100644 --- a/src/test/resources/org/prebid/server/functional/db_mysql_schema.sql +++ b/src/test/resources/org/prebid/server/functional/db_mysql_schema.sql @@ -42,6 +42,7 @@ CREATE TABLE stored_responses storedBidResponse varchar(1024) ); +<<<<<<< HEAD CREATE TABLE profiles ( accountId varchar(40) NOT NULL, @@ -51,5 +52,7 @@ CREATE TABLE profiles type enum ('request', 'imp', '', 'unknown') ); +======= +>>>>>>> 04d9d4a13 (Initial commit) -- set session wait timeout to 1 minute SET SESSION wait_timeout = 60000; diff --git a/src/test/resources/org/prebid/server/it/openrtb2/coinzilla/test-coinzilla-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/coinzilla/test-coinzilla-bid-response.json index 5eb319eccfe..8136716f754 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/coinzilla/test-coinzilla-bid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/coinzilla/test-coinzilla-bid-response.json @@ -1,3 +1,4 @@ +<<<<<<< HEAD { "id": "request_id", "seatbid": [ @@ -17,4 +18,25 @@ ] } ] +======= +{ + "id": "request_id", + "seatbid": [ + { + "bid": [ + { + "id": "bid_id", + "impid": "imp_id", + "price": 6.66, + "adid": "adid001", + "crid": "crid001", + "cid": "cid001", + "adm": "adm001", + "h": 250, + "w": 300 + } + ] + } + ] +>>>>>>> 04d9d4a13 (Initial commit) } \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/impactify/test-impactify-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/impactify/test-impactify-bid-response.json index 2dd18dff6c6..0f695fcb5aa 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/impactify/test-impactify-bid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/impactify/test-impactify-bid-response.json @@ -1,3 +1,4 @@ +<<<<<<< HEAD { "id": "tid", "seatbid": [ @@ -16,3 +17,23 @@ } ] } +======= +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "crid": "24080", + "adid": "2068416", + "price": 0.01, + "id": "bid_id", + "impid": "imp_id", + "cid": "8048" + } + ], + "type": "banner" + } + ] +} +>>>>>>> 04d9d4a13 (Initial commit) diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-request.json b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-request.json index 6d99b8b6278..1af2908be8a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-request.json @@ -20,6 +20,7 @@ "ext": { "gdpr": 0 } +<<<<<<< HEAD }, "ext": { "ixdiag": { @@ -29,5 +30,7 @@ "ren": false, "version": "6.29.1" } +======= +>>>>>>> 04d9d4a13 (Initial commit) } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request.json index 0b9d5fb0aaf..8da58f22ac9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request.json @@ -62,6 +62,7 @@ } }, "ixdiag": { +<<<<<<< HEAD "pbsv": "{{ pbs.java.version }}", "pbsp": "java", "msd": 2, @@ -69,6 +70,9 @@ "mfu": 0, "ren": false, "version": "6.29.1" +======= + "pbsv": "{{ pbs.java.version }}" +>>>>>>> 04d9d4a13 (Initial commit) } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-onetag-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-onetag-bid-request.json index b0d37448267..2a4aab56142 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-onetag-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-onetag-bid-request.json @@ -12,6 +12,7 @@ "displaymanagerver": "2.0.0", "tagid": "possibleTagId", "ext": { +<<<<<<< HEAD "tid": "${json-unit.any-string}", "bidder": { "pubId": "386276e072", @@ -20,6 +21,10 @@ "key2": "value2" } } +======= + "key1": "value1", + "key2": "value2" +>>>>>>> 04d9d4a13 (Initial commit) } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-request.json b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-request.json index b02d4d0a642..72f18df50aa 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-request.json @@ -14,8 +14,12 @@ "siteId": 1, "pageId": 2, "formatId": 3, +<<<<<<< HEAD "networkId": 73, "programmaticGuaranteed": true +======= + "networkId": 73 +>>>>>>> 04d9d4a13 (Initial commit) } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-request.json index f53c88fe858..d463cd3443a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-request.json @@ -10,7 +10,11 @@ }, "ext": { "tid": "${json-unit.any-string}", +<<<<<<< HEAD "smartadserver": { +======= + "bidder": { +>>>>>>> 04d9d4a13 (Initial commit) "siteId": 1, "pageId": 2, "formatId": 3, diff --git a/src/test/resources/org/prebid/server/it/test-application.properties b/src/test/resources/org/prebid/server/it/test-application.properties index 33a5bccfe4d..fc81488d2a7 100644 --- a/src/test/resources/org/prebid/server/it/test-application.properties +++ b/src/test/resources/org/prebid/server/it/test-application.properties @@ -104,8 +104,11 @@ adapters.adxcg.enabled=true adapters.adxcg.endpoint=http://localhost:8090/adxcg-exchange adapters.adyoulike.enabled=true adapters.adyoulike.endpoint=http://localhost:8090/adyoulike-exchange +<<<<<<< HEAD adapters.afront.enabled=true adapters.afront.endpoint=http://localhost:8090/afront-exchange +======= +>>>>>>> 04d9d4a13 (Initial commit) adapters.aidem.enabled=true adapters.aidem.endpoint=http://localhost:8090/aidem-exchange adapters.aja.enabled=true @@ -493,7 +496,10 @@ adapters.smaato.enabled=true adapters.smaato.endpoint=http://localhost:8090/smaato-exchange adapters.smartadserver.enabled=true adapters.smartadserver.endpoint=http://localhost:8090/smartadserver-exchange +<<<<<<< HEAD adapters.smartadserver.secondary-endpoint=http://localhost:8090/smartadserver-secondary-exchange +======= +>>>>>>> 04d9d4a13 (Initial commit) adapters.smartadserver.aliases.equativ.enabled=true adapters.smartrtb.enabled=true adapters.smartrtb.endpoint=http://localhost:8090/smartrtb-exchange/ @@ -605,8 +611,11 @@ adapters.xeworks.enabled=true adapters.xeworks.endpoint=http://localhost:8090/xeworks-exchange adapters.xeworks.aliases.connektai.enabled=true adapters.xeworks.aliases.connektai.endpoint=http://localhost:8090/connektai-exchange +<<<<<<< HEAD adapters.xeworks.aliases.adipolo.enabled=true adapters.xeworks.aliases.adipolo.endpoint=http://localhost:8090/adipolo-exchange +======= +>>>>>>> 04d9d4a13 (Initial commit) adapters.vidazoo.enabled=true adapters.vidazoo.endpoint=http://localhost:8090/vidazoo-exchange/ adapters.vidazoo.aliases.progx.enabled=true @@ -678,7 +687,10 @@ metrics.accounts.default-verbosity=none settings.filesystem.settings-filename=src/test/resources/org/prebid/server/it/test-app-settings.yaml settings.filesystem.stored-requests-dir=src/test/resources/org/prebid/server/it/storedrequests settings.filesystem.stored-imps-dir=src/test/resources/org/prebid/server/it/storedimps +<<<<<<< HEAD settings.filesystem.profiles-dir=src/test/resources/org/prebid/server/it/profiles +======= +>>>>>>> 04d9d4a13 (Initial commit) settings.filesystem.stored-responses-dir=src/test/resources/org/prebid/server/it/storedresponses settings.filesystem.categories-dir=src/test/resources/org/prebid/server/it/categories settings.in-memory-cache.notification-endpoints-enabled=true