Commit d36e56f5 authored by calocedre TAC's avatar calocedre TAC
Browse files

Merge branch 'clea-lib/java/fixes' into 'master'

clea-lib java : small fixes

See merge request !14
parents 848f7cc7 1fb4e89e
Pipeline #229521 passed with stage
in 1 minute and 46 seconds
......@@ -58,6 +58,12 @@
<version>3.19.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.8.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
......
......@@ -50,7 +50,7 @@ public class Location {
*/
public String newDeepLink(int periodStartTime) throws CleaEncryptionException {
// QR-code validity starts at period start time
return this.newDeepLink(periodStartTime * TimeUtils.NB_SECONDS_PER_HOUR);
return this.newDeepLink(periodStartTime, periodStartTime);
}
/**
......@@ -101,6 +101,9 @@ public class Location {
this.locationSpecificPart.setPeriodStartTime(periodStartTime);
this.locationSpecificPart.setLocationTemporarySecretKey(locationTemporarySecretKey);
this.locationSpecificPart.setLocationTemporaryPublicId(currentLocationTemporaryPublicId);
if (Objects.nonNull(this.contact)) {
this.contact.setPeriodStartTime(periodStartTime);
}
log.debug("new periodStartTime: {} ", Integer.toUnsignedString(periodStartTime));
log.debug("locationTemporarySecretKey*: {}*", BytesUtils.bytesToString(locationTemporarySecretKey));
log.debug("locationTemporaryPublicID: " + currentLocationTemporaryPublicId.toString());
......@@ -112,12 +115,21 @@ public class Location {
log.warn("Cannot update QrCode validity start time. No renewal specified!");
return;
}
if(qrCodeValidityStartTime < periodStartTime){
log.warn("Cannot set QrCode validity start time to {}. It preceeds period validity (start: {}, duration (in hours): {}",
qrCodeValidityStartTime, periodStartTime, this.locationSpecificPart.getPeriodDuration());
return;
}
if (qrCodeValidityStartTime > periodStartTime + this.locationSpecificPart.getPeriodDuration() * TimeUtils.NB_SECONDS_PER_HOUR) {
log.warn("Cannot set QrCode validity start time to {}. It exceeds period validity (start: {}, duration (in hours): {}",
qrCodeValidityStartTime, periodStartTime, this.locationSpecificPart.getPeriodDuration());
return;
}
if (((qrCodeValidityStartTime - periodStartTime) % this.locationSpecificPart.getQrCodeRenewalInterval()) != 0) {
if ((this.locationSpecificPart.getQrCodeRenewalInterval() != 0) &&
(((qrCodeValidityStartTime - periodStartTime) % this.locationSpecificPart.getQrCodeRenewalInterval()) != 0)) {
log.warn("Cannot set QrCode validity start time to {}. It is not a multiple of qrCodeRenewalInterval (qrCodeValidityStartTime: {}, periodStartTime: {}, qrCodeRenewalInterval: {}",
qrCodeValidityStartTime, periodStartTime, this.locationSpecificPart.getQrCodeRenewalInterval());
return;
......
......@@ -5,7 +5,9 @@ import javax.validation.constraints.Max;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.AccessLevel;
@Builder
@Getter
......@@ -18,5 +20,6 @@ public class LocationContact {
@Max(value = 6)
String locationPin;
/* Starting time of the period in seconds */
@Setter(AccessLevel.PROTECTED)
int periodStartTime;
}
......@@ -24,7 +24,7 @@ public class TimeUtils {
}
/**
* Get timestamp rounded to the closest hour.
* Get NTP UTC timestamp rounded to the closest hour.
* @param timestamp the timestamp in seconds
* @return the rounded timestamp
*/
......@@ -32,16 +32,34 @@ public class TimeUtils {
long timestampPlusHalfTimeRounding = timestamp + NB_SECONDS_PER_HOUR/2;
return timestampPlusHalfTimeRounding - (timestampPlusHalfTimeRounding % NB_SECONDS_PER_HOUR);
}
/**
* Get NTP UTC timestamp rounded to the closest hour from an Instant
* @param instant timestamp as an Instant
* @return rounded timestamp
*/
public static long hourRoundedTimestampFromInstant(Instant instant){
return hourRoundedTimestamp(instant.getEpochSecond() + SECONDS_FROM_01_01_1900_TO_01_01_1970);
}
/**
* Get NTP UTC timestamp rounded to the closest hour from an Instant limited to 32 bits (java int)
* @param instant timestamp as an Instant
* @return rounded timestamp limited to 32 bits (java int)
*/
public static int hourRoundedTimestamp32FromInstant(Instant instant){
return (int) hourRoundedTimestamp(instant.getEpochSecond() + SECONDS_FROM_01_01_1900_TO_01_01_1970);
}
/**
* @return the current timestamp in seconds rounded to the closest hour.
* @return the current NTP UTC timestamp in seconds rounded to the closest hour.
*/
public static long hourRoundedCurrentTimeTimestamp() {
return hourRoundedTimestamp(currentNtpTime());
}
/**
* @return the current timestamp in seconds rounded to the closest hour
* @return the current NTP UTC timestamp in seconds rounded to the closest hour
* limited to 32 bits (java int).
*/
public static int hourRoundedCurrentTimeTimestamp32() {
......
package fr.inria.clea.lsp;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import fr.inria.clea.lsp.utils.TimeUtils;
// @ExtendWith(MockitoJUnitRunner.class)
public class LocationTest {
/* Example of a permanent Location Secret Key used for the tests */
private final String permanentLocationSecretKey = "23c9b8f36ac1c0cddaf869c3733b771c3dc409416a9695df40397cea53e7f39e21f76925fc0c74ca6ee7c7eafad92473fd85758bab8f45fe01aac504";
private String[] serverAuthorityKeyPair;
private String[] manualContactTracingAuthorityKeyPair;
private int periodStartTime;
private LocationContact locationContact;
//@Mock
private LocationSpecificPart lsp;
private Location location;
@BeforeEach
public void setUp() throws Exception {
CleaEciesEncoder cleaEciesEncoder = new CleaEciesEncoder();
serverAuthorityKeyPair = cleaEciesEncoder.genKeysPair(true);
manualContactTracingAuthorityKeyPair = cleaEciesEncoder.genKeysPair(true);
periodStartTime = TimeUtils.hourRoundedCurrentTimeTimestamp32();
locationContact = new LocationContact("0612150292", "01234567", periodStartTime);
}
@Test
public void testWhenSettingQrCodeValidityStartTimeWithValidQrCodeRenewalIntervalThenQrValidityStartTimeUpdated() {
int qrCodeRenewalIntervalExponentCompact = 2;
int qrCodeRenewalInterval = 1 << qrCodeRenewalIntervalExponentCompact;
int periodDuration = 3;
lsp = newLocationSpecificPart(qrCodeRenewalIntervalExponentCompact, periodDuration);
location = newLocation(locationContact, lsp);
location.setQrCodeValidityStartTime(periodStartTime, periodStartTime);
assertThat(lsp.getQrCodeValidityStartTime()).isEqualTo(periodStartTime);
location.setQrCodeValidityStartTime(periodStartTime, periodStartTime + qrCodeRenewalInterval);
assertThat(lsp.getQrCodeValidityStartTime()).isEqualTo(periodStartTime + qrCodeRenewalInterval);
}
@Test
public void testWhenSettingQrCodeValidityStartTimeWithValidQrCodeRenewalIntervalThenQrValidityStartTimeNotUpdated() {
int qrCodeRenewalIntervalExponentCompact = 2;
int periodDuration = 3;
lsp = Mockito.spy(newLocationSpecificPart(qrCodeRenewalIntervalExponentCompact, periodDuration));
location = newLocation(locationContact, lsp);
location.setQrCodeValidityStartTime(periodStartTime, periodStartTime - 1);
location.setQrCodeValidityStartTime(periodStartTime, periodStartTime + 1);
location.setQrCodeValidityStartTime(periodStartTime, periodStartTime + (periodDuration + 1) * 3600);
verify(lsp, never()).setQrCodeValidityStartTime(Mockito.anyInt());
}
@Test
public void testWhenSettingQrCodeValidityStartTimeWithNoQrCodeRenewalIntervalThenQrValidityStartTimeNotUpdated() {
int qrCodeRenewalIntervalExponentCompact = 0x1F;
int periodDuration = 3;
lsp = newLocationSpecificPart(qrCodeRenewalIntervalExponentCompact, periodDuration);
location = newLocation(locationContact, lsp);
location.setQrCodeValidityStartTime(periodStartTime, periodStartTime);
assertThat(lsp.getQrCodeValidityStartTime()).isEqualTo(periodStartTime);
location.setQrCodeValidityStartTime(periodStartTime, periodStartTime + 1);
assertThat(lsp.getQrCodeValidityStartTime()).isNotEqualTo(periodStartTime + 1);
}
@Test
public void testNewDeepLink() throws CleaEncryptionException {
int qrCodeRenewalIntervalExponentCompact = 2;
int periodDuration = 3;
lsp = newLocationSpecificPart(qrCodeRenewalIntervalExponentCompact, periodDuration);
location = newLocation(locationContact, lsp);
String deepLink = location.newDeepLink();
assertThat(deepLink).isNotEmpty();
assertThat(deepLink).startsWith(Location.COUNTRY_SPECIFIC_PREFIX);
String deepLink2 = location.newDeepLink(periodStartTime);
assertThat(deepLink2).isNotEmpty();
assertThat(deepLink2).startsWith(Location.COUNTRY_SPECIFIC_PREFIX);
String deepLink3 = location.newDeepLink(periodStartTime, periodStartTime);
assertThat(deepLink3).isNotEmpty();
assertThat(deepLink3).startsWith(Location.COUNTRY_SPECIFIC_PREFIX);
assertThat(deepLink).isNotIn(deepLink2, deepLink3);
assertThat(deepLink2).isNotIn(deepLink, deepLink3);
assertThat(deepLink3).isNotIn(deepLink, deepLink2);
}
protected LocationSpecificPart newLocationSpecificPart(int qrCodeRenewalIntervalExponentCompact,
int periodDuration) {
return LocationSpecificPart.builder().staff(true).countryCode(33)
.qrCodeRenewalIntervalExponentCompact(qrCodeRenewalIntervalExponentCompact).venueType(4)
.venueCategory1(0).venueCategory2(0).periodDuration(periodDuration).build();
}
protected Location newLocation(LocationContact locationContact, LocationSpecificPart lsp) {
return Location.builder().contact(locationContact).locationSpecificPart(lsp)
.manualContactTracingAuthorityPublicKey(manualContactTracingAuthorityKeyPair[1])
.serverAuthorityPublicKey(serverAuthorityKeyPair[1])
.permanentLocationSecretKey(permanentLocationSecretKey).build();
}
}
......@@ -46,5 +46,52 @@ public class TimeUtilsTest {
public void testTimestampIsRoundedUpToTheNextLongWhenModuloIsEqualToHalfTimeRoundingValue() {
assertThat(TimeUtils.hourRoundedTimestamp(1606141800)).isEqualTo(1606143600);
}
@Test
public void testTimestampFromInstantIsRoundedDownWhenModuloLowerThanHalfTimeRoundingValue(){
Instant instant = Instant.parse("1970-01-01T00:10:00.00Z");
assertThat(TimeUtils.hourRoundedTimestampFromInstant(instant)).isEqualTo(TimeUtils.SECONDS_FROM_01_01_1900_TO_01_01_1970);
}
@Test
public void testTimestampFromInstantIsRoundedUpWhenModuloGreaterThanHalfTimeRoundingValue(){
Instant instant = Instant.parse("1969-12-31T23:50:00.00Z");
assertThat(TimeUtils.hourRoundedTimestampFromInstant(instant)).isEqualTo(TimeUtils.SECONDS_FROM_01_01_1900_TO_01_01_1970);
}
@Test
public void testTimestampFromInstantIsNotRoundedWhenMultipleOfTimeRoundingValue(){
Instant instant = Instant.parse("1970-01-01T00:00:00.00Z");
assertThat(TimeUtils.hourRoundedTimestampFromInstant(instant)).isEqualTo(TimeUtils.SECONDS_FROM_01_01_1900_TO_01_01_1970);
}
@Test
public void testTimestampFromInstantIsRoundedUpToTheNextLongWhenModuloIsEqualToHalfTimeRoundingValue(){
Instant instant = Instant.parse("1969-12-31T23:30:00.00Z");
assertThat(TimeUtils.hourRoundedTimestampFromInstant(instant)).isEqualTo(TimeUtils.SECONDS_FROM_01_01_1900_TO_01_01_1970);
}
@Test
public void testIntTimestampFromInstantIsRoundedDownWhenModuloLowerThanHalfTimeRoundingValue(){
Instant instant = Instant.parse("1970-01-01T00:10:00.00Z");
assertThat(TimeUtils.hourRoundedTimestamp32FromInstant(instant)).isEqualTo((int)TimeUtils.SECONDS_FROM_01_01_1900_TO_01_01_1970);
}
@Test
public void testIntTimestampFromInstantIsRoundedUpWhenModuloGreaterThanHalfTimeRoundingValue(){
Instant instant = Instant.parse("1969-12-31T23:50:00.00Z");
assertThat(TimeUtils.hourRoundedTimestamp32FromInstant(instant)).isEqualTo((int)TimeUtils.SECONDS_FROM_01_01_1900_TO_01_01_1970);
}
@Test
public void testIntTimestampFromInstantIsNotRoundedWhenMultipleOfTimeRoundingValue(){
Instant instant = Instant.parse("1970-01-01T00:00:00.00Z");
assertThat(TimeUtils.hourRoundedTimestamp32FromInstant(instant)).isEqualTo((int)TimeUtils.SECONDS_FROM_01_01_1900_TO_01_01_1970);
}
@Test
public void testIntTimestampFromInstantIsRoundedUpToTheNextLongWhenModuloIsEqualToHalfTimeRoundingValue(){
Instant instant = Instant.parse("1969-12-31T23:30:00.00Z");
assertThat(TimeUtils.hourRoundedTimestamp32FromInstant(instant)).isEqualTo((int)TimeUtils.SECONDS_FROM_01_01_1900_TO_01_01_1970);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment