Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,14 @@ class PutBytesSession(

suspend fun sendInstall(cookie: UInt) {
val installResponse = putBytesService.sendInstall(cookie)
// TODO this fired?
// check(installResponse.cookie.get() == cookie) { "Received response for wrong cookie" }
val responseCookie = installResponse.cookie.get()
// Firmware answers an install with cookie 0: prv_cleanup_and_send_response reads
// s_pb_state.token, and the commit that precedes an install has already reset the
// transfer state. That is why this check used to fire on every install. Zero is
// tolerated so the check can come back for the firmware that answers properly, while
// a cookie belonging to some other transfer is still caught.
check(responseCookie == cookie || responseCookie == 0u) {
"Received response for wrong cookie"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package io.rebble.libpebblecommon.connection.endpointmanager.putbytes

import TestPebbleProtocolHandler
import io.rebble.libpebblecommon.di.ConnectionCoroutineScope
import io.rebble.libpebblecommon.packets.PutBytesInstall
import io.rebble.libpebblecommon.packets.PutBytesResponse
import io.rebble.libpebblecommon.packets.PutBytesResult
import io.rebble.libpebblecommon.services.PutBytesService
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Test
import kotlin.test.assertFailsWith

class PutBytesSessionTest {
private fun ack(cookie: UInt) = PutBytesResponse().apply {
result.set(PutBytesResult.ACK.value)
this.cookie.set(cookie)
}

/** A session whose watch answers every install with [answerWith]. */
private suspend fun TestScope.sessionAnswering(answerWith: UInt): PutBytesSession {
val handler = TestPebbleProtocolHandler { packet ->
if (packet is PutBytesInstall) {
receivePacket(ack(answerWith))
}
}
val service = PutBytesService(
handler,
ConnectionCoroutineScope(backgroundScope.coroutineContext),
)
service.init()
testScheduler.runCurrent()
return PutBytesSession(service)
}

@Test
fun anInstallAnsweredWithItsOwnCookieIsAccepted() = runTest {
sessionAnswering(answerWith = 7u).sendInstall(7u)
}

@Test
fun anInstallAnsweredWithZeroIsAccepted() = runTest {
// What the firmware actually sends: prv_cleanup_and_send_response reads
// s_pb_state.token, which the preceding commit already cleared.
sessionAnswering(answerWith = 0u).sendInstall(7u)
}

@Test
fun anInstallAnsweredForAnotherTransferIsNot() = runTest {
val session = sessionAnswering(answerWith = 8u)

assertFailsWith<IllegalStateException> { session.sendInstall(7u) }
}
}