@@ -56,7 +56,7 @@ void teardown() throws Exception {
5656 }
5757
5858 @ Test
59- void rotateSaltsLastSnapshotIsUpToDate () throws Exception {
59+ void testRotateSaltsLastSnapshotIsUpToDate () throws Exception {
6060 final Duration [] minAges = {
6161 Duration .ofDays (1 ),
6262 Duration .ofDays (2 ),
@@ -74,7 +74,7 @@ void rotateSaltsLastSnapshotIsUpToDate() throws Exception {
7474 }
7575
7676 @ Test
77- void rotateSaltsAllSaltsUpToDate () throws Exception {
77+ void testRotateSaltsAllSaltsUpToDate () throws Exception {
7878 final Duration [] minAges = {
7979 Duration .ofDays (1 ),
8080 Duration .ofDays (2 ),
@@ -90,7 +90,7 @@ void rotateSaltsAllSaltsUpToDate() throws Exception {
9090 }
9191
9292 @ Test
93- void rotateSaltsAllSaltsOld () throws Exception {
93+ void testRotateSaltsAllSaltsOld () throws Exception {
9494 final Duration [] minAges = {
9595 Duration .ofDays (1 ),
9696 Duration .ofDays (2 ),
@@ -110,7 +110,7 @@ void rotateSaltsAllSaltsOld() throws Exception {
110110 }
111111
112112 @ Test
113- void rotateSaltsRotateSaltsFromOldestBucketOnly () throws Exception {
113+ void testRotateSaltsRotateSaltsFromOldestBucketOnly () throws Exception {
114114 final Duration [] minAges = {
115115 Duration .ofDays (5 ),
116116 Duration .ofDays (4 ),
@@ -135,7 +135,7 @@ void rotateSaltsRotateSaltsFromOldestBucketOnly() throws Exception {
135135 }
136136
137137 @ Test
138- void rotateSaltsRotateSaltsFromNewerBucketOnly () throws Exception {
138+ void testRotateSaltsRotateSaltsFromNewerBucketOnly () throws Exception {
139139 final Duration [] minAges = {
140140 Duration .ofDays (5 ),
141141 Duration .ofDays (3 ),
@@ -158,7 +158,7 @@ void rotateSaltsRotateSaltsFromNewerBucketOnly() throws Exception {
158158 }
159159
160160 @ Test
161- void rotateSaltsRotateSaltsFromMultipleBuckets () throws Exception {
161+ void testRotateSaltsRotateSaltsFromMultipleBuckets () throws Exception {
162162 final Duration [] minAges = {
163163 Duration .ofDays (5 ),
164164 Duration .ofDays (4 ),
@@ -183,7 +183,7 @@ void rotateSaltsRotateSaltsFromMultipleBuckets() throws Exception {
183183 }
184184
185185 @ Test
186- void rotateSaltsRotateSaltsInsufficientOutdatedSalts () throws Exception {
186+ void testRotateSaltsRotateSaltsInsufficientOutdatedSalts () throws Exception {
187187 final Duration [] minAges = {
188188 Duration .ofDays (5 ),
189189 Duration .ofDays (3 ),
@@ -232,7 +232,7 @@ void testRefreshFromCalculation(int lastRotationDaysAgo, int lastRotationMsOffse
232232 }
233233
234234 @ Test
235- void rotateSaltsPopulatePreviousSaltsOnRotation () throws Exception {
235+ void testRotateSaltsPopulatePreviousSaltsOnRotation () throws Exception {
236236 final Duration [] minAges = {
237237 Duration .ofDays (90 ),
238238 Duration .ofDays (60 ),
@@ -260,7 +260,7 @@ void rotateSaltsPopulatePreviousSaltsOnRotation() throws Exception {
260260 }
261261
262262 @ Test
263- void rotateSaltsPreservePreviousSaltsLessThan90DaysOld () throws Exception {
263+ void testRotateSaltsPreservePreviousSaltsLessThan90DaysOld () throws Exception {
264264 final Duration [] minAges = {
265265 Duration .ofDays (60 ),
266266 };
@@ -285,7 +285,7 @@ void rotateSaltsPreservePreviousSaltsLessThan90DaysOld() throws Exception {
285285 }
286286
287287 @ Test
288- void rotateSaltsRemovePreviousSaltsOver90DaysOld () throws Exception {
288+ void testRotateSaltsRemovePreviousSaltsOver90DaysOld () throws Exception {
289289 final Duration [] minAges = {
290290 Duration .ofDays (100 ),
291291 };
@@ -309,9 +309,8 @@ void rotateSaltsRemovePreviousSaltsOver90DaysOld() throws Exception {
309309 assertNull (salts [1 ].previousSalt ());
310310 }
311311
312-
313312 @ Test
314- void rotateSaltsRotateWhenRefreshFromIsTargetDate () throws Exception {
313+ void testRotateSaltsRotateWhenRefreshFromIsTargetDate () throws Exception {
315314 JsonObject config = new JsonObject ();
316315 config .put (AdminConst .ENABLE_SALT_ROTATION_REFRESH_FROM , Boolean .TRUE );
317316 saltRotation = new SaltRotation (config , keyGenerator );
@@ -351,35 +350,40 @@ void rotateSaltsRotateWhenRefreshFromIsTargetDate() throws Exception {
351350 }
352351
353352 @ Test
354- void logsSaltAgesOnRotation () throws Exception {
353+ void testLogFewSaltAgesOnRotation () throws Exception {
355354 JsonObject config = new JsonObject ();
356355 config .put (AdminConst .ENABLE_SALT_ROTATION_REFRESH_FROM , Boolean .TRUE );
357356 saltRotation = new SaltRotation (config , keyGenerator );
358357
358+ // 7 salts total, 5 refreshable, 3 will rotate (6 * 0.4 rounded up), up to 2 will rotate per age (3 * 0.8)
359359 var lastSnapshot = SaltSnapshotBuilder .start ()
360360 .entries (
361- // 5 salts total, 3 refreshable, 2 rotated given 40% fraction
362- SaltBuilder .start ().lastUpdated (daysEarlier (65 )).refreshFrom (targetDate ()), // Refreshable, old enough, rotated
361+ SaltBuilder .start ().lastUpdated (daysEarlier (65 )).refreshFrom (targetDate ()), // Refreshable, old enough
363362 SaltBuilder .start ().lastUpdated (daysEarlier (5 )).refreshFrom (targetDate ()), // Refreshable, too new
363+ SaltBuilder .start ().lastUpdated (daysEarlier (33 )).refreshFrom (targetDate ()), // Refreshable, old enough
364364 SaltBuilder .start ().lastUpdated (daysEarlier (50 )).refreshFrom (daysLater (1 )), // Not refreshable, old enough
365- SaltBuilder .start ().lastUpdated (daysEarlier (65 )).refreshFrom (targetDate ()), // Refreshable, old enough, rotated
365+ SaltBuilder .start ().lastUpdated (daysEarlier (65 )).refreshFrom (targetDate ()), // Refreshable, old enough
366+ SaltBuilder .start ().lastUpdated (daysEarlier (65 )).refreshFrom (targetDate ()), // Refreshable, old enough
366367 SaltBuilder .start ().lastUpdated (daysEarlier (10 )).refreshFrom (daysLater (10 )) // Not refreshable, too new
367368 )
368369 .build ();
369370
370371 var expected = Set .of (
371372 "[INFO] Salt rotation complete target_date=2025-01-01" ,
372373 // Post-rotation ages, we want to look at current state
373- "[INFO] salt_count_type=total-salts target_date=2025-01-01 age=0 salt_count=2" , // The two rotated salts, used to be 65 and 50 days old
374+ "[INFO] salt_count_type=total-salts target_date=2025-01-01 age=0 salt_count=3" ,
374375 "[INFO] salt_count_type=total-salts target_date=2025-01-01 age=5 salt_count=1" ,
375376 "[INFO] salt_count_type=total-salts target_date=2025-01-01 age=10 salt_count=1" ,
376377 "[INFO] salt_count_type=total-salts target_date=2025-01-01 age=50 salt_count=1" ,
378+ "[INFO] salt_count_type=total-salts target_date=2025-01-01 age=65 salt_count=1" ,
377379
378380 // Pre-rotation ages, we want to see at which ages salts become refreshable, post rotation some will be 0
379381 "[INFO] salt_count_type=refreshable-salts target_date=2025-01-01 age=5 salt_count=1" ,
380- "[INFO] salt_count_type=refreshable-salts target_date=2025-01-01 age=65 salt_count=2" ,
382+ "[INFO] salt_count_type=refreshable-salts target_date=2025-01-01 age=33 salt_count=1" ,
383+ "[INFO] salt_count_type=refreshable-salts target_date=2025-01-01 age=65 salt_count=3" ,
381384
382385 // Pre-rotation ages, post rotation they will all have age 0
386+ "[INFO] salt_count_type=rotated-salts target_date=2025-01-01 age=33 salt_count=1" ,
383387 "[INFO] salt_count_type=rotated-salts target_date=2025-01-01 age=65 salt_count=2"
384388 );
385389
@@ -390,12 +394,53 @@ void logsSaltAgesOnRotation() throws Exception {
390394 assertThat (actual ).isEqualTo (expected );
391395 }
392396
397+ @ Test
398+ void testLogManySaltAgesOnRotation () throws Exception {
399+ JsonObject config = new JsonObject ();
400+ config .put (AdminConst .ENABLE_SALT_ROTATION_REFRESH_FROM , Boolean .TRUE );
401+ saltRotation = new SaltRotation (config , keyGenerator );
402+
403+ // 50 salts total, 16 refreshable, 10 will rotate (18 * 0.2 rounded up), up to 8 will rotate per age (10 * 0.8)
404+ var lastSnapshot = SaltSnapshotBuilder .start ()
405+ .entries (10 , daysEarlier (5 ), targetDate ()) // Refreshable, too new
406+ .entries (10 , daysEarlier (10 ), daysLater (10 )) // Not refreshable, too new
407+ .entries (10 , daysEarlier (33 ), targetDate ()) // Refreshable, old enough
408+ .entries (10 , daysEarlier (50 ), daysLater (1 )) // Not refreshable, old enough
409+ .entries (10 , daysEarlier (65 ), targetDate ()) // Refreshable, old enough
410+ .build ();
411+
412+ var expected = Set .of (
413+ "[INFO] Salt rotation complete target_date=2025-01-01" ,
414+ // Post-rotation ages, we want to look at current state
415+ "[INFO] salt_count_type=total-salts target_date=2025-01-01 age=0 salt_count=10" ,
416+ "[INFO] salt_count_type=total-salts target_date=2025-01-01 age=5 salt_count=10" ,
417+ "[INFO] salt_count_type=total-salts target_date=2025-01-01 age=10 salt_count=10" ,
418+ "[INFO] salt_count_type=total-salts target_date=2025-01-01 age=33 salt_count=8" ,
419+ "[INFO] salt_count_type=total-salts target_date=2025-01-01 age=50 salt_count=10" ,
420+ "[INFO] salt_count_type=total-salts target_date=2025-01-01 age=65 salt_count=2" ,
421+
422+ // Pre-rotation ages, we want to see at which ages salts become refreshable, post rotation some will be 0
423+ "[INFO] salt_count_type=refreshable-salts target_date=2025-01-01 age=5 salt_count=10" ,
424+ "[INFO] salt_count_type=refreshable-salts target_date=2025-01-01 age=33 salt_count=10" ,
425+ "[INFO] salt_count_type=refreshable-salts target_date=2025-01-01 age=65 salt_count=10" ,
426+
427+ // Pre-rotation ages, post rotation they will all have age 0
428+ "[INFO] salt_count_type=rotated-salts target_date=2025-01-01 age=33 salt_count=2" ,
429+ "[INFO] salt_count_type=rotated-salts target_date=2025-01-01 age=65 salt_count=8"
430+ );
431+
432+ var minAges = new Duration []{Duration .ofDays (30 ), Duration .ofDays (60 )};
433+ saltRotation .rotateSalts (lastSnapshot , minAges , 0.2 , targetDate ());
434+
435+ var actual = appender .list .stream ().map (Object ::toString ).collect (Collectors .toSet ());
436+ assertThat (actual ).isEqualTo (expected );
437+ }
438+
393439 private int countEntriesWithLastUpdated (SaltEntry [] entries , TargetDate lastUpdated ) {
394440 return countEntriesWithLastUpdated (entries , lastUpdated .asInstant ());
395441 }
396442
397443 private int countEntriesWithLastUpdated (SaltEntry [] entries , Instant lastUpdated ) {
398444 return (int ) Arrays .stream (entries ).filter (e -> e .lastUpdated () == lastUpdated .toEpochMilli ()).count ();
399445 }
400-
401446}
0 commit comments