Skip to content

Commit

Permalink
Merge pull request #40 from Malinskiy/feature/server-stub
Browse files Browse the repository at this point in the history
Adb server stub
  • Loading branch information
Malinskiy committed May 29, 2021
2 parents 050d4af + 0fa5fd4 commit c28a519
Show file tree
Hide file tree
Showing 88 changed files with 2,007 additions and 1,413 deletions.
15 changes: 4 additions & 11 deletions .buildsystem/deploy-github.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,12 @@ if [ -z "$GPG_PASSPHRASE" ]; then
exit 1
fi

ATASK=""
DTASK=""
for i in ":adam" ":android-junit4" ":android-testrunner-contract"; do
ATASK="$ATASK $i:assemble"
DTASK="$DTASK $i:publishDefaultPublicationToGitHubRepository"
done

if [ -n "$GIT_TAG_NAME" ]; then
echo "on a tag -> deploy release version $GIT_TAG_NAME"
./gradlew $ATASK -PreleaseMode=RELEASE
./gradlew $DTASK -PreleaseMode=RELEASE
./gradlew assemble -PreleaseMode=RELEASE
./gradlew publishDefaultPublicationToGitHubRepository -PreleaseMode=RELEASE
else
echo "not on a tag -> deploy snapshot version"
./gradlew $ATASK -PreleaseMode=SNAPSHOT
./gradlew $DTASK -PreleaseMode=SNAPSHOT
./gradlew assemble -PreleaseMode=SNAPSHOT
./gradlew publishDefaultPublicationToGitHubRepository -PreleaseMode=SNAPSHOT
fi
17 changes: 4 additions & 13 deletions .buildsystem/deploy-sonatype.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,12 @@ if [ -z "$GPG_PASSPHRASE" ]; then
exit 1
fi

ATASK=""
DTASK=""
for i in ":adam" ":android-junit4" ":android-testrunner-contract"; do
ATASK="$ATASK $i:assemble"
DTASK="$DTASK $i:publishDefaultPublicationToOSSHRRepository"
done

echo "Value of TEST_ENVVAR is $TEST_ENVVAR"

