Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.kaspersky.adbserver.connection.implementation.ConnectionClientImplByS
import com.kaspersky.adbserver.connection.implementation.ConnectionServerImplBySocket
import com.kaspersky.adbserver.common.log.logger.Logger
import java.net.Socket
import java.util.concurrent.TimeUnit

/*
* Licensed to the Apache Software Foundation (ASF) under one
Expand Down Expand Up @@ -43,10 +44,12 @@ object ConnectionFactory {
connectionServerLifecycle
)

@Suppress("MagicNumber")
fun createClient(
socketCreation: () -> Socket,
logger: Logger,
connectionClientLifecycle: ConnectionClientLifecycle
connectionClientLifecycle: ConnectionClientLifecycle,
commandTimeoutSeconds: Long = TimeUnit.MINUTES.toSeconds(3)
): ConnectionClient =
ConnectionClientImplBySocket(socketCreation, logger, connectionClientLifecycle)
ConnectionClientImplBySocket(socketCreation, logger, connectionClientLifecycle, commandTimeoutSeconds)
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,14 @@ import java.util.concurrent.TimeUnit
* under the License.
*/

@Suppress("MagicNumber")
internal class ConnectionClientImplBySocket(
private val socketCreation: () -> Socket,
private val logger: Logger,
private val connectionClientLifecycle: ConnectionClientLifecycle
private val connectionClientLifecycle: ConnectionClientLifecycle,
private val commandTimeoutSeconds: Long = TimeUnit.MINUTES.toSeconds(3)
) : ConnectionClient {

companion object {
private val COMMAND_TIMEOUT_MIN = TimeUnit.MINUTES.toSeconds(3)
}

private var _socket: Socket? = null
private val socket: Socket
get() = _socket
Expand Down Expand Up @@ -157,7 +155,7 @@ internal class ConnectionClientImplBySocket(

val resultMessage: ResultMessage<CommandResult>?
try {
resultMessage = resultWaiter.waitResult(COMMAND_TIMEOUT_MIN, TimeUnit.SECONDS)
resultMessage = resultWaiter.waitResult(commandTimeoutSeconds, TimeUnit.SECONDS)
} catch (exception: InterruptedException) {
val failedCommandResult = CommandResult(
ExecutorResultStatus.FAILURE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.kaspersky.adbserver.common.api.CommandResult
import com.kaspersky.adbserver.common.log.LoggerFactory
import com.kaspersky.adbserver.common.log.logger.LogLevel
import com.kaspersky.adbserver.common.log.logger.Logger
import java.util.concurrent.TimeUnit

/*
* Licensed to the Apache Software Foundation (ASF) under one
Expand All @@ -31,8 +32,12 @@ object AdbTerminal {

private var device: Device? = null

fun connect(logger: Logger = LoggerFactory.getDeviceLogger(LogLevel.INFO)) {
if (device == null) device = Device.create(logger)
@Suppress("MagicNumber")
fun connect(
logger: Logger = LoggerFactory.getDeviceLogger(LogLevel.INFO),
commandTimeoutSeconds: Long = TimeUnit.MINUTES.toSeconds(3)
) {
if (device == null) device = Device.create(logger, commandTimeoutSeconds)
device?.startConnectionToDesktop()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ internal class Device private constructor(
private const val CONNECTION_ESTABLISH_TIMEOUT_SEC = 5L
private const val CONNECTION_WAIT_MS = 200L

fun create(logger: Logger): Device {
@Suppress("MagicNumber")
fun create(logger: Logger, commandTimeoutSeconds: Long = TimeUnit.MINUTES.toSeconds(3)): Device {
val desktopDeviceSocketConnection =
DesktopDeviceSocketConnectionFactory.getSockets(
DesktopDeviceSocketConnectionType.FORWARD
Expand All @@ -56,7 +57,8 @@ internal class Device private constructor(
val connectionClient = ConnectionFactory.createClient(
desktopDeviceSocketConnection.getDeviceSocketLoad(logger),
logger,
connectionClientLifecycle
connectionClientLifecycle,
commandTimeoutSeconds
)
return Device(connectionClient, logger)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,13 @@ import java.util.concurrent.TimeUnit
* under the License.
*/

@Suppress("MagicNumber")
internal class CmdCommandPerformer(
private val desktopName: String,
private val logger: Logger,
private val executionTimeoutSeconds: Long = 2 * 60L,
) {

companion object {
private const val EXECUTION_TIMEOUT_SECONDS = 2 * 60L
}

/**
* Be aware it's a synchronous method
*/
Expand All @@ -55,7 +53,7 @@ internal class CmdCommandPerformer(
}

try {
if (process.waitFor(EXECUTION_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
if (process.waitFor(executionTimeoutSeconds, TimeUnit.SECONDS)) {
val exitCode = process.exitValue()
return if (exitCode != 0) {
val error = "exitCode=$exitCode, message=${process.errorStream.bufferedReader().readText()}"
Expand All @@ -75,7 +73,7 @@ internal class CmdCommandPerformer(
}
return CommandResult(
status = ExecutorResultStatus.TIMEOUT,
description = "Command execution timeout ($EXECUTION_TIMEOUT_SECONDS sec) overhead",
description = "Command execution timeout ($executionTimeoutSeconds sec) overhead",
serviceInfo = serviceInfo
)
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ private const val DESKTOP = "Desktop-"
// It is assumed that adb is preinstall and available by "adb" keyword
private const val DEFAULT_ADB_PATH = "adb"

@Suppress("MagicNumber")
internal fun main(args: Array<String>) {
val parser = ArgParser("Adb Server")

Expand Down Expand Up @@ -62,14 +63,21 @@ internal fun main(args: Array<String>) {
description = "Path to custom adb"
).default(DEFAULT_ADB_PATH)

val timeout by parser.option(
type = ArgType.Int,
shortName = "t",
fullName = "timeout",
description = "Operation execution timeout in seconds (default: 120)"
).default(120)

parser.parse(args)

val desktopName = getDesktopName()
val desktopLogger = LoggerFactory.getDesktopLogger(logLevel, desktopName)

desktopLogger.i("Desktop started with arguments: emulators=$emulators, adbServerPort=$port, adbPath=$adbPath")
desktopLogger.i("Desktop started with arguments: emulators=$emulators, adbServerPort=$port, adbPath=$adbPath, timeout=${timeout}s")

val cmdCommandPerformer = CmdCommandPerformer(desktopName, desktopLogger)
val cmdCommandPerformer = CmdCommandPerformer(desktopName, desktopLogger, timeout.toLong())
val desktop = Desktop(
cmdCommandPerformer = cmdCommandPerformer,
presetEmulators = emulators,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ private fun Kaspresso.Builder.initVisualTestParams(visualParams: VisualTestParam
resourcesDirsProvider,
resourceFileNamesProvider,
)
adbServer = AdbServerImpl(LogLevel.WARN, libLogger)
adbServer = AdbServerImpl(LogLevel.WARN, libLogger, adbServerParams.commandTimeoutSeconds)
files = FilesImpl(libLogger, adbServer)
visualTestWatcher = AllureVisualTestWatcher(visualTestParams, testLogger, (dirsProvider as AllureDirsProvider), resourcesRootDirsProvider, files)
}
Expand Down
Binary file modified artifacts/adbserver-desktop.jar
Binary file not shown.
11 changes: 11 additions & 0 deletions docs/Wiki/Executing_adb_commands.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Flags:
- `p`, `--port` - the adb server port number (the default value is 5037)
- `l`, `--logs` - what type of logs show (the default value is INFO).
- `a`, `--adb_path` - path to custom adb instance (by default, `adbserver-desktop.jar` uses `adb` from environment).
- `t`, `--timeout` - timeout for adb commands execution.
For more information, you can run `java -jar adbserver-desktop.jar --help`

Consider available types of logs:
Expand Down Expand Up @@ -211,6 +212,16 @@ Now the logs looks like:
2020-09-10 12:24:27.427 10349-10378/com.kaspersky.kaspressample I/KASPRESSO_ADBSERVER: The result of command=AdbCommand(body=shell su 0 svc data disable) => CommandResult(status=SUCCESS, description=exitCode=0, message=, serviceInfo=The command was executed on desktop=Desktop-30548)
```

There's a timeout for how long the device waits for the response from the server. It can be changed by
setting `AdbServerParams` value in the Kaspresso builder:
```kotlin
class DeviceNetworkSampleTest : TestCase(
kaspressoBuilder = Kaspresso.Builder.simple {
adbServerParams = AdbServerParams(commandTimeoutSeconds = 360L)
}
) {...}
```

## Development
The source code of AdbServer is available in [adb-server](https://github.com/KasperskyLab/Kaspresso/tree/master/adb-server) module. <br>
If you want to build `adbserver-desktop.jar` manually, just execute `./gradlew :adb-server:adbserver-desktop:assemble`.
10 changes: 10 additions & 0 deletions docs/Wiki/Executing_adb_commands.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,16 @@ class DeviceNetworkSampleTest: TestCase(
2020-09-10 12:24:27.427 10349-10378/com.kaspersky.kaspressample I/KASPRESSO_ADBSERVER: The result of command=AdbCommand(body=shell su 0 svc data disable) => CommandResult(status=SUCCESS, description=exitCode=0, message=, serviceInfo=The command was executed on desktop=Desktop-30548)
```

На стороне устройства есть таймаут, определяющий, как долго оно ждёт ответа от сервера. Его можно изменить,
установив значение AdbServerParams в Kaspresso builder:
```kotlin
class DeviceNetworkSampleTest : TestCase(
kaspressoBuilder = Kaspresso.Builder.simple {
adbServerParams = AdbServerParams(commandTimeoutSeconds = 360L)
}
) {...}
```

## Разработка
Исходный код AdbServer доступен в модуле [adb-server](https://github.com/KasperskyLab/Kaspresso/ru/tree/master/adb-server). <br>
Если вы хотите собрать `adbserver-desktop.jar` вручную, просто выполните `./gradlew :adb-server:adbserver-desktop:assemble`.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.kaspersky.adbserver.common.log.logger.LogLevel
import com.kaspersky.adbserver.common.log.logger.Logger
import com.kaspersky.kaspresso.internal.exceptions.AdbServerException
import com.kaspersky.kaspresso.logger.UiTestLogger
import java.util.concurrent.TimeUnit

/*
* Licensed to the Apache Software Foundation (ASF) under one
Expand All @@ -32,9 +33,11 @@ import com.kaspersky.kaspresso.logger.UiTestLogger
* Please, pay attention to the field [AdbServerLogsType] that provides several types to show logs from adb-server (device part).
* More details are available in [AdbServerLogsType].
*/
@Suppress("MagicNumber")
class AdbServerImpl(
logLevel: LogLevel,
private val logger: UiTestLogger
private val logger: UiTestLogger,
private val commandTimeoutSeconds: Long = TimeUnit.MINUTES.toSeconds(3)
) : AdbServer {

private val adbServerLogger: Logger = AdbServerLoggerKaspressoImpl(logLevel, logger)
Expand All @@ -43,7 +46,7 @@ class AdbServerImpl(
private val adbTerminal: AdbTerminal
get() {
if (!connected) {
AdbTerminal.connect(logger = adbServerLogger)
AdbTerminal.connect(logger = adbServerLogger, commandTimeoutSeconds = commandTimeoutSeconds)
connected = true
}
return AdbTerminal
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.kaspersky.kaspresso.device.server

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import java.util.concurrent.TimeUnit

/**
* Configuration parameters for the ADB server device-side connection.
*
* @param commandTimeoutSeconds how long the device waits for a command result from the desktop
* server before declaring a timeout. Defaults to 3 minutes.
*/
@Suppress("MagicNumber")
data class AdbServerParams(
val commandTimeoutSeconds: Long = TimeUnit.MINUTES.toSeconds(3)
)
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import com.kaspersky.kaspresso.device.screenshots.screenshotmaker.InternalScreen
import com.kaspersky.kaspresso.device.screenshots.screenshotmaker.ScreenshotMaker
import com.kaspersky.kaspresso.device.server.AdbServer
import com.kaspersky.kaspresso.device.server.AdbServerImpl
import com.kaspersky.kaspresso.device.server.AdbServerParams
import com.kaspersky.kaspresso.device.video.Videos
import com.kaspersky.kaspresso.device.video.VideosImpl
import com.kaspersky.kaspresso.device.video.recorder.VideoRecorderImpl
Expand Down Expand Up @@ -382,6 +383,12 @@ data class Kaspresso(
*/
lateinit var adbServer: AdbServer

/**
* Configuration parameters for the ADB server device-side connection.
* Used only when [adbServer] is not set explicitly.
*/
var adbServerParams: AdbServerParams = AdbServerParams()

/**
* Holds an implementation of [Apps] interface. If it was not specified, the default implementation is used.
*/
Expand Down Expand Up @@ -776,7 +783,7 @@ data class Kaspresso(
)
}

if (!::adbServer.isInitialized) adbServer = AdbServerImpl(LogLevel.WARN, libLogger)
if (!::adbServer.isInitialized) adbServer = AdbServerImpl(LogLevel.WARN, libLogger, adbServerParams.commandTimeoutSeconds)
if (!::apps.isInitialized) apps = AppsImpl(
libLogger,
instrumentation.context,
Expand Down
Loading