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  }