diff --git a/lib/src/main/java/tech/relaycorp/awaladroid/messaging/OutgoingMessage.kt b/lib/src/main/java/tech/relaycorp/awaladroid/messaging/OutgoingMessage.kt index 1e97ffc8..6146866a 100644 --- a/lib/src/main/java/tech/relaycorp/awaladroid/messaging/OutgoingMessage.kt +++ b/lib/src/main/java/tech/relaycorp/awaladroid/messaging/OutgoingMessage.kt @@ -24,9 +24,9 @@ public class OutgoingMessage private constructor( public val senderEndpoint: FirstPartyEndpoint, public val recipientEndpoint: ThirdPartyEndpoint, - public val parcelExpiryDate: ZonedDateTime = maxExpiryDate(), + public val parcelExpiryDate: ZonedDateTime, public val parcelId: ParcelId, - internal val parcelCreationDate: ZonedDateTime = ZonedDateTime.now() + internal val parcelCreationDate: ZonedDateTime, ) : Message() { internal lateinit var parcel: Parcel @@ -35,7 +35,10 @@ private constructor( internal val ttl get() = Duration.between(parcelCreationDate, parcelExpiryDate).seconds.toInt() public companion object { - internal fun maxExpiryDate() = ZonedDateTime.now().plusDays(180) + private val CLOCK_DRIFT_OFFSET = Duration.ofMinutes(5) + private val MAX_TTL = Duration.ofDays(180) + + private fun maxExpiryDate() = ZonedDateTime.now().plus(MAX_TTL).minus(CLOCK_DRIFT_OFFSET) /** * Create an outgoing service message (but don't send it). @@ -59,7 +62,8 @@ private constructor( senderEndpoint, recipientEndpoint, parcelExpiryDate, - parcelId + parcelId, + ZonedDateTime.now().minus(CLOCK_DRIFT_OFFSET), ) message.parcel = message.buildParcel(type, content) return message diff --git a/lib/src/test/java/tech/relaycorp/awaladroid/messaging/OutgoingMessageTest.kt b/lib/src/test/java/tech/relaycorp/awaladroid/messaging/OutgoingMessageTest.kt index 7451c772..9b1c9ef8 100644 --- a/lib/src/test/java/tech/relaycorp/awaladroid/messaging/OutgoingMessageTest.kt +++ b/lib/src/test/java/tech/relaycorp/awaladroid/messaging/OutgoingMessageTest.kt @@ -17,50 +17,60 @@ import tech.relaycorp.relaynet.ramf.RecipientAddressType internal class OutgoingMessageTest : MockContextTestCase() { - // Public Recipient + @Test + fun build_creationDate() = runBlockingTest { + val channel = createEndpointChannel(RecipientAddressType.PRIVATE) + val dateBeforeCreation = ZonedDateTime.now() + + val message = MessageFactory.buildOutgoing(channel) + + assertTrue(dateBeforeCreation.minusMinutes(5) <= message.parcel.creationDate) + assertTrue(message.parcel.creationDate <= ZonedDateTime.now().minusMinutes(5)) + } @Test - fun buildForPublicRecipient_checkBaseValues() = runBlockingTest { + fun build_defaultExpiryDate() = runBlockingTest { val channel = createEndpointChannel(RecipientAddressType.PUBLIC) val message = MessageFactory.buildOutgoing(channel) - assertEquals(message.recipientEndpoint.address, message.parcel.recipientAddress) - assertEquals(message.parcelId.value, message.parcel.id) - assertSameDateTime(message.parcelCreationDate, message.parcel.creationDate) - assertEquals(message.ttl, message.parcel.ttl) + val differenceSeconds = Duration.between( + message.parcel.expiryDate, + message.parcel.creationDate.plusDays(180) + ).seconds + assertTrue(abs(differenceSeconds) < 3) } @Test - fun buildForPublicRecipient_checkTTL() = runBlockingTest { + fun build_customExpiryDate() = runBlockingTest { val (senderEndpoint, recipientEndpoint) = createEndpointChannel(RecipientAddressType.PUBLIC) + val parcelExpiryDate = ZonedDateTime.now().plusMinutes(1) val message = OutgoingMessage.build( "the type", Random.Default.nextBytes(10), - senderEndpoint = senderEndpoint, - recipientEndpoint = recipientEndpoint, - parcelExpiryDate = ZonedDateTime.now().plusMinutes(1) + senderEndpoint, + recipientEndpoint, + parcelExpiryDate ) - assertTrue(58 < message.ttl) - assertTrue(message.ttl <= 60) + val differenceSeconds = + Duration.between(message.parcel.expiryDate, parcelExpiryDate).seconds + assertTrue(abs(differenceSeconds) < 3) } + // Public Recipient + @Test - fun buildForPublicRecipient_expiryDateDefaultsToMax() = runBlockingTest { - val (senderEndpoint, recipientEndpoint) = createEndpointChannel(RecipientAddressType.PUBLIC) + fun buildForPublicRecipient_checkBaseValues() = runBlockingTest { + val channel = createEndpointChannel(RecipientAddressType.PUBLIC) - val message = OutgoingMessage.build( - "the type", - Random.Default.nextBytes(10), - senderEndpoint = senderEndpoint, - recipientEndpoint = recipientEndpoint, - ) + val message = MessageFactory.buildOutgoing(channel) - val ttlExpected = - Duration.between(ZonedDateTime.now(), OutgoingMessage.maxExpiryDate()).seconds - assertTrue(abs(ttlExpected - message.ttl) < 2) + assertEquals(message.recipientEndpoint.address, message.parcel.recipientAddress) + assertEquals(message.parcelId.value, message.parcel.id) + assertSameDateTime(message.parcelCreationDate, message.parcel.creationDate) + assertEquals(message.ttl, message.parcel.ttl) } @Test