diff --git a/src/se/vidstige/jadb/server/AdbDeviceResponder.java b/src/se/vidstige/jadb/server/AdbDeviceResponder.java index 6e09fd2..4e9a280 100644 --- a/src/se/vidstige/jadb/server/AdbDeviceResponder.java +++ b/src/se/vidstige/jadb/server/AdbDeviceResponder.java @@ -1,5 +1,8 @@ package se.vidstige.jadb.server; +import se.vidstige.jadb.JadbException; +import se.vidstige.jadb.RemoteFile; + import java.io.ByteArrayOutputStream; /** @@ -9,5 +12,5 @@ public interface AdbDeviceResponder { String getSerial(); String getType(); - void filePushed(String path, int mode, ByteArrayOutputStream buffer); + void filePushed(RemoteFile path, int mode, ByteArrayOutputStream buffer) throws JadbException; } diff --git a/src/se/vidstige/jadb/server/AdbProtocolHandler.java b/src/se/vidstige/jadb/server/AdbProtocolHandler.java index 65a7aa5..96522ea 100644 --- a/src/se/vidstige/jadb/server/AdbProtocolHandler.java +++ b/src/se/vidstige/jadb/server/AdbProtocolHandler.java @@ -1,6 +1,7 @@ package se.vidstige.jadb.server; import se.vidstige.jadb.JadbException; +import se.vidstige.jadb.RemoteFile; import se.vidstige.jadb.SyncTransport; import java.io.*; @@ -32,7 +33,8 @@ public class AdbProtocolHandler implements Runnable { try{ runServer(); } catch (IOException e) { - System.out.println("IO Error: " + e.getMessage()); + if (e.getMessage() != null) // thrown when exiting for some reason + System.out.println("IO Error: " + e.getMessage()); } } @@ -83,7 +85,14 @@ public class AdbProtocolHandler implements Runnable { } else if ("sync:".equals(command)) { output.writeBytes("OKAY"); - sync(output, input); + try + { + sync(output, input); + } + catch (JadbException e) { // sync response with a different type of fail message + SyncTransport sync = new SyncTransport(output, input); + sync.send("FAIL", e.getMessage()); + } } else { @@ -92,9 +101,6 @@ public class AdbProtocolHandler implements Runnable { } catch (ProtocolException e) { output.writeBytes("FAIL"); send(output, e.getMessage()); - } catch (JadbException e) { - output.writeBytes("FAIL"); - send(output, e.getMessage()); } output.flush(); } @@ -127,9 +133,8 @@ public class AdbProtocolHandler implements Runnable { SyncTransport transport = new SyncTransport(output, input); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); transport.readChunksTo(buffer); + selected.filePushed(new RemoteFile(path), mode, buffer); transport.sendStatus("OKAY", 0); // 0 = ignored - - selected.filePushed(path, mode, buffer); } else throw new JadbException("Unknown sync id " + id); } diff --git a/test/se/vidstige/jadb/test/MockedTestCases.java b/test/se/vidstige/jadb/test/MockedTestCases.java index 99bbb94..58d44db 100644 --- a/test/se/vidstige/jadb/test/MockedTestCases.java +++ b/test/se/vidstige/jadb/test/MockedTestCases.java @@ -6,6 +6,7 @@ import org.junit.Before; import org.junit.Test; import se.vidstige.jadb.JadbConnection; import se.vidstige.jadb.JadbDevice; +import se.vidstige.jadb.JadbException; import se.vidstige.jadb.RemoteFile; import se.vidstige.jadb.test.fakes.FakeAdbServer; @@ -50,12 +51,20 @@ public class MockedTestCases { @Test public void testPushFile() throws Exception { server.add("serial-123"); - server.expectPush("serial-123", new RemoteFile("/remote/path/abc.txt"), "abc"); + server.expectPush("serial-123", new RemoteFile("/remote/path/abc.txt")).withContent("abc"); JadbDevice device = connection.getDevices().get(0); ByteArrayInputStream fileContents = new ByteArrayInputStream("abc".getBytes()); device.push(fileContents, parseDate("1981-08-25 13:37"), 0666, new RemoteFile("/remote/path/abc.txt")); } + @Test(expected = JadbException.class) + public void testPushToInvalidPath() throws Exception { + server.add("serial-123"); + server.expectPush("serial-123", new RemoteFile("/remote/path/abc.txt")).failWith("No such directory"); + JadbDevice device = connection.getDevices().get(0); + ByteArrayInputStream fileContents = new ByteArrayInputStream("abc".getBytes()); + device.push(fileContents, parseDate("1981-08-25 13:37"), 0666, new RemoteFile("/remote/path/abc.txt")); + } private long parseDate(String date) throws ParseException { DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); diff --git a/test/se/vidstige/jadb/test/fakes/FakeAdbServer.java b/test/se/vidstige/jadb/test/fakes/FakeAdbServer.java index 7b34f65..ab20ac4 100644 --- a/test/se/vidstige/jadb/test/fakes/FakeAdbServer.java +++ b/test/se/vidstige/jadb/test/fakes/FakeAdbServer.java @@ -1,5 +1,6 @@ package se.vidstige.jadb.test.fakes; +import se.vidstige.jadb.JadbException; import se.vidstige.jadb.RemoteFile; import se.vidstige.jadb.server.AdbDeviceResponder; import se.vidstige.jadb.server.AdbResponder; @@ -9,7 +10,6 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** @@ -17,7 +17,7 @@ import java.util.List; */ public class FakeAdbServer implements AdbResponder { private final AdbServer server; - private List devices = new ArrayList(); + private List devices = new ArrayList(); public FakeAdbServer(int port) { server = new AdbServer(this, port); @@ -48,69 +48,36 @@ public class FakeAdbServer implements AdbResponder { } public void verifyExpectations() { - org.junit.Assert.assertEquals(0, remoteFileExpectations.size()); + for (DeviceResponder d : devices) + d.verifyExpectations(); } - private static class RemoteFileExpectation { - - private final String serial; - private final RemoteFile path; - private final byte[] contents; - - public RemoteFileExpectation(String serial, RemoteFile path, byte[] contents) { - - this.serial = serial; - this.path = path; - this.contents = contents; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - RemoteFileExpectation that = (RemoteFileExpectation) o; - - if (!Arrays.equals(contents, that.contents)) return false; - if (!path.equals(that.path)) return false; - if (serial != null ? !serial.equals(that.serial) : that.serial != null) return false; - - return true; - } - - @Override - public int hashCode() { - int result = serial != null ? serial.hashCode() : 0; - result = 31 * result + path.hashCode(); - result = 31 * result + Arrays.hashCode(contents); - return result; - } + public interface ExpectationBuilder { + void failWith(String message); + void withContent(byte[] content); + void withContent(String content); } - private List remoteFileExpectations = new ArrayList(); - - public void expectPush(String serial, RemoteFile path, String contents){ - expectPush(serial, path, contents.getBytes(Charset.forName("UTF-8"))); + private DeviceResponder findBySerial(String serial) { + for (DeviceResponder d : devices) { + if (d.getSerial().equals(serial)) return d; + } + return null; } - public void expectPush(String serial, RemoteFile path, byte[] contents) + public ExpectationBuilder expectPush(String serial, RemoteFile path) { - remoteFileExpectations.add(new RemoteFileExpectation(serial, path, contents)); - } - - private void filePushed(String serial, RemoteFile path, byte[] contents) { - boolean removed = remoteFileExpectations.remove(new RemoteFileExpectation(serial, path, contents)); - if (!removed) throw new RuntimeException("Unexpected push to device " + serial + " at " + path.getPath()); - + return findBySerial(serial).expectPush(path); } @Override public List getDevices() { - return devices; + return new ArrayList(devices); } private class DeviceResponder implements AdbDeviceResponder { private final String serial; + private List expectations = new ArrayList(); private DeviceResponder(String serial) { this.serial = serial; @@ -127,8 +94,67 @@ public class FakeAdbServer implements AdbResponder { } @Override - public void filePushed(String path, int mode, ByteArrayOutputStream buffer) { - FakeAdbServer.this.filePushed(serial, new RemoteFile(path), buffer.toByteArray()); + public void filePushed(RemoteFile path, int mode, ByteArrayOutputStream buffer) throws JadbException { + for (FileExpectation fe : expectations) { + if (fe.matches(path)) + { + expectations.remove(fe); + fe.throwIfFail(); + fe.verifyContent(buffer.toByteArray()); + return; + } + } + new JadbException("Unexpected push to device " + serial + " at " + path); + } + + public void verifyExpectations() { + org.junit.Assert.assertEquals(0, expectations.size()); + } + + private class FileExpectation implements ExpectationBuilder { + private final RemoteFile path; + private byte[] content; + private String failMessage; + + public FileExpectation(RemoteFile path) { + + this.path = path; + content = null; + failMessage = null; + } + + @Override + public void failWith(String message) { + failMessage = message; + } + + @Override + public void withContent(byte[] content) { + this.content = content; + } + + @Override + public void withContent(String content) { + this.content = content.getBytes(Charset.forName("utf-8")); + } + + public boolean matches(RemoteFile path) throws JadbException { + return this.path.equals(path); + } + + public void throwIfFail() throws JadbException { + if (failMessage != null) throw new JadbException(failMessage); + } + + public void verifyContent(byte[] content) { + org.junit.Assert.assertArrayEquals(this.content, content); + } + } + + public ExpectationBuilder expectPush(RemoteFile path) { + FileExpectation expectation = new FileExpectation(path); + expectations.add(expectation); + return expectation; } } }