Skip to content

Commit

Permalink
CCPA warnings fix and unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Veronika Solovei committed Mar 15, 2021
1 parent 21f2fc5 commit ae5620e
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 44 deletions.
5 changes: 4 additions & 1 deletion endpoints/openrtb2/amp_auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,10 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
ao.Errors = append(ao.Errors, fmt.Errorf("AMP response: failed to unpack OpenRTB response.ext, debug info cannot be forwarded: %v", eRErr))
}

warnings := make(map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage)
warnings := extResponse.Warnings
if warnings == nil {
warnings = make(map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage)
}
for _, v := range errortypes.WarningOnly(errL) {
bidderErr := openrtb_ext.ExtBidderMessage{
Code: errortypes.ReadCode(v),
Expand Down
2 changes: 2 additions & 0 deletions endpoints/openrtb2/auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
if errortypes.ContainsFatalError(errL) && writeError(errL, w, &labels) {
return
}
warnings := errortypes.WarningOnly(errL)

ctx := context.Background()

Expand Down Expand Up @@ -178,6 +179,7 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
RequestType: labels.RType,
StartTime: start,
LegacyLabels: labels,
Warnings: warnings,
}

response, err := deps.ex.HoldAuction(ctx, auctionRequest, nil)
Expand Down
48 changes: 48 additions & 0 deletions endpoints/openrtb2/auction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2077,6 +2077,54 @@ func TestValidateBidders(t *testing.T) {
}
}

func TestAuctionWarnings(t *testing.T) {
reqBody := validRequest(t, "us-privacy-invalid.json")
deps := &endpointDeps{
&warningsCheckExchange{},
newParamsValidator(t),
&mockStoredReqFetcher{},
empty_fetcher.EmptyFetcher{},
empty_fetcher.EmptyFetcher{},
&config.Configuration{MaxRequestSize: int64(len(reqBody))},
newTestMetrics(),
analyticsConf.NewPBSAnalytics(&config.Analytics{}),
map[string]string{},
false,
[]byte{},
openrtb_ext.BuildBidderMap(),
nil,
nil,
hardcodedResponseIPValidator{response: true},
}

req := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(reqBody))
recorder := httptest.NewRecorder()

deps.Auction(recorder, req, nil)

if recorder.Code != http.StatusOK {
t.Errorf("Endpoint should return a 200")
}
warnings := deps.ex.(*warningsCheckExchange).auctionRequest.Warnings
assert.Len(t, warnings, 1, "One warning should be returned from exchange")

actualWarning := warnings[0].(*errortypes.Warning)
expectedMessage := "CCPA consent is invalid and will be ignored. (request.regs.ext.us_privacy must contain 4 characters)"
assert.Equal(t, expectedMessage, actualWarning.Message, "Warning message is incorrect")

assert.Equal(t, errortypes.InvalidPrivacyConsentWarningCode, actualWarning.WarningCode, "Warning code is incorrect")
}

// warningsCheckExchange is a well-behaved exchange which stores all incoming warnings.
type warningsCheckExchange struct {
auctionRequest exchange.AuctionRequest
}

func (e *warningsCheckExchange) HoldAuction(ctx context.Context, r exchange.AuctionRequest, debugLog *exchange.DebugLog) (*openrtb.BidResponse, error) {
e.auctionRequest = r
return nil, nil
}

