summaryrefslogtreecommitdiff
path: root/android/testSrc
diff options
context:
space:
mode:
authorPolina Koval <kovalp@google.com>2022-02-24 10:34:27 +0300
committerPolina Koval <kovalp@google.com>2022-03-02 17:48:26 +0000
commit558bf658c9155db4db39188aebcd9113692b0e6d (patch)
tree0eb33d6c16344e577ccaff08cdc7273229eca1da /android/testSrc
parentf7fff88732b166a447adaf7036212346c4e94791 (diff)
downloadidea-558bf658c9155db4db39188aebcd9113692b0e6d.tar.gz
Introduce RunnableClientsService instead of direct usage of RunnableClient
Bug: n/a Test: n/a refactoring Change-Id: I9a7dec860e17fe60f2047965b1164d1235fc7c0b
Diffstat (limited to 'android/testSrc')
-rw-r--r--android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidActivityConfigurationExecutorTest.kt8
-rw-r--r--android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidComplicationConfigurationExecutorTest.kt8
-rw-r--r--android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidTileConfigurationExecutorTest.kt6
-rw-r--r--android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidWatchFaceConfigurationExecutorTest.kt6
-rw-r--r--android/testSrc/com/android/tools/idea/run/configuration/execution/RunnableClientService.kt (renamed from android/testSrc/com/android/tools/idea/run/configuration/execution/RunnableClient.kt)86
-rw-r--r--android/testSrc/com/android/tools/idea/run/debug/AndroidJavaDebuggerTest.kt65
6 files changed, 97 insertions, 82 deletions
diff --git a/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidActivityConfigurationExecutorTest.kt b/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidActivityConfigurationExecutorTest.kt
index 46c640bdd8d..3cc36d1b8c5 100644
--- a/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidActivityConfigurationExecutorTest.kt
+++ b/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidActivityConfigurationExecutorTest.kt
@@ -79,14 +79,14 @@ internal class AndroidActivityConfigurationExecutorTest : AndroidConfigurationEx
val startCommand = "am start -n com.example.app/com.example.app.Component -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -D"
val stopCommand = "am force-stop com.example.app"
- val runnableClient = RunnableClient(appId, testRootDisposable)
+ val runnableClientsService = RunnableClientsService(testRootDisposable)
val startActivityCommandHandler: CommandHandler = { device, _ ->
- runnableClient.startClient(device)
+ runnableClientsService.startClient(device, appId)
}
- val stopActivityCommandHandler: CommandHandler = { _, _ ->
- runnableClient.stopClient()
+ val stopActivityCommandHandler: CommandHandler = { device, _ ->
+ runnableClientsService.stopClient(device, appId)
}
val device = getMockDevice(mapOf(
diff --git a/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidComplicationConfigurationExecutorTest.kt b/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidComplicationConfigurationExecutorTest.kt
index 85acf3821ab..7ac6e0034d6 100644
--- a/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidComplicationConfigurationExecutorTest.kt
+++ b/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidComplicationConfigurationExecutorTest.kt
@@ -171,15 +171,15 @@ class AndroidComplicationConfigurationExecutorTest : AndroidConfigurationExecuto
setDebugAppBroadcast to "Broadcast completed: result=1"
).toCommandHandlers()
- val runnableClient = RunnableClient(appId, testRootDisposable)
+ val runnableClientsService = RunnableClientsService(testRootDisposable)
val setWatchFaceCommandHandler: CommandHandler = { device, receiver ->
- runnableClient.startClient(device)
+ runnableClientsService.startClient(device, appId)
receiver.addOutput("Broadcast completed: result=1")
}
- val unsetWatchFaceCommandHandler: CommandHandler = { _, receiver ->
- runnableClient.stopClient()
+ val unsetWatchFaceCommandHandler: CommandHandler = { device, receiver ->
+ runnableClientsService.stopClient(device, appId)
receiver.addOutput("Broadcast completed: result=1")
}
diff --git a/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidTileConfigurationExecutorTest.kt b/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidTileConfigurationExecutorTest.kt
index f31adf94238..551aa5047a0 100644
--- a/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidTileConfigurationExecutorTest.kt
+++ b/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidTileConfigurationExecutorTest.kt
@@ -133,7 +133,7 @@ class AndroidTileConfigurationExecutorTest : AndroidConfigurationExecutorBaseTes
// Executor we test.
val executor = Mockito.spy(AndroidTileConfigurationExecutor(env))
- val runnableClient = RunnableClient(appId, testRootDisposable)
+ val runnableClientsService = RunnableClientsService(testRootDisposable)
val commandHandlers = mapOf(
checkVersion to "Broadcast completed: result=1, data=\"3\"",
@@ -142,12 +142,12 @@ class AndroidTileConfigurationExecutorTest : AndroidConfigurationExecutorBaseTes
).toCommandHandlers()
val addTileCommandHandler: CommandHandler = { device, receiver ->
- runnableClient.startClient(device)
+ runnableClientsService.startClient(device, appId)
receiver.addOutput("Broadcast completed: result=1, Index=[101]")
}
val removeTileCommandHandler: CommandHandler = { device, receiver ->
- runnableClient.stopClient()
+ runnableClientsService.stopClient(device, appId)
receiver.addOutput("Broadcast completed: result=1")
}
diff --git a/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidWatchFaceConfigurationExecutorTest.kt b/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidWatchFaceConfigurationExecutorTest.kt
index d72cb2dc9c2..a0edb2cb141 100644
--- a/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidWatchFaceConfigurationExecutorTest.kt
+++ b/android/testSrc/com/android/tools/idea/run/configuration/execution/AndroidWatchFaceConfigurationExecutorTest.kt
@@ -104,16 +104,16 @@ class AndroidWatchFaceConfigurationExecutorTest : AndroidConfigurationExecutorBa
"Broadcast completed: result=1, data=\"3\"",
).toCommandHandlers()
- val runnableClient = RunnableClient(appId, testRootDisposable)
+ val runnableClientsService = RunnableClientsService(testRootDisposable)
val setWatchFaceCommandHandler: CommandHandler = { device, receiver ->
- runnableClient.startClient(device)
+ runnableClientsService.startClient(device, appId)
receiver.addOutput("Broadcasting: Intent { act=com.google.android.wearable.app.DEBUG_SURFACE flg=0x400000 (has extras) }\n" +
"Broadcast completed: result=1, data=\"Favorite Id=[2] Runtime=[1]\"")
}
val unsetWatchFaceCommandHandler: CommandHandler = { device, receiver ->
- runnableClient.stopClient()
+ runnableClientsService.stopClient(device, appId)
receiver.addOutput("Broadcast completed: result=1")
}
diff --git a/android/testSrc/com/android/tools/idea/run/configuration/execution/RunnableClient.kt b/android/testSrc/com/android/tools/idea/run/configuration/execution/RunnableClientService.kt
index 3684320bbd3..d3b52694fbd 100644
--- a/android/testSrc/com/android/tools/idea/run/configuration/execution/RunnableClient.kt
+++ b/android/testSrc/com/android/tools/idea/run/configuration/execution/RunnableClientService.kt
@@ -22,6 +22,7 @@ import com.android.ddmlib.internal.ClientImpl
import com.android.sdklib.AndroidVersion
import com.android.tools.idea.run.DeploymentApplicationService
import com.google.common.util.concurrent.ThreadFactoryBuilder
+import com.intellij.concurrency.AsyncFutureResultImpl
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.testFramework.replaceService
@@ -38,10 +39,41 @@ import java.util.concurrent.atomic.AtomicBoolean
* Adds Client with given appId on IDevice.
*
* Client become available via [DeploymentApplicationService] and opens a connection for debug when [startClient] is invoked.
- * Client closes connection and "removed" from device when [stopClient] is invoked.
+ * Client closes connection and "removed" from [DeploymentApplicationService] device when [stopClient] is invoked.
*/
-internal class RunnableClient(private val appId: String, val disposable: Disposable) {
- private lateinit var client: Client
+internal class RunnableClientsService(testDisposable: Disposable) {
+ private val deviceToRunnableClients: MutableMap<IDevice, MutableMap<String, RunnableClient>> = mutableMapOf()
+ private val deploymentApplicationService = TestDeploymentApplicationService()
+
+ init {
+ ApplicationManager.getApplication()
+ .replaceService(DeploymentApplicationService::class.java, deploymentApplicationService, testDisposable)
+ }
+
+ fun stop() {
+ deviceToRunnableClients.entries.forEach { (device, clients) ->
+ clients.keys.forEach { appId -> stopClient(device, appId) }
+ }
+ }
+
+ fun startClient(device: IDevice, appId: String): Client {
+ val clients = deviceToRunnableClients.computeIfAbsent(device) { mutableMapOf() }
+ val runnableClient = RunnableClient.start(device, appId)
+ clients[appId] = runnableClient
+ deploymentApplicationService.addClient(device, appId, runnableClient.client)
+ return runnableClient.client
+ }
+
+ fun stopClient(device: IDevice, appId: String) {
+ val runnableClient = deviceToRunnableClients[device]?.get(appId) ?: throw RuntimeException("Client is not started")
+ runnableClient.stopClient()
+ deploymentApplicationService.removeClient(device, appId)
+ deviceToRunnableClients[device]!!.remove(appId)
+ }
+}
+
+private class RunnableClient private constructor(private val device: IDevice, private val appId: String) {
+ lateinit var client: Client
private val clientSocket: ServerSocket = ServerSocket()
private val isRunning = AtomicBoolean()
var task: Future<*>? = null
@@ -50,12 +82,20 @@ internal class RunnableClient(private val appId: String, val disposable: Disposa
.setNameFormat("runnable-client-%d")
.build())
+ companion object {
+ fun start(device: IDevice, appId: String): RunnableClient {
+ val runnableClient = RunnableClient(device, appId)
+ runnableClient.doStartClient()
+ return runnableClient
+ }
+ }
+
init {
clientSocket.reuseAddress = true
clientSocket.bind(InetSocketAddress(InetAddress.getLoopbackAddress(), 0))
}
- fun startClient(device: IDevice) {
+ private fun doStartClient() {
// Do not reuse RunnableClient
assert(!this::client.isInitialized)
client = createMockClient(device, clientSocket.localPort)
@@ -76,22 +116,6 @@ internal class RunnableClient(private val appId: String, val disposable: Disposa
clientSocket.close()
}
}
-
- val testDeploymentApplicationService = object : DeploymentApplicationService {
- override fun findClient(iDevice: IDevice, applicationId: String): List<Client> {
- if (device == iDevice && applicationId == appId) {
- return listOf(client)
- }
- return emptyList()
- }
-
- override fun getVersion(iDevice: IDevice): Future<AndroidVersion> {
- throw RuntimeException("Not implemented for test")
- }
- }
-
- ApplicationManager.getApplication()
- .replaceService(DeploymentApplicationService::class.java, testDeploymentApplicationService, disposable)
}
fun stopClient() {
@@ -116,4 +140,26 @@ internal class RunnableClient(private val appId: String, val disposable: Disposa
return mockClient
}
+}
+
+private class TestDeploymentApplicationService : DeploymentApplicationService {
+
+ private val deviceToClients: MutableMap<IDevice, MutableMap<String, Client>> = mutableMapOf()
+
+ fun addClient(device: IDevice, appId: String, client: Client) {
+ val clients = deviceToClients.computeIfAbsent(device) { mutableMapOf() }
+ clients[appId] = client
+ }
+
+ fun removeClient(device: IDevice, appId: String) {
+ deviceToClients[device]?.remove(appId)
+ }
+
+ override fun findClient(iDevice: IDevice, applicationId: String): List<Client> {
+ return deviceToClients[iDevice]?.get(applicationId)?.let { listOf(it) } ?: emptyList()
+ }
+
+ override fun getVersion(iDevice: IDevice): Future<AndroidVersion> {
+ return AsyncFutureResultImpl()
+ }
} \ No newline at end of file
diff --git a/android/testSrc/com/android/tools/idea/run/debug/AndroidJavaDebuggerTest.kt b/android/testSrc/com/android/tools/idea/run/debug/AndroidJavaDebuggerTest.kt
index f340d4935c8..0acaeb5f86b 100644
--- a/android/testSrc/com/android/tools/idea/run/debug/AndroidJavaDebuggerTest.kt
+++ b/android/testSrc/com/android/tools/idea/run/debug/AndroidJavaDebuggerTest.kt
@@ -16,11 +16,10 @@
package com.android.tools.idea.run.debug
import com.android.ddmlib.Client
-import com.android.ddmlib.ClientData
import com.android.ddmlib.IDevice
-import com.android.ddmlib.internal.ClientImpl
import com.android.testutils.MockitoKt.eq
import com.android.tools.idea.flags.StudioFlags
+import com.android.tools.idea.run.configuration.execution.RunnableClientsService
import com.android.tools.idea.run.editor.AndroidJavaDebugger
import com.google.common.truth.Truth.assertThat
import com.intellij.codeInsight.JavaCodeInsightTestCase
@@ -34,10 +33,6 @@ import com.intellij.execution.runners.ExecutionEnvironmentBuilder
import com.intellij.execution.runners.GenericProgramRunner
import org.junit.Test
import org.mockito.Mockito
-import java.net.InetAddress
-import java.net.InetSocketAddress
-import java.net.ServerSocket
-import java.util.concurrent.TimeUnit
import javax.swing.Icon
/**
@@ -47,22 +42,21 @@ import javax.swing.Icon
*/
class AndroidJavaDebuggerTest : JavaCodeInsightTestCase() {
private val APP_PACKAGE = "com.android.example"
- private val PID = 1111
- private lateinit var clientSocket: ServerSocket
+ private lateinit var client: Client
+ private lateinit var runnableClientsService: RunnableClientsService
private lateinit var executionEnvironment: ExecutionEnvironment
override fun setUp() {
super.setUp()
StudioFlags.NEW_EXECUTION_FLOW_FOR_JAVA_DEBUGGER.override(true)
executionEnvironment = createFakeExecutionEnvironment()
- clientSocket = ServerSocket()
- clientSocket.reuseAddress = true
- clientSocket.bind(InetSocketAddress(InetAddress.getLoopbackAddress(), 0))
+ runnableClientsService = RunnableClientsService(testRootDisposable)
+ client = runnableClientsService.startClient(Mockito.mock(IDevice::class.java), APP_PACKAGE)
}
override fun tearDown() {
- clientSocket.close()
+ runnableClientsService.stop()
StudioFlags.NEW_EXECUTION_FLOW_FOR_JAVA_DEBUGGER.clearOverride()
super.tearDown()
}
@@ -87,46 +81,38 @@ class AndroidJavaDebuggerTest : JavaCodeInsightTestCase() {
@Test
fun test() {
- val port = clientSocket.localPort
- val mockClient = createMockClient(Mockito.mock(IDevice::class.java), port)
-
- val session = attachJavaDebuggerToClient(myProject, mockClient, executionEnvironment, null).blockingGet(1000)
+ val session = attachJavaDebuggerToClient(myProject, client, executionEnvironment, null).blockingGet(1000)
assertThat(session).isNotNull()
assertThat(session!!.sessionName).isEqualTo("myConfiguration")
}
@Test
fun testCallback() {
- val port = clientSocket.localPort
- val mockClient = createMockClient(Mockito.mock(IDevice::class.java), port)
-
var callbackCount = 0
val onDebugProcessStarted: () -> Unit = {
callbackCount++
}
- val session = attachJavaDebuggerToClient(myProject, mockClient, executionEnvironment, onDebugProcessStarted = onDebugProcessStarted).blockingGet(1000)
+ val session = attachJavaDebuggerToClient(myProject, client, executionEnvironment,
+ onDebugProcessStarted = onDebugProcessStarted).blockingGet(1000)
assertThat(session).isNotNull()
assertThat(callbackCount).isEqualTo(1)
}
@Test
fun testSessionName() {
- val port = clientSocket.localPort
- val mockClient = createMockClient(Mockito.mock(IDevice::class.java), port)
-
- val session = attachJavaDebuggerToClientAndShowTab(myProject, mockClient).blockingGet(1000)
+ val session = attachJavaDebuggerToClientAndShowTab(myProject, client).blockingGet(1000)
assertThat(session).isNotNull()
- assertThat(session!!.sessionName).isEqualTo("Android Debugger (pid: 1111, debug port: $port)")
+ assertThat(client.debuggerListenPort).isAtLeast(0)
+ assertThat(client.clientData.pid).isAtLeast(0)
+ assertThat(session!!.sessionName).isEqualTo("Android Debugger (pid: ${client.clientData.pid}, debug port: ${client.debuggerListenPort})")
}
@Test
fun testKillAppOnDestroy() {
- val port = clientSocket.localPort
- val mockDevice = Mockito.mock(IDevice::class.java)
- val mockClient = createMockClient(mockDevice, port)
+ val mockDevice = client.device
- val session = attachJavaDebuggerToClient(myProject, mockClient, executionEnvironment).blockingGet(1000)!!
+ val session = attachJavaDebuggerToClient(myProject, client, executionEnvironment).blockingGet(1000)!!
session.debugProcess.processHandler.destroyProcess()
session.debugProcess.processHandler.waitFor()
Thread.sleep(100)
@@ -135,27 +121,10 @@ class AndroidJavaDebuggerTest : JavaCodeInsightTestCase() {
@Test
fun testVMExitedNotifierIsInvoked() {
- val port = clientSocket.localPort
- val mockClient = createMockClient(Mockito.mock(IDevice::class.java), port)
-
- val session = attachJavaDebuggerToClient(myProject, mockClient, executionEnvironment).blockingGet(1000)!!
+ val session = attachJavaDebuggerToClient(myProject, client, executionEnvironment).blockingGet(1000)!!
session.debugProcess.processHandler.detachProcess()
session.debugProcess.processHandler.waitFor()
- Mockito.verify(mockClient, Mockito.times(1)).notifyVmMirrorExited()
- }
-
- private fun createMockClient(mockDevice: IDevice, debugPort: Int): Client {
- val mockClientData = Mockito.mock(ClientData::class.java)
- Mockito.`when`(mockClientData.pid).thenReturn(PID)
- Mockito.`when`(mockClientData.packageName).thenReturn(APP_PACKAGE)
- Mockito.`when`(mockClientData.clientDescription).thenReturn(APP_PACKAGE)
-
- val mockClient = Mockito.mock(Client::class.java)
- Mockito.`when`(mockClient.clientData).thenReturn(mockClientData)
- Mockito.`when`(mockClient.debuggerListenPort).thenReturn(debugPort)
- Mockito.`when`(mockClient.device).thenReturn(mockDevice)
-
- return mockClient
+ Mockito.verify(client, Mockito.times(1)).notifyVmMirrorExited()
}
} \ No newline at end of file