github.com/prebid/prebid-server@v0.275.0/endpoints/events/vtrack_test.go (about)

     1  package events
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/json"
     7  	"errors"
     8  	"fmt"
     9  	"io"
    10  	"net/http"
    11  	"net/http/httptest"
    12  	"strings"
    13  	"testing"
    14  
    15  	"github.com/prebid/prebid-server/config"
    16  	"github.com/prebid/prebid-server/prebid_cache_client"
    17  	"github.com/prebid/prebid-server/stored_requests"
    18  	"github.com/stretchr/testify/assert"
    19  )
    20  
    21  const (
    22  	maxSize = 1024 * 256
    23  
    24  	vastXmlWithImpressionWithContent    = "<VAST version=\"3.0\"><Ad><Wrapper><AdSystem>prebid.org wrapper</AdSystem><VASTAdTagURI><![CDATA[adm2]]></VASTAdTagURI><Impression>content</Impression><Creatives></Creatives></Wrapper></Ad></VAST>"
    25  	vastXmlWithImpressionWithoutContent = "<VAST version=\"3.0\"><Ad><Wrapper><AdSystem>prebid.org wrapper</AdSystem><VASTAdTagURI><![CDATA[adm2]]></VASTAdTagURI><Impression></Impression><Creatives></Creatives></Wrapper></Ad></VAST>"
    26  	vastXmlWithoutImpression            = "<VAST version=\"3.0\"><Ad><Wrapper><AdSystem>prebid.org wrapper</AdSystem><VASTAdTagURI><![CDATA[adm2]]></VASTAdTagURI><Creatives></Creatives></Wrapper></Ad></VAST>"
    27  )
    28  
    29  // Mock pbs cache client
    30  type vtrackMockCacheClient struct {
    31  	Fail  bool
    32  	Error error
    33  	Uuids []string
    34  }
    35  
    36  func (m *vtrackMockCacheClient) PutJson(ctx context.Context, values []prebid_cache_client.Cacheable) ([]string, []error) {
    37  	if m.Fail {
    38  		return []string{}, []error{m.Error}
    39  	}
    40  	return m.Uuids, []error{}
    41  }
    42  func (m *vtrackMockCacheClient) GetExtCacheData() (scheme string, host string, path string) {
    43  	return
    44  }
    45  
    46  // Test
    47  func TestShouldRespondWithBadRequestWhenAccountParameterIsMissing(t *testing.T) {
    48  	// mock pbs cache client
    49  	mockCacheClient := &vtrackMockCacheClient{}
    50  
    51  	// mock AccountsFetcher
    52  	mockAccountsFetcher := &mockAccountsFetcher{}
    53  
    54  	// mock config
    55  	cfg := &config.Configuration{
    56  		AccountDefaults: config.Account{},
    57  	}
    58  	cfg.MarshalAccountDefaults()
    59  
    60  	// prepare
    61  	reqData := ""
    62  
    63  	req := httptest.NewRequest("POST", "/vtrack", strings.NewReader(reqData))
    64  	recorder := httptest.NewRecorder()
    65  
    66  	e := vtrackEndpoint{
    67  		Cfg:         cfg,
    68  		BidderInfos: nil,
    69  		Cache:       mockCacheClient,
    70  		Accounts:    mockAccountsFetcher,
    71  	}
    72  
    73  	// execute
    74  	e.Handle(recorder, req, nil)
    75  
    76  	d, err := io.ReadAll(recorder.Result().Body)
    77  	if err != nil {
    78  		t.Fatal(err)
    79  	}
    80  
    81  	// validate
    82  	assert.Equal(t, 400, recorder.Result().StatusCode, "Expected 400 on request with missing account parameter")
    83  	assert.Equal(t, "Account 'a' is required query parameter and can't be empty", string(d))
    84  }
    85  
    86  func TestShouldRespondWithBadRequestWhenRequestBodyIsEmpty(t *testing.T) {
    87  	// mock pbs cache client
    88  	mockCacheClient := &vtrackMockCacheClient{}
    89  
    90  	// mock AccountsFetcher
    91  	mockAccountsFetcher := &mockAccountsFetcher{}
    92  
    93  	// config
    94  	cfg := &config.Configuration{
    95  		MaxRequestSize:  maxSize,
    96  		AccountDefaults: config.Account{},
    97  	}
    98  	cfg.MarshalAccountDefaults()
    99  
   100  	// prepare
   101  	reqData := ""
   102  
   103  	req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(reqData))
   104  
   105  	recorder := httptest.NewRecorder()
   106  
   107  	e := vtrackEndpoint{
   108  		Cfg:         cfg,
   109  		BidderInfos: nil,
   110  		Cache:       mockCacheClient,
   111  		Accounts:    mockAccountsFetcher,
   112  	}
   113  
   114  	// execute
   115  	e.Handle(recorder, req, nil)
   116  
   117  	d, err := io.ReadAll(recorder.Result().Body)
   118  	if err != nil {
   119  		t.Fatal(err)
   120  	}
   121  
   122  	// validate
   123  	assert.Equal(t, 400, recorder.Result().StatusCode, "Expected 400 on request with empty body")
   124  	assert.Equal(t, "Invalid request: request body is empty\n", string(d))
   125  }
   126  
   127  func TestShouldRespondWithBadRequestWhenRequestBodyIsInvalid(t *testing.T) {
   128  	// mock pbs cache client
   129  	mockCacheClient := &vtrackMockCacheClient{}
   130  
   131  	// mock AccountsFetcher
   132  	mockAccountsFetcher := &mockAccountsFetcher{}
   133  
   134  	// config
   135  	cfg := &config.Configuration{
   136  		MaxRequestSize:  maxSize,
   137  		AccountDefaults: config.Account{},
   138  	}
   139  	cfg.MarshalAccountDefaults()
   140  
   141  	// prepare
   142  	reqData := "invalid"
   143  
   144  	req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(reqData))
   145  
   146  	recorder := httptest.NewRecorder()
   147  
   148  	e := vtrackEndpoint{
   149  		Cfg:         cfg,
   150  		BidderInfos: nil,
   151  		Cache:       mockCacheClient,
   152  		Accounts:    mockAccountsFetcher,
   153  	}
   154  
   155  	// execute
   156  	e.Handle(recorder, req, nil)
   157  
   158  	// validate
   159  	assert.Equal(t, 400, recorder.Result().StatusCode, "Expected 400 on request with invalid body")
   160  }
   161  
   162  func TestShouldRespondWithBadRequestWhenBidIdIsMissing(t *testing.T) {
   163  	// mock pbs cache client
   164  	mockCacheClient := &vtrackMockCacheClient{}
   165  
   166  	// mock AccountsFetcher
   167  	mockAccountsFetcher := &mockAccountsFetcher{}
   168  
   169  	// config
   170  	cfg := &config.Configuration{
   171  		MaxRequestSize:  maxSize,
   172  		AccountDefaults: config.Account{},
   173  	}
   174  	cfg.MarshalAccountDefaults()
   175  
   176  	// prepare
   177  	data := &BidCacheRequest{
   178  		Puts: []prebid_cache_client.Cacheable{
   179  			{},
   180  		},
   181  	}
   182  
   183  	reqData, err := json.Marshal(data)
   184  	if err != nil {
   185  		t.Fatal(err)
   186  	}
   187  
   188  	req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(string(reqData)))
   189  
   190  	recorder := httptest.NewRecorder()
   191  
   192  	e := vtrackEndpoint{
   193  		Cfg:         cfg,
   194  		BidderInfos: nil,
   195  		Cache:       mockCacheClient,
   196  		Accounts:    mockAccountsFetcher,
   197  	}
   198  
   199  	// execute
   200  	e.Handle(recorder, req, nil)
   201  
   202  	d, err := io.ReadAll(recorder.Result().Body)
   203  	if err != nil {
   204  		t.Fatal(err)
   205  	}
   206  
   207  	// validate
   208  	assert.Equal(t, 400, recorder.Result().StatusCode, "Expected 400 on request with elements missing bidid")
   209  	assert.Equal(t, "Invalid request: 'bidid' is required field and can't be empty\n", string(d))
   210  }
   211  
   212  func TestShouldRespondWithBadRequestWhenBidderIsMissing(t *testing.T) {
   213  	// mock pbs cache client
   214  	mockCacheClient := &vtrackMockCacheClient{}
   215  
   216  	// mock AccountsFetcher
   217  	mockAccountsFetcher := &mockAccountsFetcher{}
   218  
   219  	// config
   220  	cfg := &config.Configuration{
   221  		MaxRequestSize:  maxSize,
   222  		AccountDefaults: config.Account{},
   223  	}
   224  	cfg.MarshalAccountDefaults()
   225  
   226  	// prepare
   227  	data := &BidCacheRequest{
   228  		Puts: []prebid_cache_client.Cacheable{
   229  			{
   230  				BidID: "test",
   231  			},
   232  		},
   233  	}
   234  
   235  	reqData, err := json.Marshal(data)
   236  	if err != nil {
   237  		t.Fatal(err)
   238  	}
   239  
   240  	req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(string(reqData)))
   241  
   242  	recorder := httptest.NewRecorder()
   243  
   244  	e := vtrackEndpoint{
   245  		Cfg:         cfg,
   246  		BidderInfos: nil,
   247  		Cache:       mockCacheClient,
   248  		Accounts:    mockAccountsFetcher,
   249  	}
   250  
   251  	// execute
   252  	e.Handle(recorder, req, nil)
   253  
   254  	d, err := io.ReadAll(recorder.Result().Body)
   255  	if err != nil {
   256  		t.Fatal(err)
   257  	}
   258  
   259  	// validate
   260  	assert.Equal(t, 400, recorder.Result().StatusCode, "Expected 400 on request with elements missing bidder")
   261  	assert.Equal(t, "Invalid request: 'bidder' is required field and can't be empty\n", string(d))
   262  }
   263  
   264  func TestShouldRespondWithInternalServerErrorWhenPbsCacheClientFails(t *testing.T) {
   265  	// mock pbs cache client
   266  	mockCacheClient := &vtrackMockCacheClient{
   267  		Fail:  true,
   268  		Error: fmt.Errorf("pbs cache client failed"),
   269  	}
   270  
   271  	// mock AccountsFetcher
   272  	mockAccountsFetcher := &mockAccountsFetcher{}
   273  
   274  	// config
   275  	cfg := &config.Configuration{
   276  		MaxRequestSize: maxSize, VTrack: config.VTrack{
   277  			TimeoutMS: int64(2000), AllowUnknownBidder: true,
   278  		},
   279  		AccountDefaults: config.Account{},
   280  	}
   281  	cfg.MarshalAccountDefaults()
   282  
   283  	// prepare
   284  	data, err := getValidVTrackRequestBody(false, false)
   285  	if err != nil {
   286  		t.Fatal(err)
   287  	}
   288  
   289  	req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(data))
   290  
   291  	recorder := httptest.NewRecorder()
   292  
   293  	e := vtrackEndpoint{
   294  		Cfg:         cfg,
   295  		BidderInfos: nil,
   296  		Cache:       mockCacheClient,
   297  		Accounts:    mockAccountsFetcher,
   298  	}
   299  
   300  	// execute
   301  	e.Handle(recorder, req, nil)
   302  
   303  	d, err := io.ReadAll(recorder.Result().Body)
   304  	if err != nil {
   305  		t.Fatal(err)
   306  	}
   307  
   308  	// validate
   309  	assert.Equal(t, 500, recorder.Result().StatusCode, "Expected 500 when pbs cache client fails")
   310  	assert.Equal(t, "Error(s) updating vast: pbs cache client failed\n", string(d))
   311  }
   312  
   313  func TestShouldTolerateAccountNotFound(t *testing.T) {
   314  	// mock pbs cache client
   315  	mockCacheClient := &vtrackMockCacheClient{}
   316  
   317  	// mock AccountsFetcher
   318  	mockAccountsFetcher := &mockAccountsFetcher{
   319  		Fail:  true,
   320  		Error: stored_requests.NotFoundError{},
   321  	}
   322  
   323  	// config
   324  	cfg := &config.Configuration{
   325  		MaxRequestSize: maxSize, VTrack: config.VTrack{
   326  			TimeoutMS: int64(2000), AllowUnknownBidder: false,
   327  		},
   328  		AccountDefaults: config.Account{},
   329  	}
   330  	cfg.MarshalAccountDefaults()
   331  
   332  	// prepare
   333  	data, err := getValidVTrackRequestBody(true, false)
   334  	if err != nil {
   335  		t.Fatal(err)
   336  	}
   337  
   338  	req := httptest.NewRequest("POST", "/vtrack?a=1235", strings.NewReader(data))
   339  
   340  	recorder := httptest.NewRecorder()
   341  
   342  	e := vtrackEndpoint{
   343  		Cfg:         cfg,
   344  		BidderInfos: nil,
   345  		Cache:       mockCacheClient,
   346  		Accounts:    mockAccountsFetcher,
   347  	}
   348  
   349  	// execute
   350  	e.Handle(recorder, req, nil)
   351  
   352  	// validate
   353  	assert.Equal(t, 200, recorder.Result().StatusCode, "Expected 200 when account is not found and request is valid")
   354  	assert.Equal(t, "application/json", recorder.Header().Get("Content-Type"))
   355  }
   356  
   357  func TestShouldSendToCacheExpectedPutsAndUpdatableBiddersWhenBidderVastNotAllowed(t *testing.T) {
   358  	// mock pbs cache client
   359  	mockCacheClient := &vtrackMockCacheClient{
   360  		Fail:  false,
   361  		Uuids: []string{"uuid1"},
   362  	}
   363  
   364  	// mock AccountsFetcher
   365  	mockAccountsFetcher := &mockAccountsFetcher{
   366  		Fail: false,
   367  	}
   368  
   369  	// config
   370  	cfg := &config.Configuration{
   371  		MaxRequestSize: maxSize, VTrack: config.VTrack{
   372  			TimeoutMS: int64(2000), AllowUnknownBidder: false,
   373  		},
   374  		AccountDefaults: config.Account{},
   375  	}
   376  	cfg.MarshalAccountDefaults()
   377  
   378  	// bidder info
   379  	bidderInfos := make(config.BidderInfos)
   380  	bidderInfos["bidder"] = config.BidderInfo{
   381  		Disabled:                false,
   382  		ModifyingVastXmlAllowed: false,
   383  	}
   384  	bidderInfos["updatable_bidder"] = config.BidderInfo{
   385  		Disabled:                false,
   386  		ModifyingVastXmlAllowed: true,
   387  	}
   388  
   389  	// prepare
   390  	data, err := getValidVTrackRequestBody(false, false)
   391  	if err != nil {
   392  		t.Fatal(err)
   393  	}
   394  
   395  	req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(data))
   396  
   397  	recorder := httptest.NewRecorder()
   398  
   399  	e := vtrackEndpoint{
   400  		Cfg:         cfg,
   401  		BidderInfos: bidderInfos,
   402  		Cache:       mockCacheClient,
   403  		Accounts:    mockAccountsFetcher,
   404  	}
   405  
   406  	// execute
   407  	e.Handle(recorder, req, nil)
   408  
   409  	d, err := io.ReadAll(recorder.Result().Body)
   410  	if err != nil {
   411  		t.Fatal(err)
   412  	}
   413  
   414  	// validate
   415  	assert.Equal(t, 200, recorder.Result().StatusCode, "Expected 200 when account is not found and request is valid")
   416  	assert.Equal(t, "{\"responses\":[{\"uuid\":\"uuid1\"}]}", string(d), "Expected 200 when account is found and request is valid")
   417  	assert.Equal(t, "application/json", recorder.Header().Get("Content-Type"))
   418  }
   419  
   420  func TestShouldSendToCacheExpectedPutsAndUpdatableBiddersWhenBidderVastAllowed(t *testing.T) {
   421  	// mock pbs cache client
   422  	mockCacheClient := &vtrackMockCacheClient{
   423  		Fail:  false,
   424  		Uuids: []string{"uuid1", "uuid2"},
   425  	}
   426  
   427  	// mock AccountsFetcher
   428  	mockAccountsFetcher := &mockAccountsFetcher{
   429  		Fail: false,
   430  	}
   431  
   432  	// config
   433  	cfg := &config.Configuration{
   434  		MaxRequestSize: maxSize, VTrack: config.VTrack{
   435  			TimeoutMS: int64(2000), AllowUnknownBidder: false,
   436  		},
   437  		AccountDefaults: config.Account{},
   438  	}
   439  	cfg.MarshalAccountDefaults()
   440  
   441  	// bidder info
   442  	bidderInfos := make(config.BidderInfos)
   443  	bidderInfos["bidder"] = config.BidderInfo{
   444  		Disabled:                false,
   445  		ModifyingVastXmlAllowed: true,
   446  	}
   447  	bidderInfos["updatable_bidder"] = config.BidderInfo{
   448  		Disabled:                false,
   449  		ModifyingVastXmlAllowed: true,
   450  	}
   451  
   452  	// prepare
   453  	data, err := getValidVTrackRequestBody(true, true)
   454  	if err != nil {
   455  		t.Fatal(err)
   456  	}
   457  
   458  	req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(data))
   459  
   460  	recorder := httptest.NewRecorder()
   461  
   462  	e := vtrackEndpoint{
   463  		Cfg:         cfg,
   464  		BidderInfos: bidderInfos,
   465  		Cache:       mockCacheClient,
   466  		Accounts:    mockAccountsFetcher,
   467  	}
   468  
   469  	// execute
   470  	e.Handle(recorder, req, nil)
   471  
   472  	d, err := io.ReadAll(recorder.Result().Body)
   473  	if err != nil {
   474  		t.Fatal(err)
   475  	}
   476  
   477  	// validate
   478  	assert.Equal(t, 200, recorder.Result().StatusCode, "Expected 200 when account is not found and request is valid")
   479  	assert.Equal(t, "{\"responses\":[{\"uuid\":\"uuid1\"},{\"uuid\":\"uuid2\"}]}", string(d), "Expected 200 when account is found and request is valid")
   480  	assert.Equal(t, "application/json", recorder.Header().Get("Content-Type"))
   481  }
   482  
   483  func TestShouldSendToCacheExpectedPutsAndUpdatableUnknownBiddersWhenUnknownBidderIsAllowed(t *testing.T) {
   484  	// mock pbs cache client
   485  	mockCacheClient := &vtrackMockCacheClient{
   486  		Fail:  false,
   487  		Uuids: []string{"uuid1", "uuid2"},
   488  	}
   489  
   490  	// mock AccountsFetcher
   491  	mockAccountsFetcher := &mockAccountsFetcher{
   492  		Fail: false,
   493  	}
   494  
   495  	// config
   496  	cfg := &config.Configuration{
   497  		MaxRequestSize: maxSize, VTrack: config.VTrack{
   498  			TimeoutMS: int64(2000), AllowUnknownBidder: true,
   499  		},
   500  		AccountDefaults: config.Account{},
   501  	}
   502  	cfg.MarshalAccountDefaults()
   503  
   504  	// bidder info
   505  	bidderInfos := make(config.BidderInfos)
   506  
   507  	// prepare
   508  	data, err := getValidVTrackRequestBody(true, false)
   509  	if err != nil {
   510  		t.Fatal(err)
   511  	}
   512  
   513  	req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(data))
   514  
   515  	recorder := httptest.NewRecorder()
   516  
   517  	e := vtrackEndpoint{
   518  		Cfg:         cfg,
   519  		BidderInfos: bidderInfos,
   520  		Cache:       mockCacheClient,
   521  		Accounts:    mockAccountsFetcher,
   522  	}
   523  
   524  	// execute
   525  	e.Handle(recorder, req, nil)
   526  
   527  	d, err := io.ReadAll(recorder.Result().Body)
   528  	if err != nil {
   529  		t.Fatal(err)
   530  	}
   531  
   532  	// validate
   533  	assert.Equal(t, 200, recorder.Result().StatusCode, "Expected 200 when account is not found and request is valid")
   534  	assert.Equal(t, "{\"responses\":[{\"uuid\":\"uuid1\"},{\"uuid\":\"uuid2\"}]}", string(d), "Expected 200 when account is found, request has unknown bidders but allowUnknownBidders is enabled")
   535  	assert.Equal(t, "application/json", recorder.Header().Get("Content-Type"))
   536  }
   537  
   538  func TestShouldReturnBadRequestWhenRequestExceedsMaxRequestSize(t *testing.T) {
   539  	// mock pbs cache client
   540  	mockCacheClient := &vtrackMockCacheClient{
   541  		Fail:  false,
   542  		Uuids: []string{"uuid1", "uuid2"},
   543  	}
   544  
   545  	// mock AccountsFetcher
   546  	mockAccountsFetcher := &mockAccountsFetcher{
   547  		Fail: false,
   548  	}
   549  
   550  	// config
   551  	cfg := &config.Configuration{
   552  		MaxRequestSize: 1,
   553  		VTrack: config.VTrack{
   554  			TimeoutMS: int64(2000), AllowUnknownBidder: true,
   555  		},
   556  		AccountDefaults: config.Account{},
   557  	}
   558  	cfg.MarshalAccountDefaults()
   559  
   560  	// bidder info
   561  	bidderInfos := make(config.BidderInfos)
   562  
   563  	// prepare
   564  	data, err := getValidVTrackRequestBody(true, false)
   565  	if err != nil {
   566  		t.Fatal(err)
   567  	}
   568  
   569  	req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(data))
   570  
   571  	recorder := httptest.NewRecorder()
   572  
   573  	e := vtrackEndpoint{
   574  		Cfg:         cfg,
   575  		BidderInfos: bidderInfos,
   576  		Cache:       mockCacheClient,
   577  		Accounts:    mockAccountsFetcher,
   578  	}
   579  
   580  	// execute
   581  	e.Handle(recorder, req, nil)
   582  
   583  	d, err := io.ReadAll(recorder.Result().Body)
   584  	if err != nil {
   585  		t.Fatal(err)
   586  	}
   587  
   588  	// validate
   589  	assert.Equal(t, 400, recorder.Result().StatusCode, "Expected 400 when request exceeds max request size")
   590  	assert.Equal(t, "Invalid request: request size exceeded max size of 1 bytes\n", string(d))
   591  }
   592  
   593  func TestShouldRespondWithInternalErrorPbsCacheIsNotConfigured(t *testing.T) {
   594  	// mock AccountsFetcher
   595  	mockAccountsFetcher := &mockAccountsFetcher{
   596  		Fail: false,
   597  	}
   598  
   599  	// config
   600  	cfg := &config.Configuration{
   601  		MaxRequestSize: maxSize, VTrack: config.VTrack{
   602  			TimeoutMS: int64(2000), AllowUnknownBidder: false,
   603  		},
   604  		AccountDefaults: config.Account{},
   605  	}
   606  	cfg.MarshalAccountDefaults()
   607  
   608  	// prepare
   609  	data, err := getValidVTrackRequestBody(true, true)
   610  	if err != nil {
   611  		t.Fatal(err)
   612  	}
   613  
   614  	req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(data))
   615  	recorder := httptest.NewRecorder()
   616  
   617  	e := vtrackEndpoint{
   618  		Cfg:         cfg,
   619  		BidderInfos: nil,
   620  		Cache:       nil,
   621  		Accounts:    mockAccountsFetcher,
   622  	}
   623  
   624  	// execute
   625  	e.Handle(recorder, req, nil)
   626  
   627  	d, err := io.ReadAll(recorder.Result().Body)
   628  	if err != nil {
   629  		t.Fatal(err)
   630  	}
   631  
   632  	// validate
   633  	assert.Equal(t, 500, recorder.Result().StatusCode, "Expected 500 when pbs cache is not configured")
   634  	assert.Equal(t, "PBS Cache client is not configured", string(d))
   635  }
   636  
   637  func TestVastUrlShouldReturnExpectedUrl(t *testing.T) {
   638  	url := GetVastUrlTracking("http://external-url", "bidId", "bidder", "accountId", 1000, "integrationType")
   639  	assert.Equal(t, "http://external-url/event?t=imp&b=bidId&a=accountId&bidder=bidder&f=b&int=integrationType&ts=1000", url, "Invalid vast url")
   640  }
   641  
   642  func getValidVTrackRequestBody(withImpression bool, withContent bool) (string, error) {
   643  	d, e := getVTrackRequestData(withImpression, withContent)
   644  
   645  	if e != nil {
   646  		return "", e
   647  	}
   648  
   649  	req := &BidCacheRequest{
   650  		Puts: []prebid_cache_client.Cacheable{
   651  			{
   652  				Type:       prebid_cache_client.TypeXML,
   653  				BidID:      "bidId1",
   654  				Bidder:     "bidder",
   655  				Data:       d,
   656  				TTLSeconds: 3600,
   657  				Timestamp:  1000,
   658  			},
   659  			{
   660  				Type:       prebid_cache_client.TypeXML,
   661  				BidID:      "bidId2",
   662  				Bidder:     "updatable_bidder",
   663  				Data:       d,
   664  				TTLSeconds: 3600,
   665  				Timestamp:  1000,
   666  			},
   667  		},
   668  	}
   669  
   670  	buf := &bytes.Buffer{}
   671  	enc := json.NewEncoder(buf)
   672  	enc.SetEscapeHTML(false)
   673  
   674  	e = enc.Encode(req)
   675  
   676  	return buf.String(), e
   677  }
   678  
   679  func getVTrackRequestData(wi bool, wic bool) (db []byte, e error) {
   680  	data := &bytes.Buffer{}
   681  	enc := json.NewEncoder(data)
   682  	enc.SetEscapeHTML(false)
   683  
   684  	if wi && wic {
   685  		e = enc.Encode(vastXmlWithImpressionWithContent)
   686  		return data.Bytes(), e
   687  	} else if wi {
   688  		e = enc.Encode(vastXmlWithImpressionWithoutContent)
   689  	} else {
   690  		enc.Encode(vastXmlWithoutImpression)
   691  	}
   692  
   693  	return data.Bytes(), e
   694  }
   695  
   696  func TestGetIntegrationType(t *testing.T) {
   697  	testCases := []struct {
   698  		description             string
   699  		givenHttpRequest        *http.Request
   700  		expectedIntegrationType string
   701  		expectedError           error
   702  	}{
   703  		{
   704  			description:             "Integration type in http request is valid, expect same integration time and no errors",
   705  			givenHttpRequest:        httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=TestIntegrationType", strings.NewReader("")),
   706  			expectedIntegrationType: "TestIntegrationType",
   707  			expectedError:           nil,
   708  		},
   709  		{
   710  			description:      "Integration type in http request is too long, expect too long error",
   711  			givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=TestIntegrationTypeTooLongTestIntegrationTypeTooLongTestIntegrationType", strings.NewReader("")),
   712  			expectedError:    errors.New("integration type length is too long"),
   713  		},
   714  		{
   715  			description:      "Integration type in http request contains invalid character, expect invalid character error",
   716  			givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=Te$tIntegrationType", strings.NewReader("")),
   717  			expectedError:    errors.New("integration type can only contain numbers, letters and these characters '-', '_'"),
   718  		},
   719  	}
   720  
   721  	for _, test := range testCases {
   722  		integrationType, err := getIntegrationType(test.givenHttpRequest)
   723  		if test.expectedError != nil {
   724  			assert.Equal(t, test.expectedError, err, test.description)
   725  		} else {
   726  			assert.Empty(t, err, test.description)
   727  			assert.Equalf(t, test.expectedIntegrationType, integrationType, test.description)
   728  		}
   729  	}
   730  }