1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.util;
18 
19 import static android.system.OsConstants.*;
20 
21 import android.system.ErrnoException;
22 import android.system.Os;
23 import android.system.StructTimeval;
24 
25 import libcore.io.IoBridge;
26 
27 import java.io.FileDescriptor;
28 import java.io.FileInputStream;
29 import java.io.IOException;
30 import java.net.DatagramPacket;
31 import java.net.DatagramSocket;
32 import java.net.Inet6Address;
33 import java.net.InetAddress;
34 import java.net.InetSocketAddress;
35 import java.net.SocketException;
36 import java.util.Arrays;
37 import java.util.concurrent.CountDownLatch;
38 import java.util.concurrent.TimeUnit;
39 
40 import junit.framework.TestCase;
41 
42 
43 /**
44  * Tests for BlockingSocketReader.
45  *
46  * @hide
47  */
48 public class BlockingSocketReaderTest extends TestCase {
49     static final InetAddress LOOPBACK6 = Inet6Address.getLoopbackAddress();
50     static final StructTimeval TIMEO = StructTimeval.fromMillis(500);
51 
52     protected CountDownLatch mLatch;
53     protected FileDescriptor mLocalSocket;
54     protected InetSocketAddress mLocalSockName;
55     protected byte[] mLastRecvBuf;
56     protected boolean mExited;
57     protected BlockingSocketReader mReceiver;
58 
59     @Override
setUp()60     public void setUp() {
61         resetLatch();
62         mLocalSocket = null;
63         mLocalSockName = null;
64         mLastRecvBuf = null;
65         mExited = false;
66 
67         mReceiver = new BlockingSocketReader() {
68             @Override
69             protected FileDescriptor createSocket() {
70                 FileDescriptor s = null;
71                 try {
72                     s = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
73                     Os.bind(s, LOOPBACK6, 0);
74                     mLocalSockName = (InetSocketAddress) Os.getsockname(s);
75                     Os.setsockoptTimeval(s, SOL_SOCKET, SO_SNDTIMEO, TIMEO);
76                 } catch (ErrnoException|SocketException e) {
77                     closeSocket(s);
78                     fail();
79                     return null;
80                 }
81 
82                 mLocalSocket = s;
83                 return s;
84             }
85 
86             @Override
87             protected void handlePacket(byte[] recvbuf, int length) {
88                 mLastRecvBuf = Arrays.copyOf(recvbuf, length);
89                 mLatch.countDown();
90             }
91 
92             @Override
93             protected void onExit() {
94                 mExited = true;
95                 mLatch.countDown();
96             }
97         };
98     }
99 
100     @Override
tearDown()101     public void tearDown() {
102         if (mReceiver != null) mReceiver.stop();
103         mReceiver = null;
104     }
105 
resetLatch()106     void resetLatch() { mLatch = new CountDownLatch(1); }
107 
waitForActivity()108     void waitForActivity() throws Exception {
109         assertTrue(mLatch.await(500, TimeUnit.MILLISECONDS));
110         resetLatch();
111     }
112 
sendPacket(byte[] contents)113     void sendPacket(byte[] contents) throws Exception {
114         final DatagramSocket sender = new DatagramSocket();
115         sender.connect(mLocalSockName);
116         sender.send(new DatagramPacket(contents, contents.length));
117         sender.close();
118     }
119 
testBasicWorking()120     public void testBasicWorking() throws Exception {
121         assertTrue(mReceiver.start());
122         assertTrue(mLocalSockName != null);
123         assertEquals(LOOPBACK6, mLocalSockName.getAddress());
124         assertTrue(0 < mLocalSockName.getPort());
125         assertTrue(mLocalSocket != null);
126         assertFalse(mExited);
127 
128         final byte[] one = "one 1".getBytes("UTF-8");
129         sendPacket(one);
130         waitForActivity();
131         assertEquals(1, mReceiver.numPacketsReceived());
132         assertTrue(Arrays.equals(one, mLastRecvBuf));
133         assertFalse(mExited);
134 
135         final byte[] two = "two 2".getBytes("UTF-8");
136         sendPacket(two);
137         waitForActivity();
138         assertEquals(2, mReceiver.numPacketsReceived());
139         assertTrue(Arrays.equals(two, mLastRecvBuf));
140         assertFalse(mExited);
141 
142         mReceiver.stop();
143         waitForActivity();
144         assertEquals(2, mReceiver.numPacketsReceived());
145         assertTrue(Arrays.equals(two, mLastRecvBuf));
146         assertTrue(mExited);
147     }
148 }
149