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 }