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  }