From 6bdbc1fbd404405de9607f47efafca26f2df8a98 Mon Sep 17 00:00:00 2001 From: Anish B Date: Mon, 4 May 2026 14:49:37 +0530 Subject: [PATCH 1/4] Skip all remaining available bidders if priority-groups-only set to true --- config/account.go | 9 ++-- endpoints/cookie_sync.go | 12 ++++- endpoints/cookie_sync_test.go | 38 ++++++++++++++++ usersync/bidderchooser.go | 12 ++--- usersync/bidderchooser_test.go | 82 ++++++++++++++++++++++------------ usersync/chooser.go | 5 ++- 6 files changed, 116 insertions(+), 42 deletions(-) diff --git a/config/account.go b/config/account.go index a773e6fbbd8..cc403f962b5 100644 --- a/config/account.go +++ b/config/account.go @@ -58,10 +58,11 @@ type Account struct { // CookieSync represents the account-level defaults for the cookie sync endpoint. type CookieSync struct { - DefaultLimit *int `mapstructure:"default_limit" json:"default_limit"` - MaxLimit *int `mapstructure:"max_limit" json:"max_limit"` - DefaultCoopSync *bool `mapstructure:"default_coop_sync" json:"default_coop_sync"` - PriorityGroups [][]string `mapstructure:"priority_groups" json:"priority_groups"` + DefaultLimit *int `mapstructure:"default_limit" json:"default_limit"` + MaxLimit *int `mapstructure:"max_limit" json:"max_limit"` + DefaultCoopSync *bool `mapstructure:"default_coop_sync" json:"default_coop_sync"` + PriorityGroups [][]string `mapstructure:"priority_groups" json:"priority_groups"` + PriorityGroupsOnly *bool `mapstructure:"priority_groups_only" json:"priority_groups_only"` } // AccountCCPA represents account-specific CCPA configuration diff --git a/endpoints/cookie_sync.go b/endpoints/cookie_sync.go index 0c1c1fb274c..f64b8e2bb73 100644 --- a/endpoints/cookie_sync.go +++ b/endpoints/cookie_sync.go @@ -183,8 +183,9 @@ func (c *cookieSyncEndpoint) parseRequest(r *http.Request) (usersync.Request, ma rx := usersync.Request{ Bidders: request.Bidders, Cooperative: usersync.Cooperative{ - Enabled: (request.CooperativeSync != nil && *request.CooperativeSync) || (request.CooperativeSync == nil && c.config.UserSync.Cooperative.EnabledByDefault), - PriorityGroups: c.findPriorityGroups(account.CookieSync), + Enabled: (request.CooperativeSync != nil && *request.CooperativeSync) || (request.CooperativeSync == nil && c.config.UserSync.Cooperative.EnabledByDefault), + PriorityGroups: c.findPriorityGroups(account.CookieSync), + PriorityGroupsOnly: c.findPriorityGroupsOnly(account.CookieSync), }, Debug: request.Debug, Limit: limit, @@ -341,6 +342,13 @@ func (c *cookieSyncEndpoint) findPriorityGroups(accountCookieSyncConfig config.C return c.config.UserSync.PriorityGroups } +func (c *cookieSyncEndpoint) findPriorityGroupsOnly(accountCookieSyncConfig config.CookieSync) bool { + if accountCookieSyncConfig.PriorityGroupsOnly != nil { + return *accountCookieSyncConfig.PriorityGroupsOnly + } + return false +} + func parseTypeFilter(request *cookieSyncRequestFilterSettings) (usersync.SyncTypeFilter, error) { syncTypeFilter := usersync.SyncTypeFilter{ IFrame: cookieSyncBidderFilterAllowAll, diff --git a/endpoints/cookie_sync_test.go b/endpoints/cookie_sync_test.go index 3da85fb71a4..8839b6529ba 100644 --- a/endpoints/cookie_sync_test.go +++ b/endpoints/cookie_sync_test.go @@ -2602,6 +2602,44 @@ func TestCookieSyncFindPriorityGroups(t *testing.T) { } } +func TestCookieSyncFindPriorityGroupsOnly(t *testing.T) { + testCases := []struct { + description string + givenAccountCookieSync config.CookieSync + expected bool + }{ + { + description: "Returns true when PriorityGroupsOnly is true", + givenAccountCookieSync: config.CookieSync{ + PriorityGroupsOnly: ptrutil.ToPtr(true), + }, + expected: true, + }, + { + description: "Returns false when PriorityGroupsOnly is false", + givenAccountCookieSync: config.CookieSync{ + PriorityGroupsOnly: ptrutil.ToPtr(false), + }, + expected: false, + }, + { + description: "Returns false when PriorityGroupsOnly is nil", + givenAccountCookieSync: config.CookieSync{ + PriorityGroupsOnly: nil, + }, + expected: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + endpoint := &cookieSyncEndpoint{} + result := endpoint.findPriorityGroupsOnly(tc.givenAccountCookieSync) + assert.Equal(t, tc.expected, result) + }) + } +} + // createAccountJSON creates a JSON representation of account config for testing func createAccountJSON(priorityGroups [][]string, defaultCoopSync *bool) json.RawMessage { account := map[string]interface{}{ diff --git a/usersync/bidderchooser.go b/usersync/bidderchooser.go index 1b01e5116e9..f8f40773519 100644 --- a/usersync/bidderchooser.go +++ b/usersync/bidderchooser.go @@ -13,7 +13,7 @@ type standardBidderChooser struct { func (c standardBidderChooser) choose(requested, available []string, cooperative Cooperative) []string { if cooperative.Enabled { - return c.chooseCooperative(requested, available, cooperative.PriorityGroups) + return c.chooseCooperative(requested, available, cooperative) } if len(requested) == 0 { @@ -23,7 +23,7 @@ func (c standardBidderChooser) choose(requested, available []string, cooperative return c.shuffledCopy(requested) } -func (c standardBidderChooser) chooseCooperative(requested, available []string, priorityGroups [][]string) []string { +func (c standardBidderChooser) chooseCooperative(requested, available []string, cooperative Cooperative) []string { // allocate enough memory for the slice to try to avoid re-allocation. the 50% overhead is a guess // at a satisfactory value. since all available bidders are included in the slice, along with // requested and prioritized bidders, expect there to be be many duplicates. the duplicate are @@ -35,12 +35,14 @@ func (c standardBidderChooser) chooseCooperative(requested, available []string, bidders = c.shuffledAppend(bidders, requested) // priority groups - for _, group := range priorityGroups { + for _, group := range cooperative.PriorityGroups { bidders = c.shuffledAppend(bidders, group) } - // available - bidders = c.shuffledAppend(bidders, available) + // available — only if NOT priority_groups_only + if !cooperative.PriorityGroupsOnly { + bidders = c.shuffledAppend(bidders, available) + } return bidders } diff --git a/usersync/bidderchooser_test.go b/usersync/bidderchooser_test.go index fe7d296f1f0..7c3e27ab2bc 100644 --- a/usersync/bidderchooser_test.go +++ b/usersync/bidderchooser_test.go @@ -62,6 +62,12 @@ func TestBidderChooserChoose(t *testing.T) { givenCooperative: Cooperative{Enabled: true, PriorityGroups: [][]string{{"pr1A", "pr1B"}, {"pr2A", "pr2B"}}}, expected: []string{"r2", "r1", "pr1B", "pr1A", "pr2B", "pr2A", "a2", "a1"}, }, + { + description: "Coop - PriorityGroupsOnly", + givenRequested: []string{"r1", "r2"}, + givenCooperative: Cooperative{Enabled: true, PriorityGroups: [][]string{{"pr1A", "pr1B"}}, PriorityGroupsOnly: true}, + expected: []string{"r2", "r1", "pr1B", "pr1A"}, + }, } for _, test := range testCases { @@ -77,52 +83,70 @@ func TestBidderChooserCooperative(t *testing.T) { available := []string{"a1", "a2"} testCases := []struct { - description string - givenRequested []string - givenPriorityGroups [][]string - expected []string + description string + givenRequested []string + givenCoop Cooperative + expected []string }{ { - description: "Nil", - givenRequested: nil, - givenPriorityGroups: nil, - expected: []string{"a2", "a1"}, + description: "Nil", + givenRequested: nil, + givenCoop: Cooperative{Enabled: true}, + expected: []string{"a2", "a1"}, + }, + { + description: "Empty", + givenRequested: []string{}, + givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{}}, + expected: []string{"a2", "a1"}, + }, + { + description: "Requested", + givenRequested: []string{"r1", "r2"}, + givenCoop: Cooperative{Enabled: true}, + expected: []string{"r2", "r1", "a2", "a1"}, + }, + { + description: "Priority Groups - One", + givenRequested: nil, + givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{{"pr1A", "pr1B"}}}, + expected: []string{"pr1B", "pr1A", "a2", "a1"}, }, { - description: "Empty", - givenRequested: []string{}, - givenPriorityGroups: [][]string{}, - expected: []string{"a2", "a1"}, + description: "Priority Groups - Many", + givenRequested: nil, + givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{{"pr1A", "pr1B"}, {"pr2A", "pr2B"}}}, + expected: []string{"pr1B", "pr1A", "pr2B", "pr2A", "a2", "a1"}, }, { - description: "Requested", - givenRequested: []string{"r1", "r2"}, - givenPriorityGroups: nil, - expected: []string{"r2", "r1", "a2", "a1"}, + description: "Requested + Priority Groups", + givenRequested: []string{"r1", "r2"}, + givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{{"pr1A", "pr1B"}, {"pr2A", "pr2B"}}}, + expected: []string{"r2", "r1", "pr1B", "pr1A", "pr2B", "pr2A", "a2", "a1"}, }, { - description: "Priority Groups - One", - givenRequested: nil, - givenPriorityGroups: [][]string{{"pr1A", "pr1B"}}, - expected: []string{"pr1B", "pr1A", "a2", "a1"}, + description: "PriorityGroupsOnly - No Remaining Bidders", + givenRequested: []string{"r1", "r2"}, + givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{{"pr1A", "pr1B"}}, PriorityGroupsOnly: true}, + expected: []string{"r2", "r1", "pr1B", "pr1A"}, }, { - description: "Priority Groups - Many", - givenRequested: nil, - givenPriorityGroups: [][]string{{"pr1A", "pr1B"}, {"pr2A", "pr2B"}}, - expected: []string{"pr1B", "pr1A", "pr2B", "pr2A", "a2", "a1"}, + description: "PriorityGroupsOnly - No Requested", + givenRequested: nil, + givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{{"pr1A", "pr1B"}, {"pr2A", "pr2B"}}, PriorityGroupsOnly: true}, + expected: []string{"pr1B", "pr1A", "pr2B", "pr2A"}, }, { - description: "Requested + Priority Groups", - givenRequested: []string{"r1", "r2"}, - givenPriorityGroups: [][]string{{"pr1A", "pr1B"}, {"pr2A", "pr2B"}}, - expected: []string{"r2", "r1", "pr1B", "pr1A", "pr2B", "pr2A", "a2", "a1"}, + description: "PriorityGroupsOnly - Empty Priority Groups", + givenRequested: []string{"r1", "r2"}, + givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{}, PriorityGroupsOnly: true}, + expected: []string{"r2", "r1"}, }, } for _, test := range testCases { chooser := standardBidderChooser{shuffler: shuffler} - result := chooser.chooseCooperative(test.givenRequested, available, test.givenPriorityGroups) + result := chooser.chooseCooperative(test.givenRequested, available, test.givenCoop) assert.Equal(t, test.expected, result, test.description) } diff --git a/usersync/chooser.go b/usersync/chooser.go index bc2d0812a7f..88913a76ccb 100644 --- a/usersync/chooser.go +++ b/usersync/chooser.go @@ -46,8 +46,9 @@ type Request struct { // Cooperative specifies the settings for cooperative syncing for a given request, where bidders // other than those used by the publisher are considered for syncing. type Cooperative struct { - Enabled bool - PriorityGroups [][]string + Enabled bool + PriorityGroups [][]string + PriorityGroupsOnly bool } // Result specifies which bidders were included in the evaluation and which syncers were chosen. From 69181d445c5ec81232d2d8d899fe99986560c6e9 Mon Sep 17 00:00:00 2001 From: Anish B Date: Mon, 4 May 2026 16:14:24 +0530 Subject: [PATCH 2/4] Modifying the test case --- endpoints/cookie_sync_test.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/endpoints/cookie_sync_test.go b/endpoints/cookie_sync_test.go index 8839b6529ba..f0e4224d9c2 100644 --- a/endpoints/cookie_sync_test.go +++ b/endpoints/cookie_sync_test.go @@ -2603,27 +2603,23 @@ func TestCookieSyncFindPriorityGroups(t *testing.T) { } func TestCookieSyncFindPriorityGroupsOnly(t *testing.T) { - testCases := []struct { - description string + testCases := map[string]struct { givenAccountCookieSync config.CookieSync expected bool }{ - { - description: "Returns true when PriorityGroupsOnly is true", + "true": { givenAccountCookieSync: config.CookieSync{ PriorityGroupsOnly: ptrutil.ToPtr(true), }, expected: true, }, - { - description: "Returns false when PriorityGroupsOnly is false", + "false": { givenAccountCookieSync: config.CookieSync{ PriorityGroupsOnly: ptrutil.ToPtr(false), }, expected: false, }, - { - description: "Returns false when PriorityGroupsOnly is nil", + "nil": { givenAccountCookieSync: config.CookieSync{ PriorityGroupsOnly: nil, }, @@ -2631,8 +2627,8 @@ func TestCookieSyncFindPriorityGroupsOnly(t *testing.T) { }, } - for _, tc := range testCases { - t.Run(tc.description, func(t *testing.T) { + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { endpoint := &cookieSyncEndpoint{} result := endpoint.findPriorityGroupsOnly(tc.givenAccountCookieSync) assert.Equal(t, tc.expected, result) From 933f03f29cef4d981fb384b2a448fc089946cabe Mon Sep 17 00:00:00 2001 From: Anish B Date: Mon, 4 May 2026 19:06:13 +0530 Subject: [PATCH 3/4] Reworking on the test case for bidderchooser --- usersync/bidderchooser_test.go | 41 +++++++++++++--------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/usersync/bidderchooser_test.go b/usersync/bidderchooser_test.go index 7c3e27ab2bc..cdf007aa3c7 100644 --- a/usersync/bidderchooser_test.go +++ b/usersync/bidderchooser_test.go @@ -82,73 +82,64 @@ func TestBidderChooserCooperative(t *testing.T) { shuffler := reverseShuffler{} available := []string{"a1", "a2"} - testCases := []struct { - description string + testCases := map[string]struct { givenRequested []string givenCoop Cooperative expected []string }{ - { - description: "Nil", + "nil": { givenRequested: nil, givenCoop: Cooperative{Enabled: true}, expected: []string{"a2", "a1"}, }, - { - description: "Empty", + "empty": { givenRequested: []string{}, givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{}}, expected: []string{"a2", "a1"}, }, - { - description: "Requested", + "requested": { givenRequested: []string{"r1", "r2"}, givenCoop: Cooperative{Enabled: true}, expected: []string{"r2", "r1", "a2", "a1"}, }, - { - description: "Priority Groups - One", + "priority_groups_one": { givenRequested: nil, givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{{"pr1A", "pr1B"}}}, expected: []string{"pr1B", "pr1A", "a2", "a1"}, }, - { - description: "Priority Groups - Many", + "priority_groups_many": { givenRequested: nil, givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{{"pr1A", "pr1B"}, {"pr2A", "pr2B"}}}, expected: []string{"pr1B", "pr1A", "pr2B", "pr2A", "a2", "a1"}, }, - { - description: "Requested + Priority Groups", + "requested_and_priority_groups": { givenRequested: []string{"r1", "r2"}, givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{{"pr1A", "pr1B"}, {"pr2A", "pr2B"}}}, expected: []string{"r2", "r1", "pr1B", "pr1A", "pr2B", "pr2A", "a2", "a1"}, }, - { - description: "PriorityGroupsOnly - No Remaining Bidders", + "priority_groups_only_no_remaining": { givenRequested: []string{"r1", "r2"}, givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{{"pr1A", "pr1B"}}, PriorityGroupsOnly: true}, expected: []string{"r2", "r1", "pr1B", "pr1A"}, }, - { - description: "PriorityGroupsOnly - No Requested", + "priority_groups_only_no_requested": { givenRequested: nil, givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{{"pr1A", "pr1B"}, {"pr2A", "pr2B"}}, PriorityGroupsOnly: true}, expected: []string{"pr1B", "pr1A", "pr2B", "pr2A"}, }, - { - description: "PriorityGroupsOnly - Empty Priority Groups", + "priority_groups_only_empty_groups": { givenRequested: []string{"r1", "r2"}, givenCoop: Cooperative{Enabled: true, PriorityGroups: [][]string{}, PriorityGroupsOnly: true}, expected: []string{"r2", "r1"}, }, } - for _, test := range testCases { - chooser := standardBidderChooser{shuffler: shuffler} - result := chooser.chooseCooperative(test.givenRequested, available, test.givenCoop) - - assert.Equal(t, test.expected, result, test.description) + for name, test := range testCases { + t.Run(name, func(t *testing.T) { + chooser := standardBidderChooser{shuffler: shuffler} + result := chooser.chooseCooperative(test.givenRequested, available, test.givenCoop) + assert.Equal(t, test.expected, result) + }) } } From 647b6e5d887c8aba6f2c02a850dc1fe94bb7b098 Mon Sep 17 00:00:00 2001 From: Anish B Date: Wed, 13 May 2026 16:58:59 +0530 Subject: [PATCH 4/4] Review changes --- endpoints/cookie_sync.go | 10 +--- endpoints/cookie_sync_test.go | 90 ++++++++++++++++++----------------- usersync/bidderchooser.go | 1 - 3 files changed, 48 insertions(+), 53 deletions(-) diff --git a/endpoints/cookie_sync.go b/endpoints/cookie_sync.go index f64b8e2bb73..8b90cb2ff89 100644 --- a/endpoints/cookie_sync.go +++ b/endpoints/cookie_sync.go @@ -30,6 +30,7 @@ import ( "github.com/prebid/prebid-server/v4/stored_requests" "github.com/prebid/prebid-server/v4/usersync" "github.com/prebid/prebid-server/v4/util/jsonutil" + "github.com/prebid/prebid-server/v4/util/ptrutil" stringutil "github.com/prebid/prebid-server/v4/util/stringutil" "github.com/prebid/prebid-server/v4/util/timeutil" ) @@ -185,7 +186,7 @@ func (c *cookieSyncEndpoint) parseRequest(r *http.Request) (usersync.Request, ma Cooperative: usersync.Cooperative{ Enabled: (request.CooperativeSync != nil && *request.CooperativeSync) || (request.CooperativeSync == nil && c.config.UserSync.Cooperative.EnabledByDefault), PriorityGroups: c.findPriorityGroups(account.CookieSync), - PriorityGroupsOnly: c.findPriorityGroupsOnly(account.CookieSync), + PriorityGroupsOnly: ptrutil.ValueOrDefault(account.CookieSync.PriorityGroupsOnly), }, Debug: request.Debug, Limit: limit, @@ -342,13 +343,6 @@ func (c *cookieSyncEndpoint) findPriorityGroups(accountCookieSyncConfig config.C return c.config.UserSync.PriorityGroups } -func (c *cookieSyncEndpoint) findPriorityGroupsOnly(accountCookieSyncConfig config.CookieSync) bool { - if accountCookieSyncConfig.PriorityGroupsOnly != nil { - return *accountCookieSyncConfig.PriorityGroupsOnly - } - return false -} - func parseTypeFilter(request *cookieSyncRequestFilterSettings) (usersync.SyncTypeFilter, error) { syncTypeFilter := usersync.SyncTypeFilter{ IFrame: cookieSyncBidderFilterAllowAll, diff --git a/endpoints/cookie_sync_test.go b/endpoints/cookie_sync_test.go index f0e4224d9c2..503eb9c35b2 100644 --- a/endpoints/cookie_sync_test.go +++ b/endpoints/cookie_sync_test.go @@ -2602,42 +2602,8 @@ func TestCookieSyncFindPriorityGroups(t *testing.T) { } } -func TestCookieSyncFindPriorityGroupsOnly(t *testing.T) { - testCases := map[string]struct { - givenAccountCookieSync config.CookieSync - expected bool - }{ - "true": { - givenAccountCookieSync: config.CookieSync{ - PriorityGroupsOnly: ptrutil.ToPtr(true), - }, - expected: true, - }, - "false": { - givenAccountCookieSync: config.CookieSync{ - PriorityGroupsOnly: ptrutil.ToPtr(false), - }, - expected: false, - }, - "nil": { - givenAccountCookieSync: config.CookieSync{ - PriorityGroupsOnly: nil, - }, - expected: false, - }, - } - - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - endpoint := &cookieSyncEndpoint{} - result := endpoint.findPriorityGroupsOnly(tc.givenAccountCookieSync) - assert.Equal(t, tc.expected, result) - }) - } -} - // createAccountJSON creates a JSON representation of account config for testing -func createAccountJSON(priorityGroups [][]string, defaultCoopSync *bool) json.RawMessage { +func createAccountJSON(priorityGroups [][]string, defaultCoopSync *bool, priorityGroupsOnly *bool) json.RawMessage { account := map[string]interface{}{ "cookie_sync": map[string]interface{}{ "priority_groups": priorityGroups, @@ -2648,6 +2614,10 @@ func createAccountJSON(priorityGroups [][]string, defaultCoopSync *bool) json.Ra account["cookie_sync"].(map[string]interface{})["default_coop_sync"] = *defaultCoopSync } + if priorityGroupsOnly != nil { + account["cookie_sync"].(map[string]interface{})["priority_groups_only"] = *priorityGroupsOnly + } + jsonData, _ := json.Marshal(account) return json.RawMessage(jsonData) } @@ -2686,13 +2656,15 @@ func TestCookieSyncPriorityGroupsIntegration(t *testing.T) { } testCases := []struct { - description string - givenRequestBody string - givenAccountPriorityGroups [][]string - givenAccountDefaultCoopSync *bool - givenGlobalPriorityGroups [][]string - givenCooperativeEnabledByDef bool - shouldContainBidders []string + description string + givenRequestBody string + givenAccountPriorityGroups [][]string + givenAccountDefaultCoopSync *bool + givenAccountPriorityGroupsOnly *bool + givenGlobalPriorityGroups [][]string + givenCooperativeEnabledByDef bool + shouldContainBidders []string + shouldNotContainBidders []string }{ { description: "Account-level priority groups used with cooperative sync enabled", @@ -2747,6 +2719,31 @@ func TestCookieSyncPriorityGroupsIntegration(t *testing.T) { givenCooperativeEnabledByDef: false, shouldContainBidders: []string{"appnexus", "rubicon", "pubmatic"}, }, + { + description: "Priority groups only — remaining bidders excluded", + givenRequestBody: `{"bidders":["appnexus"], "coopSync": true, "limit": 10, "account": "test_account"}`, + givenAccountPriorityGroups: [][]string{ + {"rubicon"}, + }, + givenAccountDefaultCoopSync: ptrutil.ToPtr(true), + givenAccountPriorityGroupsOnly: ptrutil.ToPtr(true), + givenGlobalPriorityGroups: [][]string{{"ignored"}}, + givenCooperativeEnabledByDef: false, + shouldContainBidders: []string{"appnexus", "rubicon"}, + shouldNotContainBidders: []string{"pubmatic"}, + }, + { + description: "Priority groups only false — remaining bidders included", + givenRequestBody: `{"bidders":["appnexus"], "coopSync": true, "limit": 10, "account": "test_account"}`, + givenAccountPriorityGroups: [][]string{ + {"rubicon"}, + }, + givenAccountDefaultCoopSync: ptrutil.ToPtr(true), + givenAccountPriorityGroupsOnly: ptrutil.ToPtr(false), + givenGlobalPriorityGroups: [][]string{{"ignored"}}, + givenCooperativeEnabledByDef: false, + shouldContainBidders: []string{"appnexus", "rubicon", "pubmatic"}, + }, } for _, tc := range testCases { @@ -2784,7 +2781,7 @@ func TestCookieSyncPriorityGroupsIntegration(t *testing.T) { &mockAnalytics, &FakeAccountsFetcher{ AccountData: map[string]json.RawMessage{ - "test_account": createAccountJSON(tc.givenAccountPriorityGroups, tc.givenAccountDefaultCoopSync), + "test_account": createAccountJSON(tc.givenAccountPriorityGroups, tc.givenAccountDefaultCoopSync, tc.givenAccountPriorityGroupsOnly), }, }, bidders, @@ -2814,6 +2811,11 @@ func TestCookieSyncPriorityGroupsIntegration(t *testing.T) { for _, expected := range tc.shouldContainBidders { assert.Contains(t, actualBidders, expected, "Expected bidder %s to be present in response", expected) } + + // Check that excluded bidders are not present + for _, excluded := range tc.shouldNotContainBidders { + assert.NotContains(t, actualBidders, excluded, "Bidder %s should not be present in response", excluded) + } }) } } @@ -2957,7 +2959,7 @@ func TestCookieSyncPriorityGroupsEdgeCases(t *testing.T) { &mockAnalytics, &FakeAccountsFetcher{ AccountData: map[string]json.RawMessage{ - "test_account": createAccountJSON(tc.givenAccountPriorityGroups, tc.givenAccountDefaultCoopSync), + "test_account": createAccountJSON(tc.givenAccountPriorityGroups, tc.givenAccountDefaultCoopSync, nil), }, }, bidders, diff --git a/usersync/bidderchooser.go b/usersync/bidderchooser.go index f8f40773519..ba79c7977cc 100644 --- a/usersync/bidderchooser.go +++ b/usersync/bidderchooser.go @@ -39,7 +39,6 @@ func (c standardBidderChooser) chooseCooperative(requested, available []string, bidders = c.shuffledAppend(bidders, group) } - // available — only if NOT priority_groups_only if !cooperative.PriorityGroupsOnly { bidders = c.shuffledAppend(bidders, available) }