Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / components / devtools_bridge / android / javatests / src / org / chromium / components / devtools_bridge / SocketTunnelServerTest.java
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.components.devtools_bridge;
6
7 import android.net.LocalServerSocket;
8 import android.net.LocalSocket;
9 import android.test.InstrumentationTestCase;
10 import android.test.suitebuilder.annotation.MediumTest;
11 import android.test.suitebuilder.annotation.SmallTest;
12
13 import junit.framework.Assert;
14
15 import java.io.IOException;
16 import java.io.OutputStream;
17 import java.nio.ByteBuffer;
18
19 /**
20  * Tests for {@link SocketTunnelServer}
21  */
22 public class SocketTunnelServerTest extends InstrumentationTestCase {
23     private static final int CONNECTION_ID = 30;
24     private static final String SOCKET_NAME = "ksdjhflksjhdflk";
25
26     private DataChannelMock mDataChannelMock;
27     private SocketTunnelServer mServer;
28     private LocalServerSocket mSocket;
29
30     @Override
31     public void setUp() throws Exception {
32         super.setUp();
33         mSocket = new LocalServerSocket(SOCKET_NAME);
34     }
35
36     @Override
37     public void tearDown() throws Exception {
38         mSocket.close();
39         if (mServer != null) destroyServer();
40         super.tearDown();
41     }
42
43     private void createServer() {
44         createServer(new DataChannelMock());
45     }
46
47     private void createServer(DataChannelMock dataChannel) {
48         mDataChannelMock = dataChannel;
49         mServer = new SocketTunnelServer(SOCKET_NAME);
50         mServer.bind(mDataChannelMock);
51     }
52
53     private void destroyServer() {
54         mServer.unbind().dispose();
55         mServer = null;
56     }
57
58     @SmallTest
59     public void testOpenDataChannel() {
60         createServer();
61         mDataChannelMock.open();
62     }
63
64     @SmallTest
65     public void testDecodeControlPacket() {
66         createServer();
67         ByteBuffer packet = buildControlPacket(CONNECTION_ID, SocketTunnelBase.SERVER_OPEN_ACK);
68
69         PacketDecoder decoder = PacketDecoder.decode(packet);
70         Assert.assertTrue(decoder.isControlPacket());
71         Assert.assertEquals(CONNECTION_ID, decoder.connectionId());
72         Assert.assertEquals(SocketTunnelBase.SERVER_OPEN_ACK, decoder.opCode());
73     }
74
75     @SmallTest
76     public void testConnectToSocket() throws IOException {
77         createServer();
78         LocalSocket socket = connectToSocket(1);
79         Assert.assertTrue(mServer.hasConnections());
80         socket.close();
81     }
82
83     private LocalSocket connectToSocket(int connectionId) throws IOException {
84         mDataChannelMock.notifyMessage(
85                 buildControlPacket(connectionId, SocketTunnelBase.CLIENT_OPEN));
86         return mSocket.accept();
87     }
88
89     private void sendClose(int connectionId) {
90         mDataChannelMock.notifyMessage(
91                 buildControlPacket(connectionId, SocketTunnelBase.CLIENT_CLOSE));
92     }
93
94     private ByteBuffer buildControlPacket(int connectionId, byte opCode) {
95         ByteBuffer packet = SocketTunnelBase.buildControlPacket(connectionId, opCode);
96         packet.limit(packet.position());
97         packet.position(0);
98         Assert.assertTrue(packet.remaining() > 0);
99         return packet;
100     }
101
102     private ByteBuffer buildDataPacket(int connectionId, byte[] data) {
103         ByteBuffer packet = SocketTunnelBase.buildDataPacket(connectionId, data, data.length);
104         packet.limit(packet.position());
105         packet.position(0);
106         Assert.assertTrue(packet.remaining() > 0);
107         return packet;
108     }
109
110     @SmallTest
111     public void testReceiveOpenAcknowledgement() throws IOException, InterruptedException {
112         createServer();
113         LocalSocket socket = connectToSocket(CONNECTION_ID);
114
115         receiveOpenAck(CONNECTION_ID);
116
117         socket.close();
118     }
119
120     private PacketDecoder receiveControlPacket(int connectionId) throws InterruptedException {
121         PacketDecoder decoder = PacketDecoder.decode(mDataChannelMock.receive());
122         Assert.assertTrue(decoder.isControlPacket());
123         Assert.assertEquals(connectionId, decoder.connectionId());
124         return decoder;
125     }
126
127     private void receiveOpenAck(int connectionId) throws InterruptedException {
128         PacketDecoder decoder = receiveControlPacket(connectionId);
129         Assert.assertEquals(SocketTunnelBase.SERVER_OPEN_ACK, decoder.opCode());
130     }
131
132     private void receiveClose(int connectionId) throws InterruptedException {
133         PacketDecoder decoder = receiveControlPacket(connectionId);
134         Assert.assertEquals(SocketTunnelBase.SERVER_CLOSE, decoder.opCode());
135     }
136
137     @SmallTest
138     public void testClosingSocket() throws IOException, InterruptedException {
139         createServer();
140         LocalSocket socket = connectToSocket(CONNECTION_ID);
141         receiveOpenAck(CONNECTION_ID);
142
143         socket.shutdownOutput();
144
145         PacketDecoder decoder = PacketDecoder.decode(mDataChannelMock.receive());
146
147         Assert.assertTrue(decoder.isControlPacket());
148         Assert.assertEquals(SocketTunnelBase.SERVER_CLOSE, decoder.opCode());
149         Assert.assertEquals(CONNECTION_ID, decoder.connectionId());
150
151         socket.close();
152     }
153
154     @SmallTest
155     public void testReadData() throws IOException, InterruptedException {
156         createServer();
157         LocalSocket socket = connectToSocket(CONNECTION_ID);
158         receiveOpenAck(CONNECTION_ID);
159
160         byte[] sample = "Sample".getBytes();
161
162         socket.getOutputStream().write(sample);
163         socket.getOutputStream().flush();
164         socket.shutdownOutput();
165
166         ByteBuffer result = receiveData(CONNECTION_ID, sample.length);
167         Assert.assertEquals(ByteBuffer.wrap(sample), result);
168     }
169
170     private ByteBuffer receiveData(int connectionId, int length) throws InterruptedException {
171         ByteBuffer result = ByteBuffer.allocate(length);
172
173         while (true) {
174             PacketDecoder decoder = PacketDecoder.decode(mDataChannelMock.receive());
175             if (decoder.isDataPacket()) {
176                 Assert.assertEquals(connectionId, decoder.connectionId());
177                 result.put(decoder.data());
178             } else if (decoder.isControlPacket()) {
179                 Assert.assertEquals(SocketTunnelBase.SERVER_CLOSE, decoder.opCode());
180                 Assert.assertEquals(connectionId, decoder.connectionId());
181                 break;
182             }
183         }
184         result.limit(result.position());
185         result.position(0);
186         return result;
187     }
188
189     private int sum(int[] values) {
190         int result = 0;
191         for (int v : values)
192             result += v;
193         return result;
194     }
195
196     private static final int[] CHUNK_SIZES =
197             new int[] { 0, 1, 5, 100, 1000, SocketTunnelBase.READING_BUFFER_SIZE * 2 };
198
199     @SmallTest
200     public void testReadLongDataChunk() throws IOException, InterruptedException {
201         createServer();
202         LocalSocket socket = connectToSocket(CONNECTION_ID);
203         receiveOpenAck(CONNECTION_ID);
204
205         byte[] buffer = new byte[CHUNK_SIZES[CHUNK_SIZES.length - 1]];
206         ByteBuffer sentData = ByteBuffer.allocate(sum(CHUNK_SIZES));
207         OutputStream stream = socket.getOutputStream();
208         byte next = 0;
209         int prevSize = 0;
210         for (int size : CHUNK_SIZES) {
211             while (prevSize < size)
212                 buffer[prevSize++] = next++;
213
214             stream.write(buffer, 0, size);
215             sentData.put(buffer, 0, size);
216         }
217
218         socket.shutdownOutput();
219
220         sentData.limit(sentData.position());
221         sentData.position(0);
222         ByteBuffer readData = receiveData(CONNECTION_ID, sentData.limit());
223
224         Assert.assertEquals(sentData, readData);
225     }
226
227     @SmallTest
228     public void testReuseConnectionId() throws IOException, InterruptedException {
229         createServer();
230         LocalSocket socket = connectToSocket(CONNECTION_ID);
231         receiveOpenAck(CONNECTION_ID);
232
233         socket.shutdownOutput();
234         socket.close();
235         receiveClose(CONNECTION_ID);
236         sendClose(CONNECTION_ID);
237
238         // Open connection with the same ID
239         socket = connectToSocket(CONNECTION_ID);
240         receiveOpenAck(CONNECTION_ID);
241     }
242
243     private static final byte[] SAMPLE = "Sample".getBytes();
244
245     @SmallTest
246     public void testWriteData() throws IOException, InterruptedException {
247         createServer();
248         LocalSocket socket = connectToSocket(CONNECTION_ID);
249         receiveOpenAck(CONNECTION_ID);
250
251         mDataChannelMock.notifyMessage(buildDataPacket(CONNECTION_ID, SAMPLE));
252
253         byte[] result = new byte[SAMPLE.length];
254         int read = 0;
255         while (read < SAMPLE.length) {
256             int count = socket.getInputStream().read(result, 0, SAMPLE.length - read);
257             Assert.assertTrue(count > 0);
258             read += count;
259         }
260
261         Assert.assertEquals(ByteBuffer.wrap(SAMPLE), ByteBuffer.wrap(result));
262
263         socket.close();
264     }
265
266     private enum TestStates {
267         INITIAL, SENDING, CLOSING, MAY_FINISH_SENDING, SENT, DONE
268     }
269
270     @MediumTest
271     public void testStopWhileSendingData() throws IOException {
272
273         final TestUtils.StateBarrier<TestStates> barrier =
274                 new TestUtils.StateBarrier<TestStates>(TestStates.INITIAL);
275
276         createServer(new DataChannelMock() {
277             @Override
278             public void send(ByteBuffer message, AbstractDataChannel.MessageType type) {
279                 barrier.advance(TestStates.INITIAL, TestStates.SENDING);
280                 barrier.advance(TestStates.MAY_FINISH_SENDING, TestStates.SENT);
281             }
282         });
283
284         LocalSocket socket = connectToSocket(CONNECTION_ID);
285         barrier.advance(TestStates.SENDING, TestStates.CLOSING);
286         socket.close();
287
288         new Thread() {
289             @Override
290             public void run() {
291                 try {
292                     Thread.sleep(100);
293                 } catch (InterruptedException e) {
294                     throw new RuntimeException(e);
295                 }
296
297                 barrier.advance(TestStates.CLOSING, TestStates.MAY_FINISH_SENDING);
298             }
299         }.start();
300
301         destroyServer();
302
303         barrier.advance(TestStates.SENT, TestStates.DONE);
304     }
305 }