package se.vidstige.jadb.test.unit;

import org.junit.After;
import org.junit.Assert;
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;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;

public class MockedTestCases {

    private FakeAdbServer server;
    private JadbConnection connection;

    @Before
    public void setUp() throws Exception {
        server = new FakeAdbServer(15037);
        server.start();
        connection = new JadbConnection("localhost", 15037);
    }

    @After
    public void tearDown() throws Exception {
        server.stop();
        server.verifyExpectations();
    }

    @Test
    public void testGetHostVersion() throws Exception {
        Assert.assertEquals("001f", connection.getHostVersion());
    }

    @Test
    public void testListDevices() throws Exception {
        server.add("serial-123");
        List<JadbDevice> devices = connection.getDevices();
        Assert.assertEquals("serial-123", devices.get(0).getSerial());
    }

    @Test
    public void testGetDeviceState() throws Exception {
        server.add("serial-1", "offline");
        server.add("serial-2", "device");
        server.add("serial-3", "unknown");
        server.add("serial-4", "foobar");
        List<JadbDevice> devices = connection.getDevices();
        Assert.assertEquals(JadbDevice.State.Offline, devices.get(0).getState());
        Assert.assertEquals(JadbDevice.State.Device, devices.get(1).getState());
        Assert.assertEquals(JadbDevice.State.Unknown, devices.get(2).getState());
        Assert.assertEquals(JadbDevice.State.Unknown, devices.get(3).getState());
    }

    @Test
    public void testListNoDevices() throws Exception {
        List<JadbDevice> devices = connection.getDevices();
        Assert.assertEquals(0, devices.size());
    }

    @Test
    public void testPushFile() throws Exception {
        server.add("serial-123");
        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"));
    }

    @Test
    public void testPullFile() throws Exception {
        server.add("serial-123");
        server.expectPull("serial-123", new RemoteFile("/remote/path/abc.txt")).withContent("foobar");
        JadbDevice device = connection.getDevices().get(0);
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        device.pull(new RemoteFile("/remote/path/abc.txt"), buffer);
        Assert.assertArrayEquals("foobar".getBytes(Charset.forName("utf-8")), buffer.toByteArray());
    }

    @Test
    public void testExecuteShell() throws Exception {
        server.add("serial-123");
        server.expectShell("serial-123", "ls -l").returns("total 0");
        JadbDevice device = connection.getDevices().get(0);
        device.executeShell("ls", "-l");
    }

    @Test
    public void testExecuteShellQuotesSpace() throws Exception {
        server.add("serial-123");
        server.expectShell("serial-123", "ls 'space file'").returns("space file");
        JadbDevice device = connection.getDevices().get(0);
        device.executeShell("ls", "space file");
    }

    private long parseDate(String date) throws ParseException {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        return dateFormat.parse(date).getTime();
    }
}

@@ -3962,17 +3962,22 @@
 llQuotes
-S
+Whites
 pace() t
@@ -4123,105 +4123,558 @@
     
-JadbDevice device = connection.getDevices().get(0);%0A        device.executeShell(%22ls%22, %22space file
+server.expectShell(%22serial-123%22, %22echo 'tab%5Ctstring'%22).returns(%22tab%5Ctstring%22);%0A        server.expectShell(%22serial-123%22, %22echo 'newline1%5Cnstring'%22).returns(%22newline1%5Cnstring%22);%0A        server.expectShell(%22serial-123%22, %22echo 'newline2%5Cr%5Cnstring'%22).returns(%22newline2%5Cr%5Cnstring%22);%0A        JadbDevice device = connection.getDevices().get(0);%0A        device.executeShell(%22ls%22, %22space file%22);%0A        device.executeShell(%22echo%22, %22tab%5Ctstring%22);%0A        device.executeShell(%22echo%22, %22newline1%5Cnstring%22);%0A        device.executeShell(%22echo%22, %22newline2%5Cr%5Cnstring
 %22);%0A

Modify testExecuteShellQuotesSpace to test other whitespace characters