github.com/prebid/prebid-server@v0.275.0/router/router_test.go (about)

     1  package router
     2  
     3  import (
     4  	"encoding/json"
     5  	"net/http"
     6  	"net/http/httptest"
     7  	"os"
     8  	"testing"
     9  
    10  	"github.com/prebid/prebid-server/config"
    11  	"github.com/prebid/prebid-server/openrtb_ext"
    12  
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  const adapterDirectory = "../adapters"
    17  
    18  type testValidator struct{}
    19  
    20  func (validator *testValidator) Validate(name openrtb_ext.BidderName, ext json.RawMessage) error {
    21  	return nil
    22  }
    23  
    24  func (validator *testValidator) Schema(name openrtb_ext.BidderName) string {
    25  	if name == openrtb_ext.BidderAppnexus {
    26  		return "{\"appnexus\":true}"
    27  	} else {
    28  		return "{\"appnexus\":false}"
    29  	}
    30  }
    31  
    32  func ensureHasKey(t *testing.T, data map[string]json.RawMessage, key string) {
    33  	t.Helper()
    34  	if _, ok := data[key]; !ok {
    35  		t.Errorf("Expected map to produce a schema for adapter: %s", key)
    36  	}
    37  }
    38  
    39  func TestNewJsonDirectoryServer(t *testing.T) {
    40  	defaultAlias := map[string]string{"aliastest": "appnexus"}
    41  	yamlAlias := map[openrtb_ext.BidderName]openrtb_ext.BidderName{openrtb_ext.BidderName("alias"): openrtb_ext.BidderName("parentAlias")}
    42  	handler := newJsonDirectoryServer("../static/bidder-params", &testValidator{}, defaultAlias, yamlAlias)
    43  	recorder := httptest.NewRecorder()
    44  	request, _ := http.NewRequest("GET", "/whatever", nil)
    45  	handler(recorder, request, nil)
    46  
    47  	var data map[string]json.RawMessage
    48  	json.Unmarshal(recorder.Body.Bytes(), &data)
    49  
    50  	// Make sure that every adapter has a json schema by the same name associated with it.
    51  	adapterFiles, err := os.ReadDir(adapterDirectory)
    52  	if err != nil {
    53  		t.Fatalf("Failed to open the adapters directory: %v", err)
    54  	}
    55  
    56  	for _, adapterFile := range adapterFiles {
    57  		if adapterFile.IsDir() && adapterFile.Name() != "adapterstest" {
    58  			ensureHasKey(t, data, adapterFile.Name())
    59  		}
    60  	}
    61  
    62  	ensureHasKey(t, data, "aliastest")
    63  	ensureHasKey(t, data, "alias")
    64  }
    65  
    66  func TestCheckSupportedUserSyncEndpoints(t *testing.T) {
    67  	anyEndpoint := &config.SyncerEndpoint{URL: "anyURL"}
    68  
    69  	var testCases = []struct {
    70  		description      string
    71  		givenBidderInfos config.BidderInfos
    72  		expectedError    string
    73  	}{
    74  		{
    75  			description:      "None",
    76  			givenBidderInfos: config.BidderInfos{},
    77  			expectedError:    "",
    78  		},
    79  		{
    80  			description: "One - No Syncer",
    81  			givenBidderInfos: config.BidderInfos{
    82  				"a": config.BidderInfo{Syncer: nil},
    83  			},
    84  			expectedError: "",
    85  		},
    86  		{
    87  			description: "One - Invalid Supported Endpoint",
    88  			givenBidderInfos: config.BidderInfos{
    89  				"a": config.BidderInfo{Syncer: &config.Syncer{Supports: []string{"invalid"}}},
    90  			},
    91  			expectedError: "failed to load bidder info for a, user sync supported endpoint 'invalid' is unrecognized",
    92  		},
    93  		{
    94  			description: "One - IFrame Supported - Not Specified",
    95  			givenBidderInfos: config.BidderInfos{
    96  				"a": config.BidderInfo{Syncer: &config.Syncer{Supports: []string{"iframe"}, IFrame: nil}},
    97  			},
    98  			expectedError: "",
    99  		},
   100  		{
   101  			description: "One - IFrame Supported - Specified",
   102  			givenBidderInfos: config.BidderInfos{
   103  				"a": config.BidderInfo{Syncer: &config.Syncer{Supports: []string{"iframe"}, IFrame: anyEndpoint}},
   104  			},
   105  			expectedError: "",
   106  		},
   107  		{
   108  			description: "One - Redirect Supported - Not Specified",
   109  			givenBidderInfos: config.BidderInfos{
   110  				"a": config.BidderInfo{Syncer: &config.Syncer{Supports: []string{"redirect"}, Redirect: nil}},
   111  			},
   112  			expectedError: "",
   113  		},
   114  		{
   115  			description: "One - IFrame Supported - Specified",
   116  			givenBidderInfos: config.BidderInfos{
   117  				"a": config.BidderInfo{Syncer: &config.Syncer{Supports: []string{"redirect"}, Redirect: anyEndpoint}},
   118  			},
   119  			expectedError: "",
   120  		},
   121  		{
   122  			description: "One - IFrame + Redirect Supported - Not Specified",
   123  			givenBidderInfos: config.BidderInfos{
   124  				"a": config.BidderInfo{Syncer: &config.Syncer{Supports: []string{"iframe", "redirect"}, IFrame: nil, Redirect: nil}},
   125  			},
   126  			expectedError: "",
   127  		},
   128  		{
   129  			description: "One - IFrame + Redirect Supported - Specified",
   130  			givenBidderInfos: config.BidderInfos{
   131  				"a": config.BidderInfo{Syncer: &config.Syncer{Supports: []string{"iframe", "redirect"}, IFrame: anyEndpoint, Redirect: anyEndpoint}},
   132  			},
   133  			expectedError: "",
   134  		},
   135  		{
   136  			description: "Many - With Invalid Supported Endpoint",
   137  			givenBidderInfos: config.BidderInfos{
   138  				"a": config.BidderInfo{},
   139  				"b": config.BidderInfo{Syncer: &config.Syncer{Supports: []string{"invalid"}}},
   140  			},
   141  			expectedError: "failed to load bidder info for b, user sync supported endpoint 'invalid' is unrecognized",
   142  		},
   143  		{
   144  			description: "Many - Specified + Not Specified",
   145  			givenBidderInfos: config.BidderInfos{
   146  				"a": config.BidderInfo{Syncer: &config.Syncer{Supports: []string{"iframe"}, IFrame: anyEndpoint}},
   147  				"b": config.BidderInfo{Syncer: &config.Syncer{Supports: []string{"redirect"}, Redirect: nil}},
   148  			},
   149  			expectedError: "",
   150  		},
   151  	}
   152  
   153  	for _, test := range testCases {
   154  		resultErr := checkSupportedUserSyncEndpoints(test.givenBidderInfos)
   155  		if test.expectedError == "" {
   156  			assert.NoError(t, resultErr, test.description)
   157  		} else {
   158  			assert.EqualError(t, resultErr, test.expectedError, test.description)
   159  		}
   160  	}
   161  }
   162  
   163  // Prevents #648
   164  func TestCORSSupport(t *testing.T) {
   165  	const origin = "https://publisher-domain.com"
   166  	handler := func(w http.ResponseWriter, r *http.Request) {}
   167  	cors := SupportCORS(http.HandlerFunc(handler))
   168  	rr := httptest.NewRecorder()
   169  	req, err := http.NewRequest("OPTIONS", "http://some-domain.com/openrtb2/auction", nil)
   170  	req.Header.Set("Access-Control-Request-Method", "POST")
   171  	req.Header.Set("Access-Control-Request-Headers", "origin")
   172  	req.Header.Set("Origin", origin)
   173  
   174  	if !assert.NoError(t, err) {
   175  		return
   176  	}
   177  	cors.ServeHTTP(rr, req)
   178  	assert.Equal(t, origin, rr.Header().Get("Access-Control-Allow-Origin"))
   179  }
   180  
   181  func TestNoCache(t *testing.T) {
   182  	nc := NoCache{
   183  		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
   184  	}
   185  	rw := httptest.NewRecorder()
   186  	req, err := http.NewRequest("GET", "http://localhost/nocache", nil)
   187  	if err != nil {
   188  		t.Fatal(err)
   189  	}
   190  	req.Header.Set("ETag", "abcdef")
   191  	nc.ServeHTTP(rw, req)
   192  	h := rw.Header()
   193  	if expected := "no-cache, no-store, must-revalidate"; expected != h.Get("Cache-Control") {
   194  		t.Errorf("invalid cache-control header: expected: %s got: %s", expected, h.Get("Cache-Control"))
   195  	}
   196  	if expected := "no-cache"; expected != h.Get("Pragma") {
   197  		t.Errorf("invalid pragma header: expected: %s got: %s", expected, h.Get("Pragma"))
   198  	}
   199  	if expected := "0"; expected != h.Get("Expires") {
   200  		t.Errorf("invalid expires header: expected: %s got: %s", expected, h.Get("Expires"))
   201  	}
   202  	if expected := ""; expected != h.Get("ETag") {
   203  		t.Errorf("invalid etag header: expected: %s got: %s", expected, h.Get("ETag"))
   204  	}
   205  }
   206  
   207  var testDefReqConfig = config.DefReqConfig{
   208  	Type: "file",
   209  	FileSystem: config.DefReqFiles{
   210  		FileName: "test_aliases.json",
   211  	},
   212  	AliasInfo: true,
   213  }
   214  
   215  func TestLoadDefaultAliases(t *testing.T) {
   216  	defAliases, aliasJSON := readDefaultRequest(testDefReqConfig)
   217  	expectedJSON := []byte(`{"ext":{"prebid":{"aliases": {"test1": "appnexus", "test2": "rubicon", "test3": "openx"}}}}`)
   218  	expectedAliases := map[string]string{
   219  		"test1": "appnexus",
   220  		"test2": "rubicon",
   221  		"test3": "openx",
   222  	}
   223  
   224  	assert.JSONEq(t, string(expectedJSON), string(aliasJSON))
   225  	assert.Equal(t, expectedAliases, defAliases)
   226  }
   227  
   228  func TestLoadDefaultAliasesNoInfo(t *testing.T) {
   229  	noInfoConfig := testDefReqConfig
   230  	noInfoConfig.AliasInfo = false
   231  	defAliases, aliasJSON := readDefaultRequest(noInfoConfig)
   232  	expectedJSON := []byte(`{"ext":{"prebid":{"aliases": {"test1": "appnexus", "test2": "rubicon", "test3": "openx"}}}}`)
   233  	expectedAliases := map[string]string{}
   234  
   235  	assert.JSONEq(t, string(expectedJSON), string(aliasJSON))
   236  	assert.Equal(t, expectedAliases, defAliases)
   237  }
   238  
   239  func TestValidateDefaultAliases(t *testing.T) {
   240  	var testCases = []struct {
   241  		description   string
   242  		givenAliases  map[string]string
   243  		expectedError string
   244  	}{
   245  		{
   246  			description:   "None",
   247  			givenAliases:  map[string]string{},
   248  			expectedError: "",
   249  		},
   250  		{
   251  			description:   "Valid",
   252  			givenAliases:  map[string]string{"aAlias": "a"},
   253  			expectedError: "",
   254  		},
   255  		{
   256  			description:   "Invalid",
   257  			givenAliases:  map[string]string{"all": "a"},
   258  			expectedError: "default request alias errors (1 error):\n  1: alias all is a reserved bidder name and cannot be used\n",
   259  		},
   260  		{
   261  			description:   "Mixed",
   262  			givenAliases:  map[string]string{"aAlias": "a", "all": "a"},
   263  			expectedError: "default request alias errors (1 error):\n  1: alias all is a reserved bidder name and cannot be used\n",
   264  		},
   265  	}
   266  
   267  	for _, test := range testCases {
   268  		err := validateDefaultAliases(test.givenAliases)
   269  
   270  		if test.expectedError == "" {
   271  			assert.NoError(t, err, test.description)
   272  		} else {
   273  			assert.EqualError(t, err, test.expectedError, test.description)
   274  		}
   275  	}
   276  }