github.com/prebid/prebid-server@v0.275.0/gdpr/full_enforcement_test.go (about)

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