Merge pull request #3101 from buessow/dev-garmin3

Fix flaky GarminSimulatorClientTest
This commit is contained in:
Milos Kozak 2023-12-09 12:05:57 +01:00 committed by GitHub
commit f08104b9dd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 13 deletions

View file

@ -17,7 +17,7 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
org.gradle.parallel=true org.gradle.parallel=true
org.gradle.warning.mode=all org.gradle.warning.mode=all
org.gradle.jvmargs=-Xmx3g -XX:+UseParallelGC org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC
android.enableJetifier=false android.enableJetifier=false
android.useAndroidX=true android.useAndroidX=true

View file

@ -13,6 +13,7 @@ import java.net.ServerSocket
import java.net.Socket import java.net.Socket
import java.net.SocketException import java.net.SocketException
import java.time.Duration import java.time.Duration
import java.time.Instant
import java.util.Collections import java.util.Collections
import java.util.concurrent.ExecutorService import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors import java.util.concurrent.Executors
@ -142,10 +143,10 @@ class GarminSimulatorClient(
/** Wait for the server to start listing to requests. */ /** Wait for the server to start listing to requests. */
fun awaitReady(wait: Duration): Boolean { fun awaitReady(wait: Duration): Boolean {
var waitNanos = wait.toNanos() val waitUntil = Instant.now() + wait
readyLock.withLock { readyLock.withLock {
while (!serverSocket.isBound && waitNanos > 0L) { while (!serverSocket.isBound && Instant.now() < waitUntil) {
waitNanos = readyCond.awaitNanos(waitNanos) readyCond.await(20, TimeUnit.MILLISECONDS)
} }
} }
return serverSocket.isBound return serverSocket.isBound

View file

@ -1,7 +1,6 @@
package app.aaps.plugins.sync.garmin package app.aaps.plugins.sync.garmin
import app.aaps.shared.tests.TestBase import app.aaps.shared.tests.TestBase
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@ -19,6 +18,14 @@ class GarminSimulatorClientTest: TestBase() {
private lateinit var client: GarminSimulatorClient private lateinit var client: GarminSimulatorClient
private val receiver: GarminReceiver = mock() private val receiver: GarminReceiver = mock()
private fun <T> waitForOrFail(c: ()->T?): T {
for (i in 0 until 10) {
c()?.let { return it }
Thread.sleep(1)
}
throw AssertionError("wait timed out")
}
@BeforeEach @BeforeEach
fun setup() { fun setup() {
client = GarminSimulatorClient(aapsLogger, receiver, 0) client = GarminSimulatorClient(aapsLogger, receiver, 0)
@ -28,33 +35,31 @@ class GarminSimulatorClientTest: TestBase() {
fun receiveMessage() { fun receiveMessage() {
val payload = "foo".toByteArray() val payload = "foo".toByteArray()
assertTrue(client.awaitReady(Duration.ofSeconds(10))) assertTrue(client.awaitReady(Duration.ofSeconds(10)))
verify(receiver, timeout(100)).onConnect(client)
val port = client.port val port = client.port
val ip = Inet4Address.getByAddress(byteArrayOf(127, 0, 0, 1)) val ip = Inet4Address.getByAddress(byteArrayOf(127, 0, 0, 1))
Socket(ip, port).use { socket -> Socket(ip, port).use { socket ->
assertTrue(socket.isConnected) assertTrue(socket.isConnected)
socket.getOutputStream().write(payload) socket.getOutputStream().write(payload)
socket.getOutputStream().flush() socket.getOutputStream().flush()
verify(receiver).onConnect(client) val device = waitForOrFail { client.connectedDevices.firstOrNull() }
}
assertEquals(1, client.connectedDevices.size)
val device: GarminDevice = client.connectedDevices.first()
verify(receiver, timeout(1_000)) verify(receiver, timeout(1_000))
.onReceiveMessage(eq(client), eq(device.id), eq("SIMAPP"), eq(payload)) .onReceiveMessage(eq(client), eq(device.id), eq("SIMAPP"), eq(payload))
} }
}
@Test @Test
fun sendMessage() { fun sendMessage() {
val payload = "foo".toByteArray() val payload = "foo".toByteArray()
assertTrue(client.awaitReady(Duration.ofSeconds(10))) assertTrue(client.awaitReady(Duration.ofSeconds(10)))
verify(receiver, timeout(100)).onConnect(client)
val port = client.port val port = client.port
val ip = Inet4Address.getByAddress(byteArrayOf(127, 0, 0, 1)) val ip = Inet4Address.getByAddress(byteArrayOf(127, 0, 0, 1))
val device: GarminDevice val device: GarminDevice
val app: GarminApplication val app: GarminApplication
Socket(ip, port).use { socket -> Socket(ip, port).use { socket ->
assertTrue(socket.isConnected) assertTrue(socket.isConnected)
verify(receiver).onConnect(client) device = waitForOrFail { client.connectedDevices.firstOrNull() }
assertEquals(1, client.connectedDevices.size)
device = client.connectedDevices.first()
app = GarminApplication(device, "SIMAPP", "T") app = GarminApplication(device, "SIMAPP", "T")
client.sendMessage(app, payload) client.sendMessage(app, payload)
} }