github.com/prebid/prebid-server@v0.275.0/config/config_test.go (about)

     1  package config
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"net"
     7  	"os"
     8  	"strconv"
     9  	"strings"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/prebid/go-gdpr/consentconstants"
    14  	"github.com/prebid/prebid-server/openrtb_ext"
    15  	"github.com/prebid/prebid-server/util/ptrutil"
    16  	"github.com/spf13/viper"
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  var bidderInfos = BidderInfos{
    21  	"bidder1": BidderInfo{
    22  		Endpoint:   "http://bidder1.com",
    23  		Maintainer: &MaintainerInfo{Email: "maintainer@bidder1.com"},
    24  		Capabilities: &CapabilitiesInfo{
    25  			App: &PlatformInfo{
    26  				MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner},
    27  			},
    28  		},
    29  	},
    30  	"bidder2": BidderInfo{
    31  		Endpoint:   "http://bidder2.com",
    32  		Maintainer: &MaintainerInfo{Email: "maintainer@bidder2.com"},
    33  		Capabilities: &CapabilitiesInfo{
    34  			App: &PlatformInfo{
    35  				MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner},
    36  			},
    37  		},
    38  		UserSyncURL: "http://bidder2.com/usersync",
    39  	},
    40  }
    41  
    42  func TestExternalCacheURLValidate(t *testing.T) {
    43  	testCases := []struct {
    44  		desc      string
    45  		data      ExternalCache
    46  		expErrors int
    47  	}{
    48  		{
    49  			desc:      "With http://",
    50  			data:      ExternalCache{Host: "http://www.google.com", Path: "/path/v1"},
    51  			expErrors: 1,
    52  		},
    53  		{
    54  			desc:      "Without http://",
    55  			data:      ExternalCache{Host: "www.google.com", Path: "/path/v1"},
    56  			expErrors: 0,
    57  		},
    58  		{
    59  			desc:      "No scheme but '//' prefix",
    60  			data:      ExternalCache{Host: "//www.google.com", Path: "/path/v1"},
    61  			expErrors: 1,
    62  		},
    63  		{
    64  			desc:      "// appears twice",
    65  			data:      ExternalCache{Host: "//www.google.com//", Path: "path/v1"},
    66  			expErrors: 1,
    67  		},
    68  		{
    69  			desc:      "Host has an only // value",
    70  			data:      ExternalCache{Host: "//", Path: "path/v1"},
    71  			expErrors: 1,
    72  		},
    73  		{
    74  			desc:      "only scheme host, valid path",
    75  			data:      ExternalCache{Host: "http://", Path: "/path/v1"},
    76  			expErrors: 1,
    77  		},
    78  		{
    79  			desc:      "No host, path only",
    80  			data:      ExternalCache{Host: "", Path: "path/v1"},
    81  			expErrors: 1,
    82  		},
    83  		{
    84  			desc:      "No host, nor path",
    85  			data:      ExternalCache{Host: "", Path: ""},
    86  			expErrors: 0,
    87  		},
    88  		{
    89  			desc:      "Invalid http at the end",
    90  			data:      ExternalCache{Host: "www.google.com", Path: "http://"},
    91  			expErrors: 1,
    92  		},
    93  		{
    94  			desc:      "Host has an unknown scheme",
    95  			data:      ExternalCache{Host: "unknownscheme://host", Path: "/path/v1"},
    96  			expErrors: 1,
    97  		},
    98  		{
    99  			desc:      "Wrong colon side in scheme",
   100  			data:      ExternalCache{Host: "http//:www.appnexus.com", Path: "/path/v1"},
   101  			expErrors: 1,
   102  		},
   103  		{
   104  			desc:      "Missing '/' in scheme",
   105  			data:      ExternalCache{Host: "http:/www.appnexus.com", Path: "/path/v1"},
   106  			expErrors: 1,
   107  		},
   108  		{
   109  			desc:      "host with scheme, no path",
   110  			data:      ExternalCache{Host: "http://www.appnexus.com", Path: ""},
   111  			expErrors: 1,
   112  		},
   113  		{
   114  			desc:      "scheme, no host nor path",
   115  			data:      ExternalCache{Host: "http://", Path: ""},
   116  			expErrors: 1,
   117  		},
   118  		{
   119  			desc:      "Scheme Invalid",
   120  			data:      ExternalCache{Scheme: "invalid", Host: "www.google.com", Path: "/path/v1"},
   121  			expErrors: 1,
   122  		},
   123  		{
   124  			desc:      "Scheme HTTP",
   125  			data:      ExternalCache{Scheme: "http", Host: "www.google.com", Path: "/path/v1"},
   126  			expErrors: 0,
   127  		},
   128  		{
   129  			desc:      "Scheme HTTPS",
   130  			data:      ExternalCache{Scheme: "https", Host: "www.google.com", Path: "/path/v1"},
   131  			expErrors: 0,
   132  		},
   133  		{
   134  			desc:      "Host with port",
   135  			data:      ExternalCache{Scheme: "https", Host: "localhost:2424", Path: "/path/v1"},
   136  			expErrors: 0,
   137  		},
   138  	}
   139  	for _, test := range testCases {
   140  		errs := test.data.validate([]error{})
   141  
   142  		assert.Equal(t, test.expErrors, len(errs), "Test case threw unexpected number of errors. Desc: %s errMsg = %v \n", test.desc, errs)
   143  	}
   144  }
   145  
   146  func TestDefaults(t *testing.T) {
   147  	cfg, _ := newDefaultConfig(t)
   148  
   149  	cmpInts(t, "port", 8000, cfg.Port)
   150  	cmpInts(t, "admin_port", 6060, cfg.AdminPort)
   151  	cmpInts(t, "auction_timeouts_ms.max", 0, int(cfg.AuctionTimeouts.Max))
   152  	cmpInts(t, "max_request_size", 1024*256, int(cfg.MaxRequestSize))
   153  	cmpInts(t, "host_cookie.ttl_days", 90, int(cfg.HostCookie.TTL))
   154  	cmpInts(t, "host_cookie.max_cookie_size_bytes", 0, cfg.HostCookie.MaxCookieSizeBytes)
   155  	cmpInts(t, "currency_converter.fetch_interval_seconds", 1800, cfg.CurrencyConverter.FetchIntervalSeconds)
   156  	cmpStrings(t, "currency_converter.fetch_url", "https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json", cfg.CurrencyConverter.FetchURL)
   157  	cmpBools(t, "account_required", false, cfg.AccountRequired)
   158  	cmpInts(t, "metrics.influxdb.collection_rate_seconds", 20, cfg.Metrics.Influxdb.MetricSendInterval)
   159  	cmpBools(t, "account_adapter_details", false, cfg.Metrics.Disabled.AccountAdapterDetails)
   160  	cmpBools(t, "account_debug", true, cfg.Metrics.Disabled.AccountDebug)
   161  	cmpBools(t, "account_stored_responses", true, cfg.Metrics.Disabled.AccountStoredResponses)
   162  	cmpBools(t, "adapter_connections_metrics", true, cfg.Metrics.Disabled.AdapterConnectionMetrics)
   163  	cmpBools(t, "adapter_gdpr_request_blocked", false, cfg.Metrics.Disabled.AdapterGDPRRequestBlocked)
   164  	cmpStrings(t, "certificates_file", "", cfg.PemCertsFile)
   165  	cmpBools(t, "stored_requests.filesystem.enabled", false, cfg.StoredRequests.Files.Enabled)
   166  	cmpStrings(t, "stored_requests.filesystem.directorypath", "./stored_requests/data/by_id", cfg.StoredRequests.Files.Path)
   167  	cmpBools(t, "auto_gen_source_tid", true, cfg.AutoGenSourceTID)
   168  	cmpBools(t, "generate_bid_id", false, cfg.GenerateBidID)
   169  	cmpStrings(t, "experiment.adscert.mode", "off", cfg.Experiment.AdCerts.Mode)
   170  	cmpStrings(t, "experiment.adscert.inprocess.origin", "", cfg.Experiment.AdCerts.InProcess.Origin)
   171  	cmpStrings(t, "experiment.adscert.inprocess.key", "", cfg.Experiment.AdCerts.InProcess.PrivateKey)
   172  	cmpInts(t, "experiment.adscert.inprocess.domain_check_interval_seconds", 30, cfg.Experiment.AdCerts.InProcess.DNSCheckIntervalInSeconds)
   173  	cmpInts(t, "experiment.adscert.inprocess.domain_renewal_interval_seconds", 30, cfg.Experiment.AdCerts.InProcess.DNSRenewalIntervalInSeconds)
   174  	cmpStrings(t, "experiment.adscert.remote.url", "", cfg.Experiment.AdCerts.Remote.Url)
   175  	cmpInts(t, "experiment.adscert.remote.signing_timeout_ms", 5, cfg.Experiment.AdCerts.Remote.SigningTimeoutMs)
   176  	cmpNils(t, "host_schain_node", cfg.HostSChainNode)
   177  	cmpStrings(t, "datacenter", "", cfg.DataCenter)
   178  
   179  	//Assert the price floor default values
   180  	cmpBools(t, "price_floors.enabled", false, cfg.PriceFloors.Enabled)
   181  
   182  	// Assert compression related defaults
   183  	cmpBools(t, "enable_gzip", false, cfg.EnableGzip)
   184  	cmpBools(t, "compression.request.enable_gzip", false, cfg.Compression.Request.GZIP)
   185  	cmpBools(t, "compression.response.enable_gzip", false, cfg.Compression.Response.GZIP)
   186  
   187  	cmpBools(t, "account_defaults.price_floors.enabled", false, cfg.AccountDefaults.PriceFloors.Enabled)
   188  	cmpInts(t, "account_defaults.price_floors.enforce_floors_rate", 100, cfg.AccountDefaults.PriceFloors.EnforceFloorsRate)
   189  	cmpBools(t, "account_defaults.price_floors.adjust_for_bid_adjustment", true, cfg.AccountDefaults.PriceFloors.AdjustForBidAdjustment)
   190  	cmpBools(t, "account_defaults.price_floors.enforce_deal_floors", false, cfg.AccountDefaults.PriceFloors.EnforceDealFloors)
   191  	cmpBools(t, "account_defaults.price_floors.use_dynamic_data", false, cfg.AccountDefaults.PriceFloors.UseDynamicData)
   192  	cmpInts(t, "account_defaults.price_floors.max_rules", 100, cfg.AccountDefaults.PriceFloors.MaxRule)
   193  	cmpInts(t, "account_defaults.price_floors.max_schema_dims", 3, cfg.AccountDefaults.PriceFloors.MaxSchemaDims)
   194  	cmpBools(t, "account_defaults.events_enabled", *cfg.AccountDefaults.EventsEnabled, false)
   195  	cmpNils(t, "account_defaults.events.enabled", cfg.AccountDefaults.Events.Enabled)
   196  
   197  	cmpBools(t, "hooks.enabled", false, cfg.Hooks.Enabled)
   198  	cmpStrings(t, "validations.banner_creative_max_size", "skip", cfg.Validations.BannerCreativeMaxSize)
   199  	cmpStrings(t, "validations.secure_markup", "skip", cfg.Validations.SecureMarkup)
   200  	cmpInts(t, "validations.max_creative_width", 0, int(cfg.Validations.MaxCreativeWidth))
   201  	cmpInts(t, "validations.max_creative_height", 0, int(cfg.Validations.MaxCreativeHeight))
   202  	cmpBools(t, "account_modules_metrics", false, cfg.Metrics.Disabled.AccountModulesMetrics)
   203  
   204  	cmpBools(t, "tmax_adjustments.enabled", false, cfg.TmaxAdjustments.Enabled)
   205  	cmpUnsignedInts(t, "tmax_adjustments.bidder_response_duration_min_ms", 0, cfg.TmaxAdjustments.BidderResponseDurationMin)
   206  	cmpUnsignedInts(t, "tmax_adjustments.bidder_network_latency_buffer_ms", 0, cfg.TmaxAdjustments.BidderNetworkLatencyBuffer)
   207  	cmpUnsignedInts(t, "tmax_adjustments.pbs_response_preparation_duration_ms", 0, cfg.TmaxAdjustments.PBSResponsePreparationDuration)
   208  
   209  	cmpInts(t, "account_defaults.privacy.ipv6.anon_keep_bits", 56, cfg.AccountDefaults.Privacy.IPv6Config.AnonKeepBits)
   210  	cmpInts(t, "account_defaults.privacy.ipv4.anon_keep_bits", 24, cfg.AccountDefaults.Privacy.IPv4Config.AnonKeepBits)
   211  
   212  	//Assert purpose VendorExceptionMap hash tables were built correctly
   213  	expectedTCF2 := TCF2{
   214  		Enabled: true,
   215  		Purpose1: TCF2Purpose{
   216  			Enabled:            true,
   217  			EnforceAlgo:        TCF2EnforceAlgoFull,
   218  			EnforceAlgoID:      TCF2FullEnforcement,
   219  			EnforcePurpose:     true,
   220  			EnforceVendors:     true,
   221  			VendorExceptions:   []openrtb_ext.BidderName{},
   222  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{},
   223  		},
   224  		Purpose2: TCF2Purpose{
   225  			Enabled:            true,
   226  			EnforceAlgo:        TCF2EnforceAlgoFull,
   227  			EnforceAlgoID:      TCF2FullEnforcement,
   228  			EnforcePurpose:     true,
   229  			EnforceVendors:     true,
   230  			VendorExceptions:   []openrtb_ext.BidderName{},
   231  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{},
   232  		},
   233  		Purpose3: TCF2Purpose{
   234  			Enabled:            true,
   235  			EnforceAlgo:        TCF2EnforceAlgoFull,
   236  			EnforceAlgoID:      TCF2FullEnforcement,
   237  			EnforcePurpose:     true,
   238  			EnforceVendors:     true,
   239  			VendorExceptions:   []openrtb_ext.BidderName{},
   240  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{},
   241  		},
   242  		Purpose4: TCF2Purpose{
   243  			Enabled:            true,
   244  			EnforceAlgo:        TCF2EnforceAlgoFull,
   245  			EnforceAlgoID:      TCF2FullEnforcement,
   246  			EnforcePurpose:     true,
   247  			EnforceVendors:     true,
   248  			VendorExceptions:   []openrtb_ext.BidderName{},
   249  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{},
   250  		},
   251  		Purpose5: TCF2Purpose{
   252  			Enabled:            true,
   253  			EnforceAlgo:        TCF2EnforceAlgoFull,
   254  			EnforceAlgoID:      TCF2FullEnforcement,
   255  			EnforcePurpose:     true,
   256  			EnforceVendors:     true,
   257  			VendorExceptions:   []openrtb_ext.BidderName{},
   258  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{},
   259  		},
   260  		Purpose6: TCF2Purpose{
   261  			Enabled:            true,
   262  			EnforceAlgo:        TCF2EnforceAlgoFull,
   263  			EnforceAlgoID:      TCF2FullEnforcement,
   264  			EnforcePurpose:     true,
   265  			EnforceVendors:     true,
   266  			VendorExceptions:   []openrtb_ext.BidderName{},
   267  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{},
   268  		},
   269  		Purpose7: TCF2Purpose{
   270  			Enabled:            true,
   271  			EnforceAlgo:        TCF2EnforceAlgoFull,
   272  			EnforceAlgoID:      TCF2FullEnforcement,
   273  			EnforcePurpose:     true,
   274  			EnforceVendors:     true,
   275  			VendorExceptions:   []openrtb_ext.BidderName{},
   276  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{},
   277  		},
   278  		Purpose8: TCF2Purpose{
   279  			Enabled:            true,
   280  			EnforceAlgo:        TCF2EnforceAlgoFull,
   281  			EnforceAlgoID:      TCF2FullEnforcement,
   282  			EnforcePurpose:     true,
   283  			EnforceVendors:     true,
   284  			VendorExceptions:   []openrtb_ext.BidderName{},
   285  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{},
   286  		},
   287  		Purpose9: TCF2Purpose{
   288  			Enabled:            true,
   289  			EnforceAlgo:        TCF2EnforceAlgoFull,
   290  			EnforceAlgoID:      TCF2FullEnforcement,
   291  			EnforcePurpose:     true,
   292  			EnforceVendors:     true,
   293  			VendorExceptions:   []openrtb_ext.BidderName{},
   294  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{},
   295  		},
   296  		Purpose10: TCF2Purpose{
   297  			Enabled:            true,
   298  			EnforceAlgo:        TCF2EnforceAlgoFull,
   299  			EnforceAlgoID:      TCF2FullEnforcement,
   300  			EnforcePurpose:     true,
   301  			EnforceVendors:     true,
   302  			VendorExceptions:   []openrtb_ext.BidderName{},
   303  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{},
   304  		},
   305  		SpecialFeature1: TCF2SpecialFeature{
   306  			Enforce:            true,
   307  			VendorExceptions:   []openrtb_ext.BidderName{},
   308  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{},
   309  		},
   310  		PurposeOneTreatment: TCF2PurposeOneTreatment{
   311  			Enabled:       true,
   312  			AccessAllowed: true,
   313  		},
   314  	}
   315  	expectedTCF2.PurposeConfigs = map[consentconstants.Purpose]*TCF2Purpose{
   316  		1:  &expectedTCF2.Purpose1,
   317  		2:  &expectedTCF2.Purpose2,
   318  		3:  &expectedTCF2.Purpose3,
   319  		4:  &expectedTCF2.Purpose4,
   320  		5:  &expectedTCF2.Purpose5,
   321  		6:  &expectedTCF2.Purpose6,
   322  		7:  &expectedTCF2.Purpose7,
   323  		8:  &expectedTCF2.Purpose8,
   324  		9:  &expectedTCF2.Purpose9,
   325  		10: &expectedTCF2.Purpose10,
   326  	}
   327  	assert.Equal(t, expectedTCF2, cfg.GDPR.TCF2, "gdpr.tcf2")
   328  }
   329  
   330  // When adding a new field, make sure the indentations are spaces not tabs otherwise read config may fail to parse the new field value.
   331  var fullConfig = []byte(`
   332  gdpr:
   333    host_vendor_id: 15
   334    default_value: "1"
   335    non_standard_publishers: ["pub1", "pub2"]
   336    eea_countries: ["eea1", "eea2"]
   337    tcf2:
   338      purpose1:
   339        enforce_vendors: false
   340        vendor_exceptions: ["foo1a", "foo1b"]
   341      purpose2:
   342        enabled: false
   343        enforce_algo: "full"
   344        enforce_purpose: false
   345        enforce_vendors: false
   346        vendor_exceptions: ["foo2"]
   347      purpose3:
   348        enforce_algo: "basic"
   349        enforce_vendors: false
   350        vendor_exceptions: ["foo3"]
   351      purpose4:
   352        enforce_vendors: false
   353        vendor_exceptions: ["foo4"]
   354      purpose5:
   355        enforce_vendors: false
   356        vendor_exceptions: ["foo5"]
   357      purpose6:
   358        enforce_vendors: false
   359        vendor_exceptions: ["foo6"]
   360      purpose7:
   361        enforce_vendors: false
   362        vendor_exceptions: ["foo7"]
   363      purpose8:
   364        enforce_vendors: false
   365        vendor_exceptions: ["foo8"]
   366      purpose9:
   367        enforce_vendors: false
   368        vendor_exceptions: ["foo9"]
   369      purpose10:
   370        enforce_vendors: false
   371        vendor_exceptions: ["foo10"]
   372      special_feature1:
   373        vendor_exceptions: ["fooSP1"]
   374  ccpa:
   375    enforce: true
   376  lmt:
   377    enforce: true
   378  host_cookie:
   379    cookie_name: userid
   380    family: prebid
   381    domain: cookies.prebid.org
   382    opt_out_url: http://prebid.org/optout
   383    opt_in_url: http://prebid.org/optin
   384    max_cookie_size_bytes: 32768
   385  external_url: http://prebid-server.prebid.org/
   386  host: prebid-server.prebid.org
   387  port: 1234
   388  admin_port: 5678
   389  enable_gzip: false
   390  compression:
   391      request:
   392          enable_gzip: true
   393      response:
   394          enable_gzip: false
   395  garbage_collector_threshold: 1
   396  datacenter: "1"
   397  auction_timeouts_ms:
   398    max: 123
   399    default: 50
   400  cache:
   401    scheme: http
   402    host: prebidcache.net
   403    query: uuid=%PBS_CACHE_UUID%
   404  external_cache:
   405    scheme: https
   406    host: www.externalprebidcache.net
   407    path: /endpoints/cache
   408  http_client:
   409    max_connections_per_host: 10
   410    max_idle_connections: 500
   411    max_idle_connections_per_host: 20
   412    idle_connection_timeout_seconds: 30
   413  http_client_cache:
   414    max_connections_per_host: 5
   415    max_idle_connections: 1
   416    max_idle_connections_per_host: 2
   417    idle_connection_timeout_seconds: 3
   418  currency_converter:
   419    fetch_url: https://currency.prebid.org
   420    fetch_interval_seconds: 1800
   421  recaptcha_secret: asdfasdfasdfasdf
   422  metrics:
   423    influxdb:
   424      host: upstream:8232
   425      database: metricsdb
   426      measurement: anyMeasurement
   427      username: admin
   428      password: admin1324
   429      align_timestamps: true
   430      metric_send_interval: 30
   431    disabled_metrics:
   432      account_adapter_details: true
   433      account_debug: false
   434      account_stored_responses: false
   435      adapter_connections_metrics: true
   436      adapter_gdpr_request_blocked: true
   437      account_modules_metrics: true
   438  blacklisted_apps: ["spamAppID","sketchy-app-id"]
   439  account_required: true
   440  auto_gen_source_tid: false
   441  certificates_file: /etc/ssl/cert.pem
   442  request_validation:
   443      ipv4_private_networks: ["1.1.1.0/24"]
   444      ipv6_private_networks: ["1111::/16", "2222::/16"]
   445  generate_bid_id: true
   446  host_schain_node:
   447      asi: "pbshostcompany.com"
   448      sid: "00001"
   449      rid: "BidRequest"
   450      hp: 1
   451  validations:
   452      banner_creative_max_size: "skip"
   453      secure_markup: "skip"
   454      max_creative_width: 0
   455      max_creative_height: 0
   456  experiment:
   457      adscert:
   458          mode: inprocess
   459          inprocess:
   460              origin: "http://test.com"
   461              key: "ABC123"
   462              domain_check_interval_seconds: 40
   463              domain_renewal_interval_seconds : 60
   464          remote:
   465              url: ""
   466              signing_timeout_ms: 10
   467  hooks:
   468      enabled: true
   469  price_floors:
   470      enabled: true
   471  account_defaults:
   472      events_enabled: false
   473      events:
   474          enabled: true
   475      price_floors:
   476          enabled: true
   477          enforce_floors_rate: 50
   478          adjust_for_bid_adjustment: false
   479          enforce_deal_floors: true
   480          use_dynamic_data: true
   481          max_rules: 120
   482          max_schema_dims: 5
   483      privacy:
   484          ipv6:
   485              anon_keep_bits: 50
   486          ipv4:
   487              anon_keep_bits: 20
   488  tmax_adjustments:
   489    enabled: true
   490    bidder_response_duration_min_ms: 700
   491    bidder_network_latency_buffer_ms: 100
   492    pbs_response_preparation_duration_ms: 100
   493  `)
   494  
   495  var oldStoredRequestsConfig = []byte(`
   496  stored_requests:
   497    filesystem: true
   498    directorypath: "/somepath"
   499  `)
   500  
   501  func cmpStrings(t *testing.T, key, expected, actual string) {
   502  	t.Helper()
   503  	assert.Equal(t, expected, actual, "%s: %s != %s", key, expected, actual)
   504  }
   505  
   506  func cmpInts(t *testing.T, key string, expected, actual int) {
   507  	t.Helper()
   508  	assert.Equal(t, expected, actual, "%s: %d != %d", key, expected, actual)
   509  }
   510  
   511  func cmpUnsignedInts(t *testing.T, key string, expected, actual uint) {
   512  	t.Helper()
   513  	assert.Equal(t, expected, actual, "%s: %d != %d", key, expected, actual)
   514  }
   515  
   516  func cmpInt8s(t *testing.T, key string, expected, actual *int8) {
   517  	t.Helper()
   518  	assert.Equal(t, expected, actual, "%s: %d != %d", key, expected, actual)
   519  }
   520  
   521  func cmpBools(t *testing.T, key string, expected, actual bool) {
   522  	t.Helper()
   523  	assert.Equal(t, expected, actual, "%s: %t != %t", key, expected, actual)
   524  }
   525  
   526  func cmpNils(t *testing.T, key string, a interface{}) {
   527  	t.Helper()
   528  	assert.Nilf(t, a, "%s: %t != nil", key, a)
   529  }
   530  
   531  func TestFullConfig(t *testing.T) {
   532  	int8One := int8(1)
   533  
   534  	v := viper.New()
   535  	SetupViper(v, "", bidderInfos)
   536  	v.SetConfigType("yaml")
   537  	v.ReadConfig(bytes.NewBuffer(fullConfig))
   538  	cfg, err := New(v, bidderInfos, mockNormalizeBidderName)
   539  	assert.NoError(t, err, "Setting up config should work but it doesn't")
   540  	cmpStrings(t, "cookie domain", "cookies.prebid.org", cfg.HostCookie.Domain)
   541  	cmpStrings(t, "cookie name", "userid", cfg.HostCookie.CookieName)
   542  	cmpStrings(t, "cookie family", "prebid", cfg.HostCookie.Family)
   543  	cmpStrings(t, "opt out", "http://prebid.org/optout", cfg.HostCookie.OptOutURL)
   544  	cmpStrings(t, "opt in", "http://prebid.org/optin", cfg.HostCookie.OptInURL)
   545  	cmpStrings(t, "external url", "http://prebid-server.prebid.org/", cfg.ExternalURL)
   546  	cmpStrings(t, "host", "prebid-server.prebid.org", cfg.Host)
   547  	cmpInts(t, "port", 1234, cfg.Port)
   548  	cmpInts(t, "admin_port", 5678, cfg.AdminPort)
   549  	cmpInts(t, "garbage_collector_threshold", 1, cfg.GarbageCollectorThreshold)
   550  	cmpInts(t, "auction_timeouts_ms.default", 50, int(cfg.AuctionTimeouts.Default))
   551  	cmpInts(t, "auction_timeouts_ms.max", 123, int(cfg.AuctionTimeouts.Max))
   552  	cmpStrings(t, "cache.scheme", "http", cfg.CacheURL.Scheme)
   553  	cmpStrings(t, "cache.host", "prebidcache.net", cfg.CacheURL.Host)
   554  	cmpStrings(t, "cache.query", "uuid=%PBS_CACHE_UUID%", cfg.CacheURL.Query)
   555  	cmpStrings(t, "external_cache.scheme", "https", cfg.ExtCacheURL.Scheme)
   556  	cmpStrings(t, "external_cache.host", "www.externalprebidcache.net", cfg.ExtCacheURL.Host)
   557  	cmpStrings(t, "external_cache.path", "/endpoints/cache", cfg.ExtCacheURL.Path)
   558  	cmpInts(t, "http_client.max_connections_per_host", 10, cfg.Client.MaxConnsPerHost)
   559  	cmpInts(t, "http_client.max_idle_connections", 500, cfg.Client.MaxIdleConns)
   560  	cmpInts(t, "http_client.max_idle_connections_per_host", 20, cfg.Client.MaxIdleConnsPerHost)
   561  	cmpInts(t, "http_client.idle_connection_timeout_seconds", 30, cfg.Client.IdleConnTimeout)
   562  	cmpInts(t, "http_client_cache.max_connections_per_host", 5, cfg.CacheClient.MaxConnsPerHost)
   563  	cmpInts(t, "http_client_cache.max_idle_connections", 1, cfg.CacheClient.MaxIdleConns)
   564  	cmpInts(t, "http_client_cache.max_idle_connections_per_host", 2, cfg.CacheClient.MaxIdleConnsPerHost)
   565  	cmpInts(t, "http_client_cache.idle_connection_timeout_seconds", 3, cfg.CacheClient.IdleConnTimeout)
   566  	cmpInts(t, "gdpr.host_vendor_id", 15, cfg.GDPR.HostVendorID)
   567  	cmpStrings(t, "gdpr.default_value", "1", cfg.GDPR.DefaultValue)
   568  	cmpStrings(t, "host_schain_node.asi", "pbshostcompany.com", cfg.HostSChainNode.ASI)
   569  	cmpStrings(t, "host_schain_node.sid", "00001", cfg.HostSChainNode.SID)
   570  	cmpStrings(t, "host_schain_node.rid", "BidRequest", cfg.HostSChainNode.RID)
   571  	cmpInt8s(t, "host_schain_node.hp", &int8One, cfg.HostSChainNode.HP)
   572  	cmpStrings(t, "datacenter", "1", cfg.DataCenter)
   573  	cmpStrings(t, "validations.banner_creative_max_size", "skip", cfg.Validations.BannerCreativeMaxSize)
   574  	cmpStrings(t, "validations.secure_markup", "skip", cfg.Validations.SecureMarkup)
   575  	cmpInts(t, "validations.max_creative_width", 0, int(cfg.Validations.MaxCreativeWidth))
   576  	cmpInts(t, "validations.max_creative_height", 0, int(cfg.Validations.MaxCreativeHeight))
   577  	cmpBools(t, "tmax_adjustments.enabled", true, cfg.TmaxAdjustments.Enabled)
   578  	cmpUnsignedInts(t, "tmax_adjustments.bidder_response_duration_min_ms", 700, cfg.TmaxAdjustments.BidderResponseDurationMin)
   579  	cmpUnsignedInts(t, "tmax_adjustments.bidder_network_latency_buffer_ms", 100, cfg.TmaxAdjustments.BidderNetworkLatencyBuffer)
   580  	cmpUnsignedInts(t, "tmax_adjustments.pbs_response_preparation_duration_ms", 100, cfg.TmaxAdjustments.PBSResponsePreparationDuration)
   581  
   582  	//Assert the price floor values
   583  	cmpBools(t, "price_floors.enabled", true, cfg.PriceFloors.Enabled)
   584  	cmpBools(t, "account_defaults.price_floors.enabled", true, cfg.AccountDefaults.PriceFloors.Enabled)
   585  	cmpInts(t, "account_defaults.price_floors.enforce_floors_rate", 50, cfg.AccountDefaults.PriceFloors.EnforceFloorsRate)
   586  	cmpBools(t, "account_defaults.price_floors.adjust_for_bid_adjustment", false, cfg.AccountDefaults.PriceFloors.AdjustForBidAdjustment)
   587  	cmpBools(t, "account_defaults.price_floors.enforce_deal_floors", true, cfg.AccountDefaults.PriceFloors.EnforceDealFloors)
   588  	cmpBools(t, "account_defaults.price_floors.use_dynamic_data", true, cfg.AccountDefaults.PriceFloors.UseDynamicData)
   589  	cmpInts(t, "account_defaults.price_floors.max_rules", 120, cfg.AccountDefaults.PriceFloors.MaxRule)
   590  	cmpInts(t, "account_defaults.price_floors.max_schema_dims", 5, cfg.AccountDefaults.PriceFloors.MaxSchemaDims)
   591  	cmpBools(t, "account_defaults.events_enabled", *cfg.AccountDefaults.EventsEnabled, true)
   592  	cmpNils(t, "account_defaults.events.enabled", cfg.AccountDefaults.Events.Enabled)
   593  
   594  	cmpInts(t, "account_defaults.privacy.ipv6.anon_keep_bits", 50, cfg.AccountDefaults.Privacy.IPv6Config.AnonKeepBits)
   595  	cmpInts(t, "account_defaults.privacy.ipv4.anon_keep_bits", 20, cfg.AccountDefaults.Privacy.IPv4Config.AnonKeepBits)
   596  
   597  	// Assert compression related defaults
   598  	cmpBools(t, "enable_gzip", false, cfg.EnableGzip)
   599  	cmpBools(t, "compression.request.enable_gzip", true, cfg.Compression.Request.GZIP)
   600  	cmpBools(t, "compression.response.enable_gzip", false, cfg.Compression.Response.GZIP)
   601  
   602  	//Assert the NonStandardPublishers was correctly unmarshalled
   603  	assert.Equal(t, []string{"pub1", "pub2"}, cfg.GDPR.NonStandardPublishers, "gdpr.non_standard_publishers")
   604  	assert.Equal(t, map[string]struct{}{"pub1": {}, "pub2": {}}, cfg.GDPR.NonStandardPublisherMap, "gdpr.non_standard_publishers Hash Map")
   605  
   606  	// Assert EEA Countries was correctly unmarshalled and the EEACountriesMap built correctly.
   607  	assert.Equal(t, []string{"eea1", "eea2"}, cfg.GDPR.EEACountries, "gdpr.eea_countries")
   608  	assert.Equal(t, map[string]struct{}{"eea1": {}, "eea2": {}}, cfg.GDPR.EEACountriesMap, "gdpr.eea_countries Hash Map")
   609  
   610  	cmpBools(t, "ccpa.enforce", true, cfg.CCPA.Enforce)
   611  	cmpBools(t, "lmt.enforce", true, cfg.LMT.Enforce)
   612  
   613  	//Assert the NonStandardPublishers was correctly unmarshalled
   614  	cmpStrings(t, "blacklisted_apps", "spamAppID", cfg.BlacklistedApps[0])
   615  	cmpStrings(t, "blacklisted_apps", "sketchy-app-id", cfg.BlacklistedApps[1])
   616  
   617  	//Assert the BlacklistedAppMap hash table was built correctly
   618  	for i := 0; i < len(cfg.BlacklistedApps); i++ {
   619  		cmpBools(t, "cfg.BlacklistedAppMap", true, cfg.BlacklistedAppMap[cfg.BlacklistedApps[i]])
   620  	}
   621  
   622  	//Assert purpose VendorExceptionMap hash tables were built correctly
   623  	expectedTCF2 := TCF2{
   624  		Enabled: true,
   625  		Purpose1: TCF2Purpose{
   626  			Enabled:            true, // true by default
   627  			EnforceAlgo:        TCF2EnforceAlgoFull,
   628  			EnforceAlgoID:      TCF2FullEnforcement,
   629  			EnforcePurpose:     true,
   630  			EnforceVendors:     false,
   631  			VendorExceptions:   []openrtb_ext.BidderName{openrtb_ext.BidderName("foo1a"), openrtb_ext.BidderName("foo1b")},
   632  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderName("foo1a"): {}, openrtb_ext.BidderName("foo1b"): {}},
   633  		},
   634  		Purpose2: TCF2Purpose{
   635  			Enabled:            false,
   636  			EnforceAlgo:        TCF2EnforceAlgoFull,
   637  			EnforceAlgoID:      TCF2FullEnforcement,
   638  			EnforcePurpose:     false,
   639  			EnforceVendors:     false,
   640  			VendorExceptions:   []openrtb_ext.BidderName{openrtb_ext.BidderName("foo2")},
   641  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderName("foo2"): {}},
   642  		},
   643  		Purpose3: TCF2Purpose{
   644  			Enabled:            true, // true by default
   645  			EnforceAlgo:        TCF2EnforceAlgoBasic,
   646  			EnforceAlgoID:      TCF2BasicEnforcement,
   647  			EnforcePurpose:     true,
   648  			EnforceVendors:     false,
   649  			VendorExceptions:   []openrtb_ext.BidderName{openrtb_ext.BidderName("foo3")},
   650  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderName("foo3"): {}},
   651  		},
   652  		Purpose4: TCF2Purpose{
   653  			Enabled:            true, // true by default
   654  			EnforceAlgo:        TCF2EnforceAlgoFull,
   655  			EnforceAlgoID:      TCF2FullEnforcement,
   656  			EnforcePurpose:     true,
   657  			EnforceVendors:     false,
   658  			VendorExceptions:   []openrtb_ext.BidderName{openrtb_ext.BidderName("foo4")},
   659  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderName("foo4"): {}},
   660  		},
   661  		Purpose5: TCF2Purpose{
   662  			Enabled:            true, // true by default
   663  			EnforceAlgo:        TCF2EnforceAlgoFull,
   664  			EnforceAlgoID:      TCF2FullEnforcement,
   665  			EnforcePurpose:     true,
   666  			EnforceVendors:     false,
   667  			VendorExceptions:   []openrtb_ext.BidderName{openrtb_ext.BidderName("foo5")},
   668  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderName("foo5"): {}},
   669  		},
   670  		Purpose6: TCF2Purpose{
   671  			Enabled:            true, // true by default
   672  			EnforceAlgo:        TCF2EnforceAlgoFull,
   673  			EnforceAlgoID:      TCF2FullEnforcement,
   674  			EnforcePurpose:     true,
   675  			EnforceVendors:     false,
   676  			VendorExceptions:   []openrtb_ext.BidderName{openrtb_ext.BidderName("foo6")},
   677  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderName("foo6"): {}},
   678  		},
   679  		Purpose7: TCF2Purpose{
   680  			Enabled:            true, // true by default
   681  			EnforceAlgo:        TCF2EnforceAlgoFull,
   682  			EnforceAlgoID:      TCF2FullEnforcement,
   683  			EnforcePurpose:     true,
   684  			EnforceVendors:     false,
   685  			VendorExceptions:   []openrtb_ext.BidderName{openrtb_ext.BidderName("foo7")},
   686  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderName("foo7"): {}},
   687  		},
   688  		Purpose8: TCF2Purpose{
   689  			Enabled:            true, // true by default
   690  			EnforceAlgo:        TCF2EnforceAlgoFull,
   691  			EnforceAlgoID:      TCF2FullEnforcement,
   692  			EnforcePurpose:     true,
   693  			EnforceVendors:     false,
   694  			VendorExceptions:   []openrtb_ext.BidderName{openrtb_ext.BidderName("foo8")},
   695  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderName("foo8"): {}},
   696  		},
   697  		Purpose9: TCF2Purpose{
   698  			Enabled:            true, // true by default
   699  			EnforceAlgo:        TCF2EnforceAlgoFull,
   700  			EnforceAlgoID:      TCF2FullEnforcement,
   701  			EnforcePurpose:     true,
   702  			EnforceVendors:     false,
   703  			VendorExceptions:   []openrtb_ext.BidderName{openrtb_ext.BidderName("foo9")},
   704  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderName("foo9"): {}},
   705  		},
   706  		Purpose10: TCF2Purpose{
   707  			Enabled:            true, // true by default
   708  			EnforceAlgo:        TCF2EnforceAlgoFull,
   709  			EnforceAlgoID:      TCF2FullEnforcement,
   710  			EnforcePurpose:     true,
   711  			EnforceVendors:     false,
   712  			VendorExceptions:   []openrtb_ext.BidderName{openrtb_ext.BidderName("foo10")},
   713  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderName("foo10"): {}},
   714  		},
   715  		SpecialFeature1: TCF2SpecialFeature{
   716  			Enforce:            true, // true by default
   717  			VendorExceptions:   []openrtb_ext.BidderName{openrtb_ext.BidderName("fooSP1")},
   718  			VendorExceptionMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderName("fooSP1"): {}},
   719  		},
   720  		PurposeOneTreatment: TCF2PurposeOneTreatment{
   721  			Enabled:       true, // true by default
   722  			AccessAllowed: true, // true by default
   723  		},
   724  	}
   725  	expectedTCF2.PurposeConfigs = map[consentconstants.Purpose]*TCF2Purpose{
   726  		1:  &expectedTCF2.Purpose1,
   727  		2:  &expectedTCF2.Purpose2,
   728  		3:  &expectedTCF2.Purpose3,
   729  		4:  &expectedTCF2.Purpose4,
   730  		5:  &expectedTCF2.Purpose5,
   731  		6:  &expectedTCF2.Purpose6,
   732  		7:  &expectedTCF2.Purpose7,
   733  		8:  &expectedTCF2.Purpose8,
   734  		9:  &expectedTCF2.Purpose9,
   735  		10: &expectedTCF2.Purpose10,
   736  	}
   737  	assert.Equal(t, expectedTCF2, cfg.GDPR.TCF2, "gdpr.tcf2")
   738  
   739  	cmpStrings(t, "currency_converter.fetch_url", "https://currency.prebid.org", cfg.CurrencyConverter.FetchURL)
   740  	cmpInts(t, "currency_converter.fetch_interval_seconds", 1800, cfg.CurrencyConverter.FetchIntervalSeconds)
   741  	cmpStrings(t, "recaptcha_secret", "asdfasdfasdfasdf", cfg.RecaptchaSecret)
   742  	cmpStrings(t, "metrics.influxdb.host", "upstream:8232", cfg.Metrics.Influxdb.Host)
   743  	cmpStrings(t, "metrics.influxdb.database", "metricsdb", cfg.Metrics.Influxdb.Database)
   744  	cmpStrings(t, "metrics.influxdb.measurement", "anyMeasurement", cfg.Metrics.Influxdb.Measurement)
   745  	cmpStrings(t, "metrics.influxdb.username", "admin", cfg.Metrics.Influxdb.Username)
   746  	cmpStrings(t, "metrics.influxdb.password", "admin1324", cfg.Metrics.Influxdb.Password)
   747  	cmpBools(t, "metrics.influxdb.align_timestamps", true, cfg.Metrics.Influxdb.AlignTimestamps)
   748  	cmpInts(t, "metrics.influxdb.metric_send_interval", 30, cfg.Metrics.Influxdb.MetricSendInterval)
   749  	cmpStrings(t, "", "http://prebidcache.net", cfg.CacheURL.GetBaseURL())
   750  	cmpStrings(t, "", "http://prebidcache.net/cache?uuid=a0eebc99-9c0b-4ef8-bb00-6bb9bd380a11", cfg.GetCachedAssetURL("a0eebc99-9c0b-4ef8-bb00-6bb9bd380a11"))
   751  	cmpBools(t, "account_required", true, cfg.AccountRequired)
   752  	cmpBools(t, "auto_gen_source_tid", false, cfg.AutoGenSourceTID)
   753  	cmpBools(t, "account_adapter_details", true, cfg.Metrics.Disabled.AccountAdapterDetails)
   754  	cmpBools(t, "account_debug", false, cfg.Metrics.Disabled.AccountDebug)
   755  	cmpBools(t, "account_stored_responses", false, cfg.Metrics.Disabled.AccountStoredResponses)
   756  	cmpBools(t, "adapter_connections_metrics", true, cfg.Metrics.Disabled.AdapterConnectionMetrics)
   757  	cmpBools(t, "adapter_gdpr_request_blocked", true, cfg.Metrics.Disabled.AdapterGDPRRequestBlocked)
   758  	cmpStrings(t, "certificates_file", "/etc/ssl/cert.pem", cfg.PemCertsFile)
   759  	cmpStrings(t, "request_validation.ipv4_private_networks", "1.1.1.0/24", cfg.RequestValidation.IPv4PrivateNetworks[0])
   760  	cmpStrings(t, "request_validation.ipv6_private_networks", "1111::/16", cfg.RequestValidation.IPv6PrivateNetworks[0])
   761  	cmpStrings(t, "request_validation.ipv6_private_networks", "2222::/16", cfg.RequestValidation.IPv6PrivateNetworks[1])
   762  	cmpBools(t, "generate_bid_id", true, cfg.GenerateBidID)
   763  	cmpStrings(t, "debug.override_token", "", cfg.Debug.OverrideToken)
   764  	cmpStrings(t, "experiment.adscert.mode", "inprocess", cfg.Experiment.AdCerts.Mode)
   765  	cmpStrings(t, "experiment.adscert.inprocess.origin", "http://test.com", cfg.Experiment.AdCerts.InProcess.Origin)
   766  	cmpStrings(t, "experiment.adscert.inprocess.key", "ABC123", cfg.Experiment.AdCerts.InProcess.PrivateKey)
   767  	cmpInts(t, "experiment.adscert.inprocess.domain_check_interval_seconds", 40, cfg.Experiment.AdCerts.InProcess.DNSCheckIntervalInSeconds)
   768  	cmpInts(t, "experiment.adscert.inprocess.domain_renewal_interval_seconds", 60, cfg.Experiment.AdCerts.InProcess.DNSRenewalIntervalInSeconds)
   769  	cmpStrings(t, "experiment.adscert.remote.url", "", cfg.Experiment.AdCerts.Remote.Url)
   770  	cmpInts(t, "experiment.adscert.remote.signing_timeout_ms", 10, cfg.Experiment.AdCerts.Remote.SigningTimeoutMs)
   771  	cmpBools(t, "hooks.enabled", true, cfg.Hooks.Enabled)
   772  	cmpBools(t, "account_modules_metrics", true, cfg.Metrics.Disabled.AccountModulesMetrics)
   773  }
   774  
   775  func TestValidateConfig(t *testing.T) {
   776  	cfg := Configuration{
   777  		GDPR: GDPR{
   778  			DefaultValue: "1",
   779  			TCF2: TCF2{
   780  				Purpose1:  TCF2Purpose{EnforceAlgo: TCF2EnforceAlgoBasic},
   781  				Purpose2:  TCF2Purpose{EnforceAlgo: TCF2EnforceAlgoFull},
   782  				Purpose3:  TCF2Purpose{EnforceAlgo: TCF2EnforceAlgoBasic},
   783  				Purpose4:  TCF2Purpose{EnforceAlgo: TCF2EnforceAlgoFull},
   784  				Purpose5:  TCF2Purpose{EnforceAlgo: TCF2EnforceAlgoBasic},
   785  				Purpose6:  TCF2Purpose{EnforceAlgo: TCF2EnforceAlgoFull},
   786  				Purpose7:  TCF2Purpose{EnforceAlgo: TCF2EnforceAlgoBasic},
   787  				Purpose8:  TCF2Purpose{EnforceAlgo: TCF2EnforceAlgoFull},
   788  				Purpose9:  TCF2Purpose{EnforceAlgo: TCF2EnforceAlgoBasic},
   789  				Purpose10: TCF2Purpose{EnforceAlgo: TCF2EnforceAlgoFull},
   790  			},
   791  		},
   792  		StoredRequests: StoredRequests{
   793  			Files: FileFetcherConfig{Enabled: true},
   794  			InMemoryCache: InMemoryCache{
   795  				Type: "none",
   796  			},
   797  		},
   798  		StoredVideo: StoredRequests{
   799  			Files: FileFetcherConfig{Enabled: true},
   800  			InMemoryCache: InMemoryCache{
   801  				Type: "none",
   802  			},
   803  		},
   804  		CategoryMapping: StoredRequests{
   805  			Files: FileFetcherConfig{Enabled: true},
   806  		},
   807  		Accounts: StoredRequests{
   808  			Files:         FileFetcherConfig{Enabled: true},
   809  			InMemoryCache: InMemoryCache{Type: "none"},
   810  		},
   811  	}
   812  
   813  	v := viper.New()
   814  	v.Set("gdpr.default_value", "0")
   815  
   816  	resolvedStoredRequestsConfig(&cfg)
   817  	err := cfg.validate(v)
   818  	assert.Nil(t, err, "OpenRTB filesystem config should work. %v", err)
   819  }
   820  
   821  func TestMigrateConfig(t *testing.T) {
   822  	v := viper.New()
   823  	SetupViper(v, "", bidderInfos)
   824  	v.Set("gdpr.default_value", "0")
   825  	v.SetConfigType("yaml")
   826  	v.ReadConfig(bytes.NewBuffer(oldStoredRequestsConfig))
   827  	migrateConfig(v)
   828  	cfg, err := New(v, bidderInfos, mockNormalizeBidderName)
   829  	assert.NoError(t, err, "Setting up config should work but it doesn't")
   830  	cmpBools(t, "stored_requests.filesystem.enabled", true, cfg.StoredRequests.Files.Enabled)
   831  	cmpStrings(t, "stored_requests.filesystem.path", "/somepath", cfg.StoredRequests.Files.Path)
   832  }
   833  
   834  func TestMigrateConfigFromEnv(t *testing.T) {
   835  	if oldval, ok := os.LookupEnv("PBS_STORED_REQUESTS_FILESYSTEM"); ok {
   836  		defer os.Setenv("PBS_STORED_REQUESTS_FILESYSTEM", oldval)
   837  	} else {
   838  		defer os.Unsetenv("PBS_STORED_REQUESTS_FILESYSTEM")
   839  	}
   840  
   841  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_ENDPOINT"); ok {
   842  		defer os.Setenv("PBS_ADAPTERS_BIDDER1_ENDPOINT", oldval)
   843  	} else {
   844  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_ENDPOINT")
   845  	}
   846  
   847  	os.Setenv("PBS_STORED_REQUESTS_FILESYSTEM", "true")
   848  	os.Setenv("PBS_ADAPTERS_BIDDER1_ENDPOINT", "http://bidder1_override.com")
   849  	cfg, _ := newDefaultConfig(t)
   850  	cmpBools(t, "stored_requests.filesystem.enabled", true, cfg.StoredRequests.Files.Enabled)
   851  	cmpStrings(t, "adapters.bidder1.endpoint", "http://bidder1_override.com", cfg.BidderInfos["bidder1"].Endpoint)
   852  }
   853  
   854  func TestUserSyncFromEnv(t *testing.T) {
   855  	truePtr := true
   856  
   857  	// setup env vars for testing
   858  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_URL"); ok {
   859  		defer os.Setenv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_URL", oldval)
   860  	} else {
   861  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_URL")
   862  	}
   863  
   864  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_USER_MACRO"); ok {
   865  		defer os.Setenv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_USER_MACRO", oldval)
   866  	} else {
   867  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_USER_MACRO")
   868  	}
   869  
   870  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_USERSYNC_SUPPORT_CORS"); ok {
   871  		defer os.Setenv("PBS_ADAPTERS_BIDDER1_USERSYNC_SUPPORT_CORS", oldval)
   872  	} else {
   873  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_USERSYNC_SUPPORT_CORS")
   874  	}
   875  
   876  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER2_USERSYNC_IFRAME_URL"); ok {
   877  		defer os.Setenv("PBS_ADAPTERS_BIDDER2_USERSYNC_IFRAME_URL", oldval)
   878  	} else {
   879  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER2_USERSYNC_IFRAME_URL")
   880  	}
   881  
   882  	// set new
   883  	os.Setenv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_URL", "http://some.url/sync?redirect={{.RedirectURL}}")
   884  	os.Setenv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_USER_MACRO", "[UID]")
   885  	os.Setenv("PBS_ADAPTERS_BIDDER1_USERSYNC_SUPPORT_CORS", "true")
   886  	os.Setenv("PBS_ADAPTERS_BIDDER2_USERSYNC_IFRAME_URL", "http://somedifferent.url/sync?redirect={{.RedirectURL}}")
   887  
   888  	cfg, _ := newDefaultConfig(t)
   889  
   890  	assert.Equal(t, "http://some.url/sync?redirect={{.RedirectURL}}", cfg.BidderInfos["bidder1"].Syncer.Redirect.URL)
   891  	assert.Equal(t, "[UID]", cfg.BidderInfos["bidder1"].Syncer.Redirect.UserMacro)
   892  	assert.Nil(t, cfg.BidderInfos["bidder1"].Syncer.IFrame)
   893  	assert.Equal(t, &truePtr, cfg.BidderInfos["bidder1"].Syncer.SupportCORS)
   894  
   895  	assert.Equal(t, "http://somedifferent.url/sync?redirect={{.RedirectURL}}", cfg.BidderInfos["bidder2"].Syncer.IFrame.URL)
   896  	assert.Nil(t, cfg.BidderInfos["bidder2"].Syncer.Redirect)
   897  	assert.Nil(t, cfg.BidderInfos["bidder2"].Syncer.SupportCORS)
   898  
   899  }
   900  
   901  func TestBidderInfoFromEnv(t *testing.T) {
   902  	// setup env vars for testing
   903  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_DISABLED"); ok {
   904  		defer os.Setenv("PBS_ADAPTERS_BIDDER1_DISABLED", oldval)
   905  	} else {
   906  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_DISABLED")
   907  	}
   908  
   909  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_ENDPOINT"); ok {
   910  		defer os.Setenv("PBS_ADAPTERS_BIDDER1_ENDPOINT", oldval)
   911  	} else {
   912  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_ENDPOINT")
   913  	}
   914  
   915  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_EXTRA_INFO"); ok {
   916  		defer os.Setenv("PBS_ADAPTERS_BIDDER1_EXTRA_INFO", oldval)
   917  	} else {
   918  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_EXTRA_INFO")
   919  	}
   920  
   921  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_DEBUG_ALLOW"); ok {
   922  		defer os.Setenv("PBS_ADAPTERS_BIDDER1_DEBUG_ALLOW", oldval)
   923  	} else {
   924  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_DEBUG_ALLOW")
   925  	}
   926  
   927  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_GVLVENDORID"); ok {
   928  		defer os.Setenv("PBS_ADAPTERS_BIDDER1_GVLVENDORID", oldval)
   929  	} else {
   930  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_GVLVENDORID")
   931  	}
   932  
   933  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_EXPERIMENT_ADSCERT_ENABLED"); ok {
   934  		defer os.Setenv("PBS_ADAPTERS_BIDDER1_EXPERIMENT_ADSCERT_ENABLED", oldval)
   935  	} else {
   936  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_EXPERIMENT_ADSCERT_ENABLED")
   937  	}
   938  
   939  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_XAPI_USERNAME"); ok {
   940  		defer os.Setenv("PBS_ADAPTERS_BIDDER1_XAPI_USERNAME", oldval)
   941  	} else {
   942  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_XAPI_USERNAME")
   943  	}
   944  
   945  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_URL"); ok {
   946  		defer os.Setenv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_URL", oldval)
   947  	} else {
   948  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_URL")
   949  	}
   950  	if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_OPENRTB_VERSION"); ok {
   951  		defer os.Setenv("PBS_ADAPTERS_BIDDER1_OPENRTB_VERSION", oldval)
   952  	} else {
   953  		defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_OPENRTB_VERSION")
   954  	}
   955  
   956  	// set new
   957  	os.Setenv("PBS_ADAPTERS_BIDDER1_DISABLED", "true")
   958  	os.Setenv("PBS_ADAPTERS_BIDDER1_ENDPOINT", "http://some.url/override")
   959  	os.Setenv("PBS_ADAPTERS_BIDDER1_EXTRA_INFO", `{"extrainfo": true}`)
   960  	os.Setenv("PBS_ADAPTERS_BIDDER1_DEBUG_ALLOW", "true")
   961  	os.Setenv("PBS_ADAPTERS_BIDDER1_GVLVENDORID", "42")
   962  	os.Setenv("PBS_ADAPTERS_BIDDER1_EXPERIMENT_ADSCERT_ENABLED", "true")
   963  	os.Setenv("PBS_ADAPTERS_BIDDER1_XAPI_USERNAME", "username_override")
   964  	os.Setenv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_URL", "http://some.url/sync?redirect={{.RedirectURL}}")
   965  	os.Setenv("PBS_ADAPTERS_BIDDER1_OPENRTB_VERSION", "2.6")
   966  
   967  	cfg, _ := newDefaultConfig(t)
   968  
   969  	assert.Equal(t, true, cfg.BidderInfos["bidder1"].Disabled)
   970  	assert.Equal(t, "http://some.url/override", cfg.BidderInfos["bidder1"].Endpoint)
   971  	assert.Equal(t, `{"extrainfo": true}`, cfg.BidderInfos["bidder1"].ExtraAdapterInfo)
   972  
   973  	assert.Equal(t, true, cfg.BidderInfos["bidder1"].Debug.Allow)
   974  	assert.Equal(t, uint16(42), cfg.BidderInfos["bidder1"].GVLVendorID)
   975  
   976  	assert.Equal(t, true, cfg.BidderInfos["bidder1"].Experiment.AdsCert.Enabled)
   977  	assert.Equal(t, "username_override", cfg.BidderInfos["bidder1"].XAPI.Username)
   978  
   979  	assert.Equal(t, "2.6", cfg.BidderInfos["bidder1"].OpenRTB.Version)
   980  }
   981  
   982  func TestMigrateConfigPurposeOneTreatment(t *testing.T) {
   983  	oldPurposeOneTreatmentConfig := []byte(`
   984        gdpr:
   985          tcf2:
   986            purpose_one_treatement:
   987              enabled: true
   988              access_allowed: true
   989      `)
   990  	newPurposeOneTreatmentConfig := []byte(`
   991        gdpr:
   992          tcf2:
   993            purpose_one_treatment:
   994              enabled: true
   995              access_allowed: true
   996      `)
   997  	oldAndNewPurposeOneTreatmentConfig := []byte(`
   998        gdpr:
   999          tcf2:
  1000            purpose_one_treatement:
  1001              enabled: false
  1002              access_allowed: true
  1003            purpose_one_treatment:
  1004              enabled: true
  1005              access_allowed: false
  1006      `)
  1007  
  1008  	tests := []struct {
  1009  		description                        string
  1010  		config                             []byte
  1011  		wantPurpose1TreatmentEnabled       bool
  1012  		wantPurpose1TreatmentAccessAllowed bool
  1013  	}{
  1014  		{
  1015  			description: "New config and old config not set",
  1016  			config:      []byte{},
  1017  		},
  1018  		{
  1019  			description:                        "New config not set, old config set",
  1020  			config:                             oldPurposeOneTreatmentConfig,
  1021  			wantPurpose1TreatmentEnabled:       true,
  1022  			wantPurpose1TreatmentAccessAllowed: true,
  1023  		},
  1024  		{
  1025  			description:                        "New config set, old config not set",
  1026  			config:                             newPurposeOneTreatmentConfig,
  1027  			wantPurpose1TreatmentEnabled:       true,
  1028  			wantPurpose1TreatmentAccessAllowed: true,
  1029  		},
  1030  		{
  1031  			description:                        "New config and old config set",
  1032  			config:                             oldAndNewPurposeOneTreatmentConfig,
  1033  			wantPurpose1TreatmentEnabled:       true,
  1034  			wantPurpose1TreatmentAccessAllowed: false,
  1035  		},
  1036  	}
  1037  
  1038  	for _, tt := range tests {
  1039  		v := viper.New()
  1040  		v.SetConfigType("yaml")
  1041  		v.ReadConfig(bytes.NewBuffer(tt.config))
  1042  
  1043  		migrateConfigPurposeOneTreatment(v)
  1044  
  1045  		if len(tt.config) > 0 {
  1046  			assert.Equal(t, tt.wantPurpose1TreatmentEnabled, v.Get("gdpr.tcf2.purpose_one_treatment.enabled").(bool), tt.description)
  1047  			assert.Equal(t, tt.wantPurpose1TreatmentAccessAllowed, v.Get("gdpr.tcf2.purpose_one_treatment.access_allowed").(bool), tt.description)
  1048  		} else {
  1049  			assert.Nil(t, v.Get("gdpr.tcf2.purpose_one_treatment.enabled"), tt.description)
  1050  			assert.Nil(t, v.Get("gdpr.tcf2.purpose_one_treatment.access_allowed"), tt.description)
  1051  		}
  1052  	}
  1053  }
  1054  
  1055  func TestMigrateConfigSpecialFeature1(t *testing.T) {
  1056  	oldSpecialFeature1Config := []byte(`
  1057        gdpr:
  1058          tcf2:
  1059            special_purpose1:
  1060              enabled: true
  1061              vendor_exceptions: ["appnexus"]
  1062      `)
  1063  	newSpecialFeature1Config := []byte(`
  1064        gdpr:
  1065          tcf2:
  1066            special_feature1:
  1067              enforce: true
  1068              vendor_exceptions: ["appnexus"]
  1069      `)
  1070  	oldAndNewSpecialFeature1Config := []byte(`
  1071        gdpr:
  1072          tcf2:
  1073            special_purpose1:
  1074              enabled: false
  1075              vendor_exceptions: ["appnexus"]
  1076            special_feature1:
  1077              enforce: true
  1078              vendor_exceptions: ["rubicon"]
  1079      `)
  1080  
  1081  	tests := []struct {
  1082  		description                         string
  1083  		config                              []byte
  1084  		wantSpecialFeature1Enforce          bool
  1085  		wantSpecialFeature1VendorExceptions []string
  1086  	}{
  1087  		{
  1088  			description: "New config and old config not set",
  1089  			config:      []byte{},
  1090  		},
  1091  		{
  1092  			description:                         "New config not set, old config set",
  1093  			config:                              oldSpecialFeature1Config,
  1094  			wantSpecialFeature1Enforce:          true,
  1095  			wantSpecialFeature1VendorExceptions: []string{"appnexus"},
  1096  		},
  1097  		{
  1098  			description:                         "New config set, old config not set",
  1099  			config:                              newSpecialFeature1Config,
  1100  			wantSpecialFeature1Enforce:          true,
  1101  			wantSpecialFeature1VendorExceptions: []string{"appnexus"},
  1102  		},
  1103  		{
  1104  			description:                         "New config and old config set",
  1105  			config:                              oldAndNewSpecialFeature1Config,
  1106  			wantSpecialFeature1Enforce:          true,
  1107  			wantSpecialFeature1VendorExceptions: []string{"rubicon"},
  1108  		},
  1109  	}
  1110  
  1111  	for _, tt := range tests {
  1112  		v := viper.New()
  1113  		v.SetConfigType("yaml")
  1114  		v.ReadConfig(bytes.NewBuffer(tt.config))
  1115  
  1116  		migrateConfigSpecialFeature1(v)
  1117  
  1118  		if len(tt.config) > 0 {
  1119  			assert.Equal(t, tt.wantSpecialFeature1Enforce, v.Get("gdpr.tcf2.special_feature1.enforce").(bool), tt.description)
  1120  			assert.Equal(t, tt.wantSpecialFeature1VendorExceptions, v.GetStringSlice("gdpr.tcf2.special_feature1.vendor_exceptions"), tt.description)
  1121  		} else {
  1122  			assert.Nil(t, v.Get("gdpr.tcf2.special_feature1.enforce"), tt.description)
  1123  			assert.Nil(t, v.Get("gdpr.tcf2.special_feature1.vendor_exceptions"), tt.description)
  1124  		}
  1125  
  1126  		var c Configuration
  1127  		err := v.Unmarshal(&c)
  1128  		assert.NoError(t, err, tt.description)
  1129  		assert.Equal(t, tt.wantSpecialFeature1Enforce, c.GDPR.TCF2.SpecialFeature1.Enforce, tt.description)
  1130  
  1131  		// convert expected vendor exceptions to type BidderName
  1132  		expectedVendorExceptions := make([]openrtb_ext.BidderName, 0, 0)
  1133  		for _, ve := range tt.wantSpecialFeature1VendorExceptions {
  1134  			expectedVendorExceptions = append(expectedVendorExceptions, openrtb_ext.BidderName(ve))
  1135  		}
  1136  		assert.ElementsMatch(t, expectedVendorExceptions, c.GDPR.TCF2.SpecialFeature1.VendorExceptions, tt.description)
  1137  	}
  1138  }
  1139  
  1140  func TestMigrateConfigTCF2PurposeEnabledFlags(t *testing.T) {
  1141  	trueStr := "true"
  1142  	falseStr := "false"
  1143  
  1144  	tests := []struct {
  1145  		description                 string
  1146  		config                      []byte
  1147  		wantPurpose1EnforcePurpose  string
  1148  		wantPurpose2EnforcePurpose  string
  1149  		wantPurpose3EnforcePurpose  string
  1150  		wantPurpose4EnforcePurpose  string
  1151  		wantPurpose5EnforcePurpose  string
  1152  		wantPurpose6EnforcePurpose  string
  1153  		wantPurpose7EnforcePurpose  string
  1154  		wantPurpose8EnforcePurpose  string
  1155  		wantPurpose9EnforcePurpose  string
  1156  		wantPurpose10EnforcePurpose string
  1157  		wantPurpose1Enabled         string
  1158  		wantPurpose2Enabled         string
  1159  		wantPurpose3Enabled         string
  1160  		wantPurpose4Enabled         string
  1161  		wantPurpose5Enabled         string
  1162  		wantPurpose6Enabled         string
  1163  		wantPurpose7Enabled         string
  1164  		wantPurpose8Enabled         string
  1165  		wantPurpose9Enabled         string
  1166  		wantPurpose10Enabled        string
  1167  	}{
  1168  		{
  1169  			description: "New config and old config flags not set",
  1170  			config:      []byte{},
  1171  		},
  1172  		{
  1173  			description: "New config not set, old config set - use old flags",
  1174  			config: []byte(`
  1175                gdpr:
  1176                  tcf2:
  1177                    purpose1:
  1178                      enabled: false
  1179                    purpose2:
  1180                      enabled: true
  1181                    purpose3:
  1182                      enabled: false
  1183                    purpose4:
  1184                      enabled: true
  1185                    purpose5:
  1186                      enabled: false
  1187                    purpose6:
  1188                      enabled: true
  1189                    purpose7:
  1190                      enabled: false
  1191                    purpose8:
  1192                      enabled: true
  1193                    purpose9:
  1194                      enabled: false
  1195                    purpose10:
  1196                      enabled: true
  1197              `),
  1198  			wantPurpose1EnforcePurpose:  falseStr,
  1199  			wantPurpose2EnforcePurpose:  trueStr,
  1200  			wantPurpose3EnforcePurpose:  falseStr,
  1201  			wantPurpose4EnforcePurpose:  trueStr,
  1202  			wantPurpose5EnforcePurpose:  falseStr,
  1203  			wantPurpose6EnforcePurpose:  trueStr,
  1204  			wantPurpose7EnforcePurpose:  falseStr,
  1205  			wantPurpose8EnforcePurpose:  trueStr,
  1206  			wantPurpose9EnforcePurpose:  falseStr,
  1207  			wantPurpose10EnforcePurpose: trueStr,
  1208  			wantPurpose1Enabled:         falseStr,
  1209  			wantPurpose2Enabled:         trueStr,
  1210  			wantPurpose3Enabled:         falseStr,
  1211  			wantPurpose4Enabled:         trueStr,
  1212  			wantPurpose5Enabled:         falseStr,
  1213  			wantPurpose6Enabled:         trueStr,
  1214  			wantPurpose7Enabled:         falseStr,
  1215  			wantPurpose8Enabled:         trueStr,
  1216  			wantPurpose9Enabled:         falseStr,
  1217  			wantPurpose10Enabled:        trueStr,
  1218  		},
  1219  		{
  1220  			description: "New config flags set, old config flags not set - use new flags",
  1221  			config: []byte(`
  1222                gdpr:
  1223                  tcf2:
  1224                    purpose1:
  1225                      enforce_purpose: true
  1226                    purpose2:
  1227                      enforce_purpose: false
  1228                    purpose3:
  1229                      enforce_purpose: true
  1230                    purpose4:
  1231                      enforce_purpose: false
  1232                    purpose5:
  1233                      enforce_purpose: true
  1234                    purpose6:
  1235                      enforce_purpose: false
  1236                    purpose7:
  1237                      enforce_purpose: true
  1238                    purpose8:
  1239                      enforce_purpose: false
  1240                    purpose9:
  1241                      enforce_purpose: true
  1242                    purpose10:
  1243                      enforce_purpose: false
  1244              `),
  1245  			wantPurpose1EnforcePurpose:  trueStr,
  1246  			wantPurpose2EnforcePurpose:  falseStr,
  1247  			wantPurpose3EnforcePurpose:  trueStr,
  1248  			wantPurpose4EnforcePurpose:  falseStr,
  1249  			wantPurpose5EnforcePurpose:  trueStr,
  1250  			wantPurpose6EnforcePurpose:  falseStr,
  1251  			wantPurpose7EnforcePurpose:  trueStr,
  1252  			wantPurpose8EnforcePurpose:  falseStr,
  1253  			wantPurpose9EnforcePurpose:  trueStr,
  1254  			wantPurpose10EnforcePurpose: falseStr,
  1255  			wantPurpose1Enabled:         trueStr,
  1256  			wantPurpose2Enabled:         falseStr,
  1257  			wantPurpose3Enabled:         trueStr,
  1258  			wantPurpose4Enabled:         falseStr,
  1259  			wantPurpose5Enabled:         trueStr,
  1260  			wantPurpose6Enabled:         falseStr,
  1261  			wantPurpose7Enabled:         trueStr,
  1262  			wantPurpose8Enabled:         falseStr,
  1263  			wantPurpose9Enabled:         trueStr,
  1264  			wantPurpose10Enabled:        falseStr,
  1265  		},
  1266  		{
  1267  			description: "New config flags and old config flags set - use new flags",
  1268  			config: []byte(`
  1269                gdpr:
  1270                  tcf2:
  1271                    purpose1:
  1272                      enabled: false
  1273                      enforce_purpose: true
  1274                    purpose2:
  1275                      enabled: false
  1276                      enforce_purpose: true
  1277                    purpose3:
  1278                      enabled: false
  1279                      enforce_purpose: true
  1280                    purpose4:
  1281                      enabled: false
  1282                      enforce_purpose: true
  1283                    purpose5:
  1284                      enabled: false
  1285                      enforce_purpose: true
  1286                    purpose6:
  1287                      enabled: false
  1288                      enforce_purpose: true
  1289                    purpose7:
  1290                      enabled: false
  1291                      enforce_purpose: true
  1292                    purpose8:
  1293                      enabled: false
  1294                      enforce_purpose: true
  1295                    purpose9:
  1296                      enabled: false
  1297                      enforce_purpose: true
  1298                    purpose10:
  1299                      enabled: false
  1300                      enforce_purpose: true
  1301                `),
  1302  			wantPurpose1EnforcePurpose:  trueStr,
  1303  			wantPurpose2EnforcePurpose:  trueStr,
  1304  			wantPurpose3EnforcePurpose:  trueStr,
  1305  			wantPurpose4EnforcePurpose:  trueStr,
  1306  			wantPurpose5EnforcePurpose:  trueStr,
  1307  			wantPurpose6EnforcePurpose:  trueStr,
  1308  			wantPurpose7EnforcePurpose:  trueStr,
  1309  			wantPurpose8EnforcePurpose:  trueStr,
  1310  			wantPurpose9EnforcePurpose:  trueStr,
  1311  			wantPurpose10EnforcePurpose: trueStr,
  1312  			wantPurpose1Enabled:         trueStr,
  1313  			wantPurpose2Enabled:         trueStr,
  1314  			wantPurpose3Enabled:         trueStr,
  1315  			wantPurpose4Enabled:         trueStr,
  1316  			wantPurpose5Enabled:         trueStr,
  1317  			wantPurpose6Enabled:         trueStr,
  1318  			wantPurpose7Enabled:         trueStr,
  1319  			wantPurpose8Enabled:         trueStr,
  1320  			wantPurpose9Enabled:         trueStr,
  1321  			wantPurpose10Enabled:        trueStr,
  1322  		},
  1323  	}
  1324  
  1325  	for _, tt := range tests {
  1326  		v := viper.New()
  1327  		v.SetConfigType("yaml")
  1328  		v.ReadConfig(bytes.NewBuffer(tt.config))
  1329  
  1330  		migrateConfigTCF2PurposeEnabledFlags(v)
  1331  
  1332  		if len(tt.config) > 0 {
  1333  			assert.Equal(t, tt.wantPurpose1EnforcePurpose, v.GetString("gdpr.tcf2.purpose1.enforce_purpose"), tt.description)
  1334  			assert.Equal(t, tt.wantPurpose2EnforcePurpose, v.GetString("gdpr.tcf2.purpose2.enforce_purpose"), tt.description)
  1335  			assert.Equal(t, tt.wantPurpose3EnforcePurpose, v.GetString("gdpr.tcf2.purpose3.enforce_purpose"), tt.description)
  1336  			assert.Equal(t, tt.wantPurpose4EnforcePurpose, v.GetString("gdpr.tcf2.purpose4.enforce_purpose"), tt.description)
  1337  			assert.Equal(t, tt.wantPurpose5EnforcePurpose, v.GetString("gdpr.tcf2.purpose5.enforce_purpose"), tt.description)
  1338  			assert.Equal(t, tt.wantPurpose6EnforcePurpose, v.GetString("gdpr.tcf2.purpose6.enforce_purpose"), tt.description)
  1339  			assert.Equal(t, tt.wantPurpose7EnforcePurpose, v.GetString("gdpr.tcf2.purpose7.enforce_purpose"), tt.description)
  1340  			assert.Equal(t, tt.wantPurpose8EnforcePurpose, v.GetString("gdpr.tcf2.purpose8.enforce_purpose"), tt.description)
  1341  			assert.Equal(t, tt.wantPurpose9EnforcePurpose, v.GetString("gdpr.tcf2.purpose9.enforce_purpose"), tt.description)
  1342  			assert.Equal(t, tt.wantPurpose10EnforcePurpose, v.GetString("gdpr.tcf2.purpose10.enforce_purpose"), tt.description)
  1343  			assert.Equal(t, tt.wantPurpose1Enabled, v.GetString("gdpr.tcf2.purpose1.enabled"), tt.description)
  1344  			assert.Equal(t, tt.wantPurpose2Enabled, v.GetString("gdpr.tcf2.purpose2.enabled"), tt.description)
  1345  			assert.Equal(t, tt.wantPurpose3Enabled, v.GetString("gdpr.tcf2.purpose3.enabled"), tt.description)
  1346  			assert.Equal(t, tt.wantPurpose4Enabled, v.GetString("gdpr.tcf2.purpose4.enabled"), tt.description)
  1347  			assert.Equal(t, tt.wantPurpose5Enabled, v.GetString("gdpr.tcf2.purpose5.enabled"), tt.description)
  1348  			assert.Equal(t, tt.wantPurpose6Enabled, v.GetString("gdpr.tcf2.purpose6.enabled"), tt.description)
  1349  			assert.Equal(t, tt.wantPurpose7Enabled, v.GetString("gdpr.tcf2.purpose7.enabled"), tt.description)
  1350  			assert.Equal(t, tt.wantPurpose8Enabled, v.GetString("gdpr.tcf2.purpose8.enabled"), tt.description)
  1351  			assert.Equal(t, tt.wantPurpose9Enabled, v.GetString("gdpr.tcf2.purpose9.enabled"), tt.description)
  1352  			assert.Equal(t, tt.wantPurpose10Enabled, v.GetString("gdpr.tcf2.purpose10.enabled"), tt.description)
  1353  		} else {
  1354  			assert.Nil(t, v.Get("gdpr.tcf2.purpose1.enforce_purpose"), tt.description)
  1355  			assert.Nil(t, v.Get("gdpr.tcf2.purpose2.enforce_purpose"), tt.description)
  1356  			assert.Nil(t, v.Get("gdpr.tcf2.purpose3.enforce_purpose"), tt.description)
  1357  			assert.Nil(t, v.Get("gdpr.tcf2.purpose4.enforce_purpose"), tt.description)
  1358  			assert.Nil(t, v.Get("gdpr.tcf2.purpose5.enforce_purpose"), tt.description)
  1359  			assert.Nil(t, v.Get("gdpr.tcf2.purpose6.enforce_purpose"), tt.description)
  1360  			assert.Nil(t, v.Get("gdpr.tcf2.purpose7.enforce_purpose"), tt.description)
  1361  			assert.Nil(t, v.Get("gdpr.tcf2.purpose8.enforce_purpose"), tt.description)
  1362  			assert.Nil(t, v.Get("gdpr.tcf2.purpose9.enforce_purpose"), tt.description)
  1363  			assert.Nil(t, v.Get("gdpr.tcf2.purpose10.enforce_purpose"), tt.description)
  1364  			assert.Nil(t, v.Get("gdpr.tcf2.purpose1.enabled"), tt.description)
  1365  			assert.Nil(t, v.Get("gdpr.tcf2.purpose2.enabled"), tt.description)
  1366  			assert.Nil(t, v.Get("gdpr.tcf2.purpose3.enabled"), tt.description)
  1367  			assert.Nil(t, v.Get("gdpr.tcf2.purpose4.enabled"), tt.description)
  1368  			assert.Nil(t, v.Get("gdpr.tcf2.purpose5.enabled"), tt.description)
  1369  			assert.Nil(t, v.Get("gdpr.tcf2.purpose6.enabled"), tt.description)
  1370  			assert.Nil(t, v.Get("gdpr.tcf2.purpose7.enabled"), tt.description)
  1371  			assert.Nil(t, v.Get("gdpr.tcf2.purpose8.enabled"), tt.description)
  1372  			assert.Nil(t, v.Get("gdpr.tcf2.purpose9.enabled"), tt.description)
  1373  			assert.Nil(t, v.Get("gdpr.tcf2.purpose10.enabled"), tt.description)
  1374  		}
  1375  	}
  1376  }
  1377  
  1378  func TestMigrateConfigTCF2PurposeFlags(t *testing.T) {
  1379  	tests := []struct {
  1380  		description                string
  1381  		config                     []byte
  1382  		wantPurpose1EnforceAlgo    string
  1383  		wantPurpose1EnforcePurpose bool
  1384  		wantPurpose1Enabled        bool
  1385  	}{
  1386  		{
  1387  			description: "enforce_purpose does not set enforce_algo but sets enabled",
  1388  			config: []byte(`
  1389                gdpr:
  1390                  tcf2:
  1391                    purpose1:
  1392                      enforce_algo: "off"
  1393                      enforce_purpose: "full"
  1394                      enabled: false
  1395                    purpose2:
  1396                      enforce_purpose: "full"
  1397                      enabled: false
  1398                    purpose3:
  1399                      enabled: false
  1400              `),
  1401  			wantPurpose1EnforceAlgo:    "off",
  1402  			wantPurpose1EnforcePurpose: true,
  1403  			wantPurpose1Enabled:        true,
  1404  		},
  1405  		{
  1406  			description: "enforce_purpose sets enforce_algo and enabled",
  1407  			config: []byte(`
  1408                gdpr:
  1409                  tcf2:
  1410                    purpose1:
  1411                      enforce_purpose: "full"
  1412                      enabled: false
  1413              `),
  1414  			wantPurpose1EnforceAlgo:    "full",
  1415  			wantPurpose1EnforcePurpose: true,
  1416  			wantPurpose1Enabled:        true,
  1417  		},
  1418  		{
  1419  			description: "enforce_purpose does not set enforce_algo or enabled",
  1420  			config: []byte(`
  1421                gdpr:
  1422                  tcf2:
  1423                    purpose1:
  1424                      enabled: false
  1425              `),
  1426  			wantPurpose1EnforceAlgo:    "",
  1427  			wantPurpose1EnforcePurpose: false,
  1428  			wantPurpose1Enabled:        false,
  1429  		},
  1430  	}
  1431  
  1432  	for _, tt := range tests {
  1433  		v := viper.New()
  1434  		v.SetConfigType("yaml")
  1435  		v.ReadConfig(bytes.NewBuffer(tt.config))
  1436  
  1437  		migrateConfigTCF2PurposeFlags(v)
  1438  
  1439  		assert.Equal(t, tt.wantPurpose1EnforceAlgo, v.GetString("gdpr.tcf2.purpose1.enforce_algo"), tt.description)
  1440  		assert.Equal(t, tt.wantPurpose1EnforcePurpose, v.GetBool("gdpr.tcf2.purpose1.enforce_purpose"), tt.description)
  1441  		assert.Equal(t, tt.wantPurpose1Enabled, v.GetBool("gdpr.tcf2.purpose1.enabled"), tt.description)
  1442  	}
  1443  
  1444  }
  1445  
  1446  func TestMigrateConfigTCF2EnforcePurposeFlags(t *testing.T) {
  1447  	trueStr := "true"
  1448  	falseStr := "false"
  1449  
  1450  	tests := []struct {
  1451  		description                 string
  1452  		config                      []byte
  1453  		wantEnforceAlgosSet         bool
  1454  		wantPurpose1EnforceAlgo     string
  1455  		wantPurpose2EnforceAlgo     string
  1456  		wantPurpose3EnforceAlgo     string
  1457  		wantPurpose4EnforceAlgo     string
  1458  		wantPurpose5EnforceAlgo     string
  1459  		wantPurpose6EnforceAlgo     string
  1460  		wantPurpose7EnforceAlgo     string
  1461  		wantPurpose8EnforceAlgo     string
  1462  		wantPurpose9EnforceAlgo     string
  1463  		wantPurpose10EnforceAlgo    string
  1464  		wantEnforcePurposesSet      bool
  1465  		wantPurpose1EnforcePurpose  string
  1466  		wantPurpose2EnforcePurpose  string
  1467  		wantPurpose3EnforcePurpose  string
  1468  		wantPurpose4EnforcePurpose  string
  1469  		wantPurpose5EnforcePurpose  string
  1470  		wantPurpose6EnforcePurpose  string
  1471  		wantPurpose7EnforcePurpose  string
  1472  		wantPurpose8EnforcePurpose  string
  1473  		wantPurpose9EnforcePurpose  string
  1474  		wantPurpose10EnforcePurpose string
  1475  	}{
  1476  		{
  1477  			description:            "enforce_algo and enforce_purpose are not set",
  1478  			config:                 []byte{},
  1479  			wantEnforceAlgosSet:    false,
  1480  			wantEnforcePurposesSet: false,
  1481  		},
  1482  		{
  1483  			description: "enforce_algo not set; set it based on enforce_purpose string value",
  1484  			config: []byte(`
  1485                gdpr:
  1486                  tcf2:
  1487                    purpose1:
  1488                      enforce_purpose: "full"
  1489                    purpose2:
  1490                      enforce_purpose: "no"
  1491                    purpose3:
  1492                      enforce_purpose: "full"
  1493                    purpose4:
  1494                      enforce_purpose: "no"
  1495                    purpose5:
  1496                      enforce_purpose: "full"
  1497                    purpose6:
  1498                      enforce_purpose: "no"
  1499                    purpose7:
  1500                      enforce_purpose: "full"
  1501                    purpose8:
  1502                      enforce_purpose: "no"
  1503                    purpose9:
  1504                      enforce_purpose: "full"
  1505                    purpose10:
  1506                      enforce_purpose: "no"
  1507              `),
  1508  			wantEnforceAlgosSet:         true,
  1509  			wantPurpose1EnforceAlgo:     TCF2EnforceAlgoFull,
  1510  			wantPurpose2EnforceAlgo:     TCF2EnforceAlgoFull,
  1511  			wantPurpose3EnforceAlgo:     TCF2EnforceAlgoFull,
  1512  			wantPurpose4EnforceAlgo:     TCF2EnforceAlgoFull,
  1513  			wantPurpose5EnforceAlgo:     TCF2EnforceAlgoFull,
  1514  			wantPurpose6EnforceAlgo:     TCF2EnforceAlgoFull,
  1515  			wantPurpose7EnforceAlgo:     TCF2EnforceAlgoFull,
  1516  			wantPurpose8EnforceAlgo:     TCF2EnforceAlgoFull,
  1517  			wantPurpose9EnforceAlgo:     TCF2EnforceAlgoFull,
  1518  			wantPurpose10EnforceAlgo:    TCF2EnforceAlgoFull,
  1519  			wantEnforcePurposesSet:      true,
  1520  			wantPurpose1EnforcePurpose:  trueStr,
  1521  			wantPurpose2EnforcePurpose:  falseStr,
  1522  			wantPurpose3EnforcePurpose:  trueStr,
  1523  			wantPurpose4EnforcePurpose:  falseStr,
  1524  			wantPurpose5EnforcePurpose:  trueStr,
  1525  			wantPurpose6EnforcePurpose:  falseStr,
  1526  			wantPurpose7EnforcePurpose:  trueStr,
  1527  			wantPurpose8EnforcePurpose:  falseStr,
  1528  			wantPurpose9EnforcePurpose:  trueStr,
  1529  			wantPurpose10EnforcePurpose: falseStr,
  1530  		},
  1531  		{
  1532  			description: "enforce_algo not set; don't set it based on enforce_purpose bool value",
  1533  			config: []byte(`
  1534                gdpr:
  1535                  tcf2:
  1536                    purpose1:
  1537                      enforce_purpose: true
  1538                    purpose2:
  1539                      enforce_purpose: false
  1540                    purpose3:
  1541                      enforce_purpose: true
  1542                    purpose4:
  1543                      enforce_purpose: false
  1544                    purpose5:
  1545                      enforce_purpose: true
  1546                    purpose6:
  1547                      enforce_purpose: false
  1548                    purpose7:
  1549                      enforce_purpose: true
  1550                    purpose8:
  1551                      enforce_purpose: false
  1552                    purpose9:
  1553                      enforce_purpose: true
  1554                    purpose10:
  1555                      enforce_purpose: false
  1556              `),
  1557  			wantEnforceAlgosSet:         false,
  1558  			wantEnforcePurposesSet:      true,
  1559  			wantPurpose1EnforcePurpose:  trueStr,
  1560  			wantPurpose2EnforcePurpose:  falseStr,
  1561  			wantPurpose3EnforcePurpose:  trueStr,
  1562  			wantPurpose4EnforcePurpose:  falseStr,
  1563  			wantPurpose5EnforcePurpose:  trueStr,
  1564  			wantPurpose6EnforcePurpose:  falseStr,
  1565  			wantPurpose7EnforcePurpose:  trueStr,
  1566  			wantPurpose8EnforcePurpose:  falseStr,
  1567  			wantPurpose9EnforcePurpose:  trueStr,
  1568  			wantPurpose10EnforcePurpose: falseStr,
  1569  		},
  1570  		{
  1571  			description: "enforce_algo is set and enforce_purpose is not; enforce_algo is unchanged",
  1572  			config: []byte(`
  1573                gdpr:
  1574                  tcf2:
  1575                    purpose1:
  1576                      enforce_algo: "full"
  1577                    purpose2:
  1578                      enforce_algo: "full"
  1579                    purpose3:
  1580                      enforce_algo: "full"
  1581                    purpose4:
  1582                      enforce_algo: "full"
  1583                    purpose5:
  1584                      enforce_algo: "full"
  1585                    purpose6:
  1586                      enforce_algo: "full"
  1587                    purpose7:
  1588                      enforce_algo: "full"
  1589                    purpose8:
  1590                      enforce_algo: "full"
  1591                    purpose9:
  1592                      enforce_algo: "full"
  1593                    purpose10:
  1594                      enforce_algo: "full"
  1595              `),
  1596  			wantEnforceAlgosSet:      true,
  1597  			wantPurpose1EnforceAlgo:  TCF2EnforceAlgoFull,
  1598  			wantPurpose2EnforceAlgo:  TCF2EnforceAlgoFull,
  1599  			wantPurpose3EnforceAlgo:  TCF2EnforceAlgoFull,
  1600  			wantPurpose4EnforceAlgo:  TCF2EnforceAlgoFull,
  1601  			wantPurpose5EnforceAlgo:  TCF2EnforceAlgoFull,
  1602  			wantPurpose6EnforceAlgo:  TCF2EnforceAlgoFull,
  1603  			wantPurpose7EnforceAlgo:  TCF2EnforceAlgoFull,
  1604  			wantPurpose8EnforceAlgo:  TCF2EnforceAlgoFull,
  1605  			wantPurpose9EnforceAlgo:  TCF2EnforceAlgoFull,
  1606  			wantPurpose10EnforceAlgo: TCF2EnforceAlgoFull,
  1607  			wantEnforcePurposesSet:   false,
  1608  		},
  1609  		{
  1610  			description: "enforce_algo and enforce_purpose are set; enforce_algo is unchanged",
  1611  			config: []byte(`
  1612                gdpr:
  1613                  tcf2:
  1614                    purpose1:
  1615                      enforce_algo: "full"
  1616                      enforce_purpose: "no"
  1617                    purpose2:
  1618                      enforce_algo: "full"
  1619                      enforce_purpose: "no"
  1620                    purpose3:
  1621                      enforce_algo: "full"
  1622                      enforce_purpose: "no"
  1623                    purpose4:
  1624                      enforce_algo: "full"
  1625                      enforce_purpose: "no"
  1626                    purpose5:
  1627                      enforce_algo: "full"
  1628                      enforce_purpose: "no"
  1629                    purpose6:
  1630                      enforce_algo: "full"
  1631                      enforce_purpose: "no"
  1632                    purpose7:
  1633                      enforce_algo: "full"
  1634                      enforce_purpose: "no"
  1635                    purpose8:
  1636                      enforce_algo: "full"
  1637                      enforce_purpose: "no"
  1638                    purpose9:
  1639                      enforce_algo: "full"
  1640                      enforce_purpose: "no"
  1641                    purpose10:
  1642                      enforce_algo: "full"
  1643                      enforce_purpose: "no"
  1644              `),
  1645  			wantEnforceAlgosSet:         true,
  1646  			wantPurpose1EnforceAlgo:     TCF2EnforceAlgoFull,
  1647  			wantPurpose2EnforceAlgo:     TCF2EnforceAlgoFull,
  1648  			wantPurpose3EnforceAlgo:     TCF2EnforceAlgoFull,
  1649  			wantPurpose4EnforceAlgo:     TCF2EnforceAlgoFull,
  1650  			wantPurpose5EnforceAlgo:     TCF2EnforceAlgoFull,
  1651  			wantPurpose6EnforceAlgo:     TCF2EnforceAlgoFull,
  1652  			wantPurpose7EnforceAlgo:     TCF2EnforceAlgoFull,
  1653  			wantPurpose8EnforceAlgo:     TCF2EnforceAlgoFull,
  1654  			wantPurpose9EnforceAlgo:     TCF2EnforceAlgoFull,
  1655  			wantPurpose10EnforceAlgo:    TCF2EnforceAlgoFull,
  1656  			wantEnforcePurposesSet:      true,
  1657  			wantPurpose1EnforcePurpose:  falseStr,
  1658  			wantPurpose2EnforcePurpose:  falseStr,
  1659  			wantPurpose3EnforcePurpose:  falseStr,
  1660  			wantPurpose4EnforcePurpose:  falseStr,
  1661  			wantPurpose5EnforcePurpose:  falseStr,
  1662  			wantPurpose6EnforcePurpose:  falseStr,
  1663  			wantPurpose7EnforcePurpose:  falseStr,
  1664  			wantPurpose8EnforcePurpose:  falseStr,
  1665  			wantPurpose9EnforcePurpose:  falseStr,
  1666  			wantPurpose10EnforcePurpose: falseStr,
  1667  		},
  1668  	}
  1669  
  1670  	for _, tt := range tests {
  1671  		v := viper.New()
  1672  		v.SetConfigType("yaml")
  1673  		v.ReadConfig(bytes.NewBuffer(tt.config))
  1674  
  1675  		migrateConfigTCF2EnforcePurposeFlags(v)
  1676  
  1677  		if tt.wantEnforceAlgosSet {
  1678  			assert.Equal(t, tt.wantPurpose1EnforceAlgo, v.GetString("gdpr.tcf2.purpose1.enforce_algo"), tt.description)
  1679  			assert.Equal(t, tt.wantPurpose2EnforceAlgo, v.GetString("gdpr.tcf2.purpose2.enforce_algo"), tt.description)
  1680  			assert.Equal(t, tt.wantPurpose3EnforceAlgo, v.GetString("gdpr.tcf2.purpose3.enforce_algo"), tt.description)
  1681  			assert.Equal(t, tt.wantPurpose4EnforceAlgo, v.GetString("gdpr.tcf2.purpose4.enforce_algo"), tt.description)
  1682  			assert.Equal(t, tt.wantPurpose5EnforceAlgo, v.GetString("gdpr.tcf2.purpose5.enforce_algo"), tt.description)
  1683  			assert.Equal(t, tt.wantPurpose6EnforceAlgo, v.GetString("gdpr.tcf2.purpose6.enforce_algo"), tt.description)
  1684  			assert.Equal(t, tt.wantPurpose7EnforceAlgo, v.GetString("gdpr.tcf2.purpose7.enforce_algo"), tt.description)
  1685  			assert.Equal(t, tt.wantPurpose8EnforceAlgo, v.GetString("gdpr.tcf2.purpose8.enforce_algo"), tt.description)
  1686  			assert.Equal(t, tt.wantPurpose9EnforceAlgo, v.GetString("gdpr.tcf2.purpose9.enforce_algo"), tt.description)
  1687  			assert.Equal(t, tt.wantPurpose10EnforceAlgo, v.GetString("gdpr.tcf2.purpose10.enforce_algo"), tt.description)
  1688  		} else {
  1689  			assert.Nil(t, v.Get("gdpr.tcf2.purpose1.enforce_algo"), tt.description)
  1690  			assert.Nil(t, v.Get("gdpr.tcf2.purpose2.enforce_algo"), tt.description)
  1691  			assert.Nil(t, v.Get("gdpr.tcf2.purpose3.enforce_algo"), tt.description)
  1692  			assert.Nil(t, v.Get("gdpr.tcf2.purpose4.enforce_algo"), tt.description)
  1693  			assert.Nil(t, v.Get("gdpr.tcf2.purpose5.enforce_algo"), tt.description)
  1694  			assert.Nil(t, v.Get("gdpr.tcf2.purpose6.enforce_algo"), tt.description)
  1695  			assert.Nil(t, v.Get("gdpr.tcf2.purpose7.enforce_algo"), tt.description)
  1696  			assert.Nil(t, v.Get("gdpr.tcf2.purpose8.enforce_algo"), tt.description)
  1697  			assert.Nil(t, v.Get("gdpr.tcf2.purpose9.enforce_algo"), tt.description)
  1698  			assert.Nil(t, v.Get("gdpr.tcf2.purpose10.enforce_algo"), tt.description)
  1699  		}
  1700  
  1701  		if tt.wantEnforcePurposesSet {
  1702  			assert.Equal(t, tt.wantPurpose1EnforcePurpose, v.GetString("gdpr.tcf2.purpose1.enforce_purpose"), tt.description)
  1703  			assert.Equal(t, tt.wantPurpose2EnforcePurpose, v.GetString("gdpr.tcf2.purpose2.enforce_purpose"), tt.description)
  1704  			assert.Equal(t, tt.wantPurpose3EnforcePurpose, v.GetString("gdpr.tcf2.purpose3.enforce_purpose"), tt.description)
  1705  			assert.Equal(t, tt.wantPurpose4EnforcePurpose, v.GetString("gdpr.tcf2.purpose4.enforce_purpose"), tt.description)
  1706  			assert.Equal(t, tt.wantPurpose5EnforcePurpose, v.GetString("gdpr.tcf2.purpose5.enforce_purpose"), tt.description)
  1707  			assert.Equal(t, tt.wantPurpose6EnforcePurpose, v.GetString("gdpr.tcf2.purpose6.enforce_purpose"), tt.description)
  1708  			assert.Equal(t, tt.wantPurpose7EnforcePurpose, v.GetString("gdpr.tcf2.purpose7.enforce_purpose"), tt.description)
  1709  			assert.Equal(t, tt.wantPurpose8EnforcePurpose, v.GetString("gdpr.tcf2.purpose8.enforce_purpose"), tt.description)
  1710  			assert.Equal(t, tt.wantPurpose9EnforcePurpose, v.GetString("gdpr.tcf2.purpose9.enforce_purpose"), tt.description)
  1711  			assert.Equal(t, tt.wantPurpose10EnforcePurpose, v.GetString("gdpr.tcf2.purpose10.enforce_purpose"), tt.description)
  1712  		} else {
  1713  			assert.Nil(t, v.Get("gdpr.tcf2.purpose1.enforce_purpose"), tt.description)
  1714  			assert.Nil(t, v.Get("gdpr.tcf2.purpose2.enforce_purpose"), tt.description)
  1715  			assert.Nil(t, v.Get("gdpr.tcf2.purpose3.enforce_purpose"), tt.description)
  1716  			assert.Nil(t, v.Get("gdpr.tcf2.purpose4.enforce_purpose"), tt.description)
  1717  			assert.Nil(t, v.Get("gdpr.tcf2.purpose5.enforce_purpose"), tt.description)
  1718  			assert.Nil(t, v.Get("gdpr.tcf2.purpose6.enforce_purpose"), tt.description)
  1719  			assert.Nil(t, v.Get("gdpr.tcf2.purpose7.enforce_purpose"), tt.description)
  1720  			assert.Nil(t, v.Get("gdpr.tcf2.purpose8.enforce_purpose"), tt.description)
  1721  			assert.Nil(t, v.Get("gdpr.tcf2.purpose9.enforce_purpose"), tt.description)
  1722  			assert.Nil(t, v.Get("gdpr.tcf2.purpose10.enforce_purpose"), tt.description)
  1723  		}
  1724  	}
  1725  }
  1726  
  1727  func TestMigrateConfigDatabaseConnection(t *testing.T) {
  1728  	type configs struct {
  1729  		old  []byte
  1730  		new  []byte
  1731  		both []byte
  1732  	}
  1733  
  1734  	// Stored Requests Config Migration
  1735  	storedReqestsConfigs := configs{
  1736  		old: []byte(`
  1737        stored_requests:
  1738          postgres:
  1739            connection:
  1740              dbname: "old_connection_dbname"
  1741              host: "old_connection_host"
  1742              port: 1000
  1743              user: "old_connection_user"
  1744              password: "old_connection_password"
  1745            fetcher:
  1746              query: "old_fetcher_query"
  1747              amp_query: "old_fetcher_amp_query"
  1748            initialize_caches:
  1749              timeout_ms: 1000
  1750              query: "old_initialize_caches_query"
  1751              amp_query: "old_initialize_caches_amp_query"
  1752            poll_for_updates:
  1753              refresh_rate_seconds: 1000
  1754              timeout_ms: 1000
  1755              query: "old_poll_for_updates_query"
  1756              amp_query: "old_poll_for_updates_amp_query"
  1757      `),
  1758  		new: []byte(`
  1759        stored_requests:
  1760          database:
  1761            connection:
  1762              dbname: "new_connection_dbname"
  1763              host: "new_connection_host"
  1764              port: 2000
  1765              user: "new_connection_user"
  1766              password: "new_connection_password"
  1767            fetcher:
  1768              query: "new_fetcher_query"
  1769              amp_query: "new_fetcher_amp_query"
  1770            initialize_caches:
  1771              timeout_ms: 2000
  1772              query: "new_initialize_caches_query"
  1773              amp_query: "new_initialize_caches_amp_query"
  1774            poll_for_updates:
  1775              refresh_rate_seconds: 2000
  1776              timeout_ms: 2000
  1777              query: "new_poll_for_updates_query"
  1778              amp_query: "new_poll_for_updates_amp_query"
  1779      `),
  1780  		both: []byte(`
  1781        stored_requests:
  1782          postgres:
  1783            connection:
  1784              dbname: "old_connection_dbname"
  1785              host: "old_connection_host"
  1786              port: 1000
  1787              user: "old_connection_user"
  1788              password: "old_connection_password"
  1789            fetcher:
  1790              query: "old_fetcher_query"
  1791              amp_query: "old_fetcher_amp_query"
  1792            initialize_caches:
  1793              timeout_ms: 1000
  1794              query: "old_initialize_caches_query"
  1795              amp_query: "old_initialize_caches_amp_query"
  1796            poll_for_updates:
  1797              refresh_rate_seconds: 1000
  1798              timeout_ms: 1000
  1799              query: "old_poll_for_updates_query"
  1800              amp_query: "old_poll_for_updates_amp_query"
  1801          database:
  1802            connection:
  1803              dbname: "new_connection_dbname"
  1804              host: "new_connection_host"
  1805              port: 2000
  1806              user: "new_connection_user"
  1807              password: "new_connection_password"
  1808            fetcher:
  1809              query: "new_fetcher_query"
  1810              amp_query: "new_fetcher_amp_query"
  1811            initialize_caches:
  1812              timeout_ms: 2000
  1813              query: "new_initialize_caches_query"
  1814              amp_query: "new_initialize_caches_amp_query"
  1815            poll_for_updates:
  1816              refresh_rate_seconds: 2000
  1817              timeout_ms: 2000
  1818              query: "new_poll_for_updates_query"
  1819              amp_query: "new_poll_for_updates_amp_query"
  1820      `),
  1821  	}
  1822  
  1823  	storedRequestsTests := []struct {
  1824  		description string
  1825  		config      []byte
  1826  
  1827  		want_connection_dbname                     string
  1828  		want_connection_host                       string
  1829  		want_connection_port                       int
  1830  		want_connection_user                       string
  1831  		want_connection_password                   string
  1832  		want_fetcher_query                         string
  1833  		want_fetcher_amp_query                     string
  1834  		want_initialize_caches_timeout_ms          int
  1835  		want_initialize_caches_query               string
  1836  		want_initialize_caches_amp_query           string
  1837  		want_poll_for_updates_refresh_rate_seconds int
  1838  		want_poll_for_updates_timeout_ms           int
  1839  		want_poll_for_updates_query                string
  1840  		want_poll_for_updates_amp_query            string
  1841  	}{
  1842  		{
  1843  			description: "New config and old config not set",
  1844  			config:      []byte{},
  1845  		},
  1846  		{
  1847  			description: "New config not set, old config set",
  1848  			config:      storedReqestsConfigs.old,
  1849  
  1850  			want_connection_dbname:                     "old_connection_dbname",
  1851  			want_connection_host:                       "old_connection_host",
  1852  			want_connection_port:                       1000,
  1853  			want_connection_user:                       "old_connection_user",
  1854  			want_connection_password:                   "old_connection_password",
  1855  			want_fetcher_query:                         "old_fetcher_query",
  1856  			want_fetcher_amp_query:                     "old_fetcher_amp_query",
  1857  			want_initialize_caches_timeout_ms:          1000,
  1858  			want_initialize_caches_query:               "old_initialize_caches_query",
  1859  			want_initialize_caches_amp_query:           "old_initialize_caches_amp_query",
  1860  			want_poll_for_updates_refresh_rate_seconds: 1000,
  1861  			want_poll_for_updates_timeout_ms:           1000,
  1862  			want_poll_for_updates_query:                "old_poll_for_updates_query",
  1863  			want_poll_for_updates_amp_query:            "old_poll_for_updates_amp_query",
  1864  		},
  1865  		{
  1866  			description: "New config set, old config not set",
  1867  			config:      storedReqestsConfigs.new,
  1868  
  1869  			want_connection_dbname:                     "new_connection_dbname",
  1870  			want_connection_host:                       "new_connection_host",
  1871  			want_connection_port:                       2000,
  1872  			want_connection_user:                       "new_connection_user",
  1873  			want_connection_password:                   "new_connection_password",
  1874  			want_fetcher_query:                         "new_fetcher_query",
  1875  			want_fetcher_amp_query:                     "new_fetcher_amp_query",
  1876  			want_initialize_caches_timeout_ms:          2000,
  1877  			want_initialize_caches_query:               "new_initialize_caches_query",
  1878  			want_initialize_caches_amp_query:           "new_initialize_caches_amp_query",
  1879  			want_poll_for_updates_refresh_rate_seconds: 2000,
  1880  			want_poll_for_updates_timeout_ms:           2000,
  1881  			want_poll_for_updates_query:                "new_poll_for_updates_query",
  1882  			want_poll_for_updates_amp_query:            "new_poll_for_updates_amp_query",
  1883  		},
  1884  		{
  1885  			description: "New config and old config set",
  1886  			config:      storedReqestsConfigs.both,
  1887  
  1888  			want_connection_dbname:                     "new_connection_dbname",
  1889  			want_connection_host:                       "new_connection_host",
  1890  			want_connection_port:                       2000,
  1891  			want_connection_user:                       "new_connection_user",
  1892  			want_connection_password:                   "new_connection_password",
  1893  			want_fetcher_query:                         "new_fetcher_query",
  1894  			want_fetcher_amp_query:                     "new_fetcher_amp_query",
  1895  			want_initialize_caches_timeout_ms:          2000,
  1896  			want_initialize_caches_query:               "new_initialize_caches_query",
  1897  			want_initialize_caches_amp_query:           "new_initialize_caches_amp_query",
  1898  			want_poll_for_updates_refresh_rate_seconds: 2000,
  1899  			want_poll_for_updates_timeout_ms:           2000,
  1900  			want_poll_for_updates_query:                "new_poll_for_updates_query",
  1901  			want_poll_for_updates_amp_query:            "new_poll_for_updates_amp_query",
  1902  		},
  1903  	}
  1904  
  1905  	for _, tt := range storedRequestsTests {
  1906  		v := viper.New()
  1907  		v.SetConfigType("yaml")
  1908  		v.ReadConfig(bytes.NewBuffer(tt.config))
  1909  
  1910  		migrateConfigDatabaseConnection(v)
  1911  
  1912  		if len(tt.config) > 0 {
  1913  			assert.Equal(t, tt.want_connection_dbname, v.GetString("stored_requests.database.connection.dbname"), tt.description)
  1914  			assert.Equal(t, tt.want_connection_host, v.GetString("stored_requests.database.connection.host"), tt.description)
  1915  			assert.Equal(t, tt.want_connection_port, v.GetInt("stored_requests.database.connection.port"), tt.description)
  1916  			assert.Equal(t, tt.want_connection_user, v.GetString("stored_requests.database.connection.user"), tt.description)
  1917  			assert.Equal(t, tt.want_connection_password, v.GetString("stored_requests.database.connection.password"), tt.description)
  1918  			assert.Equal(t, tt.want_fetcher_query, v.GetString("stored_requests.database.fetcher.query"), tt.description)
  1919  			assert.Equal(t, tt.want_fetcher_amp_query, v.GetString("stored_requests.database.fetcher.amp_query"), tt.description)
  1920  			assert.Equal(t, tt.want_initialize_caches_timeout_ms, v.GetInt("stored_requests.database.initialize_caches.timeout_ms"), tt.description)
  1921  			assert.Equal(t, tt.want_initialize_caches_query, v.GetString("stored_requests.database.initialize_caches.query"), tt.description)
  1922  			assert.Equal(t, tt.want_initialize_caches_amp_query, v.GetString("stored_requests.database.initialize_caches.amp_query"), tt.description)
  1923  			assert.Equal(t, tt.want_poll_for_updates_refresh_rate_seconds, v.GetInt("stored_requests.database.poll_for_updates.refresh_rate_seconds"), tt.description)
  1924  			assert.Equal(t, tt.want_poll_for_updates_timeout_ms, v.GetInt("stored_requests.database.poll_for_updates.timeout_ms"), tt.description)
  1925  			assert.Equal(t, tt.want_poll_for_updates_query, v.GetString("stored_requests.database.poll_for_updates.query"), tt.description)
  1926  			assert.Equal(t, tt.want_poll_for_updates_amp_query, v.GetString("stored_requests.database.poll_for_updates.amp_query"), tt.description)
  1927  		} else {
  1928  			assert.Nil(t, v.Get("stored_requests.database.connection.dbname"), tt.description)
  1929  			assert.Nil(t, v.Get("stored_requests.database.connection.host"), tt.description)
  1930  			assert.Nil(t, v.Get("stored_requests.database.connection.port"), tt.description)
  1931  			assert.Nil(t, v.Get("stored_requests.database.connection.user"), tt.description)
  1932  			assert.Nil(t, v.Get("stored_requests.database.connection.password"), tt.description)
  1933  			assert.Nil(t, v.Get("stored_requests.database.fetcher.query"), tt.description)
  1934  			assert.Nil(t, v.Get("stored_requests.database.fetcher.amp_query"), tt.description)
  1935  			assert.Nil(t, v.Get("stored_requests.database.initialize_caches.timeout_ms"), tt.description)
  1936  			assert.Nil(t, v.Get("stored_requests.database.initialize_caches.query"), tt.description)
  1937  			assert.Nil(t, v.Get("stored_requests.database.initialize_caches.amp_query"), tt.description)
  1938  			assert.Nil(t, v.Get("stored_requests.database.poll_for_updates.refresh_rate_seconds"), tt.description)
  1939  			assert.Nil(t, v.Get("stored_requests.database.poll_for_updates.timeout_ms"), tt.description)
  1940  			assert.Nil(t, v.Get("stored_requests.database.poll_for_updates.query"), tt.description)
  1941  			assert.Nil(t, v.Get("stored_requests.database.poll_for_updates.amp_query"), tt.description)
  1942  		}
  1943  	}
  1944  
  1945  	// Stored Video Reqs Config Migration
  1946  	storedVideoReqsConfigs := configs{
  1947  		old: []byte(`
  1948        stored_video_req:
  1949          postgres:
  1950            connection:
  1951              dbname: "old_connection_dbname"
  1952              host: "old_connection_host"
  1953              port: 1000
  1954              user: "old_connection_user"
  1955              password: "old_connection_password"
  1956            fetcher:
  1957              query: "old_fetcher_query"
  1958            initialize_caches:
  1959              timeout_ms: 1000
  1960              query: "old_initialize_caches_query"
  1961            poll_for_updates:
  1962              refresh_rate_seconds: 1000
  1963              timeout_ms: 1000
  1964              query: "old_poll_for_updates_query"
  1965      `),
  1966  		new: []byte(`
  1967        stored_video_req:
  1968          database:
  1969            connection:
  1970              dbname: "new_connection_dbname"
  1971              host: "new_connection_host"
  1972              port: 2000
  1973              user: "new_connection_user"
  1974              password: "new_connection_password"
  1975            fetcher:
  1976              query: "new_fetcher_query"
  1977            initialize_caches:
  1978              timeout_ms: 2000
  1979              query: "new_initialize_caches_query"
  1980            poll_for_updates:
  1981              refresh_rate_seconds: 2000
  1982              timeout_ms: 2000
  1983              query: "new_poll_for_updates_query"
  1984      `),
  1985  		both: []byte(`
  1986        stored_video_req:
  1987          postgres:
  1988            connection:
  1989              dbname: "old_connection_dbname"
  1990              host: "old_connection_host"
  1991              port: 1000
  1992              user: "old_connection_user"
  1993              password: "old_connection_password"
  1994            fetcher:
  1995              query: "old_fetcher_query"
  1996            initialize_caches:
  1997              timeout_ms: 1000
  1998              query: "old_initialize_caches_query"
  1999            poll_for_updates:
  2000              refresh_rate_seconds: 1000
  2001              timeout_ms: 1000
  2002              query: "old_poll_for_updates_query"
  2003          database:
  2004            connection:
  2005              dbname: "new_connection_dbname"
  2006              host: "new_connection_host"
  2007              port: 2000
  2008              user: "new_connection_user"
  2009              password: "new_connection_password"
  2010            fetcher:
  2011              query: "new_fetcher_query"
  2012            initialize_caches:
  2013              timeout_ms: 2000
  2014              query: "new_initialize_caches_query"
  2015            poll_for_updates:
  2016              refresh_rate_seconds: 2000
  2017              timeout_ms: 2000
  2018              query: "new_poll_for_updates_query"
  2019      `),
  2020  	}
  2021  
  2022  	storedVideoReqsTests := []struct {
  2023  		description string
  2024  		config      []byte
  2025  
  2026  		want_connection_dbname                     string
  2027  		want_connection_host                       string
  2028  		want_connection_port                       int
  2029  		want_connection_user                       string
  2030  		want_connection_password                   string
  2031  		want_fetcher_query                         string
  2032  		want_initialize_caches_timeout_ms          int
  2033  		want_initialize_caches_query               string
  2034  		want_poll_for_updates_refresh_rate_seconds int
  2035  		want_poll_for_updates_timeout_ms           int
  2036  		want_poll_for_updates_query                string
  2037  	}{
  2038  		{
  2039  			description: "New config and old config not set",
  2040  			config:      []byte{},
  2041  		},
  2042  		{
  2043  			description: "New config not set, old config set",
  2044  			config:      storedVideoReqsConfigs.old,
  2045  
  2046  			want_connection_dbname:                     "old_connection_dbname",
  2047  			want_connection_host:                       "old_connection_host",
  2048  			want_connection_port:                       1000,
  2049  			want_connection_user:                       "old_connection_user",
  2050  			want_connection_password:                   "old_connection_password",
  2051  			want_fetcher_query:                         "old_fetcher_query",
  2052  			want_initialize_caches_timeout_ms:          1000,
  2053  			want_initialize_caches_query:               "old_initialize_caches_query",
  2054  			want_poll_for_updates_refresh_rate_seconds: 1000,
  2055  			want_poll_for_updates_timeout_ms:           1000,
  2056  			want_poll_for_updates_query:                "old_poll_for_updates_query",
  2057  		},
  2058  		{
  2059  			description: "New config set, old config not set",
  2060  			config:      storedVideoReqsConfigs.new,
  2061  
  2062  			want_connection_dbname:                     "new_connection_dbname",
  2063  			want_connection_host:                       "new_connection_host",
  2064  			want_connection_port:                       2000,
  2065  			want_connection_user:                       "new_connection_user",
  2066  			want_connection_password:                   "new_connection_password",
  2067  			want_fetcher_query:                         "new_fetcher_query",
  2068  			want_initialize_caches_timeout_ms:          2000,
  2069  			want_initialize_caches_query:               "new_initialize_caches_query",
  2070  			want_poll_for_updates_refresh_rate_seconds: 2000,
  2071  			want_poll_for_updates_timeout_ms:           2000,
  2072  			want_poll_for_updates_query:                "new_poll_for_updates_query",
  2073  		},
  2074  		{
  2075  			description: "New config and old config set",
  2076  			config:      storedVideoReqsConfigs.both,
  2077  
  2078  			want_connection_dbname:                     "new_connection_dbname",
  2079  			want_connection_host:                       "new_connection_host",
  2080  			want_connection_port:                       2000,
  2081  			want_connection_user:                       "new_connection_user",
  2082  			want_connection_password:                   "new_connection_password",
  2083  			want_fetcher_query:                         "new_fetcher_query",
  2084  			want_initialize_caches_timeout_ms:          2000,
  2085  			want_initialize_caches_query:               "new_initialize_caches_query",
  2086  			want_poll_for_updates_refresh_rate_seconds: 2000,
  2087  			want_poll_for_updates_timeout_ms:           2000,
  2088  			want_poll_for_updates_query:                "new_poll_for_updates_query",
  2089  		},
  2090  	}
  2091  
  2092  	for _, tt := range storedVideoReqsTests {
  2093  		v := viper.New()
  2094  		v.SetConfigType("yaml")
  2095  		v.ReadConfig(bytes.NewBuffer(tt.config))
  2096  
  2097  		migrateConfigDatabaseConnection(v)
  2098  
  2099  		if len(tt.config) > 0 {
  2100  			assert.Equal(t, tt.want_connection_dbname, v.Get("stored_video_req.database.connection.dbname").(string), tt.description)
  2101  			assert.Equal(t, tt.want_connection_host, v.Get("stored_video_req.database.connection.host").(string), tt.description)
  2102  			assert.Equal(t, tt.want_connection_port, v.Get("stored_video_req.database.connection.port").(int), tt.description)
  2103  			assert.Equal(t, tt.want_connection_user, v.Get("stored_video_req.database.connection.user").(string), tt.description)
  2104  			assert.Equal(t, tt.want_connection_password, v.Get("stored_video_req.database.connection.password").(string), tt.description)
  2105  			assert.Equal(t, tt.want_fetcher_query, v.Get("stored_video_req.database.fetcher.query").(string), tt.description)
  2106  			assert.Equal(t, tt.want_initialize_caches_timeout_ms, v.Get("stored_video_req.database.initialize_caches.timeout_ms").(int), tt.description)
  2107  			assert.Equal(t, tt.want_initialize_caches_query, v.Get("stored_video_req.database.initialize_caches.query").(string), tt.description)
  2108  			assert.Equal(t, tt.want_poll_for_updates_refresh_rate_seconds, v.Get("stored_video_req.database.poll_for_updates.refresh_rate_seconds").(int), tt.description)
  2109  			assert.Equal(t, tt.want_poll_for_updates_timeout_ms, v.Get("stored_video_req.database.poll_for_updates.timeout_ms").(int), tt.description)
  2110  			assert.Equal(t, tt.want_poll_for_updates_query, v.Get("stored_video_req.database.poll_for_updates.query").(string), tt.description)
  2111  		} else {
  2112  			assert.Nil(t, v.Get("stored_video_req.database.connection.dbname"), tt.description)
  2113  			assert.Nil(t, v.Get("stored_video_req.database.connection.host"), tt.description)
  2114  			assert.Nil(t, v.Get("stored_video_req.database.connection.port"), tt.description)
  2115  			assert.Nil(t, v.Get("stored_video_req.database.connection.user"), tt.description)
  2116  			assert.Nil(t, v.Get("stored_video_req.database.connection.password"), tt.description)
  2117  			assert.Nil(t, v.Get("stored_video_req.database.fetcher.query"), tt.description)
  2118  			assert.Nil(t, v.Get("stored_video_req.database.initialize_caches.timeout_ms"), tt.description)
  2119  			assert.Nil(t, v.Get("stored_video_req.database.initialize_caches.query"), tt.description)
  2120  			assert.Nil(t, v.Get("stored_video_req.database.poll_for_updates.refresh_rate_seconds"), tt.description)
  2121  			assert.Nil(t, v.Get("stored_video_req.database.poll_for_updates.timeout_ms"), tt.description)
  2122  			assert.Nil(t, v.Get("stored_video_req.database.poll_for_updates.query"), tt.description)
  2123  		}
  2124  	}
  2125  
  2126  	// Stored Responses Config Migration
  2127  	storedResponsesConfigs := configs{
  2128  		old: []byte(`
  2129        stored_responses:
  2130          postgres:
  2131            connection:
  2132              dbname: "old_connection_dbname"
  2133              host: "old_connection_host"
  2134              port: 1000
  2135              user: "old_connection_user"
  2136              password: "old_connection_password"
  2137            fetcher:
  2138              query: "old_fetcher_query"
  2139            initialize_caches:
  2140              timeout_ms: 1000
  2141              query: "old_initialize_caches_query"
  2142            poll_for_updates:
  2143              refresh_rate_seconds: 1000
  2144              timeout_ms: 1000
  2145              query: "old_poll_for_updates_query"
  2146      `),
  2147  		new: []byte(`
  2148        stored_responses:
  2149          database:
  2150            connection:
  2151              dbname: "new_connection_dbname"
  2152              host: "new_connection_host"
  2153              port: 2000
  2154              user: "new_connection_user"
  2155              password: "new_connection_password"
  2156            fetcher:
  2157              query: "new_fetcher_query"
  2158            initialize_caches:
  2159              timeout_ms: 2000
  2160              query: "new_initialize_caches_query"
  2161            poll_for_updates:
  2162              refresh_rate_seconds: 2000
  2163              timeout_ms: 2000
  2164              query: "new_poll_for_updates_query"
  2165      `),
  2166  		both: []byte(`
  2167        stored_responses:
  2168          postgres:
  2169            connection:
  2170              dbname: "old_connection_dbname"
  2171              host: "old_connection_host"
  2172              port: 1000
  2173              user: "old_connection_user"
  2174              password: "old_connection_password"
  2175            fetcher:
  2176              query: "old_fetcher_query"
  2177            initialize_caches:
  2178              timeout_ms: 1000
  2179              query: "old_initialize_caches_query"
  2180            poll_for_updates:
  2181              refresh_rate_seconds: 1000
  2182              timeout_ms: 1000
  2183              query: "old_poll_for_updates_query"
  2184          database:
  2185            connection:
  2186              dbname: "new_connection_dbname"
  2187              host: "new_connection_host"
  2188              port: 2000
  2189              user: "new_connection_user"
  2190              password: "new_connection_password"
  2191            fetcher:
  2192              query: "new_fetcher_query"
  2193            initialize_caches:
  2194              timeout_ms: 2000
  2195              query: "new_initialize_caches_query"
  2196            poll_for_updates:
  2197              refresh_rate_seconds: 2000
  2198              timeout_ms: 2000
  2199              query: "new_poll_for_updates_query"
  2200      `),
  2201  	}
  2202  
  2203  	storedResponsesTests := []struct {
  2204  		description string
  2205  		config      []byte
  2206  
  2207  		want_connection_dbname                     string
  2208  		want_connection_host                       string
  2209  		want_connection_port                       int
  2210  		want_connection_user                       string
  2211  		want_connection_password                   string
  2212  		want_fetcher_query                         string
  2213  		want_initialize_caches_timeout_ms          int
  2214  		want_initialize_caches_query               string
  2215  		want_poll_for_updates_refresh_rate_seconds int
  2216  		want_poll_for_updates_timeout_ms           int
  2217  		want_poll_for_updates_query                string
  2218  	}{
  2219  		{
  2220  			description: "New config and old config not set",
  2221  			config:      []byte{},
  2222  		},
  2223  		{
  2224  			description: "New config not set, old config set",
  2225  			config:      storedResponsesConfigs.old,
  2226  
  2227  			want_connection_dbname:                     "old_connection_dbname",
  2228  			want_connection_host:                       "old_connection_host",
  2229  			want_connection_port:                       1000,
  2230  			want_connection_user:                       "old_connection_user",
  2231  			want_connection_password:                   "old_connection_password",
  2232  			want_fetcher_query:                         "old_fetcher_query",
  2233  			want_initialize_caches_timeout_ms:          1000,
  2234  			want_initialize_caches_query:               "old_initialize_caches_query",
  2235  			want_poll_for_updates_refresh_rate_seconds: 1000,
  2236  			want_poll_for_updates_timeout_ms:           1000,
  2237  			want_poll_for_updates_query:                "old_poll_for_updates_query",
  2238  		},
  2239  		{
  2240  			description: "New config set, old config not set",
  2241  			config:      storedResponsesConfigs.new,
  2242  
  2243  			want_connection_dbname:                     "new_connection_dbname",
  2244  			want_connection_host:                       "new_connection_host",
  2245  			want_connection_port:                       2000,
  2246  			want_connection_user:                       "new_connection_user",
  2247  			want_connection_password:                   "new_connection_password",
  2248  			want_fetcher_query:                         "new_fetcher_query",
  2249  			want_initialize_caches_timeout_ms:          2000,
  2250  			want_initialize_caches_query:               "new_initialize_caches_query",
  2251  			want_poll_for_updates_refresh_rate_seconds: 2000,
  2252  			want_poll_for_updates_timeout_ms:           2000,
  2253  			want_poll_for_updates_query:                "new_poll_for_updates_query",
  2254  		},
  2255  		{
  2256  			description: "New config and old config set",
  2257  			config:      storedResponsesConfigs.both,
  2258  
  2259  			want_connection_dbname:                     "new_connection_dbname",
  2260  			want_connection_host:                       "new_connection_host",
  2261  			want_connection_port:                       2000,
  2262  			want_connection_user:                       "new_connection_user",
  2263  			want_connection_password:                   "new_connection_password",
  2264  			want_fetcher_query:                         "new_fetcher_query",
  2265  			want_initialize_caches_timeout_ms:          2000,
  2266  			want_initialize_caches_query:               "new_initialize_caches_query",
  2267  			want_poll_for_updates_refresh_rate_seconds: 2000,
  2268  			want_poll_for_updates_timeout_ms:           2000,
  2269  			want_poll_for_updates_query:                "new_poll_for_updates_query",
  2270  		},
  2271  	}
  2272  
  2273  	for _, tt := range storedResponsesTests {
  2274  		v := viper.New()
  2275  		v.SetConfigType("yaml")
  2276  		v.ReadConfig(bytes.NewBuffer(tt.config))
  2277  
  2278  		migrateConfigDatabaseConnection(v)
  2279  
  2280  		if len(tt.config) > 0 {
  2281  			assert.Equal(t, tt.want_connection_dbname, v.Get("stored_responses.database.connection.dbname").(string), tt.description)
  2282  			assert.Equal(t, tt.want_connection_host, v.Get("stored_responses.database.connection.host").(string), tt.description)
  2283  			assert.Equal(t, tt.want_connection_port, v.Get("stored_responses.database.connection.port").(int), tt.description)
  2284  			assert.Equal(t, tt.want_connection_user, v.Get("stored_responses.database.connection.user").(string), tt.description)
  2285  			assert.Equal(t, tt.want_connection_password, v.Get("stored_responses.database.connection.password").(string), tt.description)
  2286  			assert.Equal(t, tt.want_fetcher_query, v.Get("stored_responses.database.fetcher.query").(string), tt.description)
  2287  			assert.Equal(t, tt.want_initialize_caches_timeout_ms, v.Get("stored_responses.database.initialize_caches.timeout_ms").(int), tt.description)
  2288  			assert.Equal(t, tt.want_initialize_caches_query, v.Get("stored_responses.database.initialize_caches.query").(string), tt.description)
  2289  			assert.Equal(t, tt.want_poll_for_updates_refresh_rate_seconds, v.Get("stored_responses.database.poll_for_updates.refresh_rate_seconds").(int), tt.description)
  2290  			assert.Equal(t, tt.want_poll_for_updates_timeout_ms, v.Get("stored_responses.database.poll_for_updates.timeout_ms").(int), tt.description)
  2291  			assert.Equal(t, tt.want_poll_for_updates_query, v.Get("stored_responses.database.poll_for_updates.query").(string), tt.description)
  2292  		} else {
  2293  			assert.Nil(t, v.Get("stored_responses.database.connection.dbname"), tt.description)
  2294  			assert.Nil(t, v.Get("stored_responses.database.connection.host"), tt.description)
  2295  			assert.Nil(t, v.Get("stored_responses.database.connection.port"), tt.description)
  2296  			assert.Nil(t, v.Get("stored_responses.database.connection.user"), tt.description)
  2297  			assert.Nil(t, v.Get("stored_responses.database.connection.password"), tt.description)
  2298  			assert.Nil(t, v.Get("stored_responses.database.fetcher.query"), tt.description)
  2299  			assert.Nil(t, v.Get("stored_responses.database.initialize_caches.timeout_ms"), tt.description)
  2300  			assert.Nil(t, v.Get("stored_responses.database.initialize_caches.query"), tt.description)
  2301  			assert.Nil(t, v.Get("stored_responses.database.poll_for_updates.refresh_rate_seconds"), tt.description)
  2302  			assert.Nil(t, v.Get("stored_responses.database.poll_for_updates.timeout_ms"), tt.description)
  2303  			assert.Nil(t, v.Get("stored_responses.database.poll_for_updates.query"), tt.description)
  2304  		}
  2305  	}
  2306  }
  2307  
  2308  func TestMigrateConfigDatabaseConnectionUsingEnvVars(t *testing.T) {
  2309  	tests := []struct {
  2310  		description        string
  2311  		prefix             string
  2312  		setDatabaseEnvVars bool
  2313  		setPostgresEnvVars bool
  2314  	}{
  2315  		{
  2316  			description:        "stored requests old config set",
  2317  			prefix:             "stored_requests",
  2318  			setPostgresEnvVars: true,
  2319  		},
  2320  		{
  2321  			description:        "stored requests new config set",
  2322  			prefix:             "stored_requests",
  2323  			setDatabaseEnvVars: true,
  2324  		},
  2325  		{
  2326  			description:        "stored requests old and new config set",
  2327  			prefix:             "stored_requests",
  2328  			setDatabaseEnvVars: true,
  2329  			setPostgresEnvVars: true,
  2330  		},
  2331  		{
  2332  			description:        "stored video requests old config set",
  2333  			prefix:             "stored_video_req",
  2334  			setPostgresEnvVars: true,
  2335  		},
  2336  		{
  2337  			description:        "stored video requests new config set",
  2338  			prefix:             "stored_video_req",
  2339  			setDatabaseEnvVars: true,
  2340  		},
  2341  		{
  2342  			description:        "stored video requests old and new config set",
  2343  			prefix:             "stored_video_req",
  2344  			setDatabaseEnvVars: true,
  2345  			setPostgresEnvVars: true,
  2346  		},
  2347  		{
  2348  			description:        "stored responses old config set",
  2349  			prefix:             "stored_responses",
  2350  			setPostgresEnvVars: true,
  2351  		},
  2352  		{
  2353  			description:        "stored responses new config set",
  2354  			prefix:             "stored_responses",
  2355  			setDatabaseEnvVars: true,
  2356  		},
  2357  		{
  2358  			description:        "stored responses old and new config set",
  2359  			prefix:             "stored_responses",
  2360  			setDatabaseEnvVars: true,
  2361  			setPostgresEnvVars: true,
  2362  		},
  2363  	}
  2364  
  2365  	pgValues := map[string]string{
  2366  		"CONNECTION_DBNAME":                     "pg-dbname",
  2367  		"CONNECTION_HOST":                       "pg-host",
  2368  		"CONNECTION_PORT":                       "1",
  2369  		"CONNECTION_USER":                       "pg-user",
  2370  		"CONNECTION_PASSWORD":                   "pg-password",
  2371  		"FETCHER_QUERY":                         "pg-fetcher-query",
  2372  		"FETCHER_AMP_QUERY":                     "pg-fetcher-amp-query",
  2373  		"INITIALIZE_CACHES_TIMEOUT_MS":          "2",
  2374  		"INITIALIZE_CACHES_QUERY":               "pg-init-caches-query",
  2375  		"INITIALIZE_CACHES_AMP_QUERY":           "pg-init-caches-amp-query",
  2376  		"POLL_FOR_UPDATES_REFRESH_RATE_SECONDS": "3",
  2377  		"POLL_FOR_UPDATES_TIMEOUT_MS":           "4",
  2378  		"POLL_FOR_UPDATES_QUERY":                "pg-poll-query $LAST_UPDATED",
  2379  		"POLL_FOR_UPDATES_AMP_QUERY":            "pg-poll-amp-query $LAST_UPDATED",
  2380  	}
  2381  	dbValues := map[string]string{
  2382  		"CONNECTION_DBNAME":                     "db-dbname",
  2383  		"CONNECTION_HOST":                       "db-host",
  2384  		"CONNECTION_PORT":                       "5",
  2385  		"CONNECTION_USER":                       "db-user",
  2386  		"CONNECTION_PASSWORD":                   "db-password",
  2387  		"FETCHER_QUERY":                         "db-fetcher-query",
  2388  		"FETCHER_AMP_QUERY":                     "db-fetcher-amp-query",
  2389  		"INITIALIZE_CACHES_TIMEOUT_MS":          "6",
  2390  		"INITIALIZE_CACHES_QUERY":               "db-init-caches-query",
  2391  		"INITIALIZE_CACHES_AMP_QUERY":           "db-init-caches-amp-query",
  2392  		"POLL_FOR_UPDATES_REFRESH_RATE_SECONDS": "7",
  2393  		"POLL_FOR_UPDATES_TIMEOUT_MS":           "8",
  2394  		"POLL_FOR_UPDATES_QUERY":                "db-poll-query $LAST_UPDATED",
  2395  		"POLL_FOR_UPDATES_AMP_QUERY":            "db-poll-amp-query $LAST_UPDATED",
  2396  	}
  2397  
  2398  	for _, tt := range tests {
  2399  		t.Run(tt.description, func(t *testing.T) {
  2400  			prefix := "PBS_" + strings.ToUpper(tt.prefix)
  2401  
  2402  			// validation rules require in memory cache type to not be "none"
  2403  			// given that we want to set the poll for update queries to non-empty values
  2404  			envVarName := prefix + "_IN_MEMORY_CACHE_TYPE"
  2405  			if oldval, ok := os.LookupEnv(envVarName); ok {
  2406  				defer os.Setenv(envVarName, oldval)
  2407  			} else {
  2408  				defer os.Unsetenv(envVarName)
  2409  			}
  2410  			os.Setenv(envVarName, "unbounded")
  2411  
  2412  			if tt.setPostgresEnvVars {
  2413  				for suffix, v := range pgValues {
  2414  					envVarName := prefix + "_POSTGRES_" + suffix
  2415  					if oldval, ok := os.LookupEnv(envVarName); ok {
  2416  						defer os.Setenv(envVarName, oldval)
  2417  					} else {
  2418  						defer os.Unsetenv(envVarName)
  2419  					}
  2420  					os.Setenv(envVarName, v)
  2421  				}
  2422  			}
  2423  			if tt.setDatabaseEnvVars {
  2424  				for suffix, v := range dbValues {
  2425  					envVarName := prefix + "_DATABASE_" + suffix
  2426  					if oldval, ok := os.LookupEnv(envVarName); ok {
  2427  						defer os.Setenv(envVarName, oldval)
  2428  					} else {
  2429  						defer os.Unsetenv(envVarName)
  2430  					}
  2431  					os.Setenv(envVarName, v)
  2432  				}
  2433  			}
  2434  
  2435  			c, _ := newDefaultConfig(t)
  2436  
  2437  			expectedDatabaseValues := map[string]string{}
  2438  			if tt.setDatabaseEnvVars {
  2439  				expectedDatabaseValues = dbValues
  2440  			} else if tt.setPostgresEnvVars {
  2441  				expectedDatabaseValues = pgValues
  2442  			}
  2443  
  2444  			if tt.prefix == "stored_requests" {
  2445  				assert.Equal(t, expectedDatabaseValues["CONNECTION_DBNAME"], c.StoredRequests.Database.ConnectionInfo.Database, tt.description)
  2446  				assert.Equal(t, expectedDatabaseValues["CONNECTION_HOST"], c.StoredRequests.Database.ConnectionInfo.Host, tt.description)
  2447  				assert.Equal(t, expectedDatabaseValues["CONNECTION_PORT"], strconv.Itoa(c.StoredRequests.Database.ConnectionInfo.Port), tt.description)
  2448  				assert.Equal(t, expectedDatabaseValues["CONNECTION_USER"], c.StoredRequests.Database.ConnectionInfo.Username, tt.description)
  2449  				assert.Equal(t, expectedDatabaseValues["CONNECTION_PASSWORD"], c.StoredRequests.Database.ConnectionInfo.Password, tt.description)
  2450  				assert.Equal(t, expectedDatabaseValues["FETCHER_QUERY"], c.StoredRequests.Database.FetcherQueries.QueryTemplate, tt.description)
  2451  				assert.Equal(t, expectedDatabaseValues["INITIALIZE_CACHES_TIMEOUT_MS"], strconv.Itoa(c.StoredRequests.Database.CacheInitialization.Timeout), tt.description)
  2452  				assert.Equal(t, expectedDatabaseValues["INITIALIZE_CACHES_QUERY"], c.StoredRequests.Database.CacheInitialization.Query, tt.description)
  2453  				assert.Equal(t, expectedDatabaseValues["POLL_FOR_UPDATES_REFRESH_RATE_SECONDS"], strconv.Itoa(c.StoredRequests.Database.PollUpdates.RefreshRate), tt.description)
  2454  				assert.Equal(t, expectedDatabaseValues["POLL_FOR_UPDATES_TIMEOUT_MS"], strconv.Itoa(c.StoredRequests.Database.PollUpdates.Timeout), tt.description)
  2455  				assert.Equal(t, expectedDatabaseValues["POLL_FOR_UPDATES_QUERY"], c.StoredRequests.Database.PollUpdates.Query, tt.description)
  2456  				// AMP queries are only migrated for stored requests
  2457  				assert.Equal(t, expectedDatabaseValues["FETCHER_AMP_QUERY"], c.StoredRequests.Database.FetcherQueries.AmpQueryTemplate, tt.description)
  2458  				assert.Equal(t, expectedDatabaseValues["INITIALIZE_CACHES_AMP_QUERY"], c.StoredRequests.Database.CacheInitialization.AmpQuery, tt.description)
  2459  				assert.Equal(t, expectedDatabaseValues["POLL_FOR_UPDATES_AMP_QUERY"], c.StoredRequests.Database.PollUpdates.AmpQuery, tt.description)
  2460  			} else if tt.prefix == "stored_video_req" {
  2461  				assert.Equal(t, expectedDatabaseValues["CONNECTION_DBNAME"], c.StoredVideo.Database.ConnectionInfo.Database, tt.description)
  2462  				assert.Equal(t, expectedDatabaseValues["CONNECTION_HOST"], c.StoredVideo.Database.ConnectionInfo.Host, tt.description)
  2463  				assert.Equal(t, expectedDatabaseValues["CONNECTION_PORT"], strconv.Itoa(c.StoredVideo.Database.ConnectionInfo.Port), tt.description)
  2464  				assert.Equal(t, expectedDatabaseValues["CONNECTION_USER"], c.StoredVideo.Database.ConnectionInfo.Username, tt.description)
  2465  				assert.Equal(t, expectedDatabaseValues["CONNECTION_PASSWORD"], c.StoredVideo.Database.ConnectionInfo.Password, tt.description)
  2466  				assert.Equal(t, expectedDatabaseValues["FETCHER_QUERY"], c.StoredVideo.Database.FetcherQueries.QueryTemplate, tt.description)
  2467  				assert.Equal(t, expectedDatabaseValues["INITIALIZE_CACHES_TIMEOUT_MS"], strconv.Itoa(c.StoredVideo.Database.CacheInitialization.Timeout), tt.description)
  2468  				assert.Equal(t, expectedDatabaseValues["INITIALIZE_CACHES_QUERY"], c.StoredVideo.Database.CacheInitialization.Query, tt.description)
  2469  				assert.Equal(t, expectedDatabaseValues["POLL_FOR_UPDATES_REFRESH_RATE_SECONDS"], strconv.Itoa(c.StoredVideo.Database.PollUpdates.RefreshRate), tt.description)
  2470  				assert.Equal(t, expectedDatabaseValues["POLL_FOR_UPDATES_TIMEOUT_MS"], strconv.Itoa(c.StoredVideo.Database.PollUpdates.Timeout), tt.description)
  2471  				assert.Equal(t, expectedDatabaseValues["POLL_FOR_UPDATES_QUERY"], c.StoredVideo.Database.PollUpdates.Query, tt.description)
  2472  				assert.Empty(t, c.StoredVideo.Database.FetcherQueries.AmpQueryTemplate, tt.description)
  2473  				assert.Empty(t, c.StoredVideo.Database.CacheInitialization.AmpQuery, tt.description)
  2474  				assert.Empty(t, c.StoredVideo.Database.PollUpdates.AmpQuery, tt.description)
  2475  			} else {
  2476  				assert.Equal(t, expectedDatabaseValues["CONNECTION_DBNAME"], c.StoredResponses.Database.ConnectionInfo.Database, tt.description)
  2477  				assert.Equal(t, expectedDatabaseValues["CONNECTION_HOST"], c.StoredResponses.Database.ConnectionInfo.Host, tt.description)
  2478  				assert.Equal(t, expectedDatabaseValues["CONNECTION_PORT"], strconv.Itoa(c.StoredResponses.Database.ConnectionInfo.Port), tt.description)
  2479  				assert.Equal(t, expectedDatabaseValues["CONNECTION_USER"], c.StoredResponses.Database.ConnectionInfo.Username, tt.description)
  2480  				assert.Equal(t, expectedDatabaseValues["CONNECTION_PASSWORD"], c.StoredResponses.Database.ConnectionInfo.Password, tt.description)
  2481  				assert.Equal(t, expectedDatabaseValues["FETCHER_QUERY"], c.StoredResponses.Database.FetcherQueries.QueryTemplate, tt.description)
  2482  				assert.Equal(t, expectedDatabaseValues["INITIALIZE_CACHES_TIMEOUT_MS"], strconv.Itoa(c.StoredResponses.Database.CacheInitialization.Timeout), tt.description)
  2483  				assert.Equal(t, expectedDatabaseValues["INITIALIZE_CACHES_QUERY"], c.StoredResponses.Database.CacheInitialization.Query, tt.description)
  2484  				assert.Equal(t, expectedDatabaseValues["POLL_FOR_UPDATES_REFRESH_RATE_SECONDS"], strconv.Itoa(c.StoredResponses.Database.PollUpdates.RefreshRate), tt.description)
  2485  				assert.Equal(t, expectedDatabaseValues["POLL_FOR_UPDATES_TIMEOUT_MS"], strconv.Itoa(c.StoredResponses.Database.PollUpdates.Timeout), tt.description)
  2486  				assert.Equal(t, expectedDatabaseValues["POLL_FOR_UPDATES_QUERY"], c.StoredResponses.Database.PollUpdates.Query, tt.description)
  2487  				assert.Empty(t, c.StoredResponses.Database.FetcherQueries.AmpQueryTemplate, tt.description)
  2488  				assert.Empty(t, c.StoredResponses.Database.CacheInitialization.AmpQuery, tt.description)
  2489  				assert.Empty(t, c.StoredResponses.Database.PollUpdates.AmpQuery, tt.description)
  2490  			}
  2491  		})
  2492  	}
  2493  }
  2494  
  2495  func TestMigrateConfigDatabaseQueryParams(t *testing.T) {
  2496  
  2497  	config := []byte(`
  2498      stored_requests:
  2499        postgres:
  2500          fetcher:
  2501            query:
  2502              SELECT * FROM Table1 WHERE id in (%REQUEST_ID_LIST%)
  2503              UNION ALL
  2504              SELECT * FROM Table2 WHERE id in (%IMP_ID_LIST%)
  2505              UNION ALL
  2506              SELECT * FROM Table3 WHERE id in (%ID_LIST%)
  2507            amp_query:
  2508              SELECT * FROM Table1 WHERE id in (%REQUEST_ID_LIST%)
  2509              UNION ALL
  2510              SELECT * FROM Table2 WHERE id in (%IMP_ID_LIST%)
  2511              UNION ALL
  2512              SELECT * FROM Table3 WHERE id in (%ID_LIST%)
  2513          poll_for_updates:
  2514            query: "SELECT * FROM Table1 WHERE last_updated > $1 UNION ALL SELECT * FROM Table2 WHERE last_updated > $1"
  2515            amp_query: "SELECT * FROM Table1 WHERE last_updated > $1 UNION ALL SELECT * FROM Table2 WHERE last_updated > $1"
  2516      stored_video_req:
  2517        postgres:
  2518          fetcher:
  2519            query:
  2520              SELECT * FROM Table1 WHERE id in (%REQUEST_ID_LIST%)
  2521              UNION ALL
  2522              SELECT * FROM Table2 WHERE id in (%IMP_ID_LIST%)
  2523              UNION ALL
  2524              SELECT * FROM Table3 WHERE id in (%ID_LIST%)
  2525            amp_query:
  2526              SELECT * FROM Table1 WHERE id in (%REQUEST_ID_LIST%)
  2527              UNION ALL
  2528              SELECT * FROM Table2 WHERE id in (%IMP_ID_LIST%)
  2529              UNION ALL
  2530              SELECT * FROM Table3 WHERE id in (%ID_LIST%)
  2531          poll_for_updates:
  2532            query: "SELECT * FROM Table1 WHERE last_updated > $1 UNION ALL SELECT * FROM Table2 WHERE last_updated > $1"
  2533            amp_query: "SELECT * FROM Table1 WHERE last_updated > $1 UNION ALL SELECT * FROM Table2 WHERE last_updated > $1"
  2534      stored_responses:
  2535        postgres:
  2536          fetcher:
  2537            query: 
  2538              SELECT * FROM Table1 WHERE id in (%REQUEST_ID_LIST%)
  2539              UNION ALL
  2540              SELECT * FROM Table2 WHERE id in (%IMP_ID_LIST%)
  2541              UNION ALL
  2542              SELECT * FROM Table3 WHERE id in (%ID_LIST%)
  2543            amp_query:
  2544              SELECT * FROM Table1 WHERE id in (%REQUEST_ID_LIST%)
  2545              UNION ALL
  2546              SELECT * FROM Table2 WHERE id in (%IMP_ID_LIST%)
  2547              UNION ALL
  2548              SELECT * FROM Table3 WHERE id in (%ID_LIST%)
  2549          poll_for_updates:
  2550            query: "SELECT * FROM Table1 WHERE last_updated > $1 UNION ALL SELECT * FROM Table2 WHERE last_updated > $1"
  2551            amp_query: "SELECT * FROM Table1 WHERE last_updated > $1 UNION ALL SELECT * FROM Table2 WHERE last_updated > $1"
  2552    `)
  2553  
  2554  	want_queries := struct {
  2555  		fetcher_query              string
  2556  		fetcher_amp_query          string
  2557  		poll_for_updates_query     string
  2558  		poll_for_updates_amp_query string
  2559  	}{
  2560  		fetcher_query: "SELECT * FROM Table1 WHERE id in ($REQUEST_ID_LIST) " +
  2561  			"UNION ALL " +
  2562  			"SELECT * FROM Table2 WHERE id in ($IMP_ID_LIST) " +
  2563  			"UNION ALL " +
  2564  			"SELECT * FROM Table3 WHERE id in ($ID_LIST)",
  2565  		fetcher_amp_query: "SELECT * FROM Table1 WHERE id in ($REQUEST_ID_LIST) " +
  2566  			"UNION ALL " +
  2567  			"SELECT * FROM Table2 WHERE id in ($IMP_ID_LIST) " +
  2568  			"UNION ALL " +
  2569  			"SELECT * FROM Table3 WHERE id in ($ID_LIST)",
  2570  		poll_for_updates_query:     "SELECT * FROM Table1 WHERE last_updated > $LAST_UPDATED UNION ALL SELECT * FROM Table2 WHERE last_updated > $LAST_UPDATED",
  2571  		poll_for_updates_amp_query: "SELECT * FROM Table1 WHERE last_updated > $LAST_UPDATED UNION ALL SELECT * FROM Table2 WHERE last_updated > $LAST_UPDATED",
  2572  	}
  2573  
  2574  	v := viper.New()
  2575  	v.SetConfigType("yaml")
  2576  	err := v.ReadConfig(bytes.NewBuffer(config))
  2577  	assert.NoError(t, err)
  2578  
  2579  	migrateConfigDatabaseConnection(v)
  2580  
  2581  	// stored_requests queries
  2582  	assert.Equal(t, want_queries.fetcher_query, v.GetString("stored_requests.database.fetcher.query"))
  2583  	assert.Equal(t, want_queries.fetcher_amp_query, v.GetString("stored_requests.database.fetcher.amp_query"))
  2584  	assert.Equal(t, want_queries.poll_for_updates_query, v.GetString("stored_requests.database.poll_for_updates.query"))
  2585  	assert.Equal(t, want_queries.poll_for_updates_amp_query, v.GetString("stored_requests.database.poll_for_updates.amp_query"))
  2586  
  2587  	// stored_video_req queries
  2588  	assert.Equal(t, want_queries.fetcher_query, v.GetString("stored_video_req.database.fetcher.query"))
  2589  	assert.Equal(t, want_queries.fetcher_amp_query, v.GetString("stored_video_req.database.fetcher.amp_query"))
  2590  	assert.Equal(t, want_queries.poll_for_updates_query, v.GetString("stored_video_req.database.poll_for_updates.query"))
  2591  	assert.Equal(t, want_queries.poll_for_updates_amp_query, v.GetString("stored_video_req.database.poll_for_updates.amp_query"))
  2592  
  2593  	// stored_responses queries
  2594  	assert.Equal(t, want_queries.fetcher_query, v.GetString("stored_responses.database.fetcher.query"))
  2595  	assert.Equal(t, want_queries.fetcher_amp_query, v.GetString("stored_responses.database.fetcher.amp_query"))
  2596  	assert.Equal(t, want_queries.poll_for_updates_query, v.GetString("stored_responses.database.poll_for_updates.query"))
  2597  	assert.Equal(t, want_queries.poll_for_updates_amp_query, v.GetString("stored_responses.database.poll_for_updates.amp_query"))
  2598  }
  2599  
  2600  func TestMigrateConfigCompression(t *testing.T) {
  2601  	testCases := []struct {
  2602  		desc                string
  2603  		config              []byte
  2604  		wantEnableGZIP      bool
  2605  		wantReqGZIPEnabled  bool
  2606  		wantRespGZIPEnabled bool
  2607  	}{
  2608  
  2609  		{
  2610  			desc:                "New config and old config not set",
  2611  			config:              []byte{},
  2612  			wantEnableGZIP:      false,
  2613  			wantReqGZIPEnabled:  false,
  2614  			wantRespGZIPEnabled: false,
  2615  		},
  2616  		{
  2617  			desc: "Old config set, new config not set",
  2618  			config: []byte(`
  2619                      enable_gzip: true
  2620                      `),
  2621  			wantEnableGZIP:      true,
  2622  			wantRespGZIPEnabled: true,
  2623  			wantReqGZIPEnabled:  false,
  2624  		},
  2625  		{
  2626  			desc: "Old config not set, new config set",
  2627  			config: []byte(`
  2628                      compression:
  2629                          response:
  2630                              enable_gzip: true
  2631                          request:
  2632                              enable_gzip: false
  2633                      `),
  2634  			wantEnableGZIP:      false,
  2635  			wantRespGZIPEnabled: true,
  2636  			wantReqGZIPEnabled:  false,
  2637  		},
  2638  		{
  2639  			desc: "Old config set and new config set",
  2640  			config: []byte(`
  2641                      enable_gzip: true
  2642                      compression:
  2643                          response:
  2644                              enable_gzip: false
  2645                          request:
  2646                              enable_gzip: true
  2647                      `),
  2648  			wantEnableGZIP:      true,
  2649  			wantRespGZIPEnabled: false,
  2650  			wantReqGZIPEnabled:  true,
  2651  		},
  2652  	}
  2653  
  2654  	for _, test := range testCases {
  2655  		v := viper.New()
  2656  		v.SetConfigType("yaml")
  2657  		err := v.ReadConfig(bytes.NewBuffer(test.config))
  2658  		assert.NoError(t, err)
  2659  
  2660  		migrateConfigCompression(v)
  2661  
  2662  		assert.Equal(t, test.wantEnableGZIP, v.GetBool("enable_gzip"), test.desc)
  2663  		assert.Equal(t, test.wantReqGZIPEnabled, v.GetBool("compression.request.enable_gzip"), test.desc)
  2664  		assert.Equal(t, test.wantRespGZIPEnabled, v.GetBool("compression.response.enable_gzip"), test.desc)
  2665  	}
  2666  }
  2667  
  2668  func TestIsConfigInfoPresent(t *testing.T) {
  2669  	configPrefix1Field2Only := []byte(`
  2670        prefix1:
  2671          field2: "value2"
  2672      `)
  2673  	configPrefix1Field4Only := []byte(`
  2674        prefix1:
  2675          field4: "value4"
  2676        `)
  2677  	configPrefix1Field2AndField3 := []byte(`
  2678        prefix1:
  2679          field2: "value2"
  2680          field3: "value3"
  2681        `)
  2682  
  2683  	tests := []struct {
  2684  		description string
  2685  		config      []byte
  2686  		keyPrefix   string
  2687  		fields      []string
  2688  		wantResult  bool
  2689  	}{
  2690  		{
  2691  			description: "config is nil",
  2692  			config:      nil,
  2693  			keyPrefix:   "prefix1",
  2694  			fields:      []string{"field1", "field2", "field3"},
  2695  			wantResult:  false,
  2696  		},
  2697  		{
  2698  			description: "config is empty",
  2699  			config:      []byte{},
  2700  			keyPrefix:   "prefix1",
  2701  			fields:      []string{"field1", "field2", "field3"},
  2702  			wantResult:  false,
  2703  		},
  2704  		{
  2705  			description: "present - one field exists in config",
  2706  			config:      configPrefix1Field2Only,
  2707  			keyPrefix:   "prefix1",
  2708  			fields:      []string{"field1", "field2", "field3"},
  2709  			wantResult:  true,
  2710  		},
  2711  		{
  2712  			description: "present - many fields exist in config",
  2713  			config:      configPrefix1Field2AndField3,
  2714  			keyPrefix:   "prefix1",
  2715  			fields:      []string{"field1", "field2", "field3"},
  2716  			wantResult:  true,
  2717  		},
  2718  		{
  2719  			description: "not present - field not found",
  2720  			config:      configPrefix1Field4Only,
  2721  			keyPrefix:   "prefix1",
  2722  			fields:      []string{"field1", "field2", "field3"},
  2723  			wantResult:  false,
  2724  		},
  2725  		{
  2726  			description: "not present - field exists but with a different prefix",
  2727  			config:      configPrefix1Field2Only,
  2728  			keyPrefix:   "prefix2",
  2729  			fields:      []string{"field1", "field2", "field3"},
  2730  			wantResult:  false,
  2731  		},
  2732  		{
  2733  			description: "not present - fields is nil",
  2734  			config:      configPrefix1Field2Only,
  2735  			keyPrefix:   "prefix1",
  2736  			fields:      nil,
  2737  			wantResult:  false,
  2738  		},
  2739  		{
  2740  			description: "not present - fields is empty",
  2741  			config:      configPrefix1Field2Only,
  2742  			keyPrefix:   "prefix1",
  2743  			fields:      []string{},
  2744  			wantResult:  false,
  2745  		},
  2746  	}
  2747  
  2748  	for _, tt := range tests {
  2749  		v := viper.New()
  2750  		v.SetConfigType("yaml")
  2751  		v.ReadConfig(bytes.NewBuffer(tt.config))
  2752  
  2753  		result := isConfigInfoPresent(v, tt.keyPrefix, tt.fields)
  2754  		assert.Equal(t, tt.wantResult, result, tt.description)
  2755  	}
  2756  }
  2757  
  2758  func TestNegativeRequestSize(t *testing.T) {
  2759  	cfg, v := newDefaultConfig(t)
  2760  	cfg.MaxRequestSize = -1
  2761  	assertOneError(t, cfg.validate(v), "cfg.max_request_size must be >= 0. Got -1")
  2762  }
  2763  
  2764  func TestNegativePrometheusTimeout(t *testing.T) {
  2765  	cfg, v := newDefaultConfig(t)
  2766  	cfg.Metrics.Prometheus.Port = 8001
  2767  	cfg.Metrics.Prometheus.TimeoutMillisRaw = 0
  2768  	assertOneError(t, cfg.validate(v), "metrics.prometheus.timeout_ms must be positive if metrics.prometheus.port is defined. Got timeout=0 and port=8001")
  2769  }
  2770  
  2771  func TestInvalidHostVendorID(t *testing.T) {
  2772  	tests := []struct {
  2773  		description  string
  2774  		vendorID     int
  2775  		wantErrorMsg string
  2776  	}{
  2777  		{
  2778  			description:  "Negative GDPR.HostVendorID",
  2779  			vendorID:     -1,
  2780  			wantErrorMsg: "gdpr.host_vendor_id must be in the range [0, 65535]. Got -1",
  2781  		},
  2782  		{
  2783  			description:  "Overflowed GDPR.HostVendorID",
  2784  			vendorID:     (0xffff) + 1,
  2785  			wantErrorMsg: "gdpr.host_vendor_id must be in the range [0, 65535]. Got 65536",
  2786  		},
  2787  	}
  2788  
  2789  	for _, tt := range tests {
  2790  		cfg, v := newDefaultConfig(t)
  2791  		cfg.GDPR.HostVendorID = tt.vendorID
  2792  		errs := cfg.validate(v)
  2793  
  2794  		assert.Equal(t, 1, len(errs), tt.description)
  2795  		assert.EqualError(t, errs[0], tt.wantErrorMsg, tt.description)
  2796  	}
  2797  }
  2798  
  2799  func TestInvalidAMPException(t *testing.T) {
  2800  	cfg, v := newDefaultConfig(t)
  2801  	cfg.GDPR.AMPException = true
  2802  	assertOneError(t, cfg.validate(v), "gdpr.amp_exception has been discontinued and must be removed from your config. If you need to disable GDPR for AMP, you may do so per-account (gdpr.integration_enabled.amp) or at the host level for the default account (account_defaults.gdpr.integration_enabled.amp)")
  2803  }
  2804  
  2805  func TestInvalidGDPRDefaultValue(t *testing.T) {
  2806  	cfg, v := newDefaultConfig(t)
  2807  	cfg.GDPR.DefaultValue = "2"
  2808  	assertOneError(t, cfg.validate(v), "gdpr.default_value must be 0 or 1")
  2809  }
  2810  
  2811  func TestMissingGDPRDefaultValue(t *testing.T) {
  2812  	v := viper.New()
  2813  
  2814  	cfg, _ := newDefaultConfig(t)
  2815  	assertOneError(t, cfg.validate(v), "gdpr.default_value is required and must be specified")
  2816  }
  2817  
  2818  func TestInvalidEnforceAlgo(t *testing.T) {
  2819  	cfg, v := newDefaultConfig(t)
  2820  	cfg.GDPR.TCF2.Purpose1.EnforceAlgo = ""
  2821  	cfg.GDPR.TCF2.Purpose2.EnforceAlgo = TCF2EnforceAlgoFull
  2822  	cfg.GDPR.TCF2.Purpose3.EnforceAlgo = TCF2EnforceAlgoBasic
  2823  	cfg.GDPR.TCF2.Purpose4.EnforceAlgo = TCF2EnforceAlgoFull
  2824  	cfg.GDPR.TCF2.Purpose5.EnforceAlgo = "invalid1"
  2825  	cfg.GDPR.TCF2.Purpose6.EnforceAlgo = "invalid2"
  2826  	cfg.GDPR.TCF2.Purpose7.EnforceAlgo = TCF2EnforceAlgoFull
  2827  	cfg.GDPR.TCF2.Purpose8.EnforceAlgo = TCF2EnforceAlgoBasic
  2828  	cfg.GDPR.TCF2.Purpose9.EnforceAlgo = TCF2EnforceAlgoFull
  2829  	cfg.GDPR.TCF2.Purpose10.EnforceAlgo = "invalid3"
  2830  
  2831  	errs := cfg.validate(v)
  2832  
  2833  	expectedErrs := []error{
  2834  		errors.New("gdpr.tcf2.purpose1.enforce_algo must be \"basic\" or \"full\". Got "),
  2835  		errors.New("gdpr.tcf2.purpose5.enforce_algo must be \"basic\" or \"full\". Got invalid1"),
  2836  		errors.New("gdpr.tcf2.purpose6.enforce_algo must be \"basic\" or \"full\". Got invalid2"),
  2837  		errors.New("gdpr.tcf2.purpose10.enforce_algo must be \"basic\" or \"full\". Got invalid3"),
  2838  	}
  2839  	assert.ElementsMatch(t, errs, expectedErrs, "gdpr.tcf2.purposeX.enforce_algo should prevent invalid values but it doesn't")
  2840  }
  2841  
  2842  func TestNegativeCurrencyConverterFetchInterval(t *testing.T) {
  2843  	v := viper.New()
  2844  	v.Set("gdpr.default_value", "0")
  2845  
  2846  	cfg := Configuration{
  2847  		CurrencyConverter: CurrencyConverter{
  2848  			FetchIntervalSeconds: -1,
  2849  		},
  2850  	}
  2851  	err := cfg.validate(v)
  2852  	assert.NotNil(t, err, "cfg.currency_converter.fetch_interval_seconds should prevent negative values, but it doesn't")
  2853  }
  2854  
  2855  func TestOverflowedCurrencyConverterFetchInterval(t *testing.T) {
  2856  	v := viper.New()
  2857  	v.Set("gdpr.default_value", "0")
  2858  
  2859  	cfg := Configuration{
  2860  		CurrencyConverter: CurrencyConverter{
  2861  			FetchIntervalSeconds: (0xffff) + 1,
  2862  		},
  2863  	}
  2864  	err := cfg.validate(v)
  2865  	assert.NotNil(t, err, "cfg.currency_converter.fetch_interval_seconds prevent values over %d, but it doesn't", 0xffff)
  2866  }
  2867  
  2868  func TestLimitTimeout(t *testing.T) {
  2869  	doTimeoutTest(t, 10, 15, 10, 0)
  2870  	doTimeoutTest(t, 10, 0, 10, 0)
  2871  	doTimeoutTest(t, 5, 5, 10, 0)
  2872  	doTimeoutTest(t, 15, 15, 0, 0)
  2873  	doTimeoutTest(t, 15, 0, 20, 15)
  2874  }
  2875  
  2876  func TestCookieSizeError(t *testing.T) {
  2877  	testCases := []struct {
  2878  		description string
  2879  		cookieSize  int
  2880  		expectError bool
  2881  	}{
  2882  		{"MIN_COOKIE_SIZE_BYTES + 1", MIN_COOKIE_SIZE_BYTES + 1, false},
  2883  		{"MIN_COOKIE_SIZE_BYTES", MIN_COOKIE_SIZE_BYTES, false},
  2884  		{"MIN_COOKIE_SIZE_BYTES - 1", MIN_COOKIE_SIZE_BYTES - 1, true},
  2885  		{"Zero", 0, false},
  2886  		{"Negative", -100, true},
  2887  	}
  2888  
  2889  	for _, test := range testCases {
  2890  		resultErr := isValidCookieSize(test.cookieSize)
  2891  
  2892  		if test.expectError {
  2893  			assert.Error(t, resultErr, test.description)
  2894  		} else {
  2895  			assert.NoError(t, resultErr, test.description)
  2896  		}
  2897  	}
  2898  }
  2899  
  2900  func TestNewCallsRequestValidation(t *testing.T) {
  2901  	testCases := []struct {
  2902  		description       string
  2903  		privateIPNetworks string
  2904  		expectedError     string
  2905  		expectedIPs       []net.IPNet
  2906  	}{
  2907  		{
  2908  			description:       "Valid",
  2909  			privateIPNetworks: `["1.1.1.0/24"]`,
  2910  			expectedIPs:       []net.IPNet{{IP: net.IP{1, 1, 1, 0}, Mask: net.CIDRMask(24, 32)}},
  2911  		},
  2912  		{
  2913  			description:       "Invalid",
  2914  			privateIPNetworks: `["1"]`,
  2915  			expectedError:     "Invalid private IPv4 networks: '1'",
  2916  		},
  2917  	}
  2918  
  2919  	for _, test := range testCases {
  2920  		v := viper.New()
  2921  		SetupViper(v, "", bidderInfos)
  2922  		v.Set("gdpr.default_value", "0")
  2923  		v.SetConfigType("yaml")
  2924  		v.ReadConfig(bytes.NewBuffer([]byte(
  2925  			`request_validation:
  2926      ipv4_private_networks: ` + test.privateIPNetworks)))
  2927  
  2928  		result, resultErr := New(v, bidderInfos, mockNormalizeBidderName)
  2929  
  2930  		if test.expectedError == "" {
  2931  			assert.NoError(t, resultErr, test.description+":err")
  2932  			assert.ElementsMatch(t, test.expectedIPs, result.RequestValidation.IPv4PrivateNetworksParsed, test.description+":parsed")
  2933  		} else {
  2934  			assert.Error(t, resultErr, test.description+":err")
  2935  		}
  2936  	}
  2937  }
  2938  
  2939  func TestValidateDebug(t *testing.T) {
  2940  	cfg, v := newDefaultConfig(t)
  2941  	cfg.Debug.TimeoutNotification.SamplingRate = 1.1
  2942  
  2943  	err := cfg.validate(v)
  2944  	assert.NotNil(t, err, "cfg.debug.timeout_notification.sampling_rate should not be allowed to be greater than 1.0, but it was allowed")
  2945  }
  2946  
  2947  func TestValidateAccountsConfigRestrictions(t *testing.T) {
  2948  	cfg, v := newDefaultConfig(t)
  2949  	cfg.Accounts.Files.Enabled = true
  2950  	cfg.Accounts.HTTP.Endpoint = "http://localhost"
  2951  	cfg.Accounts.Database.ConnectionInfo.Database = "accounts"
  2952  
  2953  	errs := cfg.validate(v)
  2954  	assert.Len(t, errs, 1)
  2955  	assert.Contains(t, errs, errors.New("accounts.database: retrieving accounts via database not available, use accounts.files"))
  2956  }
  2957  
  2958  func newDefaultConfig(t *testing.T) (*Configuration, *viper.Viper) {
  2959  	v := viper.New()
  2960  	SetupViper(v, "", bidderInfos)
  2961  	v.Set("gdpr.default_value", "0")
  2962  	v.SetConfigType("yaml")
  2963  	cfg, err := New(v, bidderInfos, mockNormalizeBidderName)
  2964  	assert.NoError(t, err, "Setting up config should work but it doesn't")
  2965  	return cfg, v
  2966  }
  2967  
  2968  func assertOneError(t *testing.T, errs []error, message string) {
  2969  	if !assert.Len(t, errs, 1) {
  2970  		return
  2971  	}
  2972  	assert.EqualError(t, errs[0], message)
  2973  }
  2974  
  2975  func doTimeoutTest(t *testing.T, expected int, requested int, max uint64, def uint64) {
  2976  	t.Helper()
  2977  	cfg := AuctionTimeouts{
  2978  		Default: def,
  2979  		Max:     max,
  2980  	}
  2981  	expectedDuration := time.Duration(expected) * time.Millisecond
  2982  	limited := cfg.LimitAuctionTimeout(time.Duration(requested) * time.Millisecond)
  2983  	assert.Equal(t, limited, expectedDuration, "Expected %dms timeout, got %dms", expectedDuration, limited/time.Millisecond)
  2984  }
  2985  
  2986  func TestSpecialFeature1VendorExceptionMap(t *testing.T) {
  2987  	baseConfig := []byte(`
  2988      gdpr:
  2989        default_value: 0
  2990        tcf2:
  2991          special_feature1:
  2992            vendor_exceptions: `)
  2993  
  2994  	tests := []struct {
  2995  		description             string
  2996  		configVendorExceptions  []byte
  2997  		wantVendorExceptions    []openrtb_ext.BidderName
  2998  		wantVendorExceptionsMap map[openrtb_ext.BidderName]struct{}
  2999  	}{
  3000  		{
  3001  			description:             "nil vendor exceptions",
  3002  			configVendorExceptions:  []byte(`null`),
  3003  			wantVendorExceptions:    []openrtb_ext.BidderName{},
  3004  			wantVendorExceptionsMap: map[openrtb_ext.BidderName]struct{}{},
  3005  		},
  3006  		{
  3007  			description:             "no vendor exceptions",
  3008  			configVendorExceptions:  []byte(`[]`),
  3009  			wantVendorExceptions:    []openrtb_ext.BidderName{},
  3010  			wantVendorExceptionsMap: map[openrtb_ext.BidderName]struct{}{},
  3011  		},
  3012  		{
  3013  			description:             "one vendor exception",
  3014  			configVendorExceptions:  []byte(`["vendor1"]`),
  3015  			wantVendorExceptions:    []openrtb_ext.BidderName{openrtb_ext.BidderName("vendor1")},
  3016  			wantVendorExceptionsMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderName("vendor1"): {}},
  3017  		},
  3018  		{
  3019  			description:             "many exceptions",
  3020  			configVendorExceptions:  []byte(`["vendor1","vendor2"]`),
  3021  			wantVendorExceptions:    []openrtb_ext.BidderName{openrtb_ext.BidderName("vendor1"), openrtb_ext.BidderName("vendor2")},
  3022  			wantVendorExceptionsMap: map[openrtb_ext.BidderName]struct{}{openrtb_ext.BidderName("vendor1"): {}, openrtb_ext.BidderName("vendor2"): {}},
  3023  		},
  3024  	}
  3025  
  3026  	for _, tt := range tests {
  3027  		config := append(baseConfig, tt.configVendorExceptions...)
  3028  
  3029  		v := viper.New()
  3030  		SetupViper(v, "", bidderInfos)
  3031  		v.SetConfigType("yaml")
  3032  		v.ReadConfig(bytes.NewBuffer(config))
  3033  		cfg, err := New(v, bidderInfos, mockNormalizeBidderName)
  3034  		assert.NoError(t, err, "Setting up config error", tt.description)
  3035  
  3036  		assert.Equal(t, tt.wantVendorExceptions, cfg.GDPR.TCF2.SpecialFeature1.VendorExceptions, tt.description)
  3037  		assert.Equal(t, tt.wantVendorExceptionsMap, cfg.GDPR.TCF2.SpecialFeature1.VendorExceptionMap, tt.description)
  3038  	}
  3039  }
  3040  
  3041  func TestTCF2PurposeEnforced(t *testing.T) {
  3042  	tests := []struct {
  3043  		description          string
  3044  		givePurposeConfigNil bool
  3045  		givePurpose1Enforced bool
  3046  		givePurpose2Enforced bool
  3047  		givePurpose          consentconstants.Purpose
  3048  		wantEnforced         bool
  3049  	}{
  3050  		{
  3051  			description:          "Purpose config is nil",
  3052  			givePurposeConfigNil: true,
  3053  			givePurpose:          1,
  3054  			wantEnforced:         false,
  3055  		},
  3056  		{
  3057  			description:          "Purpose 1 Enforced set to true",
  3058  			givePurpose1Enforced: true,
  3059  			givePurpose:          1,
  3060  			wantEnforced:         true,
  3061  		},
  3062  		{
  3063  			description:          "Purpose 1 Enforced set to false",
  3064  			givePurpose1Enforced: false,
  3065  			givePurpose:          1,
  3066  			wantEnforced:         false,
  3067  		},
  3068  		{
  3069  			description:          "Purpose 2 Enforced set to true",
  3070  			givePurpose2Enforced: true,
  3071  			givePurpose:          2,
  3072  			wantEnforced:         true,
  3073  		},
  3074  	}
  3075  
  3076  	for _, tt := range tests {
  3077  		tcf2 := TCF2{}
  3078  
  3079  		if !tt.givePurposeConfigNil {
  3080  			tcf2.PurposeConfigs = map[consentconstants.Purpose]*TCF2Purpose{
  3081  				1: {
  3082  					EnforcePurpose: tt.givePurpose1Enforced,
  3083  				},
  3084  				2: {
  3085  					EnforcePurpose: tt.givePurpose2Enforced,
  3086  				},
  3087  			}
  3088  		}
  3089  
  3090  		value := tcf2.PurposeEnforced(tt.givePurpose)
  3091  
  3092  		assert.Equal(t, tt.wantEnforced, value, tt.description)
  3093  	}
  3094  }
  3095  
  3096  func TestTCF2PurposeEnforcementAlgo(t *testing.T) {
  3097  	tests := []struct {
  3098  		description          string
  3099  		givePurposeConfigNil bool
  3100  		givePurpose1Algo     TCF2EnforcementAlgo
  3101  		givePurpose2Algo     TCF2EnforcementAlgo
  3102  		givePurpose          consentconstants.Purpose
  3103  		wantAlgo             TCF2EnforcementAlgo
  3104  	}{
  3105  		{
  3106  			description:          "Purpose config is nil",
  3107  			givePurposeConfigNil: true,
  3108  			givePurpose:          1,
  3109  			wantAlgo:             TCF2FullEnforcement,
  3110  		},
  3111  		{
  3112  			description:      "Purpose 1 enforcement algo set to basic",
  3113  			givePurpose1Algo: TCF2BasicEnforcement,
  3114  			givePurpose:      1,
  3115  			wantAlgo:         TCF2BasicEnforcement,
  3116  		},
  3117  		{
  3118  			description:      "Purpose 1 enforcement algo set to full",
  3119  			givePurpose1Algo: TCF2FullEnforcement,
  3120  			givePurpose:      1,
  3121  			wantAlgo:         TCF2FullEnforcement,
  3122  		},
  3123  		{
  3124  			description:      "Purpose 2 Enforcement algo set to basic",
  3125  			givePurpose2Algo: TCF2BasicEnforcement,
  3126  			givePurpose:      2,
  3127  			wantAlgo:         TCF2BasicEnforcement,
  3128  		},
  3129  	}
  3130  
  3131  	for _, tt := range tests {
  3132  		tcf2 := TCF2{}
  3133  
  3134  		if !tt.givePurposeConfigNil {
  3135  			tcf2.PurposeConfigs = map[consentconstants.Purpose]*TCF2Purpose{
  3136  				1: {
  3137  					EnforceAlgoID: tt.givePurpose1Algo,
  3138  				},
  3139  				2: {
  3140  					EnforceAlgoID: tt.givePurpose2Algo,
  3141  				},
  3142  			}
  3143  		}
  3144  
  3145  		value := tcf2.PurposeEnforcementAlgo(tt.givePurpose)
  3146  
  3147  		assert.Equal(t, tt.wantAlgo, value, tt.description)
  3148  	}
  3149  }
  3150  
  3151  func TestTCF2PurposeEnforcingVendors(t *testing.T) {
  3152  	tests := []struct {
  3153  		description           string
  3154  		givePurposeConfigNil  bool
  3155  		givePurpose1Enforcing bool
  3156  		givePurpose2Enforcing bool
  3157  		givePurpose           consentconstants.Purpose
  3158  		wantEnforcing         bool
  3159  	}{
  3160  		{
  3161  			description:          "Purpose config is nil",
  3162  			givePurposeConfigNil: true,
  3163  			givePurpose:          1,
  3164  			wantEnforcing:        false,
  3165  		},
  3166  		{
  3167  			description:           "Purpose 1 Enforcing set to true",
  3168  			givePurpose1Enforcing: true,
  3169  			givePurpose:           1,
  3170  			wantEnforcing:         true,
  3171  		},
  3172  		{
  3173  			description:           "Purpose 1 Enforcing set to false",
  3174  			givePurpose1Enforcing: false,
  3175  			givePurpose:           1,
  3176  			wantEnforcing:         false,
  3177  		},
  3178  		{
  3179  			description:           "Purpose 2 Enforcing set to true",
  3180  			givePurpose2Enforcing: true,
  3181  			givePurpose:           2,
  3182  			wantEnforcing:         true,
  3183  		},
  3184  	}
  3185  
  3186  	for _, tt := range tests {
  3187  		tcf2 := TCF2{}
  3188  
  3189  		if !tt.givePurposeConfigNil {
  3190  			tcf2.PurposeConfigs = map[consentconstants.Purpose]*TCF2Purpose{
  3191  				1: {
  3192  					EnforceVendors: tt.givePurpose1Enforcing,
  3193  				},
  3194  				2: {
  3195  					EnforceVendors: tt.givePurpose2Enforcing,
  3196  				},
  3197  			}
  3198  		}
  3199  
  3200  		value := tcf2.PurposeEnforcingVendors(tt.givePurpose)
  3201  
  3202  		assert.Equal(t, tt.wantEnforcing, value, tt.description)
  3203  	}
  3204  }
  3205  
  3206  func TestTCF2PurposeVendorExceptions(t *testing.T) {
  3207  	tests := []struct {
  3208  		description              string
  3209  		givePurposeConfigNil     bool
  3210  		givePurpose1ExceptionMap map[openrtb_ext.BidderName]struct{}
  3211  		givePurpose2ExceptionMap map[openrtb_ext.BidderName]struct{}
  3212  		givePurpose              consentconstants.Purpose
  3213  		wantExceptionMap         map[openrtb_ext.BidderName]struct{}
  3214  	}{
  3215  		{
  3216  			description:          "Purpose config is nil",
  3217  			givePurposeConfigNil: true,
  3218  			givePurpose:          1,
  3219  			wantExceptionMap:     map[openrtb_ext.BidderName]struct{}{},
  3220  		},
  3221  		{
  3222  			description:      "Nil - exception map not defined for purpose",
  3223  			givePurpose:      1,
  3224  			wantExceptionMap: map[openrtb_ext.BidderName]struct{}{},
  3225  		},
  3226  		{
  3227  			description:              "Empty - exception map empty for purpose",
  3228  			givePurpose:              1,
  3229  			givePurpose1ExceptionMap: map[openrtb_ext.BidderName]struct{}{},
  3230  			wantExceptionMap:         map[openrtb_ext.BidderName]struct{}{},
  3231  		},
  3232  		{
  3233  			description:              "Nonempty - exception map with multiple entries for purpose",
  3234  			givePurpose:              1,
  3235  			givePurpose1ExceptionMap: map[openrtb_ext.BidderName]struct{}{"rubicon": {}, "appnexus": {}, "index": {}},
  3236  			wantExceptionMap:         map[openrtb_ext.BidderName]struct{}{"rubicon": {}, "appnexus": {}, "index": {}},
  3237  		},
  3238  		{
  3239  			description:              "Nonempty - exception map with multiple entries for different purpose",
  3240  			givePurpose:              2,
  3241  			givePurpose1ExceptionMap: map[openrtb_ext.BidderName]struct{}{"rubicon": {}, "appnexus": {}, "index": {}},
  3242  			givePurpose2ExceptionMap: map[openrtb_ext.BidderName]struct{}{"rubicon": {}, "appnexus": {}, "openx": {}},
  3243  			wantExceptionMap:         map[openrtb_ext.BidderName]struct{}{"rubicon": {}, "appnexus": {}, "openx": {}},
  3244  		},
  3245  	}
  3246  
  3247  	for _, tt := range tests {
  3248  		tcf2 := TCF2{}
  3249  
  3250  		if !tt.givePurposeConfigNil {
  3251  			tcf2.PurposeConfigs = map[consentconstants.Purpose]*TCF2Purpose{
  3252  				1: {
  3253  					VendorExceptionMap: tt.givePurpose1ExceptionMap,
  3254  				},
  3255  				2: {
  3256  					VendorExceptionMap: tt.givePurpose2ExceptionMap,
  3257  				},
  3258  			}
  3259  		}
  3260  
  3261  		value := tcf2.PurposeVendorExceptions(tt.givePurpose)
  3262  
  3263  		assert.Equal(t, tt.wantExceptionMap, value, tt.description)
  3264  	}
  3265  }
  3266  
  3267  func TestTCF2FeatureOneVendorException(t *testing.T) {
  3268  	tests := []struct {
  3269  		description           string
  3270  		giveExceptionMap      map[openrtb_ext.BidderName]struct{}
  3271  		giveBidder            openrtb_ext.BidderName
  3272  		wantIsVendorException bool
  3273  	}{
  3274  		{
  3275  			description:           "Nil - exception map not defined",
  3276  			giveBidder:            "appnexus",
  3277  			wantIsVendorException: false,
  3278  		},
  3279  		{
  3280  			description:           "Empty - exception map empty",
  3281  			giveExceptionMap:      map[openrtb_ext.BidderName]struct{}{},
  3282  			giveBidder:            "appnexus",
  3283  			wantIsVendorException: false,
  3284  		},
  3285  		{
  3286  			description:           "One - bidder found in exception map containing one entry",
  3287  			giveExceptionMap:      map[openrtb_ext.BidderName]struct{}{"appnexus": {}},
  3288  			giveBidder:            "appnexus",
  3289  			wantIsVendorException: true,
  3290  		},
  3291  		{
  3292  			description:           "Many - bidder found in exception map containing multiple entries",
  3293  			giveExceptionMap:      map[openrtb_ext.BidderName]struct{}{"rubicon": {}, "appnexus": {}, "index": {}},
  3294  			giveBidder:            "appnexus",
  3295  			wantIsVendorException: true,
  3296  		},
  3297  		{
  3298  			description:           "Many - bidder not found in exception map containing multiple entries",
  3299  			giveExceptionMap:      map[openrtb_ext.BidderName]struct{}{"rubicon": {}, "appnexus": {}, "index": {}},
  3300  			giveBidder:            "openx",
  3301  			wantIsVendorException: false,
  3302  		},
  3303  	}
  3304  
  3305  	for _, tt := range tests {
  3306  		tcf2 := TCF2{
  3307  			SpecialFeature1: TCF2SpecialFeature{
  3308  				VendorExceptionMap: tt.giveExceptionMap,
  3309  			},
  3310  		}
  3311  
  3312  		value := tcf2.FeatureOneVendorException(tt.giveBidder)
  3313  
  3314  		assert.Equal(t, tt.wantIsVendorException, value, tt.description)
  3315  	}
  3316  }
  3317  
  3318  func TestMigrateConfigEventsEnabled(t *testing.T) {
  3319  	testCases := []struct {
  3320  		name                  string
  3321  		oldFieldValue         *bool
  3322  		newFieldValue         *bool
  3323  		expectedOldFieldValue *bool
  3324  		expectedNewFieldValue *bool
  3325  	}{
  3326  		{
  3327  			name:                  "Both old and new fields are nil",
  3328  			oldFieldValue:         nil,
  3329  			newFieldValue:         nil,
  3330  			expectedOldFieldValue: nil,
  3331  			expectedNewFieldValue: nil,
  3332  		},
  3333  		{
  3334  			name:                  "Only old field is set",
  3335  			oldFieldValue:         ptrutil.ToPtr(true),
  3336  			newFieldValue:         nil,
  3337  			expectedOldFieldValue: ptrutil.ToPtr(true),
  3338  			expectedNewFieldValue: nil,
  3339  		},
  3340  		{
  3341  			name:                  "Only new field is set",
  3342  			oldFieldValue:         nil,
  3343  			newFieldValue:         ptrutil.ToPtr(true),
  3344  			expectedOldFieldValue: ptrutil.ToPtr(true),
  3345  			expectedNewFieldValue: nil,
  3346  		},
  3347  		{
  3348  			name:                  "Both old and new fields are set, override old field with new field value",
  3349  			oldFieldValue:         ptrutil.ToPtr(false),
  3350  			newFieldValue:         ptrutil.ToPtr(true),
  3351  			expectedOldFieldValue: ptrutil.ToPtr(true),
  3352  			expectedNewFieldValue: nil,
  3353  		},
  3354  	}
  3355  
  3356  	for _, tc := range testCases {
  3357  		t.Run(tc.name, func(t *testing.T) {
  3358  			updatedOldFieldValue, updatedNewFieldValue := migrateConfigEventsEnabled(tc.oldFieldValue, tc.newFieldValue)
  3359  
  3360  			assert.Equal(t, tc.expectedOldFieldValue, updatedOldFieldValue)
  3361  			assert.Nil(t, updatedNewFieldValue)
  3362  			assert.Nil(t, tc.expectedNewFieldValue)
  3363  		})
  3364  	}
  3365  }