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 }