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