Merge pull request #59 from SKART1/FT-58-connect-disconnect

Ft 58 connect disconnect
This commit is contained in:
Samuel Carlsson 2017-03-20 14:09:22 +01:00 committed by GitHub
commit 79ab1aa5ea
13 changed files with 399 additions and 74 deletions

6
.gitignore vendored
View File

@ -4,15 +4,13 @@
################
# IntelliJ #
################
/.idea/workspace.xml
/.idea/tasks.xml
/.idea/*
jadb.iml
#############
# Maven #
#############
.idea/workspace.xml
.idea/libraries
out/
target/

32
.idea/compiler.xml generated
View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
<profile default="false" name="Annotation profile for jadb" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<processorPath useClasspath="true" />
<module name="jadb" />
</profile>
</annotationProcessing>
<bytecodeTargetLevel>
<module name="jadb" target="1.7" />
</bytecodeTargetLevel>
</component>
</project>

17
.idea/misc.xml generated
View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="WebServicesPlugin" addRequiredLibraries="true" />
</project>

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="inheritedJdk" />
<orderEntry type="library" name="junit-4.10" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.10" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
</component>
</module>

14
pom.xml
View File

@ -30,6 +30,7 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.7</maven.compiler.source>
<mockito-core.version>2.7.17</mockito-core.version>
</properties>
<dependencies>
@ -39,6 +40,13 @@
<version>4.10</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito-core.version}</version>
</dependency>
</dependencies>
<build>
@ -114,7 +122,7 @@
<include>**/*.java</include>
</includes>
<excludes>
<!--Integration tests -->
<!--Exclude integration tests -->
<exclude>se.vidstige.jadb.test.integration.*</exclude>
<!--Mocks and data-->
<exclude>**/data/*</exclude>
@ -131,8 +139,8 @@
<include>**/*.java</include>
</includes>
<excludes>
<!--Integration tests -->
<exclude>se.vidstige.jadb.test.unit.*</exclude>
<!--Include only integration tests -->
<include>se.vidstige.jadb.test.integration.*</include>
<!--Mocks and data-->
<exclude>**/data/*</exclude>
<exclude>**/fakes/*</exclude>

View File

@ -0,0 +1,7 @@
package se.vidstige.jadb;
public class ConnectionToRemoteDeviceException extends Exception {
public ConnectionToRemoteDeviceException(String message) {
super(message);
}
}

View File

@ -0,0 +1,75 @@
package se.vidstige.jadb;
import java.io.IOException;
import java.net.InetSocketAddress;
class HostConnectToRemoteTcpDevice {
private final Transport transport;
private final ResponseValidator responseValidator;
HostConnectToRemoteTcpDevice(Transport transport) {
this.transport = transport;
this.responseValidator = new ResponseValidatorImp();
}
//Visible for testing
HostConnectToRemoteTcpDevice(Transport transport, ResponseValidator responseValidator) {
this.transport = transport;
this.responseValidator = responseValidator;
}
InetSocketAddress connect(InetSocketAddress inetSocketAddress)
throws IOException, JadbException, ConnectionToRemoteDeviceException {
transport.send(String.format("host:connect:%s:%d", inetSocketAddress.getHostString(), inetSocketAddress.getPort()));
verifyTransportLevel();
verifyProtocolLevel();
return inetSocketAddress;
}
private void verifyTransportLevel() throws IOException, JadbException {
transport.verifyResponse();
}
private void verifyProtocolLevel() throws IOException, ConnectionToRemoteDeviceException {
String status = transport.readString();
responseValidator.validate(status);
}
//@VisibleForTesting
interface ResponseValidator {
void validate(String response) throws ConnectionToRemoteDeviceException;
}
final static class ResponseValidatorImp implements ResponseValidator {
private final static String SUCCESSFULLY_CONNECTED = "connected to";
private final static String ALREADY_CONNECTED = "already connected to";
ResponseValidatorImp() {
}
public void validate(String response) throws ConnectionToRemoteDeviceException {
if (!checkIfConnectedSuccessfully(response) && !checkIfAlreadyConnected(response)) {
throw new ConnectionToRemoteDeviceException(extractError(response));
}
}
private boolean checkIfConnectedSuccessfully(String response) {
return response.startsWith(SUCCESSFULLY_CONNECTED);
}
private boolean checkIfAlreadyConnected(String response) {
return response.startsWith(ALREADY_CONNECTED);
}
private String extractError(String response) {
int lastColon = response.lastIndexOf(":");
if (lastColon != -1) {
return response.substring(lastColon, response.length());
} else {
return response;
}
}
}
}

View File

@ -0,0 +1,75 @@
package se.vidstige.jadb;
import java.io.IOException;
import java.net.InetSocketAddress;
public class HostDisconnectFromRemoteTcpDevice {
private final Transport transport;
private final ResponseValidator responseValidator;
HostDisconnectFromRemoteTcpDevice(Transport transport) {
this.transport = transport;
this.responseValidator = new ResponseValidatorImp();
}
//Visible for testing
HostDisconnectFromRemoteTcpDevice(Transport transport, ResponseValidator responseValidator) {
this.transport = transport;
this.responseValidator = responseValidator;
}
InetSocketAddress disconnect(InetSocketAddress inetSocketAddress)
throws IOException, JadbException, ConnectionToRemoteDeviceException {
transport.send(String.format("host:disconnect:%s:%d", inetSocketAddress.getHostString(), inetSocketAddress.getPort()));
verifyTransportLevel();
verifyProtocolLevel();
return inetSocketAddress;
}
private void verifyTransportLevel() throws IOException, JadbException {
transport.verifyResponse();
}
private void verifyProtocolLevel() throws IOException, ConnectionToRemoteDeviceException {
String status = transport.readString();
responseValidator.validate(status);
}
//@VisibleForTesting
interface ResponseValidator {
void validate(String response) throws ConnectionToRemoteDeviceException;
}
final static class ResponseValidatorImp implements ResponseValidator {
private final static String SUCCESSFULLY_DISCONNECTED = "disconnected";
private final static String ALREADY_DISCONNECTED = "error: no such device";
ResponseValidatorImp() {
}
public void validate(String response) throws ConnectionToRemoteDeviceException {
if (!checkIfConnectedSuccessfully(response) && !checkIfAlreadyConnected(response)) {
throw new ConnectionToRemoteDeviceException(extractError(response));
}
}
private boolean checkIfConnectedSuccessfully(String response) {
return response.startsWith(SUCCESSFULLY_DISCONNECTED);
}
private boolean checkIfAlreadyConnected(String response) {
return response.startsWith(ALREADY_DISCONNECTED);
}
private String extractError(String response) {
int lastColon = response.lastIndexOf(":");
if (lastColon != -1) {
return response.substring(lastColon, response.length());
} else {
return response;
}
}
}
}

View File

@ -1,6 +1,8 @@
package se.vidstige.jadb;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
@ -34,6 +36,26 @@ public class JadbConnection implements ITransportFactory {
return version;
}
public InetSocketAddress connectToTcpDevice(InetSocketAddress inetSocketAddress)
throws IOException, JadbException, ConnectionToRemoteDeviceException {
Transport transport = createTransport();
try {
return new HostConnectToRemoteTcpDevice(transport).connect(inetSocketAddress);
} finally {
transport.close();
}
}
public InetSocketAddress disconnectFromTcpDevice(InetSocketAddress tcpAddressEntity)
throws IOException, JadbException, ConnectionToRemoteDeviceException {
Transport transport = createTransport();
try {
return new HostDisconnectFromRemoteTcpDevice(transport).disconnect(tcpAddressEntity);
} finally {
transport.close();
}
}
public List<JadbDevice> getDevices() throws IOException, JadbException {
Transport devices = createTransport();
devices.send("host:devices");

View File

@ -0,0 +1,91 @@
package se.vidstige.jadb;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.io.IOException;
import java.net.InetSocketAddress;
import static org.junit.Assert.*;
import static org.mockito.ArgumentCaptor.forClass;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class HostConnectToRemoteTcpDeviceTest {
@Test
public void testNormalConnection() throws ConnectionToRemoteDeviceException, IOException, JadbException {
//Prepare
Transport transport = mock(Transport.class);
when(transport.readString()).thenReturn("connected to somehost:1");
InetSocketAddress inetSocketAddress = new InetSocketAddress("somehost", 1);
//Do
HostConnectToRemoteTcpDevice hostConnectToRemoteTcpDevice = new HostConnectToRemoteTcpDevice(transport);
InetSocketAddress resultTcpAddressEntity = hostConnectToRemoteTcpDevice.connect(inetSocketAddress);
//Validate
assertEquals(resultTcpAddressEntity, inetSocketAddress);
ArgumentCaptor<String> argument = forClass(String.class);
verify(transport, times(1)).send(argument.capture());
assertEquals("host:connect:somehost:1", argument.getValue());
}
@Test(expected = JadbException.class)
public void testTransportLevelException() throws ConnectionToRemoteDeviceException, IOException, JadbException {
//Prepare
Transport transport = mock(Transport.class);
doThrow(new JadbException("Fake exception")).when(transport).verifyResponse();
InetSocketAddress tcpAddressEntity = new InetSocketAddress("somehost", 1);
//Do
HostConnectToRemoteTcpDevice hostConnectToRemoteTcpDevice = new HostConnectToRemoteTcpDevice(transport);
hostConnectToRemoteTcpDevice.connect(tcpAddressEntity);
//Validate
verify(transport, times(1)).send(anyString());
verify(transport, times(1)).verifyResponse();
}
@Test(expected = ConnectionToRemoteDeviceException.class)
public void testProtocolException() throws ConnectionToRemoteDeviceException, IOException, JadbException {
//Prepare
Transport transport = mock(Transport.class);
when(transport.readString()).thenReturn("connected to somehost:1");
HostConnectToRemoteTcpDevice.ResponseValidator responseValidator = mock(HostConnectToRemoteTcpDevice.ResponseValidator.class);
doThrow(new ConnectionToRemoteDeviceException("Fake exception")).when(responseValidator).validate(anyString());
InetSocketAddress tcpAddressEntity = new InetSocketAddress("somehost", 1);
//Do
HostConnectToRemoteTcpDevice hostConnectToRemoteTcpDevice = new HostConnectToRemoteTcpDevice(transport, responseValidator);
hostConnectToRemoteTcpDevice.connect(tcpAddressEntity);
//Validate
verify(transport, times(1)).send(anyString());
verify(transport, times(1)).verifyResponse();
verify(responseValidator, times(1)).validate(anyString());
}
@Test
public void testProtocolResponseValidatorSuccessfullyConnected() throws ConnectionToRemoteDeviceException, IOException, JadbException {
new HostConnectToRemoteTcpDevice.ResponseValidatorImp().validate("connected to somehost:1");
}
@Test
public void testProtocolResponseValidatorAlreadyConnected() throws ConnectionToRemoteDeviceException, IOException, JadbException {
new HostConnectToRemoteTcpDevice.ResponseValidatorImp().validate("already connected to somehost:1");
}
@Test(expected = ConnectionToRemoteDeviceException.class)
public void testProtocolResponseValidatorErrorInValidate() throws ConnectionToRemoteDeviceException, IOException, JadbException {
new HostConnectToRemoteTcpDevice.ResponseValidatorImp().validate("some error occurred");
}
}

View File

@ -0,0 +1,74 @@
package se.vidstige.jadb;
import org.junit.Test;
import java.io.IOException;
import java.net.InetSocketAddress;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class HostDisconnectFromRemoteTcpDeviceTest {
@Test
public void testNormalConnection() throws ConnectionToRemoteDeviceException, IOException, JadbException {
//Prepare
Transport transport = mock(Transport.class);
when(transport.readString()).thenReturn("disconnected host:1");
InetSocketAddress inetSocketAddress = new InetSocketAddress("host", 1);
//Do
HostDisconnectFromRemoteTcpDevice hostConnectToRemoteTcpDevice = new HostDisconnectFromRemoteTcpDevice(transport);
InetSocketAddress resultInetSocketAddress = hostConnectToRemoteTcpDevice.disconnect(inetSocketAddress);
//Validate
assertEquals(inetSocketAddress, resultInetSocketAddress);
}
@Test(expected = JadbException.class)
public void testTransportLevelException() throws ConnectionToRemoteDeviceException, IOException, JadbException {
//Prepare
Transport transport = mock(Transport.class);
doThrow(new JadbException("Fake exception")).when(transport).verifyResponse();
InetSocketAddress inetSocketAddress = new InetSocketAddress("host", 1);
//Do
HostDisconnectFromRemoteTcpDevice hostConnectToRemoteTcpDevice = new HostDisconnectFromRemoteTcpDevice(transport);
hostConnectToRemoteTcpDevice.disconnect(inetSocketAddress);
}
@Test(expected = ConnectionToRemoteDeviceException.class)
public void testProtocolException() throws ConnectionToRemoteDeviceException, IOException, JadbException {
//Prepare
Transport transport = mock(Transport.class);
when(transport.readString()).thenReturn("any string");
HostDisconnectFromRemoteTcpDevice.ResponseValidator responseValidator = mock(HostDisconnectFromRemoteTcpDevice.ResponseValidator.class);
doThrow(new ConnectionToRemoteDeviceException("Fake exception")).when(responseValidator).validate(anyString());
InetSocketAddress inetSocketAddress = new InetSocketAddress("host", 1);
//Do
HostDisconnectFromRemoteTcpDevice hostConnectToRemoteTcpDevice = new HostDisconnectFromRemoteTcpDevice(transport, responseValidator);
hostConnectToRemoteTcpDevice.disconnect(inetSocketAddress);
}
@Test
public void testProtocolResponseValidatorSuccessfullyConnected() throws ConnectionToRemoteDeviceException, IOException, JadbException {
new HostDisconnectFromRemoteTcpDevice.ResponseValidatorImp().validate("disconnected 127.0.0.1:10001");
}
@Test
public void testProtocolResponseValidatorAlreadyConnected() throws ConnectionToRemoteDeviceException, IOException, JadbException {
new HostDisconnectFromRemoteTcpDevice.ResponseValidatorImp().validate("error: no such device '127.0.0.1:10001'");
}
@Test(expected = ConnectionToRemoteDeviceException.class)
public void testProtocolResponseValidatorErrorInValidate() throws ConnectionToRemoteDeviceException, IOException, JadbException {
new HostDisconnectFromRemoteTcpDevice.ResponseValidatorImp().validate("some error occurred");
}
}

View File

@ -20,7 +20,7 @@ import java.util.List;
*/
public class FakeAdbServer implements AdbResponder {
private final AdbServer server;
private List<DeviceResponder> devices = new ArrayList<DeviceResponder>();
private final List<DeviceResponder> devices = new ArrayList<DeviceResponder>();
public FakeAdbServer(int port) {
server = new AdbServer(this, port);

View File

@ -13,8 +13,13 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.util.List;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class RealDeviceTestCases {
private JadbConnection jadb;
@ -117,4 +122,40 @@ public class RealDeviceTestCases {
if (outputStream != null) outputStream.close();
}
}
/**
* This test requires emulator running on non-standard tcp port - this may be achieve by executing such command:
* ${ANDROID_HOME}/emulator -verbose -avd ${NAME} -ports 10000,10001
*
* @throws IOException
* @throws JadbException
* @throws ConnectionToRemoteDeviceException
*/
@Test
public void testConnectionToTcpDevice() throws IOException, JadbException, ConnectionToRemoteDeviceException {
jadb.connectToTcpDevice(new InetSocketAddress("127.0.0.1", 10001));
List<JadbDevice> devices = jadb.getDevices();
assertNotNull(devices);
assertFalse(devices.isEmpty());
}
/**
* @see #testConnectionToTcpDevice()
*
* @throws IOException
* @throws JadbException
* @throws ConnectionToRemoteDeviceException
*/
@Test
public void testDisconnectionToTcpDevice() throws IOException, JadbException, ConnectionToRemoteDeviceException {
testConnectionToTcpDevice();
jadb.disconnectFromTcpDevice(new InetSocketAddress("127.0.0.1", 10001));
jadb.getDevices();
List<JadbDevice> devices = jadb.getDevices();
assertNotNull(devices);
assertTrue(devices.isEmpty());
}
}