github.com/prebid/prebid-server/v2@v2.18.0/gdpr/impl_test.go (about)

     1  package gdpr
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"testing"
     8  
     9  	"github.com/prebid/go-gdpr/consentconstants"
    10  	"github.com/prebid/go-gdpr/vendorlist"
    11  	"github.com/prebid/go-gdpr/vendorlist2"
    12  	"github.com/prebid/prebid-server/v2/config"
    13  	"github.com/prebid/prebid-server/v2/openrtb_ext"
    14  
    15  	"github.com/stretchr/testify/assert"
    16  )
    17  
    18  func TestDisallowOnEmptyConsent(t *testing.T) {
    19  	emptyConsent := ""
    20  	perms := permissionsImpl{
    21  		cfg:              &tcf2Config{},
    22  		fetchVendorList:  failedListFetcher,
    23  		gdprDefaultValue: "0",
    24  		hostVendorID:     3,
    25  		vendorIDs:        nil,
    26  		gdprSignal:       SignalYes,
    27  		consent:          emptyConsent,
    28  	}
    29  
    30  	allowSync, err := perms.BidderSyncAllowed(context.Background(), openrtb_ext.BidderAppnexus)
    31  	assertBoolsEqual(t, false, allowSync)
    32  	assertNilErr(t, err)
    33  	allowSync, err = perms.HostCookiesAllowed(context.Background())
    34  	assertBoolsEqual(t, false, allowSync)
    35  	assertNilErr(t, err)
    36  }
    37  
    38  func TestAllowOnSignalNo(t *testing.T) {
    39  	emptyConsent := ""
    40  	perms := permissionsImpl{
    41  		gdprSignal: SignalNo,
    42  		consent:    emptyConsent,
    43  	}
    44  
    45  	allowSync, err := perms.HostCookiesAllowed(context.Background())
    46  	assert.Equal(t, true, allowSync)
    47  	assert.Nil(t, err)
    48  
    49  	allowSync, err = perms.BidderSyncAllowed(context.Background(), openrtb_ext.BidderAppnexus)
    50  	assert.Equal(t, true, allowSync)
    51  	assert.Nil(t, err)
    52  }
    53  
    54  func TestAllowedSyncs(t *testing.T) {
    55  	vendor2AndPurpose1Consent := "CPGWbY_PGWbY_GYAAAENABCAAIAAAAAAAAAAACEAAAAA"
    56  	vendorListData := MarshalVendorList(vendorList{
    57  		VendorListVersion: 2,
    58  		Vendors: map[string]*vendor{
    59  			"2": {
    60  				ID:       2,
    61  				Purposes: []int{1},
    62  			},
    63  		},
    64  	})
    65  
    66  	tcf2AggConfig := tcf2Config{
    67  		HostConfig: config.TCF2{
    68  			Purpose1: config.TCF2Purpose{
    69  				EnforcePurpose: true,
    70  				EnforceVendors: true,
    71  			},
    72  		},
    73  	}
    74  	tcf2AggConfig.HostConfig.PurposeConfigs = map[consentconstants.Purpose]*config.TCF2Purpose{
    75  		consentconstants.Purpose(1): &tcf2AggConfig.HostConfig.Purpose1,
    76  	}
    77  
    78  	perms := permissionsImpl{
    79  		cfg:          &tcf2AggConfig,
    80  		hostVendorID: 2,
    81  		vendorIDs: map[openrtb_ext.BidderName]uint16{
    82  			openrtb_ext.BidderAppnexus: 2,
    83  		},
    84  		fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
    85  			2: {
    86  				1: parseVendorListDataV2(t, vendorListData),
    87  			},
    88  		}),
    89  		purposeEnforcerBuilder: NewPurposeEnforcerBuilder(&tcf2AggConfig),
    90  		gdprSignal:             SignalYes,
    91  		consent:                vendor2AndPurpose1Consent,
    92  	}
    93  
    94  	allowSync, err := perms.HostCookiesAllowed(context.Background())
    95  	assertNilErr(t, err)
    96  	assertBoolsEqual(t, true, allowSync)
    97  
    98  	allowSync, err = perms.BidderSyncAllowed(context.Background(), openrtb_ext.BidderAppnexus)
    99  	assertNilErr(t, err)
   100  	assertBoolsEqual(t, true, allowSync)
   101  }
   102  
   103  func TestProhibitedPurposes(t *testing.T) {
   104  	vendor2NoPurpose1Consent := "CPGWkCaPGWkCaApAAAENABCAAAAAAAAAAAAAABEAAAAA"
   105  	vendorListData := MarshalVendorList(vendorList{
   106  		VendorListVersion: 2,
   107  		Vendors: map[string]*vendor{
   108  			"2": {
   109  				ID:       2,
   110  				Purposes: []int{1},
   111  			},
   112  		},
   113  	})
   114  
   115  	tcf2AggConfig := tcf2Config{
   116  		HostConfig: config.TCF2{
   117  			Purpose1: config.TCF2Purpose{
   118  				EnforcePurpose: true,
   119  			},
   120  		},
   121  	}
   122  	tcf2AggConfig.HostConfig.PurposeConfigs = map[consentconstants.Purpose]*config.TCF2Purpose{
   123  		consentconstants.Purpose(1): &tcf2AggConfig.HostConfig.Purpose1,
   124  	}
   125  
   126  	perms := permissionsImpl{
   127  		cfg:          &tcf2AggConfig,
   128  		hostVendorID: 2,
   129  		vendorIDs: map[openrtb_ext.BidderName]uint16{
   130  			openrtb_ext.BidderAppnexus: 2,
   131  		},
   132  		fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
   133  			2: {
   134  				1: parseVendorListDataV2(t, vendorListData),
   135  			},
   136  		}),
   137  		purposeEnforcerBuilder: NewPurposeEnforcerBuilder(&tcf2AggConfig),
   138  		gdprSignal:             SignalYes,
   139  		consent:                vendor2NoPurpose1Consent,
   140  	}
   141  
   142  	allowSync, err := perms.HostCookiesAllowed(context.Background())
   143  	assertNilErr(t, err)
   144  	assertBoolsEqual(t, false, allowSync)
   145  
   146  	allowSync, err = perms.BidderSyncAllowed(context.Background(), openrtb_ext.BidderAppnexus)
   147  	assertNilErr(t, err)
   148  	assertBoolsEqual(t, false, allowSync)
   149  }
   150  
   151  func TestProhibitedVendors(t *testing.T) {
   152  	purpose1NoVendorConsent := "CPGWkCaPGWkCaApAAAENABCAAIAAAAAAAAAAABAAAAAA"
   153  	vendorListData := MarshalVendorList(vendorList{
   154  		VendorListVersion: 2,
   155  		Vendors: map[string]*vendor{
   156  			"2": {
   157  				ID:       2,
   158  				Purposes: []int{1},
   159  			},
   160  		},
   161  	})
   162  
   163  	tcf2AggConfig := tcf2Config{
   164  		HostConfig: config.TCF2{
   165  			Purpose1: config.TCF2Purpose{
   166  				EnforcePurpose: true,
   167  				EnforceVendors: true,
   168  			},
   169  		},
   170  	}
   171  	tcf2AggConfig.HostConfig.PurposeConfigs = map[consentconstants.Purpose]*config.TCF2Purpose{
   172  		consentconstants.Purpose(1): &tcf2AggConfig.HostConfig.Purpose1,
   173  	}
   174  
   175  	perms := permissionsImpl{
   176  		cfg:          &tcf2AggConfig,
   177  		hostVendorID: 2,
   178  		vendorIDs: map[openrtb_ext.BidderName]uint16{
   179  			openrtb_ext.BidderAppnexus: 2,
   180  		},
   181  		fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
   182  			2: {
   183  				1: parseVendorListDataV2(t, vendorListData),
   184  			},
   185  		}),
   186  		purposeEnforcerBuilder: NewPurposeEnforcerBuilder(&tcf2AggConfig),
   187  		gdprSignal:             SignalYes,
   188  		consent:                purpose1NoVendorConsent,
   189  	}
   190  
   191  	allowSync, err := perms.HostCookiesAllowed(context.Background())
   192  	assertNilErr(t, err)
   193  	assertBoolsEqual(t, false, allowSync)
   194  
   195  	allowSync, err = perms.BidderSyncAllowed(context.Background(), openrtb_ext.BidderPubmatic)
   196  	assertNilErr(t, err)
   197  	assertBoolsEqual(t, false, allowSync)
   198  }
   199  
   200  func TestMalformedConsent(t *testing.T) {
   201  	perms := permissionsImpl{
   202  		hostVendorID:    2,
   203  		fetchVendorList: listFetcher(nil),
   204  		gdprSignal:      SignalYes,
   205  		consent:         "BON",
   206  	}
   207  
   208  	sync, err := perms.HostCookiesAllowed(context.Background())
   209  	assertErr(t, err, true)
   210  	assertBoolsEqual(t, false, sync)
   211  }
   212  
   213  func TestAllowActivities(t *testing.T) {
   214  	bidderAllowedByConsent := openrtb_ext.BidderAppnexus
   215  	aliasedBidderAllowedByConsent := openrtb_ext.BidderName("appnexus1")
   216  	bidderBlockedByConsent := openrtb_ext.BidderRubicon
   217  	vendor2AndPurpose2Consent := "CPGWbY_PGWbY_GYAAAENABCAAEAAAAAAAAAAACEAAAAA"
   218  
   219  	tests := []struct {
   220  		description           string
   221  		bidderName            openrtb_ext.BidderName
   222  		bidderCoreName        openrtb_ext.BidderName
   223  		publisherID           string
   224  		gdpr                  Signal
   225  		consent               string
   226  		passID                bool
   227  		weakVendorEnforcement bool
   228  		aliasGVLIDs           map[string]uint16
   229  	}{
   230  		{
   231  			description:    "Allow PI - Non standard publisher",
   232  			bidderName:     bidderBlockedByConsent,
   233  			bidderCoreName: bidderBlockedByConsent,
   234  			publisherID:    "appNexusAppID",
   235  			gdpr:           SignalYes,
   236  			consent:        vendor2AndPurpose2Consent,
   237  			passID:         true,
   238  		},
   239  		{
   240  			description:    "Allow PI - known vendor with No GDPR",
   241  			bidderName:     bidderBlockedByConsent,
   242  			bidderCoreName: bidderBlockedByConsent,
   243  			gdpr:           SignalNo,
   244  			consent:        vendor2AndPurpose2Consent,
   245  			passID:         true,
   246  		},
   247  		{
   248  			description:    "Allow PI - known vendor with Yes GDPR",
   249  			bidderName:     bidderAllowedByConsent,
   250  			bidderCoreName: bidderAllowedByConsent,
   251  			gdpr:           SignalYes,
   252  			consent:        vendor2AndPurpose2Consent,
   253  			passID:         true,
   254  		},
   255  		{
   256  			description:    "Allow PI - known Alias vendor GVLID with Yes GDPR",
   257  			bidderName:     aliasedBidderAllowedByConsent,
   258  			bidderCoreName: bidderAllowedByConsent,
   259  			gdpr:           SignalYes,
   260  			consent:        vendor2AndPurpose2Consent,
   261  			passID:         true,
   262  			aliasGVLIDs:    map[string]uint16{"appnexus1": 2},
   263  		},
   264  		{
   265  			description:    "Don't allow PI - known alias vendor with Yes GDPR, alias vendor does not consent to purpose 2",
   266  			bidderName:     aliasedBidderAllowedByConsent,
   267  			bidderCoreName: bidderAllowedByConsent,
   268  			gdpr:           SignalYes,
   269  			consent:        vendor2AndPurpose2Consent,
   270  			passID:         false,
   271  			aliasGVLIDs:    map[string]uint16{"appnexus1": 1},
   272  		},
   273  		{
   274  			description:    "Allow PI - known vendor with Ambiguous GDPR and empty consent",
   275  			bidderName:     bidderAllowedByConsent,
   276  			bidderCoreName: bidderAllowedByConsent,
   277  			gdpr:           SignalAmbiguous,
   278  			consent:        "",
   279  			passID:         true,
   280  		},
   281  		{
   282  			description:    "Allow PI - known vendor with Ambiguous GDPR and non-empty consent",
   283  			bidderName:     bidderAllowedByConsent,
   284  			bidderCoreName: bidderAllowedByConsent,
   285  			gdpr:           SignalAmbiguous,
   286  			consent:        vendor2AndPurpose2Consent,
   287  			passID:         true,
   288  		},
   289  		{
   290  			description:    "Don't allow PI - known vendor with Yes GDPR and empty consent",
   291  			bidderName:     bidderAllowedByConsent,
   292  			bidderCoreName: bidderAllowedByConsent,
   293  			gdpr:           SignalYes,
   294  			consent:        "",
   295  			passID:         false,
   296  		},
   297  		{
   298  			description:    "Don't allow PI - default vendor with Yes GDPR and non-empty consent",
   299  			bidderName:     bidderBlockedByConsent,
   300  			bidderCoreName: bidderBlockedByConsent,
   301  			gdpr:           SignalYes,
   302  			consent:        vendor2AndPurpose2Consent,
   303  			passID:         false,
   304  		},
   305  	}
   306  	vendorListData := MarshalVendorList(vendorList{
   307  		VendorListVersion: 1,
   308  		Vendors: map[string]*vendor{
   309  			"2": {
   310  				ID:       2,
   311  				Purposes: []int{2},
   312  			},
   313  		},
   314  	})
   315  	tcf2AggConfig := allPurposesEnabledTCF2Config()
   316  
   317  	perms := permissionsImpl{
   318  		cfg:                   &tcf2AggConfig,
   319  		hostVendorID:          2,
   320  		nonStandardPublishers: map[string]struct{}{"appNexusAppID": {}},
   321  		vendorIDs: map[openrtb_ext.BidderName]uint16{
   322  			openrtb_ext.BidderAppnexus: 2,
   323  		},
   324  		fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
   325  			2: {
   326  				1: parseVendorListDataV2(t, vendorListData),
   327  			},
   328  		}),
   329  		purposeEnforcerBuilder: NewPurposeEnforcerBuilder(&tcf2AggConfig),
   330  	}
   331  
   332  	for _, tt := range tests {
   333  		perms.aliasGVLIDs = tt.aliasGVLIDs
   334  		perms.consent = tt.consent
   335  		perms.gdprSignal = tt.gdpr
   336  		perms.publisherID = tt.publisherID
   337  
   338  		permissions, err := perms.AuctionActivitiesAllowed(context.Background(), tt.bidderCoreName, tt.bidderName)
   339  
   340  		assert.Nil(t, err, tt.description)
   341  		assert.Equal(t, tt.passID, permissions.PassID, tt.description)
   342  	}
   343  }
   344  
   345  func TestAllowActivitiesBidderWithoutGVLID(t *testing.T) {
   346  	bidderWithoutGVLID := openrtb_ext.BidderPangle
   347  	purpose2Consent := "CPuDXznPuDXznMOAAAENCZCAAEAAAAAAAAAAAAAAAAAA"
   348  	noPurposeConsent := "CPuDXznPuDXznMOAAAENCZCAAAAAAAAAAAAAAAAAAAAA"
   349  
   350  	tests := []struct {
   351  		name                    string
   352  		enforceAlgoID           config.TCF2EnforcementAlgo
   353  		vendorExceptions        map[string]struct{}
   354  		basicEnforcementVendors map[string]struct{}
   355  		consent                 string
   356  		allowBidRequest         bool
   357  		passID                  bool
   358  	}{
   359  		{
   360  			name:          "full_enforcement_no_exceptions_user_consents_to_purpose_2",
   361  			enforceAlgoID: config.TCF2FullEnforcement,
   362  			consent:       purpose2Consent,
   363  		},
   364  		{
   365  			name:             "full_enforcement_vendor_exception_user_consents_to_purpose_2",
   366  			enforceAlgoID:    config.TCF2FullEnforcement,
   367  			vendorExceptions: map[string]struct{}{string(bidderWithoutGVLID): {}},
   368  			consent:          purpose2Consent,
   369  			allowBidRequest:  true,
   370  			passID:           true,
   371  		},
   372  		{
   373  			name:    "basic_enforcement_no_exceptions_user_consents_to_purpose_2",
   374  			consent: purpose2Consent,
   375  		},
   376  		{
   377  			name:             "basic_enforcement_vendor_exception_user_consents_to_purpose_2",
   378  			vendorExceptions: map[string]struct{}{string(bidderWithoutGVLID): {}},
   379  			consent:          purpose2Consent,
   380  			allowBidRequest:  true,
   381  			passID:           true,
   382  		},
   383  		{
   384  			name:                    "full_enforcement_soft_vendor_exception_user_consents_to_purpose_2", // allow bid request and pass ID
   385  			enforceAlgoID:           config.TCF2FullEnforcement,
   386  			basicEnforcementVendors: map[string]struct{}{string(bidderWithoutGVLID): {}},
   387  			consent:                 purpose2Consent,
   388  			allowBidRequest:         true,
   389  			passID:                  true,
   390  		},
   391  		{
   392  			name:                    "basic_enforcement_soft_vendor_exception_user_consents_to_purpose_2", // allow bid request and pass ID
   393  			enforceAlgoID:           config.TCF2BasicEnforcement,
   394  			basicEnforcementVendors: map[string]struct{}{string(bidderWithoutGVLID): {}},
   395  			consent:                 purpose2Consent,
   396  			allowBidRequest:         true,
   397  			passID:                  true,
   398  		},
   399  		{
   400  			name:                    "full_enforcement_soft_vendor_exception_user_consents_to_purpose_4",
   401  			enforceAlgoID:           config.TCF2FullEnforcement,
   402  			basicEnforcementVendors: map[string]struct{}{string(bidderWithoutGVLID): {}},
   403  			consent:                 noPurposeConsent,
   404  			allowBidRequest:         false,
   405  			passID:                  false,
   406  		},
   407  		{
   408  			name:                    "basic_enforcement_soft_vendor_exception_user_consents_to_purpose_4",
   409  			enforceAlgoID:           config.TCF2BasicEnforcement,
   410  			basicEnforcementVendors: map[string]struct{}{string(bidderWithoutGVLID): {}},
   411  			consent:                 noPurposeConsent,
   412  			allowBidRequest:         false,
   413  			passID:                  false,
   414  		},
   415  	}
   416  
   417  	for _, tt := range tests {
   418  		t.Run(tt.name, func(t *testing.T) {
   419  			tcf2AggConfig := allPurposesEnabledTCF2Config()
   420  			tcf2AggConfig.AccountConfig.BasicEnforcementVendorsMap = tt.basicEnforcementVendors
   421  			tcf2AggConfig.HostConfig.Purpose2.VendorExceptionMap = tt.vendorExceptions
   422  			tcf2AggConfig.HostConfig.Purpose2.EnforceAlgoID = tt.enforceAlgoID
   423  			tcf2AggConfig.HostConfig.PurposeConfigs[consentconstants.Purpose(2)] = &tcf2AggConfig.HostConfig.Purpose2
   424  
   425  			perms := permissionsImpl{
   426  				cfg:                   &tcf2AggConfig,
   427  				consent:               tt.consent,
   428  				gdprSignal:            SignalYes,
   429  				hostVendorID:          2,
   430  				nonStandardPublishers: map[string]struct{}{},
   431  				vendorIDs:             map[openrtb_ext.BidderName]uint16{},
   432  				fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
   433  					2: {
   434  						153: parseVendorListDataV2(t, MarshalVendorList(vendorList{GVLSpecificationVersion: 2, VendorListVersion: 153, Vendors: map[string]*vendor{}})),
   435  					},
   436  				}),
   437  				purposeEnforcerBuilder: NewPurposeEnforcerBuilder(&tcf2AggConfig),
   438  			}
   439  
   440  			permissions, err := perms.AuctionActivitiesAllowed(context.Background(), bidderWithoutGVLID, bidderWithoutGVLID)
   441  			assert.NoError(t, err)
   442  			assert.Equal(t, tt.allowBidRequest, permissions.AllowBidRequest)
   443  			assert.Equal(t, tt.passID, permissions.PassID)
   444  		})
   445  	}
   446  }
   447  
   448  func buildVendorList34() vendorList {
   449  	return vendorList{
   450  		VendorListVersion: 2,
   451  		Vendors: map[string]*vendor{
   452  			"2": {
   453  				ID:       2,
   454  				Purposes: []int{1},
   455  			},
   456  			"6": {
   457  				ID:               6,
   458  				Purposes:         []int{1, 2, 4},
   459  				LegIntPurposes:   []int{7},
   460  				SpecialFeatures:  []int{1},
   461  				FlexiblePurposes: []int{1, 2, 4, 7},
   462  			},
   463  			"8": {
   464  				ID:             8,
   465  				Purposes:       []int{1, 7},
   466  				LegIntPurposes: []int{2, 4},
   467  			},
   468  			"10": {
   469  				ID:              10,
   470  				Purposes:        []int{2, 4, 7},
   471  				SpecialFeatures: []int{1},
   472  			},
   473  			"20": {
   474  				ID:               20,
   475  				Purposes:         []int{1},
   476  				LegIntPurposes:   []int{2, 7},
   477  				FlexiblePurposes: []int{2, 7},
   478  			},
   479  			"32": {
   480  				ID:       32,
   481  				Purposes: []int{1, 2, 4, 7},
   482  			},
   483  		},
   484  	}
   485  }
   486  
   487  func allPurposesEnabledTCF2Config() (TCF2AggConfig tcf2Config) {
   488  	TCF2AggConfig = tcf2Config{
   489  		HostConfig: config.TCF2{
   490  			Enabled:         true,
   491  			Purpose1:        config.TCF2Purpose{EnforceAlgoID: config.TCF2FullEnforcement, EnforcePurpose: true, EnforceVendors: true},
   492  			Purpose2:        config.TCF2Purpose{EnforceAlgoID: config.TCF2FullEnforcement, EnforcePurpose: true, EnforceVendors: true},
   493  			Purpose3:        config.TCF2Purpose{EnforceAlgoID: config.TCF2FullEnforcement, EnforcePurpose: true, EnforceVendors: true},
   494  			Purpose4:        config.TCF2Purpose{EnforceAlgoID: config.TCF2FullEnforcement, EnforcePurpose: true, EnforceVendors: true},
   495  			Purpose5:        config.TCF2Purpose{EnforceAlgoID: config.TCF2FullEnforcement, EnforcePurpose: true, EnforceVendors: true},
   496  			Purpose6:        config.TCF2Purpose{EnforceAlgoID: config.TCF2FullEnforcement, EnforcePurpose: true, EnforceVendors: true},
   497  			Purpose7:        config.TCF2Purpose{EnforceAlgoID: config.TCF2FullEnforcement, EnforcePurpose: true, EnforceVendors: true},
   498  			Purpose8:        config.TCF2Purpose{EnforceAlgoID: config.TCF2FullEnforcement, EnforcePurpose: true, EnforceVendors: true},
   499  			Purpose9:        config.TCF2Purpose{EnforceAlgoID: config.TCF2FullEnforcement, EnforcePurpose: true, EnforceVendors: true},
   500  			Purpose10:       config.TCF2Purpose{EnforceAlgoID: config.TCF2FullEnforcement, EnforcePurpose: true, EnforceVendors: true},
   501  			SpecialFeature1: config.TCF2SpecialFeature{Enforce: true},
   502  		},
   503  		AccountConfig: config.AccountGDPR{
   504  			PurposeConfigs: map[consentconstants.Purpose]*config.AccountGDPRPurpose{
   505  				consentconstants.Purpose(1):  {},
   506  				consentconstants.Purpose(2):  {},
   507  				consentconstants.Purpose(3):  {},
   508  				consentconstants.Purpose(4):  {},
   509  				consentconstants.Purpose(5):  {},
   510  				consentconstants.Purpose(6):  {},
   511  				consentconstants.Purpose(7):  {},
   512  				consentconstants.Purpose(8):  {},
   513  				consentconstants.Purpose(9):  {},
   514  				consentconstants.Purpose(10): {},
   515  			},
   516  		},
   517  	}
   518  	TCF2AggConfig.HostConfig.PurposeConfigs = map[consentconstants.Purpose]*config.TCF2Purpose{
   519  		consentconstants.Purpose(1):  &TCF2AggConfig.HostConfig.Purpose1,
   520  		consentconstants.Purpose(2):  &TCF2AggConfig.HostConfig.Purpose2,
   521  		consentconstants.Purpose(3):  &TCF2AggConfig.HostConfig.Purpose3,
   522  		consentconstants.Purpose(4):  &TCF2AggConfig.HostConfig.Purpose4,
   523  		consentconstants.Purpose(5):  &TCF2AggConfig.HostConfig.Purpose5,
   524  		consentconstants.Purpose(6):  &TCF2AggConfig.HostConfig.Purpose6,
   525  		consentconstants.Purpose(7):  &TCF2AggConfig.HostConfig.Purpose7,
   526  		consentconstants.Purpose(8):  &TCF2AggConfig.HostConfig.Purpose8,
   527  		consentconstants.Purpose(9):  &TCF2AggConfig.HostConfig.Purpose9,
   528  		consentconstants.Purpose(10): &TCF2AggConfig.HostConfig.Purpose10,
   529  	}
   530  	return
   531  }
   532  
   533  type testDef struct {
   534  	description           string
   535  	bidder                openrtb_ext.BidderName
   536  	consent               string
   537  	allowBidRequest       bool
   538  	passGeo               bool
   539  	passID                bool
   540  	weakVendorEnforcement bool
   541  	bidderCoreName        openrtb_ext.BidderName
   542  	aliasGVLIDs           map[string]uint16
   543  }
   544  
   545  func TestAllowActivitiesGeoAndID(t *testing.T) {
   546  	vendorListData := MarshalVendorList(buildVendorList34())
   547  
   548  	perms := permissionsImpl{
   549  		hostVendorID:          2,
   550  		nonStandardPublishers: map[string]struct{}{"appNexusAppID": {}},
   551  		vendorIDs: map[openrtb_ext.BidderName]uint16{
   552  			openrtb_ext.BidderAppnexus:        2,
   553  			openrtb_ext.BidderPubmatic:        6,
   554  			openrtb_ext.BidderRubicon:         8,
   555  			openrtb_ext.BidderOpenx:           20,
   556  			openrtb_ext.BidderAudienceNetwork: 55,
   557  		},
   558  		fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
   559  			2: {
   560  				34: parseVendorListDataV2(t, vendorListData),
   561  				74: parseVendorListDataV2(t, vendorListData),
   562  			},
   563  		}),
   564  		gdprSignal: SignalYes,
   565  	}
   566  
   567  	// COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA : full consents to purposes and vendors 2, 6, 8 and special feature 1 opt-in
   568  	testDefs := []testDef{
   569  		{
   570  			description:     "Appnexus vendor test, insufficient purposes claimed",
   571  			bidder:          openrtb_ext.BidderAppnexus,
   572  			bidderCoreName:  openrtb_ext.BidderAppnexus,
   573  			consent:         "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA",
   574  			allowBidRequest: false,
   575  			passGeo:         false,
   576  			passID:          false,
   577  		},
   578  		{
   579  			description:     "Pubmatic Alias vendor test, insufficient purposes claimed",
   580  			bidder:          "pubmatic1",
   581  			bidderCoreName:  openrtb_ext.BidderPubmatic,
   582  			consent:         "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA",
   583  			allowBidRequest: false,
   584  			passGeo:         false,
   585  			passID:          false,
   586  			aliasGVLIDs:     map[string]uint16{"pubmatic1": 1},
   587  		},
   588  		{
   589  			description:           "Appnexus vendor test, insufficient purposes claimed, basic enforcement",
   590  			bidder:                openrtb_ext.BidderAppnexus,
   591  			bidderCoreName:        openrtb_ext.BidderAppnexus,
   592  			consent:               "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA",
   593  			allowBidRequest:       true,
   594  			passGeo:               true,
   595  			passID:                true,
   596  			weakVendorEnforcement: true,
   597  		},
   598  		{
   599  			description:           "Unknown vendor test, insufficient purposes claimed, basic enforcement",
   600  			bidder:                openrtb_ext.BidderAudienceNetwork,
   601  			bidderCoreName:        openrtb_ext.BidderAudienceNetwork,
   602  			consent:               "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA",
   603  			allowBidRequest:       true,
   604  			passGeo:               true,
   605  			passID:                true,
   606  			weakVendorEnforcement: true,
   607  		},
   608  		{
   609  			description:     "Pubmatic vendor test, flex purposes claimed",
   610  			bidder:          openrtb_ext.BidderPubmatic,
   611  			bidderCoreName:  openrtb_ext.BidderPubmatic,
   612  			consent:         "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA",
   613  			allowBidRequest: true,
   614  			passGeo:         true,
   615  			passID:          true,
   616  		},
   617  		{
   618  			description:     "Pubmatic Alias vendor test, flex purposes claimed",
   619  			bidder:          "pubmatic1",
   620  			bidderCoreName:  openrtb_ext.BidderPubmatic,
   621  			consent:         "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA",
   622  			allowBidRequest: true,
   623  			passGeo:         true,
   624  			passID:          true,
   625  			aliasGVLIDs:     map[string]uint16{"pubmatic1": 6},
   626  		},
   627  		{
   628  			description:     "Rubicon vendor test, Specific purposes/LIs claimed, no geo claimed",
   629  			bidder:          openrtb_ext.BidderRubicon,
   630  			bidderCoreName:  openrtb_ext.BidderRubicon,
   631  			consent:         "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA",
   632  			allowBidRequest: true,
   633  			passGeo:         false,
   634  			passID:          true,
   635  		},
   636  		{
   637  			// This requires publisher restrictions on any claimed purposes, 2-10. Vendor must declare all claimed purposes
   638  			// as flex with legit interest as primary.
   639  			// Using vendor 20 for this.
   640  			description:     "OpenX vendor test, Specific purposes/LIs claimed, no geo claimed, Publisher restrictions apply",
   641  			bidder:          openrtb_ext.BidderOpenx,
   642  			bidderCoreName:  openrtb_ext.BidderOpenx,
   643  			consent:         "CPAavcCPAavcCAGABCFRBKCsAP_AAH_AAAqIHFNf_X_fb3_j-_59_9t0eY1f9_7_v-0zjgeds-8Nyd_X_L8X5mM7vB36pq4KuR4Eu3LBAQdlHOHcTUmw6IkVqTPsbk2Mr7NKJ7PEinMbe2dYGH9_n9XT_ZKY79_____7__-_____7_f__-__3_vp9V---wOJAIMBAUAgAEMAAQIFCIQAAQhiQAAAABBCIBQJIAEqgAWVwEdoIEACAxAQgQAgBBQgwCAAQAAJKAgBACwQCAAiAQAAgAEAIAAEIAILACQEAAAEAJCAAiACECAgiAAg5DAgIgCCAFABAAAuJDACAMooASBAPGQGAAKAAqACGAEwALgAjgBlgDUAHZAPsA_ACMAFLAK2AbwBMQCbAFogLYAYEAw8BkQDOQGeAM-EQHwAVABWAC4AIYAZAAywBqADZAHYAPwAgABGAClgFPANYAdUA-QCGwEOgIvASIAmwBOwCkQFyAMCAYSAw8Bk4DOQGfCQAYADgBzgN_CQTgAEAALgAoACoAGQAOAAeABAACIAFQAMIAaABqADyAIYAigBMgCqAKwAWAAuABvADmAHoAQ0AiACJgEsAS4AmgBSgC3AGGAMgAZcA1ADVAGyAO8AewA-IB9gH6AQAAjABQQClgFPAL8AYoA1gBtADcAG8AOIAegA-QCGwEOgIqAReAkQBMQCZQE2AJ2AUOApEBYoC2AFyALvAYEAwYBhIDDQGHgMiAZIAycBlwDOQGfANIAadA1gDWQoAEAYQaBIACoAKwAXABDADIAGWANQAbIA7AB-AEAAIKARgApYBT4C0ALSAawA3gB1QD5AIbAQ6Ai8BIgCbAE7AKRAXIAwIBhIDDwGMAMnAZyAzwBnwcAEAA4Bv4qA2ABQAFQAQwAmABcAEcAMsAagA7AB-AEYAKXAWgBaQDeAJBATEAmwBTYC2AFyAMCAYeAyIBnIDPAGfANyHQWQAFwAUABUADIAHAAQAAiABdADAAMYAaABqADwAH0AQwBFACZAFUAVgAsABcADEAGYAN4AcwA9ACGAERAJYAmABNACjAFKALEAW4AwwBkADKAGiANQAbIA3wB3gD2gH2AfoBGACVAFBAKeAWKAtAC0gFzALyAX4AxQBuADiQHTAdQA9ACGwEOgIiAReAkEBIgCbAE7AKHAU0AqwBYsC2ALZAXAAuQBdoC7wGEgMNAYeAxIBjADHgGSAMnAZUAywBlwDOQGfANEgaQBpIDSwGnANYAbGPABAIqAb-QgZgALAAoABkAEQALgAYgBDACYAFUALgAYgAzABvAD0AI4AWIAygBqADfAHfAPsA_ACMAFBAKGAU-AtAC0gF-AMUAdQA9ACQQEiAJsAU0AsUBaMC2ALaAXAAuQBdoDDwGJAMiAZOAzkBngDPgGiANJAaWA4AlAyAAQAAsACgAGQAOAAigBgAGIAPAAiABMACqAFwAMQAZgA2gCGgEQARIAowBSgC3AGEAMoAaoA2QB3gD8AIwAU-AtAC0gGKANwAcQA6gCHQEXgJEATYAsUBbAC7QGHgMiAZOAywBnIDPAGfANIAawA4AmACARUA38pBBAAXABQAFQAMgAcABAACKAGAAYwA0ADUAHkAQwBFACYAFIAKoAWAAuABiADMAHMAQwAiABRgClAFiALcAZQA0QBqgDZAHfAPsA_ACMAFBAKGAVsAuYBeQDaAG4APQAh0BF4CRAE2AJ2AUOApoBWwCxQFsALgAXIAu0BhoDDwGMAMiAZIAycBlwDOQGeAM-gaQBpMDWANZAbGVABAA-Ab-A.YAAAAAAAAAAA",
   644  			allowBidRequest: true,
   645  			passGeo:         false,
   646  			passID:          true,
   647  		},
   648  	}
   649  
   650  	for _, td := range testDefs {
   651  
   652  		tcf2AggConfig := allPurposesEnabledTCF2Config()
   653  		if td.weakVendorEnforcement {
   654  			tcf2AggConfig.AccountConfig.BasicEnforcementVendorsMap = map[string]struct{}{string(td.bidder): {}}
   655  		}
   656  		perms.cfg = &tcf2AggConfig
   657  		perms.aliasGVLIDs = td.aliasGVLIDs
   658  		perms.consent = td.consent
   659  		perms.purposeEnforcerBuilder = NewPurposeEnforcerBuilder(&tcf2AggConfig)
   660  
   661  		permissions, err := perms.AuctionActivitiesAllowed(context.Background(), td.bidderCoreName, td.bidder)
   662  		assert.NoErrorf(t, err, "Error processing AuctionActivitiesAllowed for %s", td.description)
   663  		assert.EqualValuesf(t, td.allowBidRequest, permissions.AllowBidRequest, "AllowBid failure on %s", td.description)
   664  		assert.EqualValuesf(t, td.passGeo, permissions.PassGeo, "PassGeo failure on %s", td.description)
   665  		assert.EqualValuesf(t, td.passID, permissions.PassID, "PassID failure on %s", td.description)
   666  	}
   667  }
   668  
   669  func TestAllowActivitiesWhitelist(t *testing.T) {
   670  	// user specifies consent and LI for all purposes, and purpose and LI vendor consent for vendors 2, 6 and 8
   671  	const fullConsentToPurposesAndVendorsTwoSixEight = "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA"
   672  
   673  	vendorListData := MarshalVendorList(buildVendorList34())
   674  	tcf2AggConfig := allPurposesEnabledTCF2Config()
   675  
   676  	perms := permissionsImpl{
   677  		cfg:                   &tcf2AggConfig,
   678  		hostVendorID:          2,
   679  		nonStandardPublishers: map[string]struct{}{"appNexusAppID": {}},
   680  		vendorIDs: map[openrtb_ext.BidderName]uint16{
   681  			openrtb_ext.BidderAppnexus: 2,
   682  			openrtb_ext.BidderPubmatic: 6,
   683  			openrtb_ext.BidderRubicon:  8,
   684  		},
   685  		fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
   686  			2: {
   687  				34: parseVendorListDataV2(t, vendorListData),
   688  			},
   689  		}),
   690  		purposeEnforcerBuilder: NewPurposeEnforcerBuilder(&tcf2AggConfig),
   691  		aliasGVLIDs:            map[string]uint16{},
   692  		consent:                fullConsentToPurposesAndVendorsTwoSixEight,
   693  		gdprSignal:             SignalYes,
   694  		publisherID:            "appNexusAppID",
   695  	}
   696  
   697  	// Assert that an item that otherwise would not be allowed PI access, gets approved because it is found in the GDPR.NonStandardPublishers array
   698  	permissions, err := perms.AuctionActivitiesAllowed(context.Background(), openrtb_ext.BidderAppnexus, openrtb_ext.BidderAppnexus)
   699  	assert.NoErrorf(t, err, "Error processing AuctionActivitiesAllowed")
   700  	assert.EqualValuesf(t, true, permissions.PassGeo, "PassGeo failure")
   701  	assert.EqualValuesf(t, true, permissions.PassID, "PassID failure")
   702  }
   703  
   704  func TestAllowActivitiesPubRestrict(t *testing.T) {
   705  	vendorListData := MarshalVendorList(buildVendorList34())
   706  	tcf2AggConfig := allPurposesEnabledTCF2Config()
   707  
   708  	perms := permissionsImpl{
   709  		cfg:          &tcf2AggConfig,
   710  		hostVendorID: 2,
   711  		vendorIDs: map[openrtb_ext.BidderName]uint16{
   712  			openrtb_ext.BidderAppnexus: 2,
   713  			openrtb_ext.BidderPubmatic: 32,
   714  			openrtb_ext.BidderRubicon:  8,
   715  		},
   716  		fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
   717  			2: {
   718  				15: parseVendorListDataV2(t, vendorListData),
   719  			},
   720  		}),
   721  		purposeEnforcerBuilder: NewPurposeEnforcerBuilder(&tcf2AggConfig),
   722  		gdprSignal:             SignalYes,
   723  	}
   724  
   725  	// COwAdDhOwAdDhN4ABAENAPCgAAQAAv___wAAAFP_AAp_4AI6ACACAA - vendors 1-10 legit interest only,
   726  	// Pub restriction on purpose 7, consent only ... no allowPI will pass, no special feature 1 consent
   727  	testDefs := []testDef{
   728  		{
   729  			description:    "Appnexus vendor test, insufficient purposes claimed",
   730  			bidder:         openrtb_ext.BidderAppnexus,
   731  			bidderCoreName: openrtb_ext.BidderAppnexus,
   732  			consent:        "COwAdDhOwAdDhN4ABAENAPCgAAQAAv___wAAAFP_AAp_4AI6ACACAA",
   733  			passGeo:        false,
   734  			passID:         false,
   735  			aliasGVLIDs:    map[string]uint16{},
   736  		},
   737  		{
   738  			description:    "Pubmatic vendor test, flex purposes claimed",
   739  			bidder:         openrtb_ext.BidderPubmatic,
   740  			bidderCoreName: openrtb_ext.BidderPubmatic,
   741  			consent:        "COwAdDhOwAdDhN4ABAENAPCgAAQAAv___wAAAFP_AAp_4AI6ACACAA",
   742  			passGeo:        false,
   743  			passID:         false,
   744  			aliasGVLIDs:    map[string]uint16{},
   745  		},
   746  		{
   747  			description:    "Pubmatic Alias vendor test, flex purposes claimed",
   748  			bidder:         "pubmatic1",
   749  			bidderCoreName: openrtb_ext.BidderPubmatic,
   750  			consent:        "COwAdDhOwAdDhN4ABAENAPCgAAQAAv___wAAAFP_AAp_4AI6ACACAA",
   751  			passGeo:        false,
   752  			passID:         false,
   753  			aliasGVLIDs:    map[string]uint16{"pubmatic1": 32},
   754  		},
   755  		{
   756  			description:    "Rubicon vendor test, Specific purposes/LIs claimed, no geo claimed",
   757  			bidder:         openrtb_ext.BidderRubicon,
   758  			bidderCoreName: openrtb_ext.BidderRubicon,
   759  			consent:        "COwAdDhOwAdDhN4ABAENAPCgAAQAAv___wAAAFP_AAp_4AI6ACACAA",
   760  			passGeo:        false,
   761  			passID:         true,
   762  			aliasGVLIDs:    map[string]uint16{},
   763  		},
   764  	}
   765  
   766  	for _, td := range testDefs {
   767  		perms.aliasGVLIDs = td.aliasGVLIDs
   768  		perms.consent = td.consent
   769  
   770  		permissions, err := perms.AuctionActivitiesAllowed(context.Background(), td.bidderCoreName, td.bidder)
   771  		assert.NoErrorf(t, err, "Error processing AuctionActivitiesAllowed for %s", td.description)
   772  		assert.EqualValuesf(t, td.passGeo, permissions.PassGeo, "PassGeo failure on %s", td.description)
   773  		assert.EqualValuesf(t, td.passID, permissions.PassID, "PassID failure on %s", td.description)
   774  	}
   775  }
   776  
   777  func TestAllowSync(t *testing.T) {
   778  	const fullConsentToPurposesAndVendorsTwoSixEight = "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA"
   779  
   780  	vendorListData := MarshalVendorList(buildVendorList34())
   781  	tcf2AggConfig := allPurposesEnabledTCF2Config()
   782  
   783  	perms := permissionsImpl{
   784  		cfg:          &tcf2AggConfig,
   785  		hostVendorID: 2,
   786  		vendorIDs: map[openrtb_ext.BidderName]uint16{
   787  			openrtb_ext.BidderAppnexus: 2,
   788  			openrtb_ext.BidderPubmatic: 6,
   789  			openrtb_ext.BidderRubicon:  8,
   790  		},
   791  		fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
   792  			2: {
   793  				34: parseVendorListDataV2(t, vendorListData),
   794  			},
   795  		}),
   796  		purposeEnforcerBuilder: NewPurposeEnforcerBuilder(&tcf2AggConfig),
   797  		gdprSignal:             SignalYes,
   798  		consent:                fullConsentToPurposesAndVendorsTwoSixEight,
   799  	}
   800  
   801  	allowSync, err := perms.HostCookiesAllowed(context.Background())
   802  	assert.NoErrorf(t, err, "Error processing HostCookiesAllowed")
   803  	assert.EqualValuesf(t, true, allowSync, "HostCookiesAllowed failure")
   804  
   805  	allowSync, err = perms.BidderSyncAllowed(context.Background(), openrtb_ext.BidderRubicon)
   806  	assert.NoErrorf(t, err, "Error processing BidderSyncAllowed")
   807  	assert.EqualValuesf(t, true, allowSync, "BidderSyncAllowed failure")
   808  }
   809  
   810  func TestProhibitedPurposeSync(t *testing.T) {
   811  	const fullConsentToPurposesAndVendorsTwoSixEight = "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA"
   812  
   813  	vendorList34 := buildVendorList34()
   814  	vendorList34.Vendors["8"].Purposes = []int{7}
   815  	vendorListData := MarshalVendorList(vendorList34)
   816  
   817  	tcf2AggConfig := allPurposesEnabledTCF2Config()
   818  
   819  	perms := permissionsImpl{
   820  		cfg:          &tcf2AggConfig,
   821  		hostVendorID: 8,
   822  		vendorIDs: map[openrtb_ext.BidderName]uint16{
   823  			openrtb_ext.BidderAppnexus: 2,
   824  			openrtb_ext.BidderPubmatic: 6,
   825  			openrtb_ext.BidderRubicon:  8,
   826  		},
   827  		fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
   828  			2: {
   829  				34: parseVendorListDataV2(t, vendorListData),
   830  			},
   831  		}),
   832  		purposeEnforcerBuilder: NewPurposeEnforcerBuilder(&tcf2AggConfig),
   833  		gdprSignal:             SignalYes,
   834  		consent:                fullConsentToPurposesAndVendorsTwoSixEight,
   835  	}
   836  
   837  	allowSync, err := perms.HostCookiesAllowed(context.Background())
   838  	assert.NoErrorf(t, err, "Error processing HostCookiesAllowed")
   839  	assert.EqualValuesf(t, false, allowSync, "HostCookiesAllowed failure")
   840  
   841  	allowSync, err = perms.BidderSyncAllowed(context.Background(), openrtb_ext.BidderRubicon)
   842  	assert.NoErrorf(t, err, "Error processing BidderSyncAllowed")
   843  	assert.EqualValuesf(t, false, allowSync, "BidderSyncAllowed failure")
   844  }
   845  
   846  func TestProhibitedVendorSync(t *testing.T) {
   847  	const fullConsentToPurposesAndVendorsTwoSixEight = "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA"
   848  
   849  	vendorListData := MarshalVendorList(buildVendorList34())
   850  	tcf2AggConfig := allPurposesEnabledTCF2Config()
   851  
   852  	perms := permissionsImpl{
   853  		cfg:          &tcf2AggConfig,
   854  		hostVendorID: 10,
   855  		vendorIDs: map[openrtb_ext.BidderName]uint16{
   856  			openrtb_ext.BidderAppnexus: 2,
   857  			openrtb_ext.BidderPubmatic: 6,
   858  			openrtb_ext.BidderRubicon:  8,
   859  			openrtb_ext.BidderOpenx:    10,
   860  		},
   861  		fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
   862  			2: {
   863  				34: parseVendorListDataV2(t, vendorListData),
   864  			},
   865  		}),
   866  		purposeEnforcerBuilder: NewPurposeEnforcerBuilder(&tcf2AggConfig),
   867  		gdprSignal:             SignalYes,
   868  		consent:                fullConsentToPurposesAndVendorsTwoSixEight,
   869  	}
   870  
   871  	// COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA : full consents to purposes for vendors 2, 6, 8
   872  	allowSync, err := perms.HostCookiesAllowed(context.Background())
   873  	assert.NoErrorf(t, err, "Error processing HostCookiesAllowed")
   874  	assert.EqualValuesf(t, false, allowSync, "HostCookiesAllowed failure")
   875  
   876  	// Permission disallowed due to consent string not including vendor 10.
   877  	allowSync, err = perms.BidderSyncAllowed(context.Background(), openrtb_ext.BidderOpenx)
   878  	assert.NoErrorf(t, err, "Error processing BidderSyncAllowed")
   879  	assert.EqualValuesf(t, false, allowSync, "BidderSyncAllowed failure")
   880  }
   881  
   882  func parseVendorListDataV2(t *testing.T, data string) vendorlist.VendorList {
   883  	t.Helper()
   884  	parsed, err := vendorlist2.ParseEagerly([]byte(data))
   885  	if err != nil {
   886  		t.Fatalf("Failed to parse vendor list data. %v", err)
   887  	}
   888  	return parsed
   889  }
   890  
   891  func listFetcher(specVersionLists map[uint16]map[uint16]vendorlist.VendorList) func(context.Context, uint16, uint16) (vendorlist.VendorList, error) {
   892  	return func(ctx context.Context, specVersion, listVersion uint16) (vendorlist.VendorList, error) {
   893  		if lists, ok := specVersionLists[specVersion]; ok {
   894  			if data, ok := lists[listVersion]; ok {
   895  				return data, nil
   896  			}
   897  		}
   898  		return nil, fmt.Errorf("spec version %d vendor list %d not found", specVersion, listVersion)
   899  	}
   900  }
   901  
   902  func failedListFetcher(ctx context.Context, specVersion, listVersion uint16) (vendorlist.VendorList, error) {
   903  	return nil, errors.New("vendor list can't be fetched")
   904  }
   905  
   906  func assertNilErr(t *testing.T, err error) {
   907  	t.Helper()
   908  	if err != nil {
   909  		t.Errorf("Unexpected error: %v", err)
   910  	}
   911  }
   912  
   913  func assertErr(t *testing.T, err error, badConsent bool) {
   914  	t.Helper()
   915  	if err == nil {
   916  		t.Errorf("Expected error did not occur.")
   917  		return
   918  	}
   919  	_, isBadConsent := err.(*ErrorMalformedConsent)
   920  	assertBoolsEqual(t, badConsent, isBadConsent)
   921  }
   922  
   923  func assertBoolsEqual(t *testing.T, expected bool, actual bool) {
   924  	t.Helper()
   925  	if expected != actual {
   926  		t.Errorf("Expected %t, got %t", expected, actual)
   927  	}
   928  }
   929  
   930  func TestAllowActivitiesBidRequests(t *testing.T) {
   931  	purpose2AndVendorConsent := "CPF_61ePF_61eFxAAAENAiCAAEAAAAAAAAAAADAQAAAAAA"
   932  	purpose2ConsentWithoutVendorConsent := "CPF_61ePF_61eFxAAAENAiCAAEAAAAAAAAAAABIAAAAA"
   933  
   934  	purpose2AndVendorLI := "CPF_61ePF_61eFxAAAENAiCAAAAAAEAAAAAAAAAAIAIAAA"
   935  	purpose2LIWithoutVendorLI := "CPF_61ePF_61eFxAAAENAiCAAAAAAEAAAAAAABIAAAAA"
   936  
   937  	testDefs := []struct {
   938  		description            string
   939  		purpose2EnforcePurpose bool
   940  		purpose2EnforceVendors bool
   941  		bidder                 openrtb_ext.BidderName
   942  		bidderCoreName         openrtb_ext.BidderName
   943  		consent                string
   944  		allowBidRequest        bool
   945  		passGeo                bool
   946  		passID                 bool
   947  		aliasGVLIDs            map[string]uint16
   948  	}{
   949  		{
   950  			description:            "Bid blocked - p2 enabled, user consents to p2 but not vendor, vendor consents to p2",
   951  			purpose2EnforcePurpose: true,
   952  			purpose2EnforceVendors: true,
   953  			bidder:                 openrtb_ext.BidderPubmatic,
   954  			bidderCoreName:         openrtb_ext.BidderPubmatic,
   955  			consent:                purpose2ConsentWithoutVendorConsent,
   956  			allowBidRequest:        false,
   957  			passGeo:                false,
   958  			passID:                 false,
   959  		},
   960  		{
   961  			description:            "Bid allowed - p2 enabled, user consents to p2 and vendor, alias vendor consents to p2",
   962  			purpose2EnforcePurpose: true,
   963  			purpose2EnforceVendors: true,
   964  			bidder:                 "pubmatic1",
   965  			bidderCoreName:         openrtb_ext.BidderPubmatic,
   966  			consent:                purpose2AndVendorConsent,
   967  			allowBidRequest:        true,
   968  			passGeo:                false,
   969  			passID:                 true,
   970  			aliasGVLIDs:            map[string]uint16{"pubmatic1": 6},
   971  		},
   972  		{
   973  			description:            "Bid blocked - p2 enabled, user consents to p2 and vendor, alias vendor does not consent to p2",
   974  			purpose2EnforcePurpose: true,
   975  			purpose2EnforceVendors: true,
   976  			bidder:                 "pubmatic1",
   977  			bidderCoreName:         openrtb_ext.BidderPubmatic,
   978  			consent:                purpose2AndVendorConsent,
   979  			allowBidRequest:        false,
   980  			passGeo:                false,
   981  			passID:                 false,
   982  			aliasGVLIDs:            map[string]uint16{"pubmatic1": 1},
   983  		},
   984  		{
   985  			description:            "Bid allowed - p2 enabled not enforcing vendors, user consents to p2 but not vendor, vendor consents to p2",
   986  			purpose2EnforcePurpose: true,
   987  			purpose2EnforceVendors: false,
   988  			bidder:                 openrtb_ext.BidderPubmatic,
   989  			bidderCoreName:         openrtb_ext.BidderPubmatic,
   990  			consent:                purpose2ConsentWithoutVendorConsent,
   991  			allowBidRequest:        true,
   992  			passGeo:                false,
   993  			passID:                 false,
   994  		},
   995  		{
   996  			description:            "Bid allowed - p2 disabled and enforcing vendors, user consents to p2 but not vendor, vendor consents to p2",
   997  			purpose2EnforcePurpose: false,
   998  			purpose2EnforceVendors: true,
   999  			bidder:                 openrtb_ext.BidderPubmatic,
  1000  			bidderCoreName:         openrtb_ext.BidderPubmatic,
  1001  			consent:                purpose2ConsentWithoutVendorConsent,
  1002  			allowBidRequest:        false,
  1003  			passGeo:                false,
  1004  			passID:                 false,
  1005  		},
  1006  		{
  1007  			description:            "Bid allowed - p2 disabled not enforcing vendors, user consents to p2 but not vendor, vendor consents to p2",
  1008  			purpose2EnforcePurpose: false,
  1009  			purpose2EnforceVendors: false,
  1010  			bidder:                 openrtb_ext.BidderPubmatic,
  1011  			bidderCoreName:         openrtb_ext.BidderPubmatic,
  1012  			consent:                purpose2ConsentWithoutVendorConsent,
  1013  			allowBidRequest:        true,
  1014  			passGeo:                false,
  1015  			passID:                 false,
  1016  		},
  1017  		{
  1018  			description:            "Bid allowed - p2 disabled and enforcing vendors, user consents to p2 and vendor, vendor consents to p2",
  1019  			purpose2EnforcePurpose: false,
  1020  			purpose2EnforceVendors: true,
  1021  			bidder:                 openrtb_ext.BidderPubmatic,
  1022  			bidderCoreName:         openrtb_ext.BidderPubmatic,
  1023  			consent:                purpose2AndVendorConsent,
  1024  			allowBidRequest:        true,
  1025  			passGeo:                false,
  1026  			passID:                 true,
  1027  		},
  1028  		{
  1029  			description:            "Bid allowed - p2 enabled, user consents to p2 and vendor, vendor consents to p2",
  1030  			purpose2EnforcePurpose: true,
  1031  			purpose2EnforceVendors: true,
  1032  			bidder:                 openrtb_ext.BidderPubmatic,
  1033  			bidderCoreName:         openrtb_ext.BidderPubmatic,
  1034  			consent:                purpose2AndVendorConsent,
  1035  			allowBidRequest:        true,
  1036  			passGeo:                false,
  1037  			passID:                 true,
  1038  		},
  1039  		{
  1040  			description:            "Bid blocked - p2 enabled, user consents to p2 LI but not vendor, vendor consents to p2",
  1041  			purpose2EnforcePurpose: true,
  1042  			purpose2EnforceVendors: true,
  1043  			bidder:                 openrtb_ext.BidderRubicon,
  1044  			bidderCoreName:         openrtb_ext.BidderRubicon,
  1045  			consent:                purpose2LIWithoutVendorLI,
  1046  			allowBidRequest:        false,
  1047  			passGeo:                false,
  1048  			passID:                 false,
  1049  		},
  1050  		{
  1051  			description:            "Bid allowed - p2 enabled, user consents to p2 LI and vendor, vendor consents to p2",
  1052  			purpose2EnforcePurpose: true,
  1053  			purpose2EnforceVendors: true,
  1054  			bidder:                 openrtb_ext.BidderRubicon,
  1055  			bidderCoreName:         openrtb_ext.BidderRubicon,
  1056  			consent:                purpose2AndVendorLI,
  1057  			allowBidRequest:        true,
  1058  			passGeo:                false,
  1059  			passID:                 true,
  1060  		},
  1061  		{
  1062  			description:            "Bid allowed - p2 enabled not enforcing vendors, user consents to p2 LI but not vendor, vendor consents to p2",
  1063  			purpose2EnforcePurpose: true,
  1064  			purpose2EnforceVendors: false,
  1065  			bidder:                 openrtb_ext.BidderPubmatic,
  1066  			bidderCoreName:         openrtb_ext.BidderPubmatic,
  1067  			consent:                purpose2AndVendorLI,
  1068  			allowBidRequest:        true,
  1069  			passGeo:                false,
  1070  			passID:                 false,
  1071  		},
  1072  	}
  1073  
  1074  	for _, td := range testDefs {
  1075  		vendorListData := MarshalVendorList(buildVendorList34())
  1076  
  1077  		perms := permissionsImpl{
  1078  			hostVendorID: 2,
  1079  			vendorIDs: map[openrtb_ext.BidderName]uint16{
  1080  				openrtb_ext.BidderPubmatic: 6,
  1081  				openrtb_ext.BidderRubicon:  8,
  1082  			},
  1083  			fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
  1084  				2: {
  1085  					34: parseVendorListDataV2(t, vendorListData),
  1086  				},
  1087  			}),
  1088  			aliasGVLIDs: td.aliasGVLIDs,
  1089  			consent:     td.consent,
  1090  			gdprSignal:  SignalYes,
  1091  		}
  1092  
  1093  		tcf2AggConfig := allPurposesEnabledTCF2Config()
  1094  		tcf2AggConfig.HostConfig.Purpose2.EnforcePurpose = td.purpose2EnforcePurpose
  1095  		tcf2AggConfig.HostConfig.Purpose2.EnforceVendors = td.purpose2EnforceVendors
  1096  		p2Config := tcf2AggConfig.HostConfig.PurposeConfigs[consentconstants.Purpose(2)]
  1097  		p2Config.EnforcePurpose = td.purpose2EnforcePurpose
  1098  		p2Config.EnforceVendors = td.purpose2EnforceVendors
  1099  		tcf2AggConfig.HostConfig.PurposeConfigs[consentconstants.Purpose(2)] = p2Config
  1100  		tcf2AggConfig.HostConfig.PurposeConfigs[consentconstants.Purpose(2)] = &tcf2AggConfig.HostConfig.Purpose2
  1101  		perms.cfg = &tcf2AggConfig
  1102  		perms.purposeEnforcerBuilder = NewPurposeEnforcerBuilder(&tcf2AggConfig)
  1103  
  1104  		permissions, err := perms.AuctionActivitiesAllowed(context.Background(), td.bidderCoreName, td.bidder)
  1105  		assert.NoErrorf(t, err, "Error processing AuctionActivitiesAllowed for %s", td.description)
  1106  		assert.EqualValuesf(t, td.allowBidRequest, permissions.AllowBidRequest, "AllowBid failure on %s", td.description)
  1107  		assert.EqualValuesf(t, td.passGeo, permissions.PassGeo, "PassGeo failure on %s", td.description)
  1108  		assert.EqualValuesf(t, td.passID, permissions.PassID, "PassID failure on %s", td.description)
  1109  	}
  1110  }
  1111  
  1112  func TestAllowActivitiesVendorException(t *testing.T) {
  1113  	appnexus := string(openrtb_ext.BidderAppnexus)
  1114  	noPurposeOrVendorConsentAndPubRestrictsP2 := "CPF_61ePF_61eFxAAAENAiCAAAAAAAAAAAAAACEAAAACEAAgAgAA"
  1115  	noPurposeOrVendorConsentAndPubRestrictsNone := "CPF_61ePF_61eFxAAAENAiCAAAAAAAAAAAAAACEAAAAA"
  1116  
  1117  	testDefs := []struct {
  1118  		description           string
  1119  		p2VendorExceptionMap  map[string]struct{}
  1120  		sf1VendorExceptionMap map[openrtb_ext.BidderName]struct{}
  1121  		bidder                openrtb_ext.BidderName
  1122  		consent               string
  1123  		allowBidRequest       bool
  1124  		passGeo               bool
  1125  		passID                bool
  1126  		bidderCoreName        openrtb_ext.BidderName
  1127  	}{
  1128  		{
  1129  			description:          "Bid/ID blocked by publisher - p2 enabled with p2 vendor exception, pub restricts p2 for vendor",
  1130  			p2VendorExceptionMap: map[string]struct{}{appnexus: {}},
  1131  			bidder:               openrtb_ext.BidderAppnexus,
  1132  			bidderCoreName:       openrtb_ext.BidderAppnexus,
  1133  			consent:              noPurposeOrVendorConsentAndPubRestrictsP2,
  1134  			allowBidRequest:      false,
  1135  			passGeo:              false,
  1136  			passID:               false,
  1137  		},
  1138  		{
  1139  			description:           "Bid/ID allowed by vendor exception - p2 enabled with p2 vendor exception, pub restricts none",
  1140  			p2VendorExceptionMap:  map[string]struct{}{appnexus: {}},
  1141  			sf1VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{},
  1142  			bidder:                openrtb_ext.BidderAppnexus,
  1143  			bidderCoreName:        openrtb_ext.BidderAppnexus,
  1144  			consent:               noPurposeOrVendorConsentAndPubRestrictsNone,
  1145  			allowBidRequest:       true,
  1146  			passGeo:               false,
  1147  			passID:                true,
  1148  		},
  1149  		{
  1150  			description:           "Geo blocked - sf1 enabled but no consent",
  1151  			p2VendorExceptionMap:  map[string]struct{}{},
  1152  			sf1VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{},
  1153  			bidder:                openrtb_ext.BidderAppnexus,
  1154  			bidderCoreName:        openrtb_ext.BidderAppnexus,
  1155  			consent:               noPurposeOrVendorConsentAndPubRestrictsNone,
  1156  			allowBidRequest:       false,
  1157  			passGeo:               false,
  1158  			passID:                false,
  1159  		},
  1160  		{
  1161  			description:           "Geo allowed by vendor exception - sf1 enabled with sf1 vendor exception",
  1162  			p2VendorExceptionMap:  map[string]struct{}{},
  1163  			sf1VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderAppnexus: {}},
  1164  			bidder:                openrtb_ext.BidderAppnexus,
  1165  			bidderCoreName:        openrtb_ext.BidderAppnexus,
  1166  			consent:               noPurposeOrVendorConsentAndPubRestrictsNone,
  1167  			allowBidRequest:       false,
  1168  			passGeo:               true,
  1169  			passID:                false,
  1170  		},
  1171  	}
  1172  
  1173  	for _, td := range testDefs {
  1174  		vendorListData := MarshalVendorList(buildVendorList34())
  1175  		perms := permissionsImpl{
  1176  			hostVendorID: 2,
  1177  			vendorIDs: map[openrtb_ext.BidderName]uint16{
  1178  				openrtb_ext.BidderAppnexus: 32,
  1179  			},
  1180  			fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
  1181  				2: {
  1182  					34: parseVendorListDataV2(t, vendorListData),
  1183  				},
  1184  			}),
  1185  			aliasGVLIDs: map[string]uint16{},
  1186  			consent:     td.consent,
  1187  			gdprSignal:  SignalYes,
  1188  		}
  1189  
  1190  		tcf2AggConfig := allPurposesEnabledTCF2Config()
  1191  		tcf2AggConfig.HostConfig.Purpose2.VendorExceptionMap = td.p2VendorExceptionMap
  1192  		tcf2AggConfig.HostConfig.SpecialFeature1.Enforce = true
  1193  		tcf2AggConfig.HostConfig.SpecialFeature1.VendorExceptionMap = td.sf1VendorExceptionMap
  1194  		tcf2AggConfig.HostConfig.PurposeConfigs[consentconstants.Purpose(2)] = &tcf2AggConfig.HostConfig.Purpose2
  1195  		tcf2AggConfig.HostConfig.PurposeConfigs[consentconstants.Purpose(3)] = &tcf2AggConfig.HostConfig.Purpose3
  1196  		perms.cfg = &tcf2AggConfig
  1197  		perms.purposeEnforcerBuilder = NewPurposeEnforcerBuilder(&tcf2AggConfig)
  1198  
  1199  		permissions, err := perms.AuctionActivitiesAllowed(context.Background(), td.bidderCoreName, td.bidder)
  1200  		assert.NoErrorf(t, err, "Error processing AuctionActivitiesAllowed for %s", td.description)
  1201  		assert.EqualValuesf(t, td.allowBidRequest, permissions.AllowBidRequest, "AllowBid failure on %s", td.description)
  1202  		assert.EqualValuesf(t, td.passGeo, permissions.PassGeo, "PassGeo failure on %s", td.description)
  1203  		assert.EqualValuesf(t, td.passID, permissions.PassID, "PassID failure on %s", td.description)
  1204  	}
  1205  }
  1206  
  1207  func TestBidderSyncAllowedVendorException(t *testing.T) {
  1208  	appnexus := string(openrtb_ext.BidderAppnexus)
  1209  	noPurposeOrVendorConsentAndPubRestrictsP1 := "CPF_61ePF_61eFxAAAENAiCAAAAAAAAAAAAAAQAAAAAAAAAAIIACACA"
  1210  	noPurposeOrVendorConsentAndPubRestrictsNone := "CPF_61ePF_61eFxAAAENAiCAAAAAAAAAAAAAACEAAAAA"
  1211  
  1212  	testDefs := []struct {
  1213  		description          string
  1214  		p1VendorExceptionMap map[string]struct{}
  1215  		bidder               openrtb_ext.BidderName
  1216  		consent              string
  1217  		allowSync            bool
  1218  	}{
  1219  		{
  1220  			description:          "Sync blocked by no consent - p1 enabled, no p1 vendor exception, pub restricts none",
  1221  			p1VendorExceptionMap: map[string]struct{}{},
  1222  			bidder:               openrtb_ext.BidderAppnexus,
  1223  			consent:              noPurposeOrVendorConsentAndPubRestrictsNone,
  1224  			allowSync:            false,
  1225  		},
  1226  		{
  1227  			description:          "Sync blocked by publisher - p1 enabled with p1 vendor exception, pub restricts p1 for vendor",
  1228  			p1VendorExceptionMap: map[string]struct{}{appnexus: {}},
  1229  			bidder:               openrtb_ext.BidderAppnexus,
  1230  			consent:              noPurposeOrVendorConsentAndPubRestrictsP1,
  1231  			allowSync:            false,
  1232  		},
  1233  		{
  1234  			description:          "Sync allowed by vendor exception - p1 enabled with p1 vendor exception, pub restricts none",
  1235  			p1VendorExceptionMap: map[string]struct{}{appnexus: {}},
  1236  			bidder:               openrtb_ext.BidderAppnexus,
  1237  			consent:              noPurposeOrVendorConsentAndPubRestrictsNone,
  1238  			allowSync:            true,
  1239  		},
  1240  	}
  1241  
  1242  	for _, td := range testDefs {
  1243  		vendorListData := MarshalVendorList(buildVendorList34())
  1244  		perms := permissionsImpl{
  1245  			hostVendorID: 2,
  1246  			vendorIDs: map[openrtb_ext.BidderName]uint16{
  1247  				openrtb_ext.BidderAppnexus: 32,
  1248  			},
  1249  			fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
  1250  				2: {
  1251  					34: parseVendorListDataV2(t, vendorListData),
  1252  				},
  1253  			}),
  1254  			consent:    td.consent,
  1255  			gdprSignal: SignalYes,
  1256  		}
  1257  
  1258  		tcf2AggConfig := allPurposesEnabledTCF2Config()
  1259  		tcf2AggConfig.HostConfig.Purpose1.VendorExceptionMap = td.p1VendorExceptionMap
  1260  		tcf2AggConfig.HostConfig.PurposeConfigs[consentconstants.Purpose(1)] = &tcf2AggConfig.HostConfig.Purpose1
  1261  		perms.cfg = &tcf2AggConfig
  1262  		perms.purposeEnforcerBuilder = NewPurposeEnforcerBuilder(&tcf2AggConfig)
  1263  
  1264  		allowSync, err := perms.BidderSyncAllowed(context.Background(), td.bidder)
  1265  		assert.NoErrorf(t, err, "Error processing BidderSyncAllowed for %s", td.description)
  1266  		assert.EqualValuesf(t, td.allowSync, allowSync, "AllowSync failure on %s", td.description)
  1267  	}
  1268  }
  1269  
  1270  func TestDefaultPermissions(t *testing.T) {
  1271  	tests := []struct {
  1272  		description      string
  1273  		purpose2Enforced bool
  1274  		feature1Enforced bool
  1275  		wantPermissions  AuctionPermissions
  1276  	}{
  1277  		{
  1278  			description: "Neither enforced",
  1279  			wantPermissions: AuctionPermissions{
  1280  				AllowBidRequest: true,
  1281  				PassGeo:         true,
  1282  				PassID:          false,
  1283  			},
  1284  		},
  1285  		{
  1286  			description:      "Purpose 2 enforced only",
  1287  			purpose2Enforced: true,
  1288  			wantPermissions: AuctionPermissions{
  1289  				AllowBidRequest: false,
  1290  				PassGeo:         true,
  1291  				PassID:          false,
  1292  			},
  1293  		},
  1294  		{
  1295  			description:      "Feature 1 enforced only",
  1296  			feature1Enforced: true,
  1297  			wantPermissions: AuctionPermissions{
  1298  				AllowBidRequest: true,
  1299  				PassGeo:         false,
  1300  				PassID:          false,
  1301  			},
  1302  		},
  1303  		{
  1304  			description:      "Both enforced",
  1305  			purpose2Enforced: true,
  1306  			feature1Enforced: true,
  1307  			wantPermissions: AuctionPermissions{
  1308  				AllowBidRequest: false,
  1309  				PassGeo:         false,
  1310  				PassID:          false,
  1311  			},
  1312  		},
  1313  	}
  1314  
  1315  	for _, tt := range tests {
  1316  		perms := permissionsImpl{}
  1317  
  1318  		tcf2AggConfig := allPurposesEnabledTCF2Config()
  1319  		tcf2AggConfig.HostConfig.Purpose2.EnforcePurpose = tt.purpose2Enforced
  1320  		tcf2AggConfig.HostConfig.SpecialFeature1.Enforce = tt.feature1Enforced
  1321  		tcf2AggConfig.HostConfig.PurposeConfigs[consentconstants.Purpose(2)] = &tcf2AggConfig.HostConfig.Purpose2
  1322  		perms.cfg = &tcf2AggConfig
  1323  
  1324  		result := perms.defaultPermissions()
  1325  
  1326  		assert.Equal(t, result, tt.wantPermissions, tt.description)
  1327  	}
  1328  }
  1329  
  1330  func TestVendorListSelection(t *testing.T) {
  1331  	policyVersion3WithVendor2AndPurpose1Consent := "CPGWbY_PGWbY_GYAAAENABDAAIAAAAAAAAAAACEAAAAA"
  1332  	policyVersion4WithVendor2AndPurpose1Consent := "CPGWbY_PGWbY_GYAAAENABEAAIAAAAAAAAAAACEAAAAA"
  1333  
  1334  	specVersion2vendorListData := MarshalVendorList(vendorList{
  1335  		GVLSpecificationVersion: 2,
  1336  		VendorListVersion:       2,
  1337  		Vendors: map[string]*vendor{
  1338  			"2": {
  1339  				ID:       2,
  1340  				Purposes: []int{},
  1341  			},
  1342  		},
  1343  	})
  1344  	specVersion3vendorListData := MarshalVendorList(vendorList{
  1345  		GVLSpecificationVersion: 3,
  1346  		VendorListVersion:       2,
  1347  		Vendors: map[string]*vendor{
  1348  			"2": {
  1349  				ID:       2,
  1350  				Purposes: []int{1},
  1351  			},
  1352  		},
  1353  	})
  1354  
  1355  	tcf2AggConfig := tcf2Config{
  1356  		HostConfig: config.TCF2{
  1357  			Purpose1: config.TCF2Purpose{
  1358  				EnforcePurpose: true,
  1359  				EnforceVendors: true,
  1360  			},
  1361  		},
  1362  	}
  1363  	tcf2AggConfig.HostConfig.PurposeConfigs = map[consentconstants.Purpose]*config.TCF2Purpose{
  1364  		consentconstants.Purpose(1): &tcf2AggConfig.HostConfig.Purpose1,
  1365  	}
  1366  
  1367  	perms := permissionsImpl{
  1368  		cfg:          &tcf2AggConfig,
  1369  		hostVendorID: 2,
  1370  		vendorIDs: map[openrtb_ext.BidderName]uint16{
  1371  			openrtb_ext.BidderAppnexus: 2,
  1372  		},
  1373  		fetchVendorList: listFetcher(map[uint16]map[uint16]vendorlist.VendorList{
  1374  			2: {
  1375  				1: parseVendorListDataV2(t, specVersion2vendorListData),
  1376  			},
  1377  			3: {
  1378  				1: parseVendorListDataV2(t, specVersion3vendorListData),
  1379  			},
  1380  		}),
  1381  		purposeEnforcerBuilder: NewPurposeEnforcerBuilder(&tcf2AggConfig),
  1382  		gdprSignal:             SignalYes,
  1383  	}
  1384  
  1385  	tests := []struct {
  1386  		name              string
  1387  		consent           string
  1388  		expectedAllowSync bool
  1389  		expectedErr       bool
  1390  	}{
  1391  		{
  1392  			name:              "consent_tcf_policy_version_3_uses_gvl_spec_version_2",
  1393  			consent:           policyVersion3WithVendor2AndPurpose1Consent,
  1394  			expectedAllowSync: false,
  1395  		},
  1396  		{
  1397  			name:              "consent_tcf_policy_version_4_uses_gvl_spec_version_3",
  1398  			consent:           policyVersion4WithVendor2AndPurpose1Consent,
  1399  			expectedAllowSync: true,
  1400  		},
  1401  	}
  1402  
  1403  	for _, tt := range tests {
  1404  		t.Run(tt.name, func(t *testing.T) {
  1405  			perms.consent = tt.consent
  1406  			allowSync, err := perms.HostCookiesAllowed(context.Background())
  1407  			assert.Equal(t, tt.expectedAllowSync, allowSync)
  1408  			if tt.expectedErr {
  1409  				assert.Error(t, err)
  1410  			} else {
  1411  				assert.Nil(t, err)
  1412  			}
  1413  		})
  1414  	}
  1415  }