Skip to content
This repository has been archived by the owner on Aug 30, 2022. It is now read-only.

Suffix Exceptions with "Exception" #77

Merged
merged 1 commit into from
Jul 20, 2020
Merged
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
6 changes: 3 additions & 3 deletions core/api/core.api
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public abstract interface class com/juul/able/device/Device {
public abstract fun connectGatt (Landroid/content/Context;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class com/juul/able/gatt/ConnectionLost : java/io/IOException {
public final class com/juul/able/gatt/ConnectionLostException : java/io/IOException {
public fun <init> ()V
}

Expand Down Expand Up @@ -109,7 +109,7 @@ public abstract interface class com/juul/able/gatt/GattConnection {
public abstract fun getOnConnectionStateChange ()Lkotlinx/coroutines/flow/Flow;
}

public final class com/juul/able/gatt/GattErrorStatus : java/io/IOException {
public final class com/juul/able/gatt/GattErrorStatusException : java/io/IOException {
public final fun getEvent ()Lcom/juul/able/gatt/OnConnectionStateChange;
}

Expand Down Expand Up @@ -242,7 +242,7 @@ public final class com/juul/able/gatt/OnReadRemoteRssi : com/juul/able/gatt/HasG
public fun toString ()Ljava/lang/String;
}

public final class com/juul/able/gatt/OutOfOrderGattCallback : java/io/IOException {
public final class com/juul/able/gatt/OutOfOrderGattCallbackException : java/io/IOException {
}

public final class com/juul/able/logger/AndroidLogger : com/juul/able/logger/Logger {
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/java/device/CoroutinesDevice.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import android.os.RemoteException
import com.juul.able.Able
import com.juul.able.device.ConnectGattResult.Failure
import com.juul.able.device.ConnectGattResult.Success
import com.juul.able.gatt.ConnectionLost
import com.juul.able.gatt.ConnectionLostException
import com.juul.able.gatt.CoroutinesGatt
import com.juul.able.gatt.GattCallback
import com.juul.able.gatt.GattConnection
import com.juul.able.gatt.GattErrorStatus
import com.juul.able.gatt.GattErrorStatusException
import com.juul.able.gatt.asGattConnectionStateString
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.flow.first
Expand Down Expand Up @@ -60,8 +60,8 @@ internal class CoroutinesDevice(
onConnectionStateChange
.onEach { event ->
Able.verbose { "← Device $device received $event while waiting for connection" }
if (event.status != GATT_SUCCESS) throw GattErrorStatus(event)
if (event.newState == STATE_DISCONNECTED) throw ConnectionLost()
if (event.status != GATT_SUCCESS) throw GattErrorStatusException(event)
if (event.newState == STATE_DISCONNECTED) throw ConnectionLostException()
}
.first { (_, newState) -> newState == STATE_CONNECTED }
.also { (_, newState) ->
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/java/gatt/CoroutinesGatt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext

class OutOfOrderGattCallback internal constructor(message: String) : IOException(message)
class OutOfOrderGattCallbackException internal constructor(message: String) : IOException(message)

class CoroutinesGatt internal constructor(
private val bluetoothGatt: BluetoothGatt,
Expand Down Expand Up @@ -118,15 +118,15 @@ class CoroutinesGatt internal constructor(
} catch (e: CancellationException) {
throw CancellationException("Waiting on response for $methodName was cancelled", e)
} catch (e: Exception) {
throw ConnectionLost("Failed to receive response for $methodName", e)
throw ConnectionLostException("Failed to receive response for $methodName", e)
}
Able.info { "$methodName ← $response" }

// `lock` should always enforce a 1:1 matching of request to response, but if an Android
// `BluetoothGattCallback` method gets called out of order then we'll cast to the wrong
// response type.
response as? T
?: throw OutOfOrderGattCallback(
?: throw OutOfOrderGattCallbackException(
"Unexpected response type ${response.javaClass.simpleName} received for $methodName"
)
}
Expand All @@ -139,7 +139,7 @@ class CoroutinesGatt internal constructor(
val device = bluetoothGatt.device
"← Device $device received $event while waiting for disconnection"
}
if (event.status != GATT_SUCCESS) throw GattErrorStatus(event)
if (event.status != GATT_SUCCESS) throw GattErrorStatusException(event)
}
.first { (_, newState) -> newState == STATE_DISCONNECTED }
.also { (_, newState) ->
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/gatt/GattCallback.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ internal class GattCallback(

private fun onDisconnecting() {
onCharacteristicChanged.close()
onResponse.close(ConnectionLost())
onResponse.close(ConnectionLostException())
}

fun close(gatt: BluetoothGatt) {
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/gatt/GattConnection.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ interface GattConnection {
suspend fun disconnect(): Unit
}

class GattErrorStatus internal constructor(
class GattErrorStatusException internal constructor(
val event: OnConnectionStateChange
) : IOException("Received $event")

class ConnectionLost internal constructor(
class ConnectionLostException internal constructor(
message: String? = null,
cause: Throwable? = null
) : IOException(message, cause)
12 changes: 6 additions & 6 deletions core/src/main/java/gatt/GattIo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ interface GattIo {

/**
* @throws [RemoteException] if underlying [BluetoothGatt.discoverServices] returns `false`.
* @throws [ConnectionLost] if [Gatt] disconnects while method is executing.
* @throws [ConnectionLostException] if [Gatt] disconnects while method is executing.
*/
suspend fun discoverServices(): GattStatus

Expand All @@ -55,13 +55,13 @@ interface GattIo {

/**
* @throws [RemoteException] if underlying [BluetoothGatt.requestMtu] returns `false`.
* @throws [ConnectionLost] if [Gatt] disconnects while method is executing.
* @throws [ConnectionLostException] if [Gatt] disconnects while method is executing.
*/
suspend fun requestMtu(mtu: Int): OnMtuChanged

/**
* @throws [RemoteException] if underlying [BluetoothGatt.readCharacteristic] returns `false`.
* @throws [ConnectionLost] if [Gatt] disconnects while method is executing.
* @throws [ConnectionLostException] if [Gatt] disconnects while method is executing.
*/
suspend fun readCharacteristic(
characteristic: BluetoothGattCharacteristic
Expand All @@ -71,7 +71,7 @@ interface GattIo {
* @param value applied to [characteristic] when characteristic is written.
* @param writeType applied to [characteristic] when characteristic is written.
* @throws [RemoteException] if underlying [BluetoothGatt.writeCharacteristic] returns `false`.
* @throws [ConnectionLost] if [Gatt] disconnects while method is executing.
* @throws [ConnectionLostException] if [Gatt] disconnects while method is executing.
*/
suspend fun writeCharacteristic(
characteristic: BluetoothGattCharacteristic,
Expand All @@ -82,7 +82,7 @@ interface GattIo {
/**
* @param value applied to [descriptor] when descriptor is written.
* @throws [RemoteException] if underlying [BluetoothGatt.writeDescriptor] returns `false`.
* @throws [ConnectionLost] if [Gatt] disconnects while method is executing.
* @throws [ConnectionLostException] if [Gatt] disconnects while method is executing.
*/
suspend fun writeDescriptor(
descriptor: BluetoothGattDescriptor,
Expand All @@ -96,7 +96,7 @@ interface GattIo {

/**
* @throws [RemoteException] if underlying [BluetoothGatt.requestMtu] returns `false`.
* @throws [ConnectionLost] if [Gatt] disconnects while method is executing.
* @throws [ConnectionLostException] if [Gatt] disconnects while method is executing.
*/
suspend fun readRemoteRssi(): OnReadRemoteRssi
}
Expand Down
8 changes: 4 additions & 4 deletions core/src/test/java/device/CoroutinesDeviceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ import com.juul.able.device.ConnectGattResult
import com.juul.able.device.ConnectGattResult.Failure
import com.juul.able.device.ConnectGattResult.Success
import com.juul.able.device.CoroutinesDevice
import com.juul.able.gatt.ConnectionLost
import com.juul.able.gatt.ConnectionLostException
import com.juul.able.gatt.GATT_CONN_CANCEL
import com.juul.able.gatt.GattCallback
import com.juul.able.gatt.GattErrorStatus
import com.juul.able.gatt.GattErrorStatusException
import com.juul.able.gatt.OnConnectionStateChange
import com.juul.able.test.logger.ConsoleLoggerTestRule
import io.mockk.every
Expand Down Expand Up @@ -65,7 +65,7 @@ class CoroutinesDeviceTest {

assertEquals(
expected = OnConnectionStateChange(GATT_CONN_CANCEL, STATE_CONNECTED),
actual = (failure.cause as GattErrorStatus).event
actual = (failure.cause as GattErrorStatusException).event
)
verify(exactly = 1) { bluetoothGatt.close() }
}
Expand Down Expand Up @@ -120,7 +120,7 @@ class CoroutinesDeviceTest {
val failure = device.connectGatt(mockk()) as Failure.Connection

assertEquals<Class<out Throwable>>(
expected = ConnectionLost::class.java,
expected = ConnectionLostException::class.java,
actual = failure.cause.javaClass
)
verify(exactly = 1) { bluetoothGatt.close() }
Expand Down
12 changes: 6 additions & 6 deletions core/src/test/java/gatt/CoroutinesGattTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ import android.bluetooth.BluetoothProfile.STATE_CONNECTED
import android.bluetooth.BluetoothProfile.STATE_DISCONNECTED
import android.bluetooth.BluetoothProfile.STATE_DISCONNECTING
import android.os.RemoteException
import com.juul.able.gatt.ConnectionLost
import com.juul.able.gatt.ConnectionLostException
import com.juul.able.gatt.CoroutinesGatt
import com.juul.able.gatt.GattCallback
import com.juul.able.gatt.OnCharacteristicChanged
import com.juul.able.gatt.OnCharacteristicRead
import com.juul.able.gatt.OnCharacteristicWrite
import com.juul.able.gatt.OnDescriptorWrite
import com.juul.able.gatt.OnReadRemoteRssi
import com.juul.able.gatt.OutOfOrderGattCallback
import com.juul.able.gatt.OutOfOrderGattCallbackException
import com.juul.able.gatt.writeCharacteristic
import com.juul.able.test.gatt.FakeBluetoothGattCharacteristic as FakeCharacteristic
import com.juul.able.test.gatt.FakeBluetoothGattDescriptor as FakeDescriptor
Expand Down Expand Up @@ -357,7 +357,7 @@ class CoroutinesGattTest {

val gatt = CoroutinesGatt(bluetoothGatt, dispatcher, callback)
runBlocking {
assertFailsWith<OutOfOrderGattCallback> {
assertFailsWith<OutOfOrderGattCallbackException> {
gatt.readCharacteristic(createCharacteristic())
}
}
Expand Down Expand Up @@ -475,7 +475,7 @@ class CoroutinesGattTest {
}

@Test
fun `Gatt action throws ConnectionLost if connection drops while executing request`() {
fun `Gatt action throws ConnectionLostException if connection drops while executing request`() {
createDispatcher().use { dispatcher ->
val callback = GattCallback(dispatcher)
val bluetoothGatt = mockk<BluetoothGatt> {
Expand All @@ -489,12 +489,12 @@ class CoroutinesGattTest {

val gatt = CoroutinesGatt(bluetoothGatt, dispatcher, callback)
runBlocking {
val cause = assertFailsWith<ConnectionLost> {
val cause = assertFailsWith<ConnectionLostException> {
gatt.readCharacteristic(createCharacteristic())
}.cause

assertEquals<Class<out Throwable>>(
expected = ConnectionLost::class.java,
expected = ConnectionLostException::class.java,
actual = cause!!.javaClass
)
}
Expand Down
6 changes: 3 additions & 3 deletions keep-alive/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,12 @@ gatt.state.collect { println("State: $it") }

If a Gatt operation (e.g. `discoverServices`, `writeCharacteristic`, `readCharacteristic`, etc) is
unable to be performed due to a GATT connection being unavailable (i.e. current `State` is **not**
`Connected`), then it will immediately throw `NotReady`.
`Connected`), then it will immediately throw `NotReadyException`.

It is the responsibility of the caller to handle retrying, for example:

```kotlin
class GattCancelled : Exception()
class GattCancelledException : Exception()

suspend fun KeepAliveGatt.readCharacteristicWithRetry(
characteristic: BluetoothGattCharacteristic,
Expand All @@ -148,7 +148,7 @@ suspend fun KeepAliveGatt.readCharacteristicWithRetry(

private suspend fun KeepAliveGatt.suspendUntilConnected() {
state
.onEach { if (it is Cancelled) throw GattCancelled() }
.onEach { if (it is Cancelled) throw GattCancelledException() }
.first { it == Connected }
}
```
Expand Down
2 changes: 1 addition & 1 deletion keep-alive/api/keep-alive.api
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public final class com/juul/able/keepalive/KeepAliveGattKt {
public static synthetic fun keepAliveGatt$default (Lkotlinx/coroutines/CoroutineScope;Landroid/content/Context;Landroid/bluetooth/BluetoothDevice;JLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/juul/able/keepalive/KeepAliveGatt;
}

public final class com/juul/able/keepalive/NotReady : java/lang/IllegalStateException {
public final class com/juul/able/keepalive/NotReadyException : java/lang/IllegalStateException {
}

public abstract class com/juul/able/keepalive/State {
Expand Down
4 changes: 2 additions & 2 deletions keep-alive/src/main/java/KeepAliveGatt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeoutOrNull

class NotReady internal constructor(message: String) : IllegalStateException(message)
class NotReadyException internal constructor(message: String) : IllegalStateException(message)

typealias EventHandler = suspend (Event) -> Unit

Expand Down Expand Up @@ -92,7 +92,7 @@ class KeepAliveGatt internal constructor(
@Volatile
private var _gatt: GattIo? = null
private val gatt: GattIo
inline get() = _gatt ?: throw NotReady(toString())
inline get() = _gatt ?: throw NotReadyException(toString())

private val _state = MutableStateFlow<State>(State.Disconnected())

Expand Down
12 changes: 6 additions & 6 deletions keep-alive/src/test/java/KeepAliveGattTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import com.juul.able.Able
import com.juul.able.android.connectGatt
import com.juul.able.device.ConnectGattResult
import com.juul.able.device.ConnectGattResult.Failure
import com.juul.able.gatt.ConnectionLost
import com.juul.able.gatt.ConnectionLostException
import com.juul.able.gatt.Gatt
import com.juul.able.gatt.OnCharacteristicChanged
import com.juul.able.gatt.OnReadRemoteRssi
import com.juul.able.keepalive.Event
import com.juul.able.keepalive.NotReady
import com.juul.able.keepalive.NotReadyException
import com.juul.able.keepalive.State
import com.juul.able.keepalive.State.Connected
import com.juul.able.keepalive.State.Connecting
Expand Down Expand Up @@ -192,14 +192,14 @@ class KeepAliveGattTest {
}

@Test
fun `Bluetooth IO when not connected throws NotReady`() = runBlocking<Unit> {
fun `Bluetooth IO when not connected throws NotReadyException`() = runBlocking<Unit> {
val keepAlive = GlobalScope.keepAliveGatt(
androidContext = mockk(relaxed = true),
bluetoothDevice = mockk(),
disconnectTimeoutMillis = DISCONNECT_TIMEOUT
)

assertFailsWith<NotReady> {
assertFailsWith<NotReadyException> {
keepAlive.discoverServices()
}
}
Expand All @@ -220,7 +220,7 @@ class KeepAliveGattTest {
bluetoothDevice.connectGatt(any())
} answers {
if (++attempt >= connectionAttempts) throw EndOfTest()
Failure.Connection(mockk<ConnectionLost>())
Failure.Connection(mockk<ConnectionLostException>())
}

val keepAlive = scope.keepAliveGatt(
Expand Down Expand Up @@ -616,7 +616,7 @@ class KeepAliveGattTest {
bluetoothDevice.connectGatt(any())
} answers {
if (++attempt > connectionAttempts) throw EndOfTest()
Failure.Connection(mockk<ConnectionLost>())
Failure.Connection(mockk<ConnectionLostException>())
}

val events = mutableListOf<Event>()
Expand Down
8 changes: 4 additions & 4 deletions throw/src/main/java/android/BluetoothDeviceOrThrow.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import android.os.RemoteException
import com.juul.able.android.connectGatt
import com.juul.able.device.ConnectGattResult.Failure
import com.juul.able.device.ConnectGattResult.Success
import com.juul.able.gatt.ConnectionLost
import com.juul.able.gatt.ConnectionLostException
import com.juul.able.gatt.Gatt
import com.juul.able.gatt.GattErrorStatus
import com.juul.able.gatt.GattErrorStatusException

/**
* @throws RemoteException if underlying [BluetoothDevice.connectGatt] returns `null`.
* @throws GattErrorStatus if non-[GATT_SUCCESS] status is received during connection process.
* @throws ConnectionLost if [STATE_DISCONNECTED] is received during connection process.
* @throws GattErrorStatusException if non-[GATT_SUCCESS] status is received during connection process.
* @throws ConnectionLostException if [STATE_DISCONNECTED] is received during connection process.
*/
suspend fun BluetoothDevice.connectGattOrThrow(
context: Context
Expand Down