Skip to content

Commit

Permalink
Cache unit tests, some test refactoring.
Browse files Browse the repository at this point in the history
- wurl insertion in cached bids
- vast modifying in video bids
  • Loading branch information
laurb9 committed Nov 25, 2020
1 parent b2d8b64 commit 1849877
Show file tree
Hide file tree
Showing 10 changed files with 402 additions and 80 deletions.
152 changes: 73 additions & 79 deletions exchange/auction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import (
"encoding/xml"
"fmt"
"io/ioutil"
"path/filepath"
"regexp"
"strconv"
"strings"
"testing"

"github.com/prebid/prebid-server/adapters"
"github.com/prebid/prebid-server/config"
"github.com/prebid/prebid-server/openrtb_ext"
"github.com/prebid/prebid-server/prebid_cache_client"
Expand Down Expand Up @@ -100,57 +101,21 @@ func TestBuildCacheString(t *testing.T) {
// TestCacheJSON executes tests for all the *.json files in cachetest.
// customcachekey.json test here verifies custom cache key not used for non-vast video
func TestCacheJSON(t *testing.T) {
if specFiles, err := ioutil.ReadDir("./cachetest"); err == nil {
for _, specFile := range specFiles {
fileName := "./cachetest/" + specFile.Name()
fileDisplayName := "exchange/cachetest/" + specFile.Name()
specData, err := loadCacheSpec(fileName)
if err != nil {
t.Fatalf("Failed to load contents of file %s: %v", fileDisplayName, err)
for _, dir := range []string{"cachetest", "customcachekeytest", "impcustomcachekeytest", "eventscachetest"} {
if specFiles, err := ioutil.ReadDir(dir); err == nil {
for _, specFile := range specFiles {
fileName := filepath.Join(dir, specFile.Name())
fileDisplayName := "exchange/" + fileName
t.Run(fileDisplayName, func(t *testing.T) {
specData, err := loadCacheSpec(fileName)
if assert.NoError(t, err, "Failed to load contents of file %s: %v", fileDisplayName, err) {
runCacheSpec(t, fileDisplayName, specData)
}
})
}

runCacheSpec(t, fileDisplayName, specData)
}
} else {
t.Fatalf("Failed to read contents of directory exchange/cachetest/: %v", err)
}
}

// TestCacheJSON executes tests for all the *.json files in customcachekeytest.
// customcachekey.json test here verifies custom cache key is used for vast video
func TestCustomCacheKeyJSON(t *testing.T) {
if specFiles, err := ioutil.ReadDir("./customcachekeytest"); err == nil {
for _, specFile := range specFiles {
fileName := "./customcachekeytest/" + specFile.Name()
fileDisplayName := "exchange/customcachekeytest/" + specFile.Name()
specData, err := loadCacheSpec(fileName)
if err != nil {
t.Fatalf("Failed to load contents of file %s: %v", fileDisplayName, err)
}

runCacheSpec(t, fileDisplayName, specData)
}
} else {
t.Fatalf("Failed to read contents of directory exchange/customcachekeytest/: %v", err)
}
}

// TestMultiImpCache executes multi-Imp test cases found in *.json files in
// impcustomcachekeytest.
func TestCustomCacheKeyMultiImp(t *testing.T) {
if specFiles, err := ioutil.ReadDir("./impcustomcachekeytest"); err == nil {
for _, specFile := range specFiles {
fileName := "./impcustomcachekeytest/" + specFile.Name()
fileDisplayName := "exchange/impcustomcachekeytest/" + specFile.Name()
multiImpSpecData, err := loadCacheSpec(fileName)
if err != nil {
t.Fatalf("Failed to load contents of file %s: %v", fileDisplayName, err)
}

runCacheSpec(t, fileDisplayName, multiImpSpecData)
} else {
t.Fatalf("Failed to read contents of directory exchange/%s: %v", dir, err)
}
} else {
t.Fatalf("Failed to read contents of directory exchange/customcachekeytest/: %v", err)
}
}

Expand All @@ -169,9 +134,8 @@ func loadCacheSpec(filename string) (*cacheSpec, error) {
return &spec, nil
}

// runCacheSpec has been modified to handle multi-Imp and multi-bid Json test files,
// it cycles through the bids found in the test cases hardcoded in json files and
// finds the highest bid of every Imp.
// runCacheSpec cycles through the bids found in the json test cases and
// finds the highest bid of every Imp, then tests doCache() with resulting auction object
func runCacheSpec(t *testing.T, fileDisplayName string, specData *cacheSpec) {
var bid *pbsOrtbBid
winningBidsByImp := make(map[string]*pbsOrtbBid)
Expand Down Expand Up @@ -245,7 +209,18 @@ func runCacheSpec(t *testing.T, fileDisplayName string, specData *cacheSpec) {
winningBidsByBidder: winningBidsByBidder,
roundedPrices: roundedPrices,
}
evData := &eventsData{}
evData := &eventsData{
accountID: "ACCOUNT_ID",
enabledForAccount: specData.EventsDataEnabledForAccount,
enabledForRequest: specData.EventsDataEnabledForRequest,
externalURL: "http://localhost",
auctionTimestampMs: 1234567890,
bidderInfos: adapters.BidderInfos{
"openx": adapters.BidderInfo{ModifyingVastXmlAllowed: specData.BidderModifyingVastXmlAllowed},
"appnexus": adapters.BidderInfo{ModifyingVastXmlAllowed: specData.BidderModifyingVastXmlAllowed},
"pubmatic": adapters.BidderInfo{ModifyingVastXmlAllowed: specData.BidderModifyingVastXmlAllowed},
},
}
_ = testAuction.doCache(ctx, cache, targData, evData, &specData.BidRequest, 60, &specData.DefaultTTLs, bidCategory, &specData.DebugLog)

if len(specData.ExpectedCacheables) > len(cache.items) {
Expand All @@ -255,27 +230,43 @@ func runCacheSpec(t *testing.T, fileDisplayName string, specData *cacheSpec) {
} else { // len(specData.ExpectedCacheables) == len(cache.items)
// We cached the exact number of elements we expected, now we compare them side by side in n^2
var matched int = 0
var formattedExpectedData string
for i := 0; i < len(specData.ExpectedCacheables); i++ {
if specData.ExpectedCacheables[i].Type == prebid_cache_client.TypeJSON {
ExpectedData := strings.Replace(string(specData.ExpectedCacheables[i].Data), "\\", "", -1)
ExpectedData = strings.Replace(ExpectedData, " ", "", -1)
formattedExpectedData = ExpectedData[1 : len(ExpectedData)-1]
} else {
formattedExpectedData = string(specData.ExpectedCacheables[i].Data)
for i, expectedCacheable := range specData.ExpectedCacheables {
found := false
var expectedData interface{}
if err := json.Unmarshal(expectedCacheable.Data, &expectedData); err != nil {
t.Fatalf("Failed to decode expectedCacheables[%d].value: %v", i, err)
}
for j := 0; j < len(cache.items); j++ {
if formattedExpectedData == string(cache.items[j].Data) &&
specData.ExpectedCacheables[i].TTLSeconds == cache.items[j].TTLSeconds &&
specData.ExpectedCacheables[i].Type == cache.items[j].Type &&
len(specData.ExpectedCacheables[i].Key) <= len(cache.items[j].Key) &&
specData.ExpectedCacheables[i].Key == cache.items[j].Key[:len(specData.ExpectedCacheables[i].Key)] {
matched++
if s, ok := expectedData.(string); ok && expectedCacheable.Type == prebid_cache_client.TypeJSON {
// decode again if we have pre-encoded json string values
if err := json.Unmarshal([]byte(s), &expectedData); err != nil {
t.Fatalf("Failed to re-decode expectedCacheables[%d].value :%v", i, err)
}
}
for j, cachedItem := range cache.items {
var actualData interface{}
if err := json.Unmarshal(cachedItem.Data, &actualData); err != nil {
t.Fatalf("Failed to decode actual cache[%d].value: %s", j, err)
}
if assert.ObjectsAreEqual(expectedData, actualData) &&
expectedCacheable.TTLSeconds == cachedItem.TTLSeconds &&
expectedCacheable.Type == cachedItem.Type &&
len(expectedCacheable.Key) <= len(cachedItem.Key) &&
expectedCacheable.Key == cachedItem.Key[:len(expectedCacheable.Key)] {
found = true
cache.items = append(cache.items[:j], cache.items[j+1:]...) // remove matched item
break
}
}
if found {
matched++
} else {
t.Errorf("%s: [CACHE_ERROR] Did not see expected cacheable #%d: type=%s, ttl=%d, value=%s", fileDisplayName, i, expectedCacheable.Type, expectedCacheable.TTLSeconds, string(expectedCacheable.Data))
}
}
if matched != len(specData.ExpectedCacheables) {
t.Errorf("%s: [CACHE_ERROR] One or more keys were not cached as we expected \n", fileDisplayName)
for i, item := range cache.items {
t.Errorf("%s: [CACHE_ERROR] Got unexpected cached item #%d: type=%s, ttl=%d, value=%s", fileDisplayName, i, item.Type, item.TTLSeconds, string(item.Data))
}
t.FailNow()
}
}
Expand Down Expand Up @@ -501,15 +492,18 @@ func TestNewAuction(t *testing.T) {
}

type cacheSpec struct {
BidRequest openrtb.BidRequest `json:"bidRequest"`
PbsBids []pbsBid `json:"pbsBids"`
ExpectedCacheables []prebid_cache_client.Cacheable `json:"expectedCacheables"`
DefaultTTLs config.DefaultTTLs `json:"defaultTTLs"`
TargetDataIncludeWinners bool `json:"targetDataIncludeWinners"`
TargetDataIncludeBidderKeys bool `json:"targetDataIncludeBidderKeys"`
TargetDataIncludeCacheBids bool `json:"targetDataIncludeCacheBids"`
TargetDataIncludeCacheVast bool `json:"targetDataIncludeCacheVast"`
DebugLog DebugLog `json:"debugLog,omitempty"`
BidRequest openrtb.BidRequest `json:"bidRequest"`
PbsBids []pbsBid `json:"pbsBids"`
ExpectedCacheables []prebid_cache_client.Cacheable `json:"expectedCacheables"`
DefaultTTLs config.DefaultTTLs `json:"defaultTTLs"`
TargetDataIncludeWinners bool `json:"targetDataIncludeWinners"`
TargetDataIncludeBidderKeys bool `json:"targetDataIncludeBidderKeys"`
TargetDataIncludeCacheBids bool `json:"targetDataIncludeCacheBids"`
TargetDataIncludeCacheVast bool `json:"targetDataIncludeCacheVast"`
EventsDataEnabledForAccount bool `json:"eventsDataEnabledForAccount"`
EventsDataEnabledForRequest bool `json:"eventsDataEnabledForRequest"`
BidderModifyingVastXmlAllowed bool `json:"bidderModifyingVastXMLAllowed`
DebugLog DebugLog `json:"debugLog,omitempty"`
}

type pbsBid struct {
Expand Down
2 changes: 1 addition & 1 deletion exchange/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func getExtEventsData(requestExtPrebid *openrtb_ext.ExtRequestPrebid, ts time.Ti

// isModifyingVASTXMLAllowed returns true if this bidder config allows modifying VAST XML for event tracking
func (ev *eventsData) isModifyingVASTXMLAllowed(bidderName string) bool {
return ev.bidderInfos[bidderName].ModifyingVastXmlAllowed
return ev.bidderInfos[bidderName].ModifyingVastXmlAllowed && ev.enabledForAccount
}

// modifyVAST injects event Impression url if needed, otherwise returns original VAST string
Expand Down
49 changes: 49 additions & 0 deletions exchange/eventscachetest/json-account-off-request-off.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"bidRequest": {
"imp": [{
"id": "oneImp"
}]
},
"pbsBids": [{
"bid":{
"id": "bidOne",
"impid": "oneImp",
"price": 7.64,
"exp": 600
},
"bidType": "banner",
"bidder": "appnexus"
}, {
"bid": {
"id": "bidTwo",
"impid": "oneImp",
"price": 5.64
},
"bidType": "banner",
"bidder": "pubmatic"
}],
"expectedCacheables": [
{
"type": "json",
"ttlseconds": 660,
"value":{ "id": "bidOne", "impid": "oneImp", "price": 7.64, "exp": 600}
}, {
"type": "json",
"ttlseconds": 360,
"value": { "id": "bidTwo", "impid": "oneImp", "price": 5.64}
}
],
"defaultTTLs": {
"banner": 300,
"video": 3600,
"audio": 1800,
"native": 300
},
"targetDataIncludeWinners":true,
"targetDataIncludeBidderKeys":true,
"targetDataIncludeCacheBids":true,
"targetDataIncludeCacheVast":false,
"eventsDataEnabledForAccount": false,
"eventsDataEnabledForRequest": false
}

49 changes: 49 additions & 0 deletions exchange/eventscachetest/json-account-off-request-on.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"bidRequest": {
"imp": [{
"id": "oneImp"
}]
},
"pbsBids": [{
"bid":{
"id": "bidOne",
"impid": "oneImp",
"price": 7.64,
"exp": 600
},
"bidType": "banner",
"bidder": "appnexus"
}, {
"bid": {
"id": "bidTwo",
"impid": "oneImp",
"price": 5.64
},
"bidType": "banner",
"bidder": "pubmatic"
}],
"expectedCacheables": [
{
"type": "json",
"ttlseconds": 660,
"value":{ "id": "bidOne", "impid": "oneImp", "price": 7.64, "exp": 600, "wurl": "http://localhost/event?t=win\u0026b=bidOne\u0026a=ACCOUNT_ID\u0026bidder=appnexus\u0026ts=1234567890"}
}, {
"type": "json",
"ttlseconds": 360,
"value": { "id": "bidTwo", "impid": "oneImp", "price": 5.64, "wurl": "http://localhost/event?t=win\u0026b=bidTwo\u0026a=ACCOUNT_ID\u0026bidder=pubmatic\u0026ts=1234567890"}
}
],
"defaultTTLs": {
"banner": 300,
"video": 3600,
"audio": 1800,
"native": 300
},
"targetDataIncludeWinners":true,
"targetDataIncludeBidderKeys":true,
"targetDataIncludeCacheBids":true,
"targetDataIncludeCacheVast":false,
"eventsDataEnabledForAccount": false,
"eventsDataEnabledForRequest": true
}

49 changes: 49 additions & 0 deletions exchange/eventscachetest/json-account-on-request-off.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"bidRequest": {
"imp": [{
"id": "oneImp"
}]
},
"pbsBids": [{
"bid":{
"id": "bidOne",
"impid": "oneImp",
"price": 7.64,
"exp": 600
},
"bidType": "banner",
"bidder": "appnexus"
}, {
"bid": {
"id": "bidTwo",
"impid": "oneImp",
"price": 5.64
},
"bidType": "banner",
"bidder": "pubmatic"
}],
"expectedCacheables": [
{
"type": "json",
"ttlseconds": 660,
"value":{ "id": "bidOne", "impid": "oneImp", "price": 7.64, "exp": 600, "wurl": "http://localhost/event?t=win&b=bidOne&a=ACCOUNT_ID&bidder=appnexus&ts=1234567890"}
}, {
"type": "json",
"ttlseconds": 360,
"value": { "id": "bidTwo", "impid": "oneImp", "price": 5.64, "wurl": "http://localhost/event?t=win&b=bidTwo&a=ACCOUNT_ID&bidder=pubmatic&ts=1234567890"}
}
],
"defaultTTLs": {
"banner": 300,
"video": 3600,
"audio": 1800,
"native": 300
},
"targetDataIncludeWinners":true,
"targetDataIncludeBidderKeys":true,
"targetDataIncludeCacheBids":true,
"targetDataIncludeCacheVast":false,
"eventsDataEnabledForAccount": true,
"eventsDataEnabledForRequest": false
}

Loading

0 comments on commit 1849877

Please sign in to comment.