blob: 3abbb32a49303b765e4028a80d2bbe85da22ac8e [file] [log] [blame]
package com.google.android.connecteddevice.api
import android.os.ParcelUuid
import android.os.RemoteException
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.android.companionprotos.OperationProto.OperationType
import com.google.android.companionprotos.Query
import com.google.android.companionprotos.QueryResponse
import com.google.android.connecteddevice.api.SafeConnector.QueryCallback
import com.google.android.connecteddevice.api.external.ISafeOnAssociatedDevicesRetrievedListener
import com.google.android.connecteddevice.api.external.ISafeOnLogRequestedListener
import com.google.android.connecteddevice.core.util.mockToBeAlive
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.util.ByteUtils
import com.google.common.truth.Truth.assertThat
import com.google.protobuf.ByteString
import java.util.UUID
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class LegacyApiProxyTest {
private val negativeMockCoordinator: IFeatureCoordinator = mock()
private val versionZeroMockCoordinator: IFeatureCoordinator = mock()
private val versionOneMockCoordinator: IFeatureCoordinator = mock()
private val recipientId = ParcelUuid(UUID.randomUUID())
private val mockConnectorCallback: SafeConnector.Callback = mock()
private val testLoggerId = 0
private val mockListener: ISafeOnLogRequestedListener = mock()
private lateinit var defaultProxyVersionNegative: LegacyApiProxy
private lateinit var defaultProxyVersion0: LegacyApiProxy
private lateinit var defaultProxyVersion1: LegacyApiProxy
@Before
fun setUp() {
val connectedDevice =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName1",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
whenever(versionZeroMockCoordinator.getConnectedDevicesForDriver())
.thenReturn(listOf(connectedDevice))
whenever(versionOneMockCoordinator.getConnectedDevicesForDriver())
.thenReturn(listOf(connectedDevice))
defaultProxyVersionNegative =
LegacyApiProxy(negativeMockCoordinator, recipientId, mockConnectorCallback, testLoggerId, -1)
defaultProxyVersion0 =
LegacyApiProxy(
versionZeroMockCoordinator,
recipientId,
mockConnectorCallback,
testLoggerId,
0
)
defaultProxyVersion1 =
LegacyApiProxy(versionOneMockCoordinator, recipientId, mockConnectorCallback, testLoggerId, 1)
}
@Test
fun onInit_doesNotInvokeCoordinator_onPlatformVersionLessThanZero() {
verify(negativeMockCoordinator, never()).registerAllConnectionCallback(any())
verify(negativeMockCoordinator, never()).registerDeviceCallback(any(), any(), any())
verify(negativeMockCoordinator, never()).registerOnLogRequestedListener(any(), any())
}
@Test
fun onInit_correctlyInvokesCoordinator_onPlatformVersionZero() {
verify(versionZeroMockCoordinator).registerAllConnectionCallback(any())
verify(versionZeroMockCoordinator).registerDeviceCallback(any(), any(), any())
verify(versionZeroMockCoordinator).registerOnLogRequestedListener(any(), any())
}
@Test
fun onInit_correctlyInvokesCoordinator_onPlatformVersionOne() {
verify(versionOneMockCoordinator).registerAllConnectionCallback(any())
verify(versionOneMockCoordinator).registerDeviceCallback(any(), any(), any())
verify(versionOneMockCoordinator).registerOnLogRequestedListener(any(), any())
}
@Test
fun getConnectedDevices_returnsNullOnVersionLessThanZero() {
val device1 =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName1",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val device2 =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName2",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
whenever(negativeMockCoordinator.getConnectedDevicesForDriver())
.thenReturn(listOf(device1, device2))
val devices = defaultProxyVersionNegative.getConnectedDevices()
assertThat(devices).isNull()
}
@Test
fun getConnectedDevices_returnsListOnVersionZero() {
val device1 =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName1",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val device2 =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName2",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
whenever(versionZeroMockCoordinator.getConnectedDevicesForDriver())
.thenReturn(listOf(device1, device2))
val devices = defaultProxyVersion0.getConnectedDevices()
assertThat(devices).containsExactly(device1.deviceId, device2.deviceId)
}
@Test
fun getConnectedDevices_returnsListOnVersionGreaterThanZero() {
val device1 =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName1",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
val device2 =
ConnectedDevice(
UUID.randomUUID().toString(),
"driverDeviceName2",
/* belongsToDriver= */ true,
/* hasSecureChannel= */ true
)
whenever(versionOneMockCoordinator.getConnectedDevicesForDriver())
.thenReturn(listOf(device1, device2))
val devices = defaultProxyVersion1.getConnectedDevices()
assertThat(devices).containsExactly(device1.deviceId, device2.deviceId)
}
@Test
fun sendMessage_returnsFalseOnVersionLessThanZero() {
val connectedDevice: ConnectedDevice = mock()
val deviceId = UUID.randomUUID().toString()
val message = ByteUtils.randomBytes(10)
val deviceMessage =
DeviceMessage.createOutgoingMessage(
UUID.fromString(deviceId),
/* isMessageEncrypted= */ true,
DeviceMessage.OperationType.CLIENT_MESSAGE,
message
)
whenever(connectedDevice.deviceId).thenReturn(deviceId)
whenever(negativeMockCoordinator.getConnectedDevicesForDriver())
.thenReturn(listOf(connectedDevice))
whenever(negativeMockCoordinator.sendMessage(connectedDevice, deviceMessage)).thenReturn(true)
val messageSent = defaultProxyVersionNegative.sendMessage(deviceId, message)
assertThat(messageSent).isFalse()
}
@Test
fun sendMessage_sendsMessageToControllerOnVersionZero() {
val connectedDevice: ConnectedDevice = mock()
val deviceId = UUID.randomUUID().toString()
val message = ByteUtils.randomBytes(10)
val deviceMessage =
DeviceMessage.createOutgoingMessage(
UUID.fromString(deviceId),
/* isMessageEncrypted= */ true,
DeviceMessage.OperationType.CLIENT_MESSAGE,
message
)
whenever(connectedDevice.deviceId).thenReturn(deviceId)
whenever(versionZeroMockCoordinator.getConnectedDevicesForDriver())
.thenReturn(listOf(connectedDevice))
whenever(versionZeroMockCoordinator.sendMessage(connectedDevice, deviceMessage))
.thenReturn(true)
val messageSent = defaultProxyVersion0.sendMessage(deviceId, message)
assertThat(messageSent).isTrue()
}
@Test
fun sendMessage_sendsMessageToControllerOnVersionGreaterThanZero() {
val connectedDevice: ConnectedDevice = mock()
val deviceId = UUID.randomUUID().toString()
val message = ByteUtils.randomBytes(10)
val deviceMessage =
DeviceMessage.createOutgoingMessage(
UUID.fromString(deviceId),
/* isMessageEncrypted= */ true,
DeviceMessage.OperationType.CLIENT_MESSAGE,
message
)
whenever(connectedDevice.deviceId).thenReturn(deviceId)
whenever(versionOneMockCoordinator.getConnectedDevicesForDriver())
.thenReturn(listOf(connectedDevice))
whenever(versionOneMockCoordinator.sendMessage(connectedDevice, deviceMessage)).thenReturn(true)
val messageSent = defaultProxyVersion1.sendMessage(deviceId, message)
assertThat(messageSent).isTrue()
}
@Test
fun sendMessage_failsToSendMessageUsingInvalidDeviceIdOnVersionZero() {
val connectedDevice: ConnectedDevice = mock()
val deviceId1 = "connectedDevice"
val deviceId2 = "disconnectedDevice"
val message = ByteUtils.randomBytes(10)
whenever(connectedDevice.deviceId).thenReturn(deviceId1)
whenever(versionZeroMockCoordinator.getConnectedDevicesForDriver())
.thenReturn(listOf(connectedDevice))
whenever(versionZeroMockCoordinator.sendMessage(any(), any())).thenReturn(true)
val messageSent = defaultProxyVersion0.sendMessage(deviceId2, message)
assertThat(messageSent).isFalse()
}
@Test
fun sendMessage_failsToSendMessageUsingInvalidDeviceIdOnVersionGreaterThanZero() {
val connectedDevice: ConnectedDevice = mock()
val deviceId1 = "connectedDevice"
val deviceId2 = "disconnectedDevice"
val message = ByteUtils.randomBytes(10)
whenever(connectedDevice.deviceId).thenReturn(deviceId1)
whenever(versionOneMockCoordinator.getConnectedDevicesForDriver())
.thenReturn(listOf(connectedDevice))
whenever(versionOneMockCoordinator.sendMessage(any(), any())).thenReturn(true)
val messageSent = defaultProxyVersion1.sendMessage(deviceId2, message)
assertThat(messageSent).isFalse()
}
@Test
fun sendMessage_failsIfCoordinatorThrowsException() {
val connectedDevice: ConnectedDevice = mock()
val deviceId = UUID.randomUUID().toString()
val message = ByteUtils.randomBytes(10)
val deviceMessage =
DeviceMessage.createOutgoingMessage(
UUID.fromString(deviceId),
/* isMessageEncrypted= */ true,
DeviceMessage.OperationType.CLIENT_MESSAGE,
message
)
whenever(connectedDevice.deviceId).thenReturn(deviceId)
whenever(versionOneMockCoordinator.getConnectedDevicesForDriver())
.thenReturn(listOf(connectedDevice))
whenever(versionZeroMockCoordinator.sendMessage(connectedDevice, deviceMessage))
.thenThrow(RemoteException())
val messageSent = defaultProxyVersion0.sendMessage(UUID.randomUUID().toString(), message)
assertThat(messageSent).isFalse()
}
@Test
fun processLogRecords_returnsFalseOnVersionLessThanZero() {
val testLogs = "test logs".toByteArray()
val success = defaultProxyVersionNegative.processLogRecords(testLoggerId, testLogs)
assertThat(success).isFalse()
}
@Test
fun processLogRecords_returnsTrueOnVersionZero() {
val testLogs = "test logs".toByteArray()
val success = defaultProxyVersion0.processLogRecords(testLoggerId, testLogs)
assertThat(success).isTrue()
}
@Test
fun processLogRecords_returnsTrueOnVersionGreaterThanZero() {
val testLogs = "test logs".toByteArray()
val success = defaultProxyVersion1.processLogRecords(testLoggerId, testLogs)
assertThat(success).isTrue()
}
@Test
fun retrieveAssociatedDevices_returnsFalseOnVersionLessThanZero() {
val mockListener: IOnAssociatedDevicesRetrievedListener = mockToBeAlive()
val success = defaultProxyVersionNegative.retrieveAssociatedDevices(mockListener)
assertThat(success).isFalse()
}
@Test
fun retrieveAssociatedDevices_returnsTrueOnVersionZero() {
val mockListener: IOnAssociatedDevicesRetrievedListener = mockToBeAlive()
val success = defaultProxyVersion0.retrieveAssociatedDevices(mockListener)
assertThat(success).isTrue()
}
@Test
fun retrieveAssociatedDevices_returnsTrueOnVersionGreaterThanZero() {
val mockListener: IOnAssociatedDevicesRetrievedListener = mockToBeAlive()
val success = defaultProxyVersion1.retrieveAssociatedDevices(mockListener)
assertThat(success).isTrue()
}
@Test
fun retrieveAssociatedDevices_returnsFalseIfIncorrectParam() {
val mockListener: ISafeOnAssociatedDevicesRetrievedListener = mockToBeAlive()
val success = defaultProxyVersion0.retrieveAssociatedDevices(mockListener)
assertThat(success).isFalse()
}
@Test
fun processIncomingMessage_worksWithClientMessage() {
val deviceId = UUID.randomUUID().toString()
val mockConnectedDevice: ConnectedDevice = mock()
whenever(mockConnectedDevice.deviceId).thenReturn(deviceId)
val payload = ByteString.copyFrom(ByteUtils.randomBytes(10)).toByteArray()
val message =
DeviceMessage.createOutgoingMessage(
UUID.randomUUID(),
/* isMessageEncrypted= */ true,
DeviceMessage.OperationType.CLIENT_MESSAGE,
payload
)
defaultProxyVersion0.deviceCallback.onMessageReceived(mockConnectedDevice, message)
verify(mockConnectorCallback).onMessageReceived(deviceId, payload)
}
@Test
fun processIncomingMessage_worksWithQuery() {
val deviceId = UUID.randomUUID().toString()
val mockConnectedDevice: ConnectedDevice = mock()
whenever(mockConnectedDevice.deviceId).thenReturn(deviceId)
val payload =
Query.newBuilder()
.setId(1)
.setSender(ByteString.copyFrom(ByteUtils.uuidToBytes(recipientId.uuid)))
.setRequest(ByteString.copyFrom(ByteUtils.randomBytes(10)))
.setParameters(ByteString.copyFrom(ByteUtils.randomBytes(10)))
.build()
.toByteArray()
val message =
DeviceMessage.createOutgoingMessage(
UUID.randomUUID(),
/* isMessageEncrypted= */ true,
DeviceMessage.OperationType.QUERY,
payload
)
defaultProxyVersion0.deviceCallback.onMessageReceived(mockConnectedDevice, message)
verify(mockConnectorCallback).onQueryReceived(eq(deviceId), any(), any(), any())
}
@Test
fun processIncomingMessage_worksWithQueryResponse() {
val deviceId = UUID.randomUUID().toString()
val mockConnectedDevice: ConnectedDevice = mock()
whenever(mockConnectedDevice.deviceId).thenReturn(deviceId)
val queryId = 1
val mockQueryCallback: QueryCallback = mock()
defaultProxyVersion0.queryCallbacks[queryId] = mockQueryCallback
val payload =
QueryResponse.newBuilder().setQueryId(queryId).setSuccess(true).build().toByteArray()
val message =
DeviceMessage.createOutgoingMessage(
UUID.randomUUID(),
/* isMessageEncrypted= */ true,
DeviceMessage.OperationType.QUERY_RESPONSE,
payload
)
defaultProxyVersion0.deviceCallback.onMessageReceived(mockConnectedDevice, message)
assertThat(defaultProxyVersion0.queryCallbacks.contains(queryId)).isFalse()
verify(mockQueryCallback).onSuccess(any())
}
@Test
fun onCleanUp_doesNotInvokeCoordinator_onPlatformVersionLessThanZero() {
defaultProxyVersionNegative.cleanUp()
verify(negativeMockCoordinator, never()).unregisterConnectionCallback(any())
verify(negativeMockCoordinator, never()).unregisterDeviceCallback(any(), any(), any())
verify(negativeMockCoordinator, never()).unregisterOnLogRequestedListener(any(), any())
}
@Test
fun onCleanUp_correctlyInvokesCoordinator_onPlatformVersionZero() {
defaultProxyVersion0.cleanUp()
verify(versionZeroMockCoordinator).unregisterConnectionCallback(any())
verify(versionZeroMockCoordinator).unregisterDeviceCallback(any(), any(), any())
verify(versionZeroMockCoordinator).unregisterOnLogRequestedListener(any(), any())
}
@Test
fun onCleanUp_correctlyInvokesCoordinator_onPlatformVersionGreaterThanZero() {
defaultProxyVersion1.cleanUp()
verify(versionOneMockCoordinator).unregisterConnectionCallback(any())
verify(versionOneMockCoordinator).unregisterDeviceCallback(any(), any(), any())
verify(versionOneMockCoordinator).unregisterOnLogRequestedListener(any(), any())
}
}