// nobidExchange is a well-behaved exchange which always bids "no bid".
type nobidExchange struct {
gotRequest *openrtb.BidRequest
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"description": "Well formed amp request with invalid CCPA consent value",
"mockBidRequest": {
"id": "b9c97a4b-cbc4-483d-b2c4-58a19ed5cfc5",
"site": {
"page": "prebid.org",
"publisher": {
"id": "a3de7af2-a86a-4043-a77b-c7e86744155e"
}
},
"source": {
"tid": "b9c97a4b-cbc4-483d-b2c4-58a19ed5cfc5"
},
"tmax": 1000,
"imp": [
{
"id": "/19968336/header-bid-tag-0",
"ext": {
"appnexus": {
"placementId": 12883451
}
},
"banner": {
"format": [
{
"w": 300,
"h": 250
},
{
"w": 300,
"h": 300
}
]
}
}
],
"regs": {
"ext": {
"us_privacy": "{invalid}"
}
},
"user": {
"ext": {}
}
},
"expectedBidResponse": {
"id":"b9c97a4b-cbc4-483d-b2c4-58a19ed5cfc5",
"bidid":"test bid id",
"nbr":0
},
"expectedReturnCode": 200
}
17 changes: 15 additions & 2 deletions exchange/exchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ type AuctionRequest struct {
UserSyncs IdFetcher
RequestType metrics.RequestType
StartTime time.Time
Warnings []error

// LegacyLabels is included here for temporary compatability with cleanOpenRTBRequests
// in HoldAuction until we get to factoring it away. Do not use for anything new.
Expand Down Expand Up @@ -237,13 +238,25 @@ func (e *exchange) HoldAuction(ctx context.Context, r AuctionRequest, debugLog *
}
}

generalWarningKey := openrtb_ext.BidderName(openrtb_ext.BidderReservedGeneral)

if !r.Account.DebugAllow && requestDebugInfo {
accountDebugDisabledWarning := openrtb_ext.ExtBidderMessage{
Code: errortypes.AccountLevelDebugDisabledWarningCode,
Message: "debug turned off for account",
}
bn := openrtb_ext.BidderName(openrtb_ext.BidderReservedGeneral)
bidResponseExt.Warnings[bn] = append(bidResponseExt.Warnings[bn], accountDebugDisabledWarning)
bidResponseExt.Warnings[generalWarningKey] = append(bidResponseExt.Warnings[generalWarningKey], accountDebugDisabledWarning)
}

if len(r.Warnings) != 0 {
for _, warning := range r.Warnings {
typedWarning := warning.(*errortypes.Warning)
generalWarning := openrtb_ext.ExtBidderMessage{
Code: typedWarning.WarningCode,
Message: typedWarning.Message,
}
bidResponseExt.Warnings[generalWarningKey] = append(bidResponseExt.Warnings[generalWarningKey], generalWarning)
}
}

// Build the response
Expand Down
116 changes: 75 additions & 41 deletions exchange/exchange_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/prebid/prebid-server/errortypes"
"io/ioutil"
"net/http"
"net/http/httptest"
Expand Down Expand Up @@ -180,59 +181,68 @@ func TestDebugBehaviour(t *testing.T) {
}

type aTest struct {
desc string
in inTest
out outTest
debugData debugData
desc string
in inTest
out outTest
debugData debugData
generalWarnings bool
}
testCases := []aTest{
{
desc: "test flag equals zero, ext debug flag false, no debug info expected",
in: inTest{test: 0, debug: false},
out: outTest{debugInfoIncluded: false},
debugData: debugData{true, true},
desc: "test flag equals zero, ext debug flag false, no debug info expected",
in: inTest{test: 0, debug: false},
out: outTest{debugInfoIncluded: false},
debugData: debugData{true, true},
generalWarnings: false,
},
{
desc: "test flag equals zero, ext debug flag true, debug info expected",
in: inTest{test: 0, debug: true},
out: outTest{debugInfoIncluded: true},
debugData: debugData{true, true},
desc: "test flag equals zero, ext debug flag true, debug info expected",
in: inTest{test: 0, debug: true},
out: outTest{debugInfoIncluded: true},
debugData: debugData{true, true},
generalWarnings: false,
},
{
desc: "test flag equals 1, ext debug flag false, debug info expected",
in: inTest{test: 1, debug: false},
out: outTest{debugInfoIncluded: true},
debugData: debugData{true, true},
desc: "test flag equals 1, ext debug flag false, debug info expected",
in: inTest{test: 1, debug: false},
out: outTest{debugInfoIncluded: true},
debugData: debugData{true, true},
generalWarnings: false,
},
{
desc: "test flag equals 1, ext debug flag true, debug info expected",
in: inTest{test: 1, debug: true},
out: outTest{debugInfoIncluded: true},
debugData: debugData{true, true},
desc: "test flag equals 1, ext debug flag true, debug info expected",
in: inTest{test: 1, debug: true},
out: outTest{debugInfoIncluded: true},
debugData: debugData{true, true},
generalWarnings: false,
},
{
desc: "test flag not equal to 0 nor 1, ext debug flag false, no debug info expected",
in: inTest{test: 2, debug: false},
out: outTest{debugInfoIncluded: false},
debugData: debugData{true, true},
desc: "test flag not equal to 0 nor 1, ext debug flag false, no debug info expected",
in: inTest{test: 2, debug: false},
out: outTest{debugInfoIncluded: false},
debugData: debugData{true, true},
generalWarnings: false,
},
{
desc: "test flag not equal to 0 nor 1, ext debug flag true, debug info expected",
in: inTest{test: -1, debug: true},
out: outTest{debugInfoIncluded: true},
debugData: debugData{true, true},
desc: "test flag not equal to 0 nor 1, ext debug flag true, debug info expected",
in: inTest{test: -1, debug: true},
out: outTest{debugInfoIncluded: true},
debugData: debugData{true, true},
generalWarnings: true,
},
{
desc: "test account level debug disabled",
in: inTest{test: -1, debug: true},
out: outTest{debugInfoIncluded: false},
debugData: debugData{true, false},
desc: "test account level debug disabled",
in: inTest{test: -1, debug: true},
out: outTest{debugInfoIncluded: false},
debugData: debugData{true, false},
generalWarnings: true,
},
{
desc: "test bidder level debug disabled",
in: inTest{test: -1, debug: true},
out: outTest{debugInfoIncluded: false},
debugData: debugData{false, true},
desc: "test bidder level debug disabled",
in: inTest{test: -1, debug: true},
out: outTest{debugInfoIncluded: false},
debugData: debugData{false, true},
generalWarnings: true,
},
}

