11package app .coronawarn .server .common .persistence .service ;
22
3+ import static org .assertj .core .api .Assertions .assertThat ;
4+ import static org .assertj .core .api .Assertions .assertThatCode ;
5+ import static org .assertj .core .api .Assertions .catchThrowable ;
6+ import static org .junit .Assert .assertArrayEquals ;
7+ import static org .junit .Assert .assertEquals ;
8+
39import app .coronawarn .server .common .persistence .domain .TraceTimeIntervalWarning ;
410import app .coronawarn .server .common .persistence .repository .TraceTimeIntervalWarningRepository ;
511import app .coronawarn .server .common .persistence .service .utils .checkins .CheckinsDateSpecification ;
612import app .coronawarn .server .common .protocols .internal .pt .CheckIn ;
713import com .google .protobuf .ByteString ;
8- import org .junit .jupiter .api .BeforeEach ;
9- import org .junit .jupiter .api .Test ;
10- import org .springframework .beans .factory .annotation .Autowired ;
11- import org .springframework .boot .test .autoconfigure .data .jdbc .DataJdbcTest ;
12- import org .testcontainers .shaded .org .bouncycastle .util .encoders .Hex ;
1314import java .security .MessageDigest ;
1415import java .security .NoSuchAlgorithmException ;
1516import java .security .SecureRandom ;
1617import java .time .Instant ;
17- import java .util .ArrayList ;
18+ import java .util .Collection ;
1819import java .util .Collections ;
1920import java .util .Comparator ;
2021import java .util .List ;
22+ import java .util .concurrent .TimeUnit ;
2123import java .util .stream .Collectors ;
2224import java .util .stream .StreamSupport ;
23-
24- import static org .junit .Assert .*;
25+ import org .junit .jupiter .api .BeforeEach ;
26+ import org .junit .jupiter .api .DisplayName ;
27+ import org .junit .jupiter .api .Test ;
28+ import org .junit .jupiter .params .ParameterizedTest ;
29+ import org .junit .jupiter .params .provider .ValueSource ;
30+ import org .springframework .beans .factory .annotation .Autowired ;
31+ import org .springframework .boot .test .autoconfigure .data .jdbc .DataJdbcTest ;
32+ import org .testcontainers .shaded .org .bouncycastle .util .encoders .Hex ;
2533
2634@ DataJdbcTest
2735class TraceTimeIntervalWarningServiceTest {
@@ -32,70 +40,35 @@ class TraceTimeIntervalWarningServiceTest {
3240 @ Autowired
3341 TraceTimeIntervalWarningRepository traceWarningsRepository ;
3442
43+ private int currentTimestamp ;
44+
3545 @ BeforeEach
3646 public void setup () {
3747 traceWarningsRepository .deleteAll ();
48+ currentTimestamp = CheckinsDateSpecification .HOUR_SINCE_EPOCH_DERIVATION .apply (Instant .now ().getEpochSecond ());
3849 }
3950
4051 @ Test
4152 void testStorage () {
4253 List <CheckIn > checkins = getRandomTestData ();
43- traceWarningsService .saveCheckins (checkins );
54+ traceWarningsService .saveCheckins (checkins , currentTimestamp );
4455
4556 List <TraceTimeIntervalWarning > actualTraceWarningsStored =
4657 StreamSupport .stream (traceWarningsRepository .findAll ().spliterator (), false )
4758 .collect (Collectors .toList ());
4859
49- assertCheckinsAndWarningsAreEqual (new ArrayList <>( checkins ) , actualTraceWarningsStored );
60+ assertCheckinsAndWarningsAreEqual (checkins , actualTraceWarningsStored );
5061 }
5162
5263 @ Test
5364 void testStorageWithRandomPadding () {
5465 List <CheckIn > checkins = getRandomTestData ();
55- traceWarningsService .saveCheckinsWithFakeData (checkins , 2 , randomHashPepper ());
66+ traceWarningsService .saveCheckinsWithFakeData (checkins , 2 , randomHashPepper (), currentTimestamp );
5667
5768 List <TraceTimeIntervalWarning > actualTraceWarningsStored =
5869 StreamSupport .stream (traceWarningsRepository .findAll ().spliterator (), false )
5970 .collect (Collectors .toList ());
60- assertTrue (actualTraceWarningsStored .size () == checkins .size () + checkins .size () * 2 );
61- }
62-
63- private List <CheckIn > getRandomTestData () {
64- List <CheckIn > checkins = List .of (
65- CheckIn .newBuilder ().setStartIntervalNumber (0 ).setEndIntervalNumber (1 )
66- .setTransmissionRiskLevel (1 )
67- .setLocationId (ByteString .copyFromUtf8 ("uuid1" ))
68- .build (),
69- CheckIn .newBuilder ().setStartIntervalNumber (23 ).setEndIntervalNumber (30 )
70- .setTransmissionRiskLevel (2 )
71- .setLocationId (ByteString .copyFromUtf8 ("uuid1" ))
72- .build (),
73- CheckIn .newBuilder ().setStartIntervalNumber (40 ).setEndIntervalNumber (50 )
74- .setTransmissionRiskLevel (3 )
75- .setLocationId (ByteString .copyFromUtf8 ("uuid1" ))
76- .build ());
77- return checkins ;
78- }
79-
80- private void assertCheckinsAndWarningsAreEqual (List <CheckIn > checkins ,
81- List <TraceTimeIntervalWarning > actualTraceWarningsStored ) {
82-
83- assertEquals (checkins .size (), actualTraceWarningsStored .size ());
84-
85- Collections .sort (checkins , Comparator .comparing (CheckIn ::getTransmissionRiskLevel ));
86- Collections .sort (actualTraceWarningsStored ,
87- Comparator .comparing (TraceTimeIntervalWarning ::getTransmissionRiskLevel ));
88-
89- for (int i = 0 ; i < checkins .size (); i ++) {
90- CheckIn checkin = checkins .get (i );
91- TraceTimeIntervalWarning warning = actualTraceWarningsStored .get (i );
92- assertEquals (checkin .getTransmissionRiskLevel (),
93- warning .getTransmissionRiskLevel ().intValue ());
94- assertEquals (checkin .getStartIntervalNumber (), warning .getStartIntervalNumber ().intValue ());
95- assertEquals (checkin .getEndIntervalNumber () - checkin .getStartIntervalNumber (), warning .getPeriod ().intValue ());
96- assertArrayEquals (hashLocationId (checkin .getLocationId ()),
97- warning .getTraceLocationId ());
98- }
71+ assertEquals (actualTraceWarningsStored .size (), checkins .size () + checkins .size () * 2 );
9972 }
10073
10174 @ Test
@@ -115,7 +88,7 @@ void testSortedRetrievalResult() {
11588 CheckinsDateSpecification .HOUR_SINCE_EPOCH_DERIVATION
11689 .apply (Instant .now ().getEpochSecond ()) - 10 );
11790
118- List <CheckIn > checkins = new ArrayList <>(List .of (
91+ List <CheckIn > checkins = new java . util . ArrayList <>(List .of (
11992 CheckIn .newBuilder ().setStartIntervalNumber (56 ).setEndIntervalNumber (66 )
12093 .setTransmissionRiskLevel (3 )
12194 .setLocationId (ByteString .copyFromUtf8 ("sorted-uuid2" ))
@@ -128,8 +101,7 @@ void testSortedRetrievalResult() {
128101 // Reverse as we tempered with submission timestamp
129102 Collections .reverse (checkins );
130103
131- List <TraceTimeIntervalWarning > checkinsFromDB = new ArrayList <>(
132- traceWarningsService .getTraceTimeIntervalWarnings ());
104+ var checkinsFromDB = traceWarningsService .getTraceTimeIntervalWarnings ();
133105
134106 assertCheckinsAndWarningsAreEqual (checkins , checkinsFromDB );
135107 }
@@ -149,11 +121,95 @@ public void testHashingOfTraceLocationId() {
149121 assertEquals ("0f37dac11d1b8118ea0b44303400faa5e3b876da9d758058b5ff7dc2e5da8230" , s );
150122 }
151123
124+ @ DisplayName ("Assert a positive retention period is accepted." )
125+ @ ValueSource (ints = {0 , 1 , Integer .MAX_VALUE })
126+ @ ParameterizedTest
127+ void testApplyRetentionPolicyForValidNumberOfDays (int daysToRetain ) {
128+ assertThatCode (() -> traceWarningsService .applyRetentionPolicy (daysToRetain ))
129+ .doesNotThrowAnyException ();
130+ }
131+
132+ @ DisplayName ("Assert a negative retention period is rejected." )
133+ @ ValueSource (ints = {Integer .MIN_VALUE , -1 })
134+ @ ParameterizedTest
135+ void testApplyRetentionPolicyForNegativeNumberOfDays (int daysToRetain ) {
136+ assertThat (catchThrowable (() -> traceWarningsService .applyRetentionPolicy (daysToRetain )))
137+ .isInstanceOf (IllegalArgumentException .class );
138+ }
139+
140+ @ Test
141+ void testApplyRetentionPolicyForEmptyDb () {
142+ traceWarningsService .applyRetentionPolicy (1 );
143+ var actKeys = traceWarningsService .getTraceTimeIntervalWarnings ();
144+ assertThat (actKeys ).isEmpty ();
145+ }
146+
147+ @ Test
148+ void testApplyRetentionPolicyForNotApplicableEntries () {
149+ var expKeys = getRandomTestData ();
150+
151+ traceWarningsService .saveCheckins (expKeys , currentTimestamp );
152+ traceWarningsService .applyRetentionPolicy (1 );
153+ var actKeys = traceWarningsService .getTraceTimeIntervalWarnings ();
154+
155+ assertCheckinsAndWarningsAreEqual (expKeys , actKeys );
156+ }
157+
158+ @ Test
159+ void testApplyRetentionPolicyForOneApplicableEntry () {
160+ var keys = getRandomTestData ();
161+
162+ traceWarningsService .saveCheckins (keys , currentTimestamp - (int ) TimeUnit .DAYS .toHours (1 ) - 1 );
163+ traceWarningsService .applyRetentionPolicy (1 );
164+ var actKeys = traceWarningsService .getTraceTimeIntervalWarnings ();
165+
166+ assertThat (actKeys ).isEmpty ();
167+ }
168+
169+ private List <CheckIn > getRandomTestData () {
170+ return List .of (
171+ CheckIn .newBuilder ().setStartIntervalNumber (0 ).setEndIntervalNumber (1 )
172+ .setTransmissionRiskLevel (1 )
173+ .setLocationId (ByteString .copyFromUtf8 ("uuid1" ))
174+ .build (),
175+ CheckIn .newBuilder ().setStartIntervalNumber (23 ).setEndIntervalNumber (30 )
176+ .setTransmissionRiskLevel (2 )
177+ .setLocationId (ByteString .copyFromUtf8 ("uuid1" ))
178+ .build (),
179+ CheckIn .newBuilder ().setStartIntervalNumber (40 ).setEndIntervalNumber (50 )
180+ .setTransmissionRiskLevel (3 )
181+ .setLocationId (ByteString .copyFromUtf8 ("uuid1" ))
182+ .build ());
183+ }
184+
185+ private void assertCheckinsAndWarningsAreEqual (Collection <CheckIn > checkins ,
186+ Collection <TraceTimeIntervalWarning > actualTraceWarningsStored ) {
187+
188+ assertEquals (checkins .size (), actualTraceWarningsStored .size ());
189+
190+ var sortedCheckins = checkins .stream ()
191+ .sorted (Comparator .comparing (CheckIn ::getTransmissionRiskLevel ))
192+ .collect (Collectors .toList ());
193+ var sortedTraceTimeWarnings = actualTraceWarningsStored .stream ()
194+ .sorted (Comparator .comparing (TraceTimeIntervalWarning ::getTransmissionRiskLevel ))
195+ .collect (Collectors .toList ());
196+
197+ for (int i = 0 ; i < checkins .size (); i ++) {
198+ CheckIn checkin = sortedCheckins .get (i );
199+ TraceTimeIntervalWarning warning = sortedTraceTimeWarnings .get (i );
200+ assertEquals (checkin .getTransmissionRiskLevel (),
201+ warning .getTransmissionRiskLevel ().intValue ());
202+ assertEquals (checkin .getStartIntervalNumber (), warning .getStartIntervalNumber ().intValue ());
203+ assertEquals (checkin .getEndIntervalNumber () - checkin .getStartIntervalNumber (), warning .getPeriod ().intValue ());
204+ assertArrayEquals (hashLocationId (checkin .getLocationId ()),
205+ warning .getTraceLocationId ());
206+ }
207+ }
152208
153209 private byte [] hashLocationId (ByteString locationId ) {
154210 try {
155211 return MessageDigest .getInstance ("SHA-256" ).digest (locationId .toByteArray ());
156- } catch (NoSuchAlgorithmException e ) {
212+ } catch (NoSuchAlgorithmException ignored ) {
157213 }
158214 return new byte [0 ];
159215 }
0 commit comments