blob: de2b21c8a3bbd7749c395ff5e779f37323774740 [file] [log] [blame]
package com.google.android.connecteddevice.core
import android.os.ParcelUuid
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.android.companionprotos.DeviceMessageProto
import com.google.android.companionprotos.OperationProto.OperationType
import com.google.android.connecteddevice.api.IAssociationCallback
import com.google.android.connecteddevice.api.IConnectionCallback
import com.google.android.connecteddevice.api.IDeviceAssociationCallback
import com.google.android.connecteddevice.api.IDeviceCallback
import com.google.android.connecteddevice.api.IOnAssociatedDevicesRetrievedListener
import com.google.android.connecteddevice.api.external.ISafeConnectionCallback
import com.google.android.connecteddevice.api.external.ISafeDeviceCallback
import com.google.android.connecteddevice.api.external.ISafeOnAssociatedDevicesRetrievedListener
import com.google.android.connecteddevice.api.external.ISafeOnLogRequestedListener
import com.google.android.connecteddevice.core.FeatureCoordinator.Companion.DEVICE_NAME_LENGTH
import com.google.android.connecteddevice.core.util.mockToBeAlive
import com.google.android.connecteddevice.core.util.mockToBeDead
import com.google.android.connecteddevice.logging.LoggingManager
import com.google.android.connecteddevice.model.AssociatedDevice
import com.google.android.connecteddevice.model.ConnectedDevice
import com.google.android.connecteddevice.model.DeviceMessage
import com.google.android.connecteddevice.model.DeviceMessage.OperationType.CLIENT_MESSAGE
import com.google.android.connecteddevice.model.Errors.DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED
import com.google.android.connecteddevice.storage.ConnectedDeviceStorage
import com.google.android.connecteddevice.util.ByteUtils
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors.directExecutor
import com.google.protobuf.ByteString
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.argumentCaptor
import com.nhaarman.mockitokotlin2.eq
import com.nhaarman.mockitokotlin2.isNull
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.never
import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.whenever
import java.util.UUID
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class FeatureCoordinatorTest {
private val mockController: DeviceController = mock()
private val mockStorage: ConnectedDeviceStorage = mock()
private val mockLoggingManager: LoggingManager = mock()
private val coordinator =
FeatureCoordinator(mockController, mockStorage, mockLoggingManager, directExecutor())
private val safeCoordinator = coordinator.safeFeatureCoordinator
@Test
fun connectedDevicesForDriver_returnsOnlyDriverDevices() {
val driverDevice1 =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName1",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val driverDevice2 =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName2",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val passengerDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"passengerDeviceName",
/* belongsToDriver= */ false,
/* hasSecureChannel= */ true
)
whenever(mockController.connectedDevices)
.thenReturn(listOf(driverDevice1, passengerDevice, driverDevice2))
val driverDevices = coordinator.connectedDevicesForDriver
assertThat(driverDevices).containsExactly(driverDevice1, driverDevice2)
}
@Test
fun connectedDevicesForPassengers_returnsOnlyPassengerDevices() {
val passengerDevice1 =
ConnectedDevice(
UUID.randomUUID().toString(),
"passengerDevice1",
/* belongsToDriver= */ false,
/* hasSecureChannel= */ true
)
val passengerDevice2 =
ConnectedDevice(
UUID.randomUUID().toString(),
"passengerDevice2",
/* belongsToDriver= */ false,
/* hasSecureChannel= */ true
)
val driverDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDevice",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
whenever(mockController.connectedDevices)
.thenReturn(listOf(passengerDevice1, driverDevice, passengerDevice2))
val driverDevices = coordinator.connectedDevicesForPassengers
assertThat(driverDevices).containsExactly(passengerDevice1, passengerDevice2)
}
@Test
fun allConnectedDevices_returnsAllDevices() {
val driverDevice1 =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName1",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val driverDevice2 =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName2",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val passengerDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"passengerDeviceName",
/* belongsToDriver= */ false,
/* hasSecureChannel= */ true
)
whenever(mockController.connectedDevices)
.thenReturn(listOf(driverDevice1, passengerDevice, driverDevice2))
val driverDevices = coordinator.allConnectedDevices
assertThat(driverDevices).containsExactly(driverDevice1, passengerDevice, driverDevice2)
}
@Test
fun onDeviceConnected_driverCallbacksInvokedWhenDriverDeviceConnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerDriverConnectionCallback(mockConnectionCallback)
val driverDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.onDeviceConnectedInternal(driverDevice)
verify(mockConnectionCallback).onDeviceConnected(driverDevice)
}
@Test
fun onDeviceConnected_driverCallbacksNotInvokedWhenPassengerDeviceConnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerDriverConnectionCallback(mockConnectionCallback)
val passengerDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ false,
/* hasSecureChannel= */ true
)
coordinator.onDeviceConnectedInternal(passengerDevice)
verify(mockConnectionCallback, never()).onDeviceConnected(passengerDevice)
}
@Test
fun onDeviceConnected_passengerCallbacksNotInvokedWhenDriverDeviceConnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerPassengerConnectionCallback(mockConnectionCallback)
val driverDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.onDeviceConnectedInternal(driverDevice)
verify(mockConnectionCallback, never()).onDeviceConnected(driverDevice)
}
@Test
fun onDeviceConnected_passengerCallbacksInvokedWhenPassengerDeviceConnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerPassengerConnectionCallback(mockConnectionCallback)
val passengerDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ false,
/* hasSecureChannel= */ true
)
coordinator.onDeviceConnectedInternal(passengerDevice)
verify(mockConnectionCallback).onDeviceConnected(passengerDevice)
}
@Test
fun onDeviceConnected_allCallbacksInvokedWhenDriverDeviceConnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerAllConnectionCallback(mockConnectionCallback)
val driverDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.onDeviceConnectedInternal(driverDevice)
verify(mockConnectionCallback).onDeviceConnected(driverDevice)
}
@Test
fun onDeviceConnected_allCallbacksInvokedWhenPassengerDeviceConnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerAllConnectionCallback(mockConnectionCallback)
val passengerDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ false,
/* hasSecureChannel= */ true
)
coordinator.onDeviceConnectedInternal(passengerDevice)
verify(mockConnectionCallback).onDeviceConnected(passengerDevice)
}
@Test
fun onDeviceDisconnected_driverCallbacksInvokedWhenDriverDeviceDisconnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerDriverConnectionCallback(mockConnectionCallback)
val driverDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.onDeviceDisconnectedInternal(driverDevice)
verify(mockConnectionCallback).onDeviceDisconnected(driverDevice)
}
@Test
fun onDeviceDisconnected_driverCallbacksNotInvokedWhenPassengerDeviceDisconnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerDriverConnectionCallback(mockConnectionCallback)
val passengerDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ false,
/* hasSecureChannel= */ true
)
coordinator.onDeviceDisconnectedInternal(passengerDevice)
verify(mockConnectionCallback, never()).onDeviceDisconnected(passengerDevice)
}
@Test
fun onDeviceDisconnected_passengerCallbacksNotInvokedWhenDriverDeviceDisconnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerPassengerConnectionCallback(mockConnectionCallback)
val driverDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.onDeviceDisconnectedInternal(driverDevice)
verify(mockConnectionCallback, never()).onDeviceDisconnected(driverDevice)
}
@Test
fun onDeviceDisconnected_passengerCallbacksInvokedWhenPassengerDeviceDisconnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerPassengerConnectionCallback(mockConnectionCallback)
val passengerDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ false,
/* hasSecureChannel= */ true
)
coordinator.onDeviceDisconnectedInternal(passengerDevice)
verify(mockConnectionCallback).onDeviceDisconnected(passengerDevice)
}
@Test
fun onDeviceDisconnected_allCallbacksInvokedWhenDriverDeviceDisconnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerAllConnectionCallback(mockConnectionCallback)
val driverDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.onDeviceDisconnectedInternal(driverDevice)
verify(mockConnectionCallback).onDeviceDisconnected(driverDevice)
}
@Test
fun onDeviceDisconnected_allCallbacksInvokedWhenPassengerDeviceDisconnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerAllConnectionCallback(mockConnectionCallback)
val passengerDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ false,
/* hasSecureChannel= */ true
)
coordinator.onDeviceDisconnectedInternal(passengerDevice)
verify(mockConnectionCallback).onDeviceDisconnected(passengerDevice)
}
@Test
fun unregisterConnectionCallback_driverCallbackNotInvokedWhenDeviceConnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerDriverConnectionCallback(mockConnectionCallback)
val driverDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.unregisterConnectionCallback(mockConnectionCallback)
coordinator.onDeviceConnectedInternal(driverDevice)
verify(mockConnectionCallback, never()).onDeviceConnected(driverDevice)
}
@Test
fun unregisterConnectionCallback_passengerCallbackNotInvokedWhenDeviceConnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerPassengerConnectionCallback(mockConnectionCallback)
val passengerDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ false,
/* hasSecureChannel= */ true
)
coordinator.unregisterConnectionCallback(mockConnectionCallback)
coordinator.onDeviceConnectedInternal(passengerDevice)
verify(mockConnectionCallback, never()).onDeviceConnected(passengerDevice)
}
@Test
fun unregisterConnectionCallback_allCallbackNotInvokedWhenDeviceConnects() {
val mockConnectionCallback: IConnectionCallback = mockToBeAlive()
coordinator.registerAllConnectionCallback(mockConnectionCallback)
val driverDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.unregisterConnectionCallback(mockConnectionCallback)
coordinator.onDeviceConnectedInternal(driverDevice)
verify(mockConnectionCallback, never()).onDeviceConnected(driverDevice)
}
@Test
fun registerDeviceCallback_sendsMissedMessages() {
val deviceCallback: IDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val missedMessage =
DeviceMessage.createOutgoingMessage(
recipientId.uuid,
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
coordinator.onMessageReceivedInternal(connectedDevice, missedMessage)
coordinator.registerDeviceCallback(connectedDevice, recipientId, deviceCallback)
verify(deviceCallback).onMessageReceived(connectedDevice, missedMessage)
}
@Test
fun registerDeviceCallback_blocksRecipientAndAlivePreviousRegistererIfIdAlreadyRegistered() {
val deviceCallback: IDeviceCallback = mockToBeAlive()
val duplicateDeviceCallback: IDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.registerDeviceCallback(connectedDevice, recipientId, deviceCallback)
coordinator.registerDeviceCallback(connectedDevice, recipientId, duplicateDeviceCallback)
verify(deviceCallback)
.onDeviceError(connectedDevice, DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED)
verify(duplicateDeviceCallback)
.onDeviceError(connectedDevice, DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED)
}
@Test
fun registerDeviceCallback_ignoreDeadPreviousRegistererIfIdAlreadyRegistered() {
val deadDeviceCallback: IDeviceCallback = mockToBeDead()
val duplicateDeviceCallback: IDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.registerDeviceCallback(connectedDevice, recipientId, deadDeviceCallback)
coordinator.registerDeviceCallback(connectedDevice, recipientId, duplicateDeviceCallback)
verify(duplicateDeviceCallback, never())
.onDeviceError(connectedDevice, DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED)
}
@Test
fun registerDeviceCallback_alreadyBlockedRecipientNotifiedOnRegistration() {
val deviceCallback: IDeviceCallback = mockToBeAlive()
val duplicateDeviceCallback: IDeviceCallback = mockToBeAlive()
val secondDuplicateDeviceCallback: IDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.registerDeviceCallback(connectedDevice, recipientId, deviceCallback)
coordinator.registerDeviceCallback(connectedDevice, recipientId, duplicateDeviceCallback)
coordinator.registerDeviceCallback(connectedDevice, recipientId, secondDuplicateDeviceCallback)
verify(secondDuplicateDeviceCallback)
.onDeviceError(connectedDevice, DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED)
}
@Test
fun unregisterDeviceCallback_callbackNotInvokedAfterUnregistering() {
val deviceCallback: IDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val message =
DeviceMessage.createOutgoingMessage(
recipientId.uuid,
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
coordinator.registerDeviceCallback(connectedDevice, recipientId, deviceCallback)
coordinator.unregisterDeviceCallback(connectedDevice, recipientId, deviceCallback)
coordinator.onMessageReceivedInternal(connectedDevice, message)
verify(deviceCallback, never()).onMessageReceived(any(), any())
}
@Test
fun onMessageReceived_callbackInvokedWhenMessageReceivedForRecipient() {
val deviceCallback: IDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val message =
DeviceMessage.createOutgoingMessage(
recipientId.uuid,
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
coordinator.registerDeviceCallback(connectedDevice, recipientId, deviceCallback)
coordinator.onMessageReceivedInternal(connectedDevice, message)
verify(deviceCallback).onMessageReceived(connectedDevice, message)
}
@Test
fun onMessageReceived_callbackNotInvokedWhenMessageReceivedForDifferentRecipient() {
val deviceCallback: IDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val otherRecipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val message =
DeviceMessage.createOutgoingMessage(
otherRecipientId.uuid,
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
coordinator.registerDeviceCallback(connectedDevice, recipientId, deviceCallback)
coordinator.onMessageReceivedInternal(connectedDevice, message)
verify(deviceCallback, never()).onMessageReceived(any(), any())
}
@Test
fun onMessageReceived_blockedRecipientCallbacksNotInvoked() {
val deviceCallback: IDeviceCallback = mockToBeAlive()
val duplicateDeviceCallback: IDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val message =
DeviceMessage.createOutgoingMessage(
recipientId.uuid,
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
coordinator.registerDeviceCallback(connectedDevice, recipientId, deviceCallback)
coordinator.registerDeviceCallback(connectedDevice, recipientId, duplicateDeviceCallback)
coordinator.onMessageReceivedInternal(connectedDevice, message)
verify(deviceCallback, never()).onMessageReceived(any(), any())
verify(duplicateDeviceCallback, never()).onMessageReceived(any(), any())
}
@Test
fun onMessageReceived_blockedRecipientRecoverFromResetCallbacksInvoked() {
val deviceCallback: IDeviceCallback = mockToBeAlive()
val duplicateDeviceCallback: IDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.registerDeviceCallback(connectedDevice, recipientId, deviceCallback)
coordinator.registerDeviceCallback(connectedDevice, recipientId, duplicateDeviceCallback)
/* Clear the blocked recipient list. */
coordinator.reset()
coordinator.registerDeviceCallback(connectedDevice, recipientId, deviceCallback)
val message =
DeviceMessage.createOutgoingMessage(
recipientId.uuid,
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
coordinator.onMessageReceivedInternal(connectedDevice, message)
verify(deviceCallback).onMessageReceived(any(), any())
verify(duplicateDeviceCallback, never()).onMessageReceived(any(), any())
}
@Test
fun onMessageReceived_nullRecipientDoesNotThrow() {
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val nullRecipientMessage =
DeviceMessage.createOutgoingMessage(
/* recipient= */ null,
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
coordinator.onMessageReceivedInternal(connectedDevice, nullRecipientMessage)
}
@Test
fun sendMessage_sendsMessageToController() {
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val message =
DeviceMessage.createOutgoingMessage(
UUID.randomUUID(),
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
coordinator.sendMessage(connectedDevice, message)
verify(mockController).sendMessage(UUID.fromString(connectedDevice.deviceId), message)
}
@Test
fun startAssociation_startsAssociationWithCorrectlySizedName() {
val associationCallback: IAssociationCallback = mockToBeAlive()
coordinator.startAssociation(associationCallback)
argumentCaptor<String>().apply {
verify(mockController).startAssociation(capture(), eq(associationCallback), isNull())
assertThat(firstValue).hasLength(DEVICE_NAME_LENGTH + 2) // Starts with 0x so add 2
}
}
@Test
fun startAssociationWithIdentifier_startsAssociationWithCorrectlySizedName() {
val associationCallback: IAssociationCallback = mockToBeAlive()
val identifier = ParcelUuid(UUID.randomUUID())
coordinator.startAssociationWithIdentifier(associationCallback, identifier)
argumentCaptor<String>().apply {
verify(mockController)
.startAssociation(capture(), eq(associationCallback), eq(identifier.uuid))
assertThat(firstValue).hasLength(DEVICE_NAME_LENGTH + 2) // Starts with 0x so add 2
}
}
@Test
fun onSecureChannelEstablished_invokesAllRegisteredDeviceCallbacks() {
val deviceCallback: IDeviceCallback = mockToBeAlive()
val secondDeviceCallback: IDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val secondRecipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.registerDeviceCallback(connectedDevice, recipientId, deviceCallback)
coordinator.registerDeviceCallback(connectedDevice, secondRecipientId, secondDeviceCallback)
coordinator.onSecureChannelEstablishedInternal(connectedDevice)
verify(deviceCallback).onSecureChannelEstablished(connectedDevice)
verify(secondDeviceCallback).onSecureChannelEstablished(connectedDevice)
}
@Test
fun onSecureChannelEstablished_doesNotInvokeCallbacksRegisteredToDifferentDevice() {
val deviceCallback: IDeviceCallback = mockToBeAlive()
val otherDeviceCallback: IDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val otherRecipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val otherConnectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
coordinator.registerDeviceCallback(connectedDevice, recipientId, deviceCallback)
coordinator.registerDeviceCallback(otherConnectedDevice, otherRecipientId, otherDeviceCallback)
coordinator.onSecureChannelEstablishedInternal(connectedDevice)
verify(deviceCallback).onSecureChannelEstablished(connectedDevice)
verify(otherDeviceCallback, never()).onSecureChannelEstablished(connectedDevice)
}
@Test
fun onAssociatedDeviceAdded_invokesCallbacks() {
val callback: IDeviceAssociationCallback = mockToBeAlive()
coordinator.registerDeviceAssociationCallback(callback)
val associatedDevice =
AssociatedDevice(
UUID.randomUUID().toString(),
"deviceAddress",
"deviceName",
/* isConnectionEnabled= */ true
)
coordinator.onAssociatedDeviceAddedInternal(associatedDevice)
verify(callback).onAssociatedDeviceAdded(associatedDevice)
}
@Test
fun onAssociatedDeviceRemoved_invokesCallbacks() {
val callback: IDeviceAssociationCallback = mockToBeAlive()
coordinator.registerDeviceAssociationCallback(callback)
val associatedDevice =
AssociatedDevice(
UUID.randomUUID().toString(),
"deviceAddress",
"deviceName",
/* isConnectionEnabled= */ true
)
coordinator.onAssociatedDeviceRemovedInternal(associatedDevice)
verify(callback).onAssociatedDeviceRemoved(associatedDevice)
}
@Test
fun onAssociatedDeviceUpdated_invokesCallbacks() {
val callback: IDeviceAssociationCallback = mockToBeAlive()
coordinator.registerDeviceAssociationCallback(callback)
val associatedDevice =
AssociatedDevice(
UUID.randomUUID().toString(),
"deviceAddress",
"deviceName",
/* isConnectionEnabled= */ true
)
coordinator.onAssociatedDeviceUpdatedInternal(associatedDevice)
verify(callback).onAssociatedDeviceUpdated(associatedDevice)
}
@Test
fun unregisterDeviceAssociationCallback_preventsFutureInvocation() {
val callback: IDeviceAssociationCallback = mockToBeAlive()
coordinator.registerDeviceAssociationCallback(callback)
val associatedDevice =
AssociatedDevice(
UUID.randomUUID().toString(),
"deviceAddress",
"deviceName",
/* isConnectionEnabled= */ true
)
coordinator.unregisterDeviceAssociationCallback(callback)
coordinator.onAssociatedDeviceAddedInternal(associatedDevice)
verify(callback, never()).onAssociatedDeviceAdded(associatedDevice)
}
@Test
fun acceptVerification_notifiesControllerCodeAccepted() {
coordinator.acceptVerification()
verify(mockController).notifyVerificationCodeAccepted()
}
@Test
fun removeAssociatedDevice_disconnectsAndRemovesAssociatedDeviceFromStorage() {
val deviceId = UUID.randomUUID()
coordinator.removeAssociatedDevice(deviceId.toString())
verify(mockController).disconnectDevice(deviceId)
verify(mockStorage).removeAssociatedDevice(deviceId.toString())
}
@Test
fun enableAssociatedDeviceConnection_updatesStorageAndInitiatesConnection() {
val deviceId = UUID.randomUUID()
coordinator.enableAssociatedDeviceConnection(deviceId.toString())
verify(mockStorage)
.updateAssociatedDeviceConnectionEnabled(deviceId.toString(), /* isConnectionEnabled= */ true)
verify(mockController).initiateConnectionToDevice(deviceId)
}
@Test
fun disableAssociatedDeviceConnection_updatesStorageAndDisconnectsDevice() {
val deviceId = UUID.randomUUID()
coordinator.disableAssociatedDeviceConnection(deviceId.toString())
verify(mockStorage)
.updateAssociatedDeviceConnectionEnabled(
deviceId.toString(),
/* isConnectionEnabled= */ false
)
verify(mockController).disconnectDevice(deviceId)
}
@Test
fun retrieveAssociatedDevices_returnsAllAssociatedDevicesInStorage() {
val associatedDevices =
listOf(
AssociatedDevice(
UUID.randomUUID().toString(),
/* deviceAddress= */ "",
/* deviceName= */ null,
/* isConnectionEnabled= */ true
),
AssociatedDevice(
UUID.randomUUID().toString(),
/* deviceAddress= */ "",
/* deviceName= */ null,
/* isConnectionEnabled= */ false
)
)
val listener: IOnAssociatedDevicesRetrievedListener = mockToBeAlive()
whenever(mockStorage.allAssociatedDevices).thenReturn(associatedDevices)
coordinator.retrieveAssociatedDevices(listener)
verify(listener).onAssociatedDevicesRetrieved(associatedDevices)
}
@Test
fun retrieveAssociatedDevicesForDriver_returnsOnlyDriverDevicesInStorage() {
val driverDevices =
listOf(
AssociatedDevice(
UUID.randomUUID().toString(),
/* deviceAddress= */ "",
/* deviceName= */ null,
/* isConnectionEnabled= */ true
),
AssociatedDevice(
UUID.randomUUID().toString(),
/* deviceAddress= */ "",
/* deviceName= */ null,
/* isConnectionEnabled= */ false
)
)
val listener: IOnAssociatedDevicesRetrievedListener = mockToBeAlive()
whenever(mockStorage.driverAssociatedDevices).thenReturn(driverDevices)
coordinator.retrieveAssociatedDevicesForDriver(listener)
verify(listener).onAssociatedDevicesRetrieved(driverDevices)
}
@Test
fun retrieveAssociatedDevicesForPassengers_returnsOnlyPassengerDevicesInStorage() {
val passengerDevices =
listOf(
AssociatedDevice(
UUID.randomUUID().toString(),
/* deviceAddress= */ "",
/* deviceName= */ null,
/* isConnectionEnabled= */ true
),
AssociatedDevice(
UUID.randomUUID().toString(),
/* deviceAddress= */ "",
/* deviceName= */ null,
/* isConnectionEnabled= */ false
)
)
val listener: IOnAssociatedDevicesRetrievedListener = mockToBeAlive()
whenever(mockStorage.passengerAssociatedDevices).thenReturn(passengerDevices)
coordinator.retrieveAssociatedDevicesForPassengers(listener)
verify(listener).onAssociatedDevicesRetrieved(passengerDevices)
}
@Test
fun registerOnLogRequestedListener() {
val testLoggerId = 0
val listener: ISafeOnLogRequestedListener = mockToBeAlive()
coordinator.registerOnLogRequestedListener(testLoggerId, listener)
verify(mockLoggingManager).registerLogRequestedListener(eq(testLoggerId), eq(listener), any())
}
@Test
fun unregisterOnLogRequestedListener() {
val testLoggerId = 0
val listener: ISafeOnLogRequestedListener = mockToBeAlive()
coordinator.unregisterOnLogRequestedListener(testLoggerId, listener)
verify(mockLoggingManager).unregisterLogRequestedListener(eq(testLoggerId), eq(listener))
}
@Test
fun processLogRecords() {
val testLoggerId = 0
val testLogs = "test logs".toByteArray()
coordinator.processLogRecords(testLoggerId, testLogs)
verify(mockLoggingManager).prepareLocalLogRecords(eq(testLoggerId), eq(testLogs))
}
@Test
fun stopAssociation_directCallIntoDeviceController() {
coordinator.stopAssociation()
verify(mockController).stopAssociation()
}
@Test
fun start_startsController() {
coordinator.start()
verify(mockController).start()
}
@Test
fun reset_resetsController() {
coordinator.reset()
verify(mockController).reset()
}
@Test
fun claimAssociatedDevice_disconnectsAndClaimsDeviceAndInitiatesReconnection() {
val deviceId = UUID.randomUUID()
coordinator.claimAssociatedDevice(deviceId.toString())
verify(mockController).disconnectDevice(deviceId)
verify(mockStorage).claimAssociatedDevice(deviceId.toString())
verify(mockController).initiateConnectionToDevice(deviceId)
}
@Test
fun removeAssociatedDeviceClaim_disconnectsAndRemovesClaimAndInitiatesReconnection() {
val deviceId = UUID.randomUUID()
coordinator.removeAssociatedDeviceClaim(deviceId.toString())
verify(mockController).disconnectDevice(deviceId)
verify(mockStorage).removeAssociatedDeviceClaim(deviceId.toString())
verify(mockController).initiateConnectionToDevice(deviceId)
}
// The following tests are for the SafeFeatureCoordinator contained in FeatureCoordinator.
@Test
fun safeFC_getConnectedDevices_returnsOnlyDriverDevices() {
val driverDevice1 =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName1",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val driverDevice2 =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName2",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val passengerDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"passengerDeviceName",
/* belongsToDriver= */ false,
/* hasSecureChannel= */ true
)
whenever(mockController.connectedDevices)
.thenReturn(listOf(driverDevice1, passengerDevice, driverDevice2))
val driverDevices = safeCoordinator.getConnectedDevices()
assertThat(driverDevices).containsExactly(driverDevice1.deviceId, driverDevice2.deviceId)
}
@Test
fun safeFC_onDeviceConnected_connectionCallbacksInvoked() {
val mockConnectionCallback: ISafeConnectionCallback = mockToBeAlive()
safeCoordinator.registerConnectionCallback(mockConnectionCallback)
val deviceId = UUID.randomUUID().toString()
coordinator.safeOnDeviceConnectedInternal(deviceId)
verify(mockConnectionCallback).onDeviceConnected(deviceId)
}
@Test
fun safeFC_onDeviceDisconnected_connectionCallbacksInvoked() {
val mockConnectionCallback: ISafeConnectionCallback = mockToBeAlive()
safeCoordinator.registerConnectionCallback(mockConnectionCallback)
val deviceId = UUID.randomUUID().toString()
coordinator.safeOnDeviceDisconnectedInternal(deviceId)
verify(mockConnectionCallback).onDeviceDisconnected(deviceId)
}
@Test
fun safeFC_unregisterConnectionCallback_connectionCallbackNotInvokedWhenDeviceConnects() {
val mockConnectionCallback: ISafeConnectionCallback = mockToBeAlive()
safeCoordinator.registerConnectionCallback(mockConnectionCallback)
val deviceId = UUID.randomUUID().toString()
safeCoordinator.unregisterConnectionCallback(mockConnectionCallback)
coordinator.safeOnDeviceConnectedInternal(deviceId)
verify(mockConnectionCallback, never()).onDeviceConnected(deviceId)
}
@Test
fun safeFC_registerDeviceCallback_sendsMissedMessages() {
val deviceCallback: ISafeDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val message =
DeviceMessageProto.Message.newBuilder()
.setRecipient(ByteString.copyFrom(ByteUtils.uuidToBytes(recipientId.uuid)))
.setIsPayloadEncrypted(true)
.setOperation(
OperationType.forNumber(/* CLIENT_MESSAGE */ 4) ?: OperationType.OPERATION_TYPE_UNKNOWN
)
.setPayload(ByteString.copyFrom(ByteUtils.randomBytes(10)))
.build()
val rawBytes = message.toByteArray()
val missedMessage =
DeviceMessage.createOutgoingMessage(
ByteUtils.bytesToUUID(message.recipient.toByteArray()),
message.isPayloadEncrypted,
DeviceMessage.OperationType.fromValue(message.operation.number),
message.payload.toByteArray()
)
coordinator.onMessageReceivedInternal(connectedDevice, missedMessage)
safeCoordinator.registerDeviceCallback(connectedDevice.deviceId, recipientId, deviceCallback)
verify(deviceCallback).onMessageReceived(connectedDevice.deviceId, rawBytes)
}
@Test
fun safeFC_registerDeviceCallback_blocksRecipientAndAlivePreviousRegistererIfAlreadyRegistered() {
val deviceCallback: ISafeDeviceCallback = mockToBeAlive()
val duplicateDeviceCallback: ISafeDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
safeCoordinator.registerDeviceCallback(connectedDevice.deviceId, recipientId, deviceCallback)
safeCoordinator.registerDeviceCallback(
connectedDevice.deviceId,
recipientId,
duplicateDeviceCallback
)
verify(deviceCallback)
.onDeviceError(connectedDevice.deviceId, DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED)
verify(duplicateDeviceCallback)
.onDeviceError(connectedDevice.deviceId, DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED)
}
@Test
fun safeFC_registerDeviceCallback_ignoreDeadPreviousRegistererIfAlreadyRegistered() {
val deadDeviceCallback: ISafeDeviceCallback = mockToBeDead()
val duplicateDeviceCallback: ISafeDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
safeCoordinator.registerDeviceCallback(
connectedDevice.deviceId,
recipientId,
deadDeviceCallback
)
safeCoordinator.registerDeviceCallback(
connectedDevice.deviceId,
recipientId,
duplicateDeviceCallback
)
verify(duplicateDeviceCallback, never())
.onDeviceError(connectedDevice.deviceId, DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED)
}
@Test
fun safeFC_registerDeviceCallback_alreadyBlockedRecipientNotifiedOnRegistration() {
val deviceCallback: ISafeDeviceCallback = mockToBeAlive()
val duplicateDeviceCallback: ISafeDeviceCallback = mockToBeAlive()
val secondDuplicateDeviceCallback: ISafeDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
safeCoordinator.registerDeviceCallback(connectedDevice.deviceId, recipientId, deviceCallback)
safeCoordinator.registerDeviceCallback(
connectedDevice.deviceId,
recipientId,
duplicateDeviceCallback
)
safeCoordinator.registerDeviceCallback(
connectedDevice.deviceId,
recipientId,
secondDuplicateDeviceCallback
)
verify(secondDuplicateDeviceCallback)
.onDeviceError(connectedDevice.deviceId, DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED)
}
@Test
fun safeFC_unregisterDeviceCallback_callbackNotInvokedAfterUnregistering() {
val deviceCallback: ISafeDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val message =
DeviceMessage.createOutgoingMessage(
recipientId.uuid,
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
safeCoordinator.registerDeviceCallback(connectedDevice.deviceId, recipientId, deviceCallback)
safeCoordinator.unregisterDeviceCallback(connectedDevice.deviceId, recipientId, deviceCallback)
coordinator.onMessageReceivedInternal(connectedDevice, message)
verify(deviceCallback, never()).onMessageReceived(any(), any())
}
@Test
fun safeFC_onMessageReceived_callbackInvokedWhenMessageReceivedForRecipient() {
val deviceCallback: ISafeDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val message =
DeviceMessage.createOutgoingMessage(
recipientId.uuid,
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
safeCoordinator.registerDeviceCallback(connectedDevice.deviceId, recipientId, deviceCallback)
coordinator.onMessageReceivedInternal(connectedDevice, message)
verify(deviceCallback).onMessageReceived(connectedDevice.deviceId, message.message)
}
@Test
fun safeFC_onMessageReceived_callbackNotInvokedWhenMessageReceivedForDifferentRecipient() {
val deviceCallback: ISafeDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val otherRecipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val message =
DeviceMessage.createOutgoingMessage(
otherRecipientId.uuid,
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
safeCoordinator.registerDeviceCallback(connectedDevice.deviceId, recipientId, deviceCallback)
coordinator.onMessageReceivedInternal(connectedDevice, message)
verify(deviceCallback, never()).onMessageReceived(any(), any())
}
@Test
fun safeFC_onMessageReceived_blockedRecipientCallbacksNotInvoked() {
val deviceCallback: ISafeDeviceCallback = mockToBeAlive()
val duplicateDeviceCallback: ISafeDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val message =
DeviceMessage.createOutgoingMessage(
recipientId.uuid,
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
safeCoordinator.registerDeviceCallback(connectedDevice.deviceId, recipientId, deviceCallback)
safeCoordinator.registerDeviceCallback(
connectedDevice.deviceId,
recipientId,
duplicateDeviceCallback
)
coordinator.onMessageReceivedInternal(connectedDevice, message)
verify(deviceCallback, never()).onMessageReceived(any(), any())
verify(duplicateDeviceCallback, never()).onMessageReceived(any(), any())
}
@Test
fun safeFC_onMessageReceived_blockedRecipientRecoverFromResetCallbacksInvoked() {
val deviceCallback: ISafeDeviceCallback = mockToBeAlive()
val duplicateDeviceCallback: ISafeDeviceCallback = mockToBeAlive()
val recipientId = ParcelUuid(UUID.randomUUID())
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
safeCoordinator.registerDeviceCallback(connectedDevice.deviceId, recipientId, deviceCallback)
safeCoordinator.registerDeviceCallback(
connectedDevice.deviceId,
recipientId,
duplicateDeviceCallback
)
// Clear the blocked recipient list.
coordinator.reset()
safeCoordinator.registerDeviceCallback(connectedDevice.deviceId, recipientId, deviceCallback)
val message =
DeviceMessage.createOutgoingMessage(
recipientId.uuid,
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
coordinator.onMessageReceivedInternal(connectedDevice, message)
verify(deviceCallback).onMessageReceived(any(), any())
verify(duplicateDeviceCallback, never()).onMessageReceived(any(), any())
}
@Test
fun safeFC_onMessageReceived_nullRecipientDoesNotThrow() {
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val nullRecipientMessage =
DeviceMessage.createOutgoingMessage(
/* recipient= */ null,
/* isMessageEncrypted= */ true,
CLIENT_MESSAGE,
ByteUtils.randomBytes(10)
)
coordinator.onMessageReceivedInternal(connectedDevice, nullRecipientMessage)
}
@Test
fun safeFC_sendMessage_sendsMessageToController() {
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"testDeviceName",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val message =
DeviceMessageProto.Message.newBuilder()
.setRecipient(ByteString.copyFrom(ByteUtils.uuidToBytes(UUID.randomUUID())))
.setIsPayloadEncrypted(true)
.setOperation(
OperationType.forNumber(/* CLIENT_MESSAGE */ 4) ?: OperationType.OPERATION_TYPE_UNKNOWN
)
.setPayload(ByteString.copyFrom(ByteUtils.randomBytes(10)))
.build()
val rawBytes = message.toByteArray()
val messageSent = safeCoordinator.sendMessage(connectedDevice.deviceId, rawBytes)
val deviceMessage =
DeviceMessage.createOutgoingMessage(
ByteUtils.bytesToUUID(message.recipient.toByteArray()),
message.isPayloadEncrypted,
DeviceMessage.OperationType.fromValue(message.operation.number),
message.payload.toByteArray()
)
assertThat(messageSent).isFalse() // Recipient not registered so this will return false
verify(mockController).sendMessage(UUID.fromString(connectedDevice.deviceId), deviceMessage)
}
@Test
fun safeFC_registerOnLogRequestedListener() {
val testLoggerId = 0
val listener: ISafeOnLogRequestedListener = mockToBeAlive()
safeCoordinator.registerOnLogRequestedListener(testLoggerId, listener)
verify(mockLoggingManager).registerLogRequestedListener(eq(testLoggerId), eq(listener), any())
}
@Test
fun safeFC_unregisterOnLogRequestedListener() {
val testLoggerId = 0
val listener: ISafeOnLogRequestedListener = mockToBeAlive()
safeCoordinator.unregisterOnLogRequestedListener(testLoggerId, listener)
verify(mockLoggingManager).unregisterLogRequestedListener(eq(testLoggerId), eq(listener))
}
@Test
fun safeFC_processLogRecords() {
val testLoggerId = 0
val testLogs = "test logs".toByteArray()
safeCoordinator.processLogRecords(testLoggerId, testLogs)
verify(mockLoggingManager).prepareLocalLogRecords(eq(testLoggerId), eq(testLogs))
}
@Test
fun safeFC_retrieveAssociatedDevices_returnsOnlyDriverDevicesInStorage() {
val driverDevices =
listOf(
AssociatedDevice(
UUID.randomUUID().toString(),
/* deviceAddress= */ "",
/* deviceName= */ null,
/* isConnectionEnabled= */ true
),
AssociatedDevice(
UUID.randomUUID().toString(),
/* deviceAddress= */ "",
/* deviceName= */ null,
/* isConnectionEnabled= */ false
)
)
val listener: ISafeOnAssociatedDevicesRetrievedListener = mockToBeAlive()
whenever(mockStorage.driverAssociatedDevices).thenReturn(driverDevices)
safeCoordinator.retrieveAssociatedDevices(listener)
verify(listener).onAssociatedDevicesRetrieved(driverDevices.map { it.deviceId })
}
companion object {
private const val TAG = "FeatureCoordinatorTest"
}
}