if [ -z "$GIT_TAG_NAME" ]; then
echo "not on a tag -> deploy snapshot version"
./gradlew $ATASK -PreleaseMode=SNAPSHOT
./gradlew $DTASK -PreleaseMode=SNAPSHOT
./gradlew assemble -PreleaseMode=SNAPSHOT
./gradlew publishDefaultPublicationToOSSHRRepository -PreleaseMode=SNAPSHOT
else
echo "on a tag -> deploy release version $GIT_TAG_NAME"
./gradlew $ATASK -PreleaseMode=RELEASE
./gradlew $DTASK -PreleaseMode=RELEASE
./gradlew assemble -PreleaseMode=RELEASE
./gradlew publishDefaultPublicationToOSSHRRepository -PreleaseMode=RELEASE
fi
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
java-version: 1.8
- uses: malinskiy/action-android/install-sdk@release/0.1.1
- name: build & test
run: ./gradlew :adam:test :adam:jacocoTestReport :android-junit4:build :android-testrunner-contract:build
run: ./gradlew assemble test jacocoTestReport
- name: archive test results
if: failure()
run: (cd adam/build/reports/tests/test; zip -r -X ../../../../../test-result.zip .)
Expand Down
1 change: 1 addition & 0 deletions adam/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ dependencies {
testImplementation(TestLibraries.imageComparison)
testImplementation(kotlin("reflect", version = Versions.kotlin))
testImplementation(TestLibraries.coroutinesDebug)
testImplementation(project(":server:server-stub-junit4"))

integrationTestImplementation(TestLibraries.coroutinesDebug)
integrationTestImplementation(TestLibraries.assertk)
Expand Down
2 changes: 2 additions & 0 deletions adam/src/main/kotlin/com/malinskiy/adam/request/Feature.kt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ enum class Feature {
*/
SENDRECV_V2_DRY_RUN_SEND;

fun value() = name.toLowerCase()

companion object {
/**
* see adb/transport.cpp for up-to-date list
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,5 @@ data class FileEntryV2(
val ctime: Instant,
override val name: String? = null
) : FileEntry() {
override fun exists() = error == 3025.toUInt()
override fun exists() = !(size == 0.toULong() && mode == 0.toUInt() && mtime.epochSecond == 0L)
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,114 +23,76 @@ import com.malinskiy.adam.exception.RequestValidationException
import com.malinskiy.adam.request.ComplexRequest
import com.malinskiy.adam.request.ValidationResponse
import com.malinskiy.adam.request.shell.v1.ShellCommandRequest
import com.malinskiy.adam.server.AndroidDebugBridgeServer
import com.malinskiy.adam.server.junit4.AdbServerRule
import com.malinskiy.adam.transport.Socket
import io.ktor.utils.io.close
import kotlinx.coroutines.runBlocking
import org.junit.Rule
import org.junit.Test

class AndroidDebugBridgeClientTest {
@get:Rule
val server = AdbServerRule()
val client: AndroidDebugBridgeClient
get() = server.client

@Test(expected = RequestRejectedException::class)
fun testRequestRejection() {
runBlocking {
val server = AndroidDebugBridgeServer()

val client = server.startAndListen { input, output ->
val transportCmd = input.receiveCommand()
assertThat(transportCmd).isEqualTo("host:transport:serial")
output.respond(Const.Message.FAIL)

val response = "0013something-somethingx0".toByteArray(Const.DEFAULT_TRANSPORT_ENCODING)
output.writeFully(response, 0, response.size)
output.close()
server.session {
expectCmd { "host:transport:serial" }.reject("something-something")
}

val output = client.execute(ShellCommandRequest("xx"), serial = "serial")
assertThat(output.output).isEqualTo("something-something")
assertThat(output.exitCode).isEqualTo(0)

server.dispose()
}
}

@Test(expected = RequestRejectedException::class)
fun testRequestRejectionDuringHandshake() {
runBlocking {
val server = AndroidDebugBridgeServer()

val client = server.startAndListen { input, output ->
val transportCmd = input.receiveCommand()
assertThat(transportCmd).isEqualTo("host:transport:serial")
output.respond(Const.Message.OKAY)

val shellCmd = input.receiveCommand()
assertThat(shellCmd).isEqualTo("shell:xx;echo x$?")
output.respond(Const.Message.FAIL)

val response = "0013something-somethingx0".toByteArray(Const.DEFAULT_TRANSPORT_ENCODING)
output.writeFully(response, 0, response.size)
output.close()
server.session {
expectCmd { "host:transport:serial" }.accept()
expectShell { "xx;echo x$?" }.reject("something-somethingx0")
}

client.execute(ShellCommandRequest("xx"), serial = "serial")
server.dispose()
}
}

@Test(expected = RequestRejectedException::class)
fun testRequestRejectionDuringHandshakeWithNoMessage() {
runBlocking {
val server = AndroidDebugBridgeServer()

val client = server.startAndListen { input, output ->
val transportCmd = input.receiveCommand()
assertThat(transportCmd).isEqualTo("host:transport:serial")
output.respond(Const.Message.OKAY)
server.session {
expectCmd { "host:transport:serial" }.accept()

val shellCmd = input.receiveCommand()
assertThat(shellCmd).isEqualTo("shell:xx;echo x\$?")
expectShell { "xx;echo x\$?" }
output.respond(Const.Message.FAIL)

val response = "XXXXx".toByteArray(Const.DEFAULT_TRANSPORT_ENCODING)
output.writeFully(response, 0, response.size)
output.close()
output.respondStringRaw("XXXXx")
}

client.execute(ShellCommandRequest("xx"), serial = "serial")
server.dispose()
}
}

@Test(expected = RequestRejectedException::class)
fun testRequestRejectionAndUnexpectedMessageLength() {
runBlocking {
val server = AndroidDebugBridgeServer()
server.session {
expectCmd { "host:transport:serial" }

val client = server.startAndListen { input, output ->
val transportCmd = input.receiveCommand()
assertThat(transportCmd).isEqualTo("host:transport:serial")
output.respond(Const.Message.FAIL)

val response = "XXXXsomething-something".toByteArray(Const.DEFAULT_TRANSPORT_ENCODING)
output.writeFully(response, 0, response.size)
output.close()
output.respondStringRaw("XXXXsomething-something")
}

val output = client.execute(ShellCommandRequest("xx"), serial = "serial")
assertThat(output.output).isEqualTo("something-something")

server.dispose()
}
}

@Test(expected = RequestValidationException::class)
fun testRequestValidation() {
runBlocking {
val server = AndroidDebugBridgeServer()

val client = server.startAndListen { _, _ ->
}

client.execute(object : ComplexRequest<String>() {
override fun validate() = ValidationResponse(false, "Fake")
override suspend fun readElement(socket: Socket): String {
Expand All @@ -141,7 +103,6 @@ class AndroidDebugBridgeClientTest {
TODO("Not yet implemented")
}
}, serial = "serial")
server.dispose()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,20 @@ package com.malinskiy.adam.request

import assertk.assertThat
import assertk.assertions.isEqualTo
import com.malinskiy.adam.AndroidDebugBridgeClient
import com.malinskiy.adam.Const
import com.malinskiy.adam.request.prop.GetSinglePropRequest
import com.malinskiy.adam.server.AndroidDebugBridgeServer
import io.ktor.utils.io.close
import com.malinskiy.adam.server.junit4.AdbServerRule
import kotlinx.coroutines.runBlocking
import org.junit.Rule
import org.junit.Test

class GetSinglePropRequestTest {
@get:Rule
val server = AdbServerRule()
val client: AndroidDebugBridgeClient
get() = server.client

@Test
fun testGetX() {
assertThat(String(GetSinglePropRequest("x").serialize(), Const.DEFAULT_TRANSPORT_ENCODING))
Expand All @@ -35,25 +41,15 @@ class GetSinglePropRequestTest {
@Test
fun testReturnsProperContent() {
runBlocking {
val server = AndroidDebugBridgeServer()
val client = server.startAndListen { input, output ->
val transportCmd = input.receiveCommand()
assertThat(transportCmd).isEqualTo("host:transport:serial")
output.respond(Const.Message.OKAY)

val shellCmd = input.receiveCommand()
assertThat(shellCmd).isEqualTo("shell:getprop prop1;echo x$?")
output.respond(Const.Message.OKAY)

val response = "testingx0".toByteArray(Const.DEFAULT_TRANSPORT_ENCODING)
output.writeFully(response, 0, response.size)
output.close()
server.session {
expectCmd { "host:transport:serial" }.accept()
expectShell { "getprop prop1;echo x$?" }
.accept()
.respond("testingx0")
}

val version = client.execute(GetSinglePropRequest("prop1"), serial = "serial")
assertThat(version).isEqualTo("testing")

server.dispose()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import assertk.assertions.isTrue
import com.malinskiy.adam.Const
import com.malinskiy.adam.extension.toRequestString
import com.malinskiy.adam.request.Feature
import com.malinskiy.adam.server.StubSocket
import com.malinskiy.adam.server.stub.StubSocket
import com.malinskiy.adam.transport.use
import kotlinx.coroutines.runBlocking
import org.junit.Rule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,22 @@ package com.malinskiy.adam.request.adbd

import assertk.assertThat
import assertk.assertions.isEqualTo
import com.malinskiy.adam.Const
import com.malinskiy.adam.AndroidDebugBridgeClient
import com.malinskiy.adam.extension.toRequestString
import com.malinskiy.adam.server.AndroidDebugBridgeServer
import io.ktor.utils.io.close
import com.malinskiy.adam.server.junit4.AdbServerRule
import kotlinx.coroutines.runBlocking
import org.junit.Rule
import org.junit.Test

/**
* Restarts the on device adbd
*/
class RestartAdbdRequestTest {
@get:Rule
val server = AdbServerRule()
val client: AndroidDebugBridgeClient
get() = server.client

@Test
fun testSerializeRootMode() {
val bytes = RestartAdbdRequest(RootAdbdMode).serialize()
Expand Down Expand Up @@ -56,25 +61,14 @@ class RestartAdbdRequestTest {
@Test
fun testReturnsResultString() {
runBlocking {
val server = AndroidDebugBridgeServer()

val client = server.startAndListen { input, output ->
val transportCmd = input.receiveCommand()
assertThat(transportCmd).isEqualTo("host:transport:serial")
output.respond(Const.Message.OKAY)

val cmd = input.receiveCommand()
assertThat(cmd).isEqualTo("root:")
output.respondOkay()

output.respondStringRaw("adbd cannot run as root in production builds")
output.close()
server.session {
expectCmd { "host:transport:serial" }.accept()
expectCmd { "root:" }.accept()
resondRestartAdbd("adbd cannot run as root in production builds")
}

val output = client.execute(RestartAdbdRequest(RootAdbdMode), "serial")
assertThat(output).isEqualTo("adbd cannot run as root in production builds")

server.dispose()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,28 @@ package com.malinskiy.adam.request.async

import assertk.assertThat
import assertk.assertions.containsExactly
import assertk.assertions.isEqualTo
import com.malinskiy.adam.Const
import com.malinskiy.adam.AndroidDebugBridgeClient
import com.malinskiy.adam.request.device.AsyncDeviceMonitorRequest
import com.malinskiy.adam.request.device.Device
import com.malinskiy.adam.request.device.DeviceState
import com.malinskiy.adam.server.AndroidDebugBridgeServer
import io.ktor.utils.io.close
import kotlinx.coroutines.channels.receiveOrNull
import com.malinskiy.adam.server.junit4.AdbServerRule
import kotlinx.coroutines.runBlocking
import org.junit.Rule
import org.junit.Test

class AsyncDeviceMonitorRequestTest {
@get:Rule
val server = AdbServerRule()
val client: AndroidDebugBridgeClient
get() = server.client

@Test
fun testReturnsProperContent() {
runBlocking {
val server = AndroidDebugBridgeServer()

val client = server.startAndListen { input, output ->
val transportCmd = input.receiveCommand()
assertThat(transportCmd).isEqualTo("host:track-devices")
output.respond(Const.Message.OKAY)

var response = ("0016emulator-5554\toffline\n").toByteArray(Const.DEFAULT_TRANSPORT_ENCODING)
output.writeFully(response, 0, response.size)
response = ("0015emulator-5554\tdevice\n").toByteArray(Const.DEFAULT_TRANSPORT_ENCODING)
output.writeFully(response, 0, response.size)
output.close()
server.session {
expectCmd { "host:track-devices" }.accept()
respondAsyncDeviceMonitor("emulator-5554", "offline")
respondAsyncDeviceMonitor("emulator-5554", "device")
}

val updates = client.execute(AsyncDeviceMonitorRequest(), scope = this)
Expand All @@ -53,8 +48,6 @@ class AsyncDeviceMonitorRequestTest {
update = updates.receiveOrNull()
assertThat(update!!).containsExactly(Device("emulator-5554", DeviceState.DEVICE))
updates.cancel()

server.dispose()
}
}
}

0 comments on commit c28a519

Please sign in to comment.