Skip to content

Commit

Permalink
OTT-1327: replacing kv macro correctly if KV map has nested key value…
Browse files Browse the repository at this point in the history
… pairs
  • Loading branch information
Ankit-Pinge committed Oct 20, 2023
1 parent 51d032d commit 3d08a40
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 53 deletions.
45 changes: 22 additions & 23 deletions adapters/vastbidder/bidder_macro.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package vastbidder

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
Expand Down Expand Up @@ -177,16 +176,23 @@ func (tag *BidderMacro) GetHeaders() http.Header {
return http.Header{}
}

// GetValueFromKV returns the value from KV map wrt key
func (tag *BidderMacro) GetValueFromKV(key string) string {
if tag.KV == nil {
return ""
}
key = strings.TrimPrefix(key, kvPrefix)
if value, found := tag.KV[key]; found {
return fmt.Sprintf("%v", value)
// GetValue returns the value from KV map wrt key
func (tag *BidderMacro) GetValue(key string) (string, bool) {
tempKeys := strings.Split(key, ".")

if tempKeys[0] == prefixkv || tempKeys[0] == prefixkvm {
if tag.KV != nil {
if value, found := tag.KV[tempKeys[1]]; found {
if isMap(value) {
return getJsonString(value), true
}
return fmt.Sprintf("%v", value), true
}
return "", true
}
return "", true
}
return ""
return "", false
}

/********************* Request *********************/
Expand Down Expand Up @@ -1212,29 +1218,22 @@ func (tag *BidderMacro) MacroKV(key string) string {

keyval := ""
for key, val := range tag.KV {
if isMap(val) {
jsonString := getJsonString(val)
keyval += fmt.Sprintf("%s=%v&", key, jsonString)
continue
}
keyval += fmt.Sprintf("%s=%v&", key, val)
}
return strings.TrimSuffix(keyval, "&")

}

// MacroKVM replace the kvm macro
func (tag *BidderMacro) MacroKVM(key string) string {
if tag.KV == nil {
return ""
}
var buf bytes.Buffer
encoder := json.NewEncoder(&buf)

// Disable HTML escaping for special characters
encoder.SetEscapeHTML(false)

if err := encoder.Encode(tag.KV); err != nil {
return ""
}
jsonString := strings.TrimRight(buf.String(), "\n")

return jsonString
return getJsonString(tag.KV)
}

/********************* Request Headers *********************/
Expand Down
184 changes: 162 additions & 22 deletions adapters/vastbidder/bidder_macro_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package vastbidder
import (
"fmt"
"net/http"
"reflect"
"sort"
"strings"
"testing"

"github.com/prebid/openrtb/v19/adcom1"
Expand Down Expand Up @@ -1264,7 +1267,7 @@ func TestBidderMacro_MacroTest(t *testing.T) {
}
}

func TestBidderGetValueFromKV(t *testing.T) {
func TestBidderGetValue(t *testing.T) {
type fields struct {
KV map[string]interface{}
}
Expand Down Expand Up @@ -1308,13 +1311,74 @@ func TestBidderGetValueFromKV(t *testing.T) {
args: args{key: "kv.anykey"},
want: "",
},

{
name: "key_with_value_as_map",
fields: fields{KV: map[string]interface{}{
"name": "test",
"country": map[string]interface{}{
"state": "MH",
"pincode": 411041,
"url": "http//example.com?k1=v1&k2=v2",
},
}},
args: args{key: "kvm.country"},
want: "{\"pincode\":411041,\"state\":\"MH\",\"url\":\"http//example.com?k1=v1&k2=v2\"}",
},
{
name: "key_with_value_as_map",
fields: fields{KV: map[string]interface{}{
"name": "test",
"country": map[string]interface{}{
"state": "MH",
"pincode": 411041,
"url": "http//example.com?k1=v1&k2=v2",
},
}},
args: args{key: "kvm.country"},
want: "{\"pincode\":411041,\"state\":\"MH\",\"url\":\"http//example.com?k1=v1&k2=v2\"}",
},
{
name: "key_with_value_as_nested_map",
fields: fields{KV: map[string]interface{}{
"name": "test",
"country": map[string]interface{}{
"state": "MH",
"pincode": 411041,
"url": "http//example.com?k1=v1&k2=v2",
"metadata": map[string]interface{}{
"k1": "v1",
"k2": "v2",
},
},
}},
args: args{key: "kvm.country"},
want: "{\"metadata\":{\"k1\":\"v1\",\"k2\":\"v2\"},\"pincode\":411041,\"state\":\"MH\",\"url\":\"http//example.com?k1=v1&k2=v2\"}",
},
{
name: "key_with_value_as_nested_map_",
fields: fields{KV: map[string]interface{}{
"name": "test",
"country": map[string]interface{}{
"state": "MH",
"pincode": 411041,
"url": "http//example.com?k1=v1&k2=v2",
"metadata": map[string]interface{}{
"k1": "v1",
"k2": "v2",
},
},
}},
args: args{key: "someprefix.country"},
want: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tag := &BidderMacro{
KV: tt.fields.KV,
}
value := tag.GetValueFromKV(tt.args.key)
value, _ := tag.GetValue(tt.args.key)
assert.Equal(t, tt.want, value, tt.name)
})
}
Expand All @@ -1328,41 +1392,85 @@ func TestBidderMacroKV(t *testing.T) {
key string
}
tests := []struct {
name string
fields fields
args args
want string
name string
fields fields
args args
want string
isMatched bool
}{
{
name: "Valid_test",
fields: fields{KV: map[string]interface{}{
"name": "test",
"age": "22",
}},
args: args{key: "kv"},
want: "name=test&age=22",
args: args{key: "kv"},
want: "name=test&age=22",
isMatched: true,
},
{
name: "Valid_test_with_url",
fields: fields{KV: map[string]interface{}{
"name": "test",
"age": "22",
"url": "http://example.com?k1=v1&k2=v2",
"age": "22",
"url": "http://example.com?k1=v1&k2=v2",
}},
args: args{key: "kv"},
want: "name=test&age=22&url=http://example.com?k1=v1&k2=v2",
args: args{key: "kv"},
want: "age=22&url=http://example.com?k1=v1&k2=v2",
isMatched: true,
},
{
name: "Empty_KV_map",
fields: fields{KV: nil},
args: args{key: "kv"},
want: "",
name: "Empty_KV_map",
fields: fields{KV: nil},
args: args{key: "kv"},
want: "",
isMatched: true,
},
{
name: "KV_map_with_no_key_val_pair",
fields: fields{KV: map[string]interface{}{}},
args: args{key: "kv"},
want: "",
name: "KV_map_with_no_key_val_pair",
fields: fields{KV: map[string]interface{}{}},
args: args{key: "kv"},
want: "",
isMatched: true,
},
{
name: "key_with_value_map",
fields: fields{KV: map[string]interface{}{
"age": 22,
"country": map[string]interface{}{
"state": "MH",
"pincode": 411041,
},
}},
args: args{key: "kv"},
want: "age=22&country={\"pincode\":411041,\"state\":\"MH\"}",
isMatched: true,
},
{
name: "key_with_value_as_nested_map",
fields: fields{KV: map[string]interface{}{
"age": 22,
"country": map[string]interface{}{
"state": "MH",
"pincode": 411041,
"metadata": map[string]interface{}{
"k1": "v1",
"k2": "v2",
},
},
}},
args: args{key: "kv"},
want: "age=22&country={\"metadata\":{\"k1\":\"v1\",\"k2\":\"v2\"},\"pincode\":411041,\"state\":\"MH\"}",
isMatched: true,
},
{
name: "string_not_matched",
fields: fields{KV: map[string]interface{}{
"name": "test",
"age": "22",
}},
args: args{key: "kv"},
want: "name=test1&age=22",
isMatched: false,
},
}
for _, tt := range tests {
Expand All @@ -1371,11 +1479,26 @@ func TestBidderMacroKV(t *testing.T) {
KV: tt.fields.KV,
}
got := tag.MacroKV(tt.args.key)
assert.Equal(t, tt.want, got, tt.name)

isEqual := isEqual(tt.want, got)
assert.Equal(t, tt.isMatched, isEqual)
})
}
}

// isEqual compare two shuffled strings containing key-value pairs and determine if they have the same key-value pairs regardless of their order within the string.
func isEqual(want, got string) bool {

w := strings.Split(want, "&")
g := strings.Split(got, "&")

sort.Strings(w)
sort.Strings(g)

return reflect.DeepEqual(w, g)

}

func TestBidderMacroKVM(t *testing.T) {
type fields struct {
KV map[string]interface{}
Expand Down Expand Up @@ -1437,6 +1560,23 @@ func TestBidderMacroKVM(t *testing.T) {
args: args{key: "kvm"},
want: "{\"name\":\"test\",\"url\":\"http://example.com?k1=v1&k2=v2\"}",
},
{
name: "key_with_value_as_nested_map",
fields: fields{KV: map[string]interface{}{
"name": "test",
"age": 22,
"country": map[string]interface{}{
"state": "MH",
"pincode": 411041,
"metadata": map[string]interface{}{
"k1": "v1",
"k2": "v2",
},
},
}},
args: args{key: "kvm"},
want: "{\"age\":22,\"country\":{\"metadata\":{\"k1\":\"v1\",\"k2\":\"v2\"},\"pincode\":411041,\"state\":\"MH\"},\"name\":\"test\"}",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
7 changes: 4 additions & 3 deletions adapters/vastbidder/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,10 @@ const (
)

const (
prebid = "prebid"
keyval = "keyval"
kvPrefix = "kv."
prebid = "prebid"
keyval = "keyval"
prefixkv = "kv"
prefixkvm = "kvm"
)

var ParamKeys = []string{"param1", "param2", "param3", "param4", "param5"}
2 changes: 1 addition & 1 deletion adapters/vastbidder/ibidder_macro.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type IBidderMacro interface {
SetAdapterConfig(*config.Adapter)
GetURI() string
GetHeaders() http.Header
GetValueFromKV(string) string
GetValue(string) (string, bool)
//getAllHeaders returns default and custom heades
getAllHeaders() http.Header

Expand Down
6 changes: 2 additions & 4 deletions adapters/vastbidder/macro_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,8 @@ func (mp *MacroProcessor) processKey(key string) (string, bool) {
tmpKey = tmpKey[0 : len(tmpKey)-macroEscapeSuffixLen]
nEscaping++
continue
} else if strings.HasPrefix(tmpKey, kvPrefix) {
value = mp.bidderMacro.GetValueFromKV(tmpKey)
found = true
break
} else {
value, found = mp.bidderMacro.GetValue(tmpKey)
}
break
}
Expand Down
21 changes: 21 additions & 0 deletions adapters/vastbidder/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"math/rand"
"strconv"
"strings"

"github.com/prebid/prebid-server/adapters"
"github.com/prebid/prebid-server/openrtb_ext"
Expand Down Expand Up @@ -68,3 +69,23 @@ func NormalizeJSON(obj map[string]interface{}) map[string]string {
var GetRandomID = func() string {
return strconv.FormatInt(rand.Int63(), intBase)
}

func getJsonString(kvmap any) string {

var buf bytes.Buffer
encoder := json.NewEncoder(&buf)

// Disable HTML escaping for special characters
encoder.SetEscapeHTML(false)

if err := encoder.Encode(kvmap); err != nil {
return ""
}
return strings.TrimRight(buf.String(), "\n")

}

func isMap(data any) bool {
t := fmt.Sprintf("%T", data)
return strings.HasPrefix(t, "map[")
}

0 comments on commit 3d08a40

Please sign in to comment.