github.com/prebid/prebid-server/v2@v2.18.0/openrtb_ext/bidders_test.go (about) 1 package openrtb_ext 2 3 import ( 4 "encoding/json" 5 "errors" 6 "os" 7 "strings" 8 "testing" 9 "testing/fstest" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/xeipuuv/gojsonschema" 13 ) 14 15 func TestBidderParamValidatorValidate(t *testing.T) { 16 testSchemaLoader := gojsonschema.NewStringLoader(`{ 17 "$schema": "http://json-schema.org/draft-04/schema#", 18 "title": "Test Params", 19 "description": "Test Description", 20 "type": "object", 21 "properties": { 22 "placementId": { 23 "type": "integer", 24 "description": "An ID which identifies this placement of the impression." 25 }, 26 "optionalText": { 27 "type": "string", 28 "description": "Optional text for testing." 29 } 30 }, 31 "required": ["placementId"] 32 }`) 33 testSchema, err := gojsonschema.NewSchema(testSchemaLoader) 34 if !assert.NoError(t, err) { 35 t.FailNow() 36 } 37 testBidderName := BidderName("foo") 38 testValidator := bidderParamValidator{ 39 parsedSchemas: map[BidderName]*gojsonschema.Schema{ 40 testBidderName: testSchema, 41 }, 42 } 43 44 testCases := []struct { 45 description string 46 ext json.RawMessage 47 expectedError string 48 }{ 49 { 50 description: "Valid", 51 ext: json.RawMessage(`{"placementId":123}`), 52 expectedError: "", 53 }, 54 { 55 description: "Invalid - Wrong Type", 56 ext: json.RawMessage(`{"placementId":"stringInsteadOfInt"}`), 57 expectedError: "placementId: Invalid type. Expected: integer, given: string", 58 }, 59 { 60 description: "Invalid - Empty Object", 61 ext: json.RawMessage(`{}`), 62 expectedError: "(root): placementId is required", 63 }, 64 { 65 description: "Malformed", 66 ext: json.RawMessage(`malformedJSON`), 67 expectedError: "invalid character 'm' looking for beginning of value", 68 }, 69 } 70 71 for _, test := range testCases { 72 err := testValidator.Validate(testBidderName, test.ext) 73 if test.expectedError == "" { 74 assert.NoError(t, err, test.description) 75 } else { 76 assert.EqualError(t, err, test.expectedError, test.description) 77 } 78 } 79 } 80 81 func TestBidderParamValidatorSchema(t *testing.T) { 82 testValidator := bidderParamValidator{ 83 schemaContents: map[BidderName]string{ 84 BidderName("foo"): "foo content", 85 BidderName("bar"): "bar content", 86 }, 87 } 88 89 result := testValidator.Schema(BidderName("bar")) 90 91 assert.Equal(t, "bar content", result) 92 } 93 94 func TestIsBidderNameReserved(t *testing.T) { 95 testCases := []struct { 96 bidder string 97 expected bool 98 }{ 99 {"all", true}, 100 {"aLl", true}, 101 {"ALL", true}, 102 {"context", true}, 103 {"CONTEXT", true}, 104 {"conTExt", true}, 105 {"data", true}, 106 {"DATA", true}, 107 {"DaTa", true}, 108 {"general", true}, 109 {"gEnErAl", true}, 110 {"GENERAL", true}, 111 {"gpid", true}, 112 {"GPID", true}, 113 {"GPid", true}, 114 {"prebid", true}, 115 {"PREbid", true}, 116 {"PREBID", true}, 117 {"skadn", true}, 118 {"skADN", true}, 119 {"SKADN", true}, 120 {"tid", true}, 121 {"TId", true}, 122 {"Tid", true}, 123 {"TiD", true}, 124 {"notreserved", false}, 125 } 126 127 for _, test := range testCases { 128 result := IsBidderNameReserved(test.bidder) 129 assert.Equal(t, test.expected, result, test.bidder) 130 } 131 } 132 133 func TestSetAliasBidderName(t *testing.T) { 134 parentBidder := BidderName("pBidder") 135 existingCoreBidderNames := coreBidderNames 136 137 testCases := []struct { 138 aliasBidderName string 139 err error 140 }{ 141 {"aBidder", nil}, 142 {"all", errors.New("alias all is a reserved bidder name and cannot be used")}, 143 } 144 145 for _, test := range testCases { 146 err := SetAliasBidderName(test.aliasBidderName, parentBidder) 147 if err != nil { 148 assert.Equal(t, test.err, err) 149 } else { 150 assert.Contains(t, CoreBidderNames(), BidderName(test.aliasBidderName)) 151 assert.Contains(t, aliasBidderToParent, BidderName(test.aliasBidderName)) 152 assert.Contains(t, bidderNameLookup, strings.ToLower(test.aliasBidderName)) 153 } 154 } 155 156 //reset package variables to not interfere with other test cases. Example - TestBidderParamSchemas 157 coreBidderNames = existingCoreBidderNames 158 aliasBidderToParent = map[BidderName]BidderName{} 159 } 160 161 type mockParamsHelper struct { 162 fs fstest.MapFS 163 absFilePath string 164 absPathErr error 165 schemaLoaderErr error 166 readFileErr error 167 } 168 169 func (m *mockParamsHelper) readDir(name string) ([]os.DirEntry, error) { 170 return m.fs.ReadDir(name) 171 } 172 173 func (m *mockParamsHelper) readFile(name string) ([]byte, error) { 174 if m.readFileErr != nil { 175 return nil, m.readFileErr 176 } 177 return m.fs.ReadFile(name) 178 } 179 180 func (m *mockParamsHelper) newReferenceLoader(source string) gojsonschema.JSONLoader { 181 return nil 182 } 183 184 func (m *mockParamsHelper) newSchema(l gojsonschema.JSONLoader) (*gojsonschema.Schema, error) { 185 return nil, m.schemaLoaderErr 186 } 187 188 func (m *mockParamsHelper) abs(path string) (string, error) { 189 return m.absFilePath, m.absPathErr 190 } 191 192 func TestNewBidderParamsValidator(t *testing.T) { 193 testCases := []struct { 194 description string 195 paramsValidator mockParamsHelper 196 dir string 197 expectedErr error 198 }{ 199 { 200 description: "Valid case", 201 paramsValidator: mockParamsHelper{ 202 fs: fstest.MapFS{ 203 "test/appnexus.json": { 204 Data: []byte("{}"), 205 }, 206 }, 207 }, 208 dir: "test", 209 }, 210 { 211 description: "failed to read directory", 212 paramsValidator: mockParamsHelper{}, 213 dir: "t", 214 expectedErr: errors.New("Failed to read JSON schemas from directory t. open t: file does not exist"), 215 }, 216 { 217 description: "file name does not match the bidder name", 218 paramsValidator: mockParamsHelper{ 219 fs: fstest.MapFS{ 220 "test/anyBidder.json": { 221 Data: []byte("{}"), 222 }, 223 }, 224 }, 225 dir: "test", 226 expectedErr: errors.New("File test/anyBidder.json does not match a valid BidderName."), 227 }, 228 { 229 description: "abs file path error", 230 paramsValidator: mockParamsHelper{ 231 fs: fstest.MapFS{ 232 "test/appnexus.json": { 233 Data: []byte("{}"), 234 }, 235 }, 236 absFilePath: "test/app.json", 237 absPathErr: errors.New("any abs error"), 238 }, 239 dir: "test", 240 expectedErr: errors.New("Failed to get an absolute representation of the path: test/app.json, any abs error"), 241 }, 242 { 243 description: "schema loader error", 244 paramsValidator: mockParamsHelper{ 245 fs: fstest.MapFS{ 246 "test/appnexus.json": { 247 Data: []byte("{}"), 248 }, 249 }, 250 schemaLoaderErr: errors.New("any schema loader error"), 251 }, 252 dir: "test", 253 expectedErr: errors.New("Failed to load json schema at : any schema loader error"), 254 }, 255 { 256 description: "read file error", 257 paramsValidator: mockParamsHelper{ 258 fs: fstest.MapFS{ 259 "test/appnexus.json": { 260 Data: []byte("{}"), 261 }, 262 }, 263 readFileErr: errors.New("any read file error"), 264 }, 265 dir: "test", 266 expectedErr: errors.New("Failed to read file test/appnexus.json: any read file error"), 267 }, 268 } 269 270 for _, test := range testCases { 271 t.Run(test.description, func(t *testing.T) { 272 aliasBidderToParent = map[BidderName]BidderName{"rubicon": "appnexus"} 273 paramsValidator = &test.paramsValidator 274 bidderValidator, err := NewBidderParamsValidator(test.dir) 275 if test.expectedErr == nil { 276 assert.NoError(t, err) 277 assert.Contains(t, bidderValidator.Schema("appnexus"), "{}") 278 assert.Contains(t, bidderValidator.Schema("rubicon"), "{}") 279 } else { 280 assert.Equal(t, err, test.expectedErr) 281 } 282 }) 283 } 284 }