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

     1  package gdpr
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/prebid/go-gdpr/consentconstants"
     7  	"github.com/prebid/go-gdpr/vendorconsent"
     8  	tcf2 "github.com/prebid/go-gdpr/vendorconsent/tcf2"
     9  	"github.com/prebid/go-gdpr/vendorlist"
    10  	"github.com/prebid/go-gdpr/vendorlist2"
    11  	"github.com/prebid/prebid-server/v2/openrtb_ext"
    12  	"github.com/prebid/prebid-server/v2/util/jsonutil"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  func TestLegalBasisWithPubRestrictionAllowNone(t *testing.T) {
    18  	var (
    19  		appnexus   = string(openrtb_ext.BidderAppnexus)
    20  		appnexusID = uint16(32)
    21  	)
    22  
    23  	NoConsentsWithP1P2P3V32RestrictionAllowNone := "CPfMKEAPfMKEAAAAAAENCgCAAAAAAAAAAAAAAQAAAAAAAIAAAAAAAGCAAgAgCAAQAQBgAIAIAAAA"
    24  	P1P2P3PurposeConsentAndV32VendorConsentWithP1P2P3V32RestrictionAllowNone := "CPfMKEAPfMKEAAAAAAENCgCAAOAAAAAAAAAAAQAAAAAEAIAAAAAAAGCAAgAgCAAQAQBgAIAIAAAA"
    25  
    26  	tests := []struct {
    27  		description              string
    28  		config                   purposeConfig
    29  		consent                  string
    30  		wantConsentPurposeResult bool
    31  		wantLIPurposeResult      bool
    32  		wantFlexPurposeResult    bool
    33  	}{
    34  		{
    35  			description: "enforce purpose & vendors off",
    36  			config: purposeConfig{
    37  				EnforcePurpose: false,
    38  				EnforceVendors: false,
    39  			},
    40  			consent:                  NoConsentsWithP1P2P3V32RestrictionAllowNone,
    41  			wantConsentPurposeResult: false,
    42  			wantLIPurposeResult:      false,
    43  			wantFlexPurposeResult:    false,
    44  		},
    45  		{
    46  			description: "enforce purpose & vendors on, bidder is a vendor exception",
    47  			config: purposeConfig{
    48  				EnforcePurpose:     true,
    49  				EnforceVendors:     true,
    50  				VendorExceptionMap: map[string]struct{}{appnexus: {}},
    51  			},
    52  			consent:                  NoConsentsWithP1P2P3V32RestrictionAllowNone,
    53  			wantConsentPurposeResult: false,
    54  			wantLIPurposeResult:      false,
    55  			wantFlexPurposeResult:    false,
    56  		},
    57  		{
    58  			description: "enforce purpose & vendors on, purpose consent Y, vendor consent Y",
    59  			config: purposeConfig{
    60  				EnforcePurpose: true,
    61  				EnforceVendors: true,
    62  			},
    63  			consent:                  P1P2P3PurposeConsentAndV32VendorConsentWithP1P2P3V32RestrictionAllowNone,
    64  			wantConsentPurposeResult: false,
    65  			wantLIPurposeResult:      false,
    66  			wantFlexPurposeResult:    false,
    67  		},
    68  	}
    69  
    70  	for _, tt := range tests {
    71  		// convert consent string to TCF2 object
    72  		parsedConsent, err := vendorconsent.ParseString(tt.consent)
    73  		if err != nil {
    74  			t.Fatalf("Failed to parse consent %s: %s\n", tt.consent, tt.description)
    75  		}
    76  		consentMeta, ok := parsedConsent.(tcf2.ConsentMetadata)
    77  		if !ok {
    78  			t.Fatalf("Failed to convert consent %s: %s\n", tt.consent, tt.description)
    79  		}
    80  
    81  		vendor := getVendorList(t).Vendor(appnexusID)
    82  		vendorInfo := VendorInfo{vendorID: appnexusID, vendor: vendor}
    83  		enforcer := FullEnforcement{cfg: tt.config}
    84  
    85  		enforcer.cfg.PurposeID = consentconstants.Purpose(1)
    86  		consentPurposeResult := enforcer.LegalBasis(vendorInfo, appnexus, consentMeta, Overrides{})
    87  		assert.Equal(t, tt.wantConsentPurposeResult, consentPurposeResult, tt.description+" -- GVL consent purpose")
    88  
    89  		enforcer.cfg.PurposeID = consentconstants.Purpose(2)
    90  		LIPurposeresult := enforcer.LegalBasis(vendorInfo, appnexus, consentMeta, Overrides{})
    91  		assert.Equal(t, tt.wantLIPurposeResult, LIPurposeresult, tt.description+" -- GVL LI purpose")
    92  
    93  		enforcer.cfg.PurposeID = consentconstants.Purpose(3)
    94  		flexPurposeResult := enforcer.LegalBasis(vendorInfo, appnexus, consentMeta, Overrides{})
    95  		assert.Equal(t, tt.wantFlexPurposeResult, flexPurposeResult, tt.description+" -- GVL flex purpose")
    96  	}
    97  }
    98  
    99  func TestLegalBasisWithNoPubRestrictionsAndWithPubRestrictionAllowAll(t *testing.T) {
   100  	var (
   101  		appnexus   = string(openrtb_ext.BidderAppnexus)
   102  		appnexusID = uint16(32)
   103  	)
   104  
   105  	NoConsents := "CPfCRQAPfCRQAAAAAAENCgCAAAAAAAAAAAAAAAAAAAAA"
   106  	P1P2P3PurposeConsent := "CPfCRQAPfCRQAAAAAAENCgCAAOAAAAAAAAAAAAAAAAAA"
   107  	P1P2P3PurposeLI := "CPfCRQAPfCRQAAAAAAENCgCAAAAAAOAAAAAAAAAAAAAA"
   108  	V32VendorConsent := "CPfCRQAPfCRQAAAAAAENCgCAAAAAAAAAAAAAAQAAAAAEAAAAAAAA"
   109  	V32VendorLI := "CPfCRQAPfCRQAAAAAAENCgCAAAAAAAAAAAAAAQAAAAAAAIAAAAACAAAA"
   110  	P1P2P3PurposeConsentAndV32VendorConsent := "CPfCRQAPfCRQAAAAAAENCgCAAOAAAAAAAAAAAQAAAAAEAIAAAAAAAAAA"
   111  	P1P2P3PurposeLIAndV32VendorLI := "CPfCRQAPfCRQAAAAAAENCgCAAAAAAOAAAAAAAQAAAAAAAIAAAAACAAAA"
   112  
   113  	NoConsentsWithP1P2P3V32RestrictionAllowAll := "CPfMKEAPfMKEAAAAAAENCgCAAAAAAAAAAAAAAQAAAAAAAIAAAAAAAGDgAgAgCwAQAQB4AIAIAAAA"
   114  	P1P2P3PurposeConsentWithP1P2P3V32RestrictionAllowAll := "CPfMKEAPfMKEAAAAAAENCgCAAOAAAAAAAAAAAQAAAAAAAIAAAAAAAGDgAgAgCwAQAQB4AIAIAAAA"
   115  	P1P2P3PurposeLIWithP1P2P3V32RestrictionAllowAll := "CPfMKEAPfMKEAAAAAAENCgCAAAAAAOAAAAAAAQAAAAAAAIAAAAAAAGDgAgAgCwAQAQB4AIAIAAAA"
   116  	V32VendorConsentWithP1P2P3V32RestrictionAllowAll := "CPfMKEAPfMKEAAAAAAENCgCAAAAAAAAAAAAAAQAAAAAEAIAAAAAAAGDgAgAgCwAQAQB4AIAIAAAA"
   117  	V32VendorLIWithP1P2P3V32RestrictionAllowAll := "CPfMKEAPfMKEAAAAAAENCgCAAAAAAAAAAAAAAQAAAAAAAIAAAAACAGDgAgAgCwAQAQB4AIAIAAAA"
   118  	P1P2P3PurposeConsentAndV32VendorConsentWithP1P2P3V32RestrictionAllowAll := "CPfMKEAPfMKEAAAAAAENCgCAAOAAAAAAAAAAAQAAAAAEAIAAAAAAAGDgAgAgCwAQAQB4AIAIAAAA"
   119  	P1P2P3PurposeLIAndV32VendorLIWithP1P2P3V32RestrictionAllowAll := "CPfMKEAPfMKEAAAAAAENCgCAAAAAAOAAAAAAAQAAAAAAAIAAAAACAGDgAgAgCwAQAQB4AIAIAAAA"
   120  
   121  	tests := []struct {
   122  		description               string
   123  		config                    purposeConfig
   124  		consentNoPubRestriction   string
   125  		consentWithPubRestriction string
   126  		overrides                 Overrides
   127  		wantConsentPurposeResult  bool
   128  		wantLIPurposeResult       bool
   129  		wantFlexPurposeResult     bool
   130  	}{
   131  		{
   132  			description: "enforce purpose & vendors off",
   133  			config: purposeConfig{
   134  				EnforcePurpose: false,
   135  				EnforceVendors: false,
   136  			},
   137  			consentNoPubRestriction:   NoConsents,
   138  			consentWithPubRestriction: NoConsentsWithP1P2P3V32RestrictionAllowAll,
   139  			wantConsentPurposeResult:  true,
   140  			wantLIPurposeResult:       true,
   141  			wantFlexPurposeResult:     true,
   142  		},
   143  		{
   144  			description: "enforce purpose on, purpose consent N, legit interest N",
   145  			config: purposeConfig{
   146  				EnforcePurpose: true,
   147  			},
   148  			consentNoPubRestriction:   NoConsents,
   149  			consentWithPubRestriction: NoConsentsWithP1P2P3V32RestrictionAllowAll,
   150  			wantConsentPurposeResult:  false,
   151  			wantLIPurposeResult:       false,
   152  			wantFlexPurposeResult:     false,
   153  		},
   154  		{
   155  			description: "enforce purpose on, purpose consent Y",
   156  			config: purposeConfig{
   157  				EnforcePurpose: true,
   158  			},
   159  			consentNoPubRestriction:   P1P2P3PurposeConsent,
   160  			consentWithPubRestriction: P1P2P3PurposeConsentWithP1P2P3V32RestrictionAllowAll,
   161  			wantConsentPurposeResult:  true,
   162  			wantLIPurposeResult:       false,
   163  			wantFlexPurposeResult:     true,
   164  		},
   165  		{
   166  			description: "enforce purpose on, legit interest Y",
   167  			config: purposeConfig{
   168  				EnforcePurpose: true,
   169  			},
   170  			consentNoPubRestriction:   P1P2P3PurposeLI,
   171  			consentWithPubRestriction: P1P2P3PurposeLIWithP1P2P3V32RestrictionAllowAll,
   172  			wantConsentPurposeResult:  false,
   173  			wantLIPurposeResult:       true,
   174  			wantFlexPurposeResult:     true,
   175  		},
   176  		{
   177  			description: "enforce purpose on, purpose consent Y, enforce vendors off but overrides treats it as on",
   178  			config: purposeConfig{
   179  				EnforcePurpose: true,
   180  			},
   181  			consentNoPubRestriction:   P1P2P3PurposeConsent,
   182  			consentWithPubRestriction: P1P2P3PurposeConsentWithP1P2P3V32RestrictionAllowAll,
   183  			overrides:                 Overrides{enforceVendors: true},
   184  			wantConsentPurposeResult:  false,
   185  			wantLIPurposeResult:       false,
   186  			wantFlexPurposeResult:     false,
   187  		},
   188  		{
   189  			description: "enforce purpose on, purpose consent Y, vendor consent Y, enforce vendors off but overrides treats it as on",
   190  			config: purposeConfig{
   191  				EnforcePurpose: true,
   192  			},
   193  			consentNoPubRestriction:   P1P2P3PurposeConsentAndV32VendorConsent,
   194  			consentWithPubRestriction: P1P2P3PurposeConsentAndV32VendorConsentWithP1P2P3V32RestrictionAllowAll,
   195  			overrides:                 Overrides{enforceVendors: true},
   196  			wantConsentPurposeResult:  true,
   197  			wantLIPurposeResult:       false,
   198  			wantFlexPurposeResult:     true,
   199  		},
   200  		{
   201  			description: "enforce vendors on, vendor consent N, vendor legit interest N",
   202  			config: purposeConfig{
   203  				EnforceVendors: true,
   204  			},
   205  			consentNoPubRestriction:   NoConsents,
   206  			consentWithPubRestriction: NoConsentsWithP1P2P3V32RestrictionAllowAll,
   207  			wantConsentPurposeResult:  false,
   208  			wantLIPurposeResult:       false,
   209  			wantFlexPurposeResult:     false,
   210  		},
   211  		{
   212  			description: "enforce vendors on, vendor consent Y",
   213  			config: purposeConfig{
   214  				EnforceVendors: true,
   215  			},
   216  			consentNoPubRestriction:   V32VendorConsent,
   217  			consentWithPubRestriction: V32VendorConsentWithP1P2P3V32RestrictionAllowAll,
   218  			wantConsentPurposeResult:  true,
   219  			wantLIPurposeResult:       false,
   220  			wantFlexPurposeResult:     true,
   221  		},
   222  		{
   223  			description: "enforce vendors on, vendor legit interest Y",
   224  			config: purposeConfig{
   225  				EnforceVendors: true,
   226  			},
   227  			consentNoPubRestriction:   V32VendorLI,
   228  			consentWithPubRestriction: V32VendorLIWithP1P2P3V32RestrictionAllowAll,
   229  			wantConsentPurposeResult:  false,
   230  			wantLIPurposeResult:       true,
   231  			wantFlexPurposeResult:     true,
   232  		},
   233  		{
   234  			description: "enforce vendors on, vendor consent Y, enforce purpose off but overrides treats it as on",
   235  			config: purposeConfig{
   236  				EnforceVendors: true,
   237  			},
   238  			consentNoPubRestriction:   V32VendorConsent,
   239  			consentWithPubRestriction: V32VendorConsentWithP1P2P3V32RestrictionAllowAll,
   240  			overrides:                 Overrides{enforcePurpose: true},
   241  			wantConsentPurposeResult:  false,
   242  			wantLIPurposeResult:       false,
   243  			wantFlexPurposeResult:     false,
   244  		},
   245  		{
   246  			description: "enforce vendors on, purpose consent Y, vendor consent Y, enforce purpose off but overrides treats it as on",
   247  			config: purposeConfig{
   248  				EnforceVendors: true,
   249  			},
   250  			consentNoPubRestriction:   P1P2P3PurposeConsentAndV32VendorConsent,
   251  			consentWithPubRestriction: P1P2P3PurposeConsentAndV32VendorConsentWithP1P2P3V32RestrictionAllowAll,
   252  			overrides:                 Overrides{enforcePurpose: true},
   253  			wantConsentPurposeResult:  true,
   254  			wantLIPurposeResult:       false,
   255  			wantFlexPurposeResult:     true,
   256  		},
   257  		{
   258  			description: "enforce purpose & vendors on, purpose consent Y, vendor consent N",
   259  			config: purposeConfig{
   260  				EnforcePurpose: true,
   261  				EnforceVendors: true,
   262  			},
   263  			consentNoPubRestriction:   P1P2P3PurposeConsent,
   264  			consentWithPubRestriction: P1P2P3PurposeConsentWithP1P2P3V32RestrictionAllowAll,
   265  			wantConsentPurposeResult:  false,
   266  			wantLIPurposeResult:       false,
   267  			wantFlexPurposeResult:     false,
   268  		},
   269  		{
   270  			description: "enforce purpose & vendors on, purpose consent N, vendor consent Y",
   271  			config: purposeConfig{
   272  				EnforcePurpose: true,
   273  				EnforceVendors: true,
   274  			},
   275  			consentNoPubRestriction:   V32VendorConsent,
   276  			consentWithPubRestriction: V32VendorConsentWithP1P2P3V32RestrictionAllowAll,
   277  			wantConsentPurposeResult:  false,
   278  			wantLIPurposeResult:       false,
   279  			wantFlexPurposeResult:     false,
   280  		},
   281  		{
   282  			description: "enforce purpose & vendors on, purpose consent Y, vendor consent Y",
   283  			config: purposeConfig{
   284  				EnforcePurpose: true,
   285  				EnforceVendors: true,
   286  			},
   287  			consentNoPubRestriction:   P1P2P3PurposeConsentAndV32VendorConsent,
   288  			consentWithPubRestriction: P1P2P3PurposeConsentAndV32VendorConsentWithP1P2P3V32RestrictionAllowAll,
   289  			wantConsentPurposeResult:  true,
   290  			wantLIPurposeResult:       false,
   291  			wantFlexPurposeResult:     true,
   292  		},
   293  		{
   294  			description: "enforce purpose & vendors on, legit interest Y, vendor legit interest N",
   295  			config: purposeConfig{
   296  				EnforcePurpose: true,
   297  				EnforceVendors: true,
   298  			},
   299  			consentNoPubRestriction:   P1P2P3PurposeLI,
   300  			consentWithPubRestriction: P1P2P3PurposeLIWithP1P2P3V32RestrictionAllowAll,
   301  			wantConsentPurposeResult:  false,
   302  			wantLIPurposeResult:       false,
   303  			wantFlexPurposeResult:     false,
   304  		},
   305  		{
   306  			description: "enforce purpose & vendors on, legit interest N, vendor legit interest Y",
   307  			config: purposeConfig{
   308  				EnforcePurpose: true,
   309  				EnforceVendors: true,
   310  			},
   311  			consentNoPubRestriction:   V32VendorLI,
   312  			consentWithPubRestriction: V32VendorLIWithP1P2P3V32RestrictionAllowAll,
   313  			wantConsentPurposeResult:  false,
   314  			wantLIPurposeResult:       false,
   315  			wantFlexPurposeResult:     false,
   316  		},
   317  		{
   318  			description: "enforce purpose & vendors on, legit interest Y, vendor legit interest Y",
   319  			config: purposeConfig{
   320  				EnforcePurpose: true,
   321  				EnforceVendors: true,
   322  			},
   323  			consentNoPubRestriction:   P1P2P3PurposeLIAndV32VendorLI,
   324  			consentWithPubRestriction: P1P2P3PurposeLIAndV32VendorLIWithP1P2P3V32RestrictionAllowAll,
   325  			wantConsentPurposeResult:  false,
   326  			wantLIPurposeResult:       true,
   327  			wantFlexPurposeResult:     true,
   328  		},
   329  		{
   330  			description: "enforce purpose & vendors on, bidder is a vendor exception",
   331  			config: purposeConfig{
   332  				EnforcePurpose:     true,
   333  				EnforceVendors:     true,
   334  				VendorExceptionMap: map[string]struct{}{appnexus: {}},
   335  			},
   336  			consentNoPubRestriction:   NoConsents,
   337  			consentWithPubRestriction: NoConsentsWithP1P2P3V32RestrictionAllowAll,
   338  			wantConsentPurposeResult:  true,
   339  			wantLIPurposeResult:       true,
   340  			wantFlexPurposeResult:     true,
   341  		},
   342  		{
   343  			description: "enforce purpose & vendors on, bidder is a vendor exception but overrides disallow them",
   344  			config: purposeConfig{
   345  				EnforcePurpose:     true,
   346  				EnforceVendors:     true,
   347  				VendorExceptionMap: map[string]struct{}{appnexus: {}},
   348  			},
   349  			consentNoPubRestriction:   NoConsents,
   350  			consentWithPubRestriction: NoConsentsWithP1P2P3V32RestrictionAllowAll,
   351  			overrides:                 Overrides{blockVendorExceptions: true},
   352  			wantConsentPurposeResult:  false,
   353  			wantLIPurposeResult:       false,
   354  			wantFlexPurposeResult:     false,
   355  		},
   356  	}
   357  
   358  	for _, tt := range tests {
   359  		consents := [2]string{tt.consentNoPubRestriction, tt.consentWithPubRestriction}
   360  
   361  		for i := 0; i < len(consents); i++ {
   362  			consent := consents[i]
   363  
   364  			// convert consent string to TCF2 object
   365  			parsedConsent, err := vendorconsent.ParseString(consent)
   366  			if err != nil {
   367  				t.Fatalf("Failed to parse consent %s: %s\n", consent, tt.description)
   368  			}
   369  			consentMeta, ok := parsedConsent.(tcf2.ConsentMetadata)
   370  			if !ok {
   371  				t.Fatalf("Failed to convert consent %s: %s\n", consent, tt.description)
   372  			}
   373  
   374  			vendor := getVendorList(t).Vendor(appnexusID)
   375  			vendorInfo := VendorInfo{vendorID: appnexusID, vendor: vendor}
   376  			enforcer := FullEnforcement{cfg: tt.config}
   377  
   378  			enforcer.cfg.PurposeID = consentconstants.Purpose(1)
   379  			consentPurposeResult := enforcer.LegalBasis(vendorInfo, appnexus, consentMeta, tt.overrides)
   380  			assert.Equal(t, tt.wantConsentPurposeResult, consentPurposeResult, tt.description+" -- GVL consent purpose -- consent string %d of %d", i+1, len(consents))
   381  
   382  			enforcer.cfg.PurposeID = consentconstants.Purpose(2)
   383  			LIPurposeresult := enforcer.LegalBasis(vendorInfo, appnexus, consentMeta, tt.overrides)
   384  			assert.Equal(t, tt.wantLIPurposeResult, LIPurposeresult, tt.description+" -- GVL LI purpose -- consent string %d of %d", i+1, len(consents))
   385  
   386  			enforcer.cfg.PurposeID = consentconstants.Purpose(3)
   387  			flexPurposeResult := enforcer.LegalBasis(vendorInfo, appnexus, consentMeta, tt.overrides)
   388  			assert.Equal(t, tt.wantFlexPurposeResult, flexPurposeResult, tt.description+" -- GVL flex purpose -- consent string %d of %d", i+1, len(consents))
   389  		}
   390  	}
   391  }
   392  
   393  func TestLegalBasisWithPubRestrictionRequireConsent(t *testing.T) {
   394  	var (
   395  		appnexus   = string(openrtb_ext.BidderAppnexus)
   396  		appnexusID = uint16(32)
   397  	)
   398  
   399  	NoConsentsWithP1P2P3V32RestrictionRequireConsent := "CPfFkMAPfFkMAAAAAAENCgCAAAAAAAAAAAAAAQAAAAAAAIAAAAAAAGCgAgAgCQAQAQBoAIAIAAAA"
   400  	P1P2P3PurposeConsentWithP1P2P3V32RestrictionRequireConsent := "CPfFkMAPfFkMAAAAAAENCgCAAOAAAAAAAAAAAQAAAAAAAIAAAAAAAGCgAgAgCQAQAQBoAIAIAAAA"
   401  	P1P2P3PurposeLIWithP1P2P3V32RestrictionRequireConsent := "CPfFkMAPfFkMAAAAAAENCgCAAAAAAOAAAAAAAQAAAAAAAIAAAAAAAGCgAgAgCQAQAQBoAIAIAAAA"
   402  	V32VendorConsentWithP1P2P3V32RestrictionRequireConsent := "CPfFkMAPfFkMAAAAAAENCgCAAAAAAAAAAAAAAQAAAAAEAIAAAAAAAGCgAgAgCQAQAQBoAIAIAAAA"
   403  	V32VendorLIWithP1P2P3V32RestrictionRequireConsent := "CPfFkMAPfFkMAAAAAAENCgCAAAAAAAAAAAAAAQAAAAAAAIAAAAACAGCgAgAgCQAQAQBoAIAIAAAA"
   404  	P1P2P3PurposeConsentAndV32VendorConsentWithP1P2P3V32RestrictionRequireConsent := "CPfFkMAPfFkMAAAAAAENCgCAAOAAAAAAAAAAAQAAAAAEAIAAAAAAAGCgAgAgCQAQAQBoAIAIAAAA"
   405  	P1P2P3PurposeLIAndV32VendorLIWithP1P2P3V32RestrictionRequireConsent := "CPfFkMAPfFkMAAAAAAENCgCAAAAAAOAAAAAAAQAAAAAAAIAAAAACAGCgAgAgCQAQAQBoAIAIAAAA"
   406  
   407  	tests := []struct {
   408  		description              string
   409  		config                   purposeConfig
   410  		consent                  string
   411  		overrides                Overrides
   412  		wantConsentPurposeResult bool
   413  		wantLIPurposeResult      bool
   414  		wantFlexPurposeResult    bool
   415  	}{
   416  		{
   417  			description: "enforce purpose & vendors off",
   418  			config: purposeConfig{
   419  				EnforcePurpose: false,
   420  				EnforceVendors: false,
   421  			},
   422  			consent:                  NoConsentsWithP1P2P3V32RestrictionRequireConsent,
   423  			wantConsentPurposeResult: true,
   424  			wantLIPurposeResult:      true,
   425  			wantFlexPurposeResult:    true,
   426  		},
   427  		{
   428  			description: "enforce purpose on, purpose consent N, legit interest N",
   429  			config: purposeConfig{
   430  				EnforcePurpose: true,
   431  			},
   432  			consent:                  NoConsentsWithP1P2P3V32RestrictionRequireConsent,
   433  			wantConsentPurposeResult: false,
   434  			wantLIPurposeResult:      false,
   435  			wantFlexPurposeResult:    false,
   436  		},
   437  		{
   438  			description: "enforce purpose on, purpose consent Y",
   439  			config: purposeConfig{
   440  				EnforcePurpose: true,
   441  			},
   442  			consent:                  P1P2P3PurposeConsentWithP1P2P3V32RestrictionRequireConsent,
   443  			wantConsentPurposeResult: true,
   444  			wantLIPurposeResult:      false,
   445  			wantFlexPurposeResult:    true,
   446  		},
   447  		{
   448  			description: "enforce purpose on, legit interest Y",
   449  			config: purposeConfig{
   450  				EnforcePurpose: true,
   451  			},
   452  			consent:                  P1P2P3PurposeLIWithP1P2P3V32RestrictionRequireConsent,
   453  			wantConsentPurposeResult: false,
   454  			wantLIPurposeResult:      false,
   455  			wantFlexPurposeResult:    false,
   456  		},
   457  		{
   458  			description: "enforce purpose on, purpose consent Y, enforce vendors off but overrides treats it as on",
   459  			config: purposeConfig{
   460  				EnforcePurpose: true,
   461  			},
   462  			consent:                  P1P2P3PurposeConsentWithP1P2P3V32RestrictionRequireConsent,
   463  			overrides:                Overrides{enforceVendors: true},
   464  			wantConsentPurposeResult: false,
   465  			wantLIPurposeResult:      false,
   466  			wantFlexPurposeResult:    false,
   467  		},
   468  		{
   469  			description: "enforce purpose on, purpose consent Y, vendor consent Y, enforce vendors off but overrides treats it as on",
   470  			config: purposeConfig{
   471  				EnforcePurpose: true,
   472  			},
   473  			consent:                  P1P2P3PurposeConsentAndV32VendorConsentWithP1P2P3V32RestrictionRequireConsent,
   474  			overrides:                Overrides{enforceVendors: true},
   475  			wantConsentPurposeResult: true,
   476  			wantLIPurposeResult:      false,
   477  			wantFlexPurposeResult:    true,
   478  		},
   479  		{
   480  			description: "enforce vendors on, vendor consent N, vendor legit interest N",
   481  			config: purposeConfig{
   482  				EnforceVendors: true,
   483  			},
   484  			consent:                  NoConsentsWithP1P2P3V32RestrictionRequireConsent,
   485  			wantConsentPurposeResult: false,
   486  			wantLIPurposeResult:      false,
   487  			wantFlexPurposeResult:    false,
   488  		},
   489  		{
   490  			description: "enforce vendors on, vendor consent Y",
   491  			config: purposeConfig{
   492  				EnforceVendors: true,
   493  			},
   494  			consent:                  V32VendorConsentWithP1P2P3V32RestrictionRequireConsent,
   495  			wantConsentPurposeResult: true,
   496  			wantLIPurposeResult:      false,
   497  			wantFlexPurposeResult:    true,
   498  		},
   499  		{
   500  			description: "enforce vendors on, vendor legit interest Y",
   501  			config: purposeConfig{
   502  				EnforceVendors: true,
   503  			},
   504  			consent:                  V32VendorLIWithP1P2P3V32RestrictionRequireConsent,
   505  			wantConsentPurposeResult: false,
   506  			wantLIPurposeResult:      false,
   507  			wantFlexPurposeResult:    false,
   508  		},
   509  		{
   510  			description: "enforce vendors on, vendor consent Y, enforce purpose off but overrides treats it as on",
   511  			config: purposeConfig{
   512  				EnforceVendors: true,
   513  			},
   514  			consent:                  V32VendorConsentWithP1P2P3V32RestrictionRequireConsent,
   515  			overrides:                Overrides{enforcePurpose: true},
   516  			wantConsentPurposeResult: false,
   517  			wantLIPurposeResult:      false,
   518  			wantFlexPurposeResult:    false,
   519  		},
   520  		{
   521  			description: "enforce vendors on, purpose consent Y, vendor consent Y, enforce purpose off but overrides treats it as on",
   522  			config: purposeConfig{
   523  				EnforceVendors: true,
   524  			},
   525  			consent:                  P1P2P3PurposeConsentAndV32VendorConsentWithP1P2P3V32RestrictionRequireConsent,
   526  			overrides:                Overrides{enforcePurpose: true},
   527  			wantConsentPurposeResult: true,
   528  			wantLIPurposeResult:      false,
   529  			wantFlexPurposeResult:    true,
   530  		},
   531  		{
   532  			description: "enforce purpose & vendors on, purpose consent Y, vendor consent N",
   533  			config: purposeConfig{
   534  				EnforcePurpose: true,
   535  				EnforceVendors: true,
   536  			},
   537  			consent:                  P1P2P3PurposeConsentWithP1P2P3V32RestrictionRequireConsent,
   538  			wantConsentPurposeResult: false,
   539  			wantLIPurposeResult:      false,
   540  			wantFlexPurposeResult:    false,
   541  		},
   542  		{
   543  			description: "enforce purpose & vendors on, purpose consent N, vendor consent Y",
   544  			config: purposeConfig{
   545  				EnforcePurpose: true,
   546  				EnforceVendors: true,
   547  			},
   548  			consent:                  V32VendorConsentWithP1P2P3V32RestrictionRequireConsent,
   549  			wantConsentPurposeResult: false,
   550  			wantLIPurposeResult:      false,
   551  			wantFlexPurposeResult:    false,
   552  		},
   553  		{
   554  			description: "enforce purpose & vendors on, purpose consent Y, vendor consent Y",
   555  			config: purposeConfig{
   556  				EnforcePurpose: true,
   557  				EnforceVendors: true,
   558  			},
   559  			consent:                  P1P2P3PurposeConsentAndV32VendorConsentWithP1P2P3V32RestrictionRequireConsent,
   560  			wantConsentPurposeResult: true,
   561  			wantLIPurposeResult:      false,
   562  			wantFlexPurposeResult:    true,
   563  		},
   564  		{
   565  			description: "enforce purpose & vendors on, legit interest Y, vendor legit interest N",
   566  			config: purposeConfig{
   567  				EnforcePurpose: true,
   568  				EnforceVendors: true,
   569  			},
   570  			consent:                  P1P2P3PurposeLIWithP1P2P3V32RestrictionRequireConsent,
   571  			wantConsentPurposeResult: false,
   572  			wantLIPurposeResult:      false,
   573  			wantFlexPurposeResult:    false,
   574  		},
   575  		{
   576  			description: "enforce purpose & vendors on, legit interest N, vendor legit interest Y",
   577  			config: purposeConfig{
   578  				EnforcePurpose: true,
   579  				EnforceVendors: true,
   580  			},
   581  			consent:                  V32VendorLIWithP1P2P3V32RestrictionRequireConsent,
   582  			wantConsentPurposeResult: false,
   583  			wantLIPurposeResult:      false,
   584  			wantFlexPurposeResult:    false,
   585  		},
   586  		{
   587  			description: "enforce purpose & vendors on, legit interest Y, vendor legit interest Y",
   588  			config: purposeConfig{
   589  				EnforcePurpose: true,
   590  				EnforceVendors: true,
   591  			},
   592  			consent:                  P1P2P3PurposeLIAndV32VendorLIWithP1P2P3V32RestrictionRequireConsent,
   593  			wantConsentPurposeResult: false,
   594  			wantLIPurposeResult:      false,
   595  			wantFlexPurposeResult:    false,
   596  		},
   597  		{
   598  			description: "enforce purpose & vendors on, bidder is a vendor exception",
   599  			config: purposeConfig{
   600  				EnforcePurpose:     true,
   601  				EnforceVendors:     true,
   602  				VendorExceptionMap: map[string]struct{}{appnexus: {}},
   603  			},
   604  			consent:                  NoConsentsWithP1P2P3V32RestrictionRequireConsent,
   605  			wantConsentPurposeResult: true,
   606  			wantLIPurposeResult:      true,
   607  			wantFlexPurposeResult:    true,
   608  		},
   609  		{
   610  			description: "enforce purpose & vendors on, bidder is a vendor exception but overrides disallow them",
   611  			config: purposeConfig{
   612  				EnforcePurpose:     true,
   613  				EnforceVendors:     true,
   614  				VendorExceptionMap: map[string]struct{}{appnexus: {}},
   615  			},
   616  			consent:                  NoConsentsWithP1P2P3V32RestrictionRequireConsent,
   617  			overrides:                Overrides{blockVendorExceptions: true},
   618  			wantConsentPurposeResult: false,
   619  			wantLIPurposeResult:      false,
   620  			wantFlexPurposeResult:    false,
   621  		},
   622  	}
   623  
   624  	for _, tt := range tests {
   625  		// convert consent string to TCF2 object
   626  		parsedConsent, err := vendorconsent.ParseString(tt.consent)
   627  		if err != nil {
   628  			t.Fatalf("Failed to parse consent %s: %s\n", tt.consent, tt.description)
   629  		}
   630  		consentMeta, ok := parsedConsent.(tcf2.ConsentMetadata)
   631  		if !ok {
   632  			t.Fatalf("Failed to convert consent %s: %s\n", tt.consent, tt.description)
   633  		}
   634  
   635  		vendor := getVendorList(t).Vendor(appnexusID)
   636  		vendorInfo := VendorInfo{vendorID: appnexusID, vendor: vendor}
   637  		enforcer := FullEnforcement{cfg: tt.config}
   638  
   639  		enforcer.cfg.PurposeID = consentconstants.Purpose(1)
   640  		consentPurposeResult := enforcer.LegalBasis(vendorInfo, appnexus, consentMeta, tt.overrides)
   641  		assert.Equal(t, tt.wantConsentPurposeResult, consentPurposeResult, tt.description+" -- GVL consent purpose")
   642  
   643  		enforcer.cfg.PurposeID = consentconstants.Purpose(2)
   644  		LIPurposeresult := enforcer.LegalBasis(vendorInfo, appnexus, consentMeta, tt.overrides)
   645  		assert.Equal(t, tt.wantLIPurposeResult, LIPurposeresult, tt.description+" -- GVL LI purpose")
   646  
   647  		enforcer.cfg.PurposeID = consentconstants.Purpose(3)
   648  		flexPurposeResult := enforcer.LegalBasis(vendorInfo, appnexus, consentMeta, tt.overrides)
   649  		assert.Equal(t, tt.wantFlexPurposeResult, flexPurposeResult, tt.description+" -- GVL flex purpose")
   650  	}
   651  }
   652  
   653  func TestLegalBasisWithPubRestrictionRequireLI(t *testing.T) {
   654  	var (
   655  		appnexus   = string(openrtb_ext.BidderAppnexus)
   656  		appnexusID = uint16(32)
   657  	)
   658  
   659  	NoConsentsWithP1P2P3V32RestrictionRequireLI := "CPfFkMAPfFkMAAAAAAENCgCAAAAAAAAAAAAAAQAAAAAAAIAAAAAAAGDAAgAgCgAQAQBwAIAIAAAA"
   660  	P1P2P3PurposeConsentWithP1P2P3V32RestrictionRequireLI := "CPfFkMAPfFkMAAAAAAENCgCAAOAAAAAAAAAAAQAAAAAAAIAAAAAAAGDAAgAgCgAQAQBwAIAIAAAA"
   661  	P1P2P3PurposeLIWithP1P2P3V32RestrictionRequireLI := "CPfFkMAPfFkMAAAAAAENCgCAAAAAAOAAAAAAAQAAAAAAAIAAAAAAAGDAAgAgCgAQAQBwAIAIAAAA"
   662  	V32VendorConsentWithP1P2P3V32RestrictionRequireLI := "CPfFkMAPfFkMAAAAAAENCgCAAAAAAAAAAAAAAQAAAAAEAIAAAAAAAGDAAgAgCgAQAQBwAIAIAAAA"
   663  	V32VendorLIWithP1P2P3V32RestrictionRequireLI := "CPfFkMAPfFkMAAAAAAENCgCAAAAAAAAAAAAAAQAAAAAAAIAAAAACAGDAAgAgCgAQAQBwAIAIAAAA"
   664  	P1P2P3PurposeConsentAndV32VendorConsentWithP1P2P3V32RestrictionRequireLI := "CPfFkMAPfFkMAAAAAAENCgCAAOAAAAAAAAAAAQAAAAAEAIAAAAAAAGDAAgAgCgAQAQBwAIAIAAAA"
   665  	P1P2P3PurposeLIAndV32VendorLIWithP1P2P3V32RestrictionRequireLI := "CPfFkMAPfFkMAAAAAAENCgCAAAAAAOAAAAAAAQAAAAAAAIAAAAACAGDAAgAgCgAQAQBwAIAIAAAA"
   666  
   667  	tests := []struct {
   668  		description              string
   669  		config                   purposeConfig
   670  		consent                  string
   671  		overrides                Overrides
   672  		wantConsentPurposeResult bool
   673  		wantLIPurposeResult      bool
   674  		wantFlexPurposeResult    bool
   675  	}{
   676  		{
   677  			description: "enforce purpose & vendors off",
   678  			config: purposeConfig{
   679  				EnforcePurpose: false,
   680  				EnforceVendors: false,
   681  			},
   682  			consent:                  NoConsentsWithP1P2P3V32RestrictionRequireLI,
   683  			wantConsentPurposeResult: true,
   684  			wantLIPurposeResult:      true,
   685  			wantFlexPurposeResult:    true,
   686  		},
   687  		{
   688  			description: "enforce purpose on, purpose consent N, legit interest N",
   689  			config: purposeConfig{
   690  				EnforcePurpose: true,
   691  			},
   692  			consent:                  NoConsentsWithP1P2P3V32RestrictionRequireLI,
   693  			wantConsentPurposeResult: false,
   694  			wantLIPurposeResult:      false,
   695  			wantFlexPurposeResult:    false,
   696  		},
   697  		{
   698  			description: "enforce purpose on, purpose consent Y",
   699  			config: purposeConfig{
   700  				EnforcePurpose: true,
   701  			},
   702  			consent:                  P1P2P3PurposeConsentWithP1P2P3V32RestrictionRequireLI,
   703  			wantConsentPurposeResult: false,
   704  			wantLIPurposeResult:      false,
   705  			wantFlexPurposeResult:    false,
   706  		},
   707  		{
   708  			description: "enforce purpose on, legit interest Y",
   709  			config: purposeConfig{
   710  				EnforcePurpose: true,
   711  			},
   712  			consent:                  P1P2P3PurposeLIWithP1P2P3V32RestrictionRequireLI,
   713  			wantConsentPurposeResult: false,
   714  			wantLIPurposeResult:      true,
   715  			wantFlexPurposeResult:    true,
   716  		},
   717  		{
   718  			description: "enforce purpose on, vendor legit interest Y, enforce vendors off but overrides treats it as on",
   719  			config: purposeConfig{
   720  				EnforcePurpose: true,
   721  			},
   722  			consent:                  P1P2P3PurposeLIWithP1P2P3V32RestrictionRequireLI,
   723  			overrides:                Overrides{enforceVendors: true},
   724  			wantConsentPurposeResult: false,
   725  			wantLIPurposeResult:      false,
   726  			wantFlexPurposeResult:    false,
   727  		},
   728  		{
   729  			description: "enforce purpose on, vendor legit interest Y, vendor consent Y, enforce vendors off but overrides treats it as on",
   730  			config: purposeConfig{
   731  				EnforcePurpose: true,
   732  			},
   733  			consent:                  P1P2P3PurposeLIAndV32VendorLIWithP1P2P3V32RestrictionRequireLI,
   734  			overrides:                Overrides{enforceVendors: true},
   735  			wantConsentPurposeResult: false,
   736  			wantLIPurposeResult:      true,
   737  			wantFlexPurposeResult:    true,
   738  		},
   739  		{
   740  			description: "enforce vendors on, vendor consent N, vendor legit interest N",
   741  			config: purposeConfig{
   742  				EnforceVendors: true,
   743  			},
   744  			consent:                  NoConsentsWithP1P2P3V32RestrictionRequireLI,
   745  			wantConsentPurposeResult: false,
   746  			wantLIPurposeResult:      false,
   747  			wantFlexPurposeResult:    false,
   748  		},
   749  		{
   750  			description: "enforce vendors on, vendor consent Y",
   751  			config: purposeConfig{
   752  				EnforceVendors: true,
   753  			},
   754  			consent:                  V32VendorConsentWithP1P2P3V32RestrictionRequireLI,
   755  			wantConsentPurposeResult: false,
   756  			wantLIPurposeResult:      false,
   757  			wantFlexPurposeResult:    false,
   758  		},
   759  		{
   760  			description: "enforce vendors on, vendor legit interest Y",
   761  			config: purposeConfig{
   762  				EnforceVendors: true,
   763  			},
   764  			consent:                  V32VendorLIWithP1P2P3V32RestrictionRequireLI,
   765  			wantConsentPurposeResult: false,
   766  			wantLIPurposeResult:      true,
   767  			wantFlexPurposeResult:    true,
   768  		},
   769  		{
   770  			description: "enforce vendors on, vendor legit interest Y, enforce purpose off but overrides treats it as on",
   771  			config: purposeConfig{
   772  				EnforceVendors: true,
   773  			},
   774  			consent:                  V32VendorLIWithP1P2P3V32RestrictionRequireLI,
   775  			overrides:                Overrides{enforcePurpose: true},
   776  			wantConsentPurposeResult: false,
   777  			wantLIPurposeResult:      false,
   778  			wantFlexPurposeResult:    false,
   779  		},
   780  		{
   781  			description: "enforce vendors on, vendor legit interest Y, vendor consent Y, enforce purpose off but overrides treats it as on",
   782  			config: purposeConfig{
   783  				EnforceVendors: true,
   784  			},
   785  			consent:                  P1P2P3PurposeLIAndV32VendorLIWithP1P2P3V32RestrictionRequireLI,
   786  			overrides:                Overrides{enforcePurpose: true},
   787  			wantConsentPurposeResult: false,
   788  			wantLIPurposeResult:      true,
   789  			wantFlexPurposeResult:    true,
   790  		},
   791  		{
   792  			description: "enforce purpose & vendors on, purpose consent Y, vendor consent N",
   793  			config: purposeConfig{
   794  				EnforcePurpose: true,
   795  				EnforceVendors: true,
   796  			},
   797  			consent:                  P1P2P3PurposeConsentWithP1P2P3V32RestrictionRequireLI,
   798  			wantConsentPurposeResult: false,
   799  			wantLIPurposeResult:      false,
   800  			wantFlexPurposeResult:    false,
   801  		},
   802  		{
   803  			description: "enforce purpose & vendors on, purpose consent N, vendor consent Y",
   804  			config: purposeConfig{
   805  				EnforcePurpose: true,
   806  				EnforceVendors: true,
   807  			},
   808  			consent:                  V32VendorConsentWithP1P2P3V32RestrictionRequireLI,
   809  			wantConsentPurposeResult: false,
   810  			wantLIPurposeResult:      false,
   811  			wantFlexPurposeResult:    false,
   812  		},
   813  		{
   814  			description: "enforce purpose & vendors on, purpose consent Y, vendor consent Y",
   815  			config: purposeConfig{
   816  				EnforcePurpose: true,
   817  				EnforceVendors: true,
   818  			},
   819  			consent:                  P1P2P3PurposeConsentAndV32VendorConsentWithP1P2P3V32RestrictionRequireLI,
   820  			wantConsentPurposeResult: false,
   821  			wantLIPurposeResult:      false,
   822  			wantFlexPurposeResult:    false,
   823  		},
   824  		{
   825  			description: "enforce purpose & vendors on, legit interest Y, vendor legit interest N",
   826  			config: purposeConfig{
   827  				EnforcePurpose: true,
   828  				EnforceVendors: true,
   829  			},
   830  			consent:                  P1P2P3PurposeLIWithP1P2P3V32RestrictionRequireLI,
   831  			wantConsentPurposeResult: false,
   832  			wantLIPurposeResult:      false,
   833  			wantFlexPurposeResult:    false,
   834  		},
   835  		{
   836  			description: "enforce purpose & vendors on, legit interest N, vendor legit interest Y",
   837  			config: purposeConfig{
   838  				EnforcePurpose: true,
   839  				EnforceVendors: true,
   840  			},
   841  			consent:                  V32VendorLIWithP1P2P3V32RestrictionRequireLI,
   842  			wantConsentPurposeResult: false,
   843  			wantLIPurposeResult:      false,
   844  			wantFlexPurposeResult:    false,
   845  		},
   846  		{
   847  			description: "enforce purpose & vendors on, legit interest Y, vendor legit interest Y",
   848  			config: purposeConfig{
   849  				EnforcePurpose: true,
   850  				EnforceVendors: true,
   851  			},
   852  			consent:                  P1P2P3PurposeLIAndV32VendorLIWithP1P2P3V32RestrictionRequireLI,
   853  			wantConsentPurposeResult: false,
   854  			wantLIPurposeResult:      true,
   855  			wantFlexPurposeResult:    true,
   856  		},
   857  		{
   858  			description: "enforce purpose & vendors on, bidder is a vendor exception",
   859  			config: purposeConfig{
   860  				EnforcePurpose:     true,
   861  				EnforceVendors:     true,
   862  				VendorExceptionMap: map[string]struct{}{appnexus: {}},
   863  			},
   864  			consent:                  NoConsentsWithP1P2P3V32RestrictionRequireLI,
   865  			wantConsentPurposeResult: true,
   866  			wantLIPurposeResult:      true,
   867  			wantFlexPurposeResult:    true,
   868  		},
   869  		{
   870  			description: "enforce purpose & vendors on, bidder is a vendor exception but overrides disallow them",
   871  			config: purposeConfig{
   872  				EnforcePurpose:     true,
   873  				EnforceVendors:     true,
   874  				VendorExceptionMap: map[string]struct{}{appnexus: {}},
   875  			},
   876  			consent:                  NoConsentsWithP1P2P3V32RestrictionRequireLI,
   877  			overrides:                Overrides{blockVendorExceptions: true},
   878  			wantConsentPurposeResult: false,
   879  			wantLIPurposeResult:      false,
   880  			wantFlexPurposeResult:    false,
   881  		},
   882  	}
   883  
   884  	for _, tt := range tests {
   885  		// convert consent string to TCF2 object
   886  		parsedConsent, err := vendorconsent.ParseString(tt.consent)
   887  		if err != nil {
   888  			t.Fatalf("Failed to parse consent %s: %s\n", tt.consent, tt.description)
   889  		}
   890  		consentMeta, ok := parsedConsent.(tcf2.ConsentMetadata)
   891  		if !ok {
   892  			t.Fatalf("Failed to convert consent %s: %s\n", tt.consent, tt.description)
   893  		}
   894  
   895  		vendor := getVendorList(t).Vendor(appnexusID)
   896  		vendorInfo := VendorInfo{vendorID: appnexusID, vendor: vendor}
   897  		enforcer := FullEnforcement{cfg: tt.config}
   898  
   899  		enforcer.cfg.PurposeID = consentconstants.Purpose(1)
   900  		consentPurposeResult := enforcer.LegalBasis(vendorInfo, appnexus, consentMeta, tt.overrides)
   901  		assert.Equal(t, tt.wantConsentPurposeResult, consentPurposeResult, tt.description+" -- GVL consent purpose")
   902  
   903  		enforcer.cfg.PurposeID = consentconstants.Purpose(2)
   904  		LIPurposeresult := enforcer.LegalBasis(vendorInfo, appnexus, consentMeta, tt.overrides)
   905  		assert.Equal(t, tt.wantLIPurposeResult, LIPurposeresult, tt.description+" -- GVL LI purpose")
   906  
   907  		enforcer.cfg.PurposeID = consentconstants.Purpose(3)
   908  		flexPurposeResult := enforcer.LegalBasis(vendorInfo, appnexus, consentMeta, tt.overrides)
   909  		assert.Equal(t, tt.wantFlexPurposeResult, flexPurposeResult, tt.description+" -- GVL flex purpose")
   910  	}
   911  }
   912  
   913  func TestLegalBasisWithoutVendor(t *testing.T) {
   914  	appnexus := string(openrtb_ext.BidderAppnexus)
   915  	P1P2P3PurposeConsent := "CPfCRQAPfCRQAAAAAAENCgCAAOAAAAAAAAAAAAAAAAAA"
   916  	tests := []struct {
   917  		name       string
   918  		config     purposeConfig
   919  		wantResult bool
   920  	}{
   921  		{
   922  			name: "enforce_purpose_&_vendors_off",
   923  			config: purposeConfig{
   924  				EnforcePurpose: false,
   925  				EnforceVendors: false,
   926  			},
   927  			wantResult: true,
   928  		},
   929  		{
   930  			name: "enforce_purpose_on,_bidder_is_a_vendor_exception",
   931  			config: purposeConfig{
   932  				EnforcePurpose:     true,
   933  				EnforceVendors:     false,
   934  				VendorExceptionMap: map[string]struct{}{appnexus: {}},
   935  			},
   936  			wantResult: true,
   937  		},
   938  		{
   939  			name: "enforce_purpose_on",
   940  			config: purposeConfig{
   941  				EnforcePurpose: true,
   942  				EnforceVendors: false,
   943  			},
   944  			wantResult: false,
   945  		},
   946  	}
   947  
   948  	for _, tt := range tests {
   949  		t.Run(tt.name, func(t *testing.T) {
   950  			// convert consent string to TCF2 object
   951  			parsedConsent, err := vendorconsent.ParseString(P1P2P3PurposeConsent)
   952  			if err != nil {
   953  				t.Fatalf("Failed to parse consent %s\n", P1P2P3PurposeConsent)
   954  			}
   955  			consentMeta, ok := parsedConsent.(tcf2.ConsentMetadata)
   956  			if !ok {
   957  				t.Fatalf("Failed to convert consent %s\n", P1P2P3PurposeConsent)
   958  			}
   959  
   960  			vendorInfo := VendorInfo{
   961  				vendorID: 32,
   962  				vendor:   nil,
   963  			}
   964  
   965  			enforcer := FullEnforcement{cfg: tt.config}
   966  			enforcer.cfg.PurposeID = consentconstants.Purpose(3)
   967  
   968  			result := enforcer.LegalBasis(vendorInfo, appnexus, consentMeta, Overrides{})
   969  			assert.Equal(t, tt.wantResult, result)
   970  		})
   971  	}
   972  }
   973  
   974  func getVendorList(t *testing.T) vendorlist.VendorList {
   975  	GVL := makeVendorList()
   976  
   977  	marshaledGVL, err := jsonutil.Marshal(GVL)
   978  	if err != nil {
   979  		t.Fatalf("Failed to marshal GVL")
   980  	}
   981  
   982  	parsedGVL, err := vendorlist2.ParseEagerly(marshaledGVL)
   983  	if err != nil {
   984  		t.Fatalf("Failed to parse vendor list data. %v", err)
   985  	}
   986  	return parsedGVL
   987  }
   988  
   989  func makeVendorList() vendorList {
   990  	return vendorList{
   991  		VendorListVersion: 2,
   992  		Vendors: map[string]*vendor{
   993  			"32": {
   994  				ID:               32,
   995  				Purposes:         []int{1},
   996  				LegIntPurposes:   []int{2},
   997  				FlexiblePurposes: []int{3},
   998  			},
   999  		},
  1000  	}
  1001  }