Expand All @@ -243,9 +253,9 @@ func TestDebugBehaviour(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(noBidServer))
defer server.Close()

categoriesFetcher, error := newCategoryFetcher("./test/category-mapping")
if error != nil {
t.Errorf("Failed to create a category Fetcher: %v", error)
categoriesFetcher, err := newCategoryFetcher("./test/category-mapping")
if err != nil {
t.Errorf("Failed to create a category Fetcher: %v", err)
}

bidRequest := &openrtb.BidRequest{
Expand Down Expand Up @@ -305,6 +315,13 @@ func TestDebugBehaviour(t *testing.T) {
UserSyncs: &emptyUsersync{},
StartTime: time.Now(),
}
if test.generalWarnings {
var errL []error
errL = append(errL, &errortypes.Warning{
Message: fmt.Sprintf("CCPA consent is invalid and will be ignored."),
WarningCode: errortypes.InvalidPrivacyConsentWarningCode})
auctionRequest.Warnings = errL
}

// Run test
outBidResponse, err := e.HoldAuction(ctx, auctionRequest, nil)
Expand Down Expand Up @@ -347,10 +364,27 @@ func TestDebugBehaviour(t *testing.T) {
}

if !test.out.debugInfoIncluded && test.in.debug && test.debugData.accountLevelDebugAllowed {
assert.Len(t, actualExt.Warnings, 1, "warnings should have one warning")
assert.NotNil(t, actualExt.Warnings["appnexus"], "general warning should be present")
if test.generalWarnings {
assert.Len(t, actualExt.Warnings, 2, "warnings should have one warning")
} else {
assert.Len(t, actualExt.Warnings, 1, "warnings should have one warning")
}
assert.NotNil(t, actualExt.Warnings["appnexus"], "bidder warning should be present")
assert.Equal(t, "debug turned off for bidder", actualExt.Warnings["appnexus"][0].Message, "account debug disabled message should be present")
}

if test.generalWarnings {
assert.NotNil(t, actualExt.Warnings["general"], "general warning should be present")
CCPAWarningPresent := false
for _, warn := range actualExt.Warnings["general"] {
if warn.Code == errortypes.InvalidPrivacyConsentWarningCode {
CCPAWarningPresent = true
break
}
}
assert.True(t, CCPAWarningPresent, "CCPA Warning should be present")
}

}
}

Expand Down

0 comments on commit ae5620e

Please sign in to comment.