github.com/prebid/prebid-server/v2@v2.18.0/usersync/ejector_test.go (about)

     1  package usersync
     2  
     3  import (
     4  	"errors"
     5  	"reflect"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  func TestPriorityEjector(t *testing.T) {
    13  	testCases := []struct {
    14  		name          string
    15  		givenUids     map[string]UIDEntry
    16  		givenEjector  Ejector
    17  		expected      string
    18  		expectedError error
    19  	}{
    20  		{
    21  			name: "one-lowest-priority-element",
    22  			givenUids: map[string]UIDEntry{
    23  				"highestPrioritySyncer": {
    24  					UID:     "123",
    25  					Expires: time.Now().Add((90 * 24 * time.Hour)),
    26  				},
    27  				"lowestPriority": {
    28  					UID:     "456",
    29  					Expires: time.Now(),
    30  				},
    31  			},
    32  			givenEjector: &PriorityBidderEjector{
    33  				PriorityGroups: [][]string{
    34  					{"highestPriorityBidder"},
    35  					{"lowestPriority"},
    36  				},
    37  				SyncersByBidder: map[string]Syncer{
    38  					"highestPriorityBidder": fakeSyncer{
    39  						key: "highestPrioritySyncer",
    40  					},
    41  					"lowestPriority": fakeSyncer{
    42  						key: "lowestPriority",
    43  					},
    44  				},
    45  				IsSyncerPriority: true,
    46  			},
    47  			expected: "lowestPriority",
    48  		},
    49  		{
    50  			name: "multiple-uids-same-priority",
    51  			givenUids: map[string]UIDEntry{
    52  				"newerButSamePriority": {
    53  					UID:     "123",
    54  					Expires: time.Now().Add((90 * 24 * time.Hour)),
    55  				},
    56  				"olderButSamePriority": {
    57  					UID:     "456",
    58  					Expires: time.Now(),
    59  				},
    60  			},
    61  			givenEjector: &PriorityBidderEjector{
    62  				PriorityGroups: [][]string{
    63  					{"newerButSamePriority", "olderButSamePriority"},
    64  				},
    65  				SyncersByBidder: map[string]Syncer{
    66  					"newerButSamePriority": fakeSyncer{
    67  						key: "newerButSamePriority",
    68  					},
    69  					"olderButSamePriority": fakeSyncer{
    70  						key: "olderButSamePriority",
    71  					},
    72  				},
    73  				IsSyncerPriority: true,
    74  				TieEjector:       &OldestEjector{},
    75  			},
    76  			expected: "olderButSamePriority",
    77  		},
    78  		{
    79  			name: "non-priority-uids-present",
    80  			givenUids: map[string]UIDEntry{
    81  				"higherPriority": {
    82  					UID:     "123",
    83  					Expires: time.Now().Add((90 * 24 * time.Hour)),
    84  				},
    85  				"lowestPriority": {
    86  					UID:     "456",
    87  					Expires: time.Now(),
    88  				},
    89  				"oldestNonPriority": {
    90  					UID:     "456",
    91  					Expires: time.Now(),
    92  				},
    93  				"newestNonPriority": {
    94  					UID:     "123",
    95  					Expires: time.Now().Add((90 * 24 * time.Hour)),
    96  				},
    97  			},
    98  			givenEjector: &PriorityBidderEjector{
    99  				PriorityGroups: [][]string{
   100  					{"higherPriority"},
   101  					{"lowestPriority"},
   102  				},
   103  				SyncersByBidder: map[string]Syncer{
   104  					"higherPriority": fakeSyncer{
   105  						key: "higherPriority",
   106  					},
   107  					"lowestPriority": fakeSyncer{
   108  						key: "lowestPriority",
   109  					},
   110  					"oldestNonPriority": fakeSyncer{
   111  						key: "oldestNonPriority",
   112  					},
   113  					"newestNonPriority": fakeSyncer{
   114  						key: "newestNonPriority",
   115  					},
   116  				},
   117  				IsSyncerPriority: true,
   118  				TieEjector:       &OldestEjector{},
   119  			},
   120  			expected: "oldestNonPriority",
   121  		},
   122  		{
   123  			name: "empty-priority-groups",
   124  			givenUids: map[string]UIDEntry{
   125  				"oldestNonPriority": {
   126  					UID:     "456",
   127  					Expires: time.Now(),
   128  				},
   129  				"newestNonPriority": {
   130  					UID:     "123",
   131  					Expires: time.Now().Add((90 * 24 * time.Hour)),
   132  				},
   133  			},
   134  			givenEjector: &PriorityBidderEjector{
   135  				SyncersByBidder: map[string]Syncer{
   136  					"oldestNonPriority": fakeSyncer{
   137  						key: "oldestNonPriority",
   138  					},
   139  					"newestNonPriority": fakeSyncer{
   140  						key: "newestNonPriority",
   141  					},
   142  				},
   143  				IsSyncerPriority: false,
   144  				TieEjector:       &OldestEjector{},
   145  			},
   146  			expected: "oldestNonPriority",
   147  		},
   148  		{
   149  			name: "one-priority-element",
   150  			givenUids: map[string]UIDEntry{
   151  				"onlyPriorityElement": {
   152  					UID:     "123",
   153  					Expires: time.Now().Add((90 * 24 * time.Hour)),
   154  				},
   155  			},
   156  			givenEjector: &PriorityBidderEjector{
   157  				PriorityGroups: [][]string{
   158  					{"onlyPriorityElement"},
   159  				},
   160  				SyncersByBidder: map[string]Syncer{
   161  					"onlyPriorityElement": fakeSyncer{
   162  						key: "onlyPriorityElement",
   163  					},
   164  				},
   165  				IsSyncerPriority: true,
   166  			},
   167  			expected: "onlyPriorityElement",
   168  		},
   169  		{
   170  			name: "syncer-is-not-priority",
   171  			givenUids: map[string]UIDEntry{
   172  				"onlyPriorityElement": {
   173  					UID:     "123",
   174  					Expires: time.Now().Add((90 * 24 * time.Hour)),
   175  				},
   176  				"syncer": {
   177  					UID:     "456",
   178  					Expires: time.Now().Add((90 * 24 * time.Hour)),
   179  				},
   180  			},
   181  			givenEjector: &PriorityBidderEjector{
   182  				PriorityGroups: [][]string{
   183  					{"onlyPriorityElement"},
   184  				},
   185  				SyncersByBidder: map[string]Syncer{
   186  					"onlyPriorityElement": fakeSyncer{
   187  						key: "onlyPriorityElement",
   188  					},
   189  				},
   190  				IsSyncerPriority: false,
   191  			},
   192  			expectedError: errors.New("syncer key is not a priority, and there are only priority elements left"),
   193  		},
   194  	}
   195  
   196  	for _, test := range testCases {
   197  		t.Run(test.name, func(t *testing.T) {
   198  			uidToDelete, err := test.givenEjector.Choose(test.givenUids)
   199  			if test.expectedError != nil {
   200  				assert.Equal(t, test.expectedError, err)
   201  			} else {
   202  				assert.NoError(t, err)
   203  				assert.Equal(t, test.expected, uidToDelete)
   204  			}
   205  		})
   206  	}
   207  }
   208  
   209  func TestOldestEjector(t *testing.T) {
   210  	testCases := []struct {
   211  		name      string
   212  		givenUids map[string]UIDEntry
   213  		expected  string
   214  	}{
   215  		{
   216  			name: "multiple-elements",
   217  			givenUids: map[string]UIDEntry{
   218  				"newestElement": {
   219  					UID:     "123",
   220  					Expires: time.Now().Add((90 * 24 * time.Hour)),
   221  				},
   222  				"oldestElement": {
   223  					UID:     "456",
   224  					Expires: time.Now(),
   225  				},
   226  			},
   227  			expected: "oldestElement",
   228  		},
   229  		{
   230  			name: "one-element",
   231  			givenUids: map[string]UIDEntry{
   232  				"onlyElement": {
   233  					UID:     "123",
   234  					Expires: time.Now().Add((90 * 24 * time.Hour)),
   235  				},
   236  			},
   237  			expected: "onlyElement",
   238  		},
   239  		{
   240  			name:      "no-elements",
   241  			givenUids: map[string]UIDEntry{},
   242  			expected:  "",
   243  		},
   244  	}
   245  
   246  	for _, test := range testCases {
   247  		t.Run(test.name, func(t *testing.T) {
   248  			ejector := OldestEjector{}
   249  			oldestElement, err := ejector.Choose(test.givenUids)
   250  			assert.NoError(t, err)
   251  			assert.Equal(t, test.expected, oldestElement)
   252  		})
   253  	}
   254  }
   255  
   256  func TestGetNonPriorityUids(t *testing.T) {
   257  	syncersByBidder := map[string]Syncer{
   258  		"syncerKey1": fakeSyncer{
   259  			key: "syncerKey1",
   260  		},
   261  		"syncerKey2": fakeSyncer{
   262  			key: "syncerKey2",
   263  		},
   264  		"syncerKey3": fakeSyncer{
   265  			key: "syncerKey3",
   266  		},
   267  	}
   268  
   269  	testCases := []struct {
   270  		name                string
   271  		givenUids           map[string]UIDEntry
   272  		givenPriorityGroups [][]string
   273  		expected            map[string]UIDEntry
   274  	}{
   275  		{
   276  			name: "one-priority-group",
   277  			givenUids: map[string]UIDEntry{
   278  				"syncerKey1": {
   279  					UID: "123",
   280  				},
   281  				"syncerKey2": {
   282  					UID: "456",
   283  				},
   284  				"syncerKey3": {
   285  					UID: "789",
   286  				},
   287  			},
   288  			givenPriorityGroups: [][]string{
   289  				{"syncerKey1"},
   290  			},
   291  			expected: map[string]UIDEntry{
   292  				"syncerKey2": {
   293  					UID: "456",
   294  				},
   295  				"syncerKey3": {
   296  					UID: "789",
   297  				},
   298  			},
   299  		},
   300  		{
   301  			name: "multiple-priority-groups",
   302  			givenUids: map[string]UIDEntry{
   303  				"syncerKey1": {
   304  					UID: "123",
   305  				},
   306  				"syncerKey2": {
   307  					UID: "456",
   308  				},
   309  				"syncerKey3": {
   310  					UID: "789",
   311  				},
   312  			},
   313  			givenPriorityGroups: [][]string{
   314  				{"syncerKey1"},
   315  				{"syncerKey2"},
   316  			},
   317  			expected: map[string]UIDEntry{
   318  				"syncerKey3": {
   319  					UID: "789",
   320  				},
   321  			},
   322  		},
   323  		{
   324  			name: "no-priority-groups",
   325  			givenUids: map[string]UIDEntry{
   326  				"syncerKey1": {
   327  					UID: "123",
   328  				},
   329  				"syncerKey2": {
   330  					UID: "456",
   331  				},
   332  				"syncerKey3": {
   333  					UID: "789",
   334  				},
   335  			},
   336  			expected: map[string]UIDEntry{
   337  				"syncerKey1": {
   338  					UID: "123",
   339  				},
   340  				"syncerKey2": {
   341  					UID: "456",
   342  				},
   343  				"syncerKey3": {
   344  					UID: "789",
   345  				},
   346  			},
   347  		},
   348  	}
   349  
   350  	for _, test := range testCases {
   351  		t.Run(test.name, func(t *testing.T) {
   352  			uids := getNonPriorityUids(test.givenUids, test.givenPriorityGroups, syncersByBidder)
   353  			assert.Equal(t, true, reflect.DeepEqual(test.expected, uids))
   354  		})
   355  	}
   356  }
   357  
   358  func TestGetPriorityUids(t *testing.T) {
   359  	syncersByBidder := map[string]Syncer{
   360  		"syncerKey1": fakeSyncer{
   361  			key: "syncerKey1",
   362  		},
   363  		"syncerKey2": fakeSyncer{
   364  			key: "syncerKey2",
   365  		},
   366  		"syncerKey3": fakeSyncer{
   367  			key: "syncerKey3",
   368  		},
   369  	}
   370  
   371  	testCases := []struct {
   372  		name                     string
   373  		givenUids                map[string]UIDEntry
   374  		givenLowestPriorityGroup []string
   375  		expected                 map[string]UIDEntry
   376  	}{
   377  		{
   378  			name: "one-priority-element",
   379  			givenUids: map[string]UIDEntry{
   380  				"syncerKey1": {
   381  					UID: "123",
   382  				},
   383  				"syncerKey2": {
   384  					UID: "456",
   385  				},
   386  				"syncerKey3": {
   387  					UID: "789",
   388  				},
   389  			},
   390  			givenLowestPriorityGroup: []string{"syncerKey1"},
   391  			expected: map[string]UIDEntry{
   392  				"syncerKey1": {
   393  					UID: "123",
   394  				},
   395  			},
   396  		},
   397  		{
   398  			name: "multiple-priority-elements",
   399  			givenUids: map[string]UIDEntry{
   400  				"syncerKey1": {
   401  					UID: "123",
   402  				},
   403  				"syncerKey2": {
   404  					UID: "456",
   405  				},
   406  				"syncerKey3": {
   407  					UID: "789",
   408  				},
   409  			},
   410  			givenLowestPriorityGroup: []string{"syncerKey1", "syncerKey2"},
   411  			expected: map[string]UIDEntry{
   412  				"syncerKey1": {
   413  					UID: "123",
   414  				},
   415  				"syncerKey2": {
   416  					UID: "456",
   417  				},
   418  			},
   419  		},
   420  		{
   421  			name: "no-priority-elements",
   422  			givenUids: map[string]UIDEntry{
   423  				"syncerKey1": {
   424  					UID: "123",
   425  				},
   426  				"syncerKey2": {
   427  					UID: "456",
   428  				},
   429  				"syncerKey3": {
   430  					UID: "789",
   431  				},
   432  			},
   433  			givenLowestPriorityGroup: []string{},
   434  			expected:                 map[string]UIDEntry{},
   435  		},
   436  	}
   437  
   438  	for _, test := range testCases {
   439  		t.Run(test.name, func(t *testing.T) {
   440  			uids := getPriorityUids(test.givenLowestPriorityGroup, test.givenUids, syncersByBidder)
   441  			assert.Equal(t, true, reflect.DeepEqual(test.expected, uids))
   442  		})
   443  	}
   